itube-modern-player 0.8.0 → 0.8.2

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,12 +1,12 @@
1
1
  import { posterSrc as q } from "./placeholder.js";
2
- import { d as D } from "./labels-CCjOCBKU.js";
2
+ import { d as G } from "./labels-CCjOCBKU.js";
3
3
  function a(r, t, e) {
4
4
  const i = document.createElement(r);
5
5
  if (t && (i.className = t), e)
6
6
  for (const [s, n] of Object.entries(e)) i.setAttribute(s, n);
7
7
  return i;
8
8
  }
9
- function S(r, t) {
9
+ function L(r, t) {
10
10
  if (r.textContent = "", typeof t == "object") {
11
11
  "url" in t ? r.append(a("img", "imp-icon-img", { src: t.url, alt: "" })) : r.innerHTML = t.svg;
12
12
  return;
@@ -19,22 +19,22 @@ function T(r, t = "") {
19
19
  }
20
20
  function b(r, t, e) {
21
21
  const i = a("button", `imp-btn ${r}`, { type: "button", "aria-label": t, title: t });
22
- return S(i, e), i;
22
+ return L(i, e), i;
23
23
  }
24
- function K(r, t) {
24
+ function X(r, t) {
25
25
  const e = a("div", `${t}__meta`);
26
26
  return r.forEach((i, s) => {
27
27
  s > 0 && e.append(document.createTextNode(" "));
28
- const n = typeof i == "string" ? i : i.text, l = typeof i == "string" ? void 0 : i.icon, o = a("span", `${t}__meta-chunk`);
29
- if (l) {
28
+ const n = typeof i == "string" ? i : i.text, o = typeof i == "string" ? void 0 : i.icon, l = a("span", `${t}__meta-chunk`);
29
+ if (o) {
30
30
  const h = a("span", `${t}__meta-icon`);
31
- S(h, l), o.append(h);
31
+ L(h, o), l.append(h);
32
32
  }
33
- o.append(document.createTextNode(n)), e.append(o);
33
+ l.append(document.createTextNode(n)), e.append(l);
34
34
  }), e;
35
35
  }
36
36
  function I(r, t, e) {
37
- S(r, t), e !== void 0 && (r.setAttribute("aria-label", e), r.setAttribute("title", e));
37
+ L(r, t), e !== void 0 && (r.setAttribute("aria-label", e), r.setAttribute("title", e));
38
38
  }
39
39
  function x(r, t, e) {
40
40
  return Math.min(e, Math.max(t, r));
@@ -44,22 +44,22 @@ function _(r) {
44
44
  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");
45
45
  return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
46
46
  }
47
- function O(r) {
47
+ function H(r) {
48
48
  const t = r.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
49
49
  if (!t) return null;
50
50
  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;
51
51
  return e * 3600 + i * 60 + s + n / 1e3;
52
52
  }
53
- function X(r) {
53
+ function J(r) {
54
54
  const t = [], e = r.replace(/\r\n?/g, `
55
55
  `).split(/\n\n+/);
56
56
  for (const i of e) {
57
57
  const s = i.split(`
58
- `).filter((v) => v.trim() !== "");
58
+ `).filter((f) => f.trim() !== "");
59
59
  if (s.length === 0) continue;
60
- let n = s.findIndex((v) => v.includes("-->"));
60
+ let n = s.findIndex((f) => f.includes("-->"));
61
61
  if (n === -1) continue;
62
- const [l, o] = s[n].split("-->"), h = O(l), c = O((o ?? "").split(" ")[1] ?? o ?? "") ?? O(o ?? "");
62
+ const [o, l] = s[n].split("-->"), h = H(o), c = H((l ?? "").split(" ")[1] ?? l ?? "") ?? H(l ?? "");
63
63
  if (h === null || c === null) continue;
64
64
  const u = s.slice(n + 1).join(`
65
65
  `).trim();
@@ -67,14 +67,14 @@ function X(r) {
67
67
  }
68
68
  return t;
69
69
  }
70
- function st(r, t) {
70
+ function nt(r, t) {
71
71
  try {
72
72
  return new URL(r, new URL(t, window.location.href)).toString();
73
73
  } catch {
74
74
  return r;
75
75
  }
76
76
  }
77
- class nt {
77
+ class rt {
78
78
  constructor() {
79
79
  this.listeners = /* @__PURE__ */ new Map();
80
80
  }
@@ -106,7 +106,7 @@ class nt {
106
106
  this.listeners.clear();
107
107
  }
108
108
  }
109
- const g = (r, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${r}</svg>`, rt = {
109
+ const g = (r, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${r}</svg>`, ot = {
110
110
  play: g('<path d="M8 5.14v13.72c0 .8.87 1.3 1.56.88l10.54-6.86a1.05 1.05 0 0 0 0-1.76L9.56 4.26C8.87 3.84 8 4.34 8 5.14Z"/>'),
111
111
  pause: g('<rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/>'),
112
112
  replay: g('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
@@ -141,79 +141,79 @@ const g = (r, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-
141
141
  user: g('<path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm0 2c-3.6 0-8 1.8-8 4.4V21h16v-2.6c0-2.6-4.4-4.4-8-4.4Z"/>'),
142
142
  // Generic "channel" glyph (play badge) for preview meta when a channel is set.
143
143
  channel: g('<path d="M3 5h18a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm7 3.5v7l6-3.5-6-3.5Z"/>')
144
- }, F = { en: D };
144
+ }, V = { en: G };
145
145
  function qt(r, t) {
146
- F[r] = t;
146
+ V[r] = t;
147
147
  }
148
- function Ft(r) {
148
+ function Vt(r) {
149
149
  for (const [t, e] of Object.entries(r))
150
- e && (F[t] = e);
150
+ e && (V[t] = e);
151
151
  }
152
- function ot(r) {
153
- return r && F[r] || D;
152
+ function at(r) {
153
+ return r && V[r] || G;
154
154
  }
155
- function Vt() {
156
- return Object.keys(F);
155
+ function Ot() {
156
+ return Object.keys(V);
157
157
  }
158
158
  function lt(r) {
159
159
  const t = [0.06, 0.24, 0.4, 0.24, 0.06], e = r.length;
160
160
  return r.map(
161
- (i, s) => t.reduce((n, l, o) => {
162
- const h = Math.min(e - 1, Math.max(0, s + o - 2));
163
- return n + l * r[h];
161
+ (i, s) => t.reduce((n, o, l) => {
162
+ const h = Math.min(e - 1, Math.max(0, s + l - 2));
163
+ return n + o * r[h];
164
164
  }, 0)
165
165
  );
166
166
  }
167
- function at(r, t) {
167
+ function ht(r, t) {
168
168
  if (r.length === 0) return 0;
169
169
  const e = Math.min(r.length - 1, Math.max(0, Math.round((r.length - 1) * t)));
170
170
  return r[e];
171
171
  }
172
- function J(r, t) {
172
+ function Y(r, t) {
173
173
  if (r.length === 0 || r.every((n) => n <= 0)) return [];
174
- const e = lt(r), i = t === "retention" ? at([...e].sort((n, l) => n - l), 0.95) : Math.max(...e);
174
+ const e = lt(r), i = t === "retention" ? ht([...e].sort((n, o) => n - o), 0.95) : Math.max(...e);
175
175
  if (i <= 0) return [];
176
176
  const s = 0.08;
177
177
  return e.map((n) => s + (1 - s) * Math.min(1, Math.max(0, n / i)));
178
178
  }
179
- function ht(r, t, e = 100) {
179
+ function ct(r, t, e = 100) {
180
180
  if (r.length === 0 || !Number.isFinite(t) || t <= 0) return [];
181
181
  const i = new Array(e).fill(0);
182
182
  let s = !1;
183
183
  for (const n of r) {
184
184
  if (!Number.isFinite(n.time) || n.time < 0 || n.time > t) continue;
185
- const l = Math.max(0, n.value);
186
- l !== 0 && (i[Math.min(e - 1, Math.floor(n.time / t * e))] += l, s = !0);
185
+ const o = Math.max(0, n.value);
186
+ o !== 0 && (i[Math.min(e - 1, Math.floor(n.time / t * e))] += o, s = !0);
187
187
  }
188
- return s ? J(i, "peaks") : [];
188
+ return s ? Y(i, "peaks") : [];
189
189
  }
190
- function ct(r, t = "peaks", e = 200) {
190
+ function dt(r, t = "peaks", e = 200) {
191
191
  let i = r.map((s) => Number.isFinite(s) ? Math.max(0, s) : 0);
192
192
  if (i.length > e) {
193
193
  const s = new Array(e).fill(0), n = new Array(e).fill(0);
194
- for (let l = 0; l < i.length; l++) {
195
- const o = Math.min(e - 1, Math.floor(l / i.length * e));
196
- s[o] += i[l], n[o]++;
194
+ for (let o = 0; o < i.length; o++) {
195
+ const l = Math.min(e - 1, Math.floor(o / i.length * e));
196
+ s[l] += i[o], n[l]++;
197
197
  }
198
- i = s.map((l, o) => n[o] > 0 ? l / n[o] : 0);
198
+ i = s.map((o, l) => n[l] > 0 ? o / n[l] : 0);
199
199
  }
200
- return J(i, t);
200
+ return Y(i, t);
201
201
  }
202
- function dt(r, t = 1, e = 1e3, i = 100) {
202
+ function ut(r, t = 1, e = 1e3, i = 100) {
203
203
  const s = r.length;
204
204
  if (s === 0) return "";
205
- const n = e / (s - 1 || 1), l = Math.max(0, t) / 6, o = (u) => {
206
- const v = Math.min(s - 1, Math.max(0, u));
207
- return [v * n, i - r[v] * i];
208
- }, [, h] = o(0);
205
+ const n = e / (s - 1 || 1), o = Math.max(0, t) / 6, l = (u) => {
206
+ const f = Math.min(s - 1, Math.max(0, u));
207
+ return [f * n, i - r[f] * i];
208
+ }, [, h] = l(0);
209
209
  let c = `M 0 ${i} L 0 ${h.toFixed(1)}`;
210
210
  for (let u = 0; u < s - 1; u++) {
211
- const [v, p] = o(u - 1), [m, f] = o(u), [y, d] = o(u + 1), [k, C] = o(u + 2), A = m + (y - v) * l, V = Math.min(i, Math.max(0, f + (d - p) * l)), P = y - (k - m) * l, R = Math.min(i, Math.max(0, d - (C - f) * l));
212
- c += ` C ${A.toFixed(1)} ${V.toFixed(1)} ${P.toFixed(1)} ${R.toFixed(1)} ${y.toFixed(1)} ${d.toFixed(1)}`;
211
+ const [f, p] = l(u - 1), [m, v] = l(u), [y, d] = l(u + 1), [k, C] = l(u + 2), A = m + (y - f) * o, O = Math.min(i, Math.max(0, v + (d - p) * o)), P = y - (k - m) * o, R = Math.min(i, Math.max(0, d - (C - v) * o));
212
+ c += ` C ${A.toFixed(1)} ${O.toFixed(1)} ${P.toFixed(1)} ${R.toFixed(1)} ${y.toFixed(1)} ${d.toFixed(1)}`;
213
213
  }
214
214
  return c += ` L ${e} ${i} Z`, c;
215
215
  }
216
- async function ut(r, t) {
216
+ async function pt(r, t) {
217
217
  if (r.src)
218
218
  return {
219
219
  roll: r.roll,
@@ -223,82 +223,82 @@ async function ut(r, t) {
223
223
  tracking: {}
224
224
  };
225
225
  if (!r.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
226
- return Y(r, r.vastTag, t, 0, { impressions: [], tracking: {} });
226
+ return tt(r, r.vastTag, t, 0, { impressions: [], tracking: {} });
227
227
  }
228
- async function Y(r, t, e, i, s) {
228
+ async function tt(r, t, e, i, s) {
229
229
  if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
230
- const n = new AbortController(), l = setTimeout(() => n.abort(), e.requestTimeout);
231
- let o;
230
+ const n = new AbortController(), o = setTimeout(() => n.abort(), e.requestTimeout);
231
+ let l;
232
232
  try {
233
- const f = await fetch(t, { signal: n.signal, credentials: "omit" });
234
- if (!f.ok) throw new Error(`VAST request failed (${f.status})`);
235
- o = await f.text();
233
+ const v = await fetch(t, { signal: n.signal, credentials: "omit" });
234
+ if (!v.ok) throw new Error(`VAST request failed (${v.status})`);
235
+ l = await v.text();
236
236
  } finally {
237
- clearTimeout(l);
237
+ clearTimeout(o);
238
238
  }
239
- const h = new DOMParser().parseFromString(o, "text/xml");
239
+ const h = new DOMParser().parseFromString(l, "text/xml");
240
240
  if (h.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
241
241
  const c = h.querySelector("VAST > Ad");
242
242
  if (!c) throw new Error("VAST response contains no ads");
243
- pt(c, s);
243
+ mt(c, s);
244
244
  const u = c.querySelector(":scope > Wrapper");
245
245
  if (u) {
246
- const f = L(u.querySelector("VASTAdTagURI"));
247
- if (!f) throw new Error("VAST wrapper without VASTAdTagURI");
248
- return Y(r, f, e, i + 1, s);
246
+ const v = S(u.querySelector("VASTAdTagURI"));
247
+ if (!v) throw new Error("VAST wrapper without VASTAdTagURI");
248
+ return tt(r, v, e, i + 1, s);
249
249
  }
250
- const v = c.querySelector(":scope > InLine");
251
- if (!v) throw new Error("VAST ad has neither InLine nor Wrapper");
252
- const p = v.querySelector("Creatives > Creative > Linear");
250
+ const f = c.querySelector(":scope > InLine");
251
+ if (!f) throw new Error("VAST ad has neither InLine nor Wrapper");
252
+ const p = f.querySelector("Creatives > Creative > Linear");
253
253
  if (!p) throw new Error("VAST ad has no Linear creative");
254
- const m = mt(p);
254
+ const m = ft(p);
255
255
  if (!m) throw new Error("VAST ad has no playable MediaFile");
256
256
  return {
257
257
  roll: r.roll,
258
258
  mediaUrl: m.url,
259
259
  mediaType: m.type,
260
- clickThrough: L(p.querySelector("VideoClicks > ClickThrough")) ?? r.clickUrl,
261
- duration: Z(L(p.querySelector(":scope > Duration"))),
260
+ clickThrough: S(p.querySelector("VideoClicks > ClickThrough")) ?? r.clickUrl,
261
+ duration: D(S(p.querySelector(":scope > Duration"))),
262
262
  skipOffset: vt(
263
263
  p.getAttribute("skipoffset"),
264
- Z(L(p.querySelector(":scope > Duration")))
264
+ D(S(p.querySelector(":scope > Duration")))
265
265
  ),
266
266
  impressions: s.impressions,
267
267
  tracking: s.tracking,
268
- adTitle: L(v.querySelector(":scope > AdTitle")) ?? void 0
268
+ adTitle: S(f.querySelector(":scope > AdTitle")) ?? void 0
269
269
  };
270
270
  }
271
- function pt(r, t) {
271
+ function mt(r, t) {
272
272
  var e, i;
273
273
  for (const s of r.querySelectorAll("Impression")) {
274
- const n = L(s);
274
+ const n = S(s);
275
275
  n && t.impressions.push(n);
276
276
  }
277
277
  for (const s of r.querySelectorAll("Linear > TrackingEvents > Tracking")) {
278
- const n = s.getAttribute("event"), l = L(s);
279
- !n || !l || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(l);
278
+ const n = s.getAttribute("event"), o = S(s);
279
+ !n || !o || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(o);
280
280
  }
281
281
  for (const s of r.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
282
- const n = L(s);
282
+ const n = S(s);
283
283
  n && ((i = t.tracking).click ?? (i.click = [])).push(n);
284
284
  }
285
285
  }
286
- function mt(r) {
287
- const e = [...r.querySelectorAll("MediaFiles > MediaFile")].map((l) => ({
288
- url: L(l) ?? "",
289
- type: l.getAttribute("type") ?? void 0,
290
- delivery: l.getAttribute("delivery") ?? "",
291
- bitrate: Number(l.getAttribute("bitrate") ?? 0),
292
- apiFramework: l.getAttribute("apiFramework") ?? ""
293
- })).filter((l) => l.url && l.apiFramework.toUpperCase() !== "VPAID").filter(
294
- (l) => !l.type || /(video\/(mp4|webm|ogg)|application\/(x-mpegurl|vnd\.apple\.mpegurl))/i.test(l.type)
286
+ function ft(r) {
287
+ const e = [...r.querySelectorAll("MediaFiles > MediaFile")].map((o) => ({
288
+ url: S(o) ?? "",
289
+ type: o.getAttribute("type") ?? void 0,
290
+ delivery: o.getAttribute("delivery") ?? "",
291
+ bitrate: Number(o.getAttribute("bitrate") ?? 0),
292
+ apiFramework: o.getAttribute("apiFramework") ?? ""
293
+ })).filter((o) => o.url && o.apiFramework.toUpperCase() !== "VPAID").filter(
294
+ (o) => !o.type || /(video\/(mp4|webm|ogg)|application\/(x-mpegurl|vnd\.apple\.mpegurl))/i.test(o.type)
295
295
  );
296
296
  if (e.length === 0) return null;
297
- e.sort((l, o) => l.bitrate - o.bitrate);
298
- const i = e.filter((l) => l.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
297
+ e.sort((o, l) => o.bitrate - l.bitrate);
298
+ const i = e.filter((o) => o.delivery !== "streaming"), s = i.length > 0 ? i : e, n = s[Math.floor(s.length / 2)];
299
299
  return { url: n.url, type: n.type };
300
300
  }
301
- function Z(r) {
301
+ function D(r) {
302
302
  if (!r) return;
303
303
  const t = r.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
304
304
  if (t)
@@ -307,9 +307,9 @@ function Z(r) {
307
307
  function vt(r, t) {
308
308
  if (!r) return;
309
309
  const e = r.trim().match(/^(\d+(?:\.\d+)?)%$/);
310
- return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : Z(r);
310
+ return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : D(r);
311
311
  }
312
- function $(r) {
312
+ function F(r) {
313
313
  if (r)
314
314
  for (const t of r)
315
315
  try {
@@ -317,10 +317,10 @@ function $(r) {
317
317
  } catch {
318
318
  }
319
319
  }
320
- function L(r) {
320
+ function S(r) {
321
321
  return r?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
322
322
  }
323
- class ft {
323
+ class gt {
324
324
  constructor(t, e) {
325
325
  this.host = t, this.playedRolls = /* @__PURE__ */ new Set(), this.sourcesSeen = 0, this.activeBreak = null, this.layer = null, this.adVideo = null, this.destroyed = !1, this.opts = {
326
326
  skipDelay: 5,
@@ -387,11 +387,11 @@ class ft {
387
387
  for (const n of t) {
388
388
  this.playedRolls.add(n);
389
389
  try {
390
- const l = await ut(n, this.opts);
391
- await this.playAd(l);
392
- } catch (l) {
393
- const o = l instanceof Error ? l : new Error(String(l));
394
- this.host.emitter.emit("aderror", { roll: n, error: o });
390
+ const o = await pt(n, this.opts);
391
+ await this.playAd(o);
392
+ } catch (o) {
393
+ const l = o instanceof Error ? o : new Error(String(o));
394
+ this.host.emitter.emit("aderror", { roll: n, error: l });
395
395
  }
396
396
  if (this.destroyed) return;
397
397
  }
@@ -404,22 +404,22 @@ class ft {
404
404
  }
405
405
  playAd(t) {
406
406
  return new Promise((e) => {
407
- const { labels: i } = this.host, s = a("div", "imp-ad"), n = this.ensureAdVideo(), l = new AbortController(), o = l.signal;
407
+ const { labels: i } = this.host, s = a("div", "imp-ad"), n = this.ensureAdVideo(), o = new AbortController(), l = o.signal;
408
408
  n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
409
409
  const h = a("div", "imp-spinner imp-ad__spinner"), c = a("div", "imp-ad__hud"), u = a("span", "imp-ad__badge");
410
410
  u.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
411
- const v = a("span", "imp-ad__countdown");
412
- c.append(u, v);
411
+ const f = a("span", "imp-ad__countdown");
412
+ c.append(u, f);
413
413
  const p = a("div", "imp-ad__actions");
414
414
  let m = null;
415
415
  t.clickThrough && (m = a("button", "imp-ad__visit", { type: "button" }), m.textContent = i.visitAdvertiser, p.append(m));
416
- const f = a("button", "imp-ad__skip", { type: "button" });
417
- f.hidden = !0, p.append(f), s.append(n, h, c, p), this.host.container.append(s), this.layer = s;
416
+ const v = a("button", "imp-ad__skip", { type: "button" });
417
+ v.hidden = !0, p.append(v), s.append(n, h, c, p), this.host.container.append(s), this.layer = s;
418
418
  const y = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), k = (w) => {
419
- d.has(w) || (d.add(w), $(t.tracking[w]));
419
+ d.has(w) || (d.add(w), F(t.tracking[w]));
420
420
  };
421
421
  let C = Date.now(), A = -1;
422
- const V = setInterval(() => {
422
+ const O = setInterval(() => {
423
423
  if (n.paused) {
424
424
  C = Date.now();
425
425
  return;
@@ -433,40 +433,40 @@ class ft {
433
433
  error: new Error(`Ad media stalled for ${this.opts.mediaTimeout} ms — skipping`)
434
434
  }), P());
435
435
  }, 500), P = () => {
436
- clearInterval(V), l.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
436
+ clearInterval(O), o.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
437
437
  }, R = (w) => {
438
438
  w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }), P();
439
439
  };
440
440
  n.addEventListener("playing", () => {
441
- $(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
442
- }, { once: !0, signal: o }), n.addEventListener("playing", () => {
441
+ F(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
442
+ }, { once: !0, signal: l }), n.addEventListener("playing", () => {
443
443
  h.hidden = !0;
444
- }, { signal: o }), n.addEventListener("waiting", () => {
444
+ }, { signal: l }), n.addEventListener("waiting", () => {
445
445
  h.hidden = !1;
446
- }, { signal: o }), n.addEventListener("timeupdate", () => {
446
+ }, { signal: l }), n.addEventListener("timeupdate", () => {
447
447
  const w = n.currentTime, B = n.duration;
448
- if (Number.isFinite(B) && B > 0 && (v.textContent = _(Math.max(0, B - w)), w / B >= 0.25 && k("firstQuartile"), w / B >= 0.5 && k("midpoint"), w / B >= 0.75 && k("thirdQuartile")), y >= 0) {
449
- const Q = Math.ceil(y - w);
450
- Q > 0 ? (f.hidden = !1, f.disabled = !0, f.textContent = `${i.skipAdIn} ${Q}`) : (f.hidden = !1, f.disabled = !1, f.textContent = i.skipAd);
448
+ if (Number.isFinite(B) && B > 0 && (f.textContent = _(Math.max(0, B - w)), w / B >= 0.25 && k("firstQuartile"), w / B >= 0.5 && k("midpoint"), w / B >= 0.75 && k("thirdQuartile")), y >= 0) {
449
+ const U = Math.ceil(y - w);
450
+ U > 0 ? (v.hidden = !1, v.disabled = !0, v.textContent = `${i.skipAdIn} ${U}`) : (v.hidden = !1, v.disabled = !1, v.textContent = i.skipAd);
451
451
  }
452
- }, { signal: o }), n.addEventListener("ended", () => R(!1), { signal: o }), n.addEventListener("error", () => {
452
+ }, { signal: l }), n.addEventListener("ended", () => R(!1), { signal: l }), n.addEventListener("error", () => {
453
453
  this.host.emitter.emit("aderror", {
454
454
  roll: { roll: t.roll },
455
455
  error: new Error("Ad media failed to play")
456
456
  }), P();
457
- }, { signal: o }), f.addEventListener("click", () => R(!0));
458
- const W = () => {
457
+ }, { signal: l }), v.addEventListener("click", () => R(!0));
458
+ const z = () => {
459
459
  t.clickThrough && (k("click"), this.host.emitter.emit("adclick", { ad: t }), window.open(t.clickThrough, "_blank", "noopener"), n.pause());
460
460
  };
461
- n.addEventListener("click", W, { signal: o }), m?.addEventListener("click", W);
462
- let z = !1, N = !1;
461
+ n.addEventListener("click", z, { signal: l }), m?.addEventListener("click", z);
462
+ let Q = !1, N = !1;
463
463
  n.addEventListener("playing", () => {
464
- z = !0;
465
- }, { once: !0, signal: o }), n.addEventListener("pause", () => {
466
- n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), z && !N && (N = !0, $(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
467
- }, { signal: o }), n.addEventListener("play", () => {
468
- s.classList.remove("imp-ad--paused"), N && (N = !1, $(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
469
- }, { signal: o }), s.addEventListener("click", (w) => {
464
+ Q = !0;
465
+ }, { once: !0, signal: l }), n.addEventListener("pause", () => {
466
+ n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), Q && !N && (N = !0, F(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
467
+ }, { signal: l }), n.addEventListener("play", () => {
468
+ s.classList.remove("imp-ad--paused"), N && (N = !1, F(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
469
+ }, { signal: l }), s.addEventListener("click", (w) => {
470
470
  (w.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
471
471
  });
472
472
  }), n.play().catch(() => {
@@ -482,32 +482,32 @@ class ft {
482
482
  this.destroyed = !0, this.adVideo?.pause(), this.layer?.remove(), this.layer = null, this.adVideo = null;
483
483
  }
484
484
  }
485
- function U(r, t) {
485
+ function j(r, t) {
486
486
  const e = [...r].sort((s, n) => s.start - n.start), i = [];
487
487
  for (let s = 0; s < e.length; s++) {
488
488
  const n = Math.max(0, e[s].start);
489
489
  if (Number.isFinite(t) && n >= t) continue;
490
- let l = e[s].end ?? e[s + 1]?.start ?? t;
491
- Number.isFinite(t) && (l = Math.min(l, t)), !(l <= n) && i.push({ start: n, end: l, title: e[s].title });
490
+ let o = e[s].end ?? e[s + 1]?.start ?? t;
491
+ Number.isFinite(t) && (o = Math.min(o, t)), !(!Number.isFinite(o) || o <= n) && i.push({ start: n, end: o, title: e[s].title });
492
492
  }
493
493
  return i;
494
494
  }
495
- async function gt(r) {
495
+ async function yt(r) {
496
496
  const t = await fetch(r);
497
497
  if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
498
498
  const e = await t.text();
499
- return X(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
499
+ return J(e).map((i) => ({ start: i.start, end: i.end, title: i.text }));
500
500
  }
501
- function tt(r, t) {
501
+ function et(r, t) {
502
502
  for (const e of r)
503
503
  if (t >= e.start && t < e.end) return e;
504
504
  return null;
505
505
  }
506
- function yt(r, t) {
506
+ function bt(r, t) {
507
507
  return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(r);
508
508
  }
509
509
  let E;
510
- async function bt() {
510
+ async function kt() {
511
511
  if (E !== void 0) return E;
512
512
  const r = globalThis.Hls;
513
513
  if (r)
@@ -518,14 +518,14 @@ async function bt() {
518
518
  return null;
519
519
  }
520
520
  }
521
- async function kt(r, t, e, i) {
522
- if (yt(t, e)) {
523
- const s = r.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await bt();
524
- return n && n.isSupported() ? wt(n, r, t, i) : s ? (r.src = t, H(r)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), H(r));
521
+ async function wt(r, t, e, i) {
522
+ if (bt(t, e)) {
523
+ const s = r.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await kt();
524
+ return n && n.isSupported() ? xt(n, r, t, i) : s ? (r.src = t, Z(r)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), Z(r));
525
525
  }
526
- return r.src = t, H(r);
526
+ return r.src = t, Z(r);
527
527
  }
528
- function H(r) {
528
+ function Z(r) {
529
529
  return {
530
530
  kind: "native",
531
531
  levels: [],
@@ -537,7 +537,7 @@ function H(r) {
537
537
  }
538
538
  };
539
539
  }
540
- function wt(r, t, e, i) {
540
+ function xt(r, t, e, i) {
541
541
  const s = new r({ enableWorker: !0 }), n = {
542
542
  kind: "hls",
543
543
  levels: [],
@@ -555,20 +555,20 @@ function wt(r, t, e, i) {
555
555
  label: c.height ? `${c.height}p` : `${Math.round(c.bitrate / 1e3)} kbps`
556
556
  })).reverse(), i.onLevels(n.levels);
557
557
  }), s.on(r.Events.LEVEL_SWITCHED, (c, u) => {
558
- const v = s.levels[u.level];
559
- v && i.onLevelSwitch(v.height ? `${v.height}p` : `${Math.round(v.bitrate / 1e3)} kbps`);
558
+ const f = s.levels[u.level];
559
+ f && i.onLevelSwitch(f.height ? `${f.height}p` : `${Math.round(f.bitrate / 1e3)} kbps`);
560
560
  });
561
- let l = 0, o = 0, h = !1;
561
+ let o = 0, l = 0, h = !1;
562
562
  return s.on(r.Events.FRAG_BUFFERED, () => {
563
- o = 0;
563
+ l = 0;
564
564
  }), s.on(r.Events.ERROR, (c, u) => {
565
565
  if (u.fatal)
566
566
  switch (u.type) {
567
567
  case r.ErrorTypes.NETWORK_ERROR:
568
- o < 3 ? (o++, s.startLoad()) : (i.onError(`HLS network error: ${u.details}`, u), s.destroy());
568
+ l < 3 ? (l++, s.startLoad()) : (i.onError(`HLS network error: ${u.details}`, u), s.destroy());
569
569
  break;
570
570
  case r.ErrorTypes.MEDIA_ERROR:
571
- l < 3 ? (l++, s.recoverMediaError()) : (i.onError(`HLS media error: ${u.details}`, u), s.destroy());
571
+ o < 3 ? (o++, s.recoverMediaError()) : (i.onError(`HLS media error: ${u.details}`, u), s.destroy());
572
572
  break;
573
573
  default:
574
574
  if (h)
@@ -584,7 +584,7 @@ function wt(r, t, e, i) {
584
584
  }
585
585
  }), s.loadSource(e), s.attachMedia(t), n;
586
586
  }
587
- class G {
587
+ class W {
588
588
  constructor(t) {
589
589
  this.cues = t;
590
590
  }
@@ -592,17 +592,17 @@ class G {
592
592
  const e = await fetch(t);
593
593
  if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
594
594
  const i = await e.text(), s = [];
595
- for (const n of X(i)) {
596
- const [l, o] = n.text.trim().split("#");
597
- if (!l) continue;
595
+ for (const n of J(i)) {
596
+ const [o, l] = n.text.trim().split("#");
597
+ if (!o) continue;
598
598
  const h = {
599
599
  start: n.start,
600
600
  end: n.end,
601
- src: st(l, t)
602
- }, c = o?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
601
+ src: nt(o, t)
602
+ }, c = l?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
603
603
  c && (h.xywh = { x: Number(c[1]), y: Number(c[2]), w: Number(c[3]), h: Number(c[4]) }), s.push(h);
604
604
  }
605
- return s.sort((n, l) => n.start - l.start), new G(s);
605
+ return s.sort((n, o) => n.start - o.start), new W(s);
606
606
  }
607
607
  cueAt(t) {
608
608
  let e = 0, i = this.cues.length - 1;
@@ -615,7 +615,7 @@ class G {
615
615
  return null;
616
616
  }
617
617
  }
618
- const xt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg>', _t = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg>';
618
+ const _t = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg>', St = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg>';
619
619
  class M {
620
620
  constructor(t) {
621
621
  this.anchor = t, this.outsideListener = null, this.escListener = null, this.root = a("div", "imp-menu"), this.root.hidden = !0, this.backdrop = a("div", "imp-menu__backdrop"), this.backdrop.hidden = !0, this.backdrop.addEventListener("pointerdown", (e) => {
@@ -651,10 +651,10 @@ class M {
651
651
  }
652
652
  const s = a("button", "imp-menu__item imp-menu__row", { type: "button" }), n = a("span", "imp-menu__label");
653
653
  n.textContent = i.label;
654
- const l = a("span", "imp-menu__value");
655
- l.textContent = i.value ?? "";
656
- const o = a("span", "imp-menu__chevron");
657
- o.innerHTML = xt, s.append(n, l, o), s.addEventListener("click", () => this.renderSettingsDetail(t, i)), e.append(s);
654
+ const o = a("span", "imp-menu__value");
655
+ o.textContent = i.value ?? "";
656
+ const l = a("span", "imp-menu__chevron");
657
+ l.innerHTML = _t, s.append(n, o, l), s.addEventListener("click", () => this.renderSettingsDetail(t, i)), e.append(s);
658
658
  }
659
659
  this.root.append(e);
660
660
  }
@@ -668,15 +668,15 @@ class M {
668
668
  s.textContent = t.label;
669
669
  const n = a("span", "imp-switch");
670
670
  return n.append(a("span", "imp-switch__knob")), i.classList.toggle("imp-menu__toggle--on", e.value), i.append(s, n), i.addEventListener("click", () => {
671
- const l = i.getAttribute("aria-checked") !== "true";
672
- i.setAttribute("aria-checked", String(l)), i.classList.toggle("imp-menu__toggle--on", l), e.onChange(l);
671
+ const o = i.getAttribute("aria-checked") !== "true";
672
+ i.setAttribute("aria-checked", String(o)), i.classList.toggle("imp-menu__toggle--on", o), e.onChange(o);
673
673
  }), i;
674
674
  }
675
675
  renderSettingsDetail(t, e) {
676
676
  if (!e.section) return;
677
677
  this.root.textContent = "";
678
678
  const i = a("button", "imp-menu__item imp-menu__back", { type: "button" }), s = a("span", "imp-menu__chevron");
679
- s.innerHTML = _t;
679
+ s.innerHTML = St;
680
680
  const n = a("span", "imp-menu__label");
681
681
  n.textContent = e.label, i.append(s, n), i.addEventListener("click", () => this.renderSettingsRoot(t)), this.root.append(i), this.root.append(this.renderSection(e.section())), this.root.scrollTop = 0;
682
682
  }
@@ -690,8 +690,8 @@ class M {
690
690
  for (const i of t.items) {
691
691
  const s = a("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
692
692
  if (s.setAttribute("aria-checked", String(i.active)), i.active && s.classList.add("imp-menu__item--active"), i.icon) {
693
- const l = a("span", "imp-menu__icon");
694
- S(l, i.icon), s.append(l);
693
+ const o = a("span", "imp-menu__icon");
694
+ L(o, i.icon), s.append(o);
695
695
  }
696
696
  const n = a("span", "imp-menu__label");
697
697
  n.textContent = i.label, s.append(n), s.addEventListener("click", () => {
@@ -729,7 +729,7 @@ class Lt {
729
729
  this.heatmap.hidden = !0, this.heatmap.textContent = "";
730
730
  return;
731
731
  }
732
- this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${dt(t, e)}"/></svg>`, this.heatmap.hidden = !1;
732
+ this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${ut(t, e)}"/></svg>`, this.heatmap.hidden = !1;
733
733
  }
734
734
  setDuration(t) {
735
735
  this.duration = Number.isFinite(t) ? t : 0, this.root.classList.toggle("imp-progress--live", !Number.isFinite(t)), this.chapters.length === 0 && this.setChapters([]);
@@ -742,10 +742,10 @@ class Lt {
742
742
  n.start > s && i.push({ start: s, end: n.start, title: "" }), i.push(n), s = n.end;
743
743
  this.duration > 0 && s < this.duration && i.push({ start: s, end: this.duration, title: "" });
744
744
  for (const n of i) {
745
- const l = a("div", "imp-progress__segment");
746
- l.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
747
- const o = a("div", "imp-progress__fill");
748
- l.append(o), this.track.append(l), this.segments.push({ chapter: n, root: l, fill: o });
745
+ const o = a("div", "imp-progress__segment");
746
+ o.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
747
+ const l = a("div", "imp-progress__fill");
748
+ o.append(l), this.track.append(o), this.segments.push({ chapter: n, root: o, fill: l });
749
749
  }
750
750
  }
751
751
  setThumbnails(t) {
@@ -759,8 +759,8 @@ class Lt {
759
759
  }
760
760
  render(t) {
761
761
  for (const { chapter: i, fill: s } of this.segments) {
762
- const n = i.end - i.start, l = n > 0 ? x((t - i.start) / n, 0, 1) : 0;
763
- s.style.transform = `scaleX(${l})`;
762
+ const n = i.end - i.start, o = n > 0 ? x((t - i.start) / n, 0, 1) : 0;
763
+ s.style.transform = `scaleX(${o})`;
764
764
  }
765
765
  const e = this.duration > 0 ? x(t / this.duration, 0, 1) : 0;
766
766
  this.handle.style.left = `${e * 100}%`;
@@ -783,18 +783,18 @@ class Lt {
783
783
  showTooltip(t) {
784
784
  const e = this.timeFromEvent(t);
785
785
  this.tooltipTime.textContent = _(e);
786
- const i = tt(this.chapters, e), s = !!i?.title;
786
+ const i = et(this.chapters, e), s = !!i?.title;
787
787
  this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !s, this.tooltipCaption.classList.toggle("imp-progress__caption--time-only", !s);
788
788
  const n = this.thumbnails?.cueAt(e) ?? null;
789
789
  this.tooltip.classList.toggle("imp-progress__tooltip--thumb", !!n), n ? (this.tooltipThumb.hidden = !1, this.tooltipThumb.style.backgroundImage = `url("${n.src}")`, n.xywh ? (this.tooltipThumb.style.width = `${n.xywh.w}px`, this.tooltipThumb.style.height = `${n.xywh.h}px`, this.tooltipThumb.style.backgroundPosition = `-${n.xywh.x}px -${n.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");
790
- const l = this.root.getBoundingClientRect(), o = x(t.clientX - l.left, 0, l.width), h = this.tooltip.offsetWidth / 2;
791
- this.tooltip.style.left = `${x(o, h, Math.max(h, l.width - h))}px`;
790
+ const o = this.root.getBoundingClientRect(), l = x(t.clientX - o.left, 0, o.width), h = this.tooltip.offsetWidth / 2;
791
+ this.tooltip.style.left = `${x(l, h, Math.max(h, o.width - h))}px`;
792
792
  }
793
793
  hideTooltip() {
794
794
  this.tooltip.classList.remove("imp-progress__tooltip--visible");
795
795
  }
796
796
  }
797
- class St {
797
+ class Tt {
798
798
  constructor(t) {
799
799
  this.player = t, this.rightItems = /* @__PURE__ */ new Map(), 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.gearBtn = null, this.gearMenu = null, this.gear = { speed: !1, quality: !1, subtitles: !1 }, this.nextPreviewEl = null, this.nextPreviewOpts = null, this.scenesBtn = null, this.sceneTypeBtn = null, this.sceneTypeMenu = 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;
800
800
  const { labels: e, icons: i } = t, s = t.controlsOptions;
@@ -804,17 +804,17 @@ class St {
804
804
  t.scrubbing = !0, this.wasPlayingBeforeScrub = !t.paused, t.pause();
805
805
  },
806
806
  onScrubEnd: () => {
807
- t.scrubbing = !1, this.wasPlayingBeforeScrub && t.play(!0);
807
+ t.scrubbing = !1, this.wasPlayingBeforeScrub ? t.play(!0) : t.started || t.play();
808
808
  }
809
809
  }, t.labels.seek), s.progress && this.root.append(this.progress.root);
810
810
  const n = a("div", "imp-controls__row");
811
811
  this.row = n, this.root.append(n);
812
- const l = a("div", "imp-controls__group"), o = a("div", "imp-controls__group");
813
- this.rightGroup = o;
812
+ const o = a("div", "imp-controls__group"), l = a("div", "imp-controls__group");
813
+ this.rightGroup = l;
814
814
  const h = a("div", "imp-controls__spacer");
815
- this.chapterLabel = a("div", "imp-controls__chapter"), n.append(l, h, o), h.append(this.chapterLabel);
816
- const c = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = c.back ?? t.seekStep, v = c.forward ?? t.seekStep;
817
- if (this.seekLabelFn = c.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn = b("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), l.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = b("imp-btn--seek-back", `${e.seekBack} ${u}s`, i.seekBack), this.addStepBadge(this.seekBackBtn, u, "back"), this.seekBackBtn.addEventListener("click", () => t.skip(-u)), l.append(this.seekBackBtn)), s.play && (this.playBtn = b("imp-btn--play", e.play, i.play), this.playBtn.addEventListener("click", () => t.togglePlay()), l.append(this.playBtn)), s.seekButtons && (this.seekFwdBtn = b("imp-btn--seek-forward", `${e.seekForward} ${v}s`, i.seekForward), this.addStepBadge(this.seekFwdBtn, v, "forward"), this.seekFwdBtn.addEventListener("click", () => t.skip(v)), l.append(this.seekFwdBtn)), s.playlist && t.hasPlaylist && !s.hideNext && (this.nextBtn = b("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), l.append(this.nextBtn)), s.volume) {
815
+ this.chapterLabel = a("div", "imp-controls__chapter"), n.append(o, h, l), h.append(this.chapterLabel);
816
+ const c = typeof s.seekButtons == "object" ? s.seekButtons : {}, u = c.back ?? t.seekStep, f = c.forward ?? t.seekStep;
817
+ if (this.seekLabelFn = c.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn = b("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), o.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = b("imp-btn--seek-back", `${e.seekBack} ${u}s`, i.seekBack), this.addStepBadge(this.seekBackBtn, u, "back"), this.seekBackBtn.addEventListener("click", () => t.skip(-u)), o.append(this.seekBackBtn)), s.play && (this.playBtn = b("imp-btn--play", e.play, i.play), this.playBtn.addEventListener("click", () => t.togglePlay()), o.append(this.playBtn)), s.seekButtons && (this.seekFwdBtn = b("imp-btn--seek-forward", `${e.seekForward} ${f}s`, i.seekForward), this.addStepBadge(this.seekFwdBtn, f, "forward"), this.seekFwdBtn.addEventListener("click", () => t.skip(f)), o.append(this.seekFwdBtn)), s.playlist && t.hasPlaylist && !s.hideNext && (this.nextBtn = b("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), o.append(this.nextBtn)), s.volume) {
818
818
  const d = a("div", "imp-volume");
819
819
  this.muteBtn = b("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = a("input", "imp-volume__slider", {
820
820
  type: "range",
@@ -824,9 +824,9 @@ class St {
824
824
  "aria-label": e.volume
825
825
  }), this.volumeSlider.addEventListener("input", () => {
826
826
  t.setVolume(Number(this.volumeSlider.value));
827
- }), d.append(this.muteBtn, this.volumeSlider), l.append(d);
827
+ }), d.append(this.muteBtn, this.volumeSlider), o.append(d);
828
828
  }
829
- s.time && (this.timeLabel = a("div", "imp-controls__time"), this.timeCurrent = a("span", "imp-controls__time-current"), this.timeTotal = a("span", "imp-controls__time-total"), this.timeLabel.append(this.timeCurrent, this.timeTotal), this.liveBadge = a("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, l.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike();
829
+ s.time && (this.timeLabel = a("div", "imp-controls__time"), this.timeCurrent = a("span", "imp-controls__time-current"), this.timeTotal = a("span", "imp-controls__time-total"), this.timeLabel.append(this.timeCurrent, this.timeTotal), this.liveBadge = a("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, o.append(this.timeLabel, this.liveBadge)), this.buildLikeDislike();
830
830
  for (const d of (t.actionsOptions.custom ?? []).filter((k) => k.placement === "bar")) {
831
831
  const k = b(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
832
832
  k.addEventListener("click", () => t.emit("customaction", { id: d.id })), this.rightItems.set(`custom:${d.id}`, k), this.registerCollapsible({
@@ -837,8 +837,8 @@ class St {
837
837
  section: () => this.simpleSection(`custom:${d.id}`, d.title, d.icon ?? i.more, () => t.emit("customaction", { id: d.id }))
838
838
  });
839
839
  }
840
- const p = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", m = p(s.subtitles), f = p(s.quality), y = p(s.speed);
841
- if (this.gear = { speed: y === "gear", quality: f === "gear", subtitles: m === "gear" }, m === "bar") {
840
+ const p = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", m = p(s.subtitles), v = p(s.quality), y = p(s.speed);
841
+ if (this.gear = { speed: y === "gear", quality: v === "gear", subtitles: m === "gear" }, m === "bar") {
842
842
  this.subtitlesBtn = b("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new M(this.subtitlesBtn);
843
843
  const d = a("div", "imp-controls__menu-anchor");
844
844
  d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), this.rightItems.set("subtitles", d), this.registerCollapsible({
@@ -849,7 +849,7 @@ class St {
849
849
  section: () => this.subtitlesSection()
850
850
  });
851
851
  }
852
- if (f === "bar") {
852
+ if (v === "bar") {
853
853
  this.qualityBtn = b("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new M(this.qualityBtn);
854
854
  const d = a("div", "imp-controls__menu-anchor");
855
855
  d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), this.rightItems.set("quality", d), this.registerCollapsible({
@@ -883,7 +883,7 @@ class St {
883
883
  d.append(this.sceneTypeBtn, this.sceneTypeMenu.root), this.sceneTypeBtn.addEventListener("click", () => this.toggleSceneTypeMenu()), this.rightItems.set("sceneTypes", d), this.refreshSceneTypeButton(), this.registerCollapsible({
884
884
  key: "sceneTypes",
885
885
  el: d,
886
- priority: 26,
886
+ priority: 68,
887
887
  available: () => t.sceneTypes.length > 0,
888
888
  section: () => this.sceneTypeSection()
889
889
  });
@@ -937,7 +937,7 @@ class St {
937
937
  el: d,
938
938
  priority: 82,
939
939
  available: () => Number.isFinite(t.duration) && t.duration > 0,
940
- section: () => this.simpleSection("seekFwd", `${e.seekForward} ${v}s`, i.seekForward, () => t.skip(v))
940
+ section: () => this.simpleSection("seekFwd", `${e.seekForward} ${f}s`, i.seekForward, () => t.skip(f))
941
941
  });
942
942
  }
943
943
  if (this.center = a("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) {
@@ -945,8 +945,8 @@ class St {
945
945
  this.addStepBadge(d, u, "back"), d.addEventListener("click", () => t.skip(-u)), this.center.append(d);
946
946
  }
947
947
  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) {
948
- const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${v}s`, i.seekForward);
949
- this.addStepBadge(d, v, "forward"), d.addEventListener("click", () => t.skip(v)), this.center.append(d);
948
+ const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${f}s`, i.seekForward);
949
+ this.addStepBadge(d, f, "forward"), d.addEventListener("click", () => t.skip(f)), this.center.append(d);
950
950
  }
951
951
  if (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.setupNextPreview(), this.gear.speed || this.gear.quality || this.gear.subtitles) {
952
952
  this.gearBtn = b("imp-btn--settings", e.settings, i.settings), this.gearMenu = new M(this.gearBtn);
@@ -959,7 +959,7 @@ class St {
959
959
  section: () => this.gearSections()
960
960
  });
961
961
  }
962
- this.layoutRightCluster(o), this.buildMoreDropdown(o), 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);
962
+ this.layoutRightCluster(l), this.buildMoreDropdown(l), 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);
963
963
  }
964
964
  registerCollapsible(t) {
965
965
  this.collapsibles.push(t);
@@ -975,19 +975,19 @@ class St {
975
975
  if (i.length > 0) {
976
976
  const n = /* @__PURE__ */ new Set();
977
977
  s = [];
978
- for (const l of i)
979
- this.rightItems.has(l) && !n.has(l) && (s.push(l), n.add(l));
980
- for (const l of e) n.has(l) || s.push(l);
978
+ for (const o of i)
979
+ this.rightItems.has(o) && !n.has(o) && (s.push(o), n.add(o));
980
+ for (const o of e) n.has(o) || s.push(o);
981
981
  }
982
982
  for (const n of s) {
983
- const l = this.rightItems.get(n);
984
- l && t.append(l);
983
+ const o = this.rightItems.get(n);
984
+ o && t.append(o);
985
985
  }
986
986
  }
987
987
  /** Center-cluster button — deliberately NOT `.imp-btn` (own sizing/look). */
988
988
  makeCenterButton(t, e, i) {
989
989
  const s = a("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
990
- return S(s, i), s;
990
+ return L(s, i), s;
991
991
  }
992
992
  /** Caption under the seek arrow. Default "−15s"/"+15s"; overridable via `controls.seekButtons.label`. */
993
993
  addStepBadge(t, e, i) {
@@ -1030,7 +1030,7 @@ class St {
1030
1030
  if (t.textContent = "", !e) return;
1031
1031
  if (e.icon) {
1032
1032
  const s = a("span", "imp-scene-type__icon");
1033
- S(s, e.icon), t.append(s);
1033
+ L(s, e.icon), t.append(s);
1034
1034
  }
1035
1035
  const i = a("span", "imp-scene-type__label");
1036
1036
  i.textContent = e.title, t.append(i), t.setAttribute("aria-label", `${this.player.labels.sceneTypes}: ${e.title}`), t.title = e.title;
@@ -1086,12 +1086,12 @@ class St {
1086
1086
  e.textContent = "";
1087
1087
  const n = a("div", "imp-next-preview__kicker");
1088
1088
  n.textContent = this.player.labels.next, e.append(n);
1089
- const l = q(s.poster);
1090
- if (i.thumbnail && l) {
1091
- const m = a("div", "imp-next-preview__thumb"), f = T(l);
1092
- if (f.addEventListener("error", () => {
1089
+ const o = q(s.poster);
1090
+ if (i.thumbnail && o) {
1091
+ const m = a("div", "imp-next-preview__thumb"), v = T(o);
1092
+ if (v.addEventListener("error", () => {
1093
1093
  this.player.markSourceDead(s), this.nextPreviewEl && !this.nextPreviewEl.hidden && this.showNextPreview(t);
1094
- }, { once: !0 }), m.append(f), i.duration && s.duration) {
1094
+ }, { once: !0 }), m.append(v), i.duration && s.duration) {
1095
1095
  const y = a("span", "imp-next-preview__duration");
1096
1096
  y.textContent = _(s.duration), m.append(y);
1097
1097
  }
@@ -1101,9 +1101,9 @@ class St {
1101
1101
  const m = a("div", "imp-next-preview__title");
1102
1102
  m.textContent = s.title, e.append(m);
1103
1103
  }
1104
- i.meta && s.previewMeta?.length && e.append(K(s.previewMeta, "imp-next-preview")), e.hidden = !1;
1105
- const o = this.player.container.getBoundingClientRect(), h = t.getBoundingClientRect(), c = 8, u = e.offsetWidth, v = h.left - o.left + h.width / 2 - u / 2, p = Math.max(c, Math.min(v, o.width - u - c));
1106
- e.style.left = `${p}px`, e.style.bottom = `${o.height - (h.top - o.top) + 10}px`;
1104
+ i.meta && s.previewMeta?.length && e.append(X(s.previewMeta, "imp-next-preview")), e.hidden = !1;
1105
+ const l = this.player.container.getBoundingClientRect(), h = t.getBoundingClientRect(), c = 8, u = e.offsetWidth, f = h.left - l.left + h.width / 2 - u / 2, p = Math.max(c, Math.min(f, l.width - u - c));
1106
+ e.style.left = `${p}px`, e.style.bottom = `${l.height - (h.top - l.top) + 10}px`;
1107
1107
  }
1108
1108
  hideNextPreview() {
1109
1109
  this.nextPreviewEl && (this.nextPreviewEl.hidden = !0);
@@ -1158,21 +1158,21 @@ class St {
1158
1158
  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" }) });
1159
1159
  for (const h of (i.custom ?? []).filter((c) => c.placement !== "bar"))
1160
1160
  this.actionItems.push({ value: `custom:${h.id}`, label: h.title, icon: h.icon, run: () => e.emit("customaction", { id: h.id }) });
1161
- const l = b("imp-btn--more", s.more, n.more);
1162
- this.moreMenu = new M(l);
1163
- const o = a("div", "imp-controls__menu-anchor imp-controls__more");
1164
- o.append(l, this.moreMenu.root), l.addEventListener("click", () => {
1161
+ const o = b("imp-btn--more", s.more, n.more);
1162
+ this.moreMenu = new M(o);
1163
+ const l = a("div", "imp-controls__menu-anchor imp-controls__more");
1164
+ l.append(o, this.moreMenu.root), o.addEventListener("click", () => {
1165
1165
  this.closeMenus(this.moreMenu), this.moreMenu?.toggle(this.buildMoreSections());
1166
- }), t.append(o), this.moreWrap = o;
1166
+ }), t.append(l), this.moreWrap = l;
1167
1167
  }
1168
1168
  /** ⋯ menu = overflowed controls (in display order) + consumer actions. */
1169
1169
  buildMoreSections() {
1170
- const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (o) => {
1171
- const h = s.indexOf(o);
1170
+ const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (l) => {
1171
+ const h = s.indexOf(l);
1172
1172
  return h === -1 ? s.length : h;
1173
- }, l = this.collapsibles.filter((o) => this.overflowed.has(o.key) && o.available()).sort((o, h) => n(o.key) - n(h.key));
1174
- for (const o of l) {
1175
- const h = o.section();
1173
+ }, o = this.collapsibles.filter((l) => this.overflowed.has(l.key) && l.available()).sort((l, h) => n(l.key) - n(h.key));
1174
+ for (const l of o) {
1175
+ const h = l.section();
1176
1176
  if (h)
1177
1177
  for (const c of Array.isArray(h) ? h : [h])
1178
1178
  if (!c.title && c.items.length === 1) {
@@ -1181,12 +1181,12 @@ class St {
1181
1181
  } else
1182
1182
  t.push(c);
1183
1183
  }
1184
- if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (o) => e.get(o)?.() }), this.actionItems.length > 0) {
1185
- const o = new Map(this.actionItems.map((h) => [h.value, h.run]));
1184
+ if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (l) => e.get(l)?.() }), this.actionItems.length > 0) {
1185
+ const l = new Map(this.actionItems.map((h) => [h.value, h.run]));
1186
1186
  t.push({
1187
1187
  title: "",
1188
1188
  items: this.actionItems.map(({ value: h, label: c, icon: u }) => ({ value: h, label: c, icon: u, active: !1 })),
1189
- onSelect: (h) => o.get(h)?.()
1189
+ onSelect: (h) => l.get(h)?.()
1190
1190
  });
1191
1191
  }
1192
1192
  return t;
@@ -1239,28 +1239,28 @@ class St {
1239
1239
  * the ⋯ menu can offer them. Unavailable controls are hidden outright.
1240
1240
  */
1241
1241
  reflow() {
1242
- const t = window.innerWidth <= 767, i = this.player.controlsOptions.seekPlacement !== "bar" || t;
1243
- this.center.style.display = i ? "flex" : "none", this.centerPrevBtn && (this.centerPrevBtn.style.display = t ? "" : "none"), this.centerNextBtn && (this.centerNextBtn.style.display = t ? "" : "none"), this.playBtn && (this.playBtn.style.display = t ? "none" : "");
1244
- const s = (o) => o === "seekBack" || o === "seekFwd" ? i : o === "prev" || o === "next" ? t : !1;
1242
+ const t = window.innerWidth <= 767, e = t && this.player.controlsOptions.mobileLayout === "center", s = this.player.controlsOptions.seekPlacement !== "bar" || t;
1243
+ this.center.style.display = s ? "flex" : "none", this.centerPrevBtn && (this.centerPrevBtn.style.display = e ? "" : "none"), this.centerNextBtn && (this.centerNextBtn.style.display = e ? "" : "none"), this.playBtn && (this.playBtn.style.display = e ? "none" : "");
1244
+ const n = (h) => h === "seekBack" || h === "seekFwd" ? s : h === "prev" || h === "next" ? e : !1;
1245
1245
  this.overflowed.clear();
1246
- for (const o of this.collapsibles) {
1247
- if (s(o.key)) {
1248
- o.el.style.display = "none";
1246
+ for (const h of this.collapsibles) {
1247
+ if (n(h.key)) {
1248
+ h.el.style.display = "none";
1249
1249
  continue;
1250
1250
  }
1251
- const h = o.available();
1252
- o.el.style.display = h ? "" : "none", o.el.classList.remove("imp-collapsed");
1251
+ const c = h.available();
1252
+ h.el.style.display = c ? "" : "none", h.el.classList.remove("imp-collapsed");
1253
1253
  }
1254
- const n = this.collapsibles.filter((o) => o.available() && !s(o.key)).sort((o, h) => o.priority - h.priority);
1255
- let l = n.length;
1254
+ const o = this.collapsibles.filter((h) => h.available() && !n(h.key)).sort((h, c) => h.priority - c.priority);
1255
+ let l = o.length;
1256
1256
  for (; l-- > 0 && this.overflowsRow(); ) {
1257
- const o = n.find((h) => !this.overflowed.has(h.key));
1258
- if (!o) break;
1259
- o.el.style.display = "none", o.el.classList.add("imp-collapsed"), this.overflowed.add(o.key);
1257
+ const h = o.find((c) => !this.overflowed.has(c.key));
1258
+ if (!h) break;
1259
+ h.el.style.display = "none", h.el.classList.add("imp-collapsed"), this.overflowed.add(h.key);
1260
1260
  }
1261
1261
  if (this.moreWrap) {
1262
- const o = this.actionItems.length > 0 || this.overflowed.size > 0;
1263
- this.moreWrap.style.display = o ? "" : "none";
1262
+ const h = this.actionItems.length > 0 || this.overflowed.size > 0;
1263
+ this.moreWrap.style.display = h ? "" : "none";
1264
1264
  }
1265
1265
  }
1266
1266
  overflowsRow() {
@@ -1330,7 +1330,7 @@ class St {
1330
1330
  this.disposers = [], this.resizeObserver?.disconnect(), this.onWindowResize && window.removeEventListener("resize", this.onWindowResize), this.gearMenu?.destroy(), this.sceneTypeMenu?.destroy(), this.settingsMenu?.destroy(), this.subtitlesMenu?.destroy(), this.qualityMenu?.destroy(), this.moreMenu?.destroy(), this.nextPreviewEl?.remove(), this.root.remove();
1331
1331
  }
1332
1332
  }
1333
- class Tt {
1333
+ class Bt {
1334
1334
  constructor(t) {
1335
1335
  this.root = a("div", "imp-poster"), this.image = a("div", "imp-poster__image"), this.image.hidden = !0, this.img = T(""), this.image.append(this.img);
1336
1336
  const e = b("imp-poster__play", t.labels.play, t.icons.bigPlay);
@@ -1353,7 +1353,7 @@ class Tt {
1353
1353
  this.root.hidden = !0;
1354
1354
  }
1355
1355
  }
1356
- class Bt {
1356
+ class Et {
1357
1357
  constructor(t) {
1358
1358
  this.labels = t, this.channelUrl = null, this.custom = null, this.visible = { title: !0, description: !0, sponsor: !0 }, this.root = a("div", "imp-pause-screen"), this.root.hidden = !0, this.defaultContent = a("div", "imp-pause-screen__default"), this.channel = a("button", "imp-channel", { type: "button" }), this.channel.hidden = !0, this.channelAvatar = a("div", "imp-channel__avatar"), this.channelName = a("div", "imp-channel__name"), this.channel.append(this.channelName, this.channelAvatar), this.channel.addEventListener("click", () => {
1359
1359
  this.channelUrl && window.open(this.channelUrl, "_blank", "noopener");
@@ -1390,7 +1390,7 @@ class Bt {
1390
1390
  this.root.hidden = !0;
1391
1391
  }
1392
1392
  }
1393
- class Et {
1393
+ class Mt {
1394
1394
  constructor(t) {
1395
1395
  this.player = t, this.clickBehavior = "player", this.root = a("div", "imp-related"), this.root.hidden = !0, this.heading = a("div", "imp-related__title"), this.grid = a("div", "imp-related__grid");
1396
1396
  const e = b("imp-related__close", t.labels.close, t.icons.close);
@@ -1439,7 +1439,7 @@ class Et {
1439
1439
  this.root.hidden = !0;
1440
1440
  }
1441
1441
  }
1442
- class Mt {
1442
+ class Ct {
1443
1443
  constructor(t) {
1444
1444
  this.player = t, this.root = a("div", "imp-upnext"), this.root.hidden = !0;
1445
1445
  }
@@ -1458,29 +1458,29 @@ class Mt {
1458
1458
  s.textContent = e.nextVideo, i.append(s);
1459
1459
  const n = q(t.poster);
1460
1460
  if (n) {
1461
- const o = a("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext }), h = T(n);
1461
+ const l = a("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext }), h = T(n);
1462
1462
  if (h.addEventListener("error", () => {
1463
1463
  this.player.markSourceDead(t), this.root.hidden || this.show();
1464
- }, { once: !0 }), o.append(h), t.duration) {
1464
+ }, { once: !0 }), l.append(h), t.duration) {
1465
1465
  const u = a("span", "imp-upnext__duration");
1466
- u.textContent = _(t.duration), o.append(u);
1466
+ u.textContent = _(t.duration), l.append(u);
1467
1467
  }
1468
1468
  const c = a("span", "imp-upnext__thumb-play");
1469
- S(c, this.player.icons.bigPlay), o.append(c), o.addEventListener("click", () => this.player.next()), i.append(o);
1469
+ L(c, this.player.icons.bigPlay), l.append(c), l.addEventListener("click", () => this.player.next()), i.append(l);
1470
1470
  }
1471
1471
  if (t.title) {
1472
- const o = a("div", "imp-upnext__title");
1473
- o.textContent = t.title, i.append(o);
1472
+ const l = a("div", "imp-upnext__title");
1473
+ l.textContent = t.title, i.append(l);
1474
1474
  }
1475
- t.previewMeta?.length && i.append(K(t.previewMeta, "imp-upnext"));
1476
- const l = a("button", "imp-upnext__btn", { type: "button" });
1477
- l.textContent = e.playNext, l.addEventListener("click", () => this.player.next()), i.append(l), this.root.append(i), this.root.hidden = !1;
1475
+ t.previewMeta?.length && i.append(X(t.previewMeta, "imp-upnext"));
1476
+ const o = a("button", "imp-upnext__btn", { type: "button" });
1477
+ o.textContent = e.playNext, o.addEventListener("click", () => this.player.next()), i.append(o), this.root.append(i), this.root.hidden = !1;
1478
1478
  }
1479
1479
  hide() {
1480
1480
  this.root.hidden = !0;
1481
1481
  }
1482
1482
  }
1483
- class Ct {
1483
+ class Pt {
1484
1484
  constructor(t, e = "sidebar", i) {
1485
1485
  this.player = t, this.root = a("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
1486
1486
  const s = a("div", "imp-playlist__header"), n = a("div", "imp-playlist__heading");
@@ -1491,14 +1491,14 @@ class Ct {
1491
1491
  c.textContent = i, n.append(h, c);
1492
1492
  } else
1493
1493
  n.textContent = t.labels.playlist;
1494
- const l = a("div", "imp-playlist__tools");
1494
+ const o = a("div", "imp-playlist__tools");
1495
1495
  this.shuffleBtn = b("imp-playlist__shuffle", t.labels.shuffle, t.icons.shuffle), this.shuffleBtn.addEventListener("click", () => {
1496
1496
  t.setShuffle(!t.shuffle), this.syncModes();
1497
1497
  }), this.repeatBtn = b("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
1498
1498
  t.setRepeat(!t.repeat), this.syncModes();
1499
1499
  });
1500
- const o = b("imp-playlist__close", t.labels.close, t.icons.close);
1501
- o.addEventListener("click", () => this.hide()), l.append(this.shuffleBtn, this.repeatBtn, o), s.append(n, l), this.list = a("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
1500
+ const l = b("imp-playlist__close", t.labels.close, t.icons.close);
1501
+ l.addEventListener("click", () => this.hide()), o.append(this.shuffleBtn, this.repeatBtn, l), s.append(n, o), this.list = a("div", "imp-playlist__list"), this.root.append(s, this.list), this.rebuild(), this.syncModes();
1502
1502
  }
1503
1503
  syncModes() {
1504
1504
  this.shuffleBtn.classList.toggle("imp-btn--active", this.player.shuffle), this.repeatBtn.classList.toggle("imp-btn--active", this.player.repeat);
@@ -1509,12 +1509,12 @@ class Ct {
1509
1509
  e === this.player.index && i.classList.add("imp-playlist__item--active");
1510
1510
  const s = a("div", "imp-playlist__thumb"), n = q(t.poster);
1511
1511
  n && s.append(T(n));
1512
- const l = a("div", "imp-playlist__meta"), o = a("div", "imp-playlist__title");
1513
- if (o.textContent = t.title ?? `#${e + 1}`, l.append(o), t.duration) {
1512
+ const o = a("div", "imp-playlist__meta"), l = a("div", "imp-playlist__title");
1513
+ if (l.textContent = t.title ?? `#${e + 1}`, o.append(l), t.duration) {
1514
1514
  const h = a("div", "imp-playlist__duration");
1515
- h.textContent = _(t.duration), l.append(h);
1515
+ h.textContent = _(t.duration), o.append(h);
1516
1516
  }
1517
- i.append(s, l), i.addEventListener("click", () => {
1517
+ i.append(s, o), i.addEventListener("click", () => {
1518
1518
  this.player.playItem(e), window.innerWidth <= 767 && this.hide();
1519
1519
  }), this.list.append(i);
1520
1520
  });
@@ -1532,7 +1532,7 @@ class Ct {
1532
1532
  this.visible ? this.hide() : this.show();
1533
1533
  }
1534
1534
  }
1535
- class Pt {
1535
+ class At {
1536
1536
  constructor(t, e = "bottom") {
1537
1537
  this.player = t, this.items = [], this.root = a("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
1538
1538
  const i = a("div", "imp-playlist__header"), s = a("span");
@@ -1550,10 +1550,10 @@ class Pt {
1550
1550
  const c = a("div", "imp-scenes__sprite");
1551
1551
  c.style.width = `${n.xywh.w}px`, c.style.height = `${n.xywh.h}px`, c.style.backgroundImage = `url("${n.src}")`, c.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, c.style.setProperty("--imp-sprite-w", String(n.xywh.w)), s.append(c);
1552
1552
  } else n && s.append(T(n.src));
1553
- const l = a("div", "imp-playlist__meta"), o = a("div", "imp-playlist__title");
1554
- o.textContent = e.title || _(e.start);
1553
+ const o = a("div", "imp-playlist__meta"), l = a("div", "imp-playlist__title");
1554
+ l.textContent = e.title || _(e.start);
1555
1555
  const h = a("div", "imp-playlist__duration");
1556
- h.textContent = _(e.start), l.append(o, h), i.append(s, l), i.addEventListener("click", () => {
1556
+ h.textContent = _(e.start), o.append(l, h), i.append(s, o), i.addEventListener("click", () => {
1557
1557
  this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
1558
1558
  }), this.list.append(i), this.items.push(i);
1559
1559
  }
@@ -1578,21 +1578,24 @@ class Pt {
1578
1578
  this.visible ? this.hide() : this.show();
1579
1579
  }
1580
1580
  }
1581
- let et = 0;
1582
- function it(r) {
1581
+ let it = 0;
1582
+ function st(r) {
1583
1583
  const t = r.reason;
1584
1584
  t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") && r.preventDefault();
1585
1585
  }
1586
- function At() {
1587
- typeof window < "u" && ++et === 1 && window.addEventListener("unhandledrejection", it);
1588
- }
1589
1586
  function Rt() {
1590
- typeof window < "u" && --et === 0 && window.removeEventListener("unhandledrejection", it);
1587
+ typeof window < "u" && ++it === 1 && window.addEventListener("unhandledrejection", st);
1591
1588
  }
1592
- function j(r) {
1589
+ function Nt() {
1590
+ typeof window < "u" && --it === 0 && window.removeEventListener("unhandledrejection", st);
1591
+ }
1592
+ function $(r) {
1593
+ console.debug("[itube-player] play() rejected:", r);
1594
+ }
1595
+ function K(r) {
1593
1596
  return r ? typeof r == "string" ? [{ src: r, label: "Subtitles" }] : Array.isArray(r) ? r : [r] : [];
1594
1597
  }
1595
- const Nt = {
1598
+ const It = {
1596
1599
  play: !0,
1597
1600
  progress: !0,
1598
1601
  time: !0,
@@ -1611,6 +1614,8 @@ const Nt = {
1611
1614
  seekButtons: !0,
1612
1615
  // Prev/seek/play/next as a centered overlay on every viewport.
1613
1616
  seekPlacement: "overlay",
1617
+ // Mobile: only ±N seek over the video; play/next live in the bottom bar.
1618
+ mobileLayout: "bar",
1614
1619
  order: [],
1615
1620
  // empty → built-in right-cluster order
1616
1621
  playlist: !0,
@@ -1621,26 +1626,26 @@ const Nt = {
1621
1626
  hideDelay: 2500,
1622
1627
  revealBeforePlay: !0
1623
1628
  };
1624
- class Ot {
1629
+ class Ht {
1625
1630
  constructor(t, e = {}) {
1626
- this.scrubbing = !1, this.emitter = new nt(), this.externalAdvance = !1, this.abort = new AbortController(), this.sources = [], this.deadSources = /* @__PURE__ */ new WeakSet(), this.currentIndex = -1, this.sourceController = null, this.loadToken = 0, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.thumbTrack = null, this.shuffleMode = !1, this.autoAdvanceEnabled = !0, this.persistKey = null, this.persistVolume = !1, this.persistAutoAdvance = !1, this.decodeRecoveries = 0, this.adManager = null, this.playedOnce = !1, this.idleTimer = null, this.peekTimer = null, this.lastRetryAt = 0, this.retryTimer = null, this.errorResumeTime = 0, this.lastPlayheadTime = 0, this.destroyed = !1, this.persistTimer = null;
1631
+ this.scrubbing = !1, this.emitter = new rt(), this.externalAdvance = !1, this.abort = new AbortController(), this.sources = [], this.deadSources = /* @__PURE__ */ new WeakSet(), this.currentIndex = -1, this.sourceController = null, this.loadToken = 0, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.thumbTrack = null, this.shuffleMode = !1, this.autoAdvanceEnabled = !0, this.persistKey = null, this.persistVolume = !1, this.persistAutoAdvance = !1, this.decodeRecoveries = 0, this.adManager = null, this.playedOnce = !1, this.idleTimer = null, this.peekTimer = null, this.lastRetryAt = 0, this.retryTimer = null, this.errorResumeTime = 0, this.lastPlayheadTime = 0, this.pendingSeek = null, this.destroyed = !1, this.persistTimer = null;
1627
1632
  const i = typeof t == "string" ? document.querySelector(t) : t;
1628
1633
  if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
1629
- this.mount = i, this.options = e, this.labels = { ...D, ...ot(e.language), ...e.labels }, this.icons = { ...rt, ...e.icons };
1634
+ this.mount = i, this.options = e, this.labels = { ...G, ...at(e.language), ...e.labels }, this.icons = { ...ot, ...e.icons };
1630
1635
  const s = e.controls ?? {}, n = s.speed ?? s.settings ?? "gear";
1631
- if (this.controlsOptions = { ...Nt, ...s, speed: n, settings: n }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 1, 1.5, 2], this.seekStep = e.seekStep ?? 15, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", externalAdvance: !1, ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, this.externalAdvance = this.playlistOptions.externalAdvance, e.persist) {
1636
+ if (this.controlsOptions = { ...It, ...s, speed: n, settings: n }, this.actionsOptions = e.actions ?? {}, this.playbackRates = e.playbackRates ?? [0.5, 1, 1.5, 2], this.seekStep = e.seekStep ?? 15, this.playlistOptions = { title: "", autoAdvance: !0, loop: !1, shuffle: !1, startIndex: 0, layout: "sidebar", externalAdvance: !1, ...e.playlist }, this.shuffleMode = this.playlistOptions.shuffle, this.externalAdvance = this.playlistOptions.externalAdvance, e.persist) {
1632
1637
  const y = e.persist === !0 ? {} : e.persist;
1633
1638
  this.persistKey = y.key ?? "itube-player", this.persistVolume = y.volume !== !1, this.persistAutoAdvance = y.autoAdvance !== !1;
1634
1639
  }
1635
- const l = this.readPersisted();
1636
- this.autoAdvanceEnabled = this.persistAutoAdvance && typeof l?.autoAdvance == "boolean" ? l.autoAdvance : this.playlistOptions.autoAdvance, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = a("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
1637
- const o = e.styling;
1638
- if (o?.themeColor && this.container.style.setProperty("--imp-accent", o.themeColor), o?.likeColor && this.container.style.setProperty("--imp-like", o.likeColor), o?.dislikeColor && this.container.style.setProperty("--imp-dislike", o.dislikeColor), o?.fontFamily && this.container.style.setProperty("--imp-font", o.fontFamily), o?.borderRadius !== void 0) {
1639
- const y = typeof o.borderRadius == "number" ? `${o.borderRadius}px` : o.borderRadius;
1640
+ const o = this.readPersisted();
1641
+ this.autoAdvanceEnabled = this.persistAutoAdvance && typeof o?.autoAdvance == "boolean" ? o.autoAdvance : this.playlistOptions.autoAdvance, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = a("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
1642
+ const l = e.styling;
1643
+ if (l?.themeColor && this.container.style.setProperty("--imp-accent", l.themeColor), l?.likeColor && this.container.style.setProperty("--imp-like", l.likeColor), l?.dislikeColor && this.container.style.setProperty("--imp-dislike", l.dislikeColor), l?.fontFamily && this.container.style.setProperty("--imp-font", l.fontFamily), l?.borderRadius !== void 0) {
1644
+ const y = typeof l.borderRadius == "number" ? `${l.borderRadius}px` : l.borderRadius;
1640
1645
  this.container.style.setProperty("--imp-radius", y);
1641
1646
  }
1642
- o?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = a("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);
1643
- const h = this.persistVolume ? l : null;
1647
+ l?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = e.videoElement ?? a("video", "imp-video"), this.video.classList.add("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);
1648
+ const h = this.persistVolume ? o : null;
1644
1649
  this.video.volume = x(h?.volume ?? e.volume ?? 1, 0, 1), (h?.muted ?? e.muted) && (this.video.muted = !0);
1645
1650
  const c = a("div", "imp-layer");
1646
1651
  this.spinner = a("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = a("div", "imp-error"), this.errorBox.hidden = !0, this.errorText = a("div", "imp-error__text"), this.retryBtn = a("button", "imp-error__retry", { type: "button" });
@@ -1648,21 +1653,21 @@ class Ot {
1648
1653
  u.textContent = this.labels.tryAgain, this.retryBtn.append(u, a("span", "imp-error__retry-spinner")), this.retryBtn.addEventListener("click", () => this.retry()), this.errorNextBtn = a("button", "imp-error__next", { type: "button" }), this.errorNextBtn.textContent = this.labels.nextVideo, this.errorNextBtn.addEventListener("click", () => {
1649
1654
  this.clearError(), this.next();
1650
1655
  });
1651
- const v = a("div", "imp-error__actions");
1652
- v.append(this.retryBtn, this.errorNextBtn), this.errorBox.append(this.errorText, v), this.pauseScreen = new Bt(this.labels), this.poster = new Tt(this), this.related = new Et(this), this.related.setOptions(e.related), this.upNext = new Mt(this), this.controls = new St(this), this.playlistPanel = new Ct(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new Pt(this, e.scenes?.layout ?? "bottom");
1656
+ const f = a("div", "imp-error__actions");
1657
+ f.append(this.retryBtn, this.errorNextBtn), this.errorBox.append(this.errorText, f), this.pauseScreen = new Et(this.labels), this.poster = new Bt(this), this.related = new Mt(this), this.related.setOptions(e.related), this.upNext = new Ct(this), this.controls = new Tt(this), this.playlistPanel = new Pt(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new At(this, e.scenes?.layout ?? "bottom");
1653
1658
  const p = a("div", "imp-layer__middle");
1654
1659
  p.append(this.spinner, this.errorBox, this.controls.center);
1655
1660
  const m = a("div", "imp-layer__bottom");
1656
1661
  m.append(this.controls.root), c.append(this.pauseScreen.root, this.related.root, this.upNext.root, p, m), this.container.append(this.video, c, this.poster.root, this.playlistPanel.root, this.scenesPanel.root), this.mount.append(this.container), e.pauseScreen instanceof HTMLElement ? this.pauseScreen.setCustomContent(e.pauseScreen) : typeof e.pauseScreen == "function" ? this.pauseScreen.setCustomContent(e.pauseScreen(this)) : e.pauseScreen && typeof e.pauseScreen == "object" && this.pauseScreen.setVisibility(e.pauseScreen);
1657
- const f = e.adConfig ?? e.ads;
1658
- f && f.adList.length > 0 && (this.adManager = new ft(
1662
+ const v = e.adConfig ?? e.ads;
1663
+ v && v.adList.length > 0 && (this.adManager = new gt(
1659
1664
  { container: this.container, contentVideo: this.video, emitter: this.emitter, labels: this.labels, closeIcon: this.icons.close },
1660
- f
1665
+ v
1661
1666
  )), this.emitter.on("error", ({ fatal: y }) => {
1662
1667
  if (!y) return;
1663
1668
  const d = this.lastPlayheadTime || this.video.currentTime;
1664
1669
  Number.isFinite(d) && d > 0 && (this.errorResumeTime = d), this.errorText.textContent = this.labels.videoNotFound, this.errorNextBtn.hidden = !this.hasNext, this.errorBox.hidden = !1, this.spinner.hidden = !0, this.poster.hide(), this.container.classList.add("imp-player--error");
1665
- }), At(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (y) => {
1670
+ }), Rt(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (y) => {
1666
1671
  if (!(this.adPlaying || !this.playedOnce)) {
1667
1672
  if (y.pointerType === "mouse") {
1668
1673
  this.togglePlay();
@@ -1722,12 +1727,11 @@ class Ot {
1722
1727
  if (i === "NotSupportedError" && this.video.readyState === 0) {
1723
1728
  const s = this.loadToken;
1724
1729
  this.video.addEventListener("loadedmetadata", () => {
1725
- s === this.loadToken && this.video.play().catch(() => {
1726
- });
1730
+ s === this.loadToken && this.video.play().catch($);
1727
1731
  }, { once: !0, signal: this.abort.signal });
1728
1732
  return;
1729
1733
  }
1730
- i !== "AbortError" && !this.playedOnce && this.poster.show();
1734
+ i !== "AbortError" && ($(e), this.playedOnce || this.poster.show());
1731
1735
  }
1732
1736
  }
1733
1737
  pause() {
@@ -1762,8 +1766,17 @@ class Ot {
1762
1766
  clearError() {
1763
1767
  this.errorBox.hidden = !0, this.container.classList.remove("imp-player--error");
1764
1768
  }
1769
+ /** True once the current source has started playing at least once. */
1770
+ get started() {
1771
+ return this.playedOnce;
1772
+ }
1765
1773
  seek(t) {
1766
- Number.isFinite(this.video.duration) && (this.video.currentTime = x(t, 0, this.video.duration));
1774
+ if (Number.isFinite(this.video.duration)) {
1775
+ this.video.currentTime = x(t, 0, this.video.duration);
1776
+ return;
1777
+ }
1778
+ const e = this.source?.duration;
1779
+ typeof e == "number" && e > 0 && (this.pendingSeek = x(t, 0, e));
1767
1780
  }
1768
1781
  /** Relative seek, e.g. `skip(-10)`. */
1769
1782
  skip(t) {
@@ -1832,8 +1845,8 @@ class Ot {
1832
1845
  setQuality(t) {
1833
1846
  if (this.sourceController?.kind === "hls") {
1834
1847
  this.sourceController.setLevel(t);
1835
- const l = t === -1 ? this.labels.qualityAuto : this.sourceController.levels.find((o) => o.index === t)?.label ?? String(t);
1836
- this.emitter.emit("qualitychange", { label: l });
1848
+ const o = t === -1 ? this.labels.qualityAuto : this.sourceController.levels.find((l) => l.index === t)?.label ?? String(t);
1849
+ this.emitter.emit("qualitychange", { label: o });
1837
1850
  return;
1838
1851
  }
1839
1852
  const e = this.source?.qualities;
@@ -1847,14 +1860,13 @@ class Ot {
1847
1860
  this.video.currentTime = i;
1848
1861
  } catch {
1849
1862
  }
1850
- s && this.video.play().catch(() => {
1851
- });
1863
+ s && this.video.play().catch($);
1852
1864
  }
1853
1865
  }, { once: !0, signal: this.abort.signal }), this.emitter.emit("qualitychange", { label: e[t].label ?? String(e[t].quality ?? t) });
1854
1866
  }
1855
1867
  // === subtitles ========================================================
1856
1868
  get subtitleTracks() {
1857
- return j(this.source?.subtitles);
1869
+ return K(this.source?.subtitles);
1858
1870
  }
1859
1871
  get activeSubtitle() {
1860
1872
  const t = this.video.textTracks;
@@ -2015,9 +2027,20 @@ class Ot {
2015
2027
  setSceneGroup(t) {
2016
2028
  t === this.activeSceneGroupId || !this.sceneGroupList.some((e) => e.id === t) || (this.activeSceneGroupId = t, this.applyActiveSceneGroup(), this.emitter.emit("scenetypechange", { group: this.activeSceneType }));
2017
2029
  }
2030
+ /**
2031
+ * Best duration currently known: the media's real one once metadata is in,
2032
+ * else the declared `source.duration` (lets scene groups and the seek bar
2033
+ * render before the first play), else NaN.
2034
+ */
2035
+ get knownDuration() {
2036
+ const t = this.video.duration;
2037
+ if (Number.isFinite(t) && t > 0) return t;
2038
+ const e = this.source?.duration;
2039
+ return typeof e == "number" && e > 0 ? e : NaN;
2040
+ }
2018
2041
  /** Normalize the active group's scenes into `chapters` and refresh the UI. */
2019
2042
  applyActiveSceneGroup() {
2020
- this.chapters = U(this.activeSceneType?.scenes ?? [], this.video.duration), this.currentChapter = null, this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild();
2043
+ this.chapters = j(this.activeSceneType?.scenes ?? [], this.knownDuration), this.currentChapter = null, this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild();
2021
2044
  }
2022
2045
  // === actions ==========================================================
2023
2046
  /**
@@ -2054,16 +2077,16 @@ class Ot {
2054
2077
  }
2055
2078
  // === teardown =========================================================
2056
2079
  destroy() {
2057
- this.destroyed || (this.destroyed = !0, this.loadToken++, this.adManager?.destroy(), this.controls.destroy(), this.sourceController?.destroy(), this.abort.abort(), this.idleTimer && clearTimeout(this.idleTimer), this.peekTimer && clearTimeout(this.peekTimer), this.retryTimer && clearTimeout(this.retryTimer), this.persistTimer && (clearTimeout(this.persistTimer), this.persistTimer = null, this.persistState()), this.container.remove(), Rt(), this.emitter.emit("destroy", void 0), this.emitter.removeAll());
2080
+ this.destroyed || (this.destroyed = !0, this.loadToken++, this.adManager?.destroy(), this.controls.destroy(), this.sourceController?.destroy(), this.abort.abort(), this.idleTimer && clearTimeout(this.idleTimer), this.peekTimer && clearTimeout(this.peekTimer), this.retryTimer && clearTimeout(this.retryTimer), this.persistTimer && (clearTimeout(this.persistTimer), this.persistTimer = null, this.persistState()), this.container.remove(), Nt(), this.emitter.emit("destroy", void 0), this.emitter.removeAll());
2058
2081
  }
2059
2082
  // === internals ========================================================
2060
2083
  async loadItem(t, e, i = !1) {
2061
2084
  const s = ++this.loadToken, n = this.sources[t];
2062
2085
  if (!n) return;
2063
- this.currentIndex = t, this.sourceController?.destroy(), this.sourceController = null, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.playedOnce = !1, this.lastPlayheadTime = 0, this.errorResumeTime = 0, this.endPeek();
2086
+ this.currentIndex = t, this.sourceController?.destroy(), this.sourceController = null, this.chapters = [], this.currentChapter = null, this.sceneGroupList = [], this.activeSceneGroupId = "", this.progressiveQuality = -1, this.playedOnce = !1, this.lastPlayheadTime = 0, this.errorResumeTime = 0, this.pendingSeek = null, this.endPeek();
2064
2087
  for (const p of [...this.video.querySelectorAll("track")]) p.remove();
2065
- this.adManager?.resetForNewSource(), this.related.hide(), this.upNext.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.decodeRecoveries = 0, this.video.poster = q(n.poster) ?? "", this.poster.setSource(n), this.pauseScreen.setSource(n), this.controls.progress.setChapters([]), this.controls.progress.setThumbnails(null), this.controls.progress.setHeatmap([]), e ? this.poster.hide() : this.poster.show(), this.playlistPanel.rebuild();
2066
- for (const p of j(n.subtitles)) {
2088
+ this.adManager?.resetForNewSource(), this.related.hide(), this.upNext.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.decodeRecoveries = 0, this.video.poster = q(n.poster) ?? "", this.poster.setSource(n), this.pauseScreen.setSource(n), this.controls.progress.setChapters([]), this.controls.progress.setThumbnails(null), this.controls.progress.setHeatmap([]), typeof n.duration == "number" && n.duration > 0 && this.controls.progress.update(0, n.duration, 0), e ? this.poster.hide() : this.poster.show(), this.playlistPanel.rebuild();
2089
+ for (const p of K(n.subtitles)) {
2067
2090
  const m = a("track", "", {
2068
2091
  kind: "subtitles",
2069
2092
  src: p.src,
@@ -2072,13 +2095,13 @@ class Ot {
2072
2095
  });
2073
2096
  p.default && m.setAttribute("default", ""), this.video.append(m);
2074
2097
  }
2075
- let l = n.src, o = n.type;
2098
+ let o = n.src, l = n.type;
2076
2099
  if (n.qualities && n.qualities.length > 0) {
2077
2100
  const p = Math.max(0, n.qualities.findIndex((m) => m.src === n.src));
2078
- this.progressiveQuality = p, l = n.qualities[p].src, o = n.qualities[p].type ?? o;
2101
+ this.progressiveQuality = p, o = n.qualities[p].src, l = n.qualities[p].type ?? l;
2079
2102
  }
2080
2103
  this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
2081
- const h = await kt(this.video, l, o, {
2104
+ const h = await wt(this.video, o, l, {
2082
2105
  onLevels: () => {
2083
2106
  s === this.loadToken && this.controls.syncFeatureButtons();
2084
2107
  },
@@ -2089,28 +2112,26 @@ class Ot {
2089
2112
  h.destroy();
2090
2113
  return;
2091
2114
  }
2092
- if (this.sourceController = h, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && G.load(n.thumbnails).then((p) => {
2115
+ if (this.sourceController = h, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && W.load(n.thumbnails).then((p) => {
2093
2116
  s === this.loadToken && (this.thumbTrack = p, this.controls.progress.setThumbnails(p), this.scenesPanel.visible && this.scenesPanel.rebuild());
2094
- }).catch((p) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: p })), n.sceneGroups && n.sceneGroups.length > 0) {
2095
- this.sceneGroupList = n.sceneGroups, this.activeSceneGroupId = n.sceneGroups[0].id;
2096
- const p = () => {
2117
+ }).catch((p) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: p })), n.sceneGroups && n.sceneGroups.length > 0)
2118
+ this.sceneGroupList = n.sceneGroups, this.activeSceneGroupId = n.sceneGroups[0].id, this.applyActiveSceneGroup(), Number.isFinite(this.video.duration) && this.video.duration > 0 || this.video.addEventListener("loadedmetadata", () => {
2097
2119
  s === this.loadToken && this.applyActiveSceneGroup();
2098
- };
2099
- Number.isFinite(this.video.duration) && this.video.duration > 0 ? p() : this.video.addEventListener("loadedmetadata", p, { once: !0, signal: this.abort.signal });
2100
- } else if (n.chapters) {
2120
+ }, { once: !0, signal: this.abort.signal });
2121
+ else if (n.chapters) {
2101
2122
  const p = (m) => {
2102
- const f = () => {
2103
- s === this.loadToken && (this.chapters = U(m, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
2123
+ const v = () => {
2124
+ s === this.loadToken && (this.chapters = j(m, this.knownDuration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
2104
2125
  };
2105
- Number.isFinite(this.video.duration) && this.video.duration > 0 ? f() : this.video.addEventListener("loadedmetadata", f, { once: !0, signal: this.abort.signal });
2126
+ Number.isFinite(this.video.duration) && this.video.duration > 0 ? v() : this.video.addEventListener("loadedmetadata", v, { once: !0, signal: this.abort.signal });
2106
2127
  };
2107
- typeof n.chapters == "string" ? gt(n.chapters).then((m) => p(m)).catch((m) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: m })) : p(n.chapters);
2128
+ typeof n.chapters == "string" ? yt(n.chapters).then((m) => p(m)).catch((m) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: m })) : p(n.chapters);
2108
2129
  }
2109
- const c = n.heatmap, u = c && !Array.isArray(c), v = u ? c.values.length > 0 : !!(c && c.length > 0);
2110
- if (c && v && this.controlsOptions.heatmap) {
2130
+ const c = n.heatmap, u = c && !Array.isArray(c), f = u ? c.values.length > 0 : !!(c && c.length > 0);
2131
+ if (c && f && this.controlsOptions.heatmap) {
2111
2132
  const p = () => {
2112
2133
  if (s !== this.loadToken) return;
2113
- const m = u ? ct(c.values, c.mode) : ht(c, this.video.duration);
2134
+ const m = u ? dt(c.values, c.mode) : ct(c, this.video.duration);
2114
2135
  this.controls.progress.setHeatmap(m, u ? c.smoothing ?? 1 : 1);
2115
2136
  };
2116
2137
  u || Number.isFinite(this.video.duration) && this.video.duration > 0 ? p() : this.video.addEventListener("loadedmetadata", p, { once: !0, signal: this.abort.signal });
@@ -2127,12 +2148,22 @@ class Ot {
2127
2148
  this.handleEnded();
2128
2149
  }, { signal: t }), e.addEventListener("timeupdate", () => {
2129
2150
  !this.adPlaying && e.currentTime > 0 && (this.lastPlayheadTime = e.currentTime), this.emitter.emit("timeupdate", { currentTime: e.currentTime, duration: e.duration || 0 }), this.adManager?.checkMidRolls(e.currentTime);
2130
- const i = tt(this.chapters, e.currentTime);
2151
+ const i = et(this.chapters, e.currentTime);
2131
2152
  i !== this.currentChapter && (this.currentChapter = i, this.emitter.emit("chapterchange", { chapter: i }));
2132
2153
  }, { signal: t }), e.addEventListener("progress", () => {
2133
2154
  this.emitter.emit("progress", { buffered: this.bufferedEnd });
2134
2155
  }, { signal: t }), e.addEventListener("volumechange", () => {
2135
2156
  this.emitter.emit("volumechange", { volume: e.volume, muted: e.muted }), this.persistVolume && this.schedulePersist();
2157
+ }, { signal: t }), e.addEventListener("loadedmetadata", () => {
2158
+ if (this.pendingSeek !== null) {
2159
+ const i = x(this.pendingSeek, 0, Number.isFinite(e.duration) ? e.duration : this.pendingSeek);
2160
+ this.pendingSeek = null;
2161
+ try {
2162
+ e.currentTime = i;
2163
+ } catch {
2164
+ }
2165
+ }
2166
+ !this.playedOnce && Number.isFinite(e.duration) && this.controls.progress.update(e.currentTime, e.duration, this.bufferedEnd);
2136
2167
  }, { 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", () => {
2137
2168
  this.spinner.hidden = !1;
2138
2169
  }, { signal: t });
@@ -2145,17 +2176,16 @@ class Ot {
2145
2176
  if (!i || this.sourceController?.kind === "hls" || e.getAttribute("src") === null && !e.currentSrc) return;
2146
2177
  if ((i.code === MediaError.MEDIA_ERR_DECODE || /DEMUXER|PARSE|DECODE/i.test(i.message || "")) && this.decodeRecoveries < 2 && Number.isFinite(e.duration)) {
2147
2178
  this.decodeRecoveries++;
2148
- const n = e.currentTime, l = !e.paused;
2179
+ const n = e.currentTime, o = !e.paused;
2149
2180
  e.load();
2150
- const o = () => {
2181
+ const l = () => {
2151
2182
  try {
2152
2183
  e.currentTime = n;
2153
2184
  } catch {
2154
2185
  }
2155
- l && e.play().catch(() => {
2156
- });
2186
+ o && e.play().catch($);
2157
2187
  };
2158
- e.readyState >= 1 ? o() : e.addEventListener("loadedmetadata", o, { once: !0, signal: this.abort.signal });
2188
+ e.readyState >= 1 ? l() : e.addEventListener("loadedmetadata", l, { once: !0, signal: this.abort.signal });
2159
2189
  return;
2160
2190
  }
2161
2191
  this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i, fatal: !0 });
@@ -2273,22 +2303,22 @@ class Ot {
2273
2303
  }
2274
2304
  }
2275
2305
  export {
2276
- nt as Emitter,
2277
- Ot as Player,
2278
- G as ThumbnailTrack,
2279
- ht as buildHeatmapValues,
2280
- tt as chapterAt,
2281
- rt as defaultIcons,
2282
- D as defaultLabels,
2306
+ rt as Emitter,
2307
+ Ht as Player,
2308
+ W as ThumbnailTrack,
2309
+ ct as buildHeatmapValues,
2310
+ et as chapterAt,
2311
+ ot as defaultIcons,
2312
+ G as defaultLabels,
2283
2313
  _ as formatTime,
2284
- ot as getLocale,
2285
- dt as heatmapPath,
2286
- yt as isHlsSource,
2287
- gt as loadChaptersVtt,
2288
- U as normalizeChapters,
2314
+ at as getLocale,
2315
+ ut as heatmapPath,
2316
+ bt as isHlsSource,
2317
+ yt as loadChaptersVtt,
2318
+ j as normalizeChapters,
2289
2319
  qt as registerLocale,
2290
- Ft as registerLocales,
2291
- Vt as registeredLanguages,
2292
- ut as resolveVast
2320
+ Vt as registerLocales,
2321
+ Ot as registeredLanguages,
2322
+ pt as resolveVast
2293
2323
  };
2294
2324
  //# sourceMappingURL=core.js.map