itube-modern-player 0.7.2 → 0.8.1

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,6 +1,80 @@
1
- import { e as o, f as _, p as U, r as et, a as q, c as x, i as g, b as S, d as j, s as I } from "./dom-DrpWbY0y.js";
2
- import { d as H } from "./labels-CCjOCBKU.js";
3
- class it {
1
+ import { posterSrc as q } from "./placeholder.js";
2
+ import { d as G } from "./labels-CCjOCBKU.js";
3
+ function a(r, t, e) {
4
+ const i = document.createElement(r);
5
+ if (t && (i.className = t), e)
6
+ for (const [s, n] of Object.entries(e)) i.setAttribute(s, n);
7
+ return i;
8
+ }
9
+ function L(r, t) {
10
+ if (r.textContent = "", typeof t == "object") {
11
+ "url" in t ? r.append(a("img", "imp-icon-img", { src: t.url, alt: "" })) : r.innerHTML = t.svg;
12
+ return;
13
+ }
14
+ /^\s*</.test(t) ? r.innerHTML = t : r.append(a("img", "imp-icon-img", { src: t, alt: "" }));
15
+ }
16
+ function T(r, t = "") {
17
+ const e = a("img", "imp-cover-img", { alt: t, decoding: "async" });
18
+ return e.src = r, e;
19
+ }
20
+ function b(r, t, e) {
21
+ const i = a("button", `imp-btn ${r}`, { type: "button", "aria-label": t, title: t });
22
+ return L(i, e), i;
23
+ }
24
+ function X(r, t) {
25
+ const e = a("div", `${t}__meta`);
26
+ return r.forEach((i, s) => {
27
+ s > 0 && e.append(document.createTextNode(" "));
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
+ const h = a("span", `${t}__meta-icon`);
31
+ L(h, o), l.append(h);
32
+ }
33
+ l.append(document.createTextNode(n)), e.append(l);
34
+ }), e;
35
+ }
36
+ function I(r, t, e) {
37
+ L(r, t), e !== void 0 && (r.setAttribute("aria-label", e), r.setAttribute("title", e));
38
+ }
39
+ function x(r, t, e) {
40
+ return Math.min(e, Math.max(t, r));
41
+ }
42
+ function _(r) {
43
+ if (!Number.isFinite(r) || r < 0) return "0:00";
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
+ return i > 0 ? `${i}:${s}:${n}` : `${s}:${n}`;
46
+ }
47
+ function H(r) {
48
+ const t = r.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:[.,](\d{1,3}))?$/);
49
+ if (!t) return null;
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
+ return e * 3600 + i * 60 + s + n / 1e3;
52
+ }
53
+ function J(r) {
54
+ const t = [], e = r.replace(/\r\n?/g, `
55
+ `).split(/\n\n+/);
56
+ for (const i of e) {
57
+ const s = i.split(`
58
+ `).filter((f) => f.trim() !== "");
59
+ if (s.length === 0) continue;
60
+ let n = s.findIndex((f) => f.includes("-->"));
61
+ if (n === -1) continue;
62
+ const [o, l] = s[n].split("-->"), h = H(o), c = H((l ?? "").split(" ")[1] ?? l ?? "") ?? H(l ?? "");
63
+ if (h === null || c === null) continue;
64
+ const u = s.slice(n + 1).join(`
65
+ `).trim();
66
+ u && t.push({ start: h, end: c, text: u });
67
+ }
68
+ return t;
69
+ }
70
+ function nt(r, t) {
71
+ try {
72
+ return new URL(r, new URL(t, window.location.href)).toString();
73
+ } catch {
74
+ return r;
75
+ }
76
+ }
77
+ class rt {
4
78
  constructor() {
5
79
  this.listeners = /* @__PURE__ */ new Map();
6
80
  }
@@ -32,221 +106,221 @@ class it {
32
106
  this.listeners.clear();
33
107
  }
34
108
  }
