@oddin-gg/havik-player 2.12.0 → 2.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -290,32 +290,32 @@ function he(e, t) {
290
290
  function ge(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function _e(e) {
293
+ function x(e) {
294
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
295
295
  }
296
- function x(e, t) {
297
- let n = _e(ge(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 S(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 C(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 = ge(e), i = _e(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 ve(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 ve(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: ye(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 ye(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 ye(e) {
360
360
  };
361
361
  });
362
362
  }
363
- async function be(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 be(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: xe(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 xe(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,11 +406,16 @@ function xe(e) {
406
406
  }))
407
407
  };
408
408
  }
409
- function Se(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 Se = /* @__PURE__ */ new Set([
415
+ "NOT_FOUND",
416
+ "GONE",
417
+ "INVALID_URN"
418
+ ]);
414
419
  function Ce(e) {
415
420
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
416
421
  u || (a = setTimeout(m, t));
@@ -442,7 +447,10 @@ function Ce(e) {
442
447
  }));
443
448
  }
444
449
  } catch (t) {
445
- i.signal.aborted || e.onError?.(t instanceof n ? t : new n("NETWORK", 0, String(t)));
450
+ if (!i.signal.aborted) {
451
+ let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
+ Se.has(r.code) && (u = !0), e.onError?.(r);
453
+ }
446
454
  } finally {
447
455
  f();
448
456
  }
@@ -454,7 +462,7 @@ function Ce(e) {
454
462
  //#endregion
455
463
  //#region src/core/events.ts
456
464
  var we = 45e3;
457
- function w(e) {
465
+ function T(e) {
458
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) => {
459
467
  if (a.signal.aborted) return t();
460
468
  let n = setTimeout(t, e);
@@ -536,7 +544,7 @@ function w(e) {
536
544
  o || (o = !0, a.abort());
537
545
  } };
538
546
  }
539
- function T(e) {
547
+ function E(e) {
540
548
  try {
541
549
  let t = new URL(e);
542
550
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -546,24 +554,24 @@ function T(e) {
546
554
  }
547
555
  //#endregion
548
556
  //#region src/core/drm/deviceId.ts
549
- var E = "havik.player.deviceId", D;
550
- function O() {
551
- if (D) return D;
557
+ var D = "havik.player.deviceId", O;
558
+ function k() {
559
+ if (O) return O;
552
560
  try {
553
- let e = globalThis.localStorage?.getItem(E);
554
- if (e) return D = e, e;
561
+ let e = globalThis.localStorage?.getItem(D);
562
+ if (e) return O = e, e;
555
563
  } catch {}
556
564
  let e = Ee();
557
- D = e;
565
+ O = e;
558
566
  try {
559
- globalThis.localStorage?.setItem(E, e);
567
+ globalThis.localStorage?.setItem(D, e);
560
568
  } catch {}
561
569
  return e;
562
570
  }
563
571
  function Te() {
564
- D = void 0;
572
+ O = void 0;
565
573
  try {
566
- globalThis.localStorage?.removeItem(E);
574
+ globalThis.localStorage?.removeItem(D);
567
575
  } catch {}
568
576
  }
569
577
  function Ee() {
@@ -582,17 +590,17 @@ function De(e, t, n = {}) {
582
590
  let r = {
583
591
  "x-api-key": t.apiKey,
584
592
  "X-Match-Urn": e.matchUrn,
585
- "X-Device-Id": n.deviceId ?? O(),
593
+ "X-Device-Id": n.deviceId ?? k(),
586
594
  "Content-Type": "application/octet-stream"
587
595
  };
588
596
  return n.userId && (r["X-User-Id"] = n.userId), r;
589
597
  }
590
598
  //#endregion
591
599
  //#region src/core/drm/cdm.ts
592
- var k = /* @__PURE__ */ new WeakMap();
600
+ var A = /* @__PURE__ */ new WeakMap();
593
601
  function Oe(e, t) {
594
- let n = k.get(e);
595
- n || (n = /* @__PURE__ */ new Map(), k.set(e, n));
602
+ let n = A.get(e);
603
+ n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
596
604
  let r = n.get(t.keySystem);
597
605
  if (r) return r;
598
606
  let i = t.createMediaKeys().catch((e) => {
@@ -600,22 +608,22 @@ function Oe(e, t) {
600
608
  });
601
609
  return n.set(t.keySystem, i), i;
602
610
  }
603
- function A() {
611
+ function j() {
604
612
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
605
613
  }
606
- var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
614
+ var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
607
615
  function ke(e) {
608
616
  return e.startsWith("com.widevine");
609
617
  }
610
- function M(e, t) {
618
+ function N(e, t) {
611
619
  if (!ke(e)) return t;
612
620
  let n = (e, t) => {
613
621
  let n = e.videoCapabilities;
614
622
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
615
- let n = j.indexOf(e.robustness);
616
- return n === -1 || j.indexOf(t) > n;
623
+ let n = M.indexOf(e.robustness);
624
+ return n === -1 || M.indexOf(t) > n;
617
625
  });
618
- }, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
626
+ }, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
619
627
  ...t,
620
628
  videoCapabilities: t.videoCapabilities?.map((t) => ({
621
629
  ...t,
@@ -624,43 +632,43 @@ function M(e, t) {
624
632
  })));
625
633
  return [...t, ...r];
626
634
  }
627
- function N(e) {
628
- return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
635
+ function P(e) {
636
+ return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
629
637
  keySystem: t.keySystem,
630
638
  getConfiguration: () => t.getConfiguration(),
631
639
  createMediaKeys: () => Oe(e, t)
632
640
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
633
641
  }
634
- var P = {
642
+ var F = {
635
643
  video: "SW_SECURE_DECODE",
636
644
  audio: "SW_SECURE_CRYPTO",
637
645
  scheme: "cbcs"
638
646
  };
639
647
  function Ae(e) {
640
- if (!A()) return;
648
+ if (!j()) return;
641
649
  let t = (e, t) => ({
642
650
  contentType: e,
643
651
  robustness: t,
644
- encryptionScheme: P.scheme
652
+ encryptionScheme: F.scheme
645
653
  });
646
- N(e)("com.widevine.alpha", [{
654
+ P(e)("com.widevine.alpha", [{
647
655
  initDataTypes: ["cenc"],
648
656
  distinctiveIdentifier: "optional",
649
657
  persistentState: "optional",
650
658
  sessionTypes: ["temporary"],
651
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", P.audio)],
652
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", P.video)]
659
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
660
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
653
661
  }]).then((e) => e.createMediaKeys()).catch(() => {});
654
662
  }
655
- function F(e) {
656
- let t = I(e);
663
+ function I(e) {
664
+ let t = L(e);
657
665
  if (/^avc[13]/.test(t)) return "avc";
658
666
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
659
667
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
660
668
  if (t.startsWith("av01")) return "av1";
661
669
  if (/^vp0?9/.test(t)) return "vp9";
662
670
  }
663
- function I(e) {
671
+ function L(e) {
664
672
  return (e ?? "").trim().toLowerCase();
665
673
  }
666
674
  var je = {
@@ -668,9 +676,9 @@ var je = {
668
676
  dv: "dvh1.05.06",
669
677
  av1: "av01.0.05M.08",
670
678
  vp9: "vp09.00.10.08"
671
- }, Me = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new Map();
679
+ }, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
672
680
  function Ne(e) {
673
- let t = I(e), n = Me.get(t);
681
+ let t = L(e), n = Me.get(t);
674
682
  if (n) return n;
675
683
  let r = {
676
684
  initDataTypes: ["cenc"],
@@ -679,32 +687,32 @@ function Ne(e) {
679
687
  sessionTypes: ["temporary"],
680
688
  videoCapabilities: [{
681
689
  contentType: `video/mp4; codecs="${e.trim()}"`,
682
- robustness: P.video,
683
- encryptionScheme: P.scheme
690
+ robustness: F.video,
691
+ encryptionScheme: F.scheme
684
692
  }]
685
693
  }, i = (async () => {
686
694
  try {
687
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
695
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
688
696
  } catch {
689
697
  return !1;
690
698
  }
691
- })().then((e) => (L.set(t, e), e));
699
+ })().then((e) => (R.set(t, e), e));
692
700
  return Me.set(t, i), i;
693
701
  }
694
702
  function Pe() {
695
- if (A()) for (let e of Object.values(je)) Ne(e);
703
+ if (j()) for (let e of Object.values(je)) Ne(e);
696
704
  }
697
705
  function Fe(e) {
698
- let t = F(e);
699
- if (t) return t === "avc" ? !0 : L.get(I(e)) ?? L.get(I(je[t]));
706
+ let t = I(e);
707
+ if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
700
708
  }
701
709
  //#endregion
702
710
  //#region src/core/drm/support.ts
703
- var Ie = 5e3, R = "video/mp4; codecs=\"avc1.42E01E\"", z = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
711
+ var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
704
712
  widevine: ["com.widevine.alpha"],
705
713
  fairplay: ["com.apple.fps"]
706
714
  };
707
- function Re(e) {
715
+ function Be(e) {
708
716
  return e === "fairplay" ? [{
709
717
  initDataTypes: [
710
718
  "sinf",
@@ -712,30 +720,30 @@ function Re(e) {
712
720
  "cenc"
713
721
  ],
714
722
  videoCapabilities: [{
715
- contentType: R,
723
+ contentType: Le,
716
724
  robustness: "",
717
725
  encryptionScheme: "cbcs"
718
726
  }],
719
727
  audioCapabilities: [{
720
- contentType: z,
728
+ contentType: Re,
721
729
  robustness: "",
722
730
  encryptionScheme: "cbcs"
723
731
  }]
724
- }] : M("com.widevine.alpha", [{
732
+ }] : N("com.widevine.alpha", [{
725
733
  initDataTypes: ["cenc"],
726
734
  videoCapabilities: [{
727
- contentType: R,
728
- robustness: P.video,
729
- encryptionScheme: P.scheme
735
+ contentType: Le,
736
+ robustness: F.video,
737
+ encryptionScheme: F.scheme
730
738
  }],
731
739
  audioCapabilities: [{
732
- contentType: z,
733
- robustness: P.audio,
734
- encryptionScheme: P.scheme
740
+ contentType: Re,
741
+ robustness: F.audio,
742
+ encryptionScheme: F.scheme
735
743
  }]
736
744
  }]);
737
745
  }
738
- function B(e, t) {
746
+ function Ve(e, t) {
739
747
  return new Promise((n, r) => {
740
748
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
741
749
  e.then((e) => {
@@ -745,7 +753,7 @@ function B(e, t) {
745
753
  });
746
754
  });
747
755
  }
748
- async function ze(e = {}) {
756
+ async function He(e = {}) {
749
757
  let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
750
758
  if (typeof window < "u" && window.isSecureContext === !1) return {
751
759
  verdict: "insecure-context",
@@ -758,7 +766,7 @@ async function ze(e = {}) {
758
766
  };
759
767
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
760
768
  for (let e of t) {
761
- let t = Le[e];
769
+ let t = ze[e];
762
770
  if (!t) {
763
771
  r[e] = "unknown system";
764
772
  continue;
@@ -769,7 +777,7 @@ async function ze(e = {}) {
769
777
  break;
770
778
  }
771
779
  try {
772
- return await B((await B(i(n, Re(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})`, {
773
781
  verdict: "supported",
774
782
  system: e,
775
783
  detail: r
@@ -793,49 +801,49 @@ async function ze(e = {}) {
793
801
  }
794
802
  //#endregion
795
803
  //#region src/core/manifest.ts
796
- var Be = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
797
- function Ve(e) {
798
- return Be.test(e);
804
+ var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function We(e) {
806
+ return Ue.test(e);
799
807
  }
800
808
  //#endregion
801
809
  //#region src/core/env.ts
802
- var V = {
810
+ var z = {
803
811
  integration: "https://feed-dev.oddin-video.gg",
804
812
  production: "https://feed.oddin-video.gg"
805
813
  };
806
- function H(e) {
807
- let t = Object.prototype.hasOwnProperty.call(V, e) ? V[e] : void 0;
814
+ function B(e) {
815
+ let t = Object.prototype.hasOwnProperty.call(z, e) ? z[e] : void 0;
808
816
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
809
817
  return t;
810
818
  }
811
819
  //#endregion
812
820
  //#region src/core/stats.ts
813
- var U = { droppedFrames: 0 };
814
- function W(e) {
821
+ var V = { droppedFrames: 0 };
822
+ function H(e) {
815
823
  try {
816
824
  return new URL(e).host;
817
825
  } catch {
818
826
  return "";
819
827
  }
820
828
  }
821
- var He = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
822
- function Ue(e) {
829
+ var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
+ function Ke(e) {
823
831
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
824
832
  let t = "", n = -1, r = performance.getEntriesByType("resource");
825
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || He.test(i.name)) && i.startTime >= n) {
826
- let e = W(i.name);
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);
827
835
  e && (t = e, n = i.startTime);
828
836
  }
829
837
  return t;
830
838
  }
831
- function G(e) {
839
+ function U(e) {
832
840
  let t = e.getVideoPlaybackQuality?.();
833
841
  return {
834
842
  dropped: t?.droppedVideoFrames ?? 0,
835
843
  totalFrames: t?.totalVideoFrames ?? 0
836
844
  };
837
845
  }
838
- function We(e, t) {
846
+ function qe(e, t) {
839
847
  let n = [
840
848
  ["playing", () => t("playing")],
841
849
  ["waiting", () => t("buffering")],
@@ -852,7 +860,7 @@ function We(e, t) {
852
860
  }
853
861
  //#endregion
854
862
  //#region src/core/engine/native.ts
855
- function Ge(e) {
863
+ function Je(e) {
856
864
  try {
857
865
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
858
866
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -860,15 +868,15 @@ function Ge(e) {
860
868
  return;
861
869
  }
862
870
  }
863
- function K(e) {
871
+ function W(e) {
864
872
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
865
873
  }
866
- function q() {
874
+ function G() {
867
875
  if (typeof window > "u") return !1;
868
876
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
869
877
  return e || t;
870
878
  }
871
- var J = class {
879
+ var K = class {
872
880
  name = "native";
873
881
  deps;
874
882
  onLoaded;
@@ -904,7 +912,7 @@ var J = class {
904
912
  type: "error",
905
913
  error: new n("INTERNAL", 0, "native HLS playback error"),
906
914
  fatal: !0
907
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ke(t.manifestUrl, t.analytics?.sid), e.load();
915
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ye(t.manifestUrl, t.analytics?.sid), e.load();
908
916
  }
909
917
  startLoad() {
910
918
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -926,7 +934,7 @@ var J = class {
926
934
  });
927
935
  this.onEncrypted = (n) => {
928
936
  let i = n;
929
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ge(i.initData), (async () => {
937
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
930
938
  try {
931
939
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
932
940
  initDataTypes: [i.initDataType],
@@ -1021,11 +1029,11 @@ var J = class {
1021
1029
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
1022
1030
  }
1023
1031
  getStats() {
1024
- let e = this.deps.video, t = G(e), n = {
1032
+ let e = this.deps.video, t = U(e), n = {
1025
1033
  droppedFrames: t.dropped,
1026
1034
  decodedFrames: t.totalFrames
1027
1035
  };
1028
- return this.cdnHost ||= Ue(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1036
+ return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1029
1037
  }
1030
1038
  stop() {
1031
1039
  try {
@@ -1044,13 +1052,13 @@ var J = class {
1044
1052
  } catch {}
1045
1053
  }
1046
1054
  };
1047
- function Ke(e, t) {
1055
+ function Ye(e, t) {
1048
1056
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1049
1057
  }
1050
1058
  //#endregion
1051
1059
  //#region src/core/engine/prefetch.ts
1052
- var qe = 15e3, Je = 5e3, Ye = 6;
1053
- function Xe(e) {
1060
+ var Xe = 15e3, Ze = 5e3, Qe = 6;
1061
+ function $e(e) {
1054
1062
  try {
1055
1063
  let t = new URL(e);
1056
1064
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1058,7 +1066,7 @@ function Xe(e) {
1058
1066
  return e;
1059
1067
  }
1060
1068
  }
1061
- var Ze = class {
1069
+ var et = class {
1062
1070
  cmcd;
1063
1071
  entries = /* @__PURE__ */ new Map();
1064
1072
  keyed = /* @__PURE__ */ new Set();
@@ -1081,10 +1089,10 @@ var Ze = class {
1081
1089
  }
1082
1090
  prefetch(e, t, n) {
1083
1091
  if (!this.isActive(t)) return;
1084
- let r = Xe(e);
1092
+ let r = $e(e);
1085
1093
  if (this.entries.has(r)) return;
1086
1094
  let i = this.perTrack.get(t) ?? 0;
1087
- if (i >= Ye) return;
1095
+ if (i >= Qe) return;
1088
1096
  this.perTrack.set(t, i + 1);
1089
1097
  let a = new AbortController(), o = {
1090
1098
  started: performance.now(),
@@ -1098,10 +1106,10 @@ var Ze = class {
1098
1106
  signal: a.signal
1099
1107
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1100
1108
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1101
- }, qe);
1109
+ }, Xe);
1102
1110
  }
1103
1111
  take(e) {
1104
- let t = Xe(e), n = this.entries.get(t);
1112
+ let t = $e(e), n = this.entries.get(t);
1105
1113
  return n && this.entries.delete(t), n;
1106
1114
  }
1107
1115
  destroy() {
@@ -1121,13 +1129,13 @@ var Ze = class {
1121
1129
  }
1122
1130
  }
1123
1131
  };
1124
- function Qe(t) {
1132
+ function tt(t) {
1125
1133
  let n = e.DefaultConfig?.loader;
1126
1134
  if (typeof n != "function") return;
1127
1135
  class r extends n {
1128
1136
  served = !1;
1129
1137
  cancelled = !1;
1130
- stats = $e();
1138
+ stats = nt();
1131
1139
  load(e, n, r) {
1132
1140
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1133
1141
  if (!i) {
@@ -1135,7 +1143,7 @@ function Qe(t) {
1135
1143
  return;
1136
1144
  }
1137
1145
  this.served = !0;
1138
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Je, s = setTimeout(() => {
1146
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ze, s = setTimeout(() => {
1139
1147
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1140
1148
  }, o);
1141
1149
  i.bytes.then((o) => {
@@ -1162,7 +1170,7 @@ function Qe(t) {
1162
1170
  }
1163
1171
  return r;
1164
1172
  }
1165
- function $e() {
1173
+ function nt() {
1166
1174
  return {
1167
1175
  aborted: !1,
1168
1176
  loaded: 0,
@@ -1186,10 +1194,10 @@ function $e() {
1186
1194
  }
1187
1195
  };
1188
1196
  }
1189
- function et(e) {
1197
+ function rt(e) {
1190
1198
  return e === "audio" ? "audio" : "main";
1191
1199
  }
1192
- function tt(e, t) {
1200
+ function it(e, t) {
1193
1201
  let n = [];
1194
1202
  t.initSegment?.url && !t.initSegment.data && n.push({
1195
1203
  url: t.initSegment.url,
@@ -1208,24 +1216,24 @@ function tt(e, t) {
1208
1216
  }
1209
1217
  //#endregion
1210
1218
  //#region src/core/engine/hls.ts
1211
- function nt() {
1219
+ function at() {
1212
1220
  return e.isSupported();
1213
1221
  }
1214
- var rt = 3, it = 5, at = 3, ot = 3e4, st = 12e3, ct = 3e3, lt = 6e3, ut = 5e3, dt = 4e3, ft = 2, pt = 5, mt = 2, ht = 2, gt = 4, _t = 4, vt = 2e3, yt = 3e4, bt = 2, xt = 9, St = .5, Ct = 64;
1215
- function wt(e) {
1222
+ var ot = 3, st = 5, ct = 3, lt = 3e4, ut = 12e3, dt = 3e3, ft = 6e3, pt = 5e3, mt = 4e3, ht = 2, gt = 5, _t = 2, vt = 2, yt = 4, bt = 4, xt = 2e3, St = 3e4, Ct = 2, wt = 9, Tt = .5, Et = 64;
1223
+ function Dt(e) {
1216
1224
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1217
1225
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1218
1226
  return;
1219
1227
  }
1220
- e.liveSyncDuration ??= bt;
1221
- let t = Math.max(12, e.liveSyncDuration + xt);
1222
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Tt(e, e.liveSyncDuration);
1228
+ e.liveSyncDuration ??= Ct;
1229
+ let t = Math.max(12, e.liveSyncDuration + wt);
1230
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ot(e, e.liveSyncDuration);
1223
1231
  }
1224
- function Tt(e, t) {
1232
+ function Ot(e, t) {
1225
1233
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1226
1234
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1227
1235
  }
1228
- var Et = class {
1236
+ var kt = class {
1229
1237
  name = "hls";
1230
1238
  hls = null;
1231
1239
  deps;
@@ -1293,7 +1301,7 @@ var Et = class {
1293
1301
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1294
1302
  }
1295
1303
  async load() {
1296
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = K(r) && q(), o = !!e.drm?.widevine?.licenseUrl && !a;
1304
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
1297
1305
  if (e.drmEnabled && !o) {
1298
1306
  i({
1299
1307
  type: "error",
@@ -1325,7 +1333,7 @@ var Et = class {
1325
1333
  }
1326
1334
  this.loadSuspended = !0;
1327
1335
  }
1328
- }, ut));
1336
+ }, pt));
1329
1337
  }
1330
1338
  resumeLoading() {
1331
1339
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1357,7 +1365,7 @@ var Et = class {
1357
1365
  let t = e.liveSyncPosition;
1358
1366
  if (typeof t != "number" || !Number.isFinite(t)) return;
1359
1367
  let { video: n } = this.deps;
1360
- n.currentTime <= t + St || (n.currentTime = t);
1368
+ n.currentTime <= t + Tt || (n.currentTime = t);
1361
1369
  }
1362
1370
  startHls() {
1363
1371
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1376,12 +1384,12 @@ var Et = class {
1376
1384
  emeEnabled: !0,
1377
1385
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1378
1386
  drmSystemOptions: {
1379
- videoRobustness: P.video,
1380
- audioRobustness: P.audio,
1381
- videoEncryptionScheme: P.scheme,
1382
- audioEncryptionScheme: P.scheme
1387
+ videoRobustness: F.video,
1388
+ audioRobustness: F.audio,
1389
+ videoEncryptionScheme: F.scheme,
1390
+ audioEncryptionScheme: F.scheme
1383
1391
  },
1384
- ...A() ? { requestMediaKeySystemAccessFunc: N(t) } : {},
1392
+ ...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
1385
1393
  licenseXhrSetup: (e, t) => {
1386
1394
  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;
1387
1395
  let o = performance.now();
@@ -1398,20 +1406,20 @@ var Et = class {
1398
1406
  ...c
1399
1407
  };
1400
1408
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1401
- let e = new Ze({
1409
+ let e = new et({
1402
1410
  sessionId: n.analytics?.sid,
1403
1411
  contentId: n.matchUrn
1404
- }), t = Qe(e);
1412
+ }), t = tt(e);
1405
1413
  t && (this.prefetch = e, d.fLoader = t);
1406
1414
  }
1407
- wt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1415
+ Dt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1408
1416
  let f = new e(d);
1409
1417
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1410
1418
  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" });
1411
1419
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1412
1420
  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(() => {
1413
1421
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1414
- }, ot)));
1422
+ }, lt)));
1415
1423
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1416
1424
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1417
1425
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1419,10 +1427,10 @@ var Et = class {
1419
1427
  let n = t?.frag?.stats, r = n?.loaded;
1420
1428
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1421
1429
  let i = n?.loading;
1422
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ct && this.requestTimesMs.shift());
1430
+ 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 > Et && this.requestTimesMs.shift());
1423
1431
  let a = t?.frag?.url;
1424
1432
  if (a) {
1425
- let e = W(a);
1433
+ let e = H(a);
1426
1434
  e && (this.cdnHost = e);
1427
1435
  }
1428
1436
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1436,15 +1444,15 @@ var Et = class {
1436
1444
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1437
1445
  let t = this.prefetch;
1438
1446
  f.on(e.Events.KEY_LOADING, (e, n) => {
1439
- let r = n?.frag, i = et(r?.type);
1440
- if (r && t.isActive(i)) for (let e of tt(f, r)) t.prefetch(e.url, i, e.kind);
1441
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(et(n?.frag?.type)));
1447
+ let r = n?.frag, i = rt(r?.type);
1448
+ if (r && t.isActive(i)) for (let e of it(f, r)) t.prefetch(e.url, i, e.kind);
1449
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(rt(n?.frag?.type)));
1442
1450
  }
1443
1451
  f.on(e.Events.KEY_LOADED, () => {
1444
1452
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1445
1453
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1446
1454
  this.checkEndStale(), this.checkStarvation();
1447
- }, ct), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1455
+ }, dt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1448
1456
  this.renditionSwitches += 1;
1449
1457
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1450
1458
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1508,7 +1516,7 @@ var Et = class {
1508
1516
  return;
1509
1517
  }
1510
1518
  this.capTimer && clearTimeout(this.capTimer);
1511
- let t = e > this.sizeCapLevel ? vt : yt;
1519
+ let t = e > this.sizeCapLevel ? xt : St;
1512
1520
  this.capTimer = setTimeout(() => {
1513
1521
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1514
1522
  }, t);
@@ -1519,7 +1527,7 @@ var Et = class {
1519
1527
  }
1520
1528
  dropLevelsWidevineCannotPlay(e) {
1521
1529
  this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1522
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && F(e) !== "avc" && !!F(e)));
1530
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1523
1531
  for (let n of t) Ne(n).then((t) => {
1524
1532
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1525
1533
  });
@@ -1528,10 +1536,10 @@ var Et = class {
1528
1536
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1529
1537
  if (n.forEach((e, n) => {
1530
1538
  let a = e.videoCodec;
1531
- a && F(a) && t(a) && (r.push(n), i.add(a));
1539
+ a && I(a) && t(a) && (r.push(n), i.add(a));
1532
1540
  }), !r.length) return !1;
1533
1541
  let a = [...i].join(", ");
1534
- if (!n.some((e, t) => r.includes(t) ? !1 : !F(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1542
+ 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;
1535
1543
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1536
1544
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1537
1545
  }
@@ -1577,7 +1585,7 @@ var Et = class {
1577
1585
  e.widevine && (this.licenseUrl = e.widevine);
1578
1586
  }
1579
1587
  getStats() {
1580
- let e = this.hls, t = G(this.deps.video), n = {
1588
+ let e = this.hls, t = U(this.deps.video), n = {
1581
1589
  droppedFrames: t.dropped,
1582
1590
  decodedFrames: t.totalFrames,
1583
1591
  lowLatency: this.detectedLowLatency,
@@ -1623,7 +1631,7 @@ var Et = class {
1623
1631
  return;
1624
1632
  }
1625
1633
  let e = Date.now() - this.lastAdvanceMs;
1626
- !this.chaseSuspended && e > lt && this.suspendChasing(), e > st && this.emitEnded("stalled");
1634
+ !this.chaseSuspended && e > ft && this.suspendChasing(), e > ut && this.emitEnded("stalled");
1627
1635
  }
1628
1636
  resetStarvationWindow() {
1629
1637
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1638,7 +1646,7 @@ var Et = class {
1638
1646
  this.resetStarvationWindow();
1639
1647
  return;
1640
1648
  }
1641
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < lt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = G(t), c = o - s, l = c !== this.starvedFrames;
1649
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ft, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > mt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1642
1650
  if (this.starvedFrames = c, !a || l) {
1643
1651
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1644
1652
  return;
@@ -1647,12 +1655,12 @@ var Et = class {
1647
1655
  this.resetStarvationWindow();
1648
1656
  return;
1649
1657
  }
1650
- if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > gt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mt && (this.clearKick(), this.starvationRebuilds < ht)) {
1658
+ 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 > yt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= _t && (this.clearKick(), this.starvationRebuilds < vt)) {
1651
1659
  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");
1652
1660
  return;
1653
1661
  }
1654
- let u = i && this.starvedTicks >= ft, d = !i && this.deadTicks >= gt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _t;
1655
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pt))) {
1662
+ let u = i && this.starvedTicks >= ht, d = !i && this.deadTicks >= yt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= bt;
1663
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= gt))) {
1656
1664
  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");
1657
1665
  try {
1658
1666
  e.stopLoad(), e.startLoad(-1);
@@ -1701,7 +1709,7 @@ var Et = class {
1701
1709
  scheduleLicenseRetry(t) {
1702
1710
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1703
1711
  let n = t.response?.code ?? 0;
1704
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= at) return !1;
1712
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ct) return !1;
1705
1713
  this.licenseRecoveries += 1;
1706
1714
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1707
1715
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1733,7 +1741,7 @@ var Et = class {
1733
1741
  return;
1734
1742
  }
1735
1743
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1736
- if (this.networkRecoveries < it) {
1744
+ if (this.networkRecoveries < st) {
1737
1745
  this.networkRecoveries += 1;
1738
1746
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1739
1747
  this.networkRetryTimer = setTimeout(() => {
@@ -1750,7 +1758,7 @@ var Et = class {
1750
1758
  return;
1751
1759
  }
1752
1760
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1753
- if (this.mediaRecoveries < rt) {
1761
+ if (this.mediaRecoveries < ot) {
1754
1762
  this.mediaRecoveries += 1, n.recoverMediaError();
1755
1763
  return;
1756
1764
  }
@@ -1774,19 +1782,19 @@ var Et = class {
1774
1782
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1775
1783
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1776
1784
  }
1777
- }, Dt = 15e3, Ot = 6e5, kt = 3e5, At = 100, Y = 1, jt = 1e3, Mt = 3e4, Nt = 1e3, Pt = {
1785
+ }, At = 15e3, jt = 6e5, Mt = 3e5, Nt = 100, q = 1, Pt = 1e3, Ft = 3e4, It = 1e3, Lt = {
1778
1786
  inline: "PRESENTATION_INLINE",
1779
1787
  fullscreen: "PRESENTATION_FULLSCREEN",
1780
1788
  pip: "PRESENTATION_PIP"
1781
- }, Ft = {
1789
+ }, Rt = {
1782
1790
  widevine: "KEY_SYSTEM_WIDEVINE",
1783
1791
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1784
1792
  none: "KEY_SYSTEM_NONE"
1785
1793
  };
1786
- function It(e, t) {
1794
+ function zt(e, t) {
1787
1795
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1788
1796
  }
1789
- var Lt = /* @__PURE__ */ new Set([
1797
+ var Bt = /* @__PURE__ */ new Set([
1790
1798
  "INVALID_URN",
1791
1799
  "NOT_FOUND",
1792
1800
  "GONE",
@@ -1796,7 +1804,7 @@ var Lt = /* @__PURE__ */ new Set([
1796
1804
  "FORBIDDEN",
1797
1805
  "RATE_LIMITED",
1798
1806
  "TIMEOUT"
1799
- ]), X = {
1807
+ ]), J = {
1800
1808
  idle: "PLAYER_STATE_IDLE",
1801
1809
  waiting: "PLAYER_STATE_WAITING",
1802
1810
  loading: "PLAYER_STATE_LOADING",
@@ -1806,7 +1814,7 @@ var Lt = /* @__PURE__ */ new Set([
1806
1814
  ended: "PLAYER_STATE_ENDED",
1807
1815
  error: "PLAYER_STATE_ERROR"
1808
1816
  };
1809
- function Rt(e) {
1817
+ function Vt(e) {
1810
1818
  try {
1811
1819
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1812
1820
  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);
@@ -1814,15 +1822,29 @@ function Rt(e) {
1814
1822
  return;
1815
1823
  }
1816
1824
  }
1817
- var zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase();
1818
- function Bt(e, t) {
1825
+ var Ht = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Ut = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Wt = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1826
+ function Gt(e) {
1827
+ if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
1828
+ let t;
1829
+ try {
1830
+ let n = new URL(e.blockedURI);
1831
+ t = n.origin + n.pathname;
1832
+ } catch {
1833
+ return;
1834
+ }
1835
+ if (Ut.has(t) && !Y.has(t)) {
1836
+ Y.add(t), g(Wt(new URL(t).origin));
1837
+ for (let e of X) e.noteCspBlocked();
1838
+ }
1839
+ }
1840
+ function Kt(e, t) {
1819
1841
  return g(t, e), { disabledReason: t };
1820
1842
  }
1821
- function Vt(e, t, n) {
1822
- if (n) return t && !zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1843
+ function qt(e, t, n) {
1844
+ if (n) return t && !Ht(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1823
1845
  if (t) return { endpoint: t };
1824
- if (t !== void 0) return Bt("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
1825
- let r = Rt(e);
1846
+ if (t !== void 0) return Kt("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).");
1847
+ let r = Vt(e);
1826
1848
  if (r) return { endpoint: r };
1827
1849
  let i;
1828
1850
  try {
@@ -1830,11 +1852,12 @@ function Vt(e, t, n) {
1830
1852
  } catch {
1831
1853
  i = e;
1832
1854
  }
1833
- return Bt(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
1855
+ return Kt(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).`);
1834
1856
  }
1835
- var Ht = class {
1857
+ var Jt = class {
1836
1858
  opts;
1837
1859
  url;
1860
+ cspKey;
1838
1861
  now;
1839
1862
  seq = 0;
1840
1863
  pending = [];
@@ -1902,6 +1925,7 @@ var Ht = class {
1902
1925
  firstPlaylistMs = 0;
1903
1926
  drmSetupMs = 0;
1904
1927
  onPagehide = () => this.end("END_REASON_PAGEHIDE");
1928
+ cspBlockedNoted = !1;
1905
1929
  onFreeze = () => {
1906
1930
  this.endedFlag || this.flush(!0);
1907
1931
  };
@@ -1912,9 +1936,16 @@ var Ht = class {
1912
1936
  constructor(e) {
1913
1937
  this.opts = {
1914
1938
  ...e,
1915
- heartbeatMs: e.heartbeatMs ?? Dt,
1916
- idleMs: e.idleMs ?? Ot
1917
- }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1939
+ heartbeatMs: e.heartbeatMs ?? At,
1940
+ idleMs: e.idleMs ?? jt
1941
+ }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
1942
+ try {
1943
+ let e = new URL(this.url);
1944
+ this.cspKey = e.origin + e.pathname;
1945
+ } catch {
1946
+ this.cspKey = void 0;
1947
+ }
1948
+ this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1918
1949
  }
1919
1950
  start() {
1920
1951
  if (this.endedFlag) return;
@@ -1923,11 +1954,11 @@ var Ht = class {
1923
1954
  sdkVersion: this.opts.sdkVersion,
1924
1955
  ...this.opts.environment
1925
1956
  };
1926
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), jt), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
1957
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Pt), 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 && Ut.add(this.cspKey), document.addEventListener("securitypolicyviolation", Gt), X.add(this), this.noteCspBlocked(), this.onVisibility());
1927
1958
  }
1928
1959
  checkSuspension(e) {
1929
1960
  if (this.endedFlag || !this.opts.idleMs) return !1;
1930
- let t = Math.max(this.opts.idleMs, kt);
1961
+ let t = Math.max(this.opts.idleMs, Mt);
1931
1962
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1932
1963
  }
1933
1964
  syncIdle(e) {
@@ -1941,21 +1972,21 @@ var Ht = class {
1941
1972
  noteStateChange(e, t, n, r) {
1942
1973
  if (this.endedFlag || e === t) return;
1943
1974
  let i = this.now();
1944
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Y, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Y, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1975
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1945
1976
  this.stallIsSeekInduced = this.seekInduced(i);
1946
1977
  let e = !this.isHidden && !this.stallIsSeekInduced;
1947
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
1978
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
1948
1979
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1949
1980
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1950
1981
  let a = {
1951
- fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
1952
- toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
1953
- presentation: Pt[this.presentation]
1982
+ fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
1983
+ toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
1984
+ presentation: Lt[this.presentation]
1954
1985
  }, o = this.causeOf(e, t, i);
1955
1986
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1956
1987
  }
1957
1988
  seekInduced(e) {
1958
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Nt;
1989
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < It;
1959
1990
  }
1960
1991
  causeOf(e, t, n) {
1961
1992
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1992,25 +2023,25 @@ var Ht = class {
1992
2023
  }
1993
2024
  this.muteChanges += 1;
1994
2025
  let r = this.now();
1995
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Y, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2026
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1996
2027
  }
1997
2028
  notePresentation(e) {
1998
2029
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1999
2030
  }
2000
2031
  notePlayIntent() {
2001
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Y), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Y), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Y), this.drmSetupMs > 0 && (this.drmSetupMs = Y));
2032
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = q), this.drmSetupMs > 0 && (this.drmSetupMs = q));
2002
2033
  }
2003
2034
  noteReady() {
2004
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
2035
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
2005
2036
  }
2006
2037
  noteFirstPlaylist() {
2007
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
2038
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
2008
2039
  }
2009
2040
  noteDrmReady() {
2010
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
2041
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
2011
2042
  }
2012
2043
  noteFirstBytes() {
2013
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
2044
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
2014
2045
  }
2015
2046
  noteSeek() {
2016
2047
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2029,7 +2060,7 @@ var Ht = class {
2029
2060
  let r = n ?? "";
2030
2061
  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";
2031
2062
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2032
- if (Lt.has(e)) return "ERROR_STAGE_RESOLVE";
2063
+ if (Bt.has(e)) return "ERROR_STAGE_RESOLVE";
2033
2064
  let i = t ?? "";
2034
2065
  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";
2035
2066
  }
@@ -2045,7 +2076,7 @@ var Ht = class {
2045
2076
  heartbeat() {
2046
2077
  if (this.endedFlag) return;
2047
2078
  let e = this.now();
2048
- if (this.checkSuspension(e)) return;
2079
+ if (this.checkSuspension(e) || this.cspBlocked()) return;
2049
2080
  let t = this.opts.sample(), n = this.playingTotalMs;
2050
2081
  this.playingSinceMs !== null && (n += e - this.playingSinceMs);
2051
2082
  let r = this.hiddenTotalMs;
@@ -2061,7 +2092,7 @@ var Ht = class {
2061
2092
  let l = t.droppedFrames ?? 0;
2062
2093
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2063
2094
  let u = t.renditionSwitches ?? 0;
2064
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = X[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2095
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2065
2096
  let d = this.mutedTotalMs;
2066
2097
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2067
2098
  let f = t.upshifts ?? 0;
@@ -2076,20 +2107,20 @@ var Ht = class {
2076
2107
  if (this.lastRequestCount = g, _ > 0) {
2077
2108
  o.requestCountDelta = _;
2078
2109
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2079
- n.length > 0 && (o.requestTimeP50Ms = It(n, 50), o.requestTimeP95Ms = It(n, 95));
2110
+ n.length > 0 && (o.requestTimeP50Ms = zt(n, 50), o.requestTimeP95Ms = zt(n, 95));
2080
2111
  }
2081
2112
  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();
2082
2113
  }
2083
2114
  maybeEmitMediaInfo(e) {
2084
2115
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2085
2116
  let t = {};
2086
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Ft[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2117
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Rt[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);
2087
2118
  let n = JSON.stringify(t);
2088
2119
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2089
2120
  }
2090
2121
  end(e, t) {
2091
2122
  if (this.endedFlag) return;
2092
- this.endedFlag = !0;
2123
+ this.endedFlag = !0, X.delete(this);
2093
2124
  let n = t ?? this.now();
2094
2125
  this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
2095
2126
  let r = this.safeSample();
@@ -2103,7 +2134,7 @@ var Ht = class {
2103
2134
  let c = r?.positionMs ?? 0;
2104
2135
  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));
2105
2136
  let l = e !== "END_REASON_ENDED";
2106
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Mt && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Mt && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2137
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Ft && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ft && (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);
2107
2138
  let u = r?.decodedFrames ?? this.lastDecoded;
2108
2139
  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");
2109
2140
  }
@@ -2122,14 +2153,24 @@ var Ht = class {
2122
2153
  ...e
2123
2154
  };
2124
2155
  }
2156
+ noteCspBlocked() {
2157
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Wt(new URL(this.url).origin)));
2158
+ }
2159
+ cspBlocked() {
2160
+ return !!this.cspKey && Y.has(this.cspKey);
2161
+ }
2125
2162
  enqueue(e) {
2126
- for (this.pending.push(this.wrap(e)); this.pending.length > At;) {
2163
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Nt;) {
2127
2164
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2128
2165
  this.pending.splice(e >= 0 ? e : 0, 1);
2129
2166
  }
2130
2167
  }
2131
2168
  flush(e = !1) {
2132
2169
  if (this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.pendingStart = null, this.pending.length === 0) return;
2170
+ if (this.cspBlocked()) {
2171
+ this.pending = [];
2172
+ return;
2173
+ }
2133
2174
  let t = JSON.stringify({ beacons: this.pending });
2134
2175
  if (this.pending = [], e) {
2135
2176
  let e = this.opts.sendBeacon ?? (typeof navigator < "u" && navigator.sendBeacon ? navigator.sendBeacon.bind(navigator) : void 0);
@@ -2146,7 +2187,7 @@ var Ht = class {
2146
2187
  };
2147
2188
  //#endregion
2148
2189
  //#region src/core/environment.ts
2149
- function Ut() {
2190
+ function Yt() {
2150
2191
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2151
2192
  let e;
2152
2193
  try {
@@ -2171,14 +2212,14 @@ function Ut() {
2171
2212
  integration: "INTEGRATION_KIND_IFRAME"
2172
2213
  };
2173
2214
  }
2174
- function Wt() {
2215
+ function Xt() {
2175
2216
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2176
2217
  let e = navigator.userAgentData, t = e?.platform ?? "";
2177
2218
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2178
2219
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2179
2220
  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";
2180
2221
  }
2181
- function Gt() {
2222
+ function Zt() {
2182
2223
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2183
2224
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2184
2225
  let t = {
@@ -2197,17 +2238,17 @@ function Gt() {
2197
2238
  }
2198
2239
  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;
2199
2240
  }
2200
- function Kt(e) {
2201
- let t = Ut(), n = {
2202
- deviceClass: Wt(),
2241
+ function Qt(e) {
2242
+ let t = Yt(), n = {
2243
+ deviceClass: Xt(),
2203
2244
  integration: t.integration,
2204
- ...Gt()
2245
+ ...Zt()
2205
2246
  };
2206
2247
  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);
2207
2248
  let r = e.getBoundingClientRect?.();
2208
2249
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2209
2250
  }
2210
- async function qt() {
2251
+ async function $t() {
2211
2252
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2212
2253
  if (!e?.getHighEntropyValues) return {};
2213
2254
  try {
@@ -2219,7 +2260,7 @@ async function qt() {
2219
2260
  }
2220
2261
  //#endregion
2221
2262
  //#region src/core/version.ts
2222
- var Jt = "2.12.0", Yt = {
2263
+ var en = "2.13.1", tn = {
2223
2264
  accent: "#E1B600",
2224
2265
  accentText: "#1B1C23",
2225
2266
  background: "#0e0f13",
@@ -2230,7 +2271,7 @@ var Jt = "2.12.0", Yt = {
2230
2271
  border: "rgba(255, 255, 255, 0.1)",
2231
2272
  radius: "8px",
2232
2273
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2233
- }, Xt = {
2274
+ }, nn = {
2234
2275
  accent: "--havik-accent",
2235
2276
  accentText: "--havik-accent-text",
2236
2277
  background: "--havik-bg",
@@ -2242,25 +2283,25 @@ var Jt = "2.12.0", Yt = {
2242
2283
  radius: "--havik-radius",
2243
2284
  fontFamily: "--havik-font"
2244
2285
  };
2245
- function Zt(e, t) {
2286
+ function rn(e, t) {
2246
2287
  let n = {
2247
- ...Yt,
2288
+ ...tn,
2248
2289
  ...t
2249
2290
  };
2250
- for (let t of Object.keys(Xt)) e.style.setProperty(Xt[t], n[t]);
2291
+ for (let t of Object.keys(nn)) e.style.setProperty(nn[t], n[t]);
2251
2292
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2252
2293
  }
2253
2294
  //#endregion
2254
2295
  //#region src/ui/styles.ts
2255
- var Qt = "havik-player-styles", $t = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
2256
- function en(e = document) {
2257
- if (e.getElementById(Qt)) return;
2296
+ var an = "havik-player-styles", on = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
2297
+ function sn(e = document) {
2298
+ if (e.getElementById(an)) return;
2258
2299
  let t = e.createElement("style");
2259
- t.id = Qt, t.textContent = $t, e.head.appendChild(t);
2300
+ t.id = an, t.textContent = on, e.head.appendChild(t);
2260
2301
  }
2261
2302
  //#endregion
2262
2303
  //#region src/ui/icons.ts
2263
- var tn = {
2304
+ var cn = {
2264
2305
  play: "<path d=\"M8 5v14l11-7z\"/>",
2265
2306
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2266
2307
  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\"/>",
@@ -2274,20 +2315,20 @@ var tn = {
2274
2315
  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\"/>"
2275
2316
  };
2276
2317
  function Z(e) {
2277
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${tn[e]}</svg>`;
2318
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${cn[e]}</svg>`;
2278
2319
  }
2279
2320
  //#endregion
2280
2321
  //#region src/ui/controls.ts
2281
- var nn = 3e3, rn = /* @__PURE__ */ new Set([
2322
+ var ln = 3e3, un = /* @__PURE__ */ new Set([
2282
2323
  "GONE",
2283
2324
  "NOT_FOUND",
2284
2325
  "INVALID_URN",
2285
2326
  "UNAUTHORIZED"
2286
2327
  ]);
2287
- function an(e) {
2288
- return new on(e);
2328
+ function dn(e) {
2329
+ return new fn(e);
2289
2330
  }
2290
- var on = class {
2331
+ var fn = class {
2291
2332
  root;
2292
2333
  video;
2293
2334
  player;
@@ -2329,7 +2370,7 @@ var on = class {
2329
2370
  scrubbing = !1;
2330
2371
  offFns = [];
2331
2372
  constructor(e) {
2332
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? nn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, en(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2373
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ln, 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), 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");
2333
2374
  let t = (e, t, n) => {
2334
2375
  let r = this.doc.createElement(e);
2335
2376
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2420,7 +2461,7 @@ var on = class {
2420
2461
  e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2421
2462
  } else {
2422
2463
  let r = this.doc.createElement("div");
2423
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !rn.has(this.lastError.code)) {
2464
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !un.has(this.lastError.code)) {
2424
2465
  let e = this.doc.createElement("button");
2425
2466
  e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2426
2467
  }
@@ -2511,17 +2552,17 @@ var on = class {
2511
2552
  renderQualityMenu() {
2512
2553
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2513
2554
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2514
- for (let n of e) this.menu.append(this.menuItem(sn(n), t === n.index, () => this.player.setQuality(n.index)));
2555
+ for (let n of e) this.menu.append(this.menuItem(pn(n), t === n.index, () => this.player.setQuality(n.index)));
2515
2556
  }
2516
2557
  renderAudioMenu() {
2517
2558
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2518
2559
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2519
- for (let t of e) this.menu.append(this.menuItem(cn(t), t.default, () => this.player.setAudioTrack(t.id)));
2560
+ for (let t of e) this.menu.append(this.menuItem(mn(t), t.default, () => this.player.setAudioTrack(t.id)));
2520
2561
  }
2521
2562
  renderCcMenu() {
2522
2563
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2523
2564
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2524
- for (let t of e) this.menu.append(this.menuItem(ln(t), !1, () => this.player.setTextTrack(t.id)));
2565
+ for (let t of e) this.menu.append(this.menuItem(hn(t), !1, () => this.player.setTextTrack(t.id)));
2525
2566
  }
2526
2567
  onTracksChanged() {
2527
2568
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2541,11 +2582,11 @@ var on = class {
2541
2582
  }
2542
2583
  async toggleFullscreen() {
2543
2584
  try {
2544
- x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
2585
+ S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
2545
2586
  } catch {}
2546
2587
  }
2547
2588
  syncFullscreen() {
2548
- let e = x(this.video, this.root);
2589
+ let e = S(this.video, this.root);
2549
2590
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2550
2591
  }
2551
2592
  poke() {
@@ -2626,36 +2667,36 @@ function Q(e) {
2626
2667
  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");
2627
2668
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2628
2669
  }
2629
- function sn(e) {
2670
+ function pn(e) {
2630
2671
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2631
2672
  }
2632
- function cn(e) {
2673
+ function mn(e) {
2633
2674
  return e.name || e.lang || `Track ${e.id}`;
2634
2675
  }
2635
- function ln(e) {
2676
+ function hn(e) {
2636
2677
  return e.name || e.lang || `Track ${e.id}`;
2637
2678
  }
2638
2679
  //#endregion
2639
2680
  //#region src/managed/index.ts
2640
- var un = 6e3, dn = 45e3, fn = 2e3, pn = 3, mn = 2e3, hn = 48e4;
2641
- function gn(e) {
2681
+ var gn = 6e3, _n = 45e3, vn = 2e3, yn = 3, bn = 2e3, xn = 48e4;
2682
+ function Sn(e) {
2642
2683
  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)})`);
2643
- if (e.env !== void 0) return H(e.env);
2684
+ if (e.env !== void 0) return B(e.env);
2644
2685
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2645
2686
  return e.baseUrl;
2646
2687
  }
2647
- async function _n(e) {
2688
+ async function Cn(e) {
2648
2689
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2649
- let t = gn(e);
2690
+ let t = Sn(e);
2650
2691
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2651
2692
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2652
- let r = new vn({
2693
+ let r = new wn({
2653
2694
  ...e,
2654
2695
  baseUrl: t
2655
2696
  });
2656
2697
  return await r.start(), r;
2657
2698
  }
2658
- var vn = class {
2699
+ var wn = class {
2659
2700
  opts;
2660
2701
  abort = new AbortController();
2661
2702
  listeners = {};
@@ -2722,7 +2763,7 @@ var vn = class {
2722
2763
  };
2723
2764
  }
2724
2765
  beginArming(e, t, n = !1) {
2725
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
2766
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2726
2767
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2727
2768
  }
2728
2769
  beginArmingByPolling(e) {
@@ -2743,7 +2784,7 @@ var vn = class {
2743
2784
  setTimeout(() => {
2744
2785
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2745
2786
  phase: i ? "unavailable" : "tooEarly",
2746
- retryInMs: dn,
2787
+ retryInMs: _n,
2747
2788
  attempt: 1,
2748
2789
  elapsedMs: 0,
2749
2790
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2782,13 +2823,13 @@ var vn = class {
2782
2823
  !a && !p() && h();
2783
2824
  }, e);
2784
2825
  };
2785
- _(un), this.armingSub = w({
2826
+ _(gn), this.armingSub = T({
2786
2827
  eventsBaseUrl: t,
2787
2828
  matchUrn: this.opts.matchUrn,
2788
2829
  credential: this.opts.credential,
2789
- onAlive: () => _(dn),
2830
+ onAlive: () => _(_n),
2790
2831
  onState: (e) => {
2791
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * fn);
2832
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * vn);
2792
2833
  },
2793
2834
  onError: () => h()
2794
2835
  });
@@ -2811,7 +2852,7 @@ var vn = class {
2811
2852
  let n = await s(this.opts.credential);
2812
2853
  if (this.destroyed || t !== this.loadGen) return;
2813
2854
  this.setState("loading");
2814
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = We(this.opts.video, (e) => {
2855
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
2815
2856
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2816
2857
  });
2817
2858
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2833,23 +2874,26 @@ var vn = class {
2833
2874
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2834
2875
  let i = e.analytics?.sid;
2835
2876
  if (!i) return;
2836
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Vt(this.opts.baseUrl, a, e.analytics?.endpoint);
2877
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = qt(this.opts.baseUrl, a, e.analytics?.endpoint);
2837
2878
  if (!o) {
2838
2879
  s && setTimeout(() => {
2839
2880
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2840
2881
  }, 0);
2841
2882
  return;
2842
2883
  }
2843
- let c = this.opts.video, l = new Ht({
2884
+ let c = this.opts.video, l = new Jt({
2844
2885
  endpoint: o,
2845
2886
  sid: i,
2846
2887
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2847
- sdkVersion: Jt,
2848
- environment: Kt(c),
2888
+ sdkVersion: en,
2889
+ environment: Qt(c),
2849
2890
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2850
2891
  onIdle: () => this.onAnalyticsIdle(t),
2892
+ onBlocked: (e) => setTimeout(() => {
2893
+ this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
2894
+ }, 0),
2851
2895
  sample: () => {
2852
- let e = this.engine?.getStats() ?? U, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2896
+ let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2853
2897
  return {
2854
2898
  ...e,
2855
2899
  bufferedMs: Math.round(t * 1e3),
@@ -2863,7 +2907,7 @@ var vn = class {
2863
2907
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2864
2908
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2865
2909
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
2866
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), qt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2910
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), $t().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2867
2911
  }
2868
2912
  currentPresentation() {
2869
2913
  let e = this.opts.video;
@@ -2878,7 +2922,7 @@ var vn = class {
2878
2922
  video: this.opts.video,
2879
2923
  descriptor: e,
2880
2924
  credential: t,
2881
- deviceId: O(),
2925
+ deviceId: k(),
2882
2926
  userId: this.opts.userId,
2883
2927
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
2884
2928
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -2888,11 +2932,11 @@ var vn = class {
2888
2932
  hlsConfig: i,
2889
2933
  emit: (e) => this.onEngineEvent(e)
2890
2934
  }, o = this.opts.engine ?? "auto";
2891
- if (o === "native") return new J(a);
2892
- if (o === "hls") return new Et(a);
2893
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && K(this.opts.video) && q()) return new J(a);
2894
- if (nt()) return new Et(a);
2895
- if (K(this.opts.video)) return new J(a);
2935
+ if (o === "native") return new K(a);
2936
+ if (o === "hls") return new kt(a);
2937
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
2938
+ if (at()) return new kt(a);
2939
+ if (W(this.opts.video)) return new K(a);
2896
2940
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2897
2941
  }
2898
2942
  onEngineEvent(e) {
@@ -2929,11 +2973,11 @@ var vn = class {
2929
2973
  }
2930
2974
  startLiveState(e) {
2931
2975
  if (this.opts.liveStateEvents === !1) return;
2932
- let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
2976
+ let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2933
2977
  if (!t) return;
2934
2978
  this.closeLiveState();
2935
2979
  let r = 0, i = !1;
2936
- this.liveStateSub = w({
2980
+ this.liveStateSub = T({
2937
2981
  eventsBaseUrl: t,
2938
2982
  matchUrn: this.opts.matchUrn,
2939
2983
  credential: this.opts.credential,
@@ -2944,7 +2988,7 @@ var vn = class {
2944
2988
  r = 0, i = !1;
2945
2989
  },
2946
2990
  onError: () => {
2947
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= pn && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2991
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= yn && (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.`))));
2948
2992
  }
2949
2993
  });
2950
2994
  }
@@ -2966,7 +3010,7 @@ var vn = class {
2966
3010
  scheduleRejoin(e) {
2967
3011
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2968
3012
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2969
- }, Math.random() * fn));
3013
+ }, Math.random() * vn));
2970
3014
  }
2971
3015
  cancelRejoin() {
2972
3016
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2990,7 +3034,7 @@ var vn = class {
2990
3034
  }
2991
3035
  t.controls = !1;
2992
3036
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2993
- r && r.insertBefore(n, t), n.appendChild(t), Zt(n, this.opts.theme), this.container = n, this.controlBar = an({
3037
+ r && r.insertBefore(n, t), n.appendChild(t), rn(n, this.opts.theme), this.container = n, this.controlBar = dn({
2994
3038
  root: n,
2995
3039
  video: t,
2996
3040
  player: this,
@@ -3020,7 +3064,7 @@ var vn = class {
3020
3064
  }
3021
3065
  startStats() {
3022
3066
  this.stopStats();
3023
- let e = Math.max(500, this.opts.statsIntervalMs ?? mn);
3067
+ let e = Math.max(500, this.opts.statsIntervalMs ?? bn);
3024
3068
  this.statsTimer = setInterval(() => {
3025
3069
  if (!this.engine) return;
3026
3070
  let e = this.engine.getStats();
@@ -3032,7 +3076,7 @@ var vn = class {
3032
3076
  }
3033
3077
  scheduleLicenseRefresh() {
3034
3078
  this.stopRefresh();
3035
- let e = this.opts.licenseRefreshMs ?? hn;
3079
+ let e = this.opts.licenseRefreshMs ?? xn;
3036
3080
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3037
3081
  }
3038
3082
  stopRefresh() {
@@ -3077,7 +3121,7 @@ var vn = class {
3077
3121
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3078
3122
  }
3079
3123
  getStats() {
3080
- return this.engine?.getStats() ?? U;
3124
+ return this.engine?.getStats() ?? V;
3081
3125
  }
3082
3126
  getQualityLevels() {
3083
3127
  return this.engine?.getQualityLevels() ?? [];
@@ -3116,10 +3160,10 @@ var vn = class {
3116
3160
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3117
3161
  }
3118
3162
  async enterFullscreen() {
3119
- return !this.destroyed && S(this.opts.video, this.container ?? void 0);
3163
+ return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3120
3164
  }
3121
3165
  async exitFullscreen() {
3122
- await C(this.opts.video, this.container ?? void 0);
3166
+ await w(this.opts.video, this.container ?? void 0);
3123
3167
  }
3124
3168
  retry() {
3125
3169
  return this.reload();
@@ -3187,7 +3231,7 @@ function $(e) {
3187
3231
  }
3188
3232
  //#endregion
3189
3233
  //#region src/embed/host.ts
3190
- function yn(e) {
3234
+ function Tn(e) {
3191
3235
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3192
3236
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3193
3237
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3246,15 +3290,15 @@ function yn(e) {
3246
3290
  }
3247
3291
  //#endregion
3248
3292
  //#region src/embed/page.ts
3249
- var bn = /^[A-Za-z0-9:_.-]{1,128}$/;
3250
- function xn(e) {
3293
+ var En = /^[A-Za-z0-9:_.-]{1,128}$/;
3294
+ function Dn(e) {
3251
3295
  if (typeof e == "boolean") return e;
3252
3296
  if (typeof e == "object" && e) {
3253
3297
  let t = e.endpoint;
3254
3298
  return typeof t == "string" ? { endpoint: t } : {};
3255
3299
  }
3256
3300
  }
3257
- function Sn() {
3301
+ function On() {
3258
3302
  let e = window.HAVIK_EMBED_CONFIG;
3259
3303
  if (e) return {
3260
3304
  baseUrl: e.baseUrl ?? "",
@@ -3264,7 +3308,7 @@ function Sn() {
3264
3308
  autoplay: e.autoplay ?? !0,
3265
3309
  muted: e.muted ?? !0,
3266
3310
  waitForLive: e.waitForLive ?? !0,
3267
- analytics: xn(e.analytics)
3311
+ analytics: Dn(e.analytics)
3268
3312
  };
3269
3313
  let t = new URLSearchParams(location.search);
3270
3314
  return {
@@ -3277,9 +3321,9 @@ function Sn() {
3277
3321
  waitForLive: !0
3278
3322
  };
3279
3323
  }
3280
- async function Cn() {
3281
- let e = Sn();
3282
- Tn();
3324
+ async function kn() {
3325
+ let e = On();
3326
+ jn();
3283
3327
  let t = document.createElement("video");
3284
3328
  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);
3285
3329
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3334,12 +3378,12 @@ async function Cn() {
3334
3378
  code: e.code,
3335
3379
  message: e.message
3336
3380
  })), e.on("autoplayblocked", () => {
3337
- i({ type: "oddin:autoplayblocked" }), wn(t, e);
3381
+ i({ type: "oddin:autoplayblocked" }), An(t, e);
3338
3382
  });
3339
3383
  }, s = async (r) => {
3340
3384
  a?.destroy(), a = null;
3341
3385
  try {
3342
- let n = await _n({
3386
+ let n = await Cn({
3343
3387
  video: t,
3344
3388
  baseUrl: e.baseUrl,
3345
3389
  matchUrn: r,
@@ -3401,7 +3445,7 @@ async function Cn() {
3401
3445
  a?.retry();
3402
3446
  break;
3403
3447
  case "oddin:load":
3404
- typeof e.matchUrn == "string" && bn.test(e.matchUrn) && s(e.matchUrn);
3448
+ typeof e.matchUrn == "string" && En.test(e.matchUrn) && s(e.matchUrn);
3405
3449
  break;
3406
3450
  case "oddin:destroy": c();
3407
3451
  }
@@ -3413,18 +3457,18 @@ async function Cn() {
3413
3457
  protocol: 1
3414
3458
  });
3415
3459
  }
3416
- function wn(e, t) {
3460
+ function An(e, t) {
3417
3461
  if (document.getElementById("havik-tap")) return;
3418
3462
  let n = document.createElement("button");
3419
3463
  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", () => {
3420
3464
  n.remove(), t.play();
3421
3465
  }), document.body.appendChild(n);
3422
3466
  }
3423
- function Tn() {
3467
+ function jn() {
3424
3468
  let e = document.createElement("style");
3425
3469
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3426
3470
  }
3427
3471
  //#endregion
3428
- export { Yt as ODDIN_THEME, n as PlaybackError, Zt as applyTheme, H as baseUrlForEnv, Cn as bootEmbed, Te as clearDeviceId, _n as createPlayer, T as deriveEventsBaseUrl, ze as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, Ve as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, yn as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, Ce as watchStatus };
3472
+ export { tn as ODDIN_THEME, n as PlaybackError, rn as applyTheme, B as baseUrlForEnv, kn as bootEmbed, Te as clearDeviceId, Cn 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, Tn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3429
3473
 
3430
3474
  //# sourceMappingURL=index.js.map