itube-modern-player 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { d as I } from "./labels-C3gAZEm-.js";
2
2
  function l(r, t, e) {
3
- const s = document.createElement(r);
4
- if (t && (s.className = t), e)
5
- for (const [i, n] of Object.entries(e)) s.setAttribute(i, n);
6
- return s;
3
+ const i = document.createElement(r);
4
+ if (t && (i.className = t), e)
5
+ for (const [s, n] of Object.entries(e)) i.setAttribute(s, n);
6
+ return i;
7
7
  }
8
8
  function m(r, t, e) {
9
- const s = l("button", `imp-btn ${r}`, { type: "button", "aria-label": t, title: t });
10
- return s.innerHTML = e, s;
9
+ const i = l("button", `imp-btn ${r}`, { type: "button", "aria-label": t, title: t });
10
+ return i.innerHTML = e, i;
11
11
  }
12
12
  function E(r, t, e) {
13
13
  r.innerHTML = t, e !== void 0 && (r.setAttribute("aria-label", e), r.setAttribute("title", e));
@@ -17,27 +17,27 @@ function y(r, t, e) {
17
17
  }
18
18
  function w(r) {
19
19
  if (!Number.isFinite(r) || r < 0) return "0:00";
20
- const t = Math.floor(r % 60), e = Math.floor(r / 60 % 60), s = Math.floor(r / 3600), i = s > 0 ? String(e).padStart(2, "0") : String(e), n = String(t).padStart(2, "0");
21
- return s > 0 ? `${s}:${i}:${n}` : `${i}:${n}`;
20
+ const t = Math.floor(r % 60), e = Math.floor(r / 60 % 60), i = Math.floor(r / 3600), s = i > 0 ? String(e).padStart(2, "0") : String(e), n = String(t).padStart(2, "0");
21
+ return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
22
22
  }
23
23
  function R(r) {
24
24
  const t = r.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
25
25
  if (!t) return null;
26
- const e = t[1] ? Number(t[1]) : 0, s = Number(t[2]), i = Number(t[3]), n = t[4] ? Number(t[4].padEnd(3, "0")) : 0;
27
- return e * 3600 + s * 60 + i + n / 1e3;
26
+ const e = t[1] ? Number(t[1]) : 0, i = Number(t[2]), s = Number(t[3]), n = t[4] ? Number(t[4].padEnd(3, "0")) : 0;
27
+ return e * 3600 + i * 60 + s + n / 1e3;
28
28
  }
29
29
  function U(r) {
30
30
  const t = [], e = r.replace(/\r\n?/g, `
31
31
  `).split(/\n\n+/);
32
- for (const s of e) {
33
- const i = s.split(`
32
+ for (const i of e) {
33
+ const s = i.split(`
34
34
  `).filter((f) => f.trim() !== "");
35
- if (i.length === 0) continue;
36
- let n = i.findIndex((f) => f.includes("-->"));
35
+ if (s.length === 0) continue;
36
+ let n = s.findIndex((f) => f.includes("-->"));
37
37
  if (n === -1) continue;
38
- const [o, a] = i[n].split("-->"), c = R(o), h = R((a ?? "").split(" ")[1] ?? a ?? "") ?? R(a ?? "");
38
+ const [o, a] = s[n].split("-->"), c = R(o), h = R((a ?? "").split(" ")[1] ?? a ?? "") ?? R(a ?? "");
39
39
  if (c === null || h === null) continue;
40
- const u = i.slice(n + 1).join(`
40
+ const u = s.slice(n + 1).join(`
41
41
  `).trim();
42
42
  u && t.push({ start: c, end: h, text: u });
43
43
  }
@@ -56,24 +56,24 @@ class Y {
56
56
  }
57
57
  /** Subscribe. Returns an unsubscribe function. */
58
58
  on(t, e) {
59
- let s = this.listeners.get(t);
60
- return s || (s = /* @__PURE__ */ new Set(), this.listeners.set(t, s)), s.add(e), () => this.off(t, e);
59
+ let i = this.listeners.get(t);
60
+ return i || (i = /* @__PURE__ */ new Set(), this.listeners.set(t, i)), i.add(e), () => this.off(t, e);
61
61
  }
62
62
  once(t, e) {
63
- const s = this.on(t, (i) => {
64
- s(), e(i);
63
+ const i = this.on(t, (s) => {
64
+ i(), e(s);
65
65
  });
66
- return s;
66
+ return i;
67
67
  }
68
68
  off(t, e) {
69
69
  this.listeners.get(t)?.delete(e);
70
70
  }
71
71
  emit(t, e) {
72
- const s = this.listeners.get(t);
73
- if (s)
74
- for (const i of [...s])
72
+ const i = this.listeners.get(t);
73
+ if (i)
74
+ for (const s of [...i])
75
75
  try {
76
- i(e);
76
+ s(e);
77
77
  } catch (n) {
78
78
  console.error("[itube-player] listener error", n);
79
79
  }
@@ -127,18 +127,18 @@ function xt() {
127
127
  }
128
128
  function et(r, t, e = 100) {
129
129
  if (r.length === 0 || !Number.isFinite(t) || t <= 0) return [];
130
- const s = new Array(e).fill(0);
131
- let i = !1;
130
+ const i = new Array(e).fill(0);
131
+ let s = !1;
132
132
  for (const h of r) {
133
133
  if (!Number.isFinite(h.time) || h.time < 0 || h.time > t) continue;
134
134
  const u = Math.max(0, h.value);
135
135
  if (u === 0) continue;
136
136
  const f = Math.min(e - 1, Math.floor(h.time / t * e));
137
- s[f] += u, i = !0;
137
+ i[f] += u, s = !0;
138
138
  }
139
- if (!i) return [];
140
- const n = [0.06, 0.24, 0.4, 0.24, 0.06], o = s.map(
141
- (h, u) => n.reduce((f, d, b) => f + d * (s[u + b - 2] ?? 0), 0)
139
+ if (!s) return [];
140
+ const n = [0.06, 0.24, 0.4, 0.24, 0.06], o = i.map(
141
+ (h, u) => n.reduce((f, d, b) => f + d * (i[u + b - 2] ?? 0), 0)
142
142
  ), a = Math.max(...o);
143
143
  if (a <= 0) return [];
144
144
  const c = 0.08;
@@ -146,11 +146,11 @@ function et(r, t, e = 100) {
146
146
  }
147
147
  function it(r, t = 1e3, e = 100) {
148
148
  if (r.length === 0) return "";
149
- const s = t / (r.length - 1 || 1);
150
- let i = `M 0 ${e}`;
149
+ const i = t / (r.length - 1 || 1);
150
+ let s = `M 0 ${e}`;
151
151
  return r.forEach((n, o) => {
152
- i += ` L ${(o * s).toFixed(1)} ${(e - n * e).toFixed(1)}`;
153
- }), i += ` L ${t} ${e} Z`, i;
152
+ s += ` L ${(o * i).toFixed(1)} ${(e - n * e).toFixed(1)}`;
153
+ }), s += ` L ${t} ${e} Z`, s;
154
154
  }
155
155
  async function st(r, t) {
156
156
  if (r.src)
@@ -164,8 +164,8 @@ async function st(r, t) {
164
164
  if (!r.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
165
165
  return j(r, r.vastTag, t, 0, { impressions: [], tracking: {} });
166
166
  }
167
- async function j(r, t, e, s, i) {
168
- if (s > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
167
+ async function j(r, t, e, i, s) {
168
+ if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
169
169
  const n = new AbortController(), o = setTimeout(() => n.abort(), e.requestTimeout);
170
170
  let a;
171
171
  try {
@@ -179,12 +179,12 @@ async function j(r, t, e, s, i) {
179
179
  if (c.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
180
180
  const h = c.querySelector("VAST > Ad");
181
181
  if (!h) throw new Error("VAST response contains no ads");
182
- nt(h, i);
182
+ nt(h, s);
183
183
  const u = h.querySelector(":scope > Wrapper");
184
184
  if (u) {
185
185
  const v = k(u.querySelector("VASTAdTagURI"));
186
186
  if (!v) throw new Error("VAST wrapper without VASTAdTagURI");
187
- return j(r, v, e, s + 1, i);
187
+ return j(r, v, e, i + 1, s);
188
188
  }
189
189
  const f = h.querySelector(":scope > InLine");
190
190
  if (!f) throw new Error("VAST ad has neither InLine nor Wrapper");
@@ -202,24 +202,24 @@ async function j(r, t, e, s, i) {
202
202
  d.getAttribute("skipoffset"),
203
203
  V(k(d.querySelector(":scope > Duration")))
204
204
  ),
205
- impressions: i.impressions,
206
- tracking: i.tracking,
205
+ impressions: s.impressions,
206
+ tracking: s.tracking,
207
207
  adTitle: k(f.querySelector(":scope > AdTitle")) ?? void 0
208
208
  };
209
209
  }
210
210
  function nt(r, t) {
211
- var e, s;
212
- for (const i of r.querySelectorAll("Impression")) {
213
- const n = k(i);
211
+ var e, i;
212
+ for (const s of r.querySelectorAll("Impression")) {
213
+ const n = k(s);
214
214
  n && t.impressions.push(n);
215
215
  }
216
- for (const i of r.querySelectorAll("Linear > TrackingEvents > Tracking")) {
217
- const n = i.getAttribute("event"), o = k(i);
216
+ for (const s of r.querySelectorAll("Linear > TrackingEvents > Tracking")) {
217
+ const n = s.getAttribute("event"), o = k(s);
218
218
  !n || !o || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(o);
219
219
  }
220
- for (const i of r.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
221
- const n = k(i);
222
- n && ((s = t.tracking).click ?? (s.click = [])).push(n);
220
+ for (const s of r.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
221
+ const n = k(s);
222
+ n && ((i = t.tracking).click ?? (i.click = [])).push(n);
223
223
  }
224
224
  }
225
225
  function rt(r) {
@@ -234,7 +234,7 @@ function rt(r) {
234
234
  );
235
235
  if (e.length === 0) return null;
236
236
  e.sort((o, a) => o.bitrate - a.bitrate);
237
- const s = e.filter((o) => o.delivery !== "streaming"), i = s.length > 0 ? s : e, n = i[Math.floor(i.length / 2)];
237
+ const i = e.filter((o) => o.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
238
238
  return { url: n.url, type: n.type };
239
239
  }
240
240
  function V(r) {
@@ -310,7 +310,7 @@ class lt {
310
310
  /** Called from timeupdate; fires due mid-rolls. */
311
311
  checkMidRolls(t) {
312
312
  if (this.adPlaying) return;
313
- const e = this.pending("midRoll").filter((s) => s.timer !== void 0 && t >= s.timer);
313
+ const e = this.pending("midRoll").filter((i) => i.timer !== void 0 && t >= i.timer);
314
314
  e.length > 0 && this.playRolls(e);
315
315
  }
316
316
  pending(t) {
@@ -321,8 +321,8 @@ class lt {
321
321
  if (this.activeBreak) return this.activeBreak;
322
322
  this.ensureAdVideo();
323
323
  const e = (async () => {
324
- const s = this.host.contentVideo, i = !s.paused && !s.ended;
325
- s.pause();
324
+ const i = this.host.contentVideo, s = !i.paused && !i.ended;
325
+ i.pause();
326
326
  for (const n of t) {
327
327
  this.playedRolls.add(n);
328
328
  try {
@@ -334,7 +334,7 @@ class lt {
334
334
  }
335
335
  if (this.destroyed) return;
336
336
  }
337
- (i || t[0].roll === "preRoll") && s.play().catch(() => {
337
+ (s || t[0].roll === "preRoll") && i.play().catch(() => {
338
338
  });
339
339
  })();
340
340
  return this.activeBreak = e.finally(() => {
@@ -343,17 +343,17 @@ class lt {
343
343
  }
344
344
  playAd(t) {
345
345
  return new Promise((e) => {
346
- const { labels: s } = this.host, i = l("div", "imp-ad"), n = this.ensureAdVideo(), o = new AbortController(), a = o.signal;
346
+ const { labels: i } = this.host, s = l("div", "imp-ad"), n = this.ensureAdVideo(), o = new AbortController(), a = o.signal;
347
347
  n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
348
348
  const c = l("div", "imp-spinner imp-ad__spinner"), h = l("div", "imp-ad__hud"), u = l("span", "imp-ad__badge");
349
- u.textContent = t.adTitle ? `${s.adLabel} · ${t.adTitle}` : s.adLabel;
349
+ u.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
350
350
  const f = l("span", "imp-ad__countdown");
351
351
  h.append(u, f);
352
352
  const d = l("div", "imp-ad__actions");
353
353
  let b = null;
354
- t.clickThrough && (b = l("button", "imp-ad__visit", { type: "button" }), b.textContent = s.visitAdvertiser, d.append(b));
354
+ t.clickThrough && (b = l("button", "imp-ad__visit", { type: "button" }), b.textContent = i.visitAdvertiser, d.append(b));
355
355
  const v = l("button", "imp-ad__skip", { type: "button" });
356
- v.hidden = !0, d.append(v), i.append(n, c, h, d), this.host.container.append(i), this.layer = i;
356
+ v.hidden = !0, d.append(v), s.append(n, c, h, d), this.host.container.append(s), this.layer = s;
357
357
  const H = t.skipOffset ?? this.opts.skipDelay, N = /* @__PURE__ */ new Set(), L = (g) => {
358
358
  N.has(g) || (N.add(g), C(t.tracking[g]));
359
359
  };
@@ -372,7 +372,7 @@ class lt {
372
372
  error: new Error(`Ad media stalled for ${this.opts.mediaTimeout} ms — skipping`)
373
373
  }), A());
374
374
  }, 500), A = () => {
375
- clearInterval(X), o.abort(), n.pause(), n.removeAttribute("src"), n.load(), i.remove(), this.layer = null, e();
375
+ clearInterval(X), o.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
376
376
  }, O = (g) => {
377
377
  g ? (L("skip"), this.host.emitter.emit("adskip", { ad: t })) : L("complete"), this.host.emitter.emit("adend", { ad: t }), A();
378
378
  };
@@ -386,7 +386,7 @@ class lt {
386
386
  const g = n.currentTime, x = n.duration;
387
387
  if (Number.isFinite(x) && x > 0 && (f.textContent = w(Math.max(0, x - g)), g / x >= 0.25 && L("firstQuartile"), g / x >= 0.5 && L("midpoint"), g / x >= 0.75 && L("thirdQuartile")), H >= 0) {
388
388
  const z = Math.ceil(H - g);
389
- z > 0 ? (v.hidden = !1, v.disabled = !0, v.textContent = `${s.skipAdIn} ${z}`) : (v.hidden = !1, v.disabled = !1, v.textContent = s.skipAd);
389
+ z > 0 ? (v.hidden = !1, v.disabled = !0, v.textContent = `${i.skipAdIn} ${z}`) : (v.hidden = !1, v.disabled = !1, v.textContent = i.skipAd);
390
390
  }
391
391
  }, { signal: a }), n.addEventListener("ended", () => O(!1), { signal: a }), n.addEventListener("error", () => {
392
392
  this.host.emitter.emit("aderror", {
@@ -402,14 +402,14 @@ class lt {
402
402
  n.addEventListener("playing", () => {
403
403
  W = !0;
404
404
  }, { once: !0, signal: a }), n.addEventListener("pause", () => {
405
- n.ended || !i.isConnected || (i.classList.add("imp-ad--paused"), W && !B && (B = !0, C(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
405
+ n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), W && !B && (B = !0, C(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
406
406
  }, { signal: a }), n.addEventListener("play", () => {
407
- i.classList.remove("imp-ad--paused"), B && (B = !1, C(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
408
- }, { signal: a }), i.addEventListener("click", (g) => {
409
- (g.target === i || i.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
407
+ s.classList.remove("imp-ad--paused"), B && (B = !1, C(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
408
+ }, { signal: a }), s.addEventListener("click", (g) => {
409
+ (g.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
410
410
  });
411
411
  }), n.play().catch(() => {
412
- i.classList.add("imp-ad--paused");
412
+ s.classList.add("imp-ad--paused");
413
413
  });
414
414
  });
415
415
  }
@@ -422,20 +422,20 @@ class lt {
422
422
  }
423
423
  }
424
424
  function at(r, t) {
425
- const e = [...r].sort((i, n) => i.start - n.start), s = [];
426
- for (let i = 0; i < e.length; i++) {
427
- const n = Math.max(0, e[i].start);
425
+ const e = [...r].sort((s, n) => s.start - n.start), i = [];
426
+ for (let s = 0; s < e.length; s++) {
427
+ const n = Math.max(0, e[s].start);
428
428
  if (Number.isFinite(t) && n >= t) continue;
429
- let o = e[i].end ?? e[i + 1]?.start ?? t;
430
- Number.isFinite(t) && (o = Math.min(o, t)), !(o <= n) && s.push({ start: n, end: o, title: e[i].title });
429
+ let o = e[s].end ?? e[s + 1]?.start ?? t;
430
+ Number.isFinite(t) && (o = Math.min(o, t)), !(o <= n) && i.push({ start: n, end: o, title: e[s].title });
431
431
  }
432
- return s;
432
+ return i;
433
433
  }
434
434
  async function ht(r) {
435
435
  const t = await fetch(r);
436
436
  if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
437
437
  const e = await t.text();
438
- return U(e).map((s) => ({ start: s.start, end: s.end, title: s.text }));
438
+ return U(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
439
439
  }
440
440
  function K(r, t) {
441
441
  for (const e of r)
@@ -458,10 +458,10 @@ async function dt() {
458
458
  }
459
459
  return S;
460
460
  }
461
- async function ut(r, t, e, s) {
461
+ async function ut(r, t, e, i) {
462
462
  if (ct(t, e)) {
463
- const i = r.canPlayType("application/vnd.apple.mpegurl"), n = i ? null : await dt();
464
- return n && n.isSupported() ? pt(n, r, t, s) : i ? (r.src = t, $(r)) : (s.onError("HLS is not supported in this browser and hls.js could not be loaded."), $(r));
463
+ const s = r.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await dt();
464
+ return n && n.isSupported() ? pt(n, r, t, i) : s ? (r.src = t, $(r)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), $(r));
465
465
  }
466
466
  return r.src = t, $(r);
467
467
  }
@@ -477,50 +477,50 @@ function $(r) {
477
477
  }
478
478
  };
479
479
  }
480
- function pt(r, t, e, s) {
481
- const i = new r({ enableWorker: !0 }), n = {
480
+ function pt(r, t, e, i) {
481
+ const s = new r({ enableWorker: !0 }), n = {
482
482
  kind: "hls",
483
483
  levels: [],
484
484
  selected: -1,
485
485
  setLevel(c) {
486
- n.selected = c, i.currentLevel = c;
486
+ n.selected = c, s.currentLevel = c;
487
487
  },
488
488
  destroy() {
489
- i.destroy(), t.removeAttribute("src"), t.load();
489
+ s.destroy(), t.removeAttribute("src"), t.load();
490
490
  }
491
491
  };
492
- i.on(r.Events.MANIFEST_PARSED, () => {
493
- n.levels = i.levels.map((c, h) => ({
492
+ s.on(r.Events.MANIFEST_PARSED, () => {
493
+ n.levels = s.levels.map((c, h) => ({
494
494
  index: h,
495
495
  label: c.height ? `${c.height}p` : `${Math.round(c.bitrate / 1e3)} kbps`
496
- })).reverse(), s.onLevels(n.levels);
497
- }), i.on(r.Events.LEVEL_SWITCHED, (c, h) => {
498
- const u = i.levels[h.level];
499
- u && s.onLevelSwitch(u.height ? `${u.height}p` : `${Math.round(u.bitrate / 1e3)} kbps`);
496
+ })).reverse(), i.onLevels(n.levels);
497
+ }), s.on(r.Events.LEVEL_SWITCHED, (c, h) => {
498
+ const u = s.levels[h.level];
499
+ u && i.onLevelSwitch(u.height ? `${u.height}p` : `${Math.round(u.bitrate / 1e3)} kbps`);
500
500
  });
501
501
  let o = 0, a = !1;
502
- return i.on(r.Events.ERROR, (c, h) => {
502
+ return s.on(r.Events.ERROR, (c, h) => {
503
503
  if (h.fatal)
504
504
  switch (h.type) {
505
505
  case r.ErrorTypes.NETWORK_ERROR:
506
- i.startLoad();
506
+ s.startLoad();
507
507
  break;
508
508
  case r.ErrorTypes.MEDIA_ERROR:
509
- o < 3 ? (o++, i.recoverMediaError()) : (s.onError(`HLS media error: ${h.details}`, h), i.destroy());
509
+ o < 3 ? (o++, s.recoverMediaError()) : (i.onError(`HLS media error: ${h.details}`, h), s.destroy());
510
510
  break;
511
511
  default:
512
512
  if (a)
513
- s.onError(`HLS fatal error: ${h.details}`, h), i.destroy();
513
+ i.onError(`HLS fatal error: ${h.details}`, h), s.destroy();
514
514
  else {
515
515
  a = !0;
516
516
  try {
517
- i.loadSource(e), i.startLoad();
517
+ s.loadSource(e), s.startLoad();
518
518
  } catch {
519
- s.onError(`HLS fatal error: ${h.details}`, h), i.destroy();
519
+ i.onError(`HLS fatal error: ${h.details}`, h), s.destroy();
520
520
  }
521
521
  }
522
522
  }
523
- }), i.loadSource(e), i.attachMedia(t), n;
523
+ }), s.loadSource(e), s.attachMedia(t), n;
524
524
  }
525
525
  class q {
526
526
  constructor(t) {
@@ -529,8 +529,8 @@ class q {
529
529
  static async load(t) {
530
530
  const e = await fetch(t);
531
531
  if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
532
- const s = await e.text(), i = [];
533
- for (const n of U(s)) {
532
+ const i = await e.text(), s = [];
533
+ for (const n of U(i)) {
534
534
  const [o, a] = n.text.trim().split("#");
535
535
  if (!o) continue;
536
536
  const c = {
@@ -538,16 +538,16 @@ class q {
538
538
  end: n.end,
539
539
  src: G(o, t)
540
540
  }, h = a?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
541
- h && (c.xywh = { x: Number(h[1]), y: Number(h[2]), w: Number(h[3]), h: Number(h[4]) }), i.push(c);
541
+ h && (c.xywh = { x: Number(h[1]), y: Number(h[2]), w: Number(h[3]), h: Number(h[4]) }), s.push(c);
542
542
  }
543
- return i.sort((n, o) => n.start - o.start), new q(i);
543
+ return s.sort((n, o) => n.start - o.start), new q(s);
544
544
  }
545
545
  cueAt(t) {
546
- let e = 0, s = this.cues.length - 1;
547
- for (; e <= s; ) {
548
- const i = e + s >> 1, n = this.cues[i];
549
- if (t < n.start) s = i - 1;
550
- else if (t >= n.end) e = i + 1;
546
+ let e = 0, i = this.cues.length - 1;
547
+ for (; e <= i; ) {
548
+ const s = e + i >> 1, n = this.cues[s];
549
+ if (t < n.start) i = s - 1;
550
+ else if (t >= n.end) e = s + 1;
551
551
  else return n;
552
552
  }
553
553
  return null;
@@ -569,27 +569,27 @@ class M {
569
569
  this.root.textContent = "";
570
570
  for (const e of t) {
571
571
  if (e.items.length === 0) continue;
572
- const s = l("div", "imp-menu__section");
572
+ const i = l("div", "imp-menu__section");
573
573
  if (e.title) {
574
- const i = l("div", "imp-menu__title");
575
- i.textContent = e.title, s.append(i);
574
+ const s = l("div", "imp-menu__title");
575
+ s.textContent = e.title, i.append(s);
576
576
  }
577
- for (const i of e.items) {
577
+ for (const s of e.items) {
578
578
  const n = l("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
579
- if (n.setAttribute("aria-checked", String(i.active)), i.active && n.classList.add("imp-menu__item--active"), i.icon) {
579
+ if (n.setAttribute("aria-checked", String(s.active)), s.active && n.classList.add("imp-menu__item--active"), s.icon) {
580
580
  const a = l("span", "imp-menu__icon");
581
- i.icon.trimStart().startsWith("<svg") ? a.innerHTML = i.icon : a.append(l("img", "", { src: i.icon, alt: "" })), n.append(a);
581
+ s.icon.trimStart().startsWith("<svg") ? a.innerHTML = s.icon : a.append(l("img", "", { src: s.icon, alt: "" })), n.append(a);
582
582
  }
583
583
  const o = l("span", "imp-menu__label");
584
- o.textContent = i.label, n.append(o), n.addEventListener("click", () => {
585
- e.onSelect(i.value), this.close();
586
- }), s.append(n);
584
+ o.textContent = s.label, n.append(o), n.addEventListener("click", () => {
585
+ e.onSelect(s.value), this.close();
586
+ }), i.append(n);
587
587
  }
588
- this.root.append(s);
588
+ this.root.append(i);
589
589
  }
590
590
  this.root.hidden = !1, this.backdrop.hidden = !1, this.outsideListener = (e) => {
591
- const s = e.target;
592
- !this.root.contains(s) && !this.anchor.contains(s) && this.close();
591
+ const i = e.target;
592
+ !this.root.contains(i) && !this.anchor.contains(i) && this.close();
593
593
  }, setTimeout(() => {
594
594
  this.outsideListener && document.addEventListener("pointerdown", this.outsideListener);
595
595
  }, 0);
@@ -618,12 +618,12 @@ class mt {
618
618
  }
619
619
  setChapters(t) {
620
620
  this.chapters = t, this.track.textContent = "", this.segments = [];
621
- const e = t.length > 0 ? t : [{ start: 0, end: this.duration || 1, title: "" }], s = [];
622
- let i = 0;
621
+ const e = t.length > 0 ? t : [{ start: 0, end: this.duration || 1, title: "" }], i = [];
622
+ let s = 0;
623
623
  for (const n of e)
624
- n.start > i && s.push({ start: i, end: n.start, title: "" }), s.push(n), i = n.end;
625
- this.duration > 0 && i < this.duration && s.push({ start: i, end: this.duration, title: "" });
626
- for (const n of s) {
624
+ n.start > s && i.push({ start: s, end: n.start, title: "" }), i.push(n), s = n.end;
625
+ this.duration > 0 && s < this.duration && i.push({ start: s, end: this.duration, title: "" });
626
+ for (const n of i) {
627
627
  const o = l("div", "imp-progress__segment");
628
628
  o.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
629
629
  const a = l("div", "imp-progress__fill");
@@ -633,16 +633,16 @@ class mt {
633
633
  setThumbnails(t) {
634
634
  this.thumbnails = t;
635
635
  }
636
- update(t, e, s) {
636
+ update(t, e, i) {
637
637
  if (e !== this.duration && Number.isFinite(e) && this.setDuration(e), this.scrubbing) return;
638
638
  this.render(t);
639
- const i = this.duration > 0 ? y(s / this.duration, 0, 1) : 0;
640
- this.buffered.style.width = `${i * 100}%`, this.root.setAttribute("aria-valuemin", "0"), this.root.setAttribute("aria-valuemax", String(Math.round(this.duration))), this.root.setAttribute("aria-valuenow", String(Math.round(t))), this.root.setAttribute("aria-valuetext", `${w(t)} / ${w(this.duration)}`);
639
+ const s = this.duration > 0 ? y(i / this.duration, 0, 1) : 0;
640
+ this.buffered.style.width = `${s * 100}%`, this.root.setAttribute("aria-valuemin", "0"), this.root.setAttribute("aria-valuemax", String(Math.round(this.duration))), this.root.setAttribute("aria-valuenow", String(Math.round(t))), this.root.setAttribute("aria-valuetext", `${w(t)} / ${w(this.duration)}`);
641
641
  }
642
642
  render(t) {
643
- for (const { chapter: s, fill: i } of this.segments) {
644
- const n = s.end - s.start, o = n > 0 ? y((t - s.start) / n, 0, 1) : 0;
645
- i.style.transform = `scaleX(${o})`;
643
+ for (const { chapter: i, fill: s } of this.segments) {
644
+ const n = i.end - i.start, o = n > 0 ? y((t - i.start) / n, 0, 1) : 0;
645
+ s.style.transform = `scaleX(${o})`;
646
646
  }
647
647
  const e = this.duration > 0 ? y(t / this.duration, 0, 1) : 0;
648
648
  this.handle.style.left = `${e * 100}%`;
@@ -665,10 +665,10 @@ class mt {
665
665
  showTooltip(t) {
666
666
  const e = this.timeFromEvent(t);
667
667
  this.tooltipTime.textContent = w(e);
668
- const s = K(this.chapters, e);
669
- this.tooltipChapter.textContent = s?.title ?? "", this.tooltipChapter.hidden = !s?.title;
670
- const i = this.thumbnails?.cueAt(e) ?? null;
671
- i ? (this.tooltipThumb.hidden = !1, this.tooltipThumb.style.backgroundImage = `url("${i.src}")`, i.xywh ? (this.tooltipThumb.style.width = `${i.xywh.w}px`, this.tooltipThumb.style.height = `${i.xywh.h}px`, this.tooltipThumb.style.backgroundPosition = `-${i.xywh.x}px -${i.xywh.y}px`, this.tooltipThumb.style.backgroundSize = "auto") : (this.tooltipThumb.style.width = "160px", this.tooltipThumb.style.height = "90px", this.tooltipThumb.style.backgroundPosition = "center", this.tooltipThumb.style.backgroundSize = "cover")) : this.tooltipThumb.hidden = !0, this.tooltip.classList.add("imp-progress__tooltip--visible");
668
+ const i = K(this.chapters, e);
669
+ this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !i?.title;
670
+ const s = this.thumbnails?.cueAt(e) ?? null;
671
+ s ? (this.tooltipThumb.hidden = !1, this.tooltipThumb.style.backgroundImage = `url("${s.src}")`, s.xywh ? (this.tooltipThumb.style.width = `${s.xywh.w}px`, this.tooltipThumb.style.height = `${s.xywh.h}px`, this.tooltipThumb.style.backgroundPosition = `-${s.xywh.x}px -${s.xywh.y}px`, this.tooltipThumb.style.backgroundSize = "auto") : (this.tooltipThumb.style.width = "160px", this.tooltipThumb.style.height = "90px", this.tooltipThumb.style.backgroundPosition = "center", this.tooltipThumb.style.backgroundSize = "cover")) : this.tooltipThumb.hidden = !0, this.tooltip.classList.add("imp-progress__tooltip--visible");
672
672
  const n = this.root.getBoundingClientRect(), o = y(t.clientX - n.left, 0, n.width), a = this.tooltip.offsetWidth / 2;
673
673
  this.tooltip.style.left = `${y(o, a, Math.max(a, n.width - a))}px`;
674
674
  }
@@ -679,7 +679,7 @@ class mt {
679
679
  const _ = class _ {
680
680
  constructor(t) {
681
681
  this.player = t, this.subtitlesBtn = null, this.settingsBtn = null, this.settingsMenu = null, this.subtitlesMenu = null, this.moreMenu = null, this.moreWrap = null, this.qualityBtn = null, this.qualityMenu = null, this.scenesBtn = null, this.likeBtn = null, this.dislikeBtn = null, this.likeCountEl = null, this.dislikeCountEl = null, this.prevBtn = null, this.nextBtn = null, this.seekBackBtn = null, this.seekFwdBtn = null, this.centerPlayBtn = null, this.centerPrevBtn = null, this.centerNextBtn = null, this.collapsibles = [], this.overflowed = /* @__PURE__ */ new Set(), this.resizeObserver = null, this.reflowScheduled = !1, this.actionItems = [], this.wasPlayingBeforeScrub = !1, this.disposers = [], this.onWindowResize = null;
682
- const { labels: e, icons: s } = t, i = t.controlsOptions;
682
+ const { labels: e, icons: i } = t, s = t.controlsOptions;
683
683
  this.root = l("div", "imp-controls"), this.progress = new mt({
684
684
  onSeek: (d) => t.seek(d),
685
685
  onScrubStart: () => {
@@ -688,17 +688,17 @@ const _ = class _ {
688
688
  onScrubEnd: () => {
689
689
  this.wasPlayingBeforeScrub && t.play();
690
690
  }
691
- }), i.progress && this.root.append(this.progress.root);
691
+ }), s.progress && this.root.append(this.progress.root);
692
692
  const n = l("div", "imp-controls__row");
693
693
  this.row = n, this.root.append(n);
694
694
  const o = l("div", "imp-controls__group"), a = l("div", "imp-controls__group");
695
695
  this.rightGroup = a;
696
696
  const c = l("div", "imp-controls__spacer");
697
697
  this.chapterLabel = l("div", "imp-controls__chapter"), n.append(o, c, a), c.append(this.chapterLabel);
698
- const h = typeof i.seekButtons == "object" ? i.seekButtons : {}, u = h.back ?? t.seekStep, f = h.forward ?? t.seekStep;
699
- if (i.playlist && t.hasPlaylist && (this.prevBtn = m("imp-btn--prev", e.previous, s.previous), this.prevBtn.addEventListener("click", () => t.previous()), o.append(this.prevBtn)), i.seekButtons && (this.seekBackBtn = m("imp-btn--seek-back", `${e.seekBack} ${u}s`, s.seekBack), this.seekBackBtn.addEventListener("click", () => t.skip(-u)), o.append(this.seekBackBtn)), i.play && (this.playBtn = m("imp-btn--play", e.play, s.play), this.playBtn.addEventListener("click", () => t.togglePlay()), o.append(this.playBtn)), i.seekButtons && (this.seekFwdBtn = m("imp-btn--seek-forward", `${e.seekForward} ${f}s`, s.seekForward), this.seekFwdBtn.addEventListener("click", () => t.skip(f)), o.append(this.seekFwdBtn)), i.playlist && t.hasPlaylist && (this.nextBtn = m("imp-btn--next", e.next, s.next), this.nextBtn.addEventListener("click", () => t.next()), o.append(this.nextBtn)), i.volume) {
698
+ const h = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = h.back ?? t.seekStep, f = h.forward ?? t.seekStep;
699
+ if (s.playlist && t.hasPlaylist && (this.prevBtn = m("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), o.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = m("imp-btn--seek-back", `${e.seekBack} ${u}s`, i.seekBack), this.seekBackBtn.addEventListener("click", () => t.skip(-u)), o.append(this.seekBackBtn)), s.play && (this.playBtn = m("imp-btn--play", e.play, i.play), this.playBtn.addEventListener("click", () => t.togglePlay()), o.append(this.playBtn)), s.seekButtons && (this.seekFwdBtn = m("imp-btn--seek-forward", `${e.seekForward} ${f}s`, i.seekForward), this.seekFwdBtn.addEventListener("click", () => t.skip(f)), o.append(this.seekFwdBtn)), s.playlist && t.hasPlaylist && (this.nextBtn = m("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), o.append(this.nextBtn)), s.volume) {
700
700
  const d = l("div", "imp-volume");
701
- this.muteBtn = m("imp-btn--mute", e.mute, s.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = l("input", "imp-volume__slider", {
701
+ this.muteBtn = m("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = l("input", "imp-volume__slider", {
702
702
  type: "range",
703
703
  min: "0",
704
704
  max: "1",
@@ -708,8 +708,8 @@ const _ = class _ {
708
708
  t.setVolume(Number(this.volumeSlider.value));
709
709
  }), d.append(this.muteBtn, this.volumeSlider), o.append(d);
710
710
  }
711
- if (i.time && (this.timeLabel = l("div", "imp-controls__time"), this.liveBadge = l("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, o.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike(a), i.subtitles) {
712
- this.subtitlesBtn = m("imp-btn--subtitles", e.subtitles, s.subtitles), this.subtitlesMenu = new M(this.subtitlesBtn);
711
+ if (s.time && (this.timeLabel = l("div", "imp-controls__time"), this.liveBadge = l("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, o.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike(a), s.subtitles) {
712
+ this.subtitlesBtn = m("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new M(this.subtitlesBtn);
713
713
  const d = l("div", "imp-controls__menu-anchor");
714
714
  d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), a.append(d), this.registerCollapsible({
715
715
  key: "subtitles",
@@ -719,8 +719,8 @@ const _ = class _ {
719
719
  section: () => this.subtitlesSection()
720
720
  });
721
721
  }
722
- if (i.settings) {
723
- this.settingsBtn = m("imp-btn--settings", e.settings, s.speed), this.settingsMenu = new M(this.settingsBtn);
722
+ if (s.settings) {
723
+ this.settingsBtn = m("imp-btn--settings", e.settings, i.speed), this.settingsMenu = new M(this.settingsBtn);
724
724
  const d = l("div", "imp-controls__menu-anchor");
725
725
  d.append(this.settingsBtn, this.settingsMenu.root), this.settingsBtn.addEventListener("click", () => this.toggleSettingsMenu()), a.append(d), this.registerCollapsible({
726
726
  key: "settings",
@@ -730,8 +730,8 @@ const _ = class _ {
730
730
  section: () => this.speedSection()
731
731
  });
732
732
  }
733
- if (i.quality) {
734
- this.qualityBtn = m("imp-btn--quality", e.quality, s.settings), this.qualityMenu = new M(this.qualityBtn);
733
+ if (s.quality) {
734
+ this.qualityBtn = m("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new M(this.qualityBtn);
735
735
  const d = l("div", "imp-controls__menu-anchor");
736
736
  d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), a.append(d), this.registerCollapsible({
737
737
  key: "quality",
@@ -741,44 +741,44 @@ const _ = class _ {
741
741
  section: () => this.qualitySection()
742
742
  });
743
743
  }
744
- if (i.scenes && (this.scenesBtn = m("imp-btn--scenes", e.scenes, s.scenes), this.scenesBtn.addEventListener("click", () => t.toggleScenesPanel()), a.append(this.scenesBtn), this.registerCollapsible({
744
+ if (s.scenes && (this.scenesBtn = m("imp-btn--scenes", e.scenes, i.scenes), this.scenesBtn.addEventListener("click", () => t.toggleScenesPanel()), a.append(this.scenesBtn), this.registerCollapsible({
745
745
  key: "scenes",
746
746
  el: this.scenesBtn,
747
747
  priority: 25,
748
748
  available: () => t.chapterList.length > 0,
749
- section: () => this.simpleSection("scenes", e.scenes, s.scenes, () => t.toggleScenesPanel())
750
- })), i.playlist && t.hasPlaylist) {
751
- const d = m("imp-btn--list", e.playlist, s.list);
749
+ section: () => this.simpleSection("scenes", e.scenes, i.scenes, () => t.toggleScenesPanel())
750
+ })), s.playlist && t.hasPlaylist) {
751
+ const d = m("imp-btn--list", e.playlist, i.list);
752
752
  d.addEventListener("click", () => t.togglePlaylistPanel()), a.append(d), this.registerCollapsible({
753
753
  key: "list",
754
754
  el: d,
755
755
  priority: 50,
756
756
  available: () => !0,
757
- section: () => this.simpleSection("list", e.playlist, s.list, () => t.togglePlaylistPanel())
757
+ section: () => this.simpleSection("list", e.playlist, i.list, () => t.togglePlaylistPanel())
758
758
  });
759
759
  }
760
- if (i.pip && "requestPictureInPicture" in HTMLVideoElement.prototype) {
761
- const d = m("imp-btn--pip", e.pip, s.pip);
760
+ if (s.pip && "requestPictureInPicture" in HTMLVideoElement.prototype) {
761
+ const d = m("imp-btn--pip", e.pip, i.pip);
762
762
  d.addEventListener("click", () => void t.togglePip()), a.append(d), this.registerCollapsible({
763
763
  key: "pip",
764
764
  el: d,
765
765
  priority: 20,
766
766
  available: () => !0,
767
- section: () => this.simpleSection("pip", e.pip, s.pip, () => void t.togglePip())
767
+ section: () => this.simpleSection("pip", e.pip, i.pip, () => void t.togglePip())
768
768
  });
769
769
  }
770
- if (i.fullscreen && (this.fullscreenBtn = m("imp-btn--fullscreen", e.fullscreen, s.fullscreen), this.fullscreenBtn.addEventListener("click", () => void t.toggleFullscreen()), a.append(this.fullscreenBtn)), this.prevBtn && this.registerCollapsible({
770
+ if (s.fullscreen && (this.fullscreenBtn = m("imp-btn--fullscreen", e.fullscreen, i.fullscreen), this.fullscreenBtn.addEventListener("click", () => void t.toggleFullscreen()), a.append(this.fullscreenBtn)), this.prevBtn && this.registerCollapsible({
771
771
  key: "prev",
772
772
  el: this.prevBtn,
773
773
  priority: 70,
774
774
  available: () => !0,
775
- section: () => t.hasPrevious ? this.simpleSection("prev", e.previous, s.previous, () => t.previous()) : null
775
+ section: () => t.hasPrevious ? this.simpleSection("prev", e.previous, i.previous, () => t.previous()) : null
776
776
  }), this.nextBtn && this.registerCollapsible({
777
777
  key: "next",
778
778
  el: this.nextBtn,
779
779
  priority: 72,
780
780
  available: () => !0,
781
- section: () => t.hasNext ? this.simpleSection("next", e.next, s.next, () => t.next()) : null
781
+ section: () => t.hasNext ? this.simpleSection("next", e.next, i.next, () => t.next()) : null
782
782
  }), this.seekBackBtn) {
783
783
  const d = this.seekBackBtn;
784
784
  this.registerCollapsible({
@@ -786,7 +786,7 @@ const _ = class _ {
786
786
  el: d,
787
787
  priority: 80,
788
788
  available: () => Number.isFinite(t.duration) && t.duration > 0,
789
- section: () => this.simpleSection("seekBack", `${e.seekBack} ${u}s`, s.seekBack, () => t.skip(-u))
789
+ section: () => this.simpleSection("seekBack", `${e.seekBack} ${u}s`, i.seekBack, () => t.skip(-u))
790
790
  });
791
791
  }
792
792
  if (this.seekFwdBtn) {
@@ -796,64 +796,64 @@ const _ = class _ {
796
796
  el: d,
797
797
  priority: 82,
798
798
  available: () => Number.isFinite(t.duration) && t.duration > 0,
799
- section: () => this.simpleSection("seekFwd", `${e.seekForward} ${f}s`, s.seekForward, () => t.skip(f))
799
+ section: () => this.simpleSection("seekFwd", `${e.seekForward} ${f}s`, i.seekForward, () => t.skip(f))
800
800
  });
801
801
  }
802
- if (this.center = l("div", "imp-center-controls"), i.playlist && t.hasPlaylist && (this.centerPrevBtn = this.makeCenterButton("prev", e.previous, s.previous), this.centerPrevBtn.addEventListener("click", () => t.previous()), this.center.append(this.centerPrevBtn)), i.seekButtons) {
803
- const d = this.makeCenterButton("seek-back", `${e.seekBack} ${u}s`, s.seekBack);
802
+ if (this.center = l("div", "imp-center-controls"), s.playlist && t.hasPlaylist && (this.centerPrevBtn = this.makeCenterButton("prev", e.previous, i.previous), this.centerPrevBtn.addEventListener("click", () => t.previous()), this.center.append(this.centerPrevBtn)), s.seekButtons) {
803
+ const d = this.makeCenterButton("seek-back", `${e.seekBack} ${u}s`, i.seekBack);
804
804
  d.addEventListener("click", () => t.skip(-u)), this.center.append(d);
805
805
  }
806
- if (i.play && (this.centerPlayBtn = this.makeCenterButton("play", e.play, s.play), this.centerPlayBtn.addEventListener("click", () => t.togglePlay()), this.center.append(this.centerPlayBtn)), i.seekButtons) {
807
- const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${f}s`, s.seekForward);
806
+ if (s.play && (this.centerPlayBtn = this.makeCenterButton("play", e.play, i.play), this.centerPlayBtn.addEventListener("click", () => t.togglePlay()), this.center.append(this.centerPlayBtn)), s.seekButtons) {
807
+ const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${f}s`, i.seekForward);
808
808
  d.addEventListener("click", () => t.skip(f)), this.center.append(d);
809
809
  }
810
- i.playlist && t.hasPlaylist && (this.centerNextBtn = this.makeCenterButton("next", e.next, s.next), this.centerNextBtn.addEventListener("click", () => t.next()), this.center.append(this.centerNextBtn)), this.center.style.display = "none", this.buildMoreDropdown(a), this.bind(), this.syncVolume(), this.syncPlayState(), this.setLikeState(t.actionsOptions.likeState ?? null), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.scheduleReflow()), this.resizeObserver.observe(t.container)), this.onWindowResize = () => this.scheduleReflow(), window.addEventListener("resize", this.onWindowResize);
810
+ s.playlist && t.hasPlaylist && (this.centerNextBtn = this.makeCenterButton("next", e.next, i.next), this.centerNextBtn.addEventListener("click", () => t.next()), this.center.append(this.centerNextBtn)), this.center.style.display = "none", this.buildMoreDropdown(a), this.bind(), this.syncVolume(), this.syncPlayState(), this.setLikeState(t.actionsOptions.likeState ?? null), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.scheduleReflow()), this.resizeObserver.observe(t.container)), this.onWindowResize = () => this.scheduleReflow(), window.addEventListener("resize", this.onWindowResize);
811
811
  }
812
812
  registerCollapsible(t) {
813
813
  this.collapsibles.push(t);
814
814
  }
815
815
  /** Center-cluster button — deliberately NOT `.imp-btn` (own sizing/look). */
816
- makeCenterButton(t, e, s) {
817
- const i = l("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
818
- return i.innerHTML = s, i;
816
+ makeCenterButton(t, e, i) {
817
+ const s = l("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
818
+ return s.innerHTML = i, s;
819
819
  }
820
820
  /** like/dislike — visible buttons (collapsible), highlightable via `setLikeState`. */
821
821
  buildLikeDislike(t) {
822
- const e = this.player, s = e.actionsOptions, { labels: i, icons: n } = e;
823
- if (s.like) {
824
- this.likeBtn = m("imp-btn--like", i.like, n.like), this.likeBtn.addEventListener("click", () => e.emit("action", { id: "like" })), this.likeCountEl = this.attachCountTooltip(this.likeBtn, s.likeCount);
822
+ const e = this.player, i = e.actionsOptions, { labels: s, icons: n } = e;
823
+ if (i.like) {
824
+ this.likeBtn = m("imp-btn--like", s.like, n.like), this.likeBtn.addEventListener("click", () => e.emit("action", { id: "like" })), this.likeCountEl = this.attachCountTooltip(this.likeBtn, i.likeCount);
825
825
  const o = this.wrapWithTooltip(this.likeBtn, this.likeCountEl);
826
826
  t.append(o), this.registerCollapsible({
827
827
  key: "like",
828
828
  el: o,
829
829
  priority: 62,
830
830
  available: () => !0,
831
- section: () => this.simpleSection("like", i.like, n.like, () => e.emit("action", { id: "like" }))
831
+ section: () => this.simpleSection("like", s.like, n.like, () => e.emit("action", { id: "like" }))
832
832
  });
833
833
  }
834
- if (s.dislike) {
835
- this.dislikeBtn = m("imp-btn--dislike", i.dislike, n.dislike), this.dislikeBtn.addEventListener("click", () => e.emit("action", { id: "dislike" })), this.dislikeCountEl = this.attachCountTooltip(this.dislikeBtn, s.dislikeCount);
834
+ if (i.dislike) {
835
+ this.dislikeBtn = m("imp-btn--dislike", s.dislike, n.dislike), this.dislikeBtn.addEventListener("click", () => e.emit("action", { id: "dislike" })), this.dislikeCountEl = this.attachCountTooltip(this.dislikeBtn, i.dislikeCount);
836
836
  const o = this.wrapWithTooltip(this.dislikeBtn, this.dislikeCountEl);
837
837
  t.append(o), this.registerCollapsible({
838
838
  key: "dislike",
839
839
  el: o,
840
840
  priority: 60,
841
841
  available: () => !0,
842
- section: () => this.simpleSection("dislike", i.dislike, n.dislike, () => e.emit("action", { id: "dislike" }))
842
+ section: () => this.simpleSection("dislike", s.dislike, n.dislike, () => e.emit("action", { id: "dislike" }))
843
843
  });
844
844
  }
845
845
  }
846
846
  attachCountTooltip(t, e) {
847
- const s = l("span", "imp-count-tooltip");
848
- return this.setCountText(s, e), s;
847
+ const i = l("span", "imp-count-tooltip");
848
+ return this.setCountText(i, e), i;
849
849
  }
850
850
  wrapWithTooltip(t, e) {
851
- const s = l("div", "imp-action");
852
- return s.append(t, e), s;
851
+ const i = l("div", "imp-action");
852
+ return i.append(t, e), i;
853
853
  }
854
854
  setCountText(t, e) {
855
- const s = e == null || e === "" ? "" : String(e);
856
- t.textContent = s, t.hidden = s === "";
855
+ const i = e == null || e === "" ? "" : String(e);
856
+ t.textContent = i, t.hidden = i === "";
857
857
  }
858
858
  setLikeCounts(t, e) {
859
859
  this.likeCountEl && t !== void 0 && this.setCountText(this.likeCountEl, t), this.dislikeCountEl && e !== void 0 && this.setCountText(this.dislikeCountEl, e);
@@ -863,11 +863,11 @@ const _ = class _ {
863
863
  }
864
864
  // === ⋯ menu ===========================================================
865
865
  buildMoreDropdown(t) {
866
- const e = this.player, s = e.actionsOptions, { labels: i, icons: n } = e;
867
- s.addTo && this.actionItems.push({ value: "addTo", label: i.addTo, icon: n.addTo, run: () => e.emit("action", { id: "addTo" }) }), s.share && this.actionItems.push({ value: "share", label: i.share, icon: n.share, run: () => void e.share() }), s.report && this.actionItems.push({ value: "report", label: i.report, icon: n.report, run: () => e.emit("action", { id: "report" }) });
868
- for (const c of s.custom ?? [])
866
+ const e = this.player, i = e.actionsOptions, { labels: s, icons: n } = e;
867
+ i.addTo && this.actionItems.push({ value: "addTo", label: s.addTo, icon: n.addTo, run: () => e.emit("action", { id: "addTo" }) }), i.share && this.actionItems.push({ value: "share", label: s.share, icon: n.share, run: () => void e.share() }), i.report && this.actionItems.push({ value: "report", label: s.report, icon: n.report, run: () => e.emit("action", { id: "report" }) });
868
+ for (const c of i.custom ?? [])
869
869
  this.actionItems.push({ value: `custom:${c.id}`, label: c.title, icon: c.icon, run: () => e.emit("customaction", { id: c.id }) });
870
- const o = m("imp-btn--more", i.more, n.more);
870
+ const o = m("imp-btn--more", s.more, n.more);
871
871
  this.moreMenu = new M(o);
872
872
  const a = l("div", "imp-controls__menu-anchor imp-controls__more");
873
873
  a.append(o, this.moreMenu.root), o.addEventListener("click", () => {
@@ -876,17 +876,17 @@ const _ = class _ {
876
876
  }
877
877
  /** ⋯ menu = overflowed controls (in display order) + consumer actions. */
878
878
  buildMoreSections() {
879
- const t = [], e = /* @__PURE__ */ new Map(), s = [], i = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "pip", "list", "subtitles", "settings", "quality"], n = this.collapsibles.filter((o) => this.overflowed.has(o.key) && o.available()).sort((o, a) => i.indexOf(o.key) - i.indexOf(a.key));
879
+ const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "pip", "list", "subtitles", "settings", "quality"], n = this.collapsibles.filter((o) => this.overflowed.has(o.key) && o.available()).sort((o, a) => s.indexOf(o.key) - s.indexOf(a.key));
880
880
  for (const o of n) {
881
881
  const a = o.section();
882
882
  if (a)
883
883
  if (!a.title && a.items.length === 1) {
884
884
  const c = a.items[0];
885
- s.push(c), e.set(c.value, () => a.onSelect(c.value));
885
+ i.push(c), e.set(c.value, () => a.onSelect(c.value));
886
886
  } else
887
887
  t.push(a);
888
888
  }
889
- if (s.length > 0 && t.unshift({ title: "", items: s, onSelect: (o) => e.get(o)?.() }), this.actionItems.length > 0) {
889
+ if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (o) => e.get(o)?.() }), this.actionItems.length > 0) {
890
890
  const o = new Map(this.actionItems.map((a) => [a.value, a.run]));
891
891
  t.push({
892
892
  title: "",
@@ -896,8 +896,8 @@ const _ = class _ {
896
896
  }
897
897
  return t;
898
898
  }
899
- simpleSection(t, e, s, i) {
900
- return { title: "", items: [{ value: t, label: e, icon: s, active: !1 }], onSelect: () => i() };
899
+ simpleSection(t, e, i, s) {
900
+ return { title: "", items: [{ value: t, label: e, icon: i, active: !1 }], onSelect: () => s() };
901
901
  }
902
902
  speedSection() {
903
903
  const t = this.player;
@@ -928,7 +928,7 @@ const _ = class _ {
928
928
  title: t.labels.subtitles,
929
929
  items: [
930
930
  { label: t.labels.subtitlesOff, value: "-1", active: t.activeSubtitle === -1 },
931
- ...t.subtitleTracks.map((e, s) => ({ label: e.label, value: String(s), active: t.activeSubtitle === s }))
931
+ ...t.subtitleTracks.map((e, i) => ({ label: e.label, value: String(i), active: t.activeSubtitle === i }))
932
932
  ],
933
933
  onSelect: (e) => t.setSubtitle(Number(e))
934
934
  };
@@ -946,24 +946,24 @@ const _ = class _ {
946
946
  reflow() {
947
947
  const t = window.innerWidth <= 767;
948
948
  this.center.style.display = t ? "flex" : "none", this.playBtn && (this.playBtn.style.display = t ? "none" : ""), this.overflowed.clear();
949
- for (const i of this.collapsibles) {
950
- if (t && _.CENTER_KEYS.has(i.key)) {
951
- i.el.style.display = "none";
949
+ for (const s of this.collapsibles) {
950
+ if (t && _.CENTER_KEYS.has(s.key)) {
951
+ s.el.style.display = "none";
952
952
  continue;
953
953
  }
954
- const n = i.available();
955
- i.el.style.display = n ? "" : "none", i.el.classList.remove("imp-collapsed");
954
+ const n = s.available();
955
+ s.el.style.display = n ? "" : "none", s.el.classList.remove("imp-collapsed");
956
956
  }
957
- const e = this.collapsibles.filter((i) => i.available() && !(t && _.CENTER_KEYS.has(i.key))).sort((i, n) => i.priority - n.priority);
958
- let s = e.length;
959
- for (; s-- > 0 && this.overflowsRow(); ) {
960
- const i = e.find((n) => !this.overflowed.has(n.key));
961
- if (!i) break;
962
- i.el.style.display = "none", i.el.classList.add("imp-collapsed"), this.overflowed.add(i.key);
957
+ const e = this.collapsibles.filter((s) => s.available() && !(t && _.CENTER_KEYS.has(s.key))).sort((s, n) => s.priority - n.priority);
958
+ let i = e.length;
959
+ for (; i-- > 0 && this.overflowsRow(); ) {
960
+ const s = e.find((n) => !this.overflowed.has(n.key));
961
+ if (!s) break;
962
+ s.el.style.display = "none", s.el.classList.add("imp-collapsed"), this.overflowed.add(s.key);
963
963
  }
964
964
  if (this.moreWrap) {
965
- const i = this.actionItems.length > 0 || this.overflowed.size > 0;
966
- this.moreWrap.style.display = i ? "" : "none";
965
+ const s = this.actionItems.length > 0 || this.overflowed.size > 0;
966
+ this.moreWrap.style.display = s ? "" : "none";
967
967
  }
968
968
  }
969
969
  overflowsRow() {
@@ -973,8 +973,8 @@ const _ = class _ {
973
973
  bind() {
974
974
  const t = this.player;
975
975
  this.disposers.push(
976
- t.on("timeupdate", ({ currentTime: e, duration: s }) => {
977
- this.progress.update(e, s, t.bufferedEnd), this.timeLabel && (t.live ? (this.timeLabel.hidden = !0, this.liveBadge.hidden = !1) : (this.timeLabel.hidden = !1, this.liveBadge.hidden = !0, this.timeLabel.textContent = `${w(e)} / ${w(s)}`));
976
+ t.on("timeupdate", ({ currentTime: e, duration: i }) => {
977
+ this.progress.update(e, i, t.bufferedEnd), this.timeLabel && (t.live ? (this.timeLabel.hidden = !0, this.liveBadge.hidden = !1) : (this.timeLabel.hidden = !1, this.liveBadge.hidden = !0, this.timeLabel.textContent = `${w(e)} / ${w(i)}`));
978
978
  }),
979
979
  t.on("play", () => this.syncPlayState()),
980
980
  t.on("pause", () => this.syncPlayState()),
@@ -995,13 +995,13 @@ const _ = class _ {
995
995
  ), this.syncPlaylistButtons(), this.reflow();
996
996
  }
997
997
  syncPlayState() {
998
- const t = this.player, [e, s] = t.ended ? [t.icons.replay, t.labels.replay] : t.paused ? [t.icons.play, t.labels.play] : [t.icons.pause, t.labels.pause];
999
- this.playBtn && E(this.playBtn, e, s), this.centerPlayBtn && E(this.centerPlayBtn, e, s);
998
+ const t = this.player, [e, i] = t.ended ? [t.icons.replay, t.labels.replay] : t.paused ? [t.icons.play, t.labels.play] : [t.icons.pause, t.labels.pause];
999
+ this.playBtn && E(this.playBtn, e, i), this.centerPlayBtn && E(this.centerPlayBtn, e, i);
1000
1000
  }
1001
1001
  syncVolume() {
1002
1002
  if (!this.muteBtn) return;
1003
- const t = this.player, e = t.muted ? 0 : t.volume, s = e === 0 ? t.icons.volumeMute : e < 0.5 ? t.icons.volumeLow : t.icons.volumeHigh;
1004
- E(this.muteBtn, s, t.muted ? t.labels.unmute : t.labels.mute), this.volumeSlider.value = String(e), this.volumeSlider.style.setProperty("--imp-volume-fill", `${e * 100}%`);
1003
+ const t = this.player, e = t.muted ? 0 : t.volume, i = e === 0 ? t.icons.volumeMute : e < 0.5 ? t.icons.volumeLow : t.icons.volumeHigh;
1004
+ E(this.muteBtn, i, t.muted ? t.labels.unmute : t.labels.mute), this.volumeSlider.value = String(e), this.volumeSlider.style.setProperty("--imp-volume-fill", `${e * 100}%`);
1005
1005
  }
1006
1006
  /** Called by the player when per-source data (chapters/quality/subtitles) changes. */
1007
1007
  syncFeatureButtons() {
@@ -1035,8 +1035,8 @@ class ft {
1035
1035
  constructor(t) {
1036
1036
  this.root = l("div", "imp-poster"), this.image = l("img", "imp-poster__image", { alt: "", decoding: "async" }), this.image.hidden = !0;
1037
1037
  const e = m("imp-poster__play", t.labels.play, t.icons.bigPlay);
1038
- e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("click", (s) => {
1039
- (s.target === this.root || s.target === this.image) && t.play();
1038
+ e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("click", (i) => {
1039
+ (i.target === this.root || i.target === this.image) && t.play();
1040
1040
  });
1041
1041
  }
1042
1042
  setSource(t) {
@@ -1055,7 +1055,7 @@ class vt {
1055
1055
  this.channelUrl && window.open(this.channelUrl, "_blank", "noopener");
1056
1056
  });
1057
1057
  const e = l("div", "imp-pause-screen__heading");
1058
- this.title = l("div", "imp-pause-screen__title"), this.description = l("div", "imp-pause-screen__description"), this.sponsor = l("a", "imp-sponsor", { target: "_blank", rel: "nofollow noopener" }), this.sponsor.hidden = !0, this.sponsorLabel = l("span", "imp-sponsor__label"), this.sponsorText = l("span", "imp-sponsor__text"), this.sponsor.append(this.sponsorLabel, this.sponsorText), this.sponsor.addEventListener("click", (s) => s.stopPropagation()), e.append(this.title, this.description, this.sponsor), this.defaultContent.append(e, this.channel), this.root.append(this.defaultContent);
1058
+ this.title = l("div", "imp-pause-screen__title"), this.description = l("div", "imp-pause-screen__description"), this.sponsor = l("a", "imp-sponsor", { target: "_blank", rel: "nofollow noopener" }), this.sponsor.hidden = !0, this.sponsorLabel = l("span", "imp-sponsor__label"), this.sponsorText = l("span", "imp-sponsor__text"), this.sponsor.append(this.sponsorLabel, this.sponsorText), this.sponsor.addEventListener("click", (i) => i.stopPropagation()), e.append(this.title, this.description, this.sponsor), this.defaultContent.append(e, this.channel), this.root.append(this.defaultContent);
1059
1059
  }
1060
1060
  setCustomContent(t) {
1061
1061
  this.custom?.remove(), this.custom = t, t && (t.classList.add("imp-pause-screen__custom"), this.root.append(t)), this.defaultContent.hidden = t !== null, this.root.classList.toggle("imp-pause-screen--custom", t !== null);
@@ -1068,8 +1068,8 @@ class vt {
1068
1068
  this.title.textContent = t?.title ?? "", this.description.textContent = t?.description ?? "";
1069
1069
  const e = t?.sponsor;
1070
1070
  this.sponsor.hidden = !e, e && (this.sponsor.href = e.url, this.sponsorText.textContent = e.text, this.sponsorLabel.textContent = e.label ?? this.labels.sponsored);
1071
- const s = t?.channel;
1072
- this.channel.hidden = !s, this.channelUrl = s?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!s?.url), s && (this.channelName.textContent = s.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${s.avatarShape ?? "circle"}`, s.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.style.backgroundImage = `url("${s.avatar}")`) : (this.channelAvatar.style.backgroundImage = "", this.channelAvatar.textContent = (s.name.trim()[0] ?? "?").toUpperCase()));
1071
+ const i = t?.channel;
1072
+ this.channel.hidden = !i, this.channelUrl = i?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!i?.url), i && (this.channelName.textContent = i.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${i.avatarShape ?? "circle"}`, i.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.style.backgroundImage = `url("${i.avatar}")`) : (this.channelAvatar.style.backgroundImage = "", this.channelAvatar.textContent = (i.name.trim()[0] ?? "?").toUpperCase()));
1073
1073
  }
1074
1074
  show() {
1075
1075
  this.root.hidden = !1;
@@ -1092,13 +1092,13 @@ class gt {
1092
1092
  }
1093
1093
  }
1094
1094
  buildCard(t) {
1095
- const e = l("button", "imp-related__card", { type: "button" }), s = l("div", "imp-related__thumb");
1096
- if (t.poster && (s.style.backgroundImage = `url("${t.poster}")`), t.duration) {
1095
+ const e = l("button", "imp-related__card", { type: "button" }), i = l("div", "imp-related__thumb");
1096
+ if (t.poster && (i.style.backgroundImage = `url("${t.poster}")`), t.duration) {
1097
1097
  const n = l("span", "imp-related__duration");
1098
- n.textContent = t.duration, s.append(n);
1098
+ n.textContent = t.duration, i.append(n);
1099
1099
  }
1100
- const i = l("div", "imp-related__card-title");
1101
- return i.textContent = t.title, e.append(s, i), e.addEventListener("click", () => {
1100
+ const s = l("div", "imp-related__card-title");
1101
+ return s.textContent = t.title, e.append(i, s), e.addEventListener("click", () => {
1102
1102
  this.player.emit("relatedclick", { item: t }), this.hide(), this.activate(t);
1103
1103
  }), e;
1104
1104
  }
@@ -1128,14 +1128,14 @@ class gt {
1128
1128
  }
1129
1129
  }
1130
1130
  class yt {
1131
- constructor(t, e = "sidebar", s) {
1131
+ constructor(t, e = "sidebar", i) {
1132
1132
  this.player = t, this.root = l("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
1133
- const i = l("div", "imp-playlist__header"), n = l("div", "imp-playlist__heading");
1134
- if (s) {
1133
+ const s = l("div", "imp-playlist__header"), n = l("div", "imp-playlist__heading");
1134
+ if (i) {
1135
1135
  const c = l("div", "imp-playlist__kicker");
1136
1136
  c.textContent = t.labels.playlist;
1137
1137
  const h = l("div", "imp-playlist__name");
1138
- h.textContent = s, n.append(c, h);
1138
+ h.textContent = i, n.append(c, h);
1139
1139
  } else
1140
1140
  n.textContent = t.labels.playlist;
1141
1141
  const o = l("div", "imp-playlist__tools");
@@ -1145,25 +1145,25 @@ class yt {
1145
1145
  t.setRepeat(!t.repeat), this.syncModes();
1146
1146
  });
1147
1147
  const a = m("imp-playlist__close", "Close", t.icons.close);
1148
- a.addEventListener("click", () => this.hide()), o.append(this.shuffleBtn, this.repeatBtn, a), i.append(n, o), this.list = l("div", "imp-playlist__list"), this.root.append(i, this.list), this.rebuild(), this.syncModes();
1148
+ a.addEventListener("click", () => this.hide()), o.append(this.shuffleBtn, this.repeatBtn, a), s.append(n, o), this.list = l("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
1149
1149
  }
1150
1150
  syncModes() {
1151
1151
  this.shuffleBtn.classList.toggle("imp-btn--active", this.player.shuffle), this.repeatBtn.classList.toggle("imp-btn--active", this.player.repeat);
1152
1152
  }
1153
1153
  rebuild() {
1154
1154
  this.list.textContent = "", this.player.playlist.forEach((t, e) => {
1155
- const s = l("button", "imp-playlist__item", { type: "button" });
1156
- e === this.player.index && s.classList.add("imp-playlist__item--active");
1157
- const i = l("div", "imp-playlist__thumb");
1158
- t.poster && (i.style.backgroundImage = `url("${t.poster}")`);
1155
+ const i = l("button", "imp-playlist__item", { type: "button" });
1156
+ e === this.player.index && i.classList.add("imp-playlist__item--active");
1157
+ const s = l("div", "imp-playlist__thumb");
1158
+ t.poster && (s.style.backgroundImage = `url("${t.poster}")`);
1159
1159
  const n = l("div", "imp-playlist__meta"), o = l("div", "imp-playlist__title");
1160
1160
  if (o.textContent = t.title ?? `#${e + 1}`, n.append(o), t.duration) {
1161
1161
  const a = l("div", "imp-playlist__duration");
1162
1162
  a.textContent = w(t.duration), n.append(a);
1163
1163
  }
1164
- s.append(i, n), s.addEventListener("click", () => {
1165
- this.player.playItem(e);
1166
- }), this.list.append(s);
1164
+ i.append(s, n), i.addEventListener("click", () => {
1165
+ this.player.playItem(e), window.innerWidth <= 767 && this.hide();
1166
+ }), this.list.append(i);
1167
1167
  });
1168
1168
  }
1169
1169
  get visible() {
@@ -1182,34 +1182,34 @@ class yt {
1182
1182
  class bt {
1183
1183
  constructor(t, e = "bottom") {
1184
1184
  this.player = t, this.items = [], this.root = l("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
1185
- const s = l("div", "imp-playlist__header"), i = l("span");
1186
- i.textContent = t.labels.scenes;
1185
+ const i = l("div", "imp-playlist__header"), s = l("span");
1186
+ s.textContent = t.labels.scenes;
1187
1187
  const n = m("imp-playlist__close", "Close", t.icons.close);
1188
- n.addEventListener("click", () => this.hide()), s.append(i, n), this.list = l("div", "imp-playlist__list"), this.root.append(s, this.list), t.on("chapterchange", () => this.syncActive());
1188
+ n.addEventListener("click", () => this.hide()), i.append(s, n), this.list = l("div", "imp-playlist__list"), this.root.append(i, this.list), t.on("chapterchange", () => this.syncActive());
1189
1189
  }
1190
1190
  /** Re-render from the player's current chapters + thumbnail track. */
1191
1191
  rebuild() {
1192
1192
  this.list.textContent = "", this.items = [];
1193
1193
  const t = this.player.thumbnails;
1194
1194
  for (const e of this.player.chapterList) {
1195
- const s = l("button", "imp-playlist__item", { type: "button" }), i = l("div", "imp-playlist__thumb"), n = t?.cueAt(e.start + 0.01) ?? null;
1195
+ const i = l("button", "imp-playlist__item", { type: "button" }), s = l("div", "imp-playlist__thumb"), n = t?.cueAt(e.start + 0.01) ?? null;
1196
1196
  if (n?.xywh) {
1197
1197
  const h = l("div", "imp-scenes__sprite");
1198
- h.style.width = `${n.xywh.w}px`, h.style.height = `${n.xywh.h}px`, h.style.backgroundImage = `url("${n.src}")`, h.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, h.style.setProperty("--imp-sprite-w", String(n.xywh.w)), i.append(h);
1199
- } else n && (i.style.backgroundImage = `url("${n.src}")`);
1198
+ h.style.width = `${n.xywh.w}px`, h.style.height = `${n.xywh.h}px`, h.style.backgroundImage = `url("${n.src}")`, h.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, h.style.setProperty("--imp-sprite-w", String(n.xywh.w)), s.append(h);
1199
+ } else n && (s.style.backgroundImage = `url("${n.src}")`);
1200
1200
  const o = l("div", "imp-playlist__meta"), a = l("div", "imp-playlist__title");
1201
1201
  a.textContent = e.title || w(e.start);
1202
1202
  const c = l("div", "imp-playlist__duration");
1203
- c.textContent = w(e.start), o.append(a, c), s.append(i, o), s.addEventListener("click", () => {
1204
- this.player.seek(e.start), this.player.play();
1205
- }), this.list.append(s), this.items.push(s);
1203
+ c.textContent = w(e.start), o.append(a, c), i.append(s, o), i.addEventListener("click", () => {
1204
+ this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
1205
+ }), this.list.append(i), this.items.push(i);
1206
1206
  }
1207
1207
  this.syncActive();
1208
1208
  }
1209
1209
  syncActive() {
1210
1210
  const t = this.player.chapter, e = this.player.chapterList;
1211
- this.items.forEach((s, i) => {
1212
- s.classList.toggle("imp-playlist__item--active", t !== null && e[i] === t);
1211
+ this.items.forEach((i, s) => {
1212
+ i.classList.toggle("imp-playlist__item--active", t !== null && e[s] === t);
1213
1213
  });
1214
1214
  }
1215
1215
  get visible() {
@@ -1247,15 +1247,15 @@ const kt = {
1247
1247
  class _t {
1248
1248
  constructor(t, e = {}) {
1249
1249
  this.scrubbing = !1, this.emitter = new Y(), this.abort = new AbortController(), this.sources = [], this.currentIndex = -1, this.sourceController = null, this.loadToken = 0, this.chapters = [], this.currentChapter = null, this.progressiveQuality = -1, this.thumbTrack = null, this.shuffleMode = !1, this.decodeRecoveries = 0, this.adManager = null, this.playedOnce = !1, this.idleTimer = null, this.destroyed = !1;
1250
- const s = typeof t == "string" ? document.querySelector(t) : t;
1251
- if (!s) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
1252
- this.mount = s, this.options = e, this.labels = { ...I, ...tt(e.language), ...e.labels }, this.icons = { ...J, ...e.icons }, this.controlsOptions = { ...kt, ...e.controls }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 0.75, 1, 1.25, 1.5, 2], this.seekStep = e.seekStep ?? 10, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = l("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
1253
- const i = e.styling;
1254
- if (i?.themeColor && this.container.style.setProperty("--imp-accent", i.themeColor), i?.likeColor && this.container.style.setProperty("--imp-like", i.likeColor), i?.dislikeColor && this.container.style.setProperty("--imp-dislike", i.dislikeColor), i?.borderRadius !== void 0) {
1255
- const h = typeof i.borderRadius == "number" ? `${i.borderRadius}px` : i.borderRadius;
1250
+ const i = typeof t == "string" ? document.querySelector(t) : t;
1251
+ if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
1252
+ this.mount = i, this.options = e, this.labels = { ...I, ...tt(e.language), ...e.labels }, this.icons = { ...J, ...e.icons }, this.controlsOptions = { ...kt, ...e.controls }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 0.75, 1, 1.25, 1.5, 2], this.seekStep = e.seekStep ?? 10, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = l("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
1253
+ const s = e.styling;
1254
+ if (s?.themeColor && this.container.style.setProperty("--imp-accent", s.themeColor), s?.likeColor && this.container.style.setProperty("--imp-like", s.likeColor), s?.dislikeColor && this.container.style.setProperty("--imp-dislike", s.dislikeColor), s?.borderRadius !== void 0) {
1255
+ const h = typeof s.borderRadius == "number" ? `${s.borderRadius}px` : s.borderRadius;
1256
1256
  this.container.style.setProperty("--imp-radius", h);
1257
1257
  }
1258
- i?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = l("video", "imp-video"), e.playsInline !== !1 && this.video.setAttribute("playsinline", ""), e.crossOrigin !== void 0 && (this.video.crossOrigin = e.crossOrigin), this.video.preload = "metadata", e.loop && (this.video.loop = !0), e.muted && (this.video.muted = !0), this.video.volume = y(e.volume ?? 1, 0, 1);
1258
+ s?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = l("video", "imp-video"), e.playsInline !== !1 && this.video.setAttribute("playsinline", ""), e.crossOrigin !== void 0 && (this.video.crossOrigin = e.crossOrigin), this.video.preload = "metadata", e.loop && (this.video.loop = !0), e.muted && (this.video.muted = !0), this.video.volume = y(e.volume ?? 1, 0, 1);
1259
1259
  const n = l("div", "imp-layer");
1260
1260
  this.spinner = l("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = l("div", "imp-error"), this.errorBox.hidden = !0, this.pauseScreen = new vt(this.labels), this.poster = new ft(this), this.related = new gt(this), this.related.setOptions(e.related), this.controls = new F(this), this.playlistPanel = new yt(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new bt(this, e.scenes?.layout ?? "bottom");
1261
1261
  const o = l("div", "imp-layer__middle");
@@ -1268,8 +1268,14 @@ class _t {
1268
1268
  c
1269
1269
  )), this.emitter.on("error", ({ message: h }) => {
1270
1270
  this.errorBox.textContent = h, this.errorBox.hidden = !1, this.spinner.hidden = !0, this.poster.hide();
1271
- }), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("click", () => {
1272
- this.playedOnce && !this.adPlaying && this.togglePlay();
1271
+ }), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (h) => {
1272
+ if (!(this.adPlaying || !this.playedOnce)) {
1273
+ if (h.pointerType === "mouse") {
1274
+ this.togglePlay();
1275
+ return;
1276
+ }
1277
+ this.container.classList.contains("imp-player--idle") ? (this.showControlsNow(), this.scheduleIdle()) : this.video.paused || this.container.classList.add("imp-player--idle");
1278
+ }
1273
1279
  }, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (h) => {
1274
1280
  this.pauseScreen.hasCustom || h.target === this.pauseScreen.root && this.togglePlay();
1275
1281
  }, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(y(this.playlistOptions.startIndex, 0, this.sources.length - 1), !!e.autoplay), this.emitter.emit("ready", { player: this });
@@ -1353,7 +1359,7 @@ class _t {
1353
1359
  get qualityLevels() {
1354
1360
  if (this.sourceController?.kind === "hls") return this.sourceController.levels;
1355
1361
  const t = this.source?.qualities;
1356
- return t ? t.map((e, s) => ({ index: s, label: e.label ?? String(e.quality ?? s) })) : [];
1362
+ return t ? t.map((e, i) => ({ index: i, label: e.label ?? String(e.quality ?? i) })) : [];
1357
1363
  }
1358
1364
  get qualityAutoAvailable() {
1359
1365
  return this.sourceController?.kind === "hls";
@@ -1370,8 +1376,8 @@ class _t {
1370
1376
  }
1371
1377
  const e = this.source?.qualities;
1372
1378
  if (!e || !e[t] || t === this.progressiveQuality) return;
1373
- const s = this.video.currentTime, i = !this.video.paused && !this.video.ended;
1374
- this.progressiveQuality = t, this.video.src = e[t].src, this.video.currentTime = s, i && this.video.play().catch(() => {
1379
+ const i = this.video.currentTime, s = !this.video.paused && !this.video.ended;
1380
+ this.progressiveQuality = t, this.video.src = e[t].src, this.video.currentTime = i, s && this.video.play().catch(() => {
1375
1381
  }), this.emitter.emit("qualitychange", { label: e[t].label ?? String(e[t].quality ?? t) });
1376
1382
  }
1377
1383
  // === subtitles ========================================================
@@ -1386,8 +1392,8 @@ class _t {
1386
1392
  }
1387
1393
  setSubtitle(t) {
1388
1394
  const e = this.video.textTracks;
1389
- for (let s = 0; s < e.length; s++)
1390
- e[s].mode = s === t ? "showing" : "disabled";
1395
+ for (let i = 0; i < e.length; i++)
1396
+ e[i].mode = i === t ? "showing" : "disabled";
1391
1397
  this.emitter.emit("subtitlechange", { track: this.subtitleTracks[t] ?? null });
1392
1398
  }
1393
1399
  // === playlist =========================================================
@@ -1517,12 +1523,12 @@ class _t {
1517
1523
  }
1518
1524
  // === internals ========================================================
1519
1525
  async loadItem(t, e) {
1520
- const s = ++this.loadToken, i = this.sources[t];
1521
- if (!i) return;
1526
+ const i = ++this.loadToken, s = this.sources[t];
1527
+ if (!s) return;
1522
1528
  this.currentIndex = t, this.sourceController?.destroy(), this.sourceController = null, this.chapters = [], this.currentChapter = null, this.progressiveQuality = -1, this.playedOnce = !1;
1523
1529
  for (const c of [...this.video.querySelectorAll("track")]) c.remove();
1524
- this.adManager?.resetForNewSource(), this.related.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.errorBox.hidden = !0, this.decodeRecoveries = 0, this.video.poster = i.poster ?? "", this.poster.setSource(i), this.pauseScreen.setSource(i), this.controls.progress.setChapters([]), this.controls.progress.setThumbnails(null), this.controls.progress.setHeatmap([]), e ? this.poster.hide() : this.poster.show(), this.playlistPanel.rebuild();
1525
- for (const c of Q(i.subtitles)) {
1530
+ this.adManager?.resetForNewSource(), this.related.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.errorBox.hidden = !0, this.decodeRecoveries = 0, this.video.poster = s.poster ?? "", this.poster.setSource(s), this.pauseScreen.setSource(s), this.controls.progress.setChapters([]), this.controls.progress.setThumbnails(null), this.controls.progress.setHeatmap([]), e ? this.poster.hide() : this.poster.show(), this.playlistPanel.rebuild();
1531
+ for (const c of Q(s.subtitles)) {
1526
1532
  const h = l("track", "", {
1527
1533
  kind: "subtitles",
1528
1534
  src: c.src,
@@ -1531,42 +1537,42 @@ class _t {
1531
1537
  });
1532
1538
  c.default && h.setAttribute("default", ""), this.video.append(h);
1533
1539
  }
1534
- let n = i.src, o = i.type;
1535
- if (i.qualities && i.qualities.length > 0) {
1536
- const c = Math.max(0, i.qualities.findIndex((h) => h.src === i.src));
1537
- this.progressiveQuality = c, n = i.qualities[c].src, o = i.qualities[c].type ?? o;
1540
+ let n = s.src, o = s.type;
1541
+ if (s.qualities && s.qualities.length > 0) {
1542
+ const c = Math.max(0, s.qualities.findIndex((h) => h.src === s.src));
1543
+ this.progressiveQuality = c, n = s.qualities[c].src, o = s.qualities[c].type ?? o;
1538
1544
  }
1539
1545
  this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
1540
1546
  const a = await ut(this.video, n, o, {
1541
1547
  onLevels: () => {
1542
- s === this.loadToken && this.controls.syncFeatureButtons();
1548
+ i === this.loadToken && this.controls.syncFeatureButtons();
1543
1549
  },
1544
1550
  onLevelSwitch: (c) => this.emitter.emit("qualitychange", { label: c }),
1545
1551
  onError: (c, h) => this.emitter.emit("error", { message: c, cause: h })
1546
1552
  });
1547
- if (s !== this.loadToken) {
1553
+ if (i !== this.loadToken) {
1548
1554
  a.destroy();
1549
1555
  return;
1550
1556
  }
1551
- if (this.sourceController = a, this.emitter.emit("sourcechange", { source: i, index: t }), i.thumbnails && q.load(i.thumbnails).then((c) => {
1552
- s === this.loadToken && (this.thumbTrack = c, this.controls.progress.setThumbnails(c), this.scenesPanel.visible && this.scenesPanel.rebuild());
1553
- }).catch((c) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: c })), i.chapters) {
1557
+ if (this.sourceController = a, this.emitter.emit("sourcechange", { source: s, index: t }), s.thumbnails && q.load(s.thumbnails).then((c) => {
1558
+ i === this.loadToken && (this.thumbTrack = c, this.controls.progress.setThumbnails(c), this.scenesPanel.visible && this.scenesPanel.rebuild());
1559
+ }).catch((c) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: c })), s.chapters) {
1554
1560
  const c = (h) => {
1555
1561
  const u = () => {
1556
- s === this.loadToken && (this.chapters = at(h, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
1562
+ i === this.loadToken && (this.chapters = at(h, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
1557
1563
  };
1558
1564
  Number.isFinite(this.video.duration) && this.video.duration > 0 ? u() : this.video.addEventListener("loadedmetadata", u, { once: !0, signal: this.abort.signal });
1559
1565
  };
1560
- typeof i.chapters == "string" ? ht(i.chapters).then((h) => c(h)).catch((h) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: h })) : c(i.chapters);
1566
+ typeof s.chapters == "string" ? ht(s.chapters).then((h) => c(h)).catch((h) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: h })) : c(s.chapters);
1561
1567
  }
1562
- if (i.heatmap && i.heatmap.length > 0 && this.controlsOptions.heatmap) {
1563
- const c = i.heatmap, h = () => {
1564
- s === this.loadToken && this.controls.progress.setHeatmap(et(c, this.video.duration));
1568
+ if (s.heatmap && s.heatmap.length > 0 && this.controlsOptions.heatmap) {
1569
+ const c = s.heatmap, h = () => {
1570
+ i === this.loadToken && this.controls.progress.setHeatmap(et(c, this.video.duration));
1565
1571
  };
1566
1572
  Number.isFinite(this.video.duration) && this.video.duration > 0 ? h() : this.video.addEventListener("loadedmetadata", h, { once: !0, signal: this.abort.signal });
1567
1573
  }
1568
1574
  e && this.play().catch(() => {
1569
- s === this.loadToken && this.poster.show();
1575
+ i === this.loadToken && this.poster.show();
1570
1576
  });
1571
1577
  }
1572
1578
  bindVideoEvents() {
@@ -1579,8 +1585,8 @@ class _t {
1579
1585
  this.handleEnded();
1580
1586
  }, { signal: t }), e.addEventListener("timeupdate", () => {
1581
1587
  this.emitter.emit("timeupdate", { currentTime: e.currentTime, duration: e.duration || 0 }), this.adManager?.checkMidRolls(e.currentTime);
1582
- const s = K(this.chapters, e.currentTime);
1583
- s !== this.currentChapter && (this.currentChapter = s, this.emitter.emit("chapterchange", { chapter: s }));
1588
+ const i = K(this.chapters, e.currentTime);
1589
+ i !== this.currentChapter && (this.currentChapter = i, this.emitter.emit("chapterchange", { chapter: i }));
1584
1590
  }, { signal: t }), e.addEventListener("progress", () => {
1585
1591
  this.emitter.emit("progress", { buffered: this.bufferedEnd });
1586
1592
  }, { signal: t }), e.addEventListener("volumechange", () => {
@@ -1588,14 +1594,14 @@ class _t {
1588
1594
  }, { signal: t }), e.addEventListener("seeking", () => this.emitter.emit("seeking", { currentTime: e.currentTime }), { signal: t }), e.addEventListener("seeked", () => this.emitter.emit("seeked", { currentTime: e.currentTime }), { signal: t }), e.addEventListener("waiting", () => {
1589
1595
  this.spinner.hidden = !1;
1590
1596
  }, { signal: t });
1591
- for (const s of ["playing", "canplay", "seeked"])
1592
- e.addEventListener(s, () => {
1597
+ for (const i of ["playing", "canplay", "seeked"])
1598
+ e.addEventListener(i, () => {
1593
1599
  this.spinner.hidden = !0, this.errorBox.hidden = !0, this.decodeRecoveries = 0;
1594
1600
  }, { signal: t });
1595
1601
  e.addEventListener("error", () => {
1596
- const s = e.error;
1597
- if (!s || this.sourceController?.kind === "hls" || e.getAttribute("src") === null && !e.currentSrc) return;
1598
- if ((s.code === MediaError.MEDIA_ERR_DECODE || /DEMUXER|PARSE|DECODE/i.test(s.message || "")) && this.decodeRecoveries < 2 && Number.isFinite(e.duration)) {
1602
+ const i = e.error;
1603
+ if (!i || this.sourceController?.kind === "hls" || e.getAttribute("src") === null && !e.currentSrc) return;
1604
+ if ((i.code === MediaError.MEDIA_ERR_DECODE || /DEMUXER|PARSE|DECODE/i.test(i.message || "")) && this.decodeRecoveries < 2 && Number.isFinite(e.duration)) {
1599
1605
  this.decodeRecoveries++;
1600
1606
  const n = e.currentTime, o = !e.paused;
1601
1607
  e.load();
@@ -1610,7 +1616,7 @@ class _t {
1610
1616
  e.readyState >= 1 ? a() : e.addEventListener("loadedmetadata", a, { once: !0, signal: this.abort.signal });
1611
1617
  return;
1612
1618
  }
1613
- this.emitter.emit("error", { message: s.message || `Media error (code ${s.code})`, cause: s });
1619
+ this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i });
1614
1620
  }, { signal: t }), e.addEventListener("enterpictureinpicture", () => this.emitter.emit("pipchange", { active: !0 }), { signal: t }), e.addEventListener("leavepictureinpicture", () => this.emitter.emit("pipchange", { active: !1 }), { signal: t }), document.addEventListener("fullscreenchange", () => {
1615
1621
  this.emitter.emit("fullscreenchange", { active: this.isFullscreen }), this.container.classList.toggle("imp-player--fullscreen", this.isFullscreen);
1616
1622
  }, { signal: t });
@@ -1629,8 +1635,12 @@ class _t {
1629
1635
  const { signal: t } = this.abort, e = () => {
1630
1636
  this.showControlsNow(), this.scheduleIdle();
1631
1637
  };
1632
- this.container.addEventListener("pointermove", e, { signal: t }), this.container.addEventListener("pointerdown", e, { signal: t }), this.container.addEventListener("keydown", e, { signal: t }), this.container.addEventListener("pointerleave", () => {
1633
- this.video.paused || this.container.classList.add("imp-player--idle");
1638
+ this.container.addEventListener("pointermove", (i) => {
1639
+ i.pointerType !== "touch" && e();
1640
+ }, { signal: t }), this.container.addEventListener("pointerdown", (i) => {
1641
+ i.pointerType !== "touch" && e();
1642
+ }, { signal: t }), this.container.addEventListener("keydown", e, { signal: t }), this.container.addEventListener("pointerleave", (i) => {
1643
+ i.pointerType !== "touch" && (this.video.paused || this.container.classList.add("imp-player--idle"));
1634
1644
  }, { signal: t });
1635
1645
  }
1636
1646
  showControlsNow() {
@@ -1646,11 +1656,11 @@ class _t {
1646
1656
  this.container.addEventListener("keydown", (t) => {
1647
1657
  const e = t.target;
1648
1658
  if (e.closest("input, select, textarea, [contenteditable]")) return;
1649
- const i = e.closest("button") !== null;
1659
+ const s = e.closest("button") !== null;
1650
1660
  switch (t.key) {
1651
1661
  case " ":
1652
1662
  case "k":
1653
- if (t.key === " " && i) return;
1663
+ if (t.key === " " && s) return;
1654
1664
  t.preventDefault(), this.togglePlay();
1655
1665
  break;
1656
1666
  case "ArrowLeft":