35
- const y = (l, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${l}</svg>`, st = {
36
- play: y('<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"/>'),
37
- pause: y('<rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/>'),
38
- replay: y('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
39
- bigPlay: y('<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"/>'),
40
- volumeHigh: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/><path d="M14.5 5.2a8 8 0 0 1 0 13.6v-2a6 6 0 0 0 0-9.6v-2Z"/>'),
41
- volumeLow: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/>'),
42
- volumeMute: y('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="m15.3 9.3 1.4 1.4 1.4-1.4 1.4 1.4-1.4 1.4 1.4 1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4Z"/>'),
43
- fullscreen: y('<path d="M5 5h5v2H7v3H5V5Zm9 0h5v5h-2V7h-3V5ZM5 14h2v3h3v2H5v-5Zm12 0h2v5h-5v-2h3v-3Z"/>'),
44
- fullscreenExit: y('<path d="M10 10H5V8h3V5h2v5Zm4 0V5h2v3h3v2h-5Zm-4 4v5H8v-3H5v-2h5Zm4 0h5v2h-3v3h-2v-5Z"/>'),
45
- pip: y('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Z"/><rect x="12" y="11" width="6" height="4"/>'),
46
- settings: y('<path d="M12 8.5A3.5 3.5 0 1 0 12 15.5 3.5 3.5 0 0 0 12 8.5Zm0 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Z"/><path d="M10.3 2.8 9.9 5.1a7 7 0 0 0-1.5.86l-2.2-.8-1.7 3 1.8 1.5a7 7 0 0 0 0 1.7l-1.8 1.5 1.7 3 2.2-.8c.46.36.97.65 1.5.86l.4 2.3h3.4l.4-2.3a7 7 0 0 0 1.5-.86l2.2.8 1.7-3-1.8-1.5a7 7 0 0 0 0-1.7l1.8-1.5-1.7-3-2.2.8a7 7 0 0 0-1.5-.86l-.4-2.3h-3.4Zm1.7 5.7a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z"/>'),
47
- speed: y('<path d="M12 4a9 9 0 0 0-9 9 8.96 8.96 0 0 0 1.62 5.16l1.64-1.15A7 7 0 0 1 5 13a7 7 0 1 1 12.74 4.01l1.64 1.15A8.96 8.96 0 0 0 21 13a9 9 0 0 0-9-9Z"/><path d="m15.6 8.3-3.95 3.13a1.5 1.5 0 1 0 1.92 1.92L16.7 9.4a.78.78 0 0 0-1.1-1.1Z"/>'),
48
- scenes: y('<path d="M3 5h18v14H3V5Zm2 2v10h3V7H5Zm5 0v10h9V7h-9Zm-5 3h3v1H5v-1Zm0 3h3v1H5v-1Z"/>'),
49
- shuffle: y('<path d="M4 6h2.6c1.5 0 2.9.7 3.8 1.9l4.1 5.4a2.75 2.75 0 0 0 2.2 1.1H19l-1.8-1.8 1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 16.4h-2.3a4.75 4.75 0 0 1-3.8-1.9L8.8 9.1A2.75 2.75 0 0 0 6.6 8H4V6Z"/><path d="M19 7.6h-2.3c-.86 0-1.67.41-2.18 1.1l-.93 1.23-1.25-1.65.58-.77A4.75 4.75 0 0 1 16.7 5.6H19L17.2 3.8l1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 7.6Z" transform="translate(0 1.2)"/>'),
50
- repeat: y('<path d="M7 7h10v2.5L21 6l-4-3.5V5H5v6h2V7Zm10 10H7v-2.5L3 18l4 3.5V19h12v-6h-2v4Z"/>'),
51
- subtitles: y('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Zm2 3h6v2H7v-2Zm8 0h2v2h-2v-2ZM7 14h2v2H7v-2Zm4 0h6v2h-6v-2Z"/>'),
52
- list: y('<path d="M4 6h2v2H4V6Zm4 0h12v2H8V6ZM4 11h2v2H4v-2Zm4 0h12v2H8v-2ZM4 16h2v2H4v-2Zm4 0h12v2H8v-2Z"/>'),
53
- next: y('<path d="M6 5.5v13c0 .77.84 1.25 1.5.85l9-6.5a1 1 0 0 0 0-1.7l-9-6.5c-.66-.4-1.5.08-1.5.85Z"/><rect x="17" y="5" width="2.5" height="14" rx="1"/>'),
54
- previous: y('<path d="M18 5.5v13c0 .77-.84 1.25-1.5.85l-9-6.5a1 1 0 0 1 0-1.7l9-6.5c.66-.4 1.5.08 1.5.85Z"/><rect x="4.5" y="5" width="2.5" height="14" rx="1"/>'),
109
+ const g = (r, t = "0 0 24 24") => `<svg viewBox="${t}" fill="currentColor" aria-hidden="true" focusable="false">${r}</svg>`, ot = {
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
+ 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
+ replay: g('<path d="M12 5V2.5L7.5 6 12 9.5V7a5 5 0 1 1-5 5H5a7 7 0 1 0 7-7Z"/>'),
113
+ bigPlay: 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"/>'),
114
+ volumeHigh: g('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/><path d="M14.5 5.2a8 8 0 0 1 0 13.6v-2a6 6 0 0 0 0-9.6v-2Z"/>'),
115
+ volumeLow: g('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="M14.5 8.6a4.5 4.5 0 0 1 0 6.8v-1.9a2.5 2.5 0 0 0 0-3v-1.9Z"/>'),
116
+ volumeMute: g('<path d="M4 9v6h3.5L12 19.5v-15L7.5 9H4Z"/><path d="m15.3 9.3 1.4 1.4 1.4-1.4 1.4 1.4-1.4 1.4 1.4 1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4-1.4 1.4-1.4-1.4-1.4 1.4-1.4Z"/>'),
117
+ fullscreen: g('<path d="M5 5h5v2H7v3H5V5Zm9 0h5v5h-2V7h-3V5ZM5 14h2v3h3v2H5v-5Zm12 0h2v5h-5v-2h3v-3Z"/>'),
118
+ fullscreenExit: g('<path d="M10 10H5V8h3V5h2v5Zm4 0V5h2v3h3v2h-5Zm-4 4v5H8v-3H5v-2h5Zm4 0h5v2h-3v3h-2v-5Z"/>'),
119
+ pip: g('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Z"/><rect x="12" y="11" width="6" height="4"/>'),
120
+ settings: g('<path d="M12 8.5A3.5 3.5 0 1 0 12 15.5 3.5 3.5 0 0 0 12 8.5Zm0 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Z"/><path d="M10.3 2.8 9.9 5.1a7 7 0 0 0-1.5.86l-2.2-.8-1.7 3 1.8 1.5a7 7 0 0 0 0 1.7l-1.8 1.5 1.7 3 2.2-.8c.46.36.97.65 1.5.86l.4 2.3h3.4l.4-2.3a7 7 0 0 0 1.5-.86l2.2.8 1.7-3-1.8-1.5a7 7 0 0 0 0-1.7l1.8-1.5-1.7-3-2.2.8a7 7 0 0 0-1.5-.86l-.4-2.3h-3.4Zm1.7 5.7a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z"/>'),
121
+ speed: g('<path d="M12 4a9 9 0 0 0-9 9 8.96 8.96 0 0 0 1.62 5.16l1.64-1.15A7 7 0 0 1 5 13a7 7 0 1 1 12.74 4.01l1.64 1.15A8.96 8.96 0 0 0 21 13a9 9 0 0 0-9-9Z"/><path d="m15.6 8.3-3.95 3.13a1.5 1.5 0 1 0 1.92 1.92L16.7 9.4a.78.78 0 0 0-1.1-1.1Z"/>'),
122
+ scenes: g('<path d="M3 5h18v14H3V5Zm2 2v10h3V7H5Zm5 0v10h9V7h-9Zm-5 3h3v1H5v-1Zm0 3h3v1H5v-1Z"/>'),
123
+ shuffle: g('<path d="M4 6h2.6c1.5 0 2.9.7 3.8 1.9l4.1 5.4a2.75 2.75 0 0 0 2.2 1.1H19l-1.8-1.8 1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 16.4h-2.3a4.75 4.75 0 0 1-3.8-1.9L8.8 9.1A2.75 2.75 0 0 0 6.6 8H4V6Z"/><path d="M19 7.6h-2.3c-.86 0-1.67.41-2.18 1.1l-.93 1.23-1.25-1.65.58-.77A4.75 4.75 0 0 1 16.7 5.6H19L17.2 3.8l1.4-1.4 4.2 4.2-4.2 4.2-1.4-1.4L19 7.6Z" transform="translate(0 1.2)"/>'),
124
+ repeat: g('<path d="M7 7h10v2.5L21 6l-4-3.5V5H5v6h2V7Zm10 10H7v-2.5L3 18l4 3.5V19h12v-6h-2v4Z"/>'),
125
+ subtitles: g('<path d="M3 5h18v14H3V5Zm2 2v10h14V7H5Zm2 3h6v2H7v-2Zm8 0h2v2h-2v-2ZM7 14h2v2H7v-2Zm4 0h6v2h-6v-2Z"/>'),
126
+ list: g('<path d="M4 6h2v2H4V6Zm4 0h12v2H8V6ZM4 11h2v2H4v-2Zm4 0h12v2H8v-2ZM4 16h2v2H4v-2Zm4 0h12v2H8v-2Z"/>'),
127
+ next: g('<path d="M6 5.5v13c0 .77.84 1.25 1.5.85l9-6.5a1 1 0 0 0 0-1.7l-9-6.5c-.66-.4-1.5.08-1.5.85Z"/><rect x="17" y="5" width="2.5" height="14" rx="1"/>'),
128
+ previous: g('<path d="M18 5.5v13c0 .77-.84 1.25-1.5.85l-9-6.5a1 1 0 0 1 0-1.7l9-6.5c.66-.4 1.5.08 1.5.85Z"/><rect x="4.5" y="5" width="2.5" height="14" rx="1"/>'),
55
129
  // Thin circular-arrow ("rotate") icons — open center so the step number reads
56
130
  // clearly inside the ring (matches the reference skip ±N look).
57
131
  seekForward: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>',
58
132
  seekBack: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>',
59
- like: y('<path d="M9 21H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h4v11Zm2 0h7.1a2 2 0 0 0 2-1.6l1.3-7a2 2 0 0 0-2-2.4H14V5.5A2.5 2.5 0 0 0 11.5 3l-.5.1V10h-.9L11 21Z"/>'),
60
- dislike: y('<path d="M15 3h4a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-4V3Zm-2 0H5.9a2 2 0 0 0-2 1.6l-1.3 7a2 2 0 0 0 2 2.4H10v4.5A2.5 2.5 0 0 0 12.5 21l.5-.1V14h.9L13 3Z"/>'),
61
- addTo: y('<path d="M4 6h12v2H4V6Zm0 4h12v2H4v-2Zm0 4h8v2H4v-2Zm14 0v-4h2v4h4v2h-4v4h-2v-4h-4v-2h4Z"/>'),
62
- share: y('<path d="M18 8a3 3 0 1 0-2.83-4H15a3 3 0 0 0 .14 1.06L8.4 8.94a3 3 0 1 0 0 6.12l6.74 3.88A3 3 0 1 0 16 16.6l-6.74-3.88a3.03 3.03 0 0 0 0-1.44L16 7.4c.55.38 1.24.6 2 .6Z"/>'),
63
- report: y('<path d="M5 3h2v18H5V3Zm4 1h10l-2.5 4L19 12H9V4Z"/>'),
64
- more: y('<circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>'),
65
- close: y('<path d="m6.4 5 5.6 5.6L17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6L6.4 19 5 17.6 10.6 12 5 6.4 6.4 5Z"/>'),
133
+ like: g('<path d="M9 21H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h4v11Zm2 0h7.1a2 2 0 0 0 2-1.6l1.3-7a2 2 0 0 0-2-2.4H14V5.5A2.5 2.5 0 0 0 11.5 3l-.5.1V10h-.9L11 21Z"/>'),
134
+ dislike: g('<path d="M15 3h4a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-4V3Zm-2 0H5.9a2 2 0 0 0-2 1.6l-1.3 7a2 2 0 0 0 2 2.4H10v4.5A2.5 2.5 0 0 0 12.5 21l.5-.1V14h.9L13 3Z"/>'),
135
+ addTo: g('<path d="M4 6h12v2H4V6Zm0 4h12v2H4v-2Zm0 4h8v2H4v-2Zm14 0v-4h2v4h4v2h-4v4h-2v-4h-4v-2h4Z"/>'),
136
+ share: g('<path d="M18 8a3 3 0 1 0-2.83-4H15a3 3 0 0 0 .14 1.06L8.4 8.94a3 3 0 1 0 0 6.12l6.74 3.88A3 3 0 1 0 16 16.6l-6.74-3.88a3.03 3.03 0 0 0 0-1.44L16 7.4c.55.38 1.24.6 2 .6Z"/>'),
137
+ report: g('<path d="M5 3h2v18H5V3Zm4 1h10l-2.5 4L19 12H9V4Z"/>'),
138
+ more: g('<circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>'),
139
+ close: g('<path d="m6.4 5 5.6 5.6L17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6L6.4 19 5 17.6 10.6 12 5 6.4 6.4 5Z"/>'),
66
140
  // Generic "uploaded by a user" glyph (head + shoulders) for preview meta.
67
- user: y('<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"/>'),
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"/>'),
68
142
  // Generic "channel" glyph (play badge) for preview meta when a channel is set.
69
- channel: y('<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"/>')
70
- }, F = { en: H };
71
- function Nt(l, t) {
72
- F[l] = t;
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
+ }, V = { en: G };
145
+ function qt(r, t) {
146
+ V[r] = t;
73
147
  }
74
- function qt(l) {
75
- for (const [t, e] of Object.entries(l))
76
- e && (F[t] = e);
148
+ function Vt(r) {
149
+ for (const [t, e] of Object.entries(r))
150
+ e && (V[t] = e);
77
151
  }
78
- function nt(l) {
79
- return l && F[l] || H;
152
+ function at(r) {
153
+ return r && V[r] || G;
80
154
  }
81
- function Ft() {
82
- return Object.keys(F);
155
+ function Ot() {
156
+ return Object.keys(V);
83
157
  }
84
- function rt(l) {
85
- const t = [0.06, 0.24, 0.4, 0.24, 0.06], e = l.length;
86
- return l.map(
87
- (i, s) => t.reduce((n, r, a) => {
88
- const c = Math.min(e - 1, Math.max(0, s + a - 2));
89
- return n + r * l[c];
158
+ function lt(r) {
159
+ const t = [0.06, 0.24, 0.4, 0.24, 0.06], e = r.length;
160
+ return r.map(
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];
90
164
  }, 0)
91
165
  );
92
166
  }
93
- function ot(l, t) {
94
- if (l.length === 0) return 0;
95
- const e = Math.min(l.length - 1, Math.max(0, Math.round((l.length - 1) * t)));
96
- return l[e];
167
+ function ht(r, t) {
168
+ if (r.length === 0) return 0;
169
+ const e = Math.min(r.length - 1, Math.max(0, Math.round((r.length - 1) * t)));
170
+ return r[e];
97
171
  }
98
- function K(l, t) {
99
- if (l.length === 0 || l.every((n) => n <= 0)) return [];
100
- const e = rt(l), i = t === "retention" ? ot([...e].sort((n, r) => n - r), 0.95) : Math.max(...e);
172
+ function Y(r, t) {
173
+ if (r.length === 0 || r.every((n) => n <= 0)) return [];
174
+ const e = lt(r), i = t === "retention" ? ht([...e].sort((n, o) => n - o), 0.95) : Math.max(...e);
101
175
  if (i <= 0) return [];
102
176
  const s = 0.08;
103
177
  return e.map((n) => s + (1 - s) * Math.min(1, Math.max(0, n / i)));
104
178
  }
105
- function at(l, t, e = 100) {
106
- if (l.length === 0 || !Number.isFinite(t) || t <= 0) return [];
179
+ function ct(r, t, e = 100) {
180
+ if (r.length === 0 || !Number.isFinite(t) || t <= 0) return [];
107
181
  const i = new Array(e).fill(0);
108
182
  let s = !1;
109
- for (const n of l) {
183
+ for (const n of r) {
110
184
  if (!Number.isFinite(n.time) || n.time < 0 || n.time > t) continue;
111
- const r = Math.max(0, n.value);
112
- r !== 0 && (i[Math.min(e - 1, Math.floor(n.time / t * e))] += r, 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);
113
187
  }
114
- return s ? K(i, "peaks") : [];
188
+ return s ? Y(i, "peaks") : [];
115
189
  }
116
- function lt(l, t = "peaks", e = 200) {
117
- let i = l.map((s) => Number.isFinite(s) ? Math.max(0, s) : 0);
190
+ function dt(r, t = "peaks", e = 200) {
191
+ let i = r.map((s) => Number.isFinite(s) ? Math.max(0, s) : 0);
118
192
  if (i.length > e) {
119
193
  const s = new Array(e).fill(0), n = new Array(e).fill(0);
120
- for (let r = 0; r < i.length; r++) {
121
- const a = Math.min(e - 1, Math.floor(r / i.length * e));
122
- s[a] += i[r], n[a]++;
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]++;
123
197
  }
124
- i = s.map((r, a) => n[a] > 0 ? r / n[a] : 0);
198
+ i = s.map((o, l) => n[l] > 0 ? o / n[l] : 0);
125
199
  }
126
- return K(i, t);
200
+ return Y(i, t);
127
201
  }
128
- function ht(l, t = 1, e = 1e3, i = 100) {
129
- const s = l.length;
202
+ function ut(r, t = 1, e = 1e3, i = 100) {
203
+ const s = r.length;
130
204
  if (s === 0) return "";
131
- const n = e / (s - 1 || 1), r = Math.max(0, t) / 6, a = (p) => {
132
- const v = Math.min(s - 1, Math.max(0, p));
133
- return [v * n, i - l[v] * i];
134
- }, [, c] = a(0);
135
- let h = `M 0 ${i} L 0 ${c.toFixed(1)}`;
136
- for (let p = 0; p < s - 1; p++) {
137
- const [v, u] = a(p - 1), [m, f] = a(p), [b, d] = a(p + 1), [k, C] = a(p + 2), P = m + (b - v) * r, V = Math.min(i, Math.max(0, f + (d - u) * r)), M = b - (k - m) * r, A = Math.min(i, Math.max(0, d - (C - f) * r));
138
- h += ` C ${P.toFixed(1)} ${V.toFixed(1)} ${M.toFixed(1)} ${A.toFixed(1)} ${b.toFixed(1)} ${d.toFixed(1)}`;
139
- }
140
- return h += ` L ${e} ${i} Z`, h;
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
+ let c = `M 0 ${i} L 0 ${h.toFixed(1)}`;
210
+ for (let u = 0; u < s - 1; u++) {
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
+ }
214
+ return c += ` L ${e} ${i} Z`, c;
141
215
  }
142
- async function ct(l, t) {
143
- if (l.src)
216
+ async function pt(r, t) {
217
+ if (r.src)
144
218
  return {
145
- roll: l.roll,
146
- mediaUrl: l.src,
147
- clickThrough: l.clickUrl,
219
+ roll: r.roll,
220
+ mediaUrl: r.src,
221
+ clickThrough: r.clickUrl,
148
222
  impressions: [],
149
223
  tracking: {}
150
224
  };
151
- if (!l.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
152
- return X(l, l.vastTag, t, 0, { impressions: [], tracking: {} });
225
+ if (!r.vastTag) throw new Error('Ad roll has neither "vastTag" nor "src"');
226
+ return tt(r, r.vastTag, t, 0, { impressions: [], tracking: {} });
153
227
  }
154
- async function X(l, t, e, i, s) {
228
+ async function tt(r, t, e, i, s) {
155
229
  if (i > e.maxWrapperDepth) throw new Error("VAST wrapper depth limit exceeded");
156
- const n = new AbortController(), r = setTimeout(() => n.abort(), e.requestTimeout);
157
- let a;
230
+ const n = new AbortController(), o = setTimeout(() => n.abort(), e.requestTimeout);
231
+ let l;
158
232
  try {
159
- const f = await fetch(t, { signal: n.signal, credentials: "omit" });
160
- if (!f.ok) throw new Error(`VAST request failed (${f.status})`);
161
- a = 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();
162
236
  } finally {
163
- clearTimeout(r);
164
- }
165
- const c = new DOMParser().parseFromString(a, "text/xml");
166
- if (c.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
167
- const h = c.querySelector("VAST > Ad");
168
- if (!h) throw new Error("VAST response contains no ads");
169
- dt(h, s);
170
- const p = h.querySelector(":scope > Wrapper");
171
- if (p) {
172
- const f = L(p.querySelector("VASTAdTagURI"));
173
- if (!f) throw new Error("VAST wrapper without VASTAdTagURI");
174
- return X(l, f, e, i + 1, s);
175
- }
176
- const v = h.querySelector(":scope > InLine");
177
- if (!v) throw new Error("VAST ad has neither InLine nor Wrapper");
178
- const u = v.querySelector("Creatives > Creative > Linear");
179
- if (!u) throw new Error("VAST ad has no Linear creative");
180
- const m = ut(u);
237
+ clearTimeout(o);
238
+ }
239
+ const h = new DOMParser().parseFromString(l, "text/xml");
240
+ if (h.querySelector("parsererror")) throw new Error("VAST response is not valid XML");
241
+ const c = h.querySelector("VAST > Ad");
242
+ if (!c) throw new Error("VAST response contains no ads");
243
+ mt(c, s);
244
+ const u = c.querySelector(":scope > Wrapper");
245
+ if (u) {
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
+ }
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
+ if (!p) throw new Error("VAST ad has no Linear creative");
254
+ const m = ft(p);
181
255
  if (!m) throw new Error("VAST ad has no playable MediaFile");
182
256
  return {
183
- roll: l.roll,
257
+ roll: r.roll,
184
258
  mediaUrl: m.url,
185
259
  mediaType: m.type,
186
- clickThrough: L(u.querySelector("VideoClicks > ClickThrough")) ?? l.clickUrl,
187
- duration: O(L(u.querySelector(":scope > Duration"))),
188
- skipOffset: pt(
189
- u.getAttribute("skipoffset"),
190
- O(L(u.querySelector(":scope > Duration")))
260
+ clickThrough: S(p.querySelector("VideoClicks > ClickThrough")) ?? r.clickUrl,
261
+ duration: D(S(p.querySelector(":scope > Duration"))),
262
+ skipOffset: vt(
263
+ p.getAttribute("skipoffset"),
264
+ D(S(p.querySelector(":scope > Duration")))
191
265
  ),
192
266
  impressions: s.impressions,
193
267
  tracking: s.tracking,
194
- adTitle: L(v.querySelector(":scope > AdTitle")) ?? void 0
268
+ adTitle: S(f.querySelector(":scope > AdTitle")) ?? void 0
195
269
  };
196
270
  }
197
- function dt(l, t) {
271
+ function mt(r, t) {
198
272
  var e, i;
199
- for (const s of l.querySelectorAll("Impression")) {
200
- const n = L(s);
273
+ for (const s of r.querySelectorAll("Impression")) {
274
+ const n = S(s);
201
275
  n && t.impressions.push(n);
202
276
  }
203
- for (const s of l.querySelectorAll("Linear > TrackingEvents > Tracking")) {
204
- const n = s.getAttribute("event"), r = L(s);
205
- !n || !r || ["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "skip", "pause", "resume"].includes(n) && ((e = t.tracking)[n] ?? (e[n] = [])).push(r);
277
+ for (const s of r.querySelectorAll("Linear > TrackingEvents > Tracking")) {
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);
206
280
  }
207
- for (const s of l.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
208
- const n = L(s);
281
+ for (const s of r.querySelectorAll("Linear > VideoClicks > ClickTracking")) {
282
+ const n = S(s);
209
283
  n && ((i = t.tracking).click ?? (i.click = [])).push(n);
210
284
  }
211
285
  }
212
- function ut(l) {
213
- const e = [...l.querySelectorAll("MediaFiles > MediaFile")].map((r) => ({
214
- url: L(r) ?? "",
215
- type: r.getAttribute("type") ?? void 0,
216
- delivery: r.getAttribute("delivery") ?? "",
217
- bitrate: Number(r.getAttribute("bitrate") ?? 0),
218
- apiFramework: r.getAttribute("apiFramework") ?? ""
219
- })).filter((r) => r.url && r.apiFramework.toUpperCase() !== "VPAID").filter(
220
- (r) => !r.type || /(video\/(mp4|webm|ogg)|application\/(x-mpegurl|vnd\.apple\.mpegurl))/i.test(r.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)
221
295
  );
222
296
  if (e.length === 0) return null;
223
- e.sort((r, a) => r.bitrate - a.bitrate);
224
- const i = e.filter((r) => r.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)];
225
299
  return { url: n.url, type: n.type };
226
300
  }
227
- function O(l) {
228
- if (!l) return;
229
- const t = l.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
301
+ function D(r) {
302
+ if (!r) return;
303
+ const t = r.trim().match(/^(?:(\d+):)?(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?$/);
230
304
  if (t)
231
305
  return (t[1] ? Number(t[1]) * 3600 : 0) + Number(t[2]) * 60 + Number(t[3]) + (t[4] ? Number(t[4].padEnd(3, "0")) / 1e3 : 0);
232
306
  }
233
- function pt(l, t) {
234
- if (!l) return;
235
- const e = l.trim().match(/^(\d+(?:\.\d+)?)%$/);
236
- return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : O(l);
307
+ function vt(r, t) {
308
+ if (!r) return;
309
+ const e = r.trim().match(/^(\d+(?:\.\d+)?)%$/);
310
+ return e ? t !== void 0 ? Number(e[1]) / 100 * t : void 0 : D(r);
237
311
  }
238
- function N(l) {
239
- if (l)
240
- for (const t of l)
312
+ function F(r) {
313
+ if (r)
314
+ for (const t of r)
241
315
  try {
242
316
  new Image().src = t;
243
317
  } catch {
244
318
  }
245
319
  }
246
- function L(l) {
247
- return l?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
320
+ function S(r) {
321
+ return r?.textContent?.trim().replace(/^<!\[CDATA\[|\]\]>$/g, "").trim() || null;
248
322
  }
249
- class mt {
323
+ class gt {
250
324
  constructor(t, e) {
251
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 = {
252
326
  skipDelay: 5,
@@ -265,7 +339,7 @@ class mt {
265
339
  */
266
340
  ensureAdVideo() {
267
341
  if (!this.adVideo) {
268
- this.adVideo = o("video", "imp-ad__video", { playsinline: "" });
342
+ this.adVideo = a("video", "imp-ad__video", { playsinline: "" });
269
343
  try {
270
344
  this.adVideo.load();
271
345
  } catch {
@@ -313,11 +387,11 @@ class mt {
313
387
  for (const n of t) {
314
388
  this.playedRolls.add(n);
315
389
  try {
316
- const r = await ct(n, this.opts);
317
- await this.playAd(r);
318
- } catch (r) {
319
- const a = r instanceof Error ? r : new Error(String(r));
320
- this.host.emitter.emit("aderror", { roll: n, error: a });
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 });
321
395
  }
322
396
  if (this.destroyed) return;
323
397
  }
@@ -330,69 +404,69 @@ class mt {
330
404
  }
331
405
  playAd(t) {
332
406
  return new Promise((e) => {
333
- const { labels: i } = this.host, s = o("div", "imp-ad"), n = this.ensureAdVideo(), r = new AbortController(), a = r.signal;
407
+ const { labels: i } = this.host, s = a("div", "imp-ad"), n = this.ensureAdVideo(), o = new AbortController(), l = o.signal;
334
408
  n.src = t.mediaUrl, n.muted = this.host.contentVideo.muted, n.volume = this.host.contentVideo.volume;
335
- const c = o("div", "imp-spinner imp-ad__spinner"), h = o("div", "imp-ad__hud"), p = o("span", "imp-ad__badge");
336
- p.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
337
- const v = o("span", "imp-ad__countdown");
338
- h.append(p, v);
339
- const u = o("div", "imp-ad__actions");
409
+ const h = a("div", "imp-spinner imp-ad__spinner"), c = a("div", "imp-ad__hud"), u = a("span", "imp-ad__badge");
410
+ u.textContent = t.adTitle ? `${i.adLabel} · ${t.adTitle}` : i.adLabel;
411
+ const f = a("span", "imp-ad__countdown");
412
+ c.append(u, f);
413
+ const p = a("div", "imp-ad__actions");
340
414
  let m = null;
341
- t.clickThrough && (m = o("button", "imp-ad__visit", { type: "button" }), m.textContent = i.visitAdvertiser, u.append(m));
342
- const f = o("button", "imp-ad__skip", { type: "button" });
343
- f.hidden = !0, u.append(f), s.append(n, c, h, u), this.host.container.append(s), this.layer = s;
344
- const b = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), k = (w) => {
345
- d.has(w) || (d.add(w), N(t.tracking[w]));
415
+ t.clickThrough && (m = a("button", "imp-ad__visit", { type: "button" }), m.textContent = i.visitAdvertiser, p.append(m));
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
+ const y = t.skipOffset ?? this.opts.skipDelay, d = /* @__PURE__ */ new Set(), k = (w) => {
419
+ d.has(w) || (d.add(w), F(t.tracking[w]));
346
420
  };
347
- let C = Date.now(), P = -1;
348
- const V = setInterval(() => {
421
+ let C = Date.now(), A = -1;
422
+ const O = setInterval(() => {
349
423
  if (n.paused) {
350
424
  C = Date.now();
351
425
  return;
352
426
  }
353
- if (n.currentTime !== P) {
354
- P = n.currentTime, C = Date.now();
427
+ if (n.currentTime !== A) {
428
+ A = n.currentTime, C = Date.now();
355
429
  return;
356
430
  }
357
431
  Date.now() - C >= this.opts.mediaTimeout && (this.host.emitter.emit("aderror", {
358
432
  roll: { roll: t.roll },
359
433
  error: new Error(`Ad media stalled for ${this.opts.mediaTimeout} ms — skipping`)
360
- }), M());
361
- }, 500), M = () => {
362
- clearInterval(V), r.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
363
- }, A = (w) => {
364
- w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }), M();
434
+ }), P());
435
+ }, 500), P = () => {
436
+ clearInterval(O), o.abort(), n.pause(), n.removeAttribute("src"), n.load(), s.remove(), this.layer = null, e();
437
+ }, R = (w) => {
438
+ w ? (k("skip"), this.host.emitter.emit("adskip", { ad: t })) : k("complete"), this.host.emitter.emit("adend", { ad: t }), P();
365
439
  };
366
440
  n.addEventListener("playing", () => {
367
- N(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
368
- }, { once: !0, signal: a }), n.addEventListener("playing", () => {
369
- c.hidden = !0;
370
- }, { signal: a }), n.addEventListener("waiting", () => {
371
- c.hidden = !1;
372
- }, { signal: a }), n.addEventListener("timeupdate", () => {
373
- const w = n.currentTime, T = n.duration;
374
- if (Number.isFinite(T) && T > 0 && (v.textContent = _(Math.max(0, T - w)), w / T >= 0.25 && k("firstQuartile"), w / T >= 0.5 && k("midpoint"), w / T >= 0.75 && k("thirdQuartile")), b >= 0) {
375
- const W = Math.ceil(b - w);
376
- W > 0 ? (f.hidden = !1, f.disabled = !0, f.textContent = `${i.skipAdIn} ${W}`) : (f.hidden = !1, f.disabled = !1, f.textContent = i.skipAd);
441
+ F(t.impressions), k("start"), this.host.emitter.emit("adstart", { ad: t });
442
+ }, { once: !0, signal: l }), n.addEventListener("playing", () => {
443
+ h.hidden = !0;
444
+ }, { signal: l }), n.addEventListener("waiting", () => {
445
+ h.hidden = !1;
446
+ }, { signal: l }), n.addEventListener("timeupdate", () => {
447
+ const w = n.currentTime, B = n.duration;
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);
377
451
  }
378
- }, { signal: a }), n.addEventListener("ended", () => A(!1), { signal: a }), n.addEventListener("error", () => {
452
+ }, { signal: l }), n.addEventListener("ended", () => R(!1), { signal: l }), n.addEventListener("error", () => {
379
453
  this.host.emitter.emit("aderror", {
380
454
  roll: { roll: t.roll },
381
455
  error: new Error("Ad media failed to play")
382
- }), M();
383
- }, { signal: a }), f.addEventListener("click", () => A(!0));
384
- const D = () => {
456
+ }), P();
457
+ }, { signal: l }), v.addEventListener("click", () => R(!0));
458
+ const z = () => {
385
459
  t.clickThrough && (k("click"), this.host.emitter.emit("adclick", { ad: t }), window.open(t.clickThrough, "_blank", "noopener"), n.pause());
386
460
  };
387
- n.addEventListener("click", D, { signal: a }), m?.addEventListener("click", D);
388
- let G = !1, R = !1;
461
+ n.addEventListener("click", z, { signal: l }), m?.addEventListener("click", z);
462
+ let Q = !1, N = !1;
389
463
  n.addEventListener("playing", () => {
390
- G = !0;
391
- }, { once: !0, signal: a }), n.addEventListener("pause", () => {
392
- n.ended || !s.isConnected || (s.classList.add("imp-ad--paused"), G && !R && (R = !0, N(t.tracking.pause), this.host.emitter.emit("adpause", { ad: t })));
393
- }, { signal: a }), n.addEventListener("play", () => {
394
- s.classList.remove("imp-ad--paused"), R && (R = !1, N(t.tracking.resume), this.host.emitter.emit("adresume", { ad: t }));
395
- }, { signal: a }), 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) => {
396
470
  (w.target === s || s.classList.contains("imp-ad--paused")) && n.paused && n.play().catch(() => {
397
471
  });
398
472
  }), n.play().catch(() => {
@@ -408,50 +482,50 @@ class mt {
408
482
  this.destroyed = !0, this.adVideo?.pause(), this.layer?.remove(), this.layer = null, this.adVideo = null;
409
483
  }
410
484
  }
411
- function z(l, t) {
412
- const e = [...l].sort((s, n) => s.start - n.start), i = [];
485
+ function j(r, t) {
486
+ const e = [...r].sort((s, n) => s.start - n.start), i = [];
413
487
  for (let s = 0; s < e.length; s++) {
414
488
  const n = Math.max(0, e[s].start);
415
489
  if (Number.isFinite(t) && n >= t) continue;
416
- let r = e[s].end ?? e[s + 1]?.start ?? t;
417
- Number.isFinite(t) && (r = Math.min(r, t)), !(r <= n) && i.push({ start: n, end: r, 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 });
418
492
  }
419
493
  return i;
420
494
  }
421
- async function vt(l) {
422
- const t = await fetch(l);
495
+ async function yt(r) {
496
+ const t = await fetch(r);
423
497
  if (!t.ok) throw new Error(`Failed to load chapters VTT (${t.status})`);
424
498
  const e = await t.text();
425
- return U(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 }));
426
500
  }
427
- function J(l, t) {
428
- for (const e of l)
501
+ function et(r, t) {
502
+ for (const e of r)
429
503
  if (t >= e.start && t < e.end) return e;
430
504
  return null;
431
505
  }
432
- function ft(l, t) {
433
- return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(l);
506
+ function bt(r, t) {
507
+ return t ? /application\/(x-mpegurl|vnd\.apple\.mpegurl)/i.test(t) : /\.m3u8(\?|#|$)/i.test(r);
434
508
  }
435
- let B;
436
- async function yt() {
437
- if (B !== void 0) return B;
438
- const l = globalThis.Hls;
439
- if (l)
440
- return B = l, B;
509
+ let E;
510
+ async function kt() {
511
+ if (E !== void 0) return E;
512
+ const r = globalThis.Hls;
513
+ if (r)
514
+ return E = r, E;
441
515
  try {
442
- return B = (await import("hls.js/light")).default, B;
516
+ return E = (await import("hls.js/light")).default, E;
443
517
  } catch {
444
518
  return null;
445
519
  }
446
520
  }
447
- async function gt(l, t, e, i) {
448
- if (ft(t, e)) {
449
- const s = l.canPlayType("application/vnd.apple.mpegurl"), n = s ? null : await yt();
450
- return n && n.isSupported() ? bt(n, l, t, i) : s ? (l.src = t, $(l)) : (i.onError("HLS is not supported in this browser and hls.js could not be loaded."), $(l));
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));
451
525
  }
452
- return l.src = t, $(l);
526
+ return r.src = t, Z(r);
453
527
  }
454
- function $(l) {
528
+ function Z(r) {
455
529
  return {
456
530
  kind: "native",
457
531
  levels: [],
@@ -459,58 +533,58 @@ function $(l) {
459
533
  setLevel() {
460
534
  },
461
535
  destroy() {
462
- l.removeAttribute("src"), l.load();
536
+ r.removeAttribute("src"), r.load();
463
537
  }
464
538
  };
465
539
  }
466
- function bt(l, t, e, i) {
467
- const s = new l({ enableWorker: !0 }), n = {
540
+ function xt(r, t, e, i) {
541
+ const s = new r({ enableWorker: !0 }), n = {
468
542
  kind: "hls",
469
543
  levels: [],
470
544
  selected: -1,
471
- setLevel(h) {
472
- n.selected = h, s.currentLevel = h;
545
+ setLevel(c) {
546
+ n.selected = c, s.currentLevel = c;
473
547
  },
474
548
  destroy() {
475
549
  s.destroy(), t.removeAttribute("src"), t.load();
476
550
  }
477
551
  };
478
- s.on(l.Events.MANIFEST_PARSED, () => {
479
- n.levels = s.levels.map((h, p) => ({
480
- index: p,
481
- label: h.height ? `${h.height}p` : `${Math.round(h.bitrate / 1e3)} kbps`
552
+ s.on(r.Events.MANIFEST_PARSED, () => {
553
+ n.levels = s.levels.map((c, u) => ({
554
+ index: u,
555
+ label: c.height ? `${c.height}p` : `${Math.round(c.bitrate / 1e3)} kbps`
482
556
  })).reverse(), i.onLevels(n.levels);
483
- }), s.on(l.Events.LEVEL_SWITCHED, (h, p) => {
484
- const v = s.levels[p.level];
485
- v && i.onLevelSwitch(v.height ? `${v.height}p` : `${Math.round(v.bitrate / 1e3)} kbps`);
557
+ }), s.on(r.Events.LEVEL_SWITCHED, (c, u) => {
558
+ const f = s.levels[u.level];
559
+ f && i.onLevelSwitch(f.height ? `${f.height}p` : `${Math.round(f.bitrate / 1e3)} kbps`);
486
560
  });
487
- let r = 0, a = 0, c = !1;
488
- return s.on(l.Events.FRAG_BUFFERED, () => {
489
- a = 0;
490
- }), s.on(l.Events.ERROR, (h, p) => {
491
- if (p.fatal)
492
- switch (p.type) {
493
- case l.ErrorTypes.NETWORK_ERROR:
494
- a < 3 ? (a++, s.startLoad()) : (i.onError(`HLS network error: ${p.details}`, p), s.destroy());
561
+ let o = 0, l = 0, h = !1;
562
+ return s.on(r.Events.FRAG_BUFFERED, () => {
563
+ l = 0;
564
+ }), s.on(r.Events.ERROR, (c, u) => {
565
+ if (u.fatal)
566
+ switch (u.type) {
567
+ case r.ErrorTypes.NETWORK_ERROR:
568
+ l < 3 ? (l++, s.startLoad()) : (i.onError(`HLS network error: ${u.details}`, u), s.destroy());
495
569
  break;
496
- case l.ErrorTypes.MEDIA_ERROR:
497
- r < 3 ? (r++, s.recoverMediaError()) : (i.onError(`HLS media error: ${p.details}`, p), s.destroy());
570
+ case r.ErrorTypes.MEDIA_ERROR:
571
+ o < 3 ? (o++, s.recoverMediaError()) : (i.onError(`HLS media error: ${u.details}`, u), s.destroy());
498
572
  break;
499
573
  default:
500
- if (c)
501
- i.onError(`HLS fatal error: ${p.details}`, p), s.destroy();
574
+ if (h)
575
+ i.onError(`HLS fatal error: ${u.details}`, u), s.destroy();
502
576
  else {
503
- c = !0;
577
+ h = !0;
504
578
  try {
505
579
  s.loadSource(e), s.startLoad();
506
580
  } catch {
507
- i.onError(`HLS fatal error: ${p.details}`, p), s.destroy();
581
+ i.onError(`HLS fatal error: ${u.details}`, u), s.destroy();
508
582
  }
509
583
  }
510
584
  }
511
585
  }), s.loadSource(e), s.attachMedia(t), n;
512
586
  }
513
- class Z {
587
+ class W {
514
588
  constructor(t) {
515
589
  this.cues = t;
516
590
  }
@@ -518,17 +592,17 @@ class Z {
518
592
  const e = await fetch(t);
519
593
  if (!e.ok) throw new Error(`Failed to load thumbnails VTT (${e.status})`);
520
594
  const i = await e.text(), s = [];
521
- for (const n of U(i)) {
522
- const [r, a] = n.text.trim().split("#");
523
- if (!r) continue;
524
- const c = {
595
+ for (const n of J(i)) {
596
+ const [o, l] = n.text.trim().split("#");
597
+ if (!o) continue;
598
+ const h = {
525
599
  start: n.start,
526
600
  end: n.end,
527
- src: et(r, t)
528
- }, h = a?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
529
- h && (c.xywh = { x: Number(h[1]), y: Number(h[2]), w: Number(h[3]), h: Number(h[4]) }), s.push(c);
601
+ src: nt(o, t)
602
+ }, c = l?.match(/xywh=(\d+),(\d+),(\d+),(\d+)/);
603
+ c && (h.xywh = { x: Number(c[1]), y: Number(c[2]), w: Number(c[3]), h: Number(c[4]) }), s.push(h);
530
604
  }
531
- return s.sort((n, r) => n.start - r.start), new Z(s);
605
+ return s.sort((n, o) => n.start - o.start), new W(s);
532
606
  }
533
607
  cueAt(t) {
534
608
  let e = 0, i = this.cues.length - 1;
@@ -541,10 +615,10 @@ class Z {
541
615
  return null;
542
616
  }
543
617
  }
544
- const kt = '<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>', wt = '<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>';
545
- class E {
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
+ class M {
546
620
  constructor(t) {
547
- this.anchor = t, this.outsideListener = null, this.escListener = null, this.root = o("div", "imp-menu"), this.root.hidden = !0, this.backdrop = o("div", "imp-menu__backdrop"), this.backdrop.hidden = !0, this.backdrop.addEventListener("pointerdown", (e) => {
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) => {
548
622
  e.preventDefault(), this.close();
549
623
  });
550
624
  }
@@ -569,57 +643,57 @@ class E {
569
643
  }
570
644
  renderSettingsRoot(t) {
571
645
  this.root.textContent = "";
572
- const e = o("div", "imp-menu__section");
646
+ const e = a("div", "imp-menu__section");
573
647
  for (const i of t) {
574
648
  if (i.toggle) {
575
649
  e.append(this.buildToggleRow(i, i.toggle));
576
650
  continue;
577
651
  }
578
- const s = o("button", "imp-menu__item imp-menu__row", { type: "button" }), n = o("span", "imp-menu__label");
652
+ const s = a("button", "imp-menu__item imp-menu__row", { type: "button" }), n = a("span", "imp-menu__label");
579
653
  n.textContent = i.label;
580
- const r = o("span", "imp-menu__value");
581
- r.textContent = i.value ?? "";
582
- const a = o("span", "imp-menu__chevron");
583
- a.innerHTML = kt, s.append(n, r, a), 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);
584
658
  }
585
659
  this.root.append(e);
586
660
  }
587
661
  /** Toggle row: label + an on/off switch. Stays in the menu (no close). */
588
662
  buildToggleRow(t, e) {
589
- const i = o("button", "imp-menu__item imp-menu__row imp-menu__toggle", {
663
+ const i = a("button", "imp-menu__item imp-menu__row imp-menu__toggle", {
590
664
  type: "button",
591
665
  role: "switch",
592
666
  "aria-checked": String(e.value)
593
- }), s = o("span", "imp-menu__label");
667
+ }), s = a("span", "imp-menu__label");
594
668
  s.textContent = t.label;
595
- const n = o("span", "imp-switch");
596
- return n.append(o("span", "imp-switch__knob")), i.classList.toggle("imp-menu__toggle--on", e.value), i.append(s, n), i.addEventListener("click", () => {
597
- const r = i.getAttribute("aria-checked") !== "true";
598
- i.setAttribute("aria-checked", String(r)), i.classList.toggle("imp-menu__toggle--on", r), e.onChange(r);
669
+ const n = a("span", "imp-switch");
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 o = i.getAttribute("aria-checked") !== "true";
672
+ i.setAttribute("aria-checked", String(o)), i.classList.toggle("imp-menu__toggle--on", o), e.onChange(o);
599
673
  }), i;
600
674
  }
601
675
  renderSettingsDetail(t, e) {
602
676
  if (!e.section) return;
603
677
  this.root.textContent = "";
604
- const i = o("button", "imp-menu__item imp-menu__back", { type: "button" }), s = o("span", "imp-menu__chevron");
605
- s.innerHTML = wt;
606
- const n = o("span", "imp-menu__label");
678
+ const i = a("button", "imp-menu__item imp-menu__back", { type: "button" }), s = a("span", "imp-menu__chevron");
679
+ s.innerHTML = St;
680
+ const n = a("span", "imp-menu__label");
607
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;
608
682
  }
609
683
  /** Build one option block (radio items) from a section. */
610
684
  renderSection(t) {
611
- const e = o("div", "imp-menu__section");
685
+ const e = a("div", "imp-menu__section");
612
686
  if (t.title) {
613
- const i = o("div", "imp-menu__title");
687
+ const i = a("div", "imp-menu__title");
614
688
  i.textContent = t.title, e.append(i);
615
689
  }
616
690
  for (const i of t.items) {
617
- const s = o("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
691
+ const s = a("button", "imp-menu__item", { type: "button", role: "menuitemradio" });
618
692
  if (s.setAttribute("aria-checked", String(i.active)), i.active && s.classList.add("imp-menu__item--active"), i.icon) {
619
- const r = o("span", "imp-menu__icon");
620
- q(r, i.icon), s.append(r);
693
+ const o = a("span", "imp-menu__icon");
694
+ L(o, i.icon), s.append(o);
621
695
  }
622
- const n = o("span", "imp-menu__label");
696
+ const n = a("span", "imp-menu__label");
623
697
  n.textContent = i.label, s.append(n), s.addEventListener("click", () => {
624
698
  t.onSelect(i.value), this.close();
625
699
  }), e.append(s);
@@ -645,9 +719,9 @@ class E {
645
719
  this.close(), this.backdrop.remove(), this.root.remove();
646
720
  }
647
721
  }
648
- class xt {
722
+ class Lt {
649
723
  constructor(t, e = "Seek") {
650
- this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root = o("div", "imp-progress", { role: "slider", "aria-label": e, tabindex: "-1" }), this.buffered = o("div", "imp-progress__buffered"), this.track = o("div", "imp-progress__track"), this.handle = o("div", "imp-progress__handle"), this.tooltipThumb = o("div", "imp-progress__thumb"), this.tooltipChapter = o("div", "imp-progress__tooltip-chapter"), this.tooltipTime = o("div", "imp-progress__tooltip-time"), this.tooltipCaption = o("div", "imp-progress__caption"), this.tooltipCaption.append(this.tooltipChapter, this.tooltipTime), this.tooltip = o("div", "imp-progress__tooltip"), this.tooltip.append(this.tooltipThumb, this.tooltipCaption), this.heatmap = o("div", "imp-progress__heatmap"), this.heatmap.hidden = !0, this.root.append(this.heatmap, this.buffered, this.track, this.handle, this.tooltip), this.setChapters([]), this.bindPointer();
724
+ this.cb = t, this.segments = [], this.duration = 0, this.chapters = [], this.thumbnails = null, this.scrubbing = !1, this.root = a("div", "imp-progress", { role: "slider", "aria-label": e, tabindex: "-1" }), this.buffered = a("div", "imp-progress__buffered"), this.track = a("div", "imp-progress__track"), this.handle = a("div", "imp-progress__handle"), this.tooltipThumb = a("div", "imp-progress__thumb"), this.tooltipChapter = a("div", "imp-progress__tooltip-chapter"), this.tooltipTime = a("div", "imp-progress__tooltip-time"), this.tooltipCaption = a("div", "imp-progress__caption"), this.tooltipCaption.append(this.tooltipChapter, this.tooltipTime), this.tooltip = a("div", "imp-progress__tooltip"), this.tooltip.append(this.tooltipThumb, this.tooltipCaption), this.heatmap = a("div", "imp-progress__heatmap"), this.heatmap.hidden = !0, this.root.append(this.heatmap, this.buffered, this.track, this.handle, this.tooltip), this.setChapters([]), this.bindPointer();
651
725
  }
652
726
  /** Render the popularity curve (empty array hides it). */
653
727
  setHeatmap(t, e = 1) {
@@ -655,7 +729,7 @@ class xt {
655
729
  this.heatmap.hidden = !0, this.heatmap.textContent = "";
656
730
  return;
657
731
  }
658
- this.heatmap.innerHTML = `<svg viewBox="0 0 1000 100" preserveAspectRatio="none" aria-hidden="true"><path d="${ht(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;
659
733
  }
