@oddin-gg/havik-player 2.16.1 → 2.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -174,7 +174,7 @@ function ue(e, t) {
174
174
  t?.addEventListener("abort", a, { once: !0 });
175
175
  });
176
176
  }
177
- async function v(e, t, r) {
177
+ async function de(e, t, r) {
178
178
  let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
179
179
  for (;;) {
180
180
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
@@ -200,21 +200,21 @@ async function v(e, t, r) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/core/resolve.ts
203
- async function y(e) {
203
+ async function v(e) {
204
204
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
205
205
  let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
206
206
  credential: e.credential,
207
207
  signal: e.signal,
208
208
  apiHeaders: e.apiHeaders
209
209
  });
210
- if (!t.ok) throw await de(t);
211
- return me(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await fe(t);
211
+ return he(await t.json(), e.matchUrn);
212
212
  }
213
- function b(e) {
214
- let t = () => y(e);
215
- 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();
216
216
  }
217
- async function de(e) {
217
+ async function fe(e) {
218
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;
219
219
  try {
220
220
  let t = await e.json();
@@ -230,7 +230,7 @@ async function de(e) {
230
230
  liveStartsAtMs: s
231
231
  });
232
232
  }
233
- var fe = /* @__PURE__ */ new Set([
233
+ var pe = /* @__PURE__ */ new Set([
234
234
  "matchUrn",
235
235
  "protocol",
236
236
  "drmEnabled",
@@ -241,7 +241,7 @@ var fe = /* @__PURE__ */ new Set([
241
241
  "expiresAt",
242
242
  "analytics"
243
243
  ]);
244
- function x(e, t) {
244
+ function b(e, t) {
245
245
  let r;
246
246
  try {
247
247
  r = new URL(t);
@@ -251,7 +251,7 @@ function x(e, t) {
251
251
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
252
252
  return t;
253
253
  }
254
- function pe(e) {
254
+ function me(e) {
255
255
  if (e !== void 0) {
256
256
  if (typeof e == "string" && !e.endsWith("/")) try {
257
257
  let t = new URL(e);
@@ -260,62 +260,62 @@ function pe(e) {
260
260
  g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
261
  }
262
262
  }
263
- function me(e, t) {
263
+ function he(e, t) {
264
264
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
265
265
  let r = e.drmEnabled ?? !!e.drm, i = {
266
266
  matchUrn: e.matchUrn ?? t,
267
267
  protocol: "hls",
268
268
  drmEnabled: r,
269
- manifestUrl: x("manifestUrl", e.manifestUrl),
269
+ manifestUrl: b("manifestUrl", e.manifestUrl),
270
270
  serverTime: e.serverTime ?? ""
271
271
  };
272
272
  if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
273
273
  i.analytics = { sid: e.analytics.sid };
274
- let t = pe(e.analytics.endpoint);
274
+ let t = me(e.analytics.endpoint);
275
275
  t && (i.analytics.endpoint = t);
276
276
  }
277
277
  if (r && e.drm) {
278
278
  let t = {};
279
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
- 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)
282
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
283
283
  }
284
284
  let a = {};
285
- for (let [t, n] of Object.entries(e)) fe.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
286
286
  return Object.keys(a).length > 0 && (i.extensions = a), i;
287
287
  }
288
288
  //#endregion
289
289
  //#region src/core/fullscreen.ts
290
- function he(e) {
290
+ function ge(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function S(e) {
293
+ function x(e) {
294
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
295
295
  }
296
- function C(e, t) {
297
- let n = S(he(e));
296
+ function S(e, t) {
297
+ let n = x(ge(e));
298
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
299
299
  }
300
- async function w(e, t) {
300
+ async function C(e, t) {
301
301
  let n = t ?? e;
302
302
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
303
303
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
304
304
  let r = e;
305
305
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
306
306
  }
307
- async function T(e, t) {
307
+ async function w(e, t) {
308
308
  let n = e;
309
309
  if (n.webkitDisplayingFullscreen) {
310
310
  n.webkitExitFullscreen?.();
311
311
  return;
312
312
  }
313
- let r = he(e), i = S(r);
313
+ let r = ge(e), i = x(r);
314
314
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
315
315
  }
316
316
  //#endregion
317
317
  //#region src/core/catalog.ts
318
- async function ge(e) {
318
+ async function _e(e) {
319
319
  let t = new URLSearchParams();
320
320
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
321
321
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -333,12 +333,12 @@ async function ge(e) {
333
333
  };
334
334
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
335
335
  return {
336
- tournaments: _e(await s.json()),
336
+ tournaments: ve(await s.json()),
337
337
  etag: s.headers.get("etag") ?? void 0,
338
338
  notModified: !1
339
339
  };
340
340
  }
341
- function _e(e) {
341
+ function ve(e) {
342
342
  return (e.tournaments ?? []).map((e) => {
343
343
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
344
344
  return {
@@ -360,7 +360,7 @@ function _e(e) {
360
360
  };
361
361
  });
362
362
  }
363
- async function ve(e) {
363
+ async function ye(e) {
364
364
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
365
365
  e.etag && i.set("If-None-Match", e.etag);
366
366
  let a = await p(t, {
@@ -380,13 +380,13 @@ async function ve(e) {
380
380
  };
381
381
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
382
382
  return {
383
- tournament: ye(await a.json()),
383
+ tournament: be(await a.json()),
384
384
  etag: a.headers.get("etag") ?? void 0,
385
385
  notModified: !1,
386
386
  notFound: !1
387
387
  };
388
388
  }
389
- function ye(e) {
389
+ function be(e) {
390
390
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
391
391
  return {
392
392
  urn: t,
@@ -406,17 +406,17 @@ function ye(e) {
406
406
  }))
407
407
  };
408
408
  }
409
- function be(e) {
409
+ function xe(e) {
410
410
  return e.tournaments.flatMap((e) => e.matches);
411
411
  }
412
412
  //#endregion
413
413
  //#region src/core/poll.ts
414
- var xe = /* @__PURE__ */ new Set([
414
+ var Se = /* @__PURE__ */ new Set([
415
415
  "NOT_FOUND",
416
416
  "GONE",
417
417
  "INVALID_URN"
418
418
  ]);
419
- function Se(e) {
419
+ function Ce(e) {
420
420
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
421
421
  u || (a = setTimeout(m, t));
422
422
  }, m = async () => {
@@ -449,7 +449,7 @@ function Se(e) {
449
449
  } catch (t) {
450
450
  if (!i.signal.aborted) {
451
451
  let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
- xe.has(r.code) && (u = !0), e.onError?.(r);
452
+ Se.has(r.code) && (u = !0), e.onError?.(r);
453
453
  }
454
454
  } finally {
455
455
  f();
@@ -461,9 +461,9 @@ function Se(e) {
461
461
  }
462
462
  //#endregion
463
463
  //#region src/core/events.ts
464
- var Ce = 45e3;
465
- function E(e) {
466
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Ce, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
464
+ var we = 45e3;
465
+ function T(e) {
466
+ 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) => {
467
467
  if (a.signal.aborted) return t();
468
468
  let n = setTimeout(t, e);
469
469
  a.signal.addEventListener("abort", () => {
@@ -544,7 +544,7 @@ function E(e) {
544
544
  o || (o = !0, a.abort());
545
545
  } };
546
546
  }
547
- function D(e) {
547
+ function E(e) {
548
548
  try {
549
549
  let t = new URL(e);
550
550
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -554,27 +554,27 @@ function D(e) {
554
554
  }
555
555
  //#endregion
556
556
  //#region src/core/drm/deviceId.ts
557
- var O = "havik.player.deviceId", k;
558
- function A() {
559
- if (k) return k;
557
+ var D = "havik.player.deviceId", O;
558
+ function k() {
559
+ if (O) return O;
560
560
  try {
561
- let e = globalThis.localStorage?.getItem(O);
562
- if (e) return k = e, e;
561
+ let e = globalThis.localStorage?.getItem(D);
562
+ if (e) return O = e, e;
563
563
  } catch {}
564
- let e = Te();
565
- k = e;
564
+ let e = Ee();
565
+ O = e;
566
566
  try {
567
- globalThis.localStorage?.setItem(O, e);
567
+ globalThis.localStorage?.setItem(D, e);
568
568
  } catch {}
569
569
  return e;
570
570
  }
571
- function we() {
572
- k = void 0;
571
+ function Te() {
572
+ O = void 0;
573
573
  try {
574
- globalThis.localStorage?.removeItem(O);
574
+ globalThis.localStorage?.removeItem(D);
575
575
  } catch {}
576
576
  }
577
- function Te() {
577
+ function Ee() {
578
578
  let e = globalThis.crypto;
579
579
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
580
580
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -586,21 +586,21 @@ function Te() {
586
586
  }
587
587
  //#endregion
588
588
  //#region src/core/drm/headers.ts
589
- function Ee(e, t, n = {}) {
589
+ function De(e, t, n = {}) {
590
590
  let r = {
591
591
  "x-api-key": t.apiKey,
592
592
  "X-Match-Urn": e.matchUrn,
593
- "X-Device-Id": n.deviceId ?? A(),
593
+ "X-Device-Id": n.deviceId ?? k(),
594
594
  "Content-Type": "application/octet-stream"
595
595
  };
596
596
  return n.userId && (r["X-User-Id"] = n.userId), r;
597
597
  }
598
598
  //#endregion
599
599
  //#region src/core/drm/cdm.ts
600
- var j = /* @__PURE__ */ new WeakMap();
601
- function De(e, t) {
602
- let n = j.get(e);
603
- n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
600
+ var A = /* @__PURE__ */ new WeakMap();
601
+ function Oe(e, t) {
602
+ let n = A.get(e);
603
+ n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
604
604
  let r = n.get(t.keySystem);
605
605
  if (r) return r;
606
606
  let i = t.createMediaKeys().catch((e) => {
@@ -608,22 +608,22 @@ function De(e, t) {
608
608
  });
609
609
  return n.set(t.keySystem, i), i;
610
610
  }
611
- function M() {
611
+ function j() {
612
612
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
613
613
  }
614
- var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
615
- function Oe(e) {
614
+ var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
615
+ function ke(e) {
616
616
  return e.startsWith("com.widevine");
617
617
  }
618
- function P(e, t) {
619
- if (!Oe(e)) return t;
618
+ function N(e, t) {
619
+ if (!ke(e)) return t;
620
620
  let n = (e, t) => {
621
621
  let n = e.videoCapabilities;
622
622
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
623
- let n = N.indexOf(e.robustness);
624
- return n === -1 || N.indexOf(t) > n;
623
+ let n = M.indexOf(e.robustness);
624
+ return n === -1 || M.indexOf(t) > n;
625
625
  });
626
- }, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
626
+ }, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
627
627
  ...t,
628
628
  videoCapabilities: t.videoCapabilities?.map((t) => ({
629
629
  ...t,
@@ -632,53 +632,53 @@ function P(e, t) {
632
632
  })));
633
633
  return [...t, ...r];
634
634
  }
635
- function F(e) {
636
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
635
+ function P(e) {
636
+ return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
637
637
  keySystem: t.keySystem,
638
638
  getConfiguration: () => t.getConfiguration(),
639
- createMediaKeys: () => De(e, t)
639
+ createMediaKeys: () => Oe(e, t)
640
640
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
641
641
  }
642
- var I = {
642
+ var F = {
643
643
  video: "SW_SECURE_DECODE",
644
644
  audio: "SW_SECURE_CRYPTO",
645
645
  scheme: "cbcs"
646
646
  };
647
- function ke(e) {
648
- if (!M()) return;
647
+ function Ae(e) {
648
+ if (!j()) return;
649
649
  let t = (e, t) => ({
650
650
  contentType: e,
651
651
  robustness: t,
652
- encryptionScheme: I.scheme
652
+ encryptionScheme: F.scheme
653
653
  });
654
- F(e)("com.widevine.alpha", [{
654
+ P(e)("com.widevine.alpha", [{
655
655
  initDataTypes: ["cenc"],
656
656
  distinctiveIdentifier: "optional",
657
657
  persistentState: "optional",
658
658
  sessionTypes: ["temporary"],
659
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
660
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
659
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
660
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
661
661
  }]).then((e) => e.createMediaKeys()).catch(() => {});
662
662
  }
663
- function L(e) {
664
- let t = R(e);
663
+ function I(e) {
664
+ let t = L(e);
665
665
  if (/^avc[13]/.test(t)) return "avc";
666
666
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
667
667
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
668
668
  if (t.startsWith("av01")) return "av1";
669
669
  if (/^vp0?9/.test(t)) return "vp9";
670
670
  }
671
- function R(e) {
671
+ function L(e) {
672
672
  return (e ?? "").trim().toLowerCase();
673
673
  }
674
- var Ae = {
674
+ var je = {
675
675
  hevc: "hvc1.1.6.L93.90",
676
676
  dv: "dvh1.05.06",
677
677
  av1: "av01.0.05M.08",
678
678
  vp9: "vp09.00.10.08"
679
- }, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
680
- function Me(e) {
681
- let t = R(e), n = je.get(t);
679
+ }, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
680
+ function Ne(e) {
681
+ let t = L(e), n = Me.get(t);
682
682
  if (n) return n;
683
683
  let r = {
684
684
  initDataTypes: ["cenc"],
@@ -687,32 +687,32 @@ function Me(e) {
687
687
  sessionTypes: ["temporary"],
688
688
  videoCapabilities: [{
689
689
  contentType: `video/mp4; codecs="${e.trim()}"`,
690
- robustness: I.video,
691
- encryptionScheme: I.scheme
690
+ robustness: F.video,
691
+ encryptionScheme: F.scheme
692
692
  }]
693
693
  }, i = (async () => {
694
694
  try {
695
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
695
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
696
696
  } catch {
697
697
  return !1;
698
698
  }
699
- })().then((e) => (z.set(t, e), e));
700
- return je.set(t, i), i;
699
+ })().then((e) => (R.set(t, e), e));
700
+ return Me.set(t, i), i;
701
701
  }
702
- function Ne() {
703
- if (M()) for (let e of Object.values(Ae)) Me(e);
702
+ function Pe() {
703
+ if (j()) for (let e of Object.values(je)) Ne(e);
704
704
  }
705
- function Pe(e) {
706
- let t = L(e);
707
- if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ae[t]));
705
+ function Fe(e) {
706
+ let t = I(e);
707
+ if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
708
708
  }
709
709
  //#endregion
710
710
  //#region src/core/drm/support.ts
711
- var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
711
+ var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
712
712
  widevine: ["com.widevine.alpha"],
713
713
  fairplay: ["com.apple.fps"]
714
714
  };
715
- function ze(e) {
715
+ function Be(e) {
716
716
  return e === "fairplay" ? [{
717
717
  initDataTypes: [
718
718
  "sinf",
@@ -720,30 +720,30 @@ function ze(e) {
720
720
  "cenc"
721
721
  ],
722
722
  videoCapabilities: [{
723
- contentType: Ie,
723
+ contentType: Le,
724
724
  robustness: "",
725
725
  encryptionScheme: "cbcs"
726
726
  }],
727
727
  audioCapabilities: [{
728
- contentType: Le,
728
+ contentType: Re,
729
729
  robustness: "",
730
730
  encryptionScheme: "cbcs"
731
731
  }]
732
- }] : P("com.widevine.alpha", [{
732
+ }] : N("com.widevine.alpha", [{
733
733
  initDataTypes: ["cenc"],
734
734
  videoCapabilities: [{
735
- contentType: Ie,
736
- robustness: I.video,
737
- encryptionScheme: I.scheme
735
+ contentType: Le,
736
+ robustness: F.video,
737
+ encryptionScheme: F.scheme
738
738
  }],
739
739
  audioCapabilities: [{
740
- contentType: Le,
741
- robustness: I.audio,
742
- encryptionScheme: I.scheme
740
+ contentType: Re,
741
+ robustness: F.audio,
742
+ encryptionScheme: F.scheme
743
743
  }]
744
744
  }]);
745
745
  }
746
- function Be(e, t) {
746
+ function Ve(e, t) {
747
747
  return new Promise((n, r) => {
748
748
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
749
749
  e.then((e) => {
@@ -753,8 +753,8 @@ function Be(e, t) {
753
753
  });
754
754
  });
755
755
  }
756
- async function Ve(e = {}) {
757
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
756
+ async function He(e = {}) {
757
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
758
758
  if (typeof window < "u" && window.isSecureContext === !1) return {
759
759
  verdict: "insecure-context",
760
760
  detail: r
@@ -766,7 +766,7 @@ async function Ve(e = {}) {
766
766
  };
767
767
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
768
768
  for (let e of t) {
769
- let t = Re[e];
769
+ let t = ze[e];
770
770
  if (!t) {
771
771
  r[e] = "unknown system";
772
772
  continue;
@@ -777,7 +777,7 @@ async function Ve(e = {}) {
777
777
  break;
778
778
  }
779
779
  try {
780
- return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
780
+ return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
781
781
  verdict: "supported",
782
782
  system: e,
783
783
  detail: r
@@ -801,49 +801,72 @@ async function Ve(e = {}) {
801
801
  }
802
802
  //#endregion
803
803
  //#region src/core/manifest.ts
804
- var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
- function Ue(e) {
806
- return He.test(e);
804
+ var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function We(e) {
806
+ return Ue.test(e);
807
807
  }
808
808
  //#endregion
809
809
  //#region src/core/env.ts
810
- var We = {
810
+ var Ge = {
811
811
  integration: "https://feed-dev.oddin-video.gg",
812
812
  production: "https://feed.oddin-video.gg"
813
813
  };
814
- function B(e) {
815
- let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
814
+ function Ke(e) {
815
+ let t = Object.prototype.hasOwnProperty.call(Ge, e) ? Ge[e] : void 0;
816
816
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
817
817
  return t;
818
818
  }
819
819
  //#endregion
820
820
  //#region src/core/stats.ts
821
- var V = { droppedFrames: 0 };
822
- function H(e) {
821
+ var z = { droppedFrames: 0 };
822
+ function B(e) {
823
823
  try {
824
824
  return new URL(e).host;
825
825
  } catch {
826
826
  return "";
827
827
  }
828
828
  }
829
- var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
- function Ke(e) {
829
+ var qe = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
+ function Je(e) {
831
831
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
832
832
  let t = "", n = -1, r = performance.getEntriesByType("resource");
833
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ge.test(i.name)) && i.startTime >= n) {
834
- let e = H(i.name);
833
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || qe.test(i.name)) && i.startTime >= n) {
834
+ let e = B(i.name);
835
835
  e && (t = e, n = i.startTime);
836
836
  }
837
837
  return t;
838
838
  }
839
- function U(e) {
839
+ function V(e) {
840
840
  let t = e.getVideoPlaybackQuality?.();
841
841
  return {
842
842
  dropped: t?.droppedVideoFrames ?? 0,
843
843
  totalFrames: t?.totalVideoFrames ?? 0
844
844
  };
845
845
  }
846
- function qe(e, t) {
846
+ var H = class {
847
+ video;
848
+ baseFrames = 0;
849
+ baseDropped = 0;
850
+ lastFrames = 0;
851
+ lastDropped = 0;
852
+ constructor(e) {
853
+ this.video = e;
854
+ }
855
+ read() {
856
+ let e = V(this.video);
857
+ return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
858
+ dropped: this.baseDropped + e.dropped,
859
+ totalFrames: this.baseFrames + e.totalFrames
860
+ };
861
+ }
862
+ attach() {
863
+ let e = () => void this.read();
864
+ return this.video.addEventListener("timeupdate", e), this.video.addEventListener("seeking", e), () => {
865
+ this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
866
+ };
867
+ }
868
+ };
869
+ function Ye(e, t) {
847
870
  let n = [
848
871
  ["playing", () => t("playing")],
849
872
  ["waiting", () => t("buffering")],
@@ -860,8 +883,8 @@ function qe(e, t) {
860
883
  }
861
884
  //#endregion
862
885
  //#region src/core/engine/native.ts
863
- var Je = 2e3, Ye = 3;
864
- function Xe(e) {
886
+ var Xe = 2e3, Ze = 3, U = 500, Qe = 6e3, $e = .25;
887
+ function et(e) {
865
888
  try {
866
889
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
867
890
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -877,7 +900,7 @@ function G() {
877
900
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
878
901
  return e || t;
879
902
  }
880
- function Ze() {
903
+ function tt() {
881
904
  if (typeof navigator > "u" || !G()) return !1;
882
905
  let e = navigator.userAgent ?? "";
883
906
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -894,16 +917,20 @@ var K = class {
894
917
  onVisibility = null;
895
918
  onPageShow = null;
896
919
  hiddenSince = null;
920
+ refocusTimer = null;
897
921
  fairplayKeyIV;
898
922
  loadStarted;
899
923
  preloadTouched = !1;
900
924
  savedPreload = null;
901
925
  cdnHost = "";
902
926
  builtAt;
927
+ frameCounter;
928
+ detachFrames = null;
903
929
  constructor(e) {
904
- this.deps = e, this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
930
+ this.deps = e, this.frameCounter = new H(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
905
931
  }
906
932
  async load() {
933
+ this.detachFrames ??= this.frameCounter.attach();
907
934
  let { video: e, descriptor: t, emit: r } = this.deps;
908
935
  if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
909
936
  if (!t.drm?.fairplay) {
@@ -921,7 +948,7 @@ var K = class {
921
948
  type: "error",
922
949
  error: new n("INTERNAL", 0, "native HLS playback error"),
923
950
  fatal: !0
924
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Qe(t.manifestUrl, t.analytics?.sid), e.load();
951
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = nt(t.manifestUrl, t.analytics?.sid), e.load();
925
952
  }
926
953
  startLoad() {
927
954
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -943,7 +970,7 @@ var K = class {
943
970
  });
944
971
  this.onEncrypted = (n) => {
945
972
  let i = n;
946
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Xe(i.initData), (async () => {
973
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = et(i.initData), (async () => {
947
974
  try {
948
975
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
949
976
  initDataTypes: [i.initDataType],
@@ -1038,11 +1065,11 @@ var K = class {
1038
1065
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
1039
1066
  }
1040
1067
  getStats() {
1041
- let e = this.deps.video, t = U(e), n = {
1068
+ let e = this.deps.video, t = this.frameCounter.read(), n = {
1042
1069
  droppedFrames: t.dropped,
1043
1070
  decodedFrames: t.totalFrames
1044
1071
  };
1045
- if (this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1072
+ if (this.cdnHost ||= Je(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1046
1073
  if (n.isLive = !0, e.seekable.length > 0) {
1047
1074
  let t = e.seekable.end(e.seekable.length - 1);
1048
1075
  n.atLiveEdge = e.currentTime >= t - 2;
@@ -1061,27 +1088,48 @@ var K = class {
1061
1088
  this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
1062
1089
  let e = typeof performance < "u" ? performance.now() : Date.now();
1063
1090
  if (document.visibilityState === "hidden") {
1064
- this.hiddenSince = e;
1091
+ this.hiddenSince = e, this.cancelRefocus();
1065
1092
  return;
1066
1093
  }
1067
1094
  let t = this.hiddenSince;
1068
- this.hiddenSince = null, t != null && e - t >= Je && this.snapToLive();
1095
+ this.hiddenSince = null, t != null && e - t >= Xe && this.armRefocus();
1069
1096
  }, this.onPageShow = (e) => {
1070
- e.persisted && this.snapToLive();
1097
+ e.persisted && this.armRefocus();
1071
1098
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
1072
1099
  }
1073
- snapToLive() {
1100
+ armRefocus() {
1101
+ if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
1102
+ let e = this.liveEnd(), t = () => typeof performance < "u" ? performance.now() : Date.now(), n = t(), r = 0, i = () => {
1103
+ if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1104
+ r += U;
1105
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + $e), s = Math.max(r, t() - n) >= Qe;
1106
+ if (o || s && a != null) {
1107
+ this.snapToLive();
1108
+ return;
1109
+ }
1110
+ this.refocusTimer = setTimeout(i, U);
1111
+ };
1112
+ this.refocusTimer = setTimeout(i, U);
1113
+ }
1114
+ cancelRefocus() {
1115
+ this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
1116
+ }
1117
+ liveEnd() {
1074
1118
  let e = this.deps.video;
1075
- if (e.duration !== Infinity || e.seekable.length === 0) return;
1076
- let t = e.seekable.start(e.seekable.length - 1), n = e.seekable.end(e.seekable.length - 1);
1077
- if (!Number.isFinite(n)) return;
1078
- let r = Math.max(t, n - Ye);
1119
+ if (e.duration !== Infinity || e.seekable.length === 0) return null;
1120
+ let t = e.seekable.end(e.seekable.length - 1);
1121
+ return Number.isFinite(t) ? t : null;
1122
+ }
1123
+ snapToLive() {
1124
+ let e = this.deps.video, t = this.liveEnd();
1125
+ if (t == null) return;
1126
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - Ze, r);
1079
1127
  try {
1080
- e.currentTime = r;
1128
+ e.currentTime = i;
1081
1129
  } catch {}
1082
1130
  }
1083
1131
  destroy() {
1084
- this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
1132
+ this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
1085
1133
  let { video: e } = this.deps;
1086
1134
  this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
1087
1135
  try {
@@ -1093,13 +1141,13 @@ var K = class {
1093
1141
  } catch {}
1094
1142
  }
1095
1143
  };
1096
- function Qe(e, t) {
1144
+ function nt(e, t) {
1097
1145
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1098
1146
  }
1099
1147
  //#endregion
1100
1148
  //#region src/core/engine/prefetch.ts
1101
- var $e = 15e3, et = 5e3, tt = 6;
1102
- function nt(e) {
1149
+ var rt = 15e3, it = 5e3, at = 6;
1150
+ function ot(e) {
1103
1151
  try {
1104
1152
  let t = new URL(e);
1105
1153
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1107,7 +1155,7 @@ function nt(e) {
1107
1155
  return e;
1108
1156
  }
1109
1157
  }
1110
- var rt = class {
1158
+ var st = class {
1111
1159
  cmcd;
1112
1160
  entries = /* @__PURE__ */ new Map();
1113
1161
  keyed = /* @__PURE__ */ new Set();
@@ -1130,10 +1178,10 @@ var rt = class {
1130
1178
  }
1131
1179
  prefetch(e, t, n) {
1132
1180
  if (!this.isActive(t)) return;
1133
- let r = nt(e);
1181
+ let r = ot(e);
1134
1182
  if (this.entries.has(r)) return;
1135
1183
  let i = this.perTrack.get(t) ?? 0;
1136
- if (i >= tt) return;
1184
+ if (i >= at) return;
1137
1185
  this.perTrack.set(t, i + 1);
1138
1186
  let a = new AbortController(), o = {
1139
1187
  started: performance.now(),
@@ -1147,10 +1195,10 @@ var rt = class {
1147
1195
  signal: a.signal
1148
1196
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1149
1197
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1150
- }, $e);
1198
+ }, rt);
1151
1199
  }
1152
1200
  take(e) {
1153
- let t = nt(e), n = this.entries.get(t);
1201
+ let t = ot(e), n = this.entries.get(t);
1154
1202
  return n && this.entries.delete(t), n;
1155
1203
  }
1156
1204
  destroy() {
@@ -1170,13 +1218,13 @@ var rt = class {
1170
1218
  }
1171
1219
  }
1172
1220
  };
1173
- function it(t) {
1221
+ function ct(t) {
1174
1222
  let n = e.DefaultConfig?.loader;
1175
1223
  if (typeof n != "function") return;
1176
1224
  class r extends n {
1177
1225
  served = !1;
1178
1226
  cancelled = !1;
1179
- stats = at();
1227
+ stats = lt();
1180
1228
  load(e, n, r) {
1181
1229
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1182
1230
  if (!i) {
@@ -1184,7 +1232,7 @@ function it(t) {
1184
1232
  return;
1185
1233
  }
1186
1234
  this.served = !0;
1187
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || et, s = setTimeout(() => {
1235
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || it, s = setTimeout(() => {
1188
1236
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1189
1237
  }, o);
1190
1238
  i.bytes.then((o) => {
@@ -1211,7 +1259,7 @@ function it(t) {
1211
1259
  }
1212
1260
  return r;
1213
1261
  }
1214
- function at() {
1262
+ function lt() {
1215
1263
  return {
1216
1264
  aborted: !1,
1217
1265
  loaded: 0,
@@ -1235,10 +1283,10 @@ function at() {
1235
1283
  }
1236
1284
  };
1237
1285
  }
1238
- function ot(e) {
1286
+ function ut(e) {
1239
1287
  return e === "audio" ? "audio" : "main";
1240
1288
  }
1241
- function st(e, t) {
1289
+ function dt(e, t) {
1242
1290
  let n = [];
1243
1291
  t.initSegment?.url && !t.initSegment.data && n.push({
1244
1292
  url: t.initSegment.url,
@@ -1257,24 +1305,24 @@ function st(e, t) {
1257
1305
  }
1258
1306
  //#endregion
1259
1307
  //#region src/core/engine/hls.ts
1260
- function ct() {
1308
+ function ft() {
1261
1309
  return e.isSupported();
1262
1310
  }
1263
- var lt = 3, ut = 5, dt = 3, ft = 3e4, pt = 12e3, mt = 3e3, ht = 6e3, gt = .5, _t = 3, vt = .5, yt = 1.1, bt = .25, xt = 5e3, St = 4e3, Ct = 2, wt = 5, Tt = 2, Et = 2, Dt = 4, Ot = 4, kt = 2e3, At = 3e4, jt = .2, Mt = 30, Nt = 2, Pt = 2, Ft = 9, It = .5, Lt = 64;
1264
- function Rt(e) {
1311
+ var pt = 3, mt = 5, ht = 3, gt = 3e4, _t = 12e3, vt = 3e3, yt = 6e3, bt = .5, xt = 3, St = .5, Ct = 1.1, wt = .25, Tt = 5e3, Et = 4e3, Dt = 2, Ot = 5, kt = 2, At = 2, jt = 4, Mt = 4, Nt = 2e3, Pt = 3e4, Ft = .2, It = 30, Lt = 2, Rt = 2, zt = 9, Bt = .5, Vt = 64;
1312
+ function Ht(e) {
1265
1313
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1266
1314
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1267
1315
  return;
1268
1316
  }
1269
- e.liveSyncDuration ??= Pt;
1270
- let t = Math.max(12, e.liveSyncDuration + Ft);
1271
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), zt(e, e.liveSyncDuration);
1317
+ e.liveSyncDuration ??= Rt;
1318
+ let t = Math.max(12, e.liveSyncDuration + zt);
1319
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ut(e, e.liveSyncDuration);
1272
1320
  }
1273
- function zt(e, t) {
1321
+ function Ut(e, t) {
1274
1322
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1275
1323
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1276
1324
  }
1277
- var Bt = class {
1325
+ var Wt = class {
1278
1326
  name = "hls";
1279
1327
  hls = null;
1280
1328
  deps;
@@ -1351,10 +1399,13 @@ var Bt = class {
1351
1399
  dprMedia = null;
1352
1400
  onDprChange = null;
1353
1401
  loadStarted;
1402
+ frameCounter;
1403
+ detachFrames = null;
1354
1404
  constructor(e) {
1355
- this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1405
+ this.deps = e, this.frameCounter = new H(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1356
1406
  }
1357
1407
  async load() {
1408
+ this.detachFrames ??= this.frameCounter.attach();
1358
1409
  let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
1359
1410
  if (e.drmEnabled && !o) {
1360
1411
  i({
@@ -1364,7 +1415,7 @@ var Bt = class {
1364
1415
  });
1365
1416
  return;
1366
1417
  }
1367
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (ke(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1418
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1368
1419
  let e = this.hls;
1369
1420
  if (document.visibilityState !== "visible" || !e) return;
1370
1421
  let t = e.liveSyncPosition;
@@ -1387,7 +1438,7 @@ var Bt = class {
1387
1438
  }
1388
1439
  this.loadSuspended = !0;
1389
1440
  }
1390
- }, xt));
1441
+ }, Tt));
1391
1442
  }
1392
1443
  resumeLoading() {
1393
1444
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1419,7 +1470,7 @@ var Bt = class {
1419
1470
  let t = e.liveSyncPosition;
1420
1471
  if (typeof t != "number" || !Number.isFinite(t)) return;
1421
1472
  let { video: n } = this.deps;
1422
- n.currentTime <= t + It || (n.currentTime = t);
1473
+ n.currentTime <= t + Bt || (n.currentTime = t);
1423
1474
  }
1424
1475
  startHls() {
1425
1476
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1438,12 +1489,12 @@ var Bt = class {
1438
1489
  emeEnabled: !0,
1439
1490
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1440
1491
  drmSystemOptions: {
1441
- videoRobustness: I.video,
1442
- audioRobustness: I.audio,
1443
- videoEncryptionScheme: I.scheme,
1444
- audioEncryptionScheme: I.scheme
1492
+ videoRobustness: F.video,
1493
+ audioRobustness: F.audio,
1494
+ videoEncryptionScheme: F.scheme,
1495
+ audioEncryptionScheme: F.scheme
1445
1496
  },
1446
- ...M() ? { requestMediaKeySystemAccessFunc: F(t) } : {},
1497
+ ...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
1447
1498
  licenseXhrSetup: (e, t) => {
1448
1499
  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;
1449
1500
  let o = performance.now();
@@ -1460,20 +1511,20 @@ var Bt = class {
1460
1511
  ...c
1461
1512
  };
1462
1513
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1463
- let e = new rt({
1514
+ let e = new st({
1464
1515
  sessionId: n.analytics?.sid,
1465
1516
  contentId: n.matchUrn
1466
- }), t = it(e);
1517
+ }), t = ct(e);
1467
1518
  t && (this.prefetch = e, d.fLoader = t);
1468
1519
  }
1469
- Rt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1520
+ Ht(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1470
1521
  let f = new e(d);
1471
1522
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1472
1523
  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" });
1473
1524
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1474
1525
  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(() => {
1475
1526
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1476
- }, ft)));
1527
+ }, gt)));
1477
1528
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1478
1529
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1479
1530
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1481,10 +1532,10 @@ var Bt = class {
1481
1532
  let n = t?.frag?.stats, r = n?.loaded;
1482
1533
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1483
1534
  let i = n?.loading;
1484
- 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 > Lt && this.requestTimesMs.shift());
1535
+ 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 > Vt && this.requestTimesMs.shift());
1485
1536
  let a = t?.frag?.url;
1486
1537
  if (a) {
1487
- let e = H(a);
1538
+ let e = B(a);
1488
1539
  e && (this.cdnHost = e);
1489
1540
  }
1490
1541
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1498,15 +1549,15 @@ var Bt = class {
1498
1549
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1499
1550
  let t = this.prefetch;
1500
1551
  f.on(e.Events.KEY_LOADING, (e, n) => {
1501
- let r = n?.frag, i = ot(r?.type);
1502
- if (r && t.isActive(i)) for (let e of st(f, r)) t.prefetch(e.url, i, e.kind);
1503
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ot(n?.frag?.type)));
1552
+ let r = n?.frag, i = ut(r?.type);
1553
+ if (r && t.isActive(i)) for (let e of dt(f, r)) t.prefetch(e.url, i, e.kind);
1554
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ut(n?.frag?.type)));
1504
1555
  }
1505
1556
  f.on(e.Events.KEY_LOADED, () => {
1506
1557
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1507
1558
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1508
1559
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1509
- }, mt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1560
+ }, vt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1510
1561
  this.renditionSwitches += 1;
1511
1562
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1512
1563
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1570,7 +1621,7 @@ var Bt = class {
1570
1621
  return;
1571
1622
  }
1572
1623
  this.capTimer && clearTimeout(this.capTimer);
1573
- let t = e > this.sizeCapLevel ? kt : At;
1624
+ let t = e > this.sizeCapLevel ? Nt : Pt;
1574
1625
  this.capTimer = setTimeout(() => {
1575
1626
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1576
1627
  }, t);
@@ -1580,9 +1631,9 @@ var Bt = class {
1580
1631
  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;
1581
1632
  }
1582
1633
  dropLevelsWidevineCannotPlay(e) {
1583
- this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
1584
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
1585
- for (let n of t) Me(n).then((t) => {
1634
+ this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1635
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1636
+ for (let n of t) Ne(n).then((t) => {
1586
1637
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1587
1638
  });
1588
1639
  }
@@ -1590,10 +1641,10 @@ var Bt = class {
1590
1641
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1591
1642
  if (n.forEach((e, n) => {
1592
1643
  let a = e.videoCodec;
1593
- a && L(a) && t(a) && (r.push(n), i.add(a));
1644
+ a && I(a) && t(a) && (r.push(n), i.add(a));
1594
1645
  }), !r.length) return !1;
1595
1646
  let a = [...i].join(", ");
1596
- if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1647
+ if (!n.some((e, t) => r.includes(t) ? !1 : !I(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;
1597
1648
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1598
1649
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1599
1650
  }
@@ -1643,7 +1694,7 @@ var Bt = class {
1643
1694
  e.widevine && (this.licenseUrl = e.widevine);
1644
1695
  }
1645
1696
  getStats() {
1646
- let e = this.hls, t = U(this.deps.video), n = {
1697
+ let e = this.hls, t = this.frameCounter.read(), n = {
1647
1698
  droppedFrames: t.dropped,
1648
1699
  decodedFrames: t.totalFrames,
1649
1700
  lowLatency: this.detectedLowLatency,
@@ -1691,7 +1742,7 @@ var Bt = class {
1691
1742
  return;
1692
1743
  }
1693
1744
  let e = Date.now() - this.lastAdvanceMs;
1694
- !this.chaseSuspended && e > ht && this.suspendChasing(), e > pt && this.emitEnded("stalled");
1745
+ !this.chaseSuspended && e > yt && this.suspendChasing(), e > _t && this.emitEnded("stalled");
1695
1746
  }
1696
1747
  resetStarvationWindow() {
1697
1748
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1706,7 +1757,7 @@ var Bt = class {
1706
1757
  this.resetStarvationWindow();
1707
1758
  return;
1708
1759
  }
1709
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ht, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > St, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1760
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < yt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Et, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = V(t), c = o - s, l = c !== this.starvedFrames;
1710
1761
  if (this.starvedFrames = c, !a || l) {
1711
1762
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1712
1763
  return;
@@ -1715,12 +1766,12 @@ var Bt = class {
1715
1766
  this.resetStarvationWindow();
1716
1767
  return;
1717
1768
  }
1718
- 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 > Dt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Tt && (this.clearKick(), this.starvationRebuilds < Et)) {
1769
+ 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 > jt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= kt && (this.clearKick(), this.starvationRebuilds < At)) {
1719
1770
  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");
1720
1771
  return;
1721
1772
  }
1722
- let u = i && this.starvedTicks >= Ct, d = !i && this.deadTicks >= Dt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Ot;
1723
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= wt))) {
1773
+ let u = i && this.starvedTicks >= Dt, d = !i && this.deadTicks >= jt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Mt;
1774
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Ot))) {
1724
1775
  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");
1725
1776
  try {
1726
1777
  e.stopLoad(), e.startLoad(-1);
@@ -1735,7 +1786,7 @@ var Bt = class {
1735
1786
  let t = e.latency, n = e.targetLatency;
1736
1787
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1737
1788
  let r = t - n;
1738
- !this.catchUpEngaged && r > gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1789
+ !this.catchUpEngaged && r > bt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= bt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1739
1790
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1740
1791
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1741
1792
  }
@@ -1756,16 +1807,16 @@ var Bt = class {
1756
1807
  this.resetFrameDropWindow();
1757
1808
  return;
1758
1809
  }
1759
- let { totalFrames: n, dropped: r } = U(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1760
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Mt || o < 0) {
1810
+ let { totalFrames: n, dropped: r } = V(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1811
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < It || o < 0) {
1761
1812
  this.fpsBadTicks = 0;
1762
1813
  return;
1763
1814
  }
1764
- if (o <= jt * a) {
1815
+ if (o <= Ft * a) {
1765
1816
  this.fpsBadTicks = 0;
1766
1817
  return;
1767
1818
  }
1768
- if (this.fpsBadTicks += 1, this.fpsBadTicks < Nt) return;
1819
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Lt) return;
1769
1820
  this.fpsBadTicks = 0;
1770
1821
  let s = e.levels, c = s[e.currentLevel];
1771
1822
  if (!c) return;
@@ -1782,20 +1833,20 @@ var Bt = class {
1782
1833
  return;
1783
1834
  }
1784
1835
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1785
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(yt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1836
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Ct, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1786
1837
  this.resetChaseWindow();
1787
1838
  return;
1788
1839
  }
1789
- if (this.chaseLatency < 0 || this.chaseLatency - n >= vt) {
1840
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= St) {
1790
1841
  this.chaseLatency = n, this.chaseTicks = 0;
1791
1842
  return;
1792
1843
  }
1793
- if (this.chaseTicks += 1, this.chaseTicks < _t) return;
1844
+ if (this.chaseTicks += 1, this.chaseTicks < xt) return;
1794
1845
  this.resetChaseWindow();
1795
1846
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1796
1847
  if (!(a > 1)) return;
1797
1848
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1798
- s < o + bt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
1849
+ s < o + wt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
1799
1850
  }
1800
1851
  suspendChasing() {
1801
1852
  let e = this.hls;
@@ -1825,7 +1876,7 @@ var Bt = class {
1825
1876
  } catch {}
1826
1877
  }
1827
1878
  destroy() {
1828
- if (this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
1879
+ if (this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
1829
1880
  try {
1830
1881
  this.hls.destroy();
1831
1882
  } catch (e) {
@@ -1840,7 +1891,7 @@ var Bt = class {
1840
1891
  scheduleLicenseRetry(t) {
1841
1892
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1842
1893
  let n = t.response?.code ?? 0;
1843
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= dt) return !1;
1894
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ht) return !1;
1844
1895
  this.licenseRecoveries += 1;
1845
1896
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1846
1897
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1872,7 +1923,7 @@ var Bt = class {
1872
1923
  return;
1873
1924
  }
1874
1925
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1875
- if (this.networkRecoveries < ut) {
1926
+ if (this.networkRecoveries < mt) {
1876
1927
  this.networkRecoveries += 1;
1877
1928
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1878
1929
  this.networkRetryTimer = setTimeout(() => {
@@ -1889,7 +1940,7 @@ var Bt = class {
1889
1940
  return;
1890
1941
  }
1891
1942
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1892
- if (this.mediaRecoveries < lt) {
1943
+ if (this.mediaRecoveries < pt) {
1893
1944
  this.mediaRecoveries += 1, n.recoverMediaError();
1894
1945
  return;
1895
1946
  }
@@ -1913,19 +1964,19 @@ var Bt = class {
1913
1964
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1914
1965
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1915
1966
  }
1916
- }, Vt = 15e3, Ht = 6e5, Ut = 3e5, Wt = 100, q = 1, Gt = 1e3, Kt = 3e4, qt = 1e3, Jt = {
1967
+ }, Gt = 15e3, Kt = 6e5, qt = 3e5, Jt = 100, q = 1, Yt = 1e3, Xt = 3e4, Zt = 1e3, Qt = {
1917
1968
  inline: "PRESENTATION_INLINE",
1918
1969
  fullscreen: "PRESENTATION_FULLSCREEN",
1919
1970
  pip: "PRESENTATION_PIP"
1920
- }, Yt = {
1971
+ }, $t = {
1921
1972
  widevine: "KEY_SYSTEM_WIDEVINE",
1922
1973
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1923
1974
  none: "KEY_SYSTEM_NONE"
1924
1975
  };
1925
- function Xt(e, t) {
1976
+ function en(e, t) {
1926
1977
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1927
1978
  }
1928
- var Zt = /* @__PURE__ */ new Set([
1979
+ var tn = /* @__PURE__ */ new Set([
1929
1980
  "INVALID_URN",
1930
1981
  "NOT_FOUND",
1931
1982
  "GONE",
@@ -1945,7 +1996,7 @@ var Zt = /* @__PURE__ */ new Set([
1945
1996
  ended: "PLAYER_STATE_ENDED",
1946
1997
  error: "PLAYER_STATE_ERROR"
1947
1998
  };
1948
- function Qt(e) {
1999
+ function nn(e) {
1949
2000
  try {
1950
2001
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1951
2002
  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);
@@ -1953,8 +2004,8 @@ function Qt(e) {
1953
2004
  return;
1954
2005
  }
1955
2006
  }
1956
- var $t = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), en = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), tn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1957
- function nn(e) {
2007
+ var rn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), an = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), on = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2008
+ function sn(e) {
1958
2009
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
1959
2010
  let t;
1960
2011
  try {
@@ -1963,19 +2014,19 @@ function nn(e) {
1963
2014
  } catch {
1964
2015
  return;
1965
2016
  }
1966
- if (en.has(t) && !Y.has(t)) {
1967
- Y.add(t), g(tn(new URL(t).origin));
2017
+ if (an.has(t) && !Y.has(t)) {
2018
+ Y.add(t), g(on(new URL(t).origin));
1968
2019
  for (let e of X) e.noteCspBlocked();
1969
2020
  }
1970
2021
  }
1971
- function rn(e, t) {
2022
+ function cn(e, t) {
1972
2023
  return g(t, e), { disabledReason: t };
1973
2024
  }
1974
- function an(e, t, n) {
1975
- if (n) return t && !$t(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2025
+ function ln(e, t, n) {
2026
+ if (n) return t && !rn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1976
2027
  if (t) return { endpoint: t };
1977
- if (t !== void 0) return rn("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).");
1978
- let r = Qt(e);
2028
+ if (t !== void 0) return cn("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).");
2029
+ let r = nn(e);
1979
2030
  if (r) return { endpoint: r };
1980
2031
  let i;
1981
2032
  try {
@@ -1983,9 +2034,9 @@ function an(e, t, n) {
1983
2034
  } catch {
1984
2035
  i = e;
1985
2036
  }
1986
- return rn(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).`);
2037
+ return cn(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).`);
1987
2038
  }
1988
- var on = class {
2039
+ var un = class {
1989
2040
  opts;
1990
2041
  url;
1991
2042
  cspKey;
@@ -2067,8 +2118,8 @@ var on = class {
2067
2118
  constructor(e) {
2068
2119
  this.opts = {
2069
2120
  ...e,
2070
- heartbeatMs: e.heartbeatMs ?? Vt,
2071
- idleMs: e.idleMs ?? Ht
2121
+ heartbeatMs: e.heartbeatMs ?? Gt,
2122
+ idleMs: e.idleMs ?? Kt
2072
2123
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2073
2124
  try {
2074
2125
  let e = new URL(this.url);
@@ -2085,11 +2136,11 @@ var on = class {
2085
2136
  sdkVersion: this.opts.sdkVersion,
2086
2137
  ...this.opts.environment
2087
2138
  };
2088
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Gt), 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.cspKey && en.add(this.cspKey), document.addEventListener("securitypolicyviolation", nn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2139
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Yt), 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.cspKey && an.add(this.cspKey), document.addEventListener("securitypolicyviolation", sn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2089
2140
  }
2090
2141
  checkSuspension(e) {
2091
2142
  if (this.endedFlag || !this.opts.idleMs) return !1;
2092
- let t = Math.max(this.opts.idleMs, Ut);
2143
+ let t = Math.max(this.opts.idleMs, qt);
2093
2144
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2094
2145
  }
2095
2146
  syncIdle(e) {
@@ -2112,12 +2163,12 @@ var on = class {
2112
2163
  let a = {
2113
2164
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2114
2165
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2115
- presentation: Jt[this.presentation]
2166
+ presentation: Qt[this.presentation]
2116
2167
  }, o = this.causeOf(e, t, i);
2117
2168
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2118
2169
  }
2119
2170
  seekInduced(e) {
2120
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < qt;
2171
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Zt;
2121
2172
  }
2122
2173
  causeOf(e, t, n) {
2123
2174
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2191,7 +2242,7 @@ var on = class {
2191
2242
  let r = n ?? "";
2192
2243
  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";
2193
2244
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2194
- if (Zt.has(e)) return "ERROR_STAGE_RESOLVE";
2245
+ if (tn.has(e)) return "ERROR_STAGE_RESOLVE";
2195
2246
  let i = t ?? "";
2196
2247
  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";
2197
2248
  }
@@ -2238,14 +2289,14 @@ var on = class {
2238
2289
  if (this.lastRequestCount = g, _ > 0) {
2239
2290
  o.requestCountDelta = _;
2240
2291
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2241
- n.length > 0 && (o.requestTimeP50Ms = Xt(n, 50), o.requestTimeP95Ms = Xt(n, 95));
2292
+ n.length > 0 && (o.requestTimeP50Ms = en(n, 50), o.requestTimeP95Ms = en(n, 95));
2242
2293
  }
2243
2294
  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();
2244
2295
  }
2245
2296
  maybeEmitMediaInfo(e) {
2246
2297
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2247
2298
  let t = {};
2248
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Yt[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);
2299
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = $t[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);
2249
2300
  let n = JSON.stringify(t);
2250
2301
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2251
2302
  }
@@ -2265,7 +2316,7 @@ var on = class {
2265
2316
  let c = r?.positionMs ?? 0;
2266
2317
  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));
2267
2318
  let l = e !== "END_REASON_ENDED";
2268
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Kt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Kt && (i.abandonAfterErrorMs = Math.max(q, 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);
2319
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Xt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Xt && (i.abandonAfterErrorMs = Math.max(q, 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);
2269
2320
  let u = r?.decodedFrames ?? this.lastDecoded;
2270
2321
  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");
2271
2322
  }
@@ -2285,13 +2336,13 @@ var on = class {
2285
2336
  };
2286
2337
  }
2287
2338
  noteCspBlocked() {
2288
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(tn(new URL(this.url).origin)));
2339
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(on(new URL(this.url).origin)));
2289
2340
  }
2290
2341
  cspBlocked() {
2291
2342
  return !!this.cspKey && Y.has(this.cspKey);
2292
2343
  }
2293
2344
  enqueue(e) {
2294
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Wt;) {
2345
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Jt;) {
2295
2346
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2296
2347
  this.pending.splice(e >= 0 ? e : 0, 1);
2297
2348
  }
@@ -2318,7 +2369,7 @@ var on = class {
2318
2369
  };
2319
2370
  //#endregion
2320
2371
  //#region src/core/environment.ts
2321
- function sn() {
2372
+ function dn() {
2322
2373
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2323
2374
  let e;
2324
2375
  try {
@@ -2343,14 +2394,14 @@ function sn() {
2343
2394
  integration: "INTEGRATION_KIND_IFRAME"
2344
2395
  };
2345
2396
  }
2346
- function cn() {
2397
+ function fn() {
2347
2398
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2348
2399
  let e = navigator.userAgentData, t = e?.platform ?? "";
2349
2400
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2350
2401
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2351
2402
  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";
2352
2403
  }
2353
- function ln() {
2404
+ function pn() {
2354
2405
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2355
2406
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2356
2407
  let t = {
@@ -2369,17 +2420,17 @@ function ln() {
2369
2420
  }
2370
2421
  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;
2371
2422
  }
2372
- function un(e) {
2373
- let t = sn(), n = {
2374
- deviceClass: cn(),
2423
+ function mn(e) {
2424
+ let t = dn(), n = {
2425
+ deviceClass: fn(),
2375
2426
  integration: t.integration,
2376
- ...ln()
2427
+ ...pn()
2377
2428
  };
2378
2429
  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);
2379
2430
  let r = e.getBoundingClientRect?.();
2380
2431
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2381
2432
  }
2382
- async function dn() {
2433
+ async function hn() {
2383
2434
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2384
2435
  if (!e?.getHighEntropyValues) return {};
2385
2436
  try {
@@ -2391,7 +2442,7 @@ async function dn() {
2391
2442
  }
2392
2443
  //#endregion
2393
2444
  //#region src/core/version.ts
2394
- var fn = "2.16.1", pn = {
2445
+ var gn = "2.16.3", _n = {
2395
2446
  accent: "#E1B600",
2396
2447
  accentText: "#1B1C23",
2397
2448
  background: "#0e0f13",
@@ -2402,7 +2453,7 @@ var fn = "2.16.1", pn = {
2402
2453
  border: "rgba(255, 255, 255, 0.1)",
2403
2454
  radius: "8px",
2404
2455
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2405
- }, mn = {
2456
+ }, vn = {
2406
2457
  accent: "--havik-accent",
2407
2458
  accentText: "--havik-accent-text",
2408
2459
  background: "--havik-bg",
@@ -2414,26 +2465,26 @@ var fn = "2.16.1", pn = {
2414
2465
  radius: "--havik-radius",
2415
2466
  fontFamily: "--havik-font"
2416
2467
  };
2417
- function hn(e, t) {
2468
+ function Z(e, t) {
2418
2469
  let n = {
2419
- ...pn,
2470
+ ..._n,
2420
2471
  ...t
2421
2472
  };
2422
- for (let t of Object.keys(mn)) e.style.setProperty(mn[t], n[t]);
2473
+ for (let t of Object.keys(vn)) e.style.setProperty(vn[t], n[t]);
2423
2474
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2424
2475
  }
2425
2476
  //#endregion
2426
2477
  //#region src/ui/styles.ts
2427
- var gn = "havik-player-styles", _n = "\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 touch-action:manipulation}\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", Z = /* @__PURE__ */ new WeakMap();
2428
- function vn(e = document, t) {
2429
- let n = e.querySelector(`style#${gn}`);
2430
- if (n && (!t || Z.get(n) === t)) return;
2478
+ var yn = "havik-player-styles", bn = "\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 touch-action:manipulation}\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", xn = /* @__PURE__ */ new WeakMap();
2479
+ function Sn(e = document, t) {
2480
+ let n = e.querySelector(`style#${yn}`);
2481
+ if (n && (!t || xn.get(n) === t)) return;
2431
2482
  let r = e.createElement("style");
2432
- r.id = gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = _n, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2483
+ r.id = yn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = bn, xn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2433
2484
  }
2434
2485
  //#endregion
2435
2486
  //#region src/ui/icons.ts
2436
- var yn = {
2487
+ var Cn = {
2437
2488
  play: "<path d=\"M8 5v14l11-7z\"/>",
2438
2489
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2439
2490
  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\"/>",
@@ -2447,20 +2498,20 @@ var yn = {
2447
2498
  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\"/>"
2448
2499
  };
2449
2500
  function Q(e) {
2450
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yn[e]}</svg>`;
2501
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Cn[e]}</svg>`;
2451
2502
  }
2452
2503
  //#endregion
2453
2504
  //#region src/ui/controls.ts
2454
- var bn = 3e3, xn = 250, Sn = /* @__PURE__ */ new Set([
2505
+ var wn = 3e3, Tn = 250, En = /* @__PURE__ */ new Set([
2455
2506
  "GONE",
2456
2507
  "NOT_FOUND",
2457
2508
  "INVALID_URN",
2458
2509
  "UNAUTHORIZED"
2459
2510
  ]);
2460
- function Cn(e) {
2461
- return new wn(e);
2511
+ function Dn(e) {
2512
+ return new On(e);
2462
2513
  }
2463
- var wn = class {
2514
+ var On = class {
2464
2515
  root;
2465
2516
  video;
2466
2517
  player;
@@ -2506,7 +2557,7 @@ var wn = class {
2506
2557
  scrubbing = !1;
2507
2558
  offFns = [];
2508
2559
  constructor(e) {
2509
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? bn, 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, vn(this.doc, e.cspNonce), 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");
2560
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? wn, 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, Sn(this.doc, e.cspNonce), 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");
2510
2561
  let t = (e, t, n) => {
2511
2562
  let r = this.doc.createElement(e);
2512
2563
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2592,7 +2643,7 @@ var wn = class {
2592
2643
  let t = this.surfaceWasHidden;
2593
2644
  this.tapTimer = setTimeout(() => {
2594
2645
  this.tapTimer = void 0, this.toggleBar(t);
2595
- }, xn);
2646
+ }, Tn);
2596
2647
  }
2597
2648
  toggleBar(e) {
2598
2649
  e ? this.poke() : this.hideIfIdle();
@@ -2627,7 +2678,7 @@ var wn = class {
2627
2678
  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);
2628
2679
  } else {
2629
2680
  let r = this.doc.createElement("div");
2630
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Sn.has(this.lastError.code)) {
2681
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !En.has(this.lastError.code)) {
2631
2682
  let e = this.doc.createElement("button");
2632
2683
  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);
2633
2684
  }
@@ -2668,7 +2719,7 @@ var wn = class {
2668
2719
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2669
2720
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2670
2721
  }
2671
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Tn(this.video.currentTime)} / ${Tn(this.video.duration)}`);
2722
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${kn(this.video.currentTime)} / ${kn(this.video.duration)}`);
2672
2723
  }
2673
2724
  syncLive() {
2674
2725
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2718,17 +2769,17 @@ var wn = class {
2718
2769
  renderQualityMenu() {
2719
2770
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2720
2771
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2721
- for (let n of e) this.menu.append(this.menuItem(En(n), t === n.index, () => this.player.setQuality(n.index)));
2772
+ for (let n of e) this.menu.append(this.menuItem(An(n), t === n.index, () => this.player.setQuality(n.index)));
2722
2773
  }
2723
2774
  renderAudioMenu() {
2724
2775
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2725
2776
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2726
- for (let t of e) this.menu.append(this.menuItem(Dn(t), t.default, () => this.player.setAudioTrack(t.id)));
2777
+ for (let t of e) this.menu.append(this.menuItem(jn(t), t.default, () => this.player.setAudioTrack(t.id)));
2727
2778
  }
2728
2779
  renderCcMenu() {
2729
2780
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2730
2781
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2731
- for (let t of e) this.menu.append(this.menuItem(On(t), !1, () => this.player.setTextTrack(t.id)));
2782
+ for (let t of e) this.menu.append(this.menuItem(Mn(t), !1, () => this.player.setTextTrack(t.id)));
2732
2783
  }
2733
2784
  onTracksChanged() {
2734
2785
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2748,11 +2799,11 @@ var wn = class {
2748
2799
  }
2749
2800
  async toggleFullscreen() {
2750
2801
  try {
2751
- C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
2802
+ S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
2752
2803
  } catch {}
2753
2804
  }
2754
2805
  syncFullscreen() {
2755
- let e = C(this.video, this.root);
2806
+ let e = S(this.video, this.root);
2756
2807
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2757
2808
  }
2758
2809
  poke() {
@@ -2829,41 +2880,41 @@ var wn = class {
2829
2880
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2830
2881
  }
2831
2882
  };
2832
- function Tn(e) {
2883
+ function kn(e) {
2833
2884
  (!Number.isFinite(e) || e < 0) && (e = 0);
2834
2885
  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");
2835
2886
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2836
2887
  }
2837
- function En(e) {
2888
+ function An(e) {
2838
2889
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2839
2890
  }
2840
- function Dn(e) {
2891
+ function jn(e) {
2841
2892
  return e.name || e.lang || `Track ${e.id}`;
2842
2893
  }
2843
- function On(e) {
2894
+ function Mn(e) {
2844
2895
  return e.name || e.lang || `Track ${e.id}`;
2845
2896
  }
2846
2897
  //#endregion
2847
2898
  //#region src/managed/index.ts
2848
- var kn = 6e3, An = 45e3, jn = 2e3, Mn = 3, Nn = 2e3, Pn = 48e4;
2849
- function Fn(e) {
2899
+ var Nn = 6e3, Pn = 45e3, Fn = 2e3, In = 3, Ln = 2e3, Rn = 48e4;
2900
+ function zn(e) {
2850
2901
  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)})`);
2851
- if (e.env !== void 0) return B(e.env);
2902
+ if (e.env !== void 0) return Ke(e.env);
2852
2903
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2853
2904
  return e.baseUrl;
2854
2905
  }
2855
- async function In(e) {
2906
+ async function Bn(e) {
2856
2907
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2857
- let t = Fn(e);
2908
+ let t = zn(e);
2858
2909
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2859
2910
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2860
- let r = new Ln({
2911
+ let r = new Vn({
2861
2912
  ...e,
2862
2913
  baseUrl: t
2863
2914
  });
2864
2915
  return await r.start(), r;
2865
2916
  }
2866
- var Ln = class {
2917
+ var Vn = class {
2867
2918
  opts;
2868
2919
  abort = new AbortController();
2869
2920
  listeners = {};
@@ -2907,7 +2958,7 @@ var Ln = class {
2907
2958
  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");
2908
2959
  let e = ++this.loadGen, t = this.resolveOptions();
2909
2960
  try {
2910
- let n = await y(t);
2961
+ let n = await v(t);
2911
2962
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2912
2963
  let e = this._lastError;
2913
2964
  throw this.destroy(), e;
@@ -2930,11 +2981,11 @@ var Ln = class {
2930
2981
  };
2931
2982
  }
2932
2983
  beginArming(e, t, n = !1) {
2933
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
2984
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2934
2985
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2935
2986
  }
2936
2987
  beginArmingByPolling(e) {
2937
- b({
2988
+ y({
2938
2989
  ...this.resolveOptions(),
2939
2990
  signal: this.abort.signal,
2940
2991
  waitForLive: this.buildWaitConfig(e)
@@ -2951,7 +3002,7 @@ var Ln = class {
2951
3002
  setTimeout(() => {
2952
3003
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2953
3004
  phase: i ? "unavailable" : "tooEarly",
2954
- retryInMs: An,
3005
+ retryInMs: Pn,
2955
3006
  attempt: 1,
2956
3007
  elapsedMs: 0,
2957
3008
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2968,7 +3019,7 @@ var Ln = class {
2968
3019
  }
2969
3020
  }
2970
3021
  }, h = () => {
2971
- a || s || p() || (s = !0, b({
3022
+ a || s || p() || (s = !0, y({
2972
3023
  ...this.resolveOptions(),
2973
3024
  signal: c.signal,
2974
3025
  waitForLive: this.buildWaitConfig(e)
@@ -2976,7 +3027,7 @@ var Ln = class {
2976
3027
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
2977
3028
  }));
2978
3029
  }, g = () => {
2979
- a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
3030
+ a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2980
3031
  if (!(a || p())) {
2981
3032
  if (e instanceof n && o(e.code)) {
2982
3033
  h();
@@ -2990,13 +3041,13 @@ var Ln = class {
2990
3041
  !a && !p() && h();
2991
3042
  }, e);
2992
3043
  };
2993
- _(kn), this.armingSub = E({
3044
+ _(Nn), this.armingSub = T({
2994
3045
  eventsBaseUrl: t,
2995
3046
  matchUrn: this.opts.matchUrn,
2996
3047
  credential: this.opts.credential,
2997
- onAlive: () => _(An),
3048
+ onAlive: () => _(Pn),
2998
3049
  onState: (e) => {
2999
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * jn);
3050
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Fn);
3000
3051
  },
3001
3052
  onError: () => h()
3002
3053
  });
@@ -3019,7 +3070,7 @@ var Ln = class {
3019
3070
  let n = await s(this.opts.credential);
3020
3071
  if (this.destroyed || t !== this.loadGen) return;
3021
3072
  this.setState("loading");
3022
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
3073
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ye(this.opts.video, (e) => {
3023
3074
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3024
3075
  });
3025
3076
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3041,26 +3092,26 @@ var Ln = class {
3041
3092
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3042
3093
  let i = e.analytics?.sid;
3043
3094
  if (!i) return;
3044
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = an(this.opts.baseUrl, a, e.analytics?.endpoint);
3095
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ln(this.opts.baseUrl, a, e.analytics?.endpoint);
3045
3096
  if (!o) {
3046
3097
  s && setTimeout(() => {
3047
3098
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3048
3099
  }, 0);
3049
3100
  return;
3050
3101
  }
3051
- let c = this.opts.video, l = new on({
3102
+ let c = this.opts.video, l = new un({
3052
3103
  endpoint: o,
3053
3104
  sid: i,
3054
3105
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3055
- sdkVersion: fn,
3056
- environment: un(c),
3106
+ sdkVersion: gn,
3107
+ environment: mn(c),
3057
3108
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3058
3109
  onIdle: () => this.onAnalyticsIdle(t),
3059
3110
  onBlocked: (e) => setTimeout(() => {
3060
3111
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3061
3112
  }, 0),
3062
3113
  sample: () => {
3063
- let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3114
+ let e = this.engine?.getStats() ?? z, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3064
3115
  return {
3065
3116
  ...e,
3066
3117
  bufferedMs: Math.round(t * 1e3),
@@ -3074,7 +3125,7 @@ var Ln = class {
3074
3125
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3075
3126
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3076
3127
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3077
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), dn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3128
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), hn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3078
3129
  }
3079
3130
  currentPresentation() {
3080
3131
  let e = this.opts.video;
@@ -3089,7 +3140,7 @@ var Ln = class {
3089
3140
  video: this.opts.video,
3090
3141
  descriptor: e,
3091
3142
  credential: t,
3092
- deviceId: A(),
3143
+ deviceId: k(),
3093
3144
  userId: this.opts.userId,
3094
3145
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3095
3146
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -3100,9 +3151,9 @@ var Ln = class {
3100
3151
  emit: (e) => this.onEngineEvent(e)
3101
3152
  }, o = this.opts.engine ?? "auto";
3102
3153
  if (o === "native") return new K(a);
3103
- if (o === "hls") return new Bt(a);
3104
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ze() && W(this.opts.video)) return new K(a);
3105
- if (ct()) return new Bt(a);
3154
+ if (o === "hls") return new Wt(a);
3155
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && tt() && W(this.opts.video)) return new K(a);
3156
+ if (ft()) return new Wt(a);
3106
3157
  if (W(this.opts.video)) return new K(a);
3107
3158
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3108
3159
  }
@@ -3140,11 +3191,11 @@ var Ln = class {
3140
3191
  }
3141
3192
  startLiveState(e) {
3142
3193
  if (this.opts.liveStateEvents === !1) return;
3143
- let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3194
+ let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
3144
3195
  if (!t) return;
3145
3196
  this.closeLiveState();
3146
3197
  let r = 0, i = !1;
3147
- this.liveStateSub = E({
3198
+ this.liveStateSub = T({
3148
3199
  eventsBaseUrl: t,
3149
3200
  matchUrn: this.opts.matchUrn,
3150
3201
  credential: this.opts.credential,
@@ -3155,7 +3206,7 @@ var Ln = class {
3155
3206
  r = 0, i = !1;
3156
3207
  },
3157
3208
  onError: () => {
3158
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Mn && (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.`))));
3209
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= In && (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.`))));
3159
3210
  }
3160
3211
  });
3161
3212
  }
@@ -3177,7 +3228,7 @@ var Ln = class {
3177
3228
  scheduleRejoin(e) {
3178
3229
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3179
3230
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3180
- }, Math.random() * jn));
3231
+ }, Math.random() * Fn));
3181
3232
  }
3182
3233
  cancelRejoin() {
3183
3234
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3201,7 +3252,7 @@ var Ln = class {
3201
3252
  }
3202
3253
  t.controls = !1;
3203
3254
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3204
- r && r.insertBefore(n, t), n.appendChild(t), hn(n, this.opts.theme), this.container = n, this.controlBar = Cn({
3255
+ r && r.insertBefore(n, t), n.appendChild(t), Z(n, this.opts.theme), this.container = n, this.controlBar = Dn({
3205
3256
  root: n,
3206
3257
  video: t,
3207
3258
  player: this,
@@ -3232,7 +3283,7 @@ var Ln = class {
3232
3283
  }
3233
3284
  startStats() {
3234
3285
  this.stopStats();
3235
- let e = Math.max(500, this.opts.statsIntervalMs ?? Nn);
3286
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Ln);
3236
3287
  this.statsTimer = setInterval(() => {
3237
3288
  if (!this.engine) return;
3238
3289
  let e = this.engine.getStats();
@@ -3244,7 +3295,7 @@ var Ln = class {
3244
3295
  }
3245
3296
  scheduleLicenseRefresh() {
3246
3297
  this.stopRefresh();
3247
- let e = this.opts.licenseRefreshMs ?? Pn;
3298
+ let e = this.opts.licenseRefreshMs ?? Rn;
3248
3299
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3249
3300
  }
3250
3301
  stopRefresh() {
@@ -3253,7 +3304,7 @@ var Ln = class {
3253
3304
  async refreshLicense() {
3254
3305
  let e = this.engine;
3255
3306
  if (!this.destroyed && e) try {
3256
- let t = await y(this.resolveOptions());
3307
+ let t = await v(this.resolveOptions());
3257
3308
  if (this.destroyed || this.engine !== e) return;
3258
3309
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3259
3310
  (n || r) && (e.setLicenseUrls({
@@ -3289,7 +3340,7 @@ var Ln = class {
3289
3340
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3290
3341
  }
3291
3342
  getStats() {
3292
- return this.engine?.getStats() ?? V;
3343
+ return this.engine?.getStats() ?? z;
3293
3344
  }
3294
3345
  getQualityLevels() {
3295
3346
  return this.engine?.getQualityLevels() ?? [];
@@ -3328,10 +3379,10 @@ var Ln = class {
3328
3379
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3329
3380
  }
3330
3381
  async enterFullscreen() {
3331
- return !this.destroyed && w(this.opts.video, this.container ?? void 0);
3382
+ return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3332
3383
  }
3333
3384
  async exitFullscreen() {
3334
- await T(this.opts.video, this.container ?? void 0);
3385
+ await w(this.opts.video, this.container ?? void 0);
3335
3386
  }
3336
3387
  retry() {
3337
3388
  return this.reload();
@@ -3341,7 +3392,7 @@ var Ln = class {
3341
3392
  let e = ++this.loadGen;
3342
3393
  this.teardownPlayback();
3343
3394
  try {
3344
- let t = await b({
3395
+ let t = await y({
3345
3396
  ...this.resolveOptions(),
3346
3397
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3347
3398
  });
@@ -3399,7 +3450,7 @@ function $(e) {
3399
3450
  }
3400
3451
  //#endregion
3401
3452
  //#region src/embed/host.ts
3402
- function Rn(e) {
3453
+ function Hn(e) {
3403
3454
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3404
3455
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3405
3456
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3458,15 +3509,15 @@ function Rn(e) {
3458
3509
  }
3459
3510
  //#endregion
3460
3511
  //#region src/embed/page.ts
3461
- var zn = /^[A-Za-z0-9:_.-]{1,128}$/;
3462
- function Bn(e) {
3512
+ var Un = /^[A-Za-z0-9:_.-]{1,128}$/;
3513
+ function Wn(e) {
3463
3514
  if (typeof e == "boolean") return e;
3464
3515
  if (typeof e == "object" && e) {
3465
3516
  let t = e.endpoint;
3466
3517
  return typeof t == "string" ? { endpoint: t } : {};
3467
3518
  }
3468
3519
  }
3469
- function Vn() {
3520
+ function Gn() {
3470
3521
  let e = window.HAVIK_EMBED_CONFIG;
3471
3522
  if (e) return {
3472
3523
  baseUrl: e.baseUrl ?? "",
@@ -3476,7 +3527,7 @@ function Vn() {
3476
3527
  autoplay: e.autoplay ?? !0,
3477
3528
  muted: e.muted ?? !0,
3478
3529
  waitForLive: e.waitForLive ?? !0,
3479
- analytics: Bn(e.analytics)
3530
+ analytics: Wn(e.analytics)
3480
3531
  };
3481
3532
  let t = new URLSearchParams(location.search);
3482
3533
  return {
@@ -3489,9 +3540,9 @@ function Vn() {
3489
3540
  waitForLive: !0
3490
3541
  };
3491
3542
  }
3492
- async function Hn() {
3493
- let e = Vn();
3494
- Wn();
3543
+ async function Kn() {
3544
+ let e = Gn();
3545
+ Jn();
3495
3546
  let t = document.createElement("video");
3496
3547
  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);
3497
3548
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3546,12 +3597,12 @@ async function Hn() {
3546
3597
  code: e.code,
3547
3598
  message: e.message
3548
3599
  })), e.on("autoplayblocked", () => {
3549
- i({ type: "oddin:autoplayblocked" }), Un(t, e);
3600
+ i({ type: "oddin:autoplayblocked" }), qn(t, e);
3550
3601
  });
3551
3602
  }, s = async (r) => {
3552
3603
  a?.destroy(), a = null;
3553
3604
  try {
3554
- let n = await In({
3605
+ let n = await Bn({
3555
3606
  video: t,
3556
3607
  baseUrl: e.baseUrl,
3557
3608
  matchUrn: r,
@@ -3613,7 +3664,7 @@ async function Hn() {
3613
3664
  a?.retry();
3614
3665
  break;
3615
3666
  case "oddin:load":
3616
- typeof e.matchUrn == "string" && zn.test(e.matchUrn) && s(e.matchUrn);
3667
+ typeof e.matchUrn == "string" && Un.test(e.matchUrn) && s(e.matchUrn);
3617
3668
  break;
3618
3669
  case "oddin:destroy": c();
3619
3670
  }
@@ -3625,18 +3676,18 @@ async function Hn() {
3625
3676
  protocol: 1
3626
3677
  });
3627
3678
  }
3628
- function Un(e, t) {
3679
+ function qn(e, t) {
3629
3680
  if (document.getElementById("havik-tap")) return;
3630
3681
  let n = document.createElement("button");
3631
3682
  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", () => {
3632
3683
  n.remove(), t.play();
3633
3684
  }), document.body.appendChild(n);
3634
3685
  }
3635
- function Wn() {
3686
+ function Jn() {
3636
3687
  let e = document.createElement("style");
3637
3688
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3638
3689
  }
3639
3690
  //#endregion
3640
- export { pn as ODDIN_THEME, n as PlaybackError, hn as applyTheme, B as baseUrlForEnv, Hn as bootEmbed, we as clearDeviceId, In as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, Rn as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
3691
+ export { _n as ODDIN_THEME, n as PlaybackError, Z as applyTheme, Ke as baseUrlForEnv, Kn as bootEmbed, Te as clearDeviceId, Bn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Hn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3641
3692
 
3642
3693
  //# sourceMappingURL=index.js.map