@oddin-gg/havik-player 2.11.1 → 2.12.0

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/index.js CHANGED
@@ -110,42 +110,48 @@ function m(e) {
110
110
  return e instanceof Error ? e.message : String(e);
111
111
  }
112
112
  //#endregion
113
+ //#region src/core/warnOnce.ts
114
+ var h = /* @__PURE__ */ new Set();
115
+ function g(e, t = e) {
116
+ h.has(t) || (h.add(t), console.warn(`havik-player: ${e}`));
117
+ }
118
+ //#endregion
113
119
  //#region src/core/waitForLive.ts
114
- var h = 1e3, g = 3e4, _ = 6e5, ee = 3e5, te = 1e3, ne = {
120
+ var _ = 1e3, ee = 3e4, te = 6e5, ne = 3e5, re = 1e3, ie = {
115
121
  TOO_EARLY: "tooEarly",
116
122
  UNAVAILABLE: "unavailable",
117
123
  RATE_LIMITED: "rateLimited",
118
124
  NETWORK: "network"
119
125
  };
120
- function re(e) {
121
- let t = e === !0 || e === !1 ? {} : e, n = Math.max(te, t.floorMs ?? h), r = Math.max(n, t.ceilMs ?? g), i = Math.max(0, t.imminentMs ?? _), a = Math.max(r, t.sanityFloorMs ?? ee);
126
+ function ae(e) {
127
+ let t = e === !0 || e === !1 ? {} : e, n = Math.max(re, t.floorMs ?? _), r = Math.max(n, t.ceilMs ?? ee), i = Math.max(0, t.imminentMs ?? te), a = Math.max(r, t.sanityFloorMs ?? ne);
122
128
  return {
123
129
  timeoutMs: t.timeoutMs,
124
130
  floorMs: n,
125
131
  ceilMs: r,
126
132
  imminentMs: i,
127
133
  sanityFloorMs: a,
128
- kickoffMs: ie(t.kickoffAt),
134
+ kickoffMs: oe(t.kickoffAt),
129
135
  jitter: t.jitter ?? !0,
130
136
  onState: t.onState
131
137
  };
132
138
  }
133
- function ie(e) {
139
+ function oe(e) {
134
140
  if (e == null) return;
135
141
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
136
142
  let t = Date.parse(e);
137
143
  return Number.isFinite(t) ? t : void 0;
138
144
  }
139
- function ae(e, t, n) {
145
+ function se(e, t, n) {
140
146
  return Math.min(n, Math.max(t, e));
141
147
  }
142
- function oe(e) {
148
+ function ce(e) {
143
149
  return Math.round(e * (1 + .15 * Math.random()));
144
150
  }
145
- function se(e, t, n, r) {
151
+ function le(e, t, n, r) {
146
152
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
147
153
  if (a == null || a <= n.imminentMs) return {
148
- delay: ae(e ?? n.floorMs, o, n.ceilMs),
154
+ delay: se(e ?? n.floorMs, o, n.ceilMs),
149
155
  ttkMs: a
150
156
  };
151
157
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -154,7 +160,7 @@ function se(e, t, n, r) {
154
160
  ttkMs: a
155
161
  };
156
162
  }
157
- function ce(e, t) {
163
+ function ue(e, t) {
158
164
  return new Promise((r, i) => {
159
165
  if (t?.aborted) {
160
166
  i(new n("ABORTED", 0, "wait-for-live aborted"));
@@ -168,8 +174,8 @@ function ce(e, t) {
168
174
  t?.addEventListener("abort", a, { once: !0 });
169
175
  });
170
176
  }
171
- async function v(e, t, r) {
172
- let i = re(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
177
+ async function de(e, t, r) {
178
+ let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
173
179
  for (;;) {
174
180
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
175
181
  try {
@@ -177,38 +183,38 @@ async function v(e, t, r) {
177
183
  } catch (e) {
178
184
  if (!(e instanceof n) || !o(e.code)) throw e;
179
185
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
180
- let t = Date.now(), u = se(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
181
- if (i.jitter && (f = oe(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
186
+ let t = Date.now(), u = le(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
187
+ if (i.jitter && (f = ce(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
182
188
  retryAfterMs: e.retryAfterMs,
183
189
  cause: e
184
190
  });
185
191
  i.onState?.({
186
- phase: ne[e.code] ?? "unavailable",
192
+ phase: ie[e.code] ?? "unavailable",
187
193
  retryInMs: f,
188
194
  attempt: c,
189
195
  elapsedMs: t - a,
190
196
  ttkMs: d
191
- }), await ce(f, r);
197
+ }), await ue(f, r);
192
198
  }
193
199
  }
194
200
  }
195
201
  //#endregion
196
202
  //#region src/core/resolve.ts
197
- async function y(e) {
203
+ async function v(e) {
198
204
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
199
205
  let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
200
206
  credential: e.credential,
201
207
  signal: e.signal,
202
208
  apiHeaders: e.apiHeaders
203
209
  });
204
- if (!t.ok) throw await le(t);
205
- return de(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await fe(t);
211
+ return he(await t.json(), e.matchUrn);
206
212
  }
207
- function b(e) {
208
- let t = () => y(e);
209
- return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
213
+ function y(e) {
214
+ let t = () => v(e);
215
+ return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
210
216
  }
211
- async function le(e) {
217
+ async function fe(e) {
212
218
  let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
213
219
  try {
214
220
  let t = await e.json();
@@ -224,7 +230,7 @@ async function le(e) {
224
230
  liveStartsAtMs: s
225
231
  });
226
232
  }
227
- var ue = /* @__PURE__ */ new Set([
233
+ var pe = /* @__PURE__ */ new Set([
228
234
  "matchUrn",
229
235
  "protocol",
230
236
  "drmEnabled",
@@ -235,7 +241,7 @@ var ue = /* @__PURE__ */ new Set([
235
241
  "expiresAt",
236
242
  "analytics"
237
243
  ]);
238
- function x(e, t) {
244
+ function b(e, t) {
239
245
  let r;
240
246
  try {
241
247
  r = new URL(t);
@@ -245,57 +251,71 @@ function x(e, t) {
245
251
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
246
252
  return t;
247
253
  }
248
- function de(e, t) {
254
+ function me(e) {
255
+ if (e !== void 0) {
256
+ if (typeof e == "string" && !e.endsWith("/")) try {
257
+ let t = new URL(e);
258
+ if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
259
+ } catch {}
260
+ g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
+ }
262
+ }
263
+ function he(e, t) {
249
264
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
250
265
  let r = e.drmEnabled ?? !!e.drm, i = {
251
266
  matchUrn: e.matchUrn ?? t,
252
267
  protocol: "hls",
253
268
  drmEnabled: r,
254
- manifestUrl: x("manifestUrl", e.manifestUrl),
269
+ manifestUrl: b("manifestUrl", e.manifestUrl),
255
270
  serverTime: e.serverTime ?? ""
256
271
  };
257
- if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid && (i.analytics = { sid: e.analytics.sid }), r && e.drm) {
272
+ if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
273
+ i.analytics = { sid: e.analytics.sid };
274
+ let t = me(e.analytics.endpoint);
275
+ t && (i.analytics.endpoint = t);
276
+ }
277
+ if (r && e.drm) {
258
278
  let t = {};
259
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
260
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
261
- certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
279
+ e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
+ licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
+ certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
262
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
263
283
  }
264
284
  let a = {};
265
- for (let [t, n] of Object.entries(e)) ue.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
266
286
  return Object.keys(a).length > 0 && (i.extensions = a), i;
267
287
  }
268
288
  //#endregion
269
289
  //#region src/core/fullscreen.ts
270
- function S(e) {
290
+ function ge(e) {
271
291
  return e.ownerDocument ?? document;
272
292
  }
273
- function C(e) {
293
+ function _e(e) {
274
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
275
295
  }
276
- function w(e, t) {
277
- let n = C(S(e));
296
+ function x(e, t) {
297
+ let n = _e(ge(e));
278
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
279
299
  }
280
- async function T(e, t) {
300
+ async function S(e, t) {
281
301
  let n = t ?? e;
282
302
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
283
303
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
284
304
  let r = e;
285
305
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
286
306
  }
287
- async function E(e, t) {
307
+ async function C(e, t) {
288
308
  let n = e;
289
309
  if (n.webkitDisplayingFullscreen) {
290
310
  n.webkitExitFullscreen?.();
291
311
  return;
292
312
  }
293
- let r = S(e), i = C(r);
313
+ let r = ge(e), i = _e(r);
294
314
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
295
315
  }
296
316
  //#endregion
297
317
  //#region src/core/catalog.ts
298
- async function fe(e) {
318
+ async function ve(e) {
299
319
  let t = new URLSearchParams();
300
320
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
301
321
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -313,12 +333,12 @@ async function fe(e) {
313
333
  };
314
334
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
315
335
  return {
316
- tournaments: pe(await s.json()),
336
+ tournaments: ye(await s.json()),
317
337
  etag: s.headers.get("etag") ?? void 0,
318
338
  notModified: !1
319
339
  };
320
340
  }
321
- function pe(e) {
341
+ function ye(e) {
322
342
  return (e.tournaments ?? []).map((e) => {
323
343
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
324
344
  return {
@@ -340,7 +360,7 @@ function pe(e) {
340
360
  };
341
361
  });
342
362
  }
343
- async function me(e) {
363
+ async function be(e) {
344
364
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
345
365
  e.etag && i.set("If-None-Match", e.etag);
346
366
  let a = await p(t, {
@@ -360,13 +380,13 @@ async function me(e) {
360
380
  };
361
381
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
362
382
  return {
363
- tournament: he(await a.json()),
383
+ tournament: xe(await a.json()),
364
384
  etag: a.headers.get("etag") ?? void 0,
365
385
  notModified: !1,
366
386
  notFound: !1
367
387
  };
368
388
  }
369
- function he(e) {
389
+ function xe(e) {
370
390
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
371
391
  return {
372
392
  urn: t,
@@ -386,12 +406,12 @@ function he(e) {
386
406
  }))
387
407
  };
388
408
  }
389
- function ge(e) {
409
+ function Se(e) {
390
410
  return e.tournaments.flatMap((e) => e.matches);
391
411
  }
392
412
  //#endregion
393
413
  //#region src/core/poll.ts
394
- function _e(e) {
414
+ function Ce(e) {
395
415
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
396
416
  u || (a = setTimeout(m, t));
397
417
  }, m = async () => {
@@ -433,9 +453,9 @@ function _e(e) {
433
453
  }
434
454
  //#endregion
435
455
  //#region src/core/events.ts
436
- var ve = 45e3;
437
- function D(e) {
438
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ve, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
456
+ var we = 45e3;
457
+ function w(e) {
458
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
439
459
  if (a.signal.aborted) return t();
440
460
  let n = setTimeout(t, e);
441
461
  a.signal.addEventListener("abort", () => {
@@ -516,7 +536,7 @@ function D(e) {
516
536
  o || (o = !0, a.abort());
517
537
  } };
518
538
  }
519
- function O(e) {
539
+ function T(e) {
520
540
  try {
521
541
  let t = new URL(e);
522
542
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -526,27 +546,27 @@ function O(e) {
526
546
  }
527
547
  //#endregion
528
548
  //#region src/core/drm/deviceId.ts
529
- var k = "havik.player.deviceId", A;
530
- function j() {
531
- if (A) return A;
549
+ var E = "havik.player.deviceId", D;
550
+ function O() {
551
+ if (D) return D;
532
552
  try {
533
- let e = globalThis.localStorage?.getItem(k);
534
- if (e) return A = e, e;
553
+ let e = globalThis.localStorage?.getItem(E);
554
+ if (e) return D = e, e;
535
555
  } catch {}
536
- let e = be();
537
- A = e;
556
+ let e = Ee();
557
+ D = e;
538
558
  try {
539
- globalThis.localStorage?.setItem(k, e);
559
+ globalThis.localStorage?.setItem(E, e);
540
560
  } catch {}
541
561
  return e;
542
562
  }
543
- function ye() {
544
- A = void 0;
563
+ function Te() {
564
+ D = void 0;
545
565
  try {
546
- globalThis.localStorage?.removeItem(k);
566
+ globalThis.localStorage?.removeItem(E);
547
567
  } catch {}
548
568
  }
549
- function be() {
569
+ function Ee() {
550
570
  let e = globalThis.crypto;
551
571
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
552
572
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -558,21 +578,21 @@ function be() {
558
578
  }
559
579
  //#endregion
560
580
  //#region src/core/drm/headers.ts
561
- function xe(e, t, n = {}) {
581
+ function De(e, t, n = {}) {
562
582
  let r = {
563
583
  "x-api-key": t.apiKey,
564
584
  "X-Match-Urn": e.matchUrn,
565
- "X-Device-Id": n.deviceId ?? j(),
585
+ "X-Device-Id": n.deviceId ?? O(),
566
586
  "Content-Type": "application/octet-stream"
567
587
  };
568
588
  return n.userId && (r["X-User-Id"] = n.userId), r;
569
589
  }
570
590
  //#endregion
571
591
  //#region src/core/drm/cdm.ts
572
- var M = /* @__PURE__ */ new WeakMap();
573
- function Se(e, t) {
574
- let n = M.get(e);
575
- n || (n = /* @__PURE__ */ new Map(), M.set(e, n));
592
+ var k = /* @__PURE__ */ new WeakMap();
593
+ function Oe(e, t) {
594
+ let n = k.get(e);
595
+ n || (n = /* @__PURE__ */ new Map(), k.set(e, n));
576
596
  let r = n.get(t.keySystem);
577
597
  if (r) return r;
578
598
  let i = t.createMediaKeys().catch((e) => {
@@ -580,22 +600,22 @@ function Se(e, t) {
580
600
  });
581
601
  return n.set(t.keySystem, i), i;
582
602
  }
583
- function N() {
603
+ function A() {
584
604
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
585
605
  }
586
- var P = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
587
- function Ce(e) {
606
+ var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
607
+ function ke(e) {
588
608
  return e.startsWith("com.widevine");
589
609
  }
590
- function F(e, t) {
591
- if (!Ce(e)) return t;
610
+ function M(e, t) {
611
+ if (!ke(e)) return t;
592
612
  let n = (e, t) => {
593
613
  let n = e.videoCapabilities;
594
614
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
595
- let n = P.indexOf(e.robustness);
596
- return n === -1 || P.indexOf(t) > n;
615
+ let n = j.indexOf(e.robustness);
616
+ return n === -1 || j.indexOf(t) > n;
597
617
  });
598
- }, r = P.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
618
+ }, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
599
619
  ...t,
600
620
  videoCapabilities: t.videoCapabilities?.map((t) => ({
601
621
  ...t,
@@ -604,53 +624,53 @@ function F(e, t) {
604
624
  })));
605
625
  return [...t, ...r];
606
626
  }
607
- function we(e) {
608
- return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, F(t, n)).then((t) => ({
627
+ function N(e) {
628
+ return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
609
629
  keySystem: t.keySystem,
610
630
  getConfiguration: () => t.getConfiguration(),
611
- createMediaKeys: () => Se(e, t)
631
+ createMediaKeys: () => Oe(e, t)
612
632
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
613
633
  }
614
- var I = {
634
+ var P = {
615
635
  video: "SW_SECURE_DECODE",
616
636
  audio: "SW_SECURE_CRYPTO",
617
637
  scheme: "cbcs"
618
638
  };
619
- function Te(e) {
620
- if (!N()) return;
639
+ function Ae(e) {
640
+ if (!A()) return;
621
641
  let t = (e, t) => ({
622
642
  contentType: e,
623
643
  robustness: t,
624
- encryptionScheme: I.scheme
644
+ encryptionScheme: P.scheme
625
645
  });
626
- we(e)("com.widevine.alpha", [{
646
+ N(e)("com.widevine.alpha", [{
627
647
  initDataTypes: ["cenc"],
628
648
  distinctiveIdentifier: "optional",
629
649
  persistentState: "optional",
630
650
  sessionTypes: ["temporary"],
631
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
632
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
651
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", P.audio)],
652
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", P.video)]
633
653
  }]).then((e) => e.createMediaKeys()).catch(() => {});
634
654
  }
635
- function L(e) {
636
- let t = R(e);
655
+ function F(e) {
656
+ let t = I(e);
637
657
  if (/^avc[13]/.test(t)) return "avc";
638
658
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
639
659
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
640
660
  if (t.startsWith("av01")) return "av1";
641
661
  if (/^vp0?9/.test(t)) return "vp9";
642
662
  }
643
- function R(e) {
663
+ function I(e) {
644
664
  return (e ?? "").trim().toLowerCase();
645
665
  }
646
- var Ee = {
666
+ var je = {
647
667
  hevc: "hvc1.1.6.L93.90",
648
668
  dv: "dvh1.05.06",
649
669
  av1: "av01.0.05M.08",
650
670
  vp9: "vp09.00.10.08"
651
- }, De = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
652
- function Oe(e) {
653
- let t = R(e), n = De.get(t);
671
+ }, Me = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new Map();
672
+ function Ne(e) {
673
+ let t = I(e), n = Me.get(t);
654
674
  if (n) return n;
655
675
  let r = {
656
676
  initDataTypes: ["cenc"],
@@ -659,32 +679,32 @@ function Oe(e) {
659
679
  sessionTypes: ["temporary"],
660
680
  videoCapabilities: [{
661
681
  contentType: `video/mp4; codecs="${e.trim()}"`,
662
- robustness: I.video,
663
- encryptionScheme: I.scheme
682
+ robustness: P.video,
683
+ encryptionScheme: P.scheme
664
684
  }]
665
685
  }, i = (async () => {
666
686
  try {
667
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", F("com.widevine.alpha", [r])), !0;
687
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
668
688
  } catch {
669
689
  return !1;
670
690
  }
671
- })().then((e) => (z.set(t, e), e));
672
- return De.set(t, i), i;
691
+ })().then((e) => (L.set(t, e), e));
692
+ return Me.set(t, i), i;
673
693
  }
674
- function ke() {
675
- if (N()) for (let e of Object.values(Ee)) Oe(e);
694
+ function Pe() {
695
+ if (A()) for (let e of Object.values(je)) Ne(e);
676
696
  }
677
- function Ae(e) {
678
- let t = L(e);
679
- if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ee[t]));
697
+ function Fe(e) {
698
+ let t = F(e);
699
+ if (t) return t === "avc" ? !0 : L.get(I(e)) ?? L.get(I(je[t]));
680
700
  }
681
701
  //#endregion
682
702
  //#region src/core/drm/support.ts
683
- var je = 5e3, Me = "video/mp4; codecs=\"avc1.42E01E\"", B = "audio/mp4; codecs=\"mp4a.40.2\"", Ne = {
703
+ var Ie = 5e3, R = "video/mp4; codecs=\"avc1.42E01E\"", z = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
684
704
  widevine: ["com.widevine.alpha"],
685
705
  fairplay: ["com.apple.fps"]
686
706
  };
687
- function Pe(e) {
707
+ function Re(e) {
688
708
  return e === "fairplay" ? [{
689
709
  initDataTypes: [
690
710
  "sinf",
@@ -692,30 +712,30 @@ function Pe(e) {
692
712
  "cenc"
693
713
  ],
694
714
  videoCapabilities: [{
695
- contentType: Me,
715
+ contentType: R,
696
716
  robustness: "",
697
717
  encryptionScheme: "cbcs"
698
718
  }],
699
719
  audioCapabilities: [{
700
- contentType: B,
720
+ contentType: z,
701
721
  robustness: "",
702
722
  encryptionScheme: "cbcs"
703
723
  }]
704
- }] : F("com.widevine.alpha", [{
724
+ }] : M("com.widevine.alpha", [{
705
725
  initDataTypes: ["cenc"],
706
726
  videoCapabilities: [{
707
- contentType: Me,
708
- robustness: I.video,
709
- encryptionScheme: I.scheme
727
+ contentType: R,
728
+ robustness: P.video,
729
+ encryptionScheme: P.scheme
710
730
  }],
711
731
  audioCapabilities: [{
712
- contentType: B,
713
- robustness: I.audio,
714
- encryptionScheme: I.scheme
732
+ contentType: z,
733
+ robustness: P.audio,
734
+ encryptionScheme: P.scheme
715
735
  }]
716
736
  }]);
717
737
  }
718
- function V(e, t) {
738
+ function B(e, t) {
719
739
  return new Promise((n, r) => {
720
740
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
721
741
  e.then((e) => {
@@ -725,8 +745,8 @@ function V(e, t) {
725
745
  });
726
746
  });
727
747
  }
728
- async function Fe(e = {}) {
729
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? je, r = {};
748
+ async function ze(e = {}) {
749
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
730
750
  if (typeof window < "u" && window.isSecureContext === !1) return {
731
751
  verdict: "insecure-context",
732
752
  detail: r
@@ -738,7 +758,7 @@ async function Fe(e = {}) {
738
758
  };
739
759
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
740
760
  for (let e of t) {
741
- let t = Ne[e];
761
+ let t = Le[e];
742
762
  if (!t) {
743
763
  r[e] = "unknown system";
744
764
  continue;
@@ -749,7 +769,7 @@ async function Fe(e = {}) {
749
769
  break;
750
770
  }
751
771
  try {
752
- return await V((await V(i(n, Pe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
772
+ return await B((await B(i(n, Re(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
753
773
  verdict: "supported",
754
774
  system: e,
755
775
  detail: r
@@ -773,49 +793,49 @@ async function Fe(e = {}) {
773
793
  }
774
794
  //#endregion
775
795
  //#region src/core/manifest.ts
776
- var Ie = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
777
- function Le(e) {
778
- return Ie.test(e);
796
+ var Be = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
797
+ function Ve(e) {
798
+ return Be.test(e);
779
799
  }
780
800
  //#endregion
781
801
  //#region src/core/env.ts
782
- var H = {
802
+ var V = {
783
803
  integration: "https://feed-dev.oddin-video.gg",
784
804
  production: "https://feed.oddin-video.gg"
785
805
  };
786
- function U(e) {
787
- let t = Object.prototype.hasOwnProperty.call(H, e) ? H[e] : void 0;
806
+ function H(e) {
807
+ let t = Object.prototype.hasOwnProperty.call(V, e) ? V[e] : void 0;
788
808
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
789
809
  return t;
790
810
  }
791
811
  //#endregion
792
812
  //#region src/core/stats.ts
793
- var W = { droppedFrames: 0 };
794
- function G(e) {
813
+ var U = { droppedFrames: 0 };
814
+ function W(e) {
795
815
  try {
796
816
  return new URL(e).host;
797
817
  } catch {
798
818
  return "";
799
819
  }
800
820
  }
801
- var Re = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
802
- function ze(e) {
821
+ var He = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
822
+ function Ue(e) {
803
823
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
804
824
  let t = "", n = -1, r = performance.getEntriesByType("resource");
805
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Re.test(i.name)) && i.startTime >= n) {
806
- let e = G(i.name);
825
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || He.test(i.name)) && i.startTime >= n) {
826
+ let e = W(i.name);
807
827
  e && (t = e, n = i.startTime);
808
828
  }
809
829
  return t;
810
830
  }
811
- function K(e) {
831
+ function G(e) {
812
832
  let t = e.getVideoPlaybackQuality?.();
813
833
  return {
814
834
  dropped: t?.droppedVideoFrames ?? 0,
815
835
  totalFrames: t?.totalVideoFrames ?? 0
816
836
  };
817
837
  }
818
- function Be(e, t) {
838
+ function We(e, t) {
819
839
  let n = [
820
840
  ["playing", () => t("playing")],
821
841
  ["waiting", () => t("buffering")],
@@ -832,7 +852,7 @@ function Be(e, t) {
832
852
  }
833
853
  //#endregion
834
854
  //#region src/core/engine/native.ts
835
- function Ve(e) {
855
+ function Ge(e) {
836
856
  try {
837
857
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
838
858
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -840,15 +860,15 @@ function Ve(e) {
840
860
  return;
841
861
  }
842
862
  }
843
- function q(e) {
863
+ function K(e) {
844
864
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
845
865
  }
846
- function J() {
866
+ function q() {
847
867
  if (typeof window > "u") return !1;
848
868
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
849
869
  return e || t;
850
870
  }
851
- var Y = class {
871
+ var J = class {
852
872
  name = "native";
853
873
  deps;
854
874
  onLoaded;
@@ -884,7 +904,7 @@ var Y = class {
884
904
  type: "error",
885
905
  error: new n("INTERNAL", 0, "native HLS playback error"),
886
906
  fatal: !0
887
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = He(t.manifestUrl, t.analytics?.sid), e.load();
907
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ke(t.manifestUrl, t.analytics?.sid), e.load();
888
908
  }
889
909
  startLoad() {
890
910
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -906,7 +926,7 @@ var Y = class {
906
926
  });
907
927
  this.onEncrypted = (n) => {
908
928
  let i = n;
909
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ve(i.initData), (async () => {
929
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ge(i.initData), (async () => {
910
930
  try {
911
931
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
912
932
  initDataTypes: [i.initDataType],
@@ -1001,11 +1021,11 @@ var Y = class {
1001
1021
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
1002
1022
  }
1003
1023
  getStats() {
1004
- let e = this.deps.video, t = K(e), n = {
1024
+ let e = this.deps.video, t = G(e), n = {
1005
1025
  droppedFrames: t.dropped,
1006
1026
  decodedFrames: t.totalFrames
1007
1027
  };
1008
- return this.cdnHost ||= ze(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1028
+ return this.cdnHost ||= Ue(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1009
1029
  }
1010
1030
  stop() {
1011
1031
  try {
@@ -1024,13 +1044,13 @@ var Y = class {
1024
1044
  } catch {}
1025
1045
  }
1026
1046
  };
1027
- function He(e, t) {
1047
+ function Ke(e, t) {
1028
1048
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1029
1049
  }
1030
1050
  //#endregion
1031
1051
  //#region src/core/engine/prefetch.ts
1032
- var Ue = 15e3, We = 5e3, Ge = 6;
1033
- function Ke(e) {
1052
+ var qe = 15e3, Je = 5e3, Ye = 6;
1053
+ function Xe(e) {
1034
1054
  try {
1035
1055
  let t = new URL(e);
1036
1056
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1038,7 +1058,7 @@ function Ke(e) {
1038
1058
  return e;
1039
1059
  }
1040
1060
  }
1041
- var qe = class {
1061
+ var Ze = class {
1042
1062
  cmcd;
1043
1063
  entries = /* @__PURE__ */ new Map();
1044
1064
  keyed = /* @__PURE__ */ new Set();
@@ -1061,10 +1081,10 @@ var qe = class {
1061
1081
  }
1062
1082
  prefetch(e, t, n) {
1063
1083
  if (!this.isActive(t)) return;
1064
- let r = Ke(e);
1084
+ let r = Xe(e);
1065
1085
  if (this.entries.has(r)) return;
1066
1086
  let i = this.perTrack.get(t) ?? 0;
1067
- if (i >= Ge) return;
1087
+ if (i >= Ye) return;
1068
1088
  this.perTrack.set(t, i + 1);
1069
1089
  let a = new AbortController(), o = {
1070
1090
  started: performance.now(),
@@ -1078,10 +1098,10 @@ var qe = class {
1078
1098
  signal: a.signal
1079
1099
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1080
1100
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1081
- }, Ue);
1101
+ }, qe);
1082
1102
  }
1083
1103
  take(e) {
1084
- let t = Ke(e), n = this.entries.get(t);
1104
+ let t = Xe(e), n = this.entries.get(t);
1085
1105
  return n && this.entries.delete(t), n;
1086
1106
  }
1087
1107
  destroy() {
@@ -1101,13 +1121,13 @@ var qe = class {
1101
1121
  }
1102
1122
  }
1103
1123
  };
1104
- function Je(t) {
1124
+ function Qe(t) {
1105
1125
  let n = e.DefaultConfig?.loader;
1106
1126
  if (typeof n != "function") return;
1107
1127
  class r extends n {
1108
1128
  served = !1;
1109
1129
  cancelled = !1;
1110
- stats = Ye();
1130
+ stats = $e();
1111
1131
  load(e, n, r) {
1112
1132
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1113
1133
  if (!i) {
@@ -1115,7 +1135,7 @@ function Je(t) {
1115
1135
  return;
1116
1136
  }
1117
1137
  this.served = !0;
1118
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || We, s = setTimeout(() => {
1138
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Je, s = setTimeout(() => {
1119
1139
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1120
1140
  }, o);
1121
1141
  i.bytes.then((o) => {
@@ -1142,7 +1162,7 @@ function Je(t) {
1142
1162
  }
1143
1163
  return r;
1144
1164
  }
1145
- function Ye() {
1165
+ function $e() {
1146
1166
  return {
1147
1167
  aborted: !1,
1148
1168
  loaded: 0,
@@ -1166,10 +1186,10 @@ function Ye() {
1166
1186
  }
1167
1187
  };
1168
1188
  }
1169
- function Xe(e) {
1189
+ function et(e) {
1170
1190
  return e === "audio" ? "audio" : "main";
1171
1191
  }
1172
- function Ze(e, t) {
1192
+ function tt(e, t) {
1173
1193
  let n = [];
1174
1194
  t.initSegment?.url && !t.initSegment.data && n.push({
1175
1195
  url: t.initSegment.url,
@@ -1188,24 +1208,24 @@ function Ze(e, t) {
1188
1208
  }
1189
1209
  //#endregion
1190
1210
  //#region src/core/engine/hls.ts
1191
- function Qe() {
1211
+ function nt() {
1192
1212
  return e.isSupported();
1193
1213
  }
1194
- var $e = 3, et = 5, tt = 3, nt = 3e4, rt = 12e3, it = 3e3, at = 6e3, ot = 5e3, st = 4e3, ct = 2, lt = 5, ut = 2, dt = 2, ft = 4, pt = 4, mt = 2e3, ht = 3e4, gt = 2, _t = 9, vt = .5, yt = 64;
1195
- function bt(e) {
1214
+ var rt = 3, it = 5, at = 3, ot = 3e4, st = 12e3, ct = 3e3, lt = 6e3, ut = 5e3, dt = 4e3, ft = 2, pt = 5, mt = 2, ht = 2, gt = 4, _t = 4, vt = 2e3, yt = 3e4, bt = 2, xt = 9, St = .5, Ct = 64;
1215
+ function wt(e) {
1196
1216
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1197
1217
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1198
1218
  return;
1199
1219
  }
1200
- e.liveSyncDuration ??= gt;
1201
- let t = Math.max(12, e.liveSyncDuration + _t);
1202
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), xt(e, e.liveSyncDuration);
1220
+ e.liveSyncDuration ??= bt;
1221
+ let t = Math.max(12, e.liveSyncDuration + xt);
1222
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Tt(e, e.liveSyncDuration);
1203
1223
  }
1204
- function xt(e, t) {
1224
+ function Tt(e, t) {
1205
1225
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1206
1226
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1207
1227
  }
1208
- var St = class {
1228
+ var Et = class {
1209
1229
  name = "hls";
1210
1230
  hls = null;
1211
1231
  deps;
@@ -1273,7 +1293,7 @@ var St = class {
1273
1293
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1274
1294
  }
1275
1295
  async load() {
1276
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = q(r) && J(), o = !!e.drm?.widevine?.licenseUrl && !a;
1296
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = K(r) && q(), o = !!e.drm?.widevine?.licenseUrl && !a;
1277
1297
  if (e.drmEnabled && !o) {
1278
1298
  i({
1279
1299
  type: "error",
@@ -1282,7 +1302,7 @@ var St = class {
1282
1302
  });
1283
1303
  return;
1284
1304
  }
1285
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Te(r), ke()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1305
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1286
1306
  let e = this.hls;
1287
1307
  if (document.visibilityState !== "visible" || !e) return;
1288
1308
  let t = e.liveSyncPosition;
@@ -1305,7 +1325,7 @@ var St = class {
1305
1325
  }
1306
1326
  this.loadSuspended = !0;
1307
1327
  }
1308
- }, ot));
1328
+ }, ut));
1309
1329
  }
1310
1330
  resumeLoading() {
1311
1331
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1337,7 +1357,7 @@ var St = class {
1337
1357
  let t = e.liveSyncPosition;
1338
1358
  if (typeof t != "number" || !Number.isFinite(t)) return;
1339
1359
  let { video: n } = this.deps;
1340
- n.currentTime <= t + vt || (n.currentTime = t);
1360
+ n.currentTime <= t + St || (n.currentTime = t);
1341
1361
  }
1342
1362
  startHls() {
1343
1363
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1356,12 +1376,12 @@ var St = class {
1356
1376
  emeEnabled: !0,
1357
1377
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1358
1378
  drmSystemOptions: {
1359
- videoRobustness: I.video,
1360
- audioRobustness: I.audio,
1361
- videoEncryptionScheme: I.scheme,
1362
- audioEncryptionScheme: I.scheme
1379
+ videoRobustness: P.video,
1380
+ audioRobustness: P.audio,
1381
+ videoEncryptionScheme: P.scheme,
1382
+ audioEncryptionScheme: P.scheme
1363
1383
  },
1364
- ...N() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
1384
+ ...A() ? { requestMediaKeySystemAccessFunc: N(t) } : {},
1365
1385
  licenseXhrSetup: (e, t) => {
1366
1386
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
1367
1387
  let o = performance.now();
@@ -1378,20 +1398,20 @@ var St = class {
1378
1398
  ...c
1379
1399
  };
1380
1400
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1381
- let e = new qe({
1401
+ let e = new Ze({
1382
1402
  sessionId: n.analytics?.sid,
1383
1403
  contentId: n.matchUrn
1384
- }), t = Je(e);
1404
+ }), t = Qe(e);
1385
1405
  t && (this.prefetch = e, d.fLoader = t);
1386
1406
  }
1387
- bt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1407
+ wt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1388
1408
  let f = new e(d);
1389
1409
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1390
1410
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1391
1411
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1392
1412
  t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1393
1413
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1394
- }, nt)));
1414
+ }, ot)));
1395
1415
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1396
1416
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1397
1417
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1399,10 +1419,10 @@ var St = class {
1399
1419
  let n = t?.frag?.stats, r = n?.loaded;
1400
1420
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1401
1421
  let i = n?.loading;
1402
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > yt && this.requestTimesMs.shift());
1422
+ i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ct && this.requestTimesMs.shift());
1403
1423
  let a = t?.frag?.url;
1404
1424
  if (a) {
1405
- let e = G(a);
1425
+ let e = W(a);
1406
1426
  e && (this.cdnHost = e);
1407
1427
  }
1408
1428
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1416,15 +1436,15 @@ var St = class {
1416
1436
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1417
1437
  let t = this.prefetch;
1418
1438
  f.on(e.Events.KEY_LOADING, (e, n) => {
1419
- let r = n?.frag, i = Xe(r?.type);
1420
- if (r && t.isActive(i)) for (let e of Ze(f, r)) t.prefetch(e.url, i, e.kind);
1421
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Xe(n?.frag?.type)));
1439
+ let r = n?.frag, i = et(r?.type);
1440
+ if (r && t.isActive(i)) for (let e of tt(f, r)) t.prefetch(e.url, i, e.kind);
1441
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(et(n?.frag?.type)));
1422
1442
  }
1423
1443
  f.on(e.Events.KEY_LOADED, () => {
1424
1444
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1425
1445
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1426
1446
  this.checkEndStale(), this.checkStarvation();
1427
- }, it), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1447
+ }, ct), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1428
1448
  this.renditionSwitches += 1;
1429
1449
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1430
1450
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1488,7 +1508,7 @@ var St = class {
1488
1508
  return;
1489
1509
  }
1490
1510
  this.capTimer && clearTimeout(this.capTimer);
1491
- let t = e > this.sizeCapLevel ? mt : ht;
1511
+ let t = e > this.sizeCapLevel ? vt : yt;
1492
1512
  this.capTimer = setTimeout(() => {
1493
1513
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1494
1514
  }, t);
@@ -1498,9 +1518,9 @@ var St = class {
1498
1518
  this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
1499
1519
  }
1500
1520
  dropLevelsWidevineCannotPlay(e) {
1501
- this.removeLevelsWhere(e, (e) => Ae(e) !== !0);
1502
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
1503
- for (let n of t) Oe(n).then((t) => {
1521
+ this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1522
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && F(e) !== "avc" && !!F(e)));
1523
+ for (let n of t) Ne(n).then((t) => {
1504
1524
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1505
1525
  });
1506
1526
  }
@@ -1508,10 +1528,10 @@ var St = class {
1508
1528
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1509
1529
  if (n.forEach((e, n) => {
1510
1530
  let a = e.videoCodec;
1511
- a && L(a) && t(a) && (r.push(n), i.add(a));
1531
+ a && F(a) && t(a) && (r.push(n), i.add(a));
1512
1532
  }), !r.length) return !1;
1513
1533
  let a = [...i].join(", ");
1514
- if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Ae(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1534
+ if (!n.some((e, t) => r.includes(t) ? !1 : !F(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1515
1535
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1516
1536
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1517
1537
  }
@@ -1557,7 +1577,7 @@ var St = class {
1557
1577
  e.widevine && (this.licenseUrl = e.widevine);
1558
1578
  }
1559
1579
  getStats() {
1560
- let e = this.hls, t = K(this.deps.video), n = {
1580
+ let e = this.hls, t = G(this.deps.video), n = {
1561
1581
  droppedFrames: t.dropped,
1562
1582
  decodedFrames: t.totalFrames,
1563
1583
  lowLatency: this.detectedLowLatency,
@@ -1603,7 +1623,7 @@ var St = class {
1603
1623
  return;
1604
1624
  }
1605
1625
  let e = Date.now() - this.lastAdvanceMs;
1606
- !this.chaseSuspended && e > at && this.suspendChasing(), e > rt && this.emitEnded("stalled");
1626
+ !this.chaseSuspended && e > lt && this.suspendChasing(), e > st && this.emitEnded("stalled");
1607
1627
  }
1608
1628
  resetStarvationWindow() {
1609
1629
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1618,7 +1638,7 @@ var St = class {
1618
1638
  this.resetStarvationWindow();
1619
1639
  return;
1620
1640
  }
1621
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < at, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > st, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = K(t), c = o - s, l = c !== this.starvedFrames;
1641
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < lt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = G(t), c = o - s, l = c !== this.starvedFrames;
1622
1642
  if (this.starvedFrames = c, !a || l) {
1623
1643
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1624
1644
  return;
@@ -1627,12 +1647,12 @@ var St = class {
1627
1647
  this.resetStarvationWindow();
1628
1648
  return;
1629
1649
  }
1630
- if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > ft && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= ut && (this.clearKick(), this.starvationRebuilds < dt)) {
1650
+ if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > gt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mt && (this.clearKick(), this.starvationRebuilds < ht)) {
1631
1651
  this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
1632
1652
  return;
1633
1653
  }
1634
- let u = i && this.starvedTicks >= ct, d = !i && this.deadTicks >= ft && this.recentMainFrags.reduce((e, t) => e + t, 0) >= pt;
1635
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= lt))) {
1654
+ let u = i && this.starvedTicks >= ft, d = !i && this.deadTicks >= gt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _t;
1655
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pt))) {
1636
1656
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1637
1657
  try {
1638
1658
  e.stopLoad(), e.startLoad(-1);
@@ -1681,7 +1701,7 @@ var St = class {
1681
1701
  scheduleLicenseRetry(t) {
1682
1702
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1683
1703
  let n = t.response?.code ?? 0;
1684
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= tt) return !1;
1704
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= at) return !1;
1685
1705
  this.licenseRecoveries += 1;
1686
1706
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1687
1707
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1713,7 +1733,7 @@ var St = class {
1713
1733
  return;
1714
1734
  }
1715
1735
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1716
- if (this.networkRecoveries < et) {
1736
+ if (this.networkRecoveries < it) {
1717
1737
  this.networkRecoveries += 1;
1718
1738
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1719
1739
  this.networkRetryTimer = setTimeout(() => {
@@ -1730,7 +1750,7 @@ var St = class {
1730
1750
  return;
1731
1751
  }
1732
1752
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1733
- if (this.mediaRecoveries < $e) {
1753
+ if (this.mediaRecoveries < rt) {
1734
1754
  this.mediaRecoveries += 1, n.recoverMediaError();
1735
1755
  return;
1736
1756
  }
@@ -1754,19 +1774,19 @@ var St = class {
1754
1774
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1755
1775
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1756
1776
  }
1757
- }, Ct = 15e3, wt = 6e5, Tt = 3e5, Et = 100, X = 1, Dt = 1e3, Ot = 3e4, kt = 1e3, At = {
1777
+ }, Dt = 15e3, Ot = 6e5, kt = 3e5, At = 100, Y = 1, jt = 1e3, Mt = 3e4, Nt = 1e3, Pt = {
1758
1778
  inline: "PRESENTATION_INLINE",
1759
1779
  fullscreen: "PRESENTATION_FULLSCREEN",
1760
1780
  pip: "PRESENTATION_PIP"
1761
- }, jt = {
1781
+ }, Ft = {
1762
1782
  widevine: "KEY_SYSTEM_WIDEVINE",
1763
1783
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1764
1784
  none: "KEY_SYSTEM_NONE"
1765
1785
  };
1766
- function Mt(e, t) {
1786
+ function It(e, t) {
1767
1787
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1768
1788
  }
1769
- var Nt = /* @__PURE__ */ new Set([
1789
+ var Lt = /* @__PURE__ */ new Set([
1770
1790
  "INVALID_URN",
1771
1791
  "NOT_FOUND",
1772
1792
  "GONE",
@@ -1776,7 +1796,7 @@ var Nt = /* @__PURE__ */ new Set([
1776
1796
  "FORBIDDEN",
1777
1797
  "RATE_LIMITED",
1778
1798
  "TIMEOUT"
1779
- ]), Z = {
1799
+ ]), X = {
1780
1800
  idle: "PLAYER_STATE_IDLE",
1781
1801
  waiting: "PLAYER_STATE_WAITING",
1782
1802
  loading: "PLAYER_STATE_LOADING",
@@ -1786,7 +1806,7 @@ var Nt = /* @__PURE__ */ new Set([
1786
1806
  ended: "PLAYER_STATE_ENDED",
1787
1807
  error: "PLAYER_STATE_ERROR"
1788
1808
  };
1789
- function Pt(e) {
1809
+ function Rt(e) {
1790
1810
  try {
1791
1811
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1792
1812
  return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
@@ -1794,24 +1814,25 @@ function Pt(e) {
1794
1814
  return;
1795
1815
  }
1796
1816
  }
1797
- var Ft = /* @__PURE__ */ new Set();
1798
- function It(e, t) {
1799
- return Ft.has(e) || (Ft.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
1817
+ var zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase();
1818
+ function Bt(e, t) {
1819
+ return g(t, e), { disabledReason: t };
1800
1820
  }
1801
- function Lt(e, t) {
1821
+ function Vt(e, t, n) {
1822
+ if (n) return t && !zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1802
1823
  if (t) return { endpoint: t };
1803
- if (t !== void 0) return It("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
1804
- let n = Pt(e);
1805
- if (n) return { endpoint: n };
1806
- let r;
1824
+ if (t !== void 0) return Bt("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
1825
+ let r = Rt(e);
1826
+ if (r) return { endpoint: r };
1827
+ let i;
1807
1828
  try {
1808
- r = new URL(e).hostname || e;
1829
+ i = new URL(e).hostname || e;
1809
1830
  } catch {
1810
- r = e;
1831
+ i = e;
1811
1832
  }
1812
- return It(r, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${r}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
1833
+ return Bt(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
1813
1834
  }
1814
- var Rt = class {
1835
+ var Ht = class {
1815
1836
  opts;
1816
1837
  url;
1817
1838
  now;
@@ -1891,8 +1912,8 @@ var Rt = class {
1891
1912
  constructor(e) {
1892
1913
  this.opts = {
1893
1914
  ...e,
1894
- heartbeatMs: e.heartbeatMs ?? Ct,
1895
- idleMs: e.idleMs ?? wt
1915
+ heartbeatMs: e.heartbeatMs ?? Dt,
1916
+ idleMs: e.idleMs ?? Ot
1896
1917
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1897
1918
  }
1898
1919
  start() {
@@ -1902,11 +1923,11 @@ var Rt = class {
1902
1923
  sdkVersion: this.opts.sdkVersion,
1903
1924
  ...this.opts.environment
1904
1925
  };
1905
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Dt), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
1926
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), jt), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
1906
1927
  }
1907
1928
  checkSuspension(e) {
1908
1929
  if (this.endedFlag || !this.opts.idleMs) return !1;
1909
- let t = Math.max(this.opts.idleMs, Tt);
1930
+ let t = Math.max(this.opts.idleMs, kt);
1910
1931
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1911
1932
  }
1912
1933
  syncIdle(e) {
@@ -1920,21 +1941,21 @@ var Rt = class {
1920
1941
  noteStateChange(e, t, n, r) {
1921
1942
  if (this.endedFlag || e === t) return;
1922
1943
  let i = this.now();
1923
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(X, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(X, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1944
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Y, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Y, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1924
1945
  this.stallIsSeekInduced = this.seekInduced(i);
1925
1946
  let e = !this.isHidden && !this.stallIsSeekInduced;
1926
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(X, Math.round(this.playingTotalMs)));
1947
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
1927
1948
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1928
1949
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1929
1950
  let a = {
1930
- fromState: Z[e] ?? "PLAYER_STATE_UNSPECIFIED",
1931
- toState: Z[t] ?? "PLAYER_STATE_UNSPECIFIED",
1932
- presentation: At[this.presentation]
1951
+ fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
1952
+ toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
1953
+ presentation: Pt[this.presentation]
1933
1954
  }, o = this.causeOf(e, t, i);
1934
1955
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1935
1956
  }
1936
1957
  seekInduced(e) {
1937
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < kt;
1958
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Nt;
1938
1959
  }
1939
1960
  causeOf(e, t, n) {
1940
1961
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1971,25 +1992,25 @@ var Rt = class {
1971
1992
  }
1972
1993
  this.muteChanges += 1;
1973
1994
  let r = this.now();
1974
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(X, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1995
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Y, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1975
1996
  }
1976
1997
  notePresentation(e) {
1977
1998
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1978
1999
  }
1979
2000
  notePlayIntent() {
1980
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = X), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = X), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = X), this.drmSetupMs > 0 && (this.drmSetupMs = X));
2001
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Y), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Y), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Y), this.drmSetupMs > 0 && (this.drmSetupMs = Y));
1981
2002
  }
1982
2003
  noteReady() {
1983
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
2004
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
1984
2005
  }
1985
2006
  noteFirstPlaylist() {
1986
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(X, this.now() - this.startupAnchorMs));
2007
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
1987
2008
  }
1988
2009
  noteDrmReady() {
1989
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(X, this.now() - this.startupAnchorMs));
2010
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
1990
2011
  }
1991
2012
  noteFirstBytes() {
1992
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
2013
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
1993
2014
  }
1994
2015
  noteSeek() {
1995
2016
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2008,7 +2029,7 @@ var Rt = class {
2008
2029
  let r = n ?? "";
2009
2030
  if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
2010
2031
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2011
- if (Nt.has(e)) return "ERROR_STAGE_RESOLVE";
2032
+ if (Lt.has(e)) return "ERROR_STAGE_RESOLVE";
2012
2033
  let i = t ?? "";
2013
2034
  return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
2014
2035
  }
@@ -2040,7 +2061,7 @@ var Rt = class {
2040
2061
  let l = t.droppedFrames ?? 0;
2041
2062
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2042
2063
  let u = t.renditionSwitches ?? 0;
2043
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = Z[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2064
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = X[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2044
2065
  let d = this.mutedTotalMs;
2045
2066
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2046
2067
  let f = t.upshifts ?? 0;
@@ -2055,14 +2076,14 @@ var Rt = class {
2055
2076
  if (this.lastRequestCount = g, _ > 0) {
2056
2077
  o.requestCountDelta = _;
2057
2078
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2058
- n.length > 0 && (o.requestTimeP50Ms = Mt(n, 50), o.requestTimeP95Ms = Mt(n, 95));
2079
+ n.length > 0 && (o.requestTimeP50Ms = It(n, 50), o.requestTimeP95Ms = It(n, 95));
2059
2080
  }
2060
2081
  typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
2061
2082
  }
2062
2083
  maybeEmitMediaInfo(e) {
2063
2084
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2064
2085
  let t = {};
2065
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = jt[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2086
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Ft[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2066
2087
  let n = JSON.stringify(t);
2067
2088
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2068
2089
  }
@@ -2082,7 +2103,7 @@ var Rt = class {
2082
2103
  let c = r?.positionMs ?? 0;
2083
2104
  c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
2084
2105
  let l = e !== "END_REASON_ENDED";
2085
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Ot && (i.abandonAfterStallMs = Math.max(X, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ot && (i.abandonAfterErrorMs = Math.max(X, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2106
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Mt && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Mt && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2086
2107
  let u = r?.decodedFrames ?? this.lastDecoded;
2087
2108
  u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
2088
2109
  }
@@ -2102,7 +2123,7 @@ var Rt = class {
2102
2123
  };
2103
2124
  }
2104
2125
  enqueue(e) {
2105
- for (this.pending.push(this.wrap(e)); this.pending.length > Et;) {
2126
+ for (this.pending.push(this.wrap(e)); this.pending.length > At;) {
2106
2127
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2107
2128
  this.pending.splice(e >= 0 ? e : 0, 1);
2108
2129
  }
@@ -2125,7 +2146,7 @@ var Rt = class {
2125
2146
  };
2126
2147
  //#endregion
2127
2148
  //#region src/core/environment.ts
2128
- function zt() {
2149
+ function Ut() {
2129
2150
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2130
2151
  let e;
2131
2152
  try {
@@ -2150,14 +2171,14 @@ function zt() {
2150
2171
  integration: "INTEGRATION_KIND_IFRAME"
2151
2172
  };
2152
2173
  }
2153
- function Bt() {
2174
+ function Wt() {
2154
2175
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2155
2176
  let e = navigator.userAgentData, t = e?.platform ?? "";
2156
2177
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2157
2178
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2158
2179
  return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
2159
2180
  }
2160
- function Vt() {
2181
+ function Gt() {
2161
2182
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2162
2183
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2163
2184
  let t = {
@@ -2176,17 +2197,17 @@ function Vt() {
2176
2197
  }
2177
2198
  return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
2178
2199
  }
2179
- function Ht(e) {
2180
- let t = zt(), n = {
2181
- deviceClass: Bt(),
2200
+ function Kt(e) {
2201
+ let t = Ut(), n = {
2202
+ deviceClass: Wt(),
2182
2203
  integration: t.integration,
2183
- ...Vt()
2204
+ ...Gt()
2184
2205
  };
2185
2206
  t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
2186
2207
  let r = e.getBoundingClientRect?.();
2187
2208
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2188
2209
  }
2189
- async function Ut() {
2210
+ async function qt() {
2190
2211
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2191
2212
  if (!e?.getHighEntropyValues) return {};
2192
2213
  try {
@@ -2198,7 +2219,7 @@ async function Ut() {
2198
2219
  }
2199
2220
  //#endregion
2200
2221
  //#region src/core/version.ts
2201
- var Wt = "2.11.1", Gt = {
2222
+ var Jt = "2.12.0", Yt = {
2202
2223
  accent: "#E1B600",
2203
2224
  accentText: "#1B1C23",
2204
2225
  background: "#0e0f13",
@@ -2209,7 +2230,7 @@ var Wt = "2.11.1", Gt = {
2209
2230
  border: "rgba(255, 255, 255, 0.1)",
2210
2231
  radius: "8px",
2211
2232
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2212
- }, Kt = {
2233
+ }, Xt = {
2213
2234
  accent: "--havik-accent",
2214
2235
  accentText: "--havik-accent-text",
2215
2236
  background: "--havik-bg",
@@ -2221,25 +2242,25 @@ var Wt = "2.11.1", Gt = {
2221
2242
  radius: "--havik-radius",
2222
2243
  fontFamily: "--havik-font"
2223
2244
  };
2224
- function qt(e, t) {
2245
+ function Zt(e, t) {
2225
2246
  let n = {
2226
- ...Gt,
2247
+ ...Yt,
2227
2248
  ...t
2228
2249
  };
2229
- for (let t of Object.keys(Kt)) e.style.setProperty(Kt[t], n[t]);
2250
+ for (let t of Object.keys(Xt)) e.style.setProperty(Xt[t], n[t]);
2230
2251
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2231
2252
  }
2232
2253
  //#endregion
2233
2254
  //#region src/ui/styles.ts
2234
- var Jt = "havik-player-styles", Yt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
2235
- function Xt(e = document) {
2236
- if (e.getElementById(Jt)) return;
2255
+ var Qt = "havik-player-styles", $t = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
2256
+ function en(e = document) {
2257
+ if (e.getElementById(Qt)) return;
2237
2258
  let t = e.createElement("style");
2238
- t.id = Jt, t.textContent = Yt, e.head.appendChild(t);
2259
+ t.id = Qt, t.textContent = $t, e.head.appendChild(t);
2239
2260
  }
2240
2261
  //#endregion
2241
2262
  //#region src/ui/icons.ts
2242
- var Zt = {
2263
+ var tn = {
2243
2264
  play: "<path d=\"M8 5v14l11-7z\"/>",
2244
2265
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2245
2266
  volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
@@ -2252,21 +2273,21 @@ var Zt = {
2252
2273
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
2253
2274
  retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
2254
2275
  };
2255
- function Q(e) {
2256
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Zt[e]}</svg>`;
2276
+ function Z(e) {
2277
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${tn[e]}</svg>`;
2257
2278
  }
2258
2279
  //#endregion
2259
2280
  //#region src/ui/controls.ts
2260
- var Qt = 3e3, $t = /* @__PURE__ */ new Set([
2281
+ var nn = 3e3, rn = /* @__PURE__ */ new Set([
2261
2282
  "GONE",
2262
2283
  "NOT_FOUND",
2263
2284
  "INVALID_URN",
2264
2285
  "UNAUTHORIZED"
2265
2286
  ]);
2266
- function en(e) {
2267
- return new tn(e);
2287
+ function an(e) {
2288
+ return new on(e);
2268
2289
  }
2269
- var tn = class {
2290
+ var on = class {
2270
2291
  root;
2271
2292
  video;
2272
2293
  player;
@@ -2308,7 +2329,7 @@ var tn = class {
2308
2329
  scrubbing = !1;
2309
2330
  offFns = [];
2310
2331
  constructor(e) {
2311
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Qt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Xt(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2332
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? nn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, en(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2312
2333
  let t = (e, t, n) => {
2313
2334
  let r = this.doc.createElement(e);
2314
2335
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2319,12 +2340,12 @@ var tn = class {
2319
2340
  "aria-label": r,
2320
2341
  title: r
2321
2342
  });
2322
- return i.innerHTML = Q(n), i;
2343
+ return i.innerHTML = Z(n), i;
2323
2344
  };
2324
2345
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
2325
2346
  type: "button",
2326
2347
  "aria-label": "Play"
2327
- }), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2348
+ }), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2328
2349
  role: "slider",
2329
2350
  "aria-label": "Seek",
2330
2351
  "aria-valuemin": "0",
@@ -2342,7 +2363,7 @@ var tn = class {
2342
2363
  "aria-label": "Volume"
2343
2364
  });
2344
2365
  let a = t("div", "havik-vol");
2345
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
2366
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
2346
2367
  let o = this.doc.createElement("span");
2347
2368
  o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
2348
2369
  let s = t("div", "havik-spacer");
@@ -2396,12 +2417,12 @@ var tn = class {
2396
2417
  }
2397
2418
  if (e === "preplay") {
2398
2419
  let e = this.doc.createElement("button");
2399
- e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2420
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2400
2421
  } else {
2401
2422
  let r = this.doc.createElement("div");
2402
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !$t.has(this.lastError.code)) {
2423
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !rn.has(this.lastError.code)) {
2403
2424
  let e = this.doc.createElement("button");
2404
- e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2425
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2405
2426
  }
2406
2427
  }
2407
2428
  this.root.append(n), this.statusBox = n, this.show();
@@ -2440,7 +2461,7 @@ var tn = class {
2440
2461
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2441
2462
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2442
2463
  }
2443
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${nn(this.video.currentTime)} / ${nn(this.video.duration)}`);
2464
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Q(this.video.currentTime)} / ${Q(this.video.duration)}`);
2444
2465
  }
2445
2466
  syncLive() {
2446
2467
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2490,17 +2511,17 @@ var tn = class {
2490
2511
  renderQualityMenu() {
2491
2512
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2492
2513
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2493
- for (let n of e) this.menu.append(this.menuItem(rn(n), t === n.index, () => this.player.setQuality(n.index)));
2514
+ for (let n of e) this.menu.append(this.menuItem(sn(n), t === n.index, () => this.player.setQuality(n.index)));
2494
2515
  }
2495
2516
  renderAudioMenu() {
2496
2517
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2497
2518
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2498
- for (let t of e) this.menu.append(this.menuItem(an(t), t.default, () => this.player.setAudioTrack(t.id)));
2519
+ for (let t of e) this.menu.append(this.menuItem(cn(t), t.default, () => this.player.setAudioTrack(t.id)));
2499
2520
  }
2500
2521
  renderCcMenu() {
2501
2522
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2502
2523
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2503
- for (let t of e) this.menu.append(this.menuItem(on(t), !1, () => this.player.setTextTrack(t.id)));
2524
+ for (let t of e) this.menu.append(this.menuItem(ln(t), !1, () => this.player.setTextTrack(t.id)));
2504
2525
  }
2505
2526
  onTracksChanged() {
2506
2527
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2520,11 +2541,11 @@ var tn = class {
2520
2541
  }
2521
2542
  async toggleFullscreen() {
2522
2543
  try {
2523
- w(this.video, this.root) ? await E(this.video, this.root) : await T(this.video, this.root);
2544
+ x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
2524
2545
  } catch {}
2525
2546
  }
2526
2547
  syncFullscreen() {
2527
- let e = w(this.video, this.root);
2548
+ let e = x(this.video, this.root);
2528
2549
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2529
2550
  }
2530
2551
  poke() {
@@ -2583,7 +2604,7 @@ var tn = class {
2583
2604
  }
2584
2605
  }
2585
2606
  setIcon(e, t) {
2586
- e.innerHTML = Q(t);
2607
+ e.innerHTML = Z(t);
2587
2608
  }
2588
2609
  destroy() {
2589
2610
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2600,41 +2621,41 @@ var tn = class {
2600
2621
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2601
2622
  }
2602
2623
  };
2603
- function nn(e) {
2624
+ function Q(e) {
2604
2625
  (!Number.isFinite(e) || e < 0) && (e = 0);
2605
2626
  let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
2606
2627
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2607
2628
  }
2608
- function rn(e) {
2629
+ function sn(e) {
2609
2630
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2610
2631
  }
2611
- function an(e) {
2632
+ function cn(e) {
2612
2633
  return e.name || e.lang || `Track ${e.id}`;
2613
2634
  }
2614
- function on(e) {
2635
+ function ln(e) {
2615
2636
  return e.name || e.lang || `Track ${e.id}`;
2616
2637
  }
2617
2638
  //#endregion
2618
2639
  //#region src/managed/index.ts
2619
- var sn = 6e3, cn = 45e3, ln = 2e3, un = 3, dn = 2e3, fn = 48e4;
2620
- function pn(e) {
2640
+ var un = 6e3, dn = 45e3, fn = 2e3, pn = 3, mn = 2e3, hn = 48e4;
2641
+ function gn(e) {
2621
2642
  if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
2622
- if (e.env !== void 0) return U(e.env);
2643
+ if (e.env !== void 0) return H(e.env);
2623
2644
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2624
2645
  return e.baseUrl;
2625
2646
  }
2626
- async function mn(e) {
2647
+ async function _n(e) {
2627
2648
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2628
- let t = pn(e);
2649
+ let t = gn(e);
2629
2650
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2630
2651
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2631
- let r = new hn({
2652
+ let r = new vn({
2632
2653
  ...e,
2633
2654
  baseUrl: t
2634
2655
  });
2635
2656
  return await r.start(), r;
2636
2657
  }
2637
- var hn = class {
2658
+ var vn = class {
2638
2659
  opts;
2639
2660
  abort = new AbortController();
2640
2661
  listeners = {};
@@ -2678,7 +2699,7 @@ var hn = class {
2678
2699
  this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
2679
2700
  let e = ++this.loadGen, t = this.resolveOptions();
2680
2701
  try {
2681
- let n = await y(t);
2702
+ let n = await v(t);
2682
2703
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2683
2704
  let e = this._lastError;
2684
2705
  throw this.destroy(), e;
@@ -2701,11 +2722,11 @@ var hn = class {
2701
2722
  };
2702
2723
  }
2703
2724
  beginArming(e, t, n = !1) {
2704
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2725
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
2705
2726
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2706
2727
  }
2707
2728
  beginArmingByPolling(e) {
2708
- b({
2729
+ y({
2709
2730
  ...this.resolveOptions(),
2710
2731
  signal: this.abort.signal,
2711
2732
  waitForLive: this.buildWaitConfig(e)
@@ -2722,7 +2743,7 @@ var hn = class {
2722
2743
  setTimeout(() => {
2723
2744
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2724
2745
  phase: i ? "unavailable" : "tooEarly",
2725
- retryInMs: cn,
2746
+ retryInMs: dn,
2726
2747
  attempt: 1,
2727
2748
  elapsedMs: 0,
2728
2749
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2739,7 +2760,7 @@ var hn = class {
2739
2760
  }
2740
2761
  }
2741
2762
  }, h = () => {
2742
- a || s || p() || (s = !0, b({
2763
+ a || s || p() || (s = !0, y({
2743
2764
  ...this.resolveOptions(),
2744
2765
  signal: c.signal,
2745
2766
  waitForLive: this.buildWaitConfig(e)
@@ -2747,7 +2768,7 @@ var hn = class {
2747
2768
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
2748
2769
  }));
2749
2770
  }, g = () => {
2750
- a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2771
+ a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2751
2772
  if (!(a || p())) {
2752
2773
  if (e instanceof n && o(e.code)) {
2753
2774
  h();
@@ -2761,13 +2782,13 @@ var hn = class {
2761
2782
  !a && !p() && h();
2762
2783
  }, e);
2763
2784
  };
2764
- _(sn), this.armingSub = D({
2785
+ _(un), this.armingSub = w({
2765
2786
  eventsBaseUrl: t,
2766
2787
  matchUrn: this.opts.matchUrn,
2767
2788
  credential: this.opts.credential,
2768
- onAlive: () => _(cn),
2789
+ onAlive: () => _(dn),
2769
2790
  onState: (e) => {
2770
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * ln);
2791
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * fn);
2771
2792
  },
2772
2793
  onError: () => h()
2773
2794
  });
@@ -2790,7 +2811,7 @@ var hn = class {
2790
2811
  let n = await s(this.opts.credential);
2791
2812
  if (this.destroyed || t !== this.loadGen) return;
2792
2813
  this.setState("loading");
2793
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Be(this.opts.video, (e) => {
2814
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = We(this.opts.video, (e) => {
2794
2815
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2795
2816
  });
2796
2817
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2812,23 +2833,23 @@ var hn = class {
2812
2833
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2813
2834
  let i = e.analytics?.sid;
2814
2835
  if (!i) return;
2815
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Lt(this.opts.baseUrl, a);
2836
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Vt(this.opts.baseUrl, a, e.analytics?.endpoint);
2816
2837
  if (!o) {
2817
2838
  s && setTimeout(() => {
2818
2839
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2819
2840
  }, 0);
2820
2841
  return;
2821
2842
  }
2822
- let c = this.opts.video, l = new Rt({
2843
+ let c = this.opts.video, l = new Ht({
2823
2844
  endpoint: o,
2824
2845
  sid: i,
2825
2846
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2826
- sdkVersion: Wt,
2827
- environment: Ht(c),
2847
+ sdkVersion: Jt,
2848
+ environment: Kt(c),
2828
2849
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2829
2850
  onIdle: () => this.onAnalyticsIdle(t),
2830
2851
  sample: () => {
2831
- let e = this.engine?.getStats() ?? W, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2852
+ let e = this.engine?.getStats() ?? U, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2832
2853
  return {
2833
2854
  ...e,
2834
2855
  bufferedMs: Math.round(t * 1e3),
@@ -2842,7 +2863,7 @@ var hn = class {
2842
2863
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2843
2864
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2844
2865
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
2845
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Ut().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2866
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), qt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2846
2867
  }
2847
2868
  currentPresentation() {
2848
2869
  let e = this.opts.video;
@@ -2857,7 +2878,7 @@ var hn = class {
2857
2878
  video: this.opts.video,
2858
2879
  descriptor: e,
2859
2880
  credential: t,
2860
- deviceId: j(),
2881
+ deviceId: O(),
2861
2882
  userId: this.opts.userId,
2862
2883
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
2863
2884
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -2867,11 +2888,11 @@ var hn = class {
2867
2888
  hlsConfig: i,
2868
2889
  emit: (e) => this.onEngineEvent(e)
2869
2890
  }, o = this.opts.engine ?? "auto";
2870
- if (o === "native") return new Y(a);
2871
- if (o === "hls") return new St(a);
2872
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && q(this.opts.video) && J()) return new Y(a);
2873
- if (Qe()) return new St(a);
2874
- if (q(this.opts.video)) return new Y(a);
2891
+ if (o === "native") return new J(a);
2892
+ if (o === "hls") return new Et(a);
2893
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && K(this.opts.video) && q()) return new J(a);
2894
+ if (nt()) return new Et(a);
2895
+ if (K(this.opts.video)) return new J(a);
2875
2896
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2876
2897
  }
2877
2898
  onEngineEvent(e) {
@@ -2908,11 +2929,11 @@ var hn = class {
2908
2929
  }
2909
2930
  startLiveState(e) {
2910
2931
  if (this.opts.liveStateEvents === !1) return;
2911
- let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2932
+ let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
2912
2933
  if (!t) return;
2913
2934
  this.closeLiveState();
2914
2935
  let r = 0, i = !1;
2915
- this.liveStateSub = D({
2936
+ this.liveStateSub = w({
2916
2937
  eventsBaseUrl: t,
2917
2938
  matchUrn: this.opts.matchUrn,
2918
2939
  credential: this.opts.credential,
@@ -2923,7 +2944,7 @@ var hn = class {
2923
2944
  r = 0, i = !1;
2924
2945
  },
2925
2946
  onError: () => {
2926
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= un && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2947
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= pn && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2927
2948
  }
2928
2949
  });
2929
2950
  }
@@ -2945,7 +2966,7 @@ var hn = class {
2945
2966
  scheduleRejoin(e) {
2946
2967
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2947
2968
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2948
- }, Math.random() * ln));
2969
+ }, Math.random() * fn));
2949
2970
  }
2950
2971
  cancelRejoin() {
2951
2972
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2969,7 +2990,7 @@ var hn = class {
2969
2990
  }
2970
2991
  t.controls = !1;
2971
2992
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2972
- r && r.insertBefore(n, t), n.appendChild(t), qt(n, this.opts.theme), this.container = n, this.controlBar = en({
2993
+ r && r.insertBefore(n, t), n.appendChild(t), Zt(n, this.opts.theme), this.container = n, this.controlBar = an({
2973
2994
  root: n,
2974
2995
  video: t,
2975
2996
  player: this,
@@ -2999,7 +3020,7 @@ var hn = class {
2999
3020
  }
3000
3021
  startStats() {
3001
3022
  this.stopStats();
3002
- let e = Math.max(500, this.opts.statsIntervalMs ?? dn);
3023
+ let e = Math.max(500, this.opts.statsIntervalMs ?? mn);
3003
3024
  this.statsTimer = setInterval(() => {
3004
3025
  if (!this.engine) return;
3005
3026
  let e = this.engine.getStats();
@@ -3011,7 +3032,7 @@ var hn = class {
3011
3032
  }
3012
3033
  scheduleLicenseRefresh() {
3013
3034
  this.stopRefresh();
3014
- let e = this.opts.licenseRefreshMs ?? fn;
3035
+ let e = this.opts.licenseRefreshMs ?? hn;
3015
3036
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3016
3037
  }
3017
3038
  stopRefresh() {
@@ -3020,7 +3041,7 @@ var hn = class {
3020
3041
  async refreshLicense() {
3021
3042
  let e = this.engine;
3022
3043
  if (!this.destroyed && e) try {
3023
- let t = await y(this.resolveOptions());
3044
+ let t = await v(this.resolveOptions());
3024
3045
  if (this.destroyed || this.engine !== e) return;
3025
3046
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3026
3047
  (n || r) && (e.setLicenseUrls({
@@ -3056,7 +3077,7 @@ var hn = class {
3056
3077
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3057
3078
  }
3058
3079
  getStats() {
3059
- return this.engine?.getStats() ?? W;
3080
+ return this.engine?.getStats() ?? U;
3060
3081
  }
3061
3082
  getQualityLevels() {
3062
3083
  return this.engine?.getQualityLevels() ?? [];
@@ -3095,10 +3116,10 @@ var hn = class {
3095
3116
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3096
3117
  }
3097
3118
  async enterFullscreen() {
3098
- return !this.destroyed && T(this.opts.video, this.container ?? void 0);
3119
+ return !this.destroyed && S(this.opts.video, this.container ?? void 0);
3099
3120
  }
3100
3121
  async exitFullscreen() {
3101
- await E(this.opts.video, this.container ?? void 0);
3122
+ await C(this.opts.video, this.container ?? void 0);
3102
3123
  }
3103
3124
  retry() {
3104
3125
  return this.reload();
@@ -3108,7 +3129,7 @@ var hn = class {
3108
3129
  let e = ++this.loadGen;
3109
3130
  this.teardownPlayback();
3110
3131
  try {
3111
- let t = await b({
3132
+ let t = await y({
3112
3133
  ...this.resolveOptions(),
3113
3134
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3114
3135
  });
@@ -3166,7 +3187,7 @@ function $(e) {
3166
3187
  }
3167
3188
  //#endregion
3168
3189
  //#region src/embed/host.ts
3169
- function gn(e) {
3190
+ function yn(e) {
3170
3191
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3171
3192
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3172
3193
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3225,15 +3246,15 @@ function gn(e) {
3225
3246
  }
3226
3247
  //#endregion
3227
3248
  //#region src/embed/page.ts
3228
- var _n = /^[A-Za-z0-9:_.-]{1,128}$/;
3229
- function vn(e) {
3249
+ var bn = /^[A-Za-z0-9:_.-]{1,128}$/;
3250
+ function xn(e) {
3230
3251
  if (typeof e == "boolean") return e;
3231
3252
  if (typeof e == "object" && e) {
3232
3253
  let t = e.endpoint;
3233
3254
  return typeof t == "string" ? { endpoint: t } : {};
3234
3255
  }
3235
3256
  }
3236
- function yn() {
3257
+ function Sn() {
3237
3258
  let e = window.HAVIK_EMBED_CONFIG;
3238
3259
  if (e) return {
3239
3260
  baseUrl: e.baseUrl ?? "",
@@ -3243,7 +3264,7 @@ function yn() {
3243
3264
  autoplay: e.autoplay ?? !0,
3244
3265
  muted: e.muted ?? !0,
3245
3266
  waitForLive: e.waitForLive ?? !0,
3246
- analytics: vn(e.analytics)
3267
+ analytics: xn(e.analytics)
3247
3268
  };
3248
3269
  let t = new URLSearchParams(location.search);
3249
3270
  return {
@@ -3256,9 +3277,9 @@ function yn() {
3256
3277
  waitForLive: !0
3257
3278
  };
3258
3279
  }
3259
- async function bn() {
3260
- let e = yn();
3261
- Sn();
3280
+ async function Cn() {
3281
+ let e = Sn();
3282
+ Tn();
3262
3283
  let t = document.createElement("video");
3263
3284
  t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
3264
3285
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3313,12 +3334,12 @@ async function bn() {
3313
3334
  code: e.code,
3314
3335
  message: e.message
3315
3336
  })), e.on("autoplayblocked", () => {
3316
- i({ type: "oddin:autoplayblocked" }), xn(t, e);
3337
+ i({ type: "oddin:autoplayblocked" }), wn(t, e);
3317
3338
  });
3318
3339
  }, s = async (r) => {
3319
3340
  a?.destroy(), a = null;
3320
3341
  try {
3321
- let n = await mn({
3342
+ let n = await _n({
3322
3343
  video: t,
3323
3344
  baseUrl: e.baseUrl,
3324
3345
  matchUrn: r,
@@ -3380,7 +3401,7 @@ async function bn() {
3380
3401
  a?.retry();
3381
3402
  break;
3382
3403
  case "oddin:load":
3383
- typeof e.matchUrn == "string" && _n.test(e.matchUrn) && s(e.matchUrn);
3404
+ typeof e.matchUrn == "string" && bn.test(e.matchUrn) && s(e.matchUrn);
3384
3405
  break;
3385
3406
  case "oddin:destroy": c();
3386
3407
  }
@@ -3392,18 +3413,18 @@ async function bn() {
3392
3413
  protocol: 1
3393
3414
  });
3394
3415
  }
3395
- function xn(e, t) {
3416
+ function wn(e, t) {
3396
3417
  if (document.getElementById("havik-tap")) return;
3397
3418
  let n = document.createElement("button");
3398
3419
  n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
3399
3420
  n.remove(), t.play();
3400
3421
  }), document.body.appendChild(n);
3401
3422
  }
3402
- function Sn() {
3423
+ function Tn() {
3403
3424
  let e = document.createElement("style");
3404
3425
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3405
3426
  }
3406
3427
  //#endregion
3407
- export { Gt as ODDIN_THEME, n as PlaybackError, qt as applyTheme, U as baseUrlForEnv, bn as bootEmbed, ye as clearDeviceId, mn as createPlayer, O as deriveEventsBaseUrl, Fe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, fe as fetchCatalog, me as fetchTournament, ge as flattenMatches, j as getDeviceId, Le as isLowLatencyManifest, $ as isOddinMessage, xe as licenseRequestHeaders, gn as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, _e as watchStatus };
3428
+ export { Yt as ODDIN_THEME, n as PlaybackError, Zt as applyTheme, H as baseUrlForEnv, Cn as bootEmbed, Te as clearDeviceId, _n as createPlayer, T as deriveEventsBaseUrl, ze as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, Ve as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, yn as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, Ce as watchStatus };
3408
3429
 
3409
3430
  //# sourceMappingURL=index.js.map