@oddin-gg/havik-player 2.18.0 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -287,35 +287,42 @@ function he(e, t) {
287
287
  }
288
288
  //#endregion
289
289
  //#region src/core/fullscreen.ts
290
- function ge(e) {
290
+ function x(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function _e(e) {
293
+ function ge(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 = ge(x(e));
298
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
299
299
  }
300
- async function S(e, t) {
300
+ function C(e, t) {
301
+ let n = t ?? e, r = x(e);
302
+ if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
303
+ if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
304
+ let i = e;
305
+ return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
306
+ }
307
+ async function w(e, t) {
301
308
  let n = t ?? e;
302
309
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
303
310
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
304
311
  let r = e;
305
312
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
306
313
  }
307
- async function C(e, t) {
314
+ async function T(e, t) {
308
315
  let n = e;
309
316
  if (n.webkitDisplayingFullscreen) {
310
317
  n.webkitExitFullscreen?.();
311
318
  return;
312
319
  }
313
- let r = ge(e), i = _e(r);
320
+ let r = x(e), i = ge(r);
314
321
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
315
322
  }
316
323
  //#endregion
317
324
  //#region src/core/catalog.ts
318
- async function ve(e) {
325
+ async function _e(e) {
319
326
  let t = new URLSearchParams();
320
327
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
321
328
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -333,12 +340,12 @@ async function ve(e) {
333
340
  };
334
341
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
335
342
  return {
336
- tournaments: ye(await s.json()),
343
+ tournaments: ve(await s.json()),
337
344
  etag: s.headers.get("etag") ?? void 0,
338
345
  notModified: !1
339
346
  };
340
347
  }
341
- function ye(e) {
348
+ function ve(e) {
342
349
  return (e.tournaments ?? []).map((e) => {
343
350
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
344
351
  return {
@@ -360,7 +367,7 @@ function ye(e) {
360
367
  };
361
368
  });
362
369
  }
363
- async function be(e) {
370
+ async function ye(e) {
364
371
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
365
372
  e.etag && i.set("If-None-Match", e.etag);
366
373
  let a = await p(t, {
@@ -380,13 +387,13 @@ async function be(e) {
380
387
  };
381
388
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
382
389
  return {
383
- tournament: xe(await a.json()),
390
+ tournament: be(await a.json()),
384
391
  etag: a.headers.get("etag") ?? void 0,
385
392
  notModified: !1,
386
393
  notFound: !1
387
394
  };
388
395
  }
389
- function xe(e) {
396
+ function be(e) {
390
397
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
391
398
  return {
392
399
  urn: t,
@@ -406,17 +413,17 @@ function xe(e) {
406
413
  }))
407
414
  };
408
415
  }
409
- function Se(e) {
416
+ function xe(e) {
410
417
  return e.tournaments.flatMap((e) => e.matches);
411
418
  }
412
419
  //#endregion
413
420
  //#region src/core/poll.ts
414
- var Ce = /* @__PURE__ */ new Set([
421
+ var Se = /* @__PURE__ */ new Set([
415
422
  "NOT_FOUND",
416
423
  "GONE",
417
424
  "INVALID_URN"
418
425
  ]);
419
- function we(e) {
426
+ function Ce(e) {
420
427
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
421
428
  u || (a = setTimeout(m, t));
422
429
  }, m = async () => {
@@ -449,7 +456,7 @@ function we(e) {
449
456
  } catch (t) {
450
457
  if (!i.signal.aborted) {
451
458
  let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
- Ce.has(r.code) && (u = !0), e.onError?.(r);
459
+ Se.has(r.code) && (u = !0), e.onError?.(r);
453
460
  }
454
461
  } finally {
455
462
  f();
@@ -461,9 +468,9 @@ function we(e) {
461
468
  }
462
469
  //#endregion
463
470
  //#region src/core/events.ts
464
- var Te = 45e3;
465
- function w(e) {
466
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
471
+ var we = 45e3;
472
+ function E(e) {
473
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
467
474
  if (a.signal.aborted) return t();
468
475
  let n = setTimeout(t, e);
469
476
  a.signal.addEventListener("abort", () => {
@@ -545,7 +552,7 @@ function w(e) {
545
552
  o || (o = !0, a.abort());
546
553
  } };
547
554
  }
548
- function T(e) {
555
+ function D(e) {
549
556
  try {
550
557
  let t = new URL(e);
551
558
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -555,27 +562,27 @@ function T(e) {
555
562
  }
556
563
  //#endregion
557
564
  //#region src/core/drm/deviceId.ts
558
- var E = "havik.player.deviceId", D;
559
- function O() {
560
- if (D) return D;
565
+ var O = "havik.player.deviceId", k;
566
+ function A() {
567
+ if (k) return k;
561
568
  try {
562
- let e = globalThis.localStorage?.getItem(E);
563
- if (e) return D = e, e;
569
+ let e = globalThis.localStorage?.getItem(O);
570
+ if (e) return k = e, e;
564
571
  } catch {}
565
- let e = De();
566
- D = e;
572
+ let e = Ee();
573
+ k = e;
567
574
  try {
568
- globalThis.localStorage?.setItem(E, e);
575
+ globalThis.localStorage?.setItem(O, e);
569
576
  } catch {}
570
577
  return e;
571
578
  }
572
- function Ee() {
573
- D = void 0;
579
+ function Te() {
580
+ k = void 0;
574
581
  try {
575
- globalThis.localStorage?.removeItem(E);
582
+ globalThis.localStorage?.removeItem(O);
576
583
  } catch {}
577
584
  }
578
- function De() {
585
+ function Ee() {
579
586
  let e = globalThis.crypto;
580
587
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
581
588
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -587,32 +594,32 @@ function De() {
587
594
  }
588
595
  //#endregion
589
596
  //#region src/core/drm/headers.ts
590
- function Oe(e, t, n = {}) {
597
+ function De(e, t, n = {}) {
591
598
  let r = {
592
599
  "x-api-key": t.apiKey,
593
600
  "X-Match-Urn": e.matchUrn,
594
- "X-Device-Id": n.deviceId ?? O(),
601
+ "X-Device-Id": n.deviceId ?? A(),
595
602
  "Content-Type": "application/octet-stream"
596
603
  };
597
604
  return n.userId && (r["X-User-Id"] = n.userId), r;
598
605
  }
599
606
  //#endregion
600
607
  //#region src/core/bandwidthMemory.ts
601
- var k = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
602
- function Me() {
608
+ var j = "havik.player.bandwidth", Oe = .8, ke = 2e7, Ae = 3e5;
609
+ function M() {
603
610
  return globalThis.navigator?.connection;
604
611
  }
605
- function Ne() {
606
- let e = Me()?.type;
612
+ function je() {
613
+ let e = M()?.type;
607
614
  return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
608
615
  }
609
- function Pe() {
610
- let e = Me()?.downlink;
616
+ function Me() {
617
+ let e = M()?.downlink;
611
618
  return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
612
619
  }
613
- function Fe() {
620
+ function Ne() {
614
621
  try {
615
- let e = globalThis.localStorage?.getItem(k);
622
+ let e = globalThis.localStorage?.getItem(j);
616
623
  if (!e) return {};
617
624
  let t = JSON.parse(e);
618
625
  return t && typeof t == "object" && !Array.isArray(t) ? t : {};
@@ -620,36 +627,36 @@ function Fe() {
620
627
  return {};
621
628
  }
622
629
  }
623
- function Ie(e = Date.now()) {
624
- let t = Fe()[Ne()];
630
+ function Pe(e = Date.now()) {
631
+ let t = Ne()[je()];
625
632
  if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
626
633
  let n = e - t.at;
627
634
  if (n < 0 || n > 2592e5) return;
628
- let r = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
629
- return Math.round(Math.min(Ae, Math.max(je, i * ke)));
635
+ let r = Me(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
636
+ return Math.round(Math.min(ke, Math.max(Ae, i * Oe)));
630
637
  }
631
- function Le(e, t = Date.now()) {
638
+ function Fe(e, t = Date.now()) {
632
639
  if (!Number.isFinite(e) || e <= 0) return;
633
- let n = Fe();
634
- n[Ne()] = {
640
+ let n = Ne();
641
+ n[je()] = {
635
642
  bps: Math.round(e),
636
643
  at: t
637
644
  };
638
645
  try {
639
- globalThis.localStorage?.setItem(k, JSON.stringify(n));
646
+ globalThis.localStorage?.setItem(j, JSON.stringify(n));
640
647
  } catch {}
641
648
  }
642
- function Re() {
649
+ function Ie() {
643
650
  try {
644
- globalThis.localStorage?.removeItem(k);
651
+ globalThis.localStorage?.removeItem(j);
645
652
  } catch {}
646
653
  }
647
654
  //#endregion
648
655
  //#region src/core/drm/cdm.ts
649
- var ze = /* @__PURE__ */ new WeakMap();
650
- function Be(e, t) {
651
- let n = ze.get(e);
652
- n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
656
+ var Le = /* @__PURE__ */ new WeakMap();
657
+ function Re(e, t) {
658
+ let n = Le.get(e);
659
+ n || (n = /* @__PURE__ */ new Map(), Le.set(e, n));
653
660
  let r = n.get(t.keySystem);
654
661
  if (r) return r;
655
662
  let i = t.createMediaKeys().catch((e) => {
@@ -657,22 +664,22 @@ function Be(e, t) {
657
664
  });
658
665
  return n.set(t.keySystem, i), i;
659
666
  }
660
- function A() {
667
+ function N() {
661
668
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
662
669
  }
663
- var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
664
- function Ve(e) {
670
+ var P = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
671
+ function ze(e) {
665
672
  return e.startsWith("com.widevine");
666
673
  }
667
- function M(e, t) {
668
- if (!Ve(e)) return t;
674
+ function F(e, t) {
675
+ if (!ze(e)) return t;
669
676
  let n = (e, t) => {
670
677
  let n = e.videoCapabilities;
671
678
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
672
- let n = j.indexOf(e.robustness);
673
- return n === -1 || j.indexOf(t) > n;
679
+ let n = P.indexOf(e.robustness);
680
+ return n === -1 || P.indexOf(t) > n;
674
681
  });
675
- }, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
682
+ }, r = P.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
676
683
  ...t,
677
684
  videoCapabilities: t.videoCapabilities?.map((t) => ({
678
685
  ...t,
@@ -681,53 +688,53 @@ function M(e, t) {
681
688
  })));
682
689
  return [...t, ...r];
683
690
  }
684
- function He(e) {
685
- return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
691
+ function Be(e) {
692
+ return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, F(t, n)).then((t) => ({
686
693
  keySystem: t.keySystem,
687
694
  getConfiguration: () => t.getConfiguration(),
688
- createMediaKeys: () => Be(e, t)
695
+ createMediaKeys: () => Re(e, t)
689
696
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
690
697
  }
691
- var N = {
698
+ var I = {
692
699
  video: "SW_SECURE_DECODE",
693
700
  audio: "SW_SECURE_CRYPTO",
694
701
  scheme: "cbcs"
695
702
  };
696
- function Ue(e) {
697
- if (!A()) return;
703
+ function Ve(e) {
704
+ if (!N()) return;
698
705
  let t = (e, t) => ({
699
706
  contentType: e,
700
707
  robustness: t,
701
- encryptionScheme: N.scheme
708
+ encryptionScheme: I.scheme
702
709
  });
703
- He(e)("com.widevine.alpha", [{
710
+ Be(e)("com.widevine.alpha", [{
704
711
  initDataTypes: ["cenc"],
705
712
  distinctiveIdentifier: "optional",
706
713
  persistentState: "optional",
707
714
  sessionTypes: ["temporary"],
708
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", N.audio)],
709
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", N.video)]
715
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
716
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
710
717
  }]).then((e) => e.createMediaKeys()).catch(() => {});
711
718
  }
712
- function P(e) {
713
- let t = F(e);
719
+ function L(e) {
720
+ let t = R(e);
714
721
  if (/^avc[13]/.test(t)) return "avc";
715
722
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
716
723
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
717
724
  if (t.startsWith("av01")) return "av1";
718
725
  if (/^vp0?9/.test(t)) return "vp9";
719
726
  }
720
- function F(e) {
727
+ function R(e) {
721
728
  return (e ?? "").trim().toLowerCase();
722
729
  }
723
- var We = {
730
+ var He = {
724
731
  hevc: "hvc1.1.6.L93.90",
725
732
  dv: "dvh1.05.06",
726
733
  av1: "av01.0.05M.08",
727
734
  vp9: "vp09.00.10.08"
728
- }, Ge = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
729
- function Ke(e) {
730
- let t = F(e), n = Ge.get(t);
735
+ }, Ue = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
736
+ function We(e) {
737
+ let t = R(e), n = Ue.get(t);
731
738
  if (n) return n;
732
739
  let r = {
733
740
  initDataTypes: ["cenc"],
@@ -736,32 +743,32 @@ function Ke(e) {
736
743
  sessionTypes: ["temporary"],
737
744
  videoCapabilities: [{
738
745
  contentType: `video/mp4; codecs="${e.trim()}"`,
739
- robustness: N.video,
740
- encryptionScheme: N.scheme
746
+ robustness: I.video,
747
+ encryptionScheme: I.scheme
741
748
  }]
742
749
  }, i = (async () => {
743
750
  try {
744
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
751
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", F("com.widevine.alpha", [r])), !0;
745
752
  } catch {
746
753
  return !1;
747
754
  }
748
- })().then((e) => (I.set(t, e), e));
749
- return Ge.set(t, i), i;
755
+ })().then((e) => (z.set(t, e), e));
756
+ return Ue.set(t, i), i;
750
757
  }
751
- function qe() {
752
- if (A()) for (let e of Object.values(We)) Ke(e);
758
+ function Ge() {
759
+ if (N()) for (let e of Object.values(He)) We(e);
753
760
  }
754
- function Je(e) {
755
- let t = P(e);
756
- if (t) return t === "avc" ? !0 : I.get(F(e)) ?? I.get(F(We[t]));
761
+ function Ke(e) {
762
+ let t = L(e);
763
+ if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(He[t]));
757
764
  }
758
765
  //#endregion
759
766
  //#region src/core/drm/support.ts
760
- var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
767
+ var qe = 5e3, Je = "video/mp4; codecs=\"avc1.42E01E\"", Ye = "audio/mp4; codecs=\"mp4a.40.2\"", Xe = {
761
768
  widevine: ["com.widevine.alpha"],
762
769
  fairplay: ["com.apple.fps"]
763
770
  };
764
- function $e(e) {
771
+ function Ze(e) {
765
772
  return e === "fairplay" ? [{
766
773
  initDataTypes: [
767
774
  "sinf",
@@ -769,30 +776,30 @@ function $e(e) {
769
776
  "cenc"
770
777
  ],
771
778
  videoCapabilities: [{
772
- contentType: Xe,
779
+ contentType: Je,
773
780
  robustness: "",
774
781
  encryptionScheme: "cbcs"
775
782
  }],
776
783
  audioCapabilities: [{
777
- contentType: Ze,
784
+ contentType: Ye,
778
785
  robustness: "",
779
786
  encryptionScheme: "cbcs"
780
787
  }]
781
- }] : M("com.widevine.alpha", [{
788
+ }] : F("com.widevine.alpha", [{
782
789
  initDataTypes: ["cenc"],
783
790
  videoCapabilities: [{
784
- contentType: Xe,
785
- robustness: N.video,
786
- encryptionScheme: N.scheme
791
+ contentType: Je,
792
+ robustness: I.video,
793
+ encryptionScheme: I.scheme
787
794
  }],
788
795
  audioCapabilities: [{
789
- contentType: Ze,
790
- robustness: N.audio,
791
- encryptionScheme: N.scheme
796
+ contentType: Ye,
797
+ robustness: I.audio,
798
+ encryptionScheme: I.scheme
792
799
  }]
793
800
  }]);
794
801
  }
795
- function et(e, t) {
802
+ function Qe(e, t) {
796
803
  return new Promise((n, r) => {
797
804
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
798
805
  e.then((e) => {
@@ -802,8 +809,8 @@ function et(e, t) {
802
809
  });
803
810
  });
804
811
  }
805
- async function tt(e = {}) {
806
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
812
+ async function $e(e = {}) {
813
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? qe, r = {};
807
814
  if (typeof window < "u" && window.isSecureContext === !1) return {
808
815
  verdict: "insecure-context",
809
816
  detail: r
@@ -815,7 +822,7 @@ async function tt(e = {}) {
815
822
  };
816
823
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
817
824
  for (let e of t) {
818
- let t = Qe[e];
825
+ let t = Xe[e];
819
826
  if (!t) {
820
827
  r[e] = "unknown system";
821
828
  continue;
@@ -826,7 +833,7 @@ async function tt(e = {}) {
826
833
  break;
827
834
  }
828
835
  try {
829
- return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
836
+ return await Qe((await Qe(i(n, Ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
830
837
  verdict: "supported",
831
838
  system: e,
832
839
  detail: r
@@ -850,37 +857,37 @@ async function tt(e = {}) {
850
857
  }
851
858
  //#endregion
852
859
  //#region src/core/manifest.ts
853
- var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
854
- function rt(e) {
855
- return nt.test(e);
860
+ var et = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
861
+ function tt(e) {
862
+ return et.test(e);
856
863
  }
857
864
  //#endregion
858
865
  //#region src/core/env.ts
859
- var it = {
866
+ var nt = {
860
867
  integration: "https://feed-dev.oddin-video.gg",
861
868
  production: "https://feed.oddin-video.gg"
862
869
  };
863
- function L(e) {
864
- let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
870
+ function rt(e) {
871
+ let t = Object.prototype.hasOwnProperty.call(nt, e) ? nt[e] : void 0;
865
872
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
866
873
  return t;
867
874
  }
868
875
  //#endregion
869
876
  //#region src/core/stats.ts
870
- var R = { droppedFrames: 0 };
871
- function z(e) {
877
+ var it = { droppedFrames: 0 };
878
+ function at(e) {
872
879
  try {
873
880
  return new URL(e).host;
874
881
  } catch {
875
882
  return "";
876
883
  }
877
884
  }
878
- var at = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
879
- function ot(e) {
885
+ var ot = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
886
+ function st(e) {
880
887
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
881
888
  let t = "", n = -1, r = performance.getEntriesByType("resource");
882
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || at.test(i.name)) && i.startTime >= n) {
883
- let e = z(i.name);
889
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ot.test(i.name)) && i.startTime >= n) {
890
+ let e = at(i.name);
884
891
  e && (t = e, n = i.startTime);
885
892
  }
886
893
  return t;
@@ -892,7 +899,7 @@ function B(e) {
892
899
  totalFrames: t?.totalVideoFrames ?? 0
893
900
  };
894
901
  }
895
- var st = class {
902
+ var ct = class {
896
903
  video;
897
904
  baseFrames = 0;
898
905
  baseDropped = 0;
@@ -915,7 +922,7 @@ var st = class {
915
922
  };
916
923
  }
917
924
  };
918
- function ct(e, t) {
925
+ function lt(e, t) {
919
926
  let n = [
920
927
  ["playing", () => t("playing")],
921
928
  ["waiting", () => t("buffering")],
@@ -932,8 +939,8 @@ function ct(e, t) {
932
939
  }
933
940
  //#endregion
934
941
  //#region src/core/engine/native.ts
935
- var lt = 2e3, ut = 3, V = 500, dt = 6e3, ft = .25, pt = 250, mt = .05, ht = 4, gt = 12e3, _t = .25, vt = 1e3;
936
- function yt(e) {
942
+ var ut = 2e3, dt = 3, V = 500, ft = 6e3, pt = .25, mt = 250, ht = .05, gt = 4, _t = 12e3, vt = .25, yt = 1e3;
943
+ function bt(e) {
937
944
  try {
938
945
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
939
946
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -949,7 +956,7 @@ function U() {
949
956
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
950
957
  return e || t;
951
958
  }
952
- function bt() {
959
+ function xt() {
953
960
  if (typeof navigator > "u" || !U()) return !1;
954
961
  let e = navigator.userAgent ?? "";
955
962
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -984,7 +991,7 @@ var W = class {
984
991
  frameCounter;
985
992
  detachFrames = null;
986
993
  constructor(e) {
987
- this.deps = e, this.frameCounter = new st(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
994
+ this.deps = e, this.frameCounter = new ct(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
988
995
  }
989
996
  async load() {
990
997
  this.detachFrames ??= this.frameCounter.attach();
@@ -1005,7 +1012,7 @@ var W = class {
1005
1012
  type: "error",
1006
1013
  error: new n("INTERNAL", 0, "native HLS playback error"),
1007
1014
  fatal: !0
1008
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = St(t.manifestUrl, t.analytics?.sid), e.load();
1015
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ct(t.manifestUrl, t.analytics?.sid), e.load();
1009
1016
  }
1010
1017
  startLoad() {
1011
1018
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -1027,7 +1034,7 @@ var W = class {
1027
1034
  });
1028
1035
  this.onEncrypted = (n) => {
1029
1036
  let i = n;
1030
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = yt(i.initData), (async () => {
1037
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = bt(i.initData), (async () => {
1031
1038
  try {
1032
1039
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
1033
1040
  initDataTypes: [i.initDataType],
@@ -1126,10 +1133,10 @@ var W = class {
1126
1133
  droppedFrames: t.dropped,
1127
1134
  decodedFrames: t.totalFrames
1128
1135
  };
1129
- if (this.cdnHost ||= ot(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1136
+ if (this.cdnHost ||= st(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1130
1137
  n.isLive = !0;
1131
1138
  let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1132
- Number.isFinite(r) && (n.atLiveEdge = r <= ht, !e.paused && r >= 0 && (n.latencySeconds = r));
1139
+ Number.isFinite(r) && (n.atLiveEdge = r <= gt, !e.paused && r >= 0 && (n.latencySeconds = r));
1133
1140
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1134
1141
  return n;
1135
1142
  }
@@ -1147,7 +1154,7 @@ var W = class {
1147
1154
  return;
1148
1155
  }
1149
1156
  let t = this.hiddenSince;
1150
- this.hiddenSince = null, t != null && e - t >= lt && this.armRefocus();
1157
+ this.hiddenSince = null, t != null && e - t >= ut && this.armRefocus();
1151
1158
  }, this.onPageShow = (e) => {
1152
1159
  e.persisted && this.armRefocus();
1153
1160
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
@@ -1157,7 +1164,7 @@ var W = class {
1157
1164
  let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
1158
1165
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1159
1166
  r += V;
1160
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + ft), s = Math.max(r, t() - n) >= dt;
1167
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + pt), s = Math.max(r, t() - n) >= ft;
1161
1168
  if (o || s && a != null) {
1162
1169
  this.snapToLive();
1163
1170
  return;
@@ -1177,9 +1184,9 @@ var W = class {
1177
1184
  }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1178
1185
  if (e.duration !== Infinity) return;
1179
1186
  this.checkEndStale();
1180
- let t = xt(e, e.currentTime);
1181
- t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= mt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
1182
- }, pt);
1187
+ let t = St(e, e.currentTime);
1188
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= ht) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
1189
+ }, mt);
1183
1190
  }
1184
1191
  checkEndStale() {
1185
1192
  if (this.endedEmitted) return;
@@ -1187,14 +1194,14 @@ var W = class {
1187
1194
  this.lastTickAt = e;
1188
1195
  let n = this.liveEnd();
1189
1196
  if (n == null) return;
1190
- let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= _t;
1197
+ let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= vt;
1191
1198
  this.lastSeekableEnd = n;
1192
1199
  let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
1193
- if (r || t > vt || a || i.paused) {
1200
+ if (r || t > yt || a || i.paused) {
1194
1201
  this.edgeStampedAt = e;
1195
1202
  return;
1196
1203
  }
1197
- e - (this.edgeStampedAt ?? e) > gt && (this.endedEmitted = !0, this.deps.emit({
1204
+ e - (this.edgeStampedAt ?? e) > _t && (this.endedEmitted = !0, this.deps.emit({
1198
1205
  type: "ended",
1199
1206
  reason: "stalled"
1200
1207
  }));
@@ -1208,7 +1215,7 @@ var W = class {
1208
1215
  liveEdgeEstimate() {
1209
1216
  let e = this.deps.video;
1210
1217
  if (e.duration !== Infinity) return null;
1211
- let t = this.liveEnd(), n = xt(e, e.currentTime) ?? this.lastBufferedEnd;
1218
+ let t = this.liveEnd(), n = St(e, e.currentTime) ?? this.lastBufferedEnd;
1212
1219
  if (n != null) {
1213
1220
  let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
1214
1221
  (t == null || r > t) && (t = r);
@@ -1224,7 +1231,7 @@ var W = class {
1224
1231
  snapToLive() {
1225
1232
  let e = this.deps.video, t = this.liveEnd();
1226
1233
  if (t == null) return;
1227
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ut, r);
1234
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - dt, r);
1228
1235
  try {
1229
1236
  e.currentTime = i;
1230
1237
  } catch {}
@@ -1245,7 +1252,7 @@ var W = class {
1245
1252
  function G() {
1246
1253
  return typeof performance < "u" ? performance.now() : Date.now();
1247
1254
  }
1248
- function xt(e, t) {
1255
+ function St(e, t) {
1249
1256
  let n = e.buffered;
1250
1257
  if (!n || !Number.isFinite(t)) return null;
1251
1258
  for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
@@ -1254,7 +1261,7 @@ function xt(e, t) {
1254
1261
  }
1255
1262
  return null;
1256
1263
  }
1257
- function St(e, t) {
1264
+ function Ct(e, t) {
1258
1265
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1259
1266
  }
1260
1267
  //#endregion
@@ -1271,8 +1278,8 @@ function K(e, t = Date.now()) {
1271
1278
  }
1272
1279
  //#endregion
1273
1280
  //#region src/core/engine/prefetch.ts
1274
- var Ct = 15e3, wt = 5e3, Tt = 6;
1275
- function Et(e) {
1281
+ var wt = 15e3, Tt = 5e3, Et = 6;
1282
+ function Dt(e) {
1276
1283
  try {
1277
1284
  let t = new URL(e);
1278
1285
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1280,7 +1287,7 @@ function Et(e) {
1280
1287
  return e;
1281
1288
  }
1282
1289
  }
1283
- var Dt = class {
1290
+ var Ot = class {
1284
1291
  cmcd;
1285
1292
  entries = /* @__PURE__ */ new Map();
1286
1293
  keyed = /* @__PURE__ */ new Set();
@@ -1303,10 +1310,10 @@ var Dt = class {
1303
1310
  }
1304
1311
  prefetch(e, t, n) {
1305
1312
  if (!this.isActive(t)) return;
1306
- let r = Et(e);
1313
+ let r = Dt(e);
1307
1314
  if (this.entries.has(r)) return;
1308
1315
  let i = this.perTrack.get(t) ?? 0;
1309
- if (i >= Tt) return;
1316
+ if (i >= Et) return;
1310
1317
  this.perTrack.set(t, i + 1);
1311
1318
  let a = new AbortController(), o = {
1312
1319
  started: performance.now(),
@@ -1320,10 +1327,10 @@ var Dt = class {
1320
1327
  signal: a.signal
1321
1328
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1322
1329
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1323
- }, Ct);
1330
+ }, wt);
1324
1331
  }
1325
1332
  take(e) {
1326
- let t = Et(e), n = this.entries.get(t);
1333
+ let t = Dt(e), n = this.entries.get(t);
1327
1334
  return n && this.entries.delete(t), n;
1328
1335
  }
1329
1336
  destroy() {
@@ -1343,13 +1350,13 @@ var Dt = class {
1343
1350
  }
1344
1351
  }
1345
1352
  };
1346
- function Ot(t) {
1353
+ function kt(t) {
1347
1354
  let n = e.DefaultConfig?.loader;
1348
1355
  if (typeof n != "function") return;
1349
1356
  class r extends n {
1350
1357
  served = !1;
1351
1358
  cancelled = !1;
1352
- stats = kt();
1359
+ stats = At();
1353
1360
  load(e, n, r) {
1354
1361
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1355
1362
  if (!i) {
@@ -1357,7 +1364,7 @@ function Ot(t) {
1357
1364
  return;
1358
1365
  }
1359
1366
  this.served = !0;
1360
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || wt, s = setTimeout(() => {
1367
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Tt, s = setTimeout(() => {
1361
1368
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1362
1369
  }, o);
1363
1370
  i.bytes.then((o) => {
@@ -1384,7 +1391,7 @@ function Ot(t) {
1384
1391
  }
1385
1392
  return r;
1386
1393
  }
1387
- function kt() {
1394
+ function At() {
1388
1395
  return {
1389
1396
  aborted: !1,
1390
1397
  loaded: 0,
@@ -1408,10 +1415,10 @@ function kt() {
1408
1415
  }
1409
1416
  };
1410
1417
  }
1411
- function At(e) {
1418
+ function jt(e) {
1412
1419
  return e === "audio" ? "audio" : "main";
1413
1420
  }
1414
- function jt(e, t) {
1421
+ function Mt(e, t) {
1415
1422
  let n = [];
1416
1423
  t.initSegment?.url && !t.initSegment.data && n.push({
1417
1424
  url: t.initSegment.url,
@@ -1430,24 +1437,24 @@ function jt(e, t) {
1430
1437
  }
1431
1438
  //#endregion
1432
1439
  //#region src/core/engine/hls.ts
1433
- function Mt() {
1440
+ function Nt() {
1434
1441
  return e.isSupported();
1435
1442
  }
1436
- var Nt = 1e6, Pt = 20, Ft = 1e4, It = 3, Lt = 5, Rt = 3, zt = 1e4, Bt = 3e4, Vt = 12e3, Ht = 3e3, Ut = .02, Wt = 6e3, Gt = .5, Kt = 3, qt = .5, Jt = 1.1, Yt = .25, Xt = 5e3, Zt = 4e3, Qt = 2, $t = 5, en = 2, tn = 2, nn = 4, rn = 4, an = 2e3, on = 3e4, sn = .2, cn = 30, ln = 2, un = 2, dn = 9, fn = .5, pn = 64;
1437
- function mn(e) {
1443
+ var Pt = 1e6, Ft = 20, It = 1e4, Lt = 3, Rt = 5, zt = 3, Bt = 1e4, Vt = 3e4, Ht = 12e3, Ut = 3e3, Wt = .02, Gt = 6e3, Kt = .5, qt = 3, Jt = .5, Yt = 1.1, Xt = .25, Zt = 5e3, Qt = 4e3, $t = 2, en = 5, tn = 2, nn = 2, rn = 4, an = 4, on = 2e3, sn = 3e4, cn = .2, ln = 30, un = 2, dn = 2, fn = 9, pn = .5, mn = 64;
1444
+ function hn(e) {
1438
1445
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1439
1446
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1440
1447
  return;
1441
1448
  }
1442
- e.liveSyncDuration ??= un;
1443
- let t = Math.max(12, e.liveSyncDuration + dn);
1444
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), hn(e, e.liveSyncDuration);
1449
+ e.liveSyncDuration ??= dn;
1450
+ let t = Math.max(12, e.liveSyncDuration + fn);
1451
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), gn(e, e.liveSyncDuration);
1445
1452
  }
1446
- function hn(e, t) {
1453
+ function gn(e, t) {
1447
1454
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1448
1455
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1449
1456
  }
1450
- var gn = class {
1457
+ var _n = class {
1451
1458
  name = "hls";
1452
1459
  hls = null;
1453
1460
  deps;
@@ -1531,7 +1538,7 @@ var gn = class {
1531
1538
  frameCounter;
1532
1539
  detachFrames = null;
1533
1540
  constructor(e) {
1534
- this.deps = e, this.frameCounter = new st(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1541
+ this.deps = e, this.frameCounter = new ct(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1535
1542
  }
1536
1543
  async load() {
1537
1544
  this.detachFrames ??= this.frameCounter.attach();
@@ -1544,7 +1551,7 @@ var gn = class {
1544
1551
  });
1545
1552
  return;
1546
1553
  }
1547
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1554
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ve(r), Ge()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1548
1555
  let e = this.hls;
1549
1556
  if (document.visibilityState !== "visible" || !e) return;
1550
1557
  let t = e.liveSyncPosition;
@@ -1567,7 +1574,7 @@ var gn = class {
1567
1574
  }
1568
1575
  this.loadSuspended = !0;
1569
1576
  }
1570
- }, Xt));
1577
+ }, Zt));
1571
1578
  }
1572
1579
  resumeLoading() {
1573
1580
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1599,7 +1606,7 @@ var gn = class {
1599
1606
  let t = e.liveSyncPosition;
1600
1607
  if (typeof t != "number" || !Number.isFinite(t)) return;
1601
1608
  let { video: n } = this.deps;
1602
- n.currentTime <= t + fn || (n.currentTime = t);
1609
+ n.currentTime <= t + pn || (n.currentTime = t);
1603
1610
  }
1604
1611
  reanchorPartTimeline(e, t) {
1605
1612
  let { frag: n, part: r } = t;
@@ -1611,7 +1618,7 @@ var gn = class {
1611
1618
  let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1612
1619
  if (!s) return;
1613
1620
  let c = a.startPTS - s.start;
1614
- if (!(!Number.isFinite(c) || Math.abs(c) < Ut)) {
1621
+ if (!(!Number.isFinite(c) || Math.abs(c) < Wt)) {
1615
1622
  for (let e of i.fragments) e && e.setStart(e.start + c);
1616
1623
  i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
1617
1624
  }
@@ -1634,12 +1641,12 @@ var gn = class {
1634
1641
  emeEnabled: !0,
1635
1642
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1636
1643
  drmSystemOptions: {
1637
- videoRobustness: N.video,
1638
- audioRobustness: N.audio,
1639
- videoEncryptionScheme: N.scheme,
1640
- audioEncryptionScheme: N.scheme
1644
+ videoRobustness: I.video,
1645
+ audioRobustness: I.audio,
1646
+ videoEncryptionScheme: I.scheme,
1647
+ audioEncryptionScheme: I.scheme
1641
1648
  },
1642
- ...A() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
1649
+ ...N() ? { requestMediaKeySystemAccessFunc: Be(t) } : {},
1643
1650
  licenseXhrSetup: (e, t) => {
1644
1651
  let o = performance.now(), s = () => {
1645
1652
  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, e.addEventListener("loadend", () => {
@@ -1651,7 +1658,7 @@ var gn = class {
1651
1658
  return;
1652
1659
  }
1653
1660
  let l = this.hls, u, d = new Promise((e) => {
1654
- u = setTimeout(() => e(void 0), zt);
1661
+ u = setTimeout(() => e(void 0), Bt);
1655
1662
  });
1656
1663
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1657
1664
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1667,20 +1674,20 @@ var gn = class {
1667
1674
  ...c
1668
1675
  };
1669
1676
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
1670
- let e = new Dt({
1677
+ let e = new Ot({
1671
1678
  sessionId: n.analytics?.sid,
1672
1679
  contentId: n.matchUrn
1673
- }), t = Ot(e);
1680
+ }), t = kt(e);
1674
1681
  t && (this.prefetch = e, f.fLoader = t);
1675
1682
  }
1676
- mn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1683
+ hn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1677
1684
  let p = new e(f);
1678
1685
  if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
1679
1686
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1680
1687
  }), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
1681
1688
  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(() => {
1682
1689
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1683
- }, Bt)));
1690
+ }, Vt)));
1684
1691
  }), p.on(e.Events.FRAG_LOADING, (e, t) => {
1685
1692
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1686
1693
  }), p.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1688,10 +1695,10 @@ var gn = class {
1688
1695
  let n = t?.frag?.stats, r = n?.loaded;
1689
1696
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1690
1697
  let i = n?.loading;
1691
- 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 > pn && this.requestTimesMs.shift());
1698
+ 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 > mn && this.requestTimesMs.shift());
1692
1699
  let a = t?.frag?.url;
1693
1700
  if (a) {
1694
- let e = z(a);
1701
+ let e = at(a);
1695
1702
  e && (this.cdnHost = e);
1696
1703
  }
1697
1704
  }), p.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1705,15 +1712,15 @@ var gn = class {
1705
1712
  }), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1706
1713
  let t = this.prefetch;
1707
1714
  p.on(e.Events.KEY_LOADING, (e, n) => {
1708
- let r = n?.frag, i = At(r?.type);
1709
- if (r && t.isActive(i)) for (let e of jt(p, r)) t.prefetch(e.url, i, e.kind);
1710
- }), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(At(n?.frag?.type)));
1715
+ let r = n?.frag, i = jt(r?.type);
1716
+ if (r && t.isActive(i)) for (let e of Mt(p, r)) t.prefetch(e.url, i, e.kind);
1717
+ }), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(jt(n?.frag?.type)));
1711
1718
  }
1712
1719
  p.on(e.Events.KEY_LOADED, () => {
1713
1720
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1714
1721
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1715
1722
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1716
- }, Ht), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1723
+ }, Ut), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1717
1724
  this.renditionSwitches += 1;
1718
1725
  let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
1719
1726
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1777,7 +1784,7 @@ var gn = class {
1777
1784
  return;
1778
1785
  }
1779
1786
  this.capTimer && clearTimeout(this.capTimer);
1780
- let t = e > this.sizeCapLevel ? an : on;
1787
+ let t = e > this.sizeCapLevel ? on : sn;
1781
1788
  this.capTimer = setTimeout(() => {
1782
1789
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1783
1790
  }, t);
@@ -1787,9 +1794,9 @@ var gn = class {
1787
1794
  this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
1788
1795
  }
1789
1796
  dropLevelsWidevineCannotPlay(e) {
1790
- this.removeLevelsWhere(e, (e) => Je(e) !== !0);
1791
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && P(e) !== "avc" && !!P(e)));
1792
- for (let n of t) Ke(n).then((t) => {
1797
+ this.removeLevelsWhere(e, (e) => Ke(e) !== !0);
1798
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
1799
+ for (let n of t) We(n).then((t) => {
1793
1800
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1794
1801
  });
1795
1802
  }
@@ -1797,10 +1804,10 @@ var gn = class {
1797
1804
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1798
1805
  if (n.forEach((e, n) => {
1799
1806
  let a = e.videoCodec;
1800
- a && P(a) && t(a) && (r.push(n), i.add(a));
1807
+ a && L(a) && t(a) && (r.push(n), i.add(a));
1801
1808
  }), !r.length) return !1;
1802
1809
  let a = [...i].join(", ");
1803
- if (!n.some((e, t) => r.includes(t) ? !1 : !P(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1810
+ if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Ke(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1804
1811
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1805
1812
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1806
1813
  }
@@ -1906,7 +1913,7 @@ var gn = class {
1906
1913
  return;
1907
1914
  }
1908
1915
  let e = Date.now() - this.lastAdvanceMs;
1909
- !this.chaseSuspended && e > Wt && this.suspendChasing(), e > Vt && this.emitEnded("stalled");
1916
+ !this.chaseSuspended && e > Gt && this.suspendChasing(), e > Ht && this.emitEnded("stalled");
1910
1917
  }
1911
1918
  resetStarvationWindow() {
1912
1919
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1921,7 +1928,7 @@ var gn = class {
1921
1928
  this.resetStarvationWindow();
1922
1929
  return;
1923
1930
  }
1924
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Wt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Zt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1931
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Gt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Qt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1925
1932
  if (this.starvedFrames = c, !a || l) {
1926
1933
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1927
1934
  return;
@@ -1930,12 +1937,12 @@ var gn = class {
1930
1937
  this.resetStarvationWindow();
1931
1938
  return;
1932
1939
  }
1933
- 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 > nn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= en && (this.clearKick(), this.starvationRebuilds < tn)) {
1940
+ 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 > rn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= tn && (this.clearKick(), this.starvationRebuilds < nn)) {
1934
1941
  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");
1935
1942
  return;
1936
1943
  }
1937
- let u = i && this.starvedTicks >= Qt, d = !i && this.deadTicks >= nn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= rn;
1938
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= $t))) {
1944
+ let u = i && this.starvedTicks >= $t, d = !i && this.deadTicks >= rn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= an;
1945
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= en))) {
1939
1946
  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");
1940
1947
  try {
1941
1948
  e.stopLoad(), e.startLoad(-1);
@@ -1950,7 +1957,7 @@ var gn = class {
1950
1957
  let t = e.latency, n = e.targetLatency;
1951
1958
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1952
1959
  let r = t - n;
1953
- !this.catchUpEngaged && r > Gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1960
+ !this.catchUpEngaged && r > Kt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Kt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1954
1961
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1955
1962
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1956
1963
  }
@@ -1972,15 +1979,15 @@ var gn = class {
1972
1979
  return;
1973
1980
  }
1974
1981
  let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1975
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < cn || o < 0) {
1982
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < ln || o < 0) {
1976
1983
  this.fpsBadTicks = 0;
1977
1984
  return;
1978
1985
  }
1979
- if (o <= sn * a) {
1986
+ if (o <= cn * a) {
1980
1987
  this.fpsBadTicks = 0;
1981
1988
  return;
1982
1989
  }
1983
- if (this.fpsBadTicks += 1, this.fpsBadTicks < ln) return;
1990
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < un) return;
1984
1991
  this.fpsBadTicks = 0;
1985
1992
  let s = e.levels, c = s[e.currentLevel];
1986
1993
  if (!c) return;
@@ -1997,20 +2004,20 @@ var gn = class {
1997
2004
  return;
1998
2005
  }
1999
2006
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
2000
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Jt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2007
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Yt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2001
2008
  this.resetChaseWindow();
2002
2009
  return;
2003
2010
  }
2004
- if (this.chaseLatency < 0 || this.chaseLatency - n >= qt) {
2011
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= Jt) {
2005
2012
  this.chaseLatency = n, this.chaseTicks = 0;
2006
2013
  return;
2007
2014
  }
2008
- if (this.chaseTicks += 1, this.chaseTicks < Kt) return;
2015
+ if (this.chaseTicks += 1, this.chaseTicks < qt) return;
2009
2016
  this.resetChaseWindow();
2010
2017
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2011
2018
  if (!(a > 1)) return;
2012
2019
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
2013
- s < o + Yt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
2020
+ s < o + Xt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
2014
2021
  }
2015
2022
  suspendChasing() {
2016
2023
  let e = this.hls;
@@ -2040,14 +2047,14 @@ var gn = class {
2040
2047
  } catch {}
2041
2048
  }
2042
2049
  startEstimate() {
2043
- return this.deps.rememberBandwidth === !1 ? Nt : Ie() ?? Nt;
2050
+ return this.deps.rememberBandwidth === !1 ? Pt : Pe() ?? Pt;
2044
2051
  }
2045
2052
  maybeRememberBandwidth(e) {
2046
- if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Pt) return;
2053
+ if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Ft) return;
2047
2054
  let t = Date.now();
2048
- if (!e && t - this.bwSavedAt < Ft) return;
2055
+ if (!e && t - this.bwSavedAt < It) return;
2049
2056
  let n = this.hls?.bandwidthEstimate;
2050
- typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
2057
+ typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Fe(n));
2051
2058
  }
2052
2059
  destroy() {
2053
2060
  if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
@@ -2065,7 +2072,7 @@ var gn = class {
2065
2072
  scheduleLicenseRetry(t) {
2066
2073
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
2067
2074
  let n = t.response?.code ?? 0;
2068
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Rt) return !1;
2075
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= zt) return !1;
2069
2076
  this.licenseRecoveries += 1;
2070
2077
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
2071
2078
  return this.licenseRetryTimer = setTimeout(() => {
@@ -2097,7 +2104,7 @@ var gn = class {
2097
2104
  return;
2098
2105
  }
2099
2106
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
2100
- if (this.networkRecoveries < Lt) {
2107
+ if (this.networkRecoveries < Rt) {
2101
2108
  this.networkRecoveries += 1;
2102
2109
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
2103
2110
  this.networkRetryTimer = setTimeout(() => {
@@ -2114,7 +2121,7 @@ var gn = class {
2114
2121
  return;
2115
2122
  }
2116
2123
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
2117
- if (this.mediaRecoveries < It) {
2124
+ if (this.mediaRecoveries < Lt) {
2118
2125
  this.mediaRecoveries += 1, n.recoverMediaError();
2119
2126
  return;
2120
2127
  }
@@ -2138,19 +2145,19 @@ var gn = class {
2138
2145
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
2139
2146
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
2140
2147
  }
2141
- }, _n = 15e3, vn = 6e5, yn = 3e5, bn = 100, q = 1, xn = 1e3, Sn = 3e4, Cn = 1e3, wn = {
2148
+ }, vn = 15e3, yn = 6e5, bn = 3e5, xn = 100, q = 1, Sn = 1e3, Cn = 3e4, wn = 1e3, Tn = {
2142
2149
  inline: "PRESENTATION_INLINE",
2143
2150
  fullscreen: "PRESENTATION_FULLSCREEN",
2144
2151
  pip: "PRESENTATION_PIP"
2145
- }, Tn = {
2152
+ }, En = {
2146
2153
  widevine: "KEY_SYSTEM_WIDEVINE",
2147
2154
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2148
2155
  none: "KEY_SYSTEM_NONE"
2149
2156
  };
2150
- function En(e, t) {
2157
+ function Dn(e, t) {
2151
2158
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
2152
2159
  }
2153
- var Dn = /* @__PURE__ */ new Set([
2160
+ var On = /* @__PURE__ */ new Set([
2154
2161
  "INVALID_URN",
2155
2162
  "NOT_FOUND",
2156
2163
  "GONE",
@@ -2170,7 +2177,7 @@ var Dn = /* @__PURE__ */ new Set([
2170
2177
  ended: "PLAYER_STATE_ENDED",
2171
2178
  error: "PLAYER_STATE_ERROR"
2172
2179
  };
2173
- function On(e) {
2180
+ function kn(e) {
2174
2181
  try {
2175
2182
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2176
2183
  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);
@@ -2178,8 +2185,8 @@ function On(e) {
2178
2185
  return;
2179
2186
  }
2180
2187
  }
2181
- var kn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), An = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), jn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2182
- function Mn(e) {
2188
+ var An = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), jn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Mn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2189
+ function Nn(e) {
2183
2190
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2184
2191
  let t;
2185
2192
  try {
@@ -2188,19 +2195,19 @@ function Mn(e) {
2188
2195
  } catch {
2189
2196
  return;
2190
2197
  }
2191
- if (An.has(t) && !Y.has(t)) {
2192
- Y.add(t), g(jn(new URL(t).origin));
2198
+ if (jn.has(t) && !Y.has(t)) {
2199
+ Y.add(t), g(Mn(new URL(t).origin));
2193
2200
  for (let e of X) e.noteCspBlocked();
2194
2201
  }
2195
2202
  }
2196
- function Nn(e, t) {
2203
+ function Pn(e, t) {
2197
2204
  return g(t, e), { disabledReason: t };
2198
2205
  }
2199
- function Pn(e, t, n) {
2200
- if (n) return t && !kn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2206
+ function Fn(e, t, n) {
2207
+ if (n) return t && !An(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2201
2208
  if (t) return { endpoint: t };
2202
- if (t !== void 0) return Nn("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).");
2203
- let r = On(e);
2209
+ if (t !== void 0) return Pn("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).");
2210
+ let r = kn(e);
2204
2211
  if (r) return { endpoint: r };
2205
2212
  let i;
2206
2213
  try {
@@ -2208,9 +2215,9 @@ function Pn(e, t, n) {
2208
2215
  } catch {
2209
2216
  i = e;
2210
2217
  }
2211
- return Nn(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).`);
2218
+ return Pn(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).`);
2212
2219
  }
2213
- var Fn = class {
2220
+ var In = class {
2214
2221
  opts;
2215
2222
  url;
2216
2223
  cspKey;
@@ -2292,8 +2299,8 @@ var Fn = class {
2292
2299
  constructor(e) {
2293
2300
  this.opts = {
2294
2301
  ...e,
2295
- heartbeatMs: e.heartbeatMs ?? _n,
2296
- idleMs: e.idleMs ?? vn
2302
+ heartbeatMs: e.heartbeatMs ?? vn,
2303
+ idleMs: e.idleMs ?? yn
2297
2304
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2298
2305
  try {
2299
2306
  let e = new URL(this.url);
@@ -2310,11 +2317,11 @@ var Fn = class {
2310
2317
  sdkVersion: this.opts.sdkVersion,
2311
2318
  ...this.opts.environment
2312
2319
  };
2313
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), xn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && An.add(this.cspKey), document.addEventListener("securitypolicyviolation", Mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2320
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Sn), 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 && jn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Nn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2314
2321
  }
2315
2322
  checkSuspension(e) {
2316
2323
  if (this.endedFlag || !this.opts.idleMs) return !1;
2317
- let t = Math.max(this.opts.idleMs, yn);
2324
+ let t = Math.max(this.opts.idleMs, bn);
2318
2325
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2319
2326
  }
2320
2327
  syncIdle(e) {
@@ -2337,12 +2344,12 @@ var Fn = class {
2337
2344
  let a = {
2338
2345
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2339
2346
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2340
- presentation: wn[this.presentation]
2347
+ presentation: Tn[this.presentation]
2341
2348
  }, o = this.causeOf(e, t, i);
2342
2349
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2343
2350
  }
2344
2351
  seekInduced(e) {
2345
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Cn;
2352
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < wn;
2346
2353
  }
2347
2354
  causeOf(e, t, n) {
2348
2355
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2416,7 +2423,7 @@ var Fn = class {
2416
2423
  let r = n ?? "";
2417
2424
  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";
2418
2425
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2419
- if (Dn.has(e)) return "ERROR_STAGE_RESOLVE";
2426
+ if (On.has(e)) return "ERROR_STAGE_RESOLVE";
2420
2427
  let i = t ?? "";
2421
2428
  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";
2422
2429
  }
@@ -2463,14 +2470,14 @@ var Fn = class {
2463
2470
  if (this.lastRequestCount = g, _ > 0) {
2464
2471
  o.requestCountDelta = _;
2465
2472
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2466
- n.length > 0 && (o.requestTimeP50Ms = En(n, 50), o.requestTimeP95Ms = En(n, 95));
2473
+ n.length > 0 && (o.requestTimeP50Ms = Dn(n, 50), o.requestTimeP95Ms = Dn(n, 95));
2467
2474
  }
2468
2475
  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();
2469
2476
  }
2470
2477
  maybeEmitMediaInfo(e) {
2471
2478
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2472
2479
  let t = {};
2473
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Tn[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);
2480
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = En[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);
2474
2481
  let n = JSON.stringify(t);
2475
2482
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2476
2483
  }
@@ -2490,7 +2497,7 @@ var Fn = class {
2490
2497
  let c = r?.positionMs ?? 0;
2491
2498
  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));
2492
2499
  let l = e !== "END_REASON_ENDED";
2493
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Sn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Sn && (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);
2500
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Cn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Cn && (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);
2494
2501
  let u = r?.decodedFrames ?? this.lastDecoded;
2495
2502
  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");
2496
2503
  }
@@ -2510,13 +2517,13 @@ var Fn = class {
2510
2517
  };
2511
2518
  }
2512
2519
  noteCspBlocked() {
2513
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(jn(new URL(this.url).origin)));
2520
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Mn(new URL(this.url).origin)));
2514
2521
  }
2515
2522
  cspBlocked() {
2516
2523
  return !!this.cspKey && Y.has(this.cspKey);
2517
2524
  }
2518
2525
  enqueue(e) {
2519
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > bn;) {
2526
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > xn;) {
2520
2527
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2521
2528
  this.pending.splice(e >= 0 ? e : 0, 1);
2522
2529
  }
@@ -2543,7 +2550,7 @@ var Fn = class {
2543
2550
  };
2544
2551
  //#endregion
2545
2552
  //#region src/core/environment.ts
2546
- function In() {
2553
+ function Ln() {
2547
2554
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2548
2555
  let e;
2549
2556
  try {
@@ -2568,14 +2575,14 @@ function In() {
2568
2575
  integration: "INTEGRATION_KIND_IFRAME"
2569
2576
  };
2570
2577
  }
2571
- function Ln() {
2578
+ function Rn() {
2572
2579
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2573
2580
  let e = navigator.userAgentData, t = e?.platform ?? "";
2574
2581
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2575
2582
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2576
2583
  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";
2577
2584
  }
2578
- function Rn() {
2585
+ function zn() {
2579
2586
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2580
2587
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2581
2588
  let t = {
@@ -2594,17 +2601,17 @@ function Rn() {
2594
2601
  }
2595
2602
  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;
2596
2603
  }
2597
- function zn(e) {
2598
- let t = In(), n = {
2599
- deviceClass: Ln(),
2604
+ function Bn(e) {
2605
+ let t = Ln(), n = {
2606
+ deviceClass: Rn(),
2600
2607
  integration: t.integration,
2601
- ...Rn()
2608
+ ...zn()
2602
2609
  };
2603
2610
  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);
2604
2611
  let r = e.getBoundingClientRect?.();
2605
2612
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2606
2613
  }
2607
- async function Bn() {
2614
+ async function Vn() {
2608
2615
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2609
2616
  if (!e?.getHighEntropyValues) return {};
2610
2617
  try {
@@ -2616,7 +2623,7 @@ async function Bn() {
2616
2623
  }
2617
2624
  //#endregion
2618
2625
  //#region src/core/version.ts
2619
- var Vn = "2.18.0", Hn = {
2626
+ var Hn = "2.19.0", Un = {
2620
2627
  accent: "#E1B600",
2621
2628
  accentText: "#1B1C23",
2622
2629
  background: "#0e0f13",
@@ -2627,7 +2634,7 @@ var Vn = "2.18.0", Hn = {
2627
2634
  border: "rgba(255, 255, 255, 0.1)",
2628
2635
  radius: "8px",
2629
2636
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2630
- }, Un = {
2637
+ }, Wn = {
2631
2638
  accent: "--havik-accent",
2632
2639
  accentText: "--havik-accent-text",
2633
2640
  background: "--havik-bg",
@@ -2639,26 +2646,26 @@ var Vn = "2.18.0", Hn = {
2639
2646
  radius: "--havik-radius",
2640
2647
  fontFamily: "--havik-font"
2641
2648
  };
2642
- function Wn(e, t) {
2649
+ function Z(e, t) {
2643
2650
  let n = {
2644
- ...Hn,
2651
+ ...Un,
2645
2652
  ...t
2646
2653
  };
2647
- for (let t of Object.keys(Un)) e.style.setProperty(Un[t], n[t]);
2654
+ for (let t of Object.keys(Wn)) e.style.setProperty(Wn[t], n[t]);
2648
2655
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2649
2656
  }
2650
2657
  //#endregion
2651
2658
  //#region src/ui/styles.ts
2652
- var Gn = "havik-player-styles", Kn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2653
- function qn(e = document, t) {
2659
+ var Gn = "havik-player-styles", Kn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", qn = /* @__PURE__ */ new WeakMap();
2660
+ function Jn(e = document, t) {
2654
2661
  let n = e.querySelector(`style#${Gn}`);
2655
- if (n && (!t || Z.get(n) === t)) return;
2662
+ if (n && (!t || qn.get(n) === t)) return;
2656
2663
  let r = e.createElement("style");
2657
- r.id = Gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2664
+ r.id = Gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, qn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2658
2665
  }
2659
2666
  //#endregion
2660
2667
  //#region src/ui/icons.ts
2661
- var Jn = {
2668
+ var Yn = {
2662
2669
  play: "<path d=\"M8 5v14l11-7z\"/>",
2663
2670
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2664
2671
  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\"/>",
@@ -2672,20 +2679,20 @@ var Jn = {
2672
2679
  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\"/>"
2673
2680
  };
2674
2681
  function Q(e) {
2675
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Jn[e]}</svg>`;
2682
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Yn[e]}</svg>`;
2676
2683
  }
2677
2684
  //#endregion
2678
2685
  //#region src/ui/controls.ts
2679
- var Yn = 3e3, Xn = 250, Zn = /* @__PURE__ */ new Set([
2686
+ var Xn = 3e3, Zn = 250, Qn = /* @__PURE__ */ new Set([
2680
2687
  "GONE",
2681
2688
  "NOT_FOUND",
2682
2689
  "INVALID_URN",
2683
2690
  "UNAUTHORIZED"
2684
2691
  ]);
2685
- function Qn(e) {
2686
- return new $n(e);
2692
+ function $n(e) {
2693
+ return new er(e);
2687
2694
  }
2688
- var $n = class {
2695
+ var er = class {
2689
2696
  root;
2690
2697
  video;
2691
2698
  player;
@@ -2716,6 +2723,7 @@ var $n = class {
2716
2723
  statusKind = null;
2717
2724
  statusMsg = null;
2718
2725
  hasPlayed = !1;
2726
+ fsSupported = !0;
2719
2727
  lastError = null;
2720
2728
  logoUrl;
2721
2729
  statusOverlays;
@@ -2732,7 +2740,7 @@ var $n = class {
2732
2740
  scrubbing = !1;
2733
2741
  offFns = [];
2734
2742
  constructor(e) {
2735
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Yn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, qn(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2743
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Xn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Jn(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2736
2744
  let t = (e, t, n) => {
2737
2745
  let r = this.doc.createElement(e);
2738
2746
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2770,7 +2778,7 @@ var $n = class {
2770
2778
  let o = this.doc.createElement("span");
2771
2779
  o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
2772
2780
  let s = t("div", "havik-spacer");
2773
- if (this.ccBtn = n("havik-btn", "cc", "Subtitles"), this.audioBtn = n("havik-btn", "settings", "Audio track"), this.qualityBtn = n("havik-btn", "settings", "Quality"), this.pipBtn = n("havik-btn", "pip", "Picture in picture"), this.fsBtn = n("havik-btn", "fullscreen", "Fullscreen"), this.ccBtn.style.display = "none", this.audioBtn.style.display = "none", this.qualityBtn.style.display = "none", this.pipSupported() || (this.pipBtn.style.display = "none"), i.append(this.playBtn, a, this.live, this.time, s, this.ccBtn, this.audioBtn, this.qualityBtn, this.pipBtn, this.fsBtn), this.bar.append(this.seek, i), this.menu = t("div", "havik-menu", { role: "menu" }), this.menu.hidden = !0, this.root.append(this.gradient, this.overlay, this.bar, this.menu), e.logoUrl) {
2781
+ if (this.ccBtn = n("havik-btn", "cc", "Subtitles"), this.audioBtn = n("havik-btn", "settings", "Audio track"), this.qualityBtn = n("havik-btn", "settings", "Quality"), this.pipBtn = n("havik-btn", "pip", "Picture in picture"), this.fsBtn = n("havik-btn", "fullscreen", "Fullscreen"), this.ccBtn.style.display = "none", this.audioBtn.style.display = "none", this.qualityBtn.style.display = "none", this.pipSupported() || (this.pipBtn.style.display = "none"), this.syncFullscreenSupport(), i.append(this.playBtn, a, this.live, this.time, s, this.ccBtn, this.audioBtn, this.qualityBtn, this.pipBtn, this.fsBtn), this.bar.append(this.seek, i), this.menu = t("div", "havik-menu", { role: "menu" }), this.menu.hidden = !0, this.root.append(this.gradient, this.overlay, this.bar, this.menu), e.logoUrl) {
2774
2782
  let n = t("div", "havik-watermark");
2775
2783
  n.style.backgroundImage = `url("${e.logoUrl}")`, this.root.append(n);
2776
2784
  }
@@ -2788,7 +2796,7 @@ var $n = class {
2788
2796
  }), this.on(this.muteBtn, "click", () => this.player.setMuted(!e.muted)), this.on(this.volSlider, "input", () => {
2789
2797
  let t = Number(this.volSlider.value);
2790
2798
  this.setVolumeFill(t), this.player.setVolume(t), t > 0 && e.muted && this.player.setMuted(!1);
2791
- }), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
2799
+ }), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.on(e, "loadedmetadata", () => this.syncFullscreenSupport()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
2792
2800
  this.lastError = e, this.statusKind = null, this.syncState();
2793
2801
  }));
2794
2802
  let t = (e) => e.pointerType !== "touch";
@@ -2818,7 +2826,7 @@ var $n = class {
2818
2826
  let t = this.surfaceWasHidden;
2819
2827
  this.tapTimer = setTimeout(() => {
2820
2828
  this.tapTimer = void 0, this.toggleBar(t);
2821
- }, Xn);
2829
+ }, Zn);
2822
2830
  }
2823
2831
  toggleBar(e) {
2824
2832
  e ? this.poke() : this.hideIfIdle();
@@ -2853,7 +2861,7 @@ var $n = class {
2853
2861
  e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2854
2862
  } else {
2855
2863
  let r = this.doc.createElement("div");
2856
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Zn.has(this.lastError.code)) {
2864
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Qn.has(this.lastError.code)) {
2857
2865
  let e = this.doc.createElement("button");
2858
2866
  e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2859
2867
  }
@@ -2894,7 +2902,7 @@ var $n = class {
2894
2902
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2895
2903
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2896
2904
  }
2897
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${er(this.video.currentTime)} / ${er(this.video.duration)}`);
2905
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${tr(this.video.currentTime)} / ${tr(this.video.duration)}`);
2898
2906
  }
2899
2907
  syncLive() {
2900
2908
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
@@ -2944,17 +2952,17 @@ var $n = class {
2944
2952
  renderQualityMenu() {
2945
2953
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2946
2954
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2947
- for (let n of e) this.menu.append(this.menuItem(tr(n), t === n.index, () => this.player.setQuality(n.index)));
2955
+ for (let n of e) this.menu.append(this.menuItem(nr(n), t === n.index, () => this.player.setQuality(n.index)));
2948
2956
  }
2949
2957
  renderAudioMenu() {
2950
2958
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2951
2959
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2952
- for (let t of e) this.menu.append(this.menuItem(nr(t), t.default, () => this.player.setAudioTrack(t.id)));
2960
+ for (let t of e) this.menu.append(this.menuItem(rr(t), t.default, () => this.player.setAudioTrack(t.id)));
2953
2961
  }
2954
2962
  renderCcMenu() {
2955
2963
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2956
2964
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2957
- for (let t of e) this.menu.append(this.menuItem(rr(t), !1, () => this.player.setTextTrack(t.id)));
2965
+ for (let t of e) this.menu.append(this.menuItem(ir(t), !1, () => this.player.setTextTrack(t.id)));
2958
2966
  }
2959
2967
  onTracksChanged() {
2960
2968
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2974,11 +2982,14 @@ var $n = class {
2974
2982
  }
2975
2983
  async toggleFullscreen() {
2976
2984
  try {
2977
- x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
2985
+ S(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
2978
2986
  } catch {}
2979
2987
  }
2988
+ syncFullscreenSupport() {
2989
+ this.fsSupported = C(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
2990
+ }
2980
2991
  syncFullscreen() {
2981
- let e = x(this.video, this.root);
2992
+ let e = S(this.video, this.root);
2982
2993
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2983
2994
  }
2984
2995
  poke() {
@@ -3012,6 +3023,7 @@ var $n = class {
3012
3023
  this.player.setMuted(!this.video.muted);
3013
3024
  break;
3014
3025
  case "f":
3026
+ if (!this.fsSupported) return;
3015
3027
  this.toggleFullscreen();
3016
3028
  break;
3017
3029
  case "c":
@@ -3055,41 +3067,41 @@ var $n = class {
3055
3067
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
3056
3068
  }
3057
3069
  };
3058
- function er(e) {
3070
+ function tr(e) {
3059
3071
  (!Number.isFinite(e) || e < 0) && (e = 0);
3060
3072
  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");
3061
3073
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3062
3074
  }
3063
- function tr(e) {
3075
+ function nr(e) {
3064
3076
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3065
3077
  }
3066
- function nr(e) {
3078
+ function rr(e) {
3067
3079
  return e.name || e.lang || `Track ${e.id}`;
3068
3080
  }
3069
- function rr(e) {
3081
+ function ir(e) {
3070
3082
  return e.name || e.lang || `Track ${e.id}`;
3071
3083
  }
3072
3084
  //#endregion
3073
3085
  //#region src/managed/index.ts
3074
- var ir = 6e3, ar = 45e3, or = 2e3, sr = 3, cr = 5e3, lr = 2e3, ur = 48e4, dr = "keySystemLicenseRequestFailed";
3075
- function fr(e) {
3086
+ var ar = 6e3, or = 45e3, sr = 2e3, cr = 3, lr = 5e3, ur = 2e3, dr = 48e4, fr = "keySystemLicenseRequestFailed";
3087
+ function pr(e) {
3076
3088
  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)})`);
3077
- if (e.env !== void 0) return L(e.env);
3089
+ if (e.env !== void 0) return rt(e.env);
3078
3090
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3079
3091
  return e.baseUrl;
3080
3092
  }
3081
- async function pr(e) {
3093
+ async function mr(e) {
3082
3094
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3083
- let t = fr(e);
3095
+ let t = pr(e);
3084
3096
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3085
3097
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3086
- let r = new mr({
3098
+ let r = new hr({
3087
3099
  ...e,
3088
3100
  baseUrl: t
3089
3101
  });
3090
3102
  return await r.start(), r;
3091
3103
  }
3092
- var mr = class {
3104
+ var hr = class {
3093
3105
  opts;
3094
3106
  abort = new AbortController();
3095
3107
  listeners = {};
@@ -3163,7 +3175,7 @@ var mr = class {
3163
3175
  };
3164
3176
  }
3165
3177
  beginArming(e, t, n = !1) {
3166
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
3178
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3167
3179
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
3168
3180
  }
3169
3181
  beginArmingByPolling(e) {
@@ -3184,7 +3196,7 @@ var mr = class {
3184
3196
  setTimeout(() => {
3185
3197
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3186
3198
  phase: i ? "unavailable" : "tooEarly",
3187
- retryInMs: ar,
3199
+ retryInMs: or,
3188
3200
  attempt: 1,
3189
3201
  elapsedMs: 0,
3190
3202
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3223,13 +3235,13 @@ var mr = class {
3223
3235
  !a && !p() && h();
3224
3236
  }, e);
3225
3237
  };
3226
- _(ir), this.armingSub = w({
3238
+ _(ar), this.armingSub = E({
3227
3239
  eventsBaseUrl: t,
3228
3240
  matchUrn: this.opts.matchUrn,
3229
3241
  credential: this.opts.credential,
3230
- onAlive: () => _(ar),
3242
+ onAlive: () => _(or),
3231
3243
  onState: (e) => {
3232
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * or);
3244
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * sr);
3233
3245
  },
3234
3246
  onError: () => h()
3235
3247
  });
@@ -3252,7 +3264,7 @@ var mr = class {
3252
3264
  let n = await s(this.opts.credential);
3253
3265
  if (this.destroyed || t !== this.loadGen) return;
3254
3266
  this.setState("loading");
3255
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ct(this.opts.video, (e) => {
3267
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = lt(this.opts.video, (e) => {
3256
3268
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3257
3269
  });
3258
3270
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3274,26 +3286,26 @@ var mr = class {
3274
3286
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3275
3287
  let i = e.analytics?.sid;
3276
3288
  if (!i) return;
3277
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Pn(this.opts.baseUrl, a, e.analytics?.endpoint);
3289
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Fn(this.opts.baseUrl, a, e.analytics?.endpoint);
3278
3290
  if (!o) {
3279
3291
  s && setTimeout(() => {
3280
3292
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3281
3293
  }, 0);
3282
3294
  return;
3283
3295
  }
3284
- let c = this.opts.video, l = new Fn({
3296
+ let c = this.opts.video, l = new In({
3285
3297
  endpoint: o,
3286
3298
  sid: i,
3287
3299
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3288
- sdkVersion: Vn,
3289
- environment: zn(c),
3300
+ sdkVersion: Hn,
3301
+ environment: Bn(c),
3290
3302
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3291
3303
  onIdle: () => this.onAnalyticsIdle(t),
3292
3304
  onBlocked: (e) => setTimeout(() => {
3293
3305
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3294
3306
  }, 0),
3295
3307
  sample: () => {
3296
- let e = this.engine?.getStats() ?? R, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3308
+ let e = this.engine?.getStats() ?? it, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3297
3309
  return {
3298
3310
  ...e,
3299
3311
  bufferedMs: Math.round(t * 1e3),
@@ -3307,7 +3319,7 @@ var mr = class {
3307
3319
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3308
3320
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3309
3321
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3310
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Bn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3322
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Vn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3311
3323
  }
3312
3324
  currentPresentation() {
3313
3325
  let e = this.opts.video;
@@ -3322,7 +3334,7 @@ var mr = class {
3322
3334
  video: this.opts.video,
3323
3335
  descriptor: e,
3324
3336
  credential: t,
3325
- deviceId: O(),
3337
+ deviceId: A(),
3326
3338
  userId: this.opts.userId,
3327
3339
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3328
3340
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -3335,9 +3347,9 @@ var mr = class {
3335
3347
  freshLicenseUrl: () => this.refreshLicense()
3336
3348
  }, o = this.opts.engine ?? "auto";
3337
3349
  if (o === "native") return new W(a);
3338
- if (o === "hls") return new gn(a);
3339
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && bt() && H(this.opts.video)) return new W(a);
3340
- if (Mt()) return new gn(a);
3350
+ if (o === "hls") return new _n(a);
3351
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && xt() && H(this.opts.video)) return new W(a);
3352
+ if (Nt()) return new _n(a);
3341
3353
  if (H(this.opts.video)) return new W(a);
3342
3354
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3343
3355
  }
@@ -3385,11 +3397,11 @@ var mr = class {
3385
3397
  }
3386
3398
  startLiveState(e) {
3387
3399
  if (this.opts.liveStateEvents === !1) return;
3388
- let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
3400
+ let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3389
3401
  if (!t) return;
3390
3402
  this.closeLiveState();
3391
3403
  let r = 0, i = !1;
3392
- this.liveStateSub = w({
3404
+ this.liveStateSub = E({
3393
3405
  eventsBaseUrl: t,
3394
3406
  matchUrn: this.opts.matchUrn,
3395
3407
  credential: this.opts.credential,
@@ -3400,7 +3412,7 @@ var mr = class {
3400
3412
  r = 0, i = !1;
3401
3413
  },
3402
3414
  onError: () => {
3403
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= sr && (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.`))));
3415
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= cr && (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.`))));
3404
3416
  }
3405
3417
  });
3406
3418
  }
@@ -3414,7 +3426,7 @@ var mr = class {
3414
3426
  return;
3415
3427
  }
3416
3428
  let e = this.hiddenAtMs;
3417
- this.hiddenAtMs = null, e != null && Date.now() - e >= cr && this.resyncLiveState();
3429
+ this.hiddenAtMs = null, e != null && Date.now() - e >= lr && this.resyncLiveState();
3418
3430
  }, this.onReturnPageShow = (e) => {
3419
3431
  e.persisted && this.resyncLiveState();
3420
3432
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3446,7 +3458,7 @@ var mr = class {
3446
3458
  scheduleRejoin(e) {
3447
3459
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3448
3460
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3449
- }, Math.random() * or));
3461
+ }, Math.random() * sr));
3450
3462
  }
3451
3463
  cancelRejoin() {
3452
3464
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3470,7 +3482,7 @@ var mr = class {
3470
3482
  }
3471
3483
  t.controls = !1;
3472
3484
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3473
- r && r.insertBefore(n, t), n.appendChild(t), Wn(n, this.opts.theme), this.container = n, this.controlBar = Qn({
3485
+ r && r.insertBefore(n, t), n.appendChild(t), Z(n, this.opts.theme), this.container = n, this.controlBar = $n({
3474
3486
  root: n,
3475
3487
  video: t,
3476
3488
  player: this,
@@ -3508,7 +3520,7 @@ var mr = class {
3508
3520
  }
3509
3521
  startStats() {
3510
3522
  this.stopStats();
3511
- let e = Math.max(500, this.opts.statsIntervalMs ?? lr);
3523
+ let e = Math.max(500, this.opts.statsIntervalMs ?? ur);
3512
3524
  this.statsTimer = setInterval(() => {
3513
3525
  if (!this.engine) return;
3514
3526
  let e = this.engine.getStats();
@@ -3519,14 +3531,14 @@ var mr = class {
3519
3531
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3520
3532
  }
3521
3533
  isStaleLicenseDenial(e) {
3522
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== dr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3534
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== fr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3523
3535
  }
3524
3536
  scheduleLicenseRefresh() {
3525
3537
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3526
3538
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3527
3539
  document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3528
3540
  }, document.addEventListener("visibilitychange", this.onRefocus));
3529
- let e = this.opts.licenseRefreshMs ?? ur;
3541
+ let e = this.opts.licenseRefreshMs ?? dr;
3530
3542
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3531
3543
  }
3532
3544
  stopRefresh() {
@@ -3583,7 +3595,7 @@ var mr = class {
3583
3595
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3584
3596
  }
3585
3597
  getStats() {
3586
- return this.engine?.getStats() ?? R;
3598
+ return this.engine?.getStats() ?? it;
3587
3599
  }
3588
3600
  getQualityLevels() {
3589
3601
  return this.engine?.getQualityLevels() ?? [];
@@ -3622,10 +3634,13 @@ var mr = class {
3622
3634
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3623
3635
  }
3624
3636
  async enterFullscreen() {
3625
- return !this.destroyed && S(this.opts.video, this.container ?? void 0);
3637
+ return !this.destroyed && w(this.opts.video, this.container ?? void 0);
3626
3638
  }
3627
3639
  async exitFullscreen() {
3628
- await C(this.opts.video, this.container ?? void 0);
3640
+ await T(this.opts.video, this.container ?? void 0);
3641
+ }
3642
+ fullscreenSupported() {
3643
+ return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3629
3644
  }
3630
3645
  retry() {
3631
3646
  return this.reload();
@@ -3693,7 +3708,7 @@ function $(e) {
3693
3708
  }
3694
3709
  //#endregion
3695
3710
  //#region src/embed/host.ts
3696
- function hr(e) {
3711
+ function gr(e) {
3697
3712
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3698
3713
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3699
3714
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3752,15 +3767,15 @@ function hr(e) {
3752
3767
  }
3753
3768
  //#endregion
3754
3769
  //#region src/embed/page.ts
3755
- var gr = /^[A-Za-z0-9:_.-]{1,128}$/;
3756
- function _r(e) {
3770
+ var _r = /^[A-Za-z0-9:_.-]{1,128}$/;
3771
+ function vr(e) {
3757
3772
  if (typeof e == "boolean") return e;
3758
3773
  if (typeof e == "object" && e) {
3759
3774
  let t = e.endpoint;
3760
3775
  return typeof t == "string" ? { endpoint: t } : {};
3761
3776
  }
3762
3777
  }
3763
- function vr() {
3778
+ function yr() {
3764
3779
  let e = window.HAVIK_EMBED_CONFIG;
3765
3780
  if (e) return {
3766
3781
  baseUrl: e.baseUrl ?? "",
@@ -3770,7 +3785,7 @@ function vr() {
3770
3785
  autoplay: e.autoplay ?? !0,
3771
3786
  muted: e.muted ?? !0,
3772
3787
  waitForLive: e.waitForLive ?? !0,
3773
- analytics: _r(e.analytics)
3788
+ analytics: vr(e.analytics)
3774
3789
  };
3775
3790
  let t = new URLSearchParams(location.search);
3776
3791
  return {
@@ -3783,9 +3798,9 @@ function vr() {
3783
3798
  waitForLive: !0
3784
3799
  };
3785
3800
  }
3786
- async function yr() {
3787
- let e = vr();
3788
- xr();
3801
+ async function br() {
3802
+ let e = yr();
3803
+ Sr();
3789
3804
  let t = document.createElement("video");
3790
3805
  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);
3791
3806
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3840,12 +3855,12 @@ async function yr() {
3840
3855
  code: e.code,
3841
3856
  message: e.message
3842
3857
  })), e.on("autoplayblocked", () => {
3843
- i({ type: "oddin:autoplayblocked" }), br(t, e);
3858
+ i({ type: "oddin:autoplayblocked" }), xr(t, e);
3844
3859
  });
3845
3860
  }, s = async (r) => {
3846
3861
  a?.destroy(), a = null;
3847
3862
  try {
3848
- let n = await pr({
3863
+ let n = await mr({
3849
3864
  video: t,
3850
3865
  baseUrl: e.baseUrl,
3851
3866
  matchUrn: r,
@@ -3907,7 +3922,7 @@ async function yr() {
3907
3922
  a?.retry();
3908
3923
  break;
3909
3924
  case "oddin:load":
3910
- typeof e.matchUrn == "string" && gr.test(e.matchUrn) && s(e.matchUrn);
3925
+ typeof e.matchUrn == "string" && _r.test(e.matchUrn) && s(e.matchUrn);
3911
3926
  break;
3912
3927
  case "oddin:destroy": c();
3913
3928
  }
@@ -3919,18 +3934,18 @@ async function yr() {
3919
3934
  protocol: 1
3920
3935
  });
3921
3936
  }
3922
- function br(e, t) {
3937
+ function xr(e, t) {
3923
3938
  if (document.getElementById("havik-tap")) return;
3924
3939
  let n = document.createElement("button");
3925
3940
  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", () => {
3926
3941
  n.remove(), t.play();
3927
3942
  }), document.body.appendChild(n);
3928
3943
  }
3929
- function xr() {
3944
+ function Sr() {
3930
3945
  let e = document.createElement("style");
3931
3946
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3932
3947
  }
3933
3948
  //#endregion
3934
- export { Hn as ODDIN_THEME, n as PlaybackError, Wn as applyTheme, L as baseUrlForEnv, yr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, pr as createPlayer, T as deriveEventsBaseUrl, tt as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, hr as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, we as watchStatus };
3949
+ export { Un as ODDIN_THEME, n as PlaybackError, Z as applyTheme, rt as baseUrlForEnv, br as bootEmbed, Te as clearDeviceId, Ie as clearRememberedBandwidth, mr as createPlayer, D as deriveEventsBaseUrl, $e as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, C as fullscreenSupported, A as getDeviceId, tt as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, gr as mountEmbed, de as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3935
3950
 
3936
3951
  //# sourceMappingURL=index.js.map