660
734
  setDuration(t) {
661
735
  this.duration = Number.isFinite(t) ? t : 0, this.root.classList.toggle("imp-progress--live", !Number.isFinite(t)), this.chapters.length === 0 && this.setChapters([]);
@@ -668,10 +742,10 @@ class xt {
668
742
  n.start > s && i.push({ start: s, end: n.start, title: "" }), i.push(n), s = n.end;
669
743
  this.duration > 0 && s < this.duration && i.push({ start: s, end: this.duration, title: "" });
670
744
  for (const n of i) {
671
- const r = o("div", "imp-progress__segment");
672
- r.style.flexGrow = String(Math.max(n.end - n.start, 0.01));
673
- const a = o("div", "imp-progress__fill");
674
- r.append(a), this.track.append(r), this.segments.push({ chapter: n, root: r, fill: a });
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 });
675
749
  }
676
750
  }
677
751
  setThumbnails(t) {
@@ -685,8 +759,8 @@ class xt {
685
759
  }
686
760
  render(t) {
687
761
  for (const { chapter: i, fill: s } of this.segments) {
688
- const n = i.end - i.start, r = n > 0 ? x((t - i.start) / n, 0, 1) : 0;
689
- s.style.transform = `scaleX(${r})`;
762
+ const n = i.end - i.start, o = n > 0 ? x((t - i.start) / n, 0, 1) : 0;
763
+ s.style.transform = `scaleX(${o})`;
690
764
  }
691
765
  const e = this.duration > 0 ? x(t / this.duration, 0, 1) : 0;
692
766
  this.handle.style.left = `${e * 100}%`;
@@ -709,40 +783,40 @@ class xt {
709
783
  showTooltip(t) {
710
784
  const e = this.timeFromEvent(t);
711
785
  this.tooltipTime.textContent = _(e);
712
- const i = J(this.chapters, e), s = !!i?.title;
786
+ const i = et(this.chapters, e), s = !!i?.title;
713
787
  this.tooltipChapter.textContent = i?.title ?? "", this.tooltipChapter.hidden = !s, this.tooltipCaption.classList.toggle("imp-progress__caption--time-only", !s);
714
788
  const n = this.thumbnails?.cueAt(e) ?? null;
715
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");
716
- const r = this.root.getBoundingClientRect(), a = x(t.clientX - r.left, 0, r.width), c = this.tooltip.offsetWidth / 2;
717
- this.tooltip.style.left = `${x(a, c, Math.max(c, r.width - c))}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`;
718
792
  }
719
793
  hideTooltip() {
720
794
  this.tooltip.classList.remove("imp-progress__tooltip--visible");
721
795
  }
722
796
  }
723
- class _t {
797
+ class Tt {
724
798
  constructor(t) {
725
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;
726
800
  const { labels: e, icons: i } = t, s = t.controlsOptions;
727
- this.root = o("div", "imp-controls"), this.progress = new xt({
801
+ this.root = a("div", "imp-controls"), this.progress = new Lt({
728
802
  onSeek: (d) => t.seek(d),
729
803
  onScrubStart: () => {
730
804
  t.scrubbing = !0, this.wasPlayingBeforeScrub = !t.paused, t.pause();
731
805
  },
732
806
  onScrubEnd: () => {
733
- t.scrubbing = !1, this.wasPlayingBeforeScrub && t.play(!0);
807
+ t.scrubbing = !1, this.wasPlayingBeforeScrub ? t.play(!0) : t.started || t.play();
734
808
  }
735
809
  }, t.labels.seek), s.progress && this.root.append(this.progress.root);
736
- const n = o("div", "imp-controls__row");
810
+ const n = a("div", "imp-controls__row");
737
811
  this.row = n, this.root.append(n);
738
- const r = o("div", "imp-controls__group"), a = o("div", "imp-controls__group");
739
- this.rightGroup = a;
740
- const c = o("div", "imp-controls__spacer");
741
- this.chapterLabel = o("div", "imp-controls__chapter"), n.append(r, c, a), c.append(this.chapterLabel);
742
- const h = typeof s.seekButtons == "object" ? s.seekButtons : {}, p = h.back ?? t.seekStep, v = h.forward ?? t.seekStep;
743
- if (this.seekLabelFn = h.label, s.playlist && t.hasPlaylist && !s.hidePrev && (this.prevBtn = g("imp-btn--prev", e.previous, i.previous), this.prevBtn.addEventListener("click", () => t.previous()), r.append(this.prevBtn)), s.seekButtons && (this.seekBackBtn = g("imp-btn--seek-back", `${e.seekBack} ${p}s`, i.seekBack), this.addStepBadge(this.seekBackBtn, p, "back"), this.seekBackBtn.addEventListener("click", () => t.skip(-p)), r.append(this.seekBackBtn)), s.play && (this.playBtn = g("imp-btn--play", e.play, i.play), this.playBtn.addEventListener("click", () => t.togglePlay()), r.append(this.playBtn)), s.seekButtons && (this.seekFwdBtn = g("imp-btn--seek-forward", `${e.seekForward} ${v}s`, i.seekForward), this.addStepBadge(this.seekFwdBtn, v, "forward"), this.seekFwdBtn.addEventListener("click", () => t.skip(v)), r.append(this.seekFwdBtn)), s.playlist && t.hasPlaylist && !s.hideNext && (this.nextBtn = g("imp-btn--next", e.next, i.next), this.nextBtn.addEventListener("click", () => t.next()), r.append(this.nextBtn)), s.volume) {
744
- const d = o("div", "imp-volume");
745
- this.muteBtn = g("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = o("input", "imp-volume__slider", {
812
+ const o = a("div", "imp-controls__group"), l = a("div", "imp-controls__group");
813
+ this.rightGroup = l;
814
+ const h = a("div", "imp-controls__spacer");
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
+ const d = a("div", "imp-volume");
819
+ this.muteBtn = b("imp-btn--mute", e.mute, i.volumeHigh), this.muteBtn.addEventListener("click", () => t.toggleMute()), this.volumeSlider = a("input", "imp-volume__slider", {
746
820
  type: "range",
747
821
  min: "0",
748
822
  max: "1",
@@ -750,11 +824,11 @@ class _t {
750
824
  "aria-label": e.volume
751
825
  }), this.volumeSlider.addEventListener("input", () => {
752
826
  t.setVolume(Number(this.volumeSlider.value));
753
- }), d.append(this.muteBtn, this.volumeSlider), r.append(d);
827
+ }), d.append(this.muteBtn, this.volumeSlider), o.append(d);
754
828
  }
755
- s.time && (this.timeLabel = o("div", "imp-controls__time"), this.timeCurrent = o("span", "imp-controls__time-current"), this.timeTotal = o("span", "imp-controls__time-total"), this.timeLabel.append(this.timeCurrent, this.timeTotal), this.liveBadge = o("span", "imp-controls__live"), this.liveBadge.textContent = e.live, this.liveBadge.hidden = !0, r.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();
756
830
  for (const d of (t.actionsOptions.custom ?? []).filter((k) => k.placement === "bar")) {
757
- const k = g(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
831
+ const k = b(`imp-btn--custom imp-btn--custom-${d.id}`, d.title, d.icon ?? i.more);
758
832
  k.addEventListener("click", () => t.emit("customaction", { id: d.id })), this.rightItems.set(`custom:${d.id}`, k), this.registerCollapsible({
759
833
  key: `custom:${d.id}`,
760
834
  el: k,
@@ -763,10 +837,10 @@ class _t {
763
837
  section: () => this.simpleSection(`custom:${d.id}`, d.title, d.icon ?? i.more, () => t.emit("customaction", { id: d.id }))
764
838
  });
765
839
  }
766
- const u = (d) => d === !1 ? "off" : d === "bar" ? "bar" : "gear", m = u(s.subtitles), f = u(s.quality), b = u(s.speed);
767
- if (this.gear = { speed: b === "gear", quality: f === "gear", subtitles: m === "gear" }, m === "bar") {
768
- this.subtitlesBtn = g("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new E(this.subtitlesBtn);
769
- const d = o("div", "imp-controls__menu-anchor");
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
+ this.subtitlesBtn = b("imp-btn--subtitles", e.subtitles, i.subtitles), this.subtitlesMenu = new M(this.subtitlesBtn);
843
+ const d = a("div", "imp-controls__menu-anchor");
770
844
  d.append(this.subtitlesBtn, this.subtitlesMenu.root), this.subtitlesBtn.addEventListener("click", () => this.toggleSubtitlesMenu()), this.rightItems.set("subtitles", d), this.registerCollapsible({
771
845
  key: "subtitles",
772
846
  el: d,
@@ -775,9 +849,9 @@ class _t {
775
849
  section: () => this.subtitlesSection()
776
850
  });
777
851
  }
778
- if (f === "bar") {
779
- this.qualityBtn = g("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new E(this.qualityBtn);
780
- const d = o("div", "imp-controls__menu-anchor");
852
+ if (v === "bar") {
853
+ this.qualityBtn = b("imp-btn--quality", e.quality, i.settings), this.qualityMenu = new M(this.qualityBtn);
854
+ const d = a("div", "imp-controls__menu-anchor");
781
855
  d.append(this.qualityBtn, this.qualityMenu.root), this.qualityBtn.addEventListener("click", () => this.toggleQualityMenu()), this.rightItems.set("quality", d), this.registerCollapsible({
782
856
  key: "quality",
783
857
  el: d,
@@ -786,9 +860,9 @@ class _t {
786
860
  section: () => this.qualitySection()
787
861
  });
788
862
  }
789
- if (b === "bar") {
790
- this.settingsBtn = g("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new E(this.settingsBtn);
791
- const d = o("div", "imp-controls__menu-anchor");
863
+ if (y === "bar") {
864
+ this.settingsBtn = b("imp-btn--speed", e.speed, i.speed), this.settingsMenu = new M(this.settingsBtn);
865
+ const d = a("div", "imp-controls__menu-anchor");
792
866
  d.append(this.settingsBtn, this.settingsMenu.root), this.settingsBtn.addEventListener("click", () => this.toggleSettingsMenu()), this.rightItems.set("speed", d), this.registerCollapsible({
793
867
  key: "speed",
794
868
  el: d,
@@ -797,25 +871,25 @@ class _t {
797
871
  section: () => this.speedSection()
798
872
  });
799
873
  }
800
- if (s.scenes && (this.scenesBtn = g("imp-btn--scenes", e.scenes, i.scenes), this.scenesBtn.addEventListener("click", () => t.toggleScenesPanel()), this.rightItems.set("scenes", this.scenesBtn), this.registerCollapsible({
874
+ if (s.scenes && (this.scenesBtn = b("imp-btn--scenes", e.scenes, i.scenes), this.scenesBtn.addEventListener("click", () => t.toggleScenesPanel()), this.rightItems.set("scenes", this.scenesBtn), this.registerCollapsible({
801
875
  key: "scenes",
802
876
  el: this.scenesBtn,
803
877
  priority: 25,
804
878
  available: () => t.chapterList.length > 0,
805
879
  section: () => this.simpleSection("scenes", e.scenes, i.scenes, () => t.toggleScenesPanel())
806
880
  })), s.sceneTypes !== !1) {
807
- this.sceneTypeBtn = o("button", "imp-btn imp-btn--scene-types", { type: "button" }), this.sceneTypeMenu = new E(this.sceneTypeBtn);
808
- const d = o("div", "imp-controls__menu-anchor");
881
+ this.sceneTypeBtn = a("button", "imp-btn imp-btn--scene-types", { type: "button" }), this.sceneTypeMenu = new M(this.sceneTypeBtn);
882
+ const d = a("div", "imp-controls__menu-anchor");
809
883
  d.append(this.sceneTypeBtn, this.sceneTypeMenu.root), this.sceneTypeBtn.addEventListener("click", () => this.toggleSceneTypeMenu()), this.rightItems.set("sceneTypes", d), this.refreshSceneTypeButton(), this.registerCollapsible({
810
884
  key: "sceneTypes",
811
885
  el: d,
812
- priority: 26,
886
+ priority: 68,
813
887
  available: () => t.sceneTypes.length > 0,
814
888
  section: () => this.sceneTypeSection()
815
889
  });
816
890
  }
817
891
  if (s.playlist && t.hasPlaylist && s.playlistButton !== !1) {
818
- const d = g("imp-btn--list", e.playlist, i.list);
892
+ const d = b("imp-btn--list", e.playlist, i.list);
819
893
  d.addEventListener("click", () => t.togglePlaylistPanel()), this.rightItems.set("playlist", d), this.registerCollapsible({
820
894
  key: "list",
821
895
  el: d,
@@ -825,7 +899,7 @@ class _t {
825
899
  });
826
900
  }
827
901
  if (s.pip && "requestPictureInPicture" in HTMLVideoElement.prototype) {
828
- const d = g("imp-btn--pip", e.pip, i.pip);
902
+ const d = b("imp-btn--pip", e.pip, i.pip);
829
903
  d.addEventListener("click", () => void t.togglePip()), this.rightItems.set("pip", d), this.registerCollapsible({
830
904
  key: "pip",
831
905
  el: d,
@@ -834,7 +908,7 @@ class _t {
834
908
  section: () => this.simpleSection("pip", e.pip, i.pip, () => void t.togglePip())
835
909
  });
836
910
  }
837
- if (s.fullscreen && (this.fullscreenBtn = g("imp-btn--fullscreen", e.fullscreen, i.fullscreen), this.fullscreenBtn.addEventListener("click", () => void t.toggleFullscreen()), this.rightItems.set("fullscreen", this.fullscreenBtn)), this.prevBtn && this.registerCollapsible({
911
+ if (s.fullscreen && (this.fullscreenBtn = b("imp-btn--fullscreen", e.fullscreen, i.fullscreen), this.fullscreenBtn.addEventListener("click", () => void t.toggleFullscreen()), this.rightItems.set("fullscreen", this.fullscreenBtn)), this.prevBtn && this.registerCollapsible({
838
912
  key: "prev",
839
913
  el: this.prevBtn,
840
914
  priority: 70,
@@ -853,7 +927,7 @@ class _t {
853
927
  el: d,
854
928
  priority: 80,
855
929
  available: () => Number.isFinite(t.duration) && t.duration > 0,
856
- section: () => this.simpleSection("seekBack", `${e.seekBack} ${p}s`, i.seekBack, () => t.skip(-p))
930
+ section: () => this.simpleSection("seekBack", `${e.seekBack} ${u}s`, i.seekBack, () => t.skip(-u))
857
931
  });
858
932
  }
859
933
  if (this.seekFwdBtn) {
@@ -863,20 +937,20 @@ class _t {
863
937
  el: d,
864
938
  priority: 82,
865
939
  available: () => Number.isFinite(t.duration) && t.duration > 0,
866
- 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))
867
941
  });
868
942
  }
869
- if (this.center = o("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) {
870
- const d = this.makeCenterButton("seek-back", `${e.seekBack} ${p}s`, i.seekBack);
871
- this.addStepBadge(d, p, "back"), d.addEventListener("click", () => t.skip(-p)), this.center.append(d);
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) {
944
+ const d = this.makeCenterButton("seek-back", `${e.seekBack} ${u}s`, i.seekBack);
945
+ this.addStepBadge(d, u, "back"), d.addEventListener("click", () => t.skip(-u)), this.center.append(d);
872
946
  }
873
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) {
874
- const d = this.makeCenterButton("seek-forward", `${e.seekForward} ${v}s`, i.seekForward);
875
- 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);
876
950
  }
877
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) {
878
- this.gearBtn = g("imp-btn--settings", e.settings, i.settings), this.gearMenu = new E(this.gearBtn);
879
- const d = o("div", "imp-controls__menu-anchor");
952
+ this.gearBtn = b("imp-btn--settings", e.settings, i.settings), this.gearMenu = new M(this.gearBtn);
953
+ const d = a("div", "imp-controls__menu-anchor");
880
954
  d.append(this.gearBtn, this.gearMenu.root), this.gearBtn.addEventListener("click", () => this.toggleGearMenu()), this.rightItems.set("gear", d), this.registerCollapsible({
881
955
  key: "gear",
882
956
  el: d,
@@ -885,7 +959,7 @@ class _t {
885
959
  section: () => this.gearSections()
886
960
  });
887
961
  }
888
- this.layoutRightCluster(a), this.buildMoreDropdown(a), this.bind(), this.syncVolume(), this.syncPlayState(), this.setLikeState(t.actionsOptions.likeState ?? null), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.scheduleReflow()), this.resizeObserver.observe(t.container)), this.onWindowResize = () => this.scheduleReflow(), window.addEventListener("resize", this.onWindowResize);
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);
889
963
  }
890
964
  registerCollapsible(t) {
891
965
  this.collapsibles.push(t);
@@ -901,23 +975,23 @@ class _t {
901
975
  if (i.length > 0) {
902
976
  const n = /* @__PURE__ */ new Set();
903
977
  s = [];
904
- for (const r of i)
905
- this.rightItems.has(r) && !n.has(r) && (s.push(r), n.add(r));
906
- for (const r of e) n.has(r) || s.push(r);
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);
907
981
  }
908
982
  for (const n of s) {
909
- const r = this.rightItems.get(n);
910
- r && t.append(r);
983
+ const o = this.rightItems.get(n);
984
+ o && t.append(o);
911
985
  }
912
986
  }
913
987
  /** Center-cluster button — deliberately NOT `.imp-btn` (own sizing/look). */
914
988
  makeCenterButton(t, e, i) {
915
- const s = o("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
916
- return q(s, i), s;
989
+ const s = a("button", `imp-center-btn imp-center-btn--${t}`, { type: "button", "aria-label": e, title: e });
990
+ return L(s, i), s;
917
991
  }
918
992
  /** Caption under the seek arrow. Default "−15s"/"+15s"; overridable via `controls.seekButtons.label`. */
919
993
  addStepBadge(t, e, i) {
920
- const s = o("span", "imp-seek-num");
994
+ const s = a("span", "imp-seek-num");
921
995
  s.textContent = this.seekLabelFn ? this.seekLabelFn(e, i) : `${i === "back" ? "−" : "+"}${e}${this.player.labels.secondsShort}`, t.append(s);
922
996
  }
923
997
  // === gear (unified settings) ==========================================
@@ -955,10 +1029,10 @@ class _t {
955
1029
  const e = this.player.activeSceneType;
956
1030
  if (t.textContent = "", !e) return;
957
1031
  if (e.icon) {
958
- const s = o("span", "imp-scene-type__icon");
959
- q(s, e.icon), t.append(s);
1032
+ const s = a("span", "imp-scene-type__icon");
1033
+ L(s, e.icon), t.append(s);
960
1034
  }
961
- const i = o("span", "imp-scene-type__label");
1035
+ const i = a("span", "imp-scene-type__label");
962
1036
  i.textContent = e.title, t.append(i), t.setAttribute("aria-label", `${this.player.labels.sceneTypes}: ${e.title}`), t.title = e.title;
963
1037
  }
964
1038
  sceneTypeSection() {
@@ -994,7 +1068,7 @@ class _t {
994
1068
  title: i.title ?? !0,
995
1069
  duration: i.duration ?? !0,
996
1070
  meta: i.meta ?? !0
997
- }, this.nextPreviewEl = o("div", "imp-next-preview"), this.nextPreviewEl.hidden = !0, t.container.append(this.nextPreviewEl), this.nextBtn && this.bindNextPreview(this.nextBtn), this.centerNextBtn && this.bindNextPreview(this.centerNextBtn);
1071
+ }, this.nextPreviewEl = a("div", "imp-next-preview"), this.nextPreviewEl.hidden = !0, t.container.append(this.nextPreviewEl), this.nextBtn && this.bindNextPreview(this.nextBtn), this.centerNextBtn && this.bindNextPreview(this.centerNextBtn);
998
1072
  }
999
1073
  bindNextPreview(t) {
1000
1074
  t.addEventListener("pointerenter", (e) => {
@@ -1010,24 +1084,26 @@ class _t {
1010
1084
  return;
1011
1085
  }
1012
1086
  e.textContent = "";
1013
- const n = o("div", "imp-next-preview__kicker");
1014
- if (n.textContent = this.player.labels.next, e.append(n), i.thumbnail && s.poster) {
1015
- const u = o("div", "imp-next-preview__thumb"), m = S(s.poster);
1016
- if (m.addEventListener("error", () => {
1087
+ const n = a("div", "imp-next-preview__kicker");
1088
+ n.textContent = this.player.labels.next, e.append(n);
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", () => {
1017
1093
  this.player.markSourceDead(s), this.nextPreviewEl && !this.nextPreviewEl.hidden && this.showNextPreview(t);
1018
- }, { once: !0 }), u.append(m), i.duration && s.duration) {
1019
- const f = o("span", "imp-next-preview__duration");
1020
- f.textContent = _(s.duration), u.append(f);
1094
+ }, { once: !0 }), m.append(v), i.duration && s.duration) {
1095
+ const y = a("span", "imp-next-preview__duration");
1096
+ y.textContent = _(s.duration), m.append(y);
1021
1097
  }
1022
- e.append(u);
1098
+ e.append(m);
1023
1099
  }
1024
1100
  if (i.title && s.title) {
1025
- const u = o("div", "imp-next-preview__title");
1026
- u.textContent = s.title, e.append(u);
1101
+ const m = a("div", "imp-next-preview__title");
1102
+ m.textContent = s.title, e.append(m);
1027
1103
  }
1028
- i.meta && s.previewMeta?.length && e.append(j(s.previewMeta, "imp-next-preview")), e.hidden = !1;
1029
- const r = this.player.container.getBoundingClientRect(), a = t.getBoundingClientRect(), c = 8, h = e.offsetWidth, p = a.left - r.left + a.width / 2 - h / 2, v = Math.max(c, Math.min(p, r.width - h - c));
1030
- e.style.left = `${v}px`, e.style.bottom = `${r.height - (a.top - r.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`;
1031
1107
  }
1032
1108
  hideNextPreview() {
1033
1109
  this.nextPreviewEl && (this.nextPreviewEl.hidden = !0);
@@ -1036,7 +1112,7 @@ class _t {
1036
1112
  buildLikeDislike() {
1037
1113
  const t = this.player, e = t.actionsOptions, { labels: i, icons: s } = t;
1038
1114
  if (e.like) {
1039
- this.likeBtn = g("imp-btn--like", i.like, s.like), this.likeBtn.addEventListener("click", () => t.emit("action", { id: "like" })), this.likeCountEl = this.attachCountTooltip(this.likeBtn, e.likeCount);
1115
+ this.likeBtn = b("imp-btn--like", i.like, s.like), this.likeBtn.addEventListener("click", () => t.emit("action", { id: "like" })), this.likeCountEl = this.attachCountTooltip(this.likeBtn, e.likeCount);
1040
1116
  const n = this.wrapWithTooltip(this.likeBtn, this.likeCountEl);
1041
1117
  this.rightItems.set("like", n), this.registerCollapsible({
1042
1118
  key: "like",
@@ -1047,7 +1123,7 @@ class _t {
1047
1123
  });
1048
1124
  }
1049
1125
  if (e.dislike) {
1050
- this.dislikeBtn = g("imp-btn--dislike", i.dislike, s.dislike), this.dislikeBtn.addEventListener("click", () => t.emit("action", { id: "dislike" })), this.dislikeCountEl = this.attachCountTooltip(this.dislikeBtn, e.dislikeCount);
1126
+ this.dislikeBtn = b("imp-btn--dislike", i.dislike, s.dislike), this.dislikeBtn.addEventListener("click", () => t.emit("action", { id: "dislike" })), this.dislikeCountEl = this.attachCountTooltip(this.dislikeBtn, e.dislikeCount);
1051
1127
  const n = this.wrapWithTooltip(this.dislikeBtn, this.dislikeCountEl);
1052
1128
  this.rightItems.set("dislike", n), this.registerCollapsible({
1053
1129
  key: "dislike",
@@ -1059,11 +1135,11 @@ class _t {
1059
1135
  }
1060
1136
  }
1061
1137
  attachCountTooltip(t, e) {
1062
- const i = o("span", "imp-count-tooltip");
1138
+ const i = a("span", "imp-count-tooltip");
1063
1139
  return this.setCountText(i, e), i;
1064
1140
  }
1065
1141
  wrapWithTooltip(t, e) {
1066
- const i = o("div", "imp-action");
1142
+ const i = a("div", "imp-action");
1067
1143
  return i.append(t, e), i;
1068
1144
  }
1069
1145
  setCountText(t, e) {
@@ -1080,37 +1156,37 @@ class _t {
1080
1156
  buildMoreDropdown(t) {
1081
1157
  const e = this.player, i = e.actionsOptions, { labels: s, icons: n } = e;
1082
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" }) });
1083
- for (const c of (i.custom ?? []).filter((h) => h.placement !== "bar"))
1084
- this.actionItems.push({ value: `custom:${c.id}`, label: c.title, icon: c.icon, run: () => e.emit("customaction", { id: c.id }) });
1085
- const r = g("imp-btn--more", s.more, n.more);
1086
- this.moreMenu = new E(r);
1087
- const a = o("div", "imp-controls__menu-anchor imp-controls__more");
1088
- a.append(r, this.moreMenu.root), r.addEventListener("click", () => {
1159
+ for (const h of (i.custom ?? []).filter((c) => c.placement !== "bar"))
1160
+ this.actionItems.push({ value: `custom:${h.id}`, label: h.title, icon: h.icon, run: () => e.emit("customaction", { id: h.id }) });
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", () => {
1089
1165
  this.closeMenus(this.moreMenu), this.moreMenu?.toggle(this.buildMoreSections());
1090
- }), t.append(a), this.moreWrap = a;
1166
+ }), t.append(l), this.moreWrap = l;
1091
1167
  }
1092
1168
  /** ⋯ menu = overflowed controls (in display order) + consumer actions. */
1093
1169
  buildMoreSections() {
1094
- const t = [], e = /* @__PURE__ */ new Map(), i = [], s = ["prev", "next", "seekBack", "seekFwd", "like", "dislike", "scenes", "sceneTypes", "pip", "list", "subtitles", "speed", "quality", "gear"], n = (a) => {
1095
- const c = s.indexOf(a);
1096
- return c === -1 ? s.length : c;
1097
- }, r = this.collapsibles.filter((a) => this.overflowed.has(a.key) && a.available()).sort((a, c) => n(a.key) - n(c.key));
1098
- for (const a of r) {
1099
- const c = a.section();
1100
- if (c)
1101
- for (const h of Array.isArray(c) ? c : [c])
1102
- if (!h.title && h.items.length === 1) {
1103
- const p = h.items[0];
1104
- i.push(p), e.set(p.value, () => h.onSelect(p.value));
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
+ return h === -1 ? s.length : h;
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
+ if (h)
1177
+ for (const c of Array.isArray(h) ? h : [h])
1178
+ if (!c.title && c.items.length === 1) {
1179
+ const u = c.items[0];
1180
+ i.push(u), e.set(u.value, () => c.onSelect(u.value));
1105
1181
  } else
1106
- t.push(h);
1182
+ t.push(c);
1107
1183
  }
1108
- if (i.length > 0 && t.unshift({ title: "", items: i, onSelect: (a) => e.get(a)?.() }), this.actionItems.length > 0) {
1109
- const a = new Map(this.actionItems.map((c) => [c.value, c.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]));
1110
1186
  t.push({
1111
1187
  title: "",
1112
- items: this.actionItems.map(({ value: c, label: h, icon: p }) => ({ value: c, label: h, icon: p, active: !1 })),
1113
- onSelect: (c) => a.get(c)?.()
1188
+ items: this.actionItems.map(({ value: h, label: c, icon: u }) => ({ value: h, label: c, icon: u, active: !1 })),
1189
+ onSelect: (h) => l.get(h)?.()
1114
1190
  });
1115
1191
  }
1116
1192
  return t;
@@ -1163,28 +1239,28 @@ class _t {
1163
1239
  * the ⋯ menu can offer them. Unavailable controls are hidden outright.
1164
1240
  */
1165
1241
  reflow() {
1166
- const t = window.innerWidth <= 767, i = this.player.controlsOptions.seekPlacement !== "bar" || t;
1167
- 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" : "");
1168
- const s = (a) => a === "seekBack" || a === "seekFwd" ? i : a === "prev" || a === "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;
1169
1245
  this.overflowed.clear();
1170
- for (const a of this.collapsibles) {
1171
- if (s(a.key)) {
1172
- a.el.style.display = "none";
1246
+ for (const h of this.collapsibles) {
1247
+ if (n(h.key)) {
1248
+ h.el.style.display = "none";
1173
1249
  continue;
1174
1250
  }
1175
- const c = a.available();
1176
- a.el.style.display = c ? "" : "none", a.el.classList.remove("imp-collapsed");
1251
+ const c = h.available();
1252
+ h.el.style.display = c ? "" : "none", h.el.classList.remove("imp-collapsed");
1177
1253
  }
1178
- const n = this.collapsibles.filter((a) => a.available() && !s(a.key)).sort((a, c) => a.priority - c.priority);
1179
- let r = n.length;
1180
- for (; r-- > 0 && this.overflowsRow(); ) {
1181
- const a = n.find((c) => !this.overflowed.has(c.key));
1182
- if (!a) break;
1183
- a.el.style.display = "none", a.el.classList.add("imp-collapsed"), this.overflowed.add(a.key);
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
+ for (; l-- > 0 && this.overflowsRow(); ) {
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);
1184
1260
  }
1185
1261
  if (this.moreWrap) {
1186
- const a = this.actionItems.length > 0 || this.overflowed.size > 0;
1187
- this.moreWrap.style.display = a ? "" : "none";
1262
+ const h = this.actionItems.length > 0 || this.overflowed.size > 0;
1263
+ this.moreWrap.style.display = h ? "" : "none";
1188
1264
  }
1189
1265
  }
1190
1266
  overflowsRow() {
@@ -1254,16 +1330,21 @@ class _t {
1254
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();
1255
1331
  }
1256
1332
  }
1257
- class Lt {
1333
+ class Bt {
1258
1334
  constructor(t) {
1259
- this.root = o("div", "imp-poster"), this.image = o("div", "imp-poster__image"), this.image.hidden = !0, this.img = S(""), this.image.append(this.img);
1260
- const e = g("imp-poster__play", t.labels.play, t.icons.bigPlay);
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
+ const e = b("imp-poster__play", t.labels.play, t.icons.bigPlay);
1261
1337
  e.addEventListener("click", () => void t.play()), this.root.append(this.image, e), this.root.addEventListener("pointerup", (i) => {
1262
1338
  i.target !== this.root && i.target !== this.image && i.target !== this.img || i.pointerType === "touch" && t.posterTapReveal() || t.play();
1263
1339
  });
1264
1340
  }
1265
1341
  setSource(t) {
1266
- t?.poster ? (this.img.src = t.poster, this.img.fetchPriority = "high", this.image.hidden = !1) : (this.img.removeAttribute("src"), this.image.hidden = !0);
1342
+ const e = t?.poster;
1343
+ if (e) {
1344
+ const i = typeof e == "string" ? { src: e } : e;
1345
+ this.img.src = i.src, i.srcset ? this.img.srcset = i.srcset : this.img.removeAttribute("srcset"), i.sizes ? this.img.sizes = i.sizes : this.img.removeAttribute("sizes"), i.width ? this.img.width = i.width : this.img.removeAttribute("width"), i.height ? this.img.height = i.height : this.img.removeAttribute("height"), this.img.alt = i.alt ?? "", this.img.fetchPriority = "high", this.image.hidden = !1;
1346
+ } else
1347
+ this.img.removeAttribute("src"), this.image.hidden = !0;
1267
1348
  }
1268
1349
  show() {
1269
1350
  this.root.hidden = !1;
@@ -1272,13 +1353,13 @@ class Lt {
1272
1353
  this.root.hidden = !0;
1273
1354
  }
1274
1355
  }
1275
- class St {
1356
+ class Et {
1276
1357
  constructor(t) {
1277
- this.labels = t, this.channelUrl = null, this.custom = null, this.visible = { title: !0, description: !0, sponsor: !0 }, this.root = o("div", "imp-pause-screen"), this.root.hidden = !0, this.defaultContent = o("div", "imp-pause-screen__default"), this.channel = o("button", "imp-channel", { type: "button" }), this.channel.hidden = !0, this.channelAvatar = o("div", "imp-channel__avatar"), this.channelName = o("div", "imp-channel__name"), this.channel.append(this.channelName, this.channelAvatar), this.channel.addEventListener("click", () => {
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", () => {
1278
1359
  this.channelUrl && window.open(this.channelUrl, "_blank", "noopener");
1279
1360
  });
1280
- const e = o("div", "imp-pause-screen__heading");
1281
- this.title = o("div", "imp-pause-screen__title"), this.description = o("div", "imp-pause-screen__description"), this.sponsor = o("a", "imp-sponsor", { target: "_blank", rel: "nofollow noopener" }), this.sponsor.hidden = !0, this.sponsorLabel = o("span", "imp-sponsor__label"), this.sponsorText = o("span", "imp-sponsor__text"), this.sponsor.append(this.sponsorLabel, this.sponsorText), this.sponsor.addEventListener("click", (i) => i.stopPropagation()), e.append(this.sponsor, this.title, this.description), this.defaultContent.append(e, this.channel), this.root.append(this.defaultContent);
1361
+ const e = a("div", "imp-pause-screen__heading");
1362
+ this.title = a("div", "imp-pause-screen__title"), this.description = a("div", "imp-pause-screen__description"), this.sponsor = a("a", "imp-sponsor", { target: "_blank", rel: "nofollow noopener" }), this.sponsor.hidden = !0, this.sponsorLabel = a("span", "imp-sponsor__label"), this.sponsorText = a("span", "imp-sponsor__text"), this.sponsor.append(this.sponsorLabel, this.sponsorText), this.sponsor.addEventListener("click", (i) => i.stopPropagation()), e.append(this.sponsor, this.title, this.description), this.defaultContent.append(e, this.channel), this.root.append(this.defaultContent);
1282
1363
  }
1283
1364
  setCustomContent(t) {
1284
1365
  this.custom?.remove(), this.custom = t, t && (t.classList.add("imp-pause-screen__custom"), this.root.append(t)), this.defaultContent.hidden = t !== null, this.root.classList.toggle("imp-pause-screen--custom", t !== null);
@@ -1300,7 +1381,7 @@ class St {
1300
1381
  const e = this.visible.sponsor ? t?.sponsor : void 0;
1301
1382
  this.sponsor.hidden = !e, e && (this.sponsor.href = e.url, this.sponsorText.textContent = e.text, this.sponsorLabel.textContent = e.label ?? this.labels.sponsored);
1302
1383
  const i = t?.channel;
1303
- this.channel.hidden = !i, this.channelUrl = i?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!i?.url), i && (this.channelName.textContent = i.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${i.avatarShape ?? "circle"}`, i.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.append(S(i.avatar, i.name))) : this.channelAvatar.textContent = (i.name.trim()[0] ?? "?").toUpperCase());
1384
+ this.channel.hidden = !i, this.channelUrl = i?.url ?? null, this.channel.classList.toggle("imp-channel--link", !!i?.url), i && (this.channelName.textContent = i.name, this.channelAvatar.className = `imp-channel__avatar imp-channel__avatar--${i.avatarShape ?? "circle"}`, i.avatar ? (this.channelAvatar.textContent = "", this.channelAvatar.append(T(i.avatar, i.name))) : this.channelAvatar.textContent = (i.name.trim()[0] ?? "?").toUpperCase());
1304
1385
  }
1305
1386
  show() {
1306
1387
  this.root.hidden = !1;
@@ -1309,10 +1390,10 @@ class St {
1309
1390
  this.root.hidden = !0;
1310
1391
  }
1311
1392
  }
1312
- class Tt {
1393
+ class Mt {
1313
1394
  constructor(t) {
1314
- this.player = t, this.clickBehavior = "player", this.root = o("div", "imp-related"), this.root.hidden = !0, this.heading = o("div", "imp-related__title"), this.grid = o("div", "imp-related__grid");
1315
- const e = g("imp-related__close", t.labels.close, t.icons.close);
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
+ const e = b("imp-related__close", t.labels.close, t.icons.close);
1316
1397
  e.addEventListener("click", () => this.hide()), this.root.append(e, this.heading, this.grid);
1317
1398
  }
1318
1399
  setOptions(t) {
@@ -1323,12 +1404,12 @@ class Tt {
1323
1404
  }
1324
1405
  }
1325
1406
  buildCard(t) {
1326
- const e = o("button", "imp-related__card", { type: "button" }), i = o("div", "imp-related__thumb");
1327
- if (t.poster && i.append(S(t.poster)), t.duration) {
1328
- const n = o("span", "imp-related__duration");
1407
+ const e = a("button", "imp-related__card", { type: "button" }), i = a("div", "imp-related__thumb");
1408
+ if (t.poster && i.append(T(t.poster)), t.duration) {
1409
+ const n = a("span", "imp-related__duration");
1329
1410
  n.textContent = t.duration, i.append(n);
1330
1411
  }
1331
- const s = o("div", "imp-related__card-title");
1412
+ const s = a("div", "imp-related__card-title");
1332
1413
  return s.textContent = t.title, e.append(i, s), e.addEventListener("click", () => {
1333
1414
  this.player.emit("relatedclick", { item: t }), this.hide(), this.activate(t);
1334
1415
  }), e;
@@ -1358,9 +1439,9 @@ class Tt {
1358
1439
  this.root.hidden = !0;
1359
1440
  }
1360
1441
  }
1361
- class Bt {
1442
+ class Ct {
1362
1443
  constructor(t) {
1363
- this.player = t, this.root = o("div", "imp-upnext"), this.root.hidden = !0;
1444
+ this.player = t, this.root = a("div", "imp-upnext"), this.root.hidden = !0;
1364
1445
  }
1365
1446
  get visible() {
1366
1447
  return !this.root.hidden;
@@ -1373,65 +1454,67 @@ class Bt {
1373
1454
  }
1374
1455
  const { labels: e } = this.player;
1375
1456
  this.root.textContent = "";
1376
- const i = o("div", "imp-upnext__card"), s = o("div", "imp-upnext__kicker");
1377
- if (s.textContent = e.nextVideo, i.append(s), t.poster) {
1378
- const r = o("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext }), a = S(t.poster);
1379
- if (a.addEventListener("error", () => {
1457
+ const i = a("div", "imp-upnext__card"), s = a("div", "imp-upnext__kicker");
1458
+ s.textContent = e.nextVideo, i.append(s);
1459
+ const n = q(t.poster);
1460
+ if (n) {
1461
+ const l = a("button", "imp-upnext__thumb", { type: "button", "aria-label": e.playNext }), h = T(n);
1462
+ if (h.addEventListener("error", () => {
1380
1463
  this.player.markSourceDead(t), this.root.hidden || this.show();
1381
- }, { once: !0 }), r.append(a), t.duration) {
1382
- const h = o("span", "imp-upnext__duration");
1383
- h.textContent = _(t.duration), r.append(h);
1464
+ }, { once: !0 }), l.append(h), t.duration) {
1465
+ const u = a("span", "imp-upnext__duration");
1466
+ u.textContent = _(t.duration), l.append(u);
1384
1467
  }
1385
- const c = o("span", "imp-upnext__thumb-play");
1386
- q(c, this.player.icons.bigPlay), r.append(c), r.addEventListener("click", () => this.player.next()), i.append(r);
1468
+ const c = a("span", "imp-upnext__thumb-play");
1469
+ L(c, this.player.icons.bigPlay), l.append(c), l.addEventListener("click", () => this.player.next()), i.append(l);
1387
1470
  }
1388
1471
  if (t.title) {
1389
- const r = o("div", "imp-upnext__title");
1390
- r.textContent = t.title, i.append(r);
1472
+ const l = a("div", "imp-upnext__title");
1473
+ l.textContent = t.title, i.append(l);
1391
1474
  }
1392
- t.previewMeta?.length && i.append(j(t.previewMeta, "imp-upnext"));
1393
- const n = o("button", "imp-upnext__btn", { type: "button" });
1394
- n.textContent = e.playNext, n.addEventListener("click", () => this.player.next()), i.append(n), 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;
1395
1478
  }
1396
1479
  hide() {
1397
1480
  this.root.hidden = !0;
1398
1481
  }
1399
1482
  }
1400
- class Et {
1483
+ class Pt {
1401
1484
  constructor(t, e = "sidebar", i) {
1402
- this.player = t, this.root = o("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
1403
- const s = o("div", "imp-playlist__header"), n = o("div", "imp-playlist__heading");
1485
+ this.player = t, this.root = a("div", `imp-playlist imp-playlist--${e}`), this.root.hidden = !0;
1486
+ const s = a("div", "imp-playlist__header"), n = a("div", "imp-playlist__heading");
1404
1487
  if (i) {
1405
- const c = o("div", "imp-playlist__kicker");
1406
- c.textContent = t.labels.playlist;
1407
- const h = o("div", "imp-playlist__name");
1408
- h.textContent = i, n.append(c, h);
1488
+ const h = a("div", "imp-playlist__kicker");
1489
+ h.textContent = t.labels.playlist;
1490
+ const c = a("div", "imp-playlist__name");
1491
+ c.textContent = i, n.append(h, c);
1409
1492
  } else
1410
1493
  n.textContent = t.labels.playlist;
1411
- const r = o("div", "imp-playlist__tools");
1412
- this.shuffleBtn = g("imp-playlist__shuffle", t.labels.shuffle, t.icons.shuffle), this.shuffleBtn.addEventListener("click", () => {
1494
+ const o = a("div", "imp-playlist__tools");
1495
+ this.shuffleBtn = b("imp-playlist__shuffle", t.labels.shuffle, t.icons.shuffle), this.shuffleBtn.addEventListener("click", () => {
1413
1496
  t.setShuffle(!t.shuffle), this.syncModes();
1414
- }), this.repeatBtn = g("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
1497
+ }), this.repeatBtn = b("imp-playlist__repeat", t.labels.repeat, t.icons.repeat), this.repeatBtn.addEventListener("click", () => {
1415
1498
  t.setRepeat(!t.repeat), this.syncModes();
1416
1499
  });
1417
- const a = g("imp-playlist__close", t.labels.close, t.icons.close);
1418
- a.addEventListener("click", () => this.hide()), r.append(this.shuffleBtn, this.repeatBtn, a), s.append(n, r), this.list = o("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();
1419
1502
  }
1420
1503
  syncModes() {
1421
1504
  this.shuffleBtn.classList.toggle("imp-btn--active", this.player.shuffle), this.repeatBtn.classList.toggle("imp-btn--active", this.player.repeat);
1422
1505
  }
1423
1506
  rebuild() {
1424
1507
  this.list.textContent = "", this.player.playlist.forEach((t, e) => {
1425
- const i = o("button", "imp-playlist__item", { type: "button" });
1508
+ const i = a("button", "imp-playlist__item", { type: "button" });
1426
1509
  e === this.player.index && i.classList.add("imp-playlist__item--active");
1427
- const s = o("div", "imp-playlist__thumb");
1428
- t.poster && s.append(S(t.poster));
1429
- const n = o("div", "imp-playlist__meta"), r = o("div", "imp-playlist__title");
1430
- if (r.textContent = t.title ?? `#${e + 1}`, n.append(r), t.duration) {
1431
- const a = o("div", "imp-playlist__duration");
1432
- a.textContent = _(t.duration), n.append(a);
1510
+ const s = a("div", "imp-playlist__thumb"), n = q(t.poster);
1511
+ n && s.append(T(n));
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
+ const h = a("div", "imp-playlist__duration");
1515
+ h.textContent = _(t.duration), o.append(h);
1433
1516
  }
1434
- i.append(s, n), i.addEventListener("click", () => {
1517
+ i.append(s, o), i.addEventListener("click", () => {
1435
1518
  this.player.playItem(e), window.innerWidth <= 767 && this.hide();
1436
1519
  }), this.list.append(i);
1437
1520
  });
@@ -1449,28 +1532,28 @@ class Et {
1449
1532
  this.visible ? this.hide() : this.show();
1450
1533
  }
1451
1534
  }
1452
- class Ct {
1535
+ class At {
1453
1536
  constructor(t, e = "bottom") {
1454
- this.player = t, this.items = [], this.root = o("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
1455
- const i = o("div", "imp-playlist__header"), s = o("span");
1537
+ this.player = t, this.items = [], this.root = a("div", `imp-playlist imp-scenes imp-playlist--${e}`), this.root.hidden = !0;
1538
+ const i = a("div", "imp-playlist__header"), s = a("span");
1456
1539
  s.textContent = t.labels.scenes;
1457
- const n = g("imp-playlist__close", t.labels.close, t.icons.close);
1458
- n.addEventListener("click", () => this.hide()), i.append(s, n), this.list = o("div", "imp-playlist__list"), this.root.append(i, this.list), t.on("chapterchange", () => this.syncActive());
1540
+ const n = b("imp-playlist__close", t.labels.close, t.icons.close);
1541
+ n.addEventListener("click", () => this.hide()), i.append(s, n), this.list = a("div", "imp-playlist__list"), this.root.append(i, this.list), t.on("chapterchange", () => this.syncActive());
1459
1542
  }
1460
1543
  /** Re-render from the player's current chapters + thumbnail track. */
1461
1544
  rebuild() {
1462
1545
  this.list.textContent = "", this.items = [];
1463
1546
  const t = this.player.thumbnails;
1464
1547
  for (const e of this.player.chapterList) {
1465
- const i = o("button", "imp-playlist__item", { type: "button" }), s = o("div", "imp-playlist__thumb"), n = t?.cueAt(e.start + 0.01) ?? null;
1548
+ const i = a("button", "imp-playlist__item", { type: "button" }), s = a("div", "imp-playlist__thumb"), n = t?.cueAt(e.start + 0.01) ?? null;
1466
1549
  if (n?.xywh) {
1467
- const h = o("div", "imp-scenes__sprite");
1468
- h.style.width = `${n.xywh.w}px`, h.style.height = `${n.xywh.h}px`, h.style.backgroundImage = `url("${n.src}")`, h.style.backgroundPosition = `-${n.xywh.x}px -${n.xywh.y}px`, h.style.setProperty("--imp-sprite-w", String(n.xywh.w)), s.append(h);
1469
- } else n && s.append(S(n.src));
1470
- const r = o("div", "imp-playlist__meta"), a = o("div", "imp-playlist__title");
1471
- a.textContent = e.title || _(e.start);
1472
- const c = o("div", "imp-playlist__duration");
1473
- c.textContent = _(e.start), r.append(a, c), i.append(s, r), i.addEventListener("click", () => {
1550
+ const c = a("div", "imp-scenes__sprite");
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
+ } else n && s.append(T(n.src));
1553
+ const o = a("div", "imp-playlist__meta"), l = a("div", "imp-playlist__title");
1554
+ l.textContent = e.title || _(e.start);
1555
+ const h = a("div", "imp-playlist__duration");
1556
+ h.textContent = _(e.start), o.append(l, h), i.append(s, o), i.addEventListener("click", () => {
1474
1557
  this.player.seek(e.start), this.player.play(), window.innerWidth <= 767 && this.hide();
1475
1558
  }), this.list.append(i), this.items.push(i);
1476
1559
  }
@@ -1495,21 +1578,24 @@ class Ct {
1495
1578
  this.visible ? this.hide() : this.show();
1496
1579
  }
1497
1580
  }
1498
- let Y = 0;
1499
- function tt(l) {
1500
- const t = l.reason;
1501
- t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") && l.preventDefault();
1581
+ let it = 0;
1582
+ function st(r) {
1583
+ const t = r.reason;
1584
+ t?.name === "AbortError" && /interrupted by a (new load request|call to pause)/i.test(t.message ?? "") && r.preventDefault();
1585
+ }
1586
+ function Rt() {
1587
+ typeof window < "u" && ++it === 1 && window.addEventListener("unhandledrejection", st);
1502
1588
  }
1503
- function Mt() {
1504
- typeof window < "u" && ++Y === 1 && window.addEventListener("unhandledrejection", tt);
1589
+ function Nt() {
1590
+ typeof window < "u" && --it === 0 && window.removeEventListener("unhandledrejection", st);
1505
1591
  }
1506
- function Pt() {
1507
- typeof window < "u" && --Y === 0 && window.removeEventListener("unhandledrejection", tt);
1592
+ function $(r) {
1593
+ console.debug("[itube-player] play() rejected:", r);
1508
1594
  }
1509
- function Q(l) {
1510
- return l ? typeof l == "string" ? [{ src: l, label: "Subtitles" }] : Array.isArray(l) ? l : [l] : [];
1595
+ function K(r) {
1596
+ return r ? typeof r == "string" ? [{ src: r, label: "Subtitles" }] : Array.isArray(r) ? r : [r] : [];
1511
1597
  }
1512
- const At = {
1598
+ const It = {
1513
1599
  play: !0,
1514
1600
  progress: !0,
1515
1601
  time: !0,
@@ -1528,6 +1614,8 @@ const At = {
1528
1614
  seekButtons: !0,
1529
1615
  // Prev/seek/play/next as a centered overlay on every viewport.
1530
1616
  seekPlacement: "overlay",
1617
+ // Mobile: only ±N seek over the video; play/next live in the bottom bar.
1618
+ mobileLayout: "bar",
1531
1619
  order: [],
1532
1620
  // empty → built-in right-cluster order
1533
1621
  playlist: !0,
@@ -1538,57 +1626,57 @@ const At = {
1538
1626
  hideDelay: 2500,
1539
1627
  revealBeforePlay: !0
1540
1628
  };
1541
- class Vt {
1629
+ class Ht {
1542
1630
  constructor(t, e = {}) {
1543
- this.scrubbing = !1, this.emitter = new it(), 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;
1544
1632
  const i = typeof t == "string" ? document.querySelector(t) : t;
1545
1633
  if (!i) throw new Error(`[itube-player] mount target not found: ${String(t)}`);
1546
- this.mount = i, this.options = e, this.labels = { ...H, ...nt(e.language), ...e.labels }, this.icons = { ...st, ...e.icons };
1634
+ this.mount = i, this.options = e, this.labels = { ...G, ...at(e.language), ...e.labels }, this.icons = { ...ot, ...e.icons };
1547
1635
  const s = e.controls ?? {}, n = s.speed ?? s.settings ?? "gear";
1548
- if (this.controlsOptions = { ...At, ...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) {
1549
- const b = e.persist === !0 ? {} : e.persist;
1550
- this.persistKey = b.key ?? "itube-player", this.persistVolume = b.volume !== !1, this.persistAutoAdvance = b.autoAdvance !== !1;
1551
- }
1552
- const r = this.readPersisted();
1553
- this.autoAdvanceEnabled = this.persistAutoAdvance && typeof r?.autoAdvance == "boolean" ? r.autoAdvance : this.playlistOptions.autoAdvance, this.sources = e.source ? Array.isArray(e.source) ? [...e.source] : [e.source] : [], this.container = o("div", "imp-player", { tabindex: "0" }), e.className && this.container.classList.add(e.className);
1554
- const a = e.styling;
1555
- if (a?.themeColor && this.container.style.setProperty("--imp-accent", a.themeColor), a?.likeColor && this.container.style.setProperty("--imp-like", a.likeColor), a?.dislikeColor && this.container.style.setProperty("--imp-dislike", a.dislikeColor), a?.fontFamily && this.container.style.setProperty("--imp-font", a.fontFamily), a?.borderRadius !== void 0) {
1556
- const b = typeof a.borderRadius == "number" ? `${a.borderRadius}px` : a.borderRadius;
1557
- this.container.style.setProperty("--imp-radius", b);
1558
- }
1559
- a?.playButtonStyle === "inverted" && this.container.classList.add("imp-player--play-inverted"), this.video = o("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);
1560
- const c = this.persistVolume ? r : null;
1561
- this.video.volume = x(c?.volume ?? e.volume ?? 1, 0, 1), (c?.muted ?? e.muted) && (this.video.muted = !0);
1562
- const h = o("div", "imp-layer");
1563
- this.spinner = o("div", "imp-spinner"), this.spinner.hidden = !0, this.errorBox = o("div", "imp-error"), this.errorBox.hidden = !0, this.errorText = o("div", "imp-error__text"), this.retryBtn = o("button", "imp-error__retry", { type: "button" });
1564
- const p = o("span", "imp-error__retry-label");
1565
- p.textContent = this.labels.tryAgain, this.retryBtn.append(p, o("span", "imp-error__retry-spinner")), this.retryBtn.addEventListener("click", () => this.retry()), this.errorNextBtn = o("button", "imp-error__next", { type: "button" }), this.errorNextBtn.textContent = this.labels.nextVideo, this.errorNextBtn.addEventListener("click", () => {
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) {
1637
+ const y = e.persist === !0 ? {} : e.persist;
1638
+ this.persistKey = y.key ?? "itube-player", this.persistVolume = y.volume !== !1, this.persistAutoAdvance = y.autoAdvance !== !1;
1639
+ }
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;
1645
+ this.container.style.setProperty("--imp-radius", y);
1646
+ }
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;
1649
+ this.video.volume = x(h?.volume ?? e.volume ?? 1, 0, 1), (h?.muted ?? e.muted) && (this.video.muted = !0);
1650
+ const c = a("div", "imp-layer");
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" });
1652
+ const u = a("span", "imp-error__retry-label");
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", () => {
1566
1654
  this.clearError(), this.next();
1567
1655
  });
1568
- const v = o("div", "imp-error__actions");
1569
- v.append(this.retryBtn, this.errorNextBtn), this.errorBox.append(this.errorText, v), this.pauseScreen = new St(this.labels), this.poster = new Lt(this), this.related = new Tt(this), this.related.setOptions(e.related), this.upNext = new Bt(this), this.controls = new _t(this), this.playlistPanel = new Et(this, this.playlistOptions.layout, this.playlistOptions.title || void 0), this.scenesPanel = new Ct(this, e.scenes?.layout ?? "bottom");
1570
- const u = o("div", "imp-layer__middle");
1571
- u.append(this.spinner, this.errorBox, this.controls.center);
1572
- const m = o("div", "imp-layer__bottom");
1573
- m.append(this.controls.root), h.append(this.pauseScreen.root, this.related.root, this.upNext.root, u, m), this.container.append(this.video, h, 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);
1574
- const f = e.adConfig ?? e.ads;
1575
- f && f.adList.length > 0 && (this.adManager = new mt(
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");
1658
+ const p = a("div", "imp-layer__middle");
1659
+ p.append(this.spinner, this.errorBox, this.controls.center);
1660
+ const m = a("div", "imp-layer__bottom");
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);
1662
+ const v = e.adConfig ?? e.ads;
1663
+ v && v.adList.length > 0 && (this.adManager = new gt(
1576
1664
  { container: this.container, contentVideo: this.video, emitter: this.emitter, labels: this.labels, closeIcon: this.icons.close },
1577
- f
1578
- )), this.emitter.on("error", ({ fatal: b }) => {
1579
- if (!b) return;
1665
+ v
1666
+ )), this.emitter.on("error", ({ fatal: y }) => {
1667
+ if (!y) return;
1580
1668
  const d = this.lastPlayheadTime || this.video.currentTime;
1581
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");
1582
- }), Mt(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (b) => {
1670
+ }), Rt(), this.bindVideoEvents(), this.bindIdleHide(), e.keyboard !== !1 && this.bindKeyboard(), this.video.addEventListener("pointerup", (y) => {
1583
1671
  if (!(this.adPlaying || !this.playedOnce)) {
1584
- if (b.pointerType === "mouse") {
1672
+ if (y.pointerType === "mouse") {
1585
1673
  this.togglePlay();
1586
1674
  return;
1587
1675
  }
1588
1676
  this.container.classList.contains("imp-player--idle") ? (this.showControlsNow(), this.scheduleIdle()) : this.video.paused || this.container.classList.add("imp-player--idle");
1589
1677
  }
1590
- }, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (b) => {
1591
- this.pauseScreen.hasCustom || b.target === this.pauseScreen.root && this.togglePlay();
1678
+ }, { signal: this.abort.signal }), this.pauseScreen.root.addEventListener("click", (y) => {
1679
+ this.pauseScreen.hasCustom || y.target === this.pauseScreen.root && this.togglePlay();
1592
1680
  }, { signal: this.abort.signal }), this.sources.length > 0 && this.loadItem(x(this.playlistOptions.startIndex, 0, this.sources.length - 1), !!(e.playOnInit ?? e.autoplay)), queueMicrotask(() => {
1593
1681
  this.destroyed || this.emitter.emit("ready", { player: this });
1594
1682
  });
@@ -1639,12 +1727,11 @@ class Vt {
1639
1727
  if (i === "NotSupportedError" && this.video.readyState === 0) {
1640
1728
  const s = this.loadToken;
1641
1729
  this.video.addEventListener("loadedmetadata", () => {
1642
- s === this.loadToken && this.video.play().catch(() => {
1643
- });
1730
+ s === this.loadToken && this.video.play().catch($);
1644
1731
  }, { once: !0, signal: this.abort.signal });
1645
1732
  return;
1646
1733
  }
1647
- i !== "AbortError" && !this.playedOnce && this.poster.show();
1734
+ i !== "AbortError" && ($(e), this.playedOnce || this.poster.show());
1648
1735
  }
1649
1736
  }
1650
1737
  pause() {
@@ -1679,8 +1766,17 @@ class Vt {
1679
1766
  clearError() {
1680
1767
  this.errorBox.hidden = !0, this.container.classList.remove("imp-player--error");
1681
1768
  }
1769
+ /** True once the current source has started playing at least once. */
1770
+ get started() {
1771
+ return this.playedOnce;
1772
+ }
1682
1773
  seek(t) {
1683
- 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));
1684
1780
  }
1685
1781
  /** Relative seek, e.g. `skip(-10)`. */
1686
1782
  skip(t) {
@@ -1749,8 +1845,8 @@ class Vt {
1749
1845
  setQuality(t) {
1750
1846
  if (this.sourceController?.kind === "hls") {
1751
1847
  this.sourceController.setLevel(t);
1752
- const r = t === -1 ? this.labels.qualityAuto : this.sourceController.levels.find((a) => a.index === t)?.label ?? String(t);
1753
- this.emitter.emit("qualitychange", { label: r });
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 });
1754
1850
  return;
1755
1851
  }
1756
1852
  const e = this.source?.qualities;
@@ -1764,14 +1860,13 @@ class Vt {
1764
1860
  this.video.currentTime = i;
1765
1861
  } catch {
1766
1862
  }
1767
- s && this.video.play().catch(() => {
1768
- });
1863
+ s && this.video.play().catch($);
1769
1864
  }
1770
1865
  }, { once: !0, signal: this.abort.signal }), this.emitter.emit("qualitychange", { label: e[t].label ?? String(e[t].quality ?? t) });
1771
1866
  }
1772
1867
  // === subtitles ========================================================
1773
1868
  get subtitleTracks() {
1774
- return Q(this.source?.subtitles);
1869
+ return K(this.source?.subtitles);
1775
1870
  }
1776
1871
  get activeSubtitle() {
1777
1872
  const t = this.video.textTracks;
@@ -1932,9 +2027,20 @@ class Vt {
1932
2027
  setSceneGroup(t) {
1933
2028
  t === this.activeSceneGroupId || !this.sceneGroupList.some((e) => e.id === t) || (this.activeSceneGroupId = t, this.applyActiveSceneGroup(), this.emitter.emit("scenetypechange", { group: this.activeSceneType }));
1934
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
+ }
1935
2041
  /** Normalize the active group's scenes into `chapters` and refresh the UI. */
1936
2042
  applyActiveSceneGroup() {
1937
- this.chapters = z(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();
1938
2044
  }
1939
2045
  // === actions ==========================================================
1940
2046
  /**
@@ -1971,66 +2077,64 @@ class Vt {
1971
2077
  }
1972
2078
  // === teardown =========================================================
1973
2079
  destroy() {
1974
- 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(), Pt(), 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());
1975
2081
  }
1976
2082
  // === internals ========================================================
1977
2083
  async loadItem(t, e, i = !1) {
1978
2084
  const s = ++this.loadToken, n = this.sources[t];
1979
2085
  if (!n) return;
1980
- 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();
1981
- for (const u of [...this.video.querySelectorAll("track")]) u.remove();
1982
- this.adManager?.resetForNewSource(), this.related.hide(), this.upNext.hide(), this.pauseScreen.hide(), this.scenesPanel.hide(), this.thumbTrack = null, this.decodeRecoveries = 0, this.video.poster = 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();
1983
- for (const u of Q(n.subtitles)) {
1984
- const m = o("track", "", {
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();
2087
+ for (const p of [...this.video.querySelectorAll("track")]) p.remove();
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)) {
2090
+ const m = a("track", "", {
1985
2091
  kind: "subtitles",
1986
- src: u.src,
1987
- label: u.label,
1988
- ...u.srclang ? { srclang: u.srclang } : {}
2092
+ src: p.src,
2093
+ label: p.label,
2094
+ ...p.srclang ? { srclang: p.srclang } : {}
1989
2095
  });
1990
- u.default && m.setAttribute("default", ""), this.video.append(m);
2096
+ p.default && m.setAttribute("default", ""), this.video.append(m);
1991
2097
  }
1992
- let r = n.src, a = n.type;
2098
+ let o = n.src, l = n.type;
1993
2099
  if (n.qualities && n.qualities.length > 0) {
1994
- const u = Math.max(0, n.qualities.findIndex((m) => m.src === n.src));
1995
- this.progressiveQuality = u, r = n.qualities[u].src, a = n.qualities[u].type ?? a;
2100
+ const p = Math.max(0, n.qualities.findIndex((m) => m.src === n.src));
2101
+ this.progressiveQuality = p, o = n.qualities[p].src, l = n.qualities[p].type ?? l;
1996
2102
  }
1997
2103
  this.video.preload = this.adManager?.hasPendingPreRoll ? "auto" : "metadata";
1998
- const c = await gt(this.video, r, a, {
2104
+ const h = await wt(this.video, o, l, {
1999
2105
  onLevels: () => {
2000
2106
  s === this.loadToken && this.controls.syncFeatureButtons();
2001
2107
  },
2002
- onLevelSwitch: (u) => this.emitter.emit("qualitychange", { label: u }),
2003
- onError: (u, m) => this.emitter.emit("error", { message: u, cause: m, fatal: !0 })
2108
+ onLevelSwitch: (p) => this.emitter.emit("qualitychange", { label: p }),
2109
+ onError: (p, m) => this.emitter.emit("error", { message: p, cause: m, fatal: !0 })
2004
2110
  });
2005
2111
  if (s !== this.loadToken) {
2006
- c.destroy();
2112
+ h.destroy();
2007
2113
  return;
2008
2114
  }
2009
- if (this.sourceController = c, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && Z.load(n.thumbnails).then((u) => {
2010
- s === this.loadToken && (this.thumbTrack = u, this.controls.progress.setThumbnails(u), this.scenesPanel.visible && this.scenesPanel.rebuild());
2011
- }).catch((u) => this.emitter.emit("error", { message: "Failed to load thumbnails track", cause: u })), n.sceneGroups && n.sceneGroups.length > 0) {
2012
- this.sceneGroupList = n.sceneGroups, this.activeSceneGroupId = n.sceneGroups[0].id;
2013
- const u = () => {
2115
+ if (this.sourceController = h, this.emitter.emit("sourcechange", { source: n, index: t }), n.thumbnails && W.load(n.thumbnails).then((p) => {
2116
+ s === this.loadToken && (this.thumbTrack = p, this.controls.progress.setThumbnails(p), this.scenesPanel.visible && this.scenesPanel.rebuild());
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", () => {
2014
2119
  s === this.loadToken && this.applyActiveSceneGroup();
2015
- };
2016
- Number.isFinite(this.video.duration) && this.video.duration > 0 ? u() : this.video.addEventListener("loadedmetadata", u, { once: !0, signal: this.abort.signal });
2017
- } else if (n.chapters) {
2018
- const u = (m) => {
2019
- const f = () => {
2020
- s === this.loadToken && (this.chapters = z(m, this.video.duration), this.controls.progress.setChapters(this.chapters), this.controls.syncFeatureButtons(), this.scenesPanel.visible && this.scenesPanel.rebuild());
2120
+ }, { once: !0, signal: this.abort.signal });
2121
+ else if (n.chapters) {
2122
+ const p = (m) => {
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());
2021
2125
  };
2022
- 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 });
2023
2127
  };
2024
- typeof n.chapters == "string" ? vt(n.chapters).then((m) => u(m)).catch((m) => this.emitter.emit("error", { message: "Failed to load chapters track", cause: m })) : u(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);
2025
2129
  }
2026
- const h = n.heatmap, p = h && !Array.isArray(h), v = p ? h.values.length > 0 : !!(h && h.length > 0);
2027
- if (h && v && this.controlsOptions.heatmap) {
2028
- const u = () => {
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) {
2132
+ const p = () => {
2029
2133
  if (s !== this.loadToken) return;
2030
- const m = p ? lt(h.values, h.mode) : at(h, this.video.duration);
2031
- this.controls.progress.setHeatmap(m, p ? h.smoothing ?? 1 : 1);
2134
+ const m = u ? dt(c.values, c.mode) : ct(c, this.video.duration);
2135
+ this.controls.progress.setHeatmap(m, u ? c.smoothing ?? 1 : 1);
2032
2136
  };
2033
- p || Number.isFinite(this.video.duration) && this.video.duration > 0 ? u() : this.video.addEventListener("loadedmetadata", u, { once: !0, signal: this.abort.signal });
2137
+ u || Number.isFinite(this.video.duration) && this.video.duration > 0 ? p() : this.video.addEventListener("loadedmetadata", p, { once: !0, signal: this.abort.signal });
2034
2138
  }
2035
2139
  e && this.play(i);
2036
2140
  }
@@ -2044,12 +2148,22 @@ class Vt {
2044
2148
  this.handleEnded();
2045
2149
  }, { signal: t }), e.addEventListener("timeupdate", () => {
2046
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);
2047
- const i = J(this.chapters, e.currentTime);
2151
+ const i = et(this.chapters, e.currentTime);
2048
2152
  i !== this.currentChapter && (this.currentChapter = i, this.emitter.emit("chapterchange", { chapter: i }));
2049
2153
  }, { signal: t }), e.addEventListener("progress", () => {
2050
2154
  this.emitter.emit("progress", { buffered: this.bufferedEnd });
2051
2155
  }, { signal: t }), e.addEventListener("volumechange", () => {
2052
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);
2053
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", () => {
2054
2168
  this.spinner.hidden = !1;
2055
2169
  }, { signal: t });
@@ -2062,17 +2176,16 @@ class Vt {
2062
2176
  if (!i || this.sourceController?.kind === "hls" || e.getAttribute("src") === null && !e.currentSrc) return;
2063
2177
  if ((i.code === MediaError.MEDIA_ERR_DECODE || /DEMUXER|PARSE|DECODE/i.test(i.message || "")) && this.decodeRecoveries < 2 && Number.isFinite(e.duration)) {
2064
2178
  this.decodeRecoveries++;
2065
- const n = e.currentTime, r = !e.paused;
2179
+ const n = e.currentTime, o = !e.paused;
2066
2180
  e.load();
2067
- const a = () => {
2181
+ const l = () => {
2068
2182
  try {
2069
2183
  e.currentTime = n;
2070
2184
  } catch {
2071
2185
  }
2072
- r && e.play().catch(() => {
2073
- });
2186
+ o && e.play().catch($);
2074
2187
  };
2075
- e.readyState >= 1 ? a() : e.addEventListener("loadedmetadata", a, { once: !0, signal: this.abort.signal });
2188
+ e.readyState >= 1 ? l() : e.addEventListener("loadedmetadata", l, { once: !0, signal: this.abort.signal });
2076
2189
  return;
2077
2190
  }
2078
2191
  this.emitter.emit("error", { message: i.message || `Media error (code ${i.code})`, cause: i, fatal: !0 });
@@ -2190,22 +2303,22 @@ class Vt {
2190
2303
  }
2191
2304
  }
2192
2305
  export {
2193
- it as Emitter,
2194
- Vt as Player,
2195
- Z as ThumbnailTrack,
2196
- at as buildHeatmapValues,
2197
- J as chapterAt,
2198
- st as defaultIcons,
2199
- H 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,
2200
2313
  _ as formatTime,
2201
- nt as getLocale,
2202
- ht as heatmapPath,
2203
- ft as isHlsSource,
2204
- vt as loadChaptersVtt,
2205
- z as normalizeChapters,
2206
- Nt as registerLocale,
2207
- qt as registerLocales,
2208
- Ft as registeredLanguages,
2209
- ct as resolveVast
2314
+ at as getLocale,
2315
+ ut as heatmapPath,
2316
+ bt as isHlsSource,
2317
+ yt as loadChaptersVtt,
2318
+ j as normalizeChapters,
2319
+ qt as registerLocale,
2320
+ Vt as registerLocales,
2321
+ Ot as registeredLanguages,
2322
+ pt as resolveVast
2210
2323
  };
2211
2324
  //# sourceMappingURL=core.js.map