@oddin-gg/havik-player 2.6.4 → 2.8.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
@@ -142,7 +142,7 @@ function ae(e, t) {
142
142
  t?.addEventListener("abort", a, { once: !0 });
143
143
  });
144
144
  }
145
- async function oe(e, t, r) {
145
+ async function v(e, t, r) {
146
146
  let i = ee(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
147
147
  for (;;) {
148
148
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
@@ -168,21 +168,21 @@ async function oe(e, t, r) {
168
168
  }
169
169
  //#endregion
170
170
  //#region src/core/resolve.ts
171
- async function v(e) {
171
+ async function y(e) {
172
172
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
173
173
  let t = await u(c(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
174
174
  credential: e.credential,
175
175
  signal: e.signal,
176
176
  apiHeaders: e.apiHeaders
177
177
  });
178
- if (!t.ok) throw await se(t);
179
- return le(await t.json(), e.matchUrn);
178
+ if (!t.ok) throw await oe(t);
179
+ return ce(await t.json(), e.matchUrn);
180
180
  }
181
- function y(e) {
182
- let t = () => v(e);
183
- return e.waitForLive ? oe(t, e.waitForLive, e.signal) : t();
181
+ function b(e) {
182
+ let t = () => y(e);
183
+ return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
184
184
  }
185
- async function se(e) {
185
+ async function oe(e) {
186
186
  let t = l(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
187
187
  try {
188
188
  let t = await e.json();
@@ -198,7 +198,7 @@ async function se(e) {
198
198
  liveStartsAtMs: s
199
199
  });
200
200
  }
201
- var ce = /* @__PURE__ */ new Set([
201
+ var se = /* @__PURE__ */ new Set([
202
202
  "matchUrn",
203
203
  "protocol",
204
204
  "drmEnabled",
@@ -209,7 +209,7 @@ var ce = /* @__PURE__ */ new Set([
209
209
  "expiresAt",
210
210
  "analytics"
211
211
  ]);
212
- function b(e, t) {
212
+ function x(e, t) {
213
213
  let r;
214
214
  try {
215
215
  r = new URL(t);
@@ -219,36 +219,36 @@ function b(e, t) {
219
219
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
220
220
  return t;
221
221
  }
222
- function le(e, t) {
222
+ function ce(e, t) {
223
223
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
224
224
  let r = e.drmEnabled ?? !!e.drm, i = {
225
225
  matchUrn: e.matchUrn ?? t,
226
226
  protocol: "hls",
227
227
  drmEnabled: r,
228
- manifestUrl: b("manifestUrl", e.manifestUrl),
228
+ manifestUrl: x("manifestUrl", e.manifestUrl),
229
229
  serverTime: e.serverTime ?? ""
230
230
  };
231
231
  if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid && (i.analytics = { sid: e.analytics.sid }), r && e.drm) {
232
232
  let t = {};
233
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
234
- licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
235
- certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
233
+ e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
234
+ licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
235
+ certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
236
236
  }), (t.widevine || t.fairplay) && (i.drm = t);
237
237
  }
238
238
  let a = {};
239
- for (let [t, n] of Object.entries(e)) ce.has(t) || (a[t] = n);
239
+ for (let [t, n] of Object.entries(e)) se.has(t) || (a[t] = n);
240
240
  return Object.keys(a).length > 0 && (i.extensions = a), i;
241
241
  }
242
242
  //#endregion
243
243
  //#region src/core/fullscreen.ts
244
- function x(e) {
244
+ function S(e) {
245
245
  return e.ownerDocument ?? document;
246
246
  }
247
- function S(e) {
247
+ function le(e) {
248
248
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
249
249
  }
250
250
  function C(e, t) {
251
- let n = S(x(e));
251
+ let n = le(S(e));
252
252
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
253
253
  }
254
254
  async function w(e, t) {
@@ -264,7 +264,7 @@ async function T(e, t) {
264
264
  n.webkitExitFullscreen?.();
265
265
  return;
266
266
  }
267
- let r = x(e), i = S(r);
267
+ let r = S(e), i = le(r);
268
268
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
269
269
  }
270
270
  //#endregion
@@ -551,7 +551,7 @@ var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
551
551
  function xe(e) {
552
552
  return e.startsWith("com.widevine");
553
553
  }
554
- function Se(e, t) {
554
+ function P(e, t) {
555
555
  if (!xe(e)) return t;
556
556
  let n = (e, t) => {
557
557
  let n = e.videoCapabilities;
@@ -568,8 +568,8 @@ function Se(e, t) {
568
568
  })));
569
569
  return [...t, ...r];
570
570
  }
571
- function Ce(e) {
572
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Se(t, n)).then((t) => ({
571
+ function Se(e) {
572
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
573
573
  keySystem: t.keySystem,
574
574
  getConfiguration: () => t.getConfiguration(),
575
575
  createMediaKeys: () => be(e, t)
@@ -577,11 +577,11 @@ function Ce(e) {
577
577
  }
578
578
  //#endregion
579
579
  //#region src/core/drm/support.ts
580
- var we = 5e3, Te = "video/mp4; codecs=\"avc1.42E01E\"", P = "audio/mp4; codecs=\"mp4a.40.2\"", Ee = {
580
+ var Ce = 5e3, F = "video/mp4; codecs=\"avc1.42E01E\"", I = "audio/mp4; codecs=\"mp4a.40.2\"", we = {
581
581
  widevine: ["com.widevine.alpha"],
582
582
  fairplay: ["com.apple.fps"]
583
583
  };
584
- function De(e) {
584
+ function Te(e) {
585
585
  return e === "fairplay" ? [{
586
586
  initDataTypes: [
587
587
  "sinf",
@@ -589,30 +589,30 @@ function De(e) {
589
589
  "cenc"
590
590
  ],
591
591
  videoCapabilities: [{
592
- contentType: Te,
592
+ contentType: F,
593
593
  robustness: "",
594
594
  encryptionScheme: "cbcs"
595
595
  }],
596
596
  audioCapabilities: [{
597
- contentType: P,
597
+ contentType: I,
598
598
  robustness: "",
599
599
  encryptionScheme: "cbcs"
600
600
  }]
601
- }] : Se("com.widevine.alpha", [{
601
+ }] : P("com.widevine.alpha", [{
602
602
  initDataTypes: ["cenc"],
603
603
  videoCapabilities: [{
604
- contentType: Te,
604
+ contentType: F,
605
605
  robustness: "SW_SECURE_DECODE",
606
606
  encryptionScheme: "cbcs"
607
607
  }],
608
608
  audioCapabilities: [{
609
- contentType: P,
609
+ contentType: I,
610
610
  robustness: "SW_SECURE_CRYPTO",
611
611
  encryptionScheme: "cbcs"
612
612
  }]
613
613
  }]);
614
614
  }
615
- function F(e, t) {
615
+ function L(e, t) {
616
616
  return new Promise((n, r) => {
617
617
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
618
618
  e.then((e) => {
@@ -622,8 +622,8 @@ function F(e, t) {
622
622
  });
623
623
  });
624
624
  }
625
- async function Oe(e = {}) {
626
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? we, r = {};
625
+ async function Ee(e = {}) {
626
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ce, r = {};
627
627
  if (typeof window < "u" && window.isSecureContext === !1) return {
628
628
  verdict: "insecure-context",
629
629
  detail: r
@@ -635,7 +635,7 @@ async function Oe(e = {}) {
635
635
  };
636
636
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
637
637
  for (let e of t) {
638
- let t = Ee[e];
638
+ let t = we[e];
639
639
  if (!t) {
640
640
  r[e] = "unknown system";
641
641
  continue;
@@ -646,7 +646,7 @@ async function Oe(e = {}) {
646
646
  break;
647
647
  }
648
648
  try {
649
- return await F((await F(i(n, De(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
649
+ return await L((await L(i(n, Te(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
650
650
  verdict: "supported",
651
651
  system: e,
652
652
  detail: r
@@ -670,38 +670,49 @@ async function Oe(e = {}) {
670
670
  }
671
671
  //#endregion
672
672
  //#region src/core/manifest.ts
673
- var ke = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
674
- function Ae(e) {
675
- return ke.test(e);
673
+ var De = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
674
+ function Oe(e) {
675
+ return De.test(e);
676
+ }
677
+ //#endregion
678
+ //#region src/core/env.ts
679
+ var R = {
680
+ integration: "https://feed-dev.oddin-video.gg",
681
+ production: "https://feed.oddin-video.gg"
682
+ };
683
+ function z(e) {
684
+ let t = Object.prototype.hasOwnProperty.call(R, e) ? R[e] : void 0;
685
+ if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
686
+ return t;
676
687
  }
677
688
  //#endregion
678
689
  //#region src/core/stats.ts
679
- var I = { droppedFrames: 0 };
680
- function L(e) {
690
+ var B = { droppedFrames: 0 };
691
+ function V(e) {
681
692
  try {
682
693
  return new URL(e).host;
683
694
  } catch {
684
695
  return "";
685
696
  }
686
697
  }
687
- var je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
688
- function Me(e) {
698
+ var ke = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
699
+ function Ae(e) {
689
700
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
690
701
  let t = "", n = -1, r = performance.getEntriesByType("resource");
691
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || je.test(i.name)) && i.startTime >= n) {
692
- let e = L(i.name);
702
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ke.test(i.name)) && i.startTime >= n) {
703
+ let e = V(i.name);
693
704
  e && (t = e, n = i.startTime);
694
705
  }
695
706
  return t;
696
707
  }
697
- function R(e) {
708
+ function H(e) {
698
709
  let t = e.getVideoPlaybackQuality?.();
699
710
  return {
700
711
  dropped: t?.droppedVideoFrames ?? 0,
701
712
  totalFrames: t?.totalVideoFrames ?? 0
702
713
  };
703
714
  }
704
- function Ne(e, t) {
715
+ function je(e, t) {
705
716
  let n = [
706
717
  ["playing", () => t("playing")],
707
718
  ["waiting", () => t("buffering")],
@@ -718,7 +729,7 @@ function Ne(e, t) {
718
729
  }
719
730
  //#endregion
720
731
  //#region src/core/engine/native.ts
721
- function Pe(e) {
732
+ function Me(e) {
722
733
  try {
723
734
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
724
735
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -726,15 +737,15 @@ function Pe(e) {
726
737
  return;
727
738
  }
728
739
  }
729
- function z(e) {
740
+ function U(e) {
730
741
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
731
742
  }
732
- function B() {
743
+ function W() {
733
744
  if (typeof window > "u") return !1;
734
745
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
735
746
  return e || t;
736
747
  }
737
- var V = class {
748
+ var G = class {
738
749
  name = "native";
739
750
  deps;
740
751
  onLoaded;
@@ -770,7 +781,7 @@ var V = class {
770
781
  type: "error",
771
782
  error: new n("INTERNAL", 0, "native HLS playback error"),
772
783
  fatal: !0
773
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Fe(t.manifestUrl, t.analytics?.sid), e.load();
784
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ne(t.manifestUrl, t.analytics?.sid), e.load();
774
785
  }
775
786
  startLoad() {
776
787
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -792,7 +803,7 @@ var V = class {
792
803
  });
793
804
  this.onEncrypted = (n) => {
794
805
  let i = n;
795
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Pe(i.initData), (async () => {
806
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Me(i.initData), (async () => {
796
807
  try {
797
808
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
798
809
  initDataTypes: [i.initDataType],
@@ -887,11 +898,11 @@ var V = class {
887
898
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
888
899
  }
889
900
  getStats() {
890
- let e = this.deps.video, t = R(e), n = {
901
+ let e = this.deps.video, t = H(e), n = {
891
902
  droppedFrames: t.dropped,
892
903
  decodedFrames: t.totalFrames
893
904
  };
894
- return this.cdnHost ||= Me(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
905
+ return this.cdnHost ||= Ae(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
895
906
  }
896
907
  stop() {
897
908
  try {
@@ -910,29 +921,29 @@ var V = class {
910
921
  } catch {}
911
922
  }
912
923
  };
913
- function Fe(e, t) {
924
+ function Ne(e, t) {
914
925
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
915
926
  }
916
927
  //#endregion
917
928
  //#region src/core/engine/hls.ts
918
- function Ie() {
929
+ function Pe() {
919
930
  return e.isSupported();
920
931
  }
921
- var Le = 3, Re = 5, ze = 3, Be = 3e4, Ve = 12e3, He = 3e3, H = 6e3, Ue = 5e3, We = 4e3, Ge = 2, Ke = 5, qe = 2, Je = 2, Ye = 2e3, Xe = 3e4, Ze = 2, Qe = 9, $e = .5, et = 64;
922
- function tt(e) {
932
+ var Fe = 3, Ie = 5, Le = 3, Re = 3e4, ze = 12e3, Be = 3e3, K = 6e3, Ve = 5e3, He = 4e3, Ue = 2, We = 5, Ge = 2, Ke = 2, qe = 2e3, Je = 3e4, Ye = 2, Xe = 9, Ze = .5, Qe = 64;
933
+ function $e(e) {
923
934
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
924
935
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
925
936
  return;
926
937
  }
927
- e.liveSyncDuration ??= Ze;
928
- let t = Math.max(12, e.liveSyncDuration + Qe);
929
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), nt(e, e.liveSyncDuration);
938
+ e.liveSyncDuration ??= Ye;
939
+ let t = Math.max(12, e.liveSyncDuration + Xe);
940
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), et(e, e.liveSyncDuration);
930
941
  }
931
- function nt(e, t) {
942
+ function et(e, t) {
932
943
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
933
944
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
934
945
  }
935
- var U = class {
946
+ var q = class {
936
947
  name = "hls";
937
948
  hls = null;
938
949
  deps;
@@ -991,7 +1002,7 @@ var U = class {
991
1002
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
992
1003
  }
993
1004
  async load() {
994
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = z(r) && B(), o = !!e.drm?.widevine?.licenseUrl && !a;
1005
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = U(r) && W(), o = !!e.drm?.widevine?.licenseUrl && !a;
995
1006
  if (e.drmEnabled && !o) {
996
1007
  i({
997
1008
  type: "error",
@@ -1023,7 +1034,7 @@ var U = class {
1023
1034
  }
1024
1035
  this.loadSuspended = !0;
1025
1036
  }
1026
- }, Ue));
1037
+ }, Ve));
1027
1038
  }
1028
1039
  resumeLoading() {
1029
1040
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1055,7 +1066,7 @@ var U = class {
1055
1066
  let t = e.liveSyncPosition;
1056
1067
  if (typeof t != "number" || !Number.isFinite(t)) return;
1057
1068
  let { video: n } = this.deps;
1058
- n.currentTime <= t + $e || (n.currentTime = t);
1069
+ n.currentTime <= t + Ze || (n.currentTime = t);
1059
1070
  }
1060
1071
  startHls() {
1061
1072
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1079,7 +1090,7 @@ var U = class {
1079
1090
  videoEncryptionScheme: "cbcs",
1080
1091
  audioEncryptionScheme: "cbcs"
1081
1092
  },
1082
- ...M() ? { requestMediaKeySystemAccessFunc: Ce(t) } : {},
1093
+ ...M() ? { requestMediaKeySystemAccessFunc: Se(t) } : {},
1083
1094
  licenseXhrSetup: (e, t) => {
1084
1095
  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;
1085
1096
  let o = performance.now();
@@ -1095,7 +1106,7 @@ var U = class {
1095
1106
  } } : {},
1096
1107
  ...c
1097
1108
  };
1098
- tt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1109
+ $e(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1099
1110
  let f = new e(d);
1100
1111
  this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1101
1112
  this.mediaRecoveries = 0, this.networkRecoveries = 0;
@@ -1104,17 +1115,17 @@ var U = class {
1104
1115
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1105
1116
  t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1106
1117
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1107
- }, Be)));
1118
+ }, Re)));
1108
1119
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1109
1120
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1110
1121
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
1111
1122
  let n = t?.frag?.stats, r = n?.loaded;
1112
1123
  typeof r == "number" && (this.bytesLoaded += r);
1113
1124
  let i = n?.loading;
1114
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > et && this.requestTimesMs.shift());
1125
+ 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 > Qe && this.requestTimesMs.shift());
1115
1126
  let a = t?.frag?.url;
1116
1127
  if (a) {
1117
- let e = L(a);
1128
+ let e = V(a);
1118
1129
  e && (this.cdnHost = e);
1119
1130
  }
1120
1131
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1127,7 +1138,7 @@ var U = class {
1127
1138
  }));
1128
1139
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1129
1140
  this.checkEndStale(), this.checkStarvation();
1130
- }, He), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1141
+ }, Be), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1131
1142
  this.renditionSwitches += 1;
1132
1143
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1133
1144
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1191,7 +1202,7 @@ var U = class {
1191
1202
  return;
1192
1203
  }
1193
1204
  this.capTimer && clearTimeout(this.capTimer);
1194
- let t = e > this.sizeCapLevel ? Ye : Xe;
1205
+ let t = e > this.sizeCapLevel ? qe : Je;
1195
1206
  this.capTimer = setTimeout(() => {
1196
1207
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1197
1208
  }, t);
@@ -1238,7 +1249,7 @@ var U = class {
1238
1249
  e.widevine && (this.licenseUrl = e.widevine);
1239
1250
  }
1240
1251
  getStats() {
1241
- let e = this.hls, t = R(this.deps.video), n = {
1252
+ let e = this.hls, t = H(this.deps.video), n = {
1242
1253
  droppedFrames: t.dropped,
1243
1254
  decodedFrames: t.totalFrames,
1244
1255
  lowLatency: this.detectedLowLatency,
@@ -1284,7 +1295,7 @@ var U = class {
1284
1295
  return;
1285
1296
  }
1286
1297
  let e = Date.now() - this.lastAdvanceMs;
1287
- !this.chaseSuspended && e > H && this.suspendChasing(), e > Ve && this.emitEnded("stalled");
1298
+ !this.chaseSuspended && e > K && this.suspendChasing(), e > ze && this.emitEnded("stalled");
1288
1299
  }
1289
1300
  checkStarvation() {
1290
1301
  let e = this.hls, { video: t } = this.deps;
@@ -1293,17 +1304,17 @@ var U = class {
1293
1304
  this.starvedTicks = 0;
1294
1305
  return;
1295
1306
  }
1296
- let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > We;
1307
+ let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < K, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > He;
1297
1308
  if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
1298
1309
  this.starvedTicks = 0;
1299
1310
  return;
1300
1311
  }
1301
- if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ge)) {
1302
- if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= qe && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Je)) {
1312
+ if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ue)) {
1313
+ if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ge && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Ke)) {
1303
1314
  this.starvationRebuilds += 1, 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");
1304
1315
  return;
1305
1316
  }
1306
- if (!(this.starvationKicks >= Ke)) {
1317
+ if (!(this.starvationKicks >= We)) {
1307
1318
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1308
1319
  try {
1309
1320
  e.stopLoad(), e.startLoad(-1);
@@ -1353,7 +1364,7 @@ var U = class {
1353
1364
  scheduleLicenseRetry(t) {
1354
1365
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1355
1366
  let n = t.response?.code ?? 0;
1356
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ze) return !1;
1367
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Le) return !1;
1357
1368
  this.licenseRecoveries += 1;
1358
1369
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1359
1370
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1385,7 +1396,7 @@ var U = class {
1385
1396
  return;
1386
1397
  }
1387
1398
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1388
- if (this.networkRecoveries < Re) {
1399
+ if (this.networkRecoveries < Ie) {
1389
1400
  this.networkRecoveries += 1;
1390
1401
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1391
1402
  this.networkRetryTimer = setTimeout(() => {
@@ -1402,7 +1413,7 @@ var U = class {
1402
1413
  return;
1403
1414
  }
1404
1415
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1405
- if (this.mediaRecoveries < Le) {
1416
+ if (this.mediaRecoveries < Fe) {
1406
1417
  this.mediaRecoveries += 1, n.recoverMediaError();
1407
1418
  return;
1408
1419
  }
@@ -1426,19 +1437,19 @@ var U = class {
1426
1437
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1427
1438
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1428
1439
  }
1429
- }, rt = 15e3, it = 100, W = 1, at = 1e3, G = 3e4, ot = 1e3, st = {
1440
+ }, tt = 15e3, nt = 6e5, rt = 3e5, it = 100, J = 1, at = 1e3, ot = 3e4, st = 1e3, ct = {
1430
1441
  inline: "PRESENTATION_INLINE",
1431
1442
  fullscreen: "PRESENTATION_FULLSCREEN",
1432
1443
  pip: "PRESENTATION_PIP"
1433
- }, ct = {
1444
+ }, lt = {
1434
1445
  widevine: "KEY_SYSTEM_WIDEVINE",
1435
1446
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1436
1447
  none: "KEY_SYSTEM_NONE"
1437
1448
  };
1438
- function K(e, t) {
1449
+ function ut(e, t) {
1439
1450
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1440
1451
  }
1441
- var lt = /* @__PURE__ */ new Set([
1452
+ var dt = /* @__PURE__ */ new Set([
1442
1453
  "INVALID_URN",
1443
1454
  "NOT_FOUND",
1444
1455
  "GONE",
@@ -1448,7 +1459,7 @@ var lt = /* @__PURE__ */ new Set([
1448
1459
  "FORBIDDEN",
1449
1460
  "RATE_LIMITED",
1450
1461
  "TIMEOUT"
1451
- ]), q = {
1462
+ ]), Y = {
1452
1463
  idle: "PLAYER_STATE_IDLE",
1453
1464
  waiting: "PLAYER_STATE_WAITING",
1454
1465
  loading: "PLAYER_STATE_LOADING",
@@ -1458,7 +1469,7 @@ var lt = /* @__PURE__ */ new Set([
1458
1469
  ended: "PLAYER_STATE_ENDED",
1459
1470
  error: "PLAYER_STATE_ERROR"
1460
1471
  };
1461
- function ut(e) {
1472
+ function ft(e) {
1462
1473
  try {
1463
1474
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1464
1475
  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);
@@ -1466,7 +1477,7 @@ function ut(e) {
1466
1477
  return;
1467
1478
  }
1468
1479
  }
1469
- var dt = class {
1480
+ var pt = class {
1470
1481
  opts;
1471
1482
  url;
1472
1483
  now;
@@ -1526,19 +1537,26 @@ var dt = class {
1526
1537
  lastRequestErrors = 0;
1527
1538
  pendingStart = null;
1528
1539
  firstFlushTimer = null;
1540
+ idleTimer = null;
1541
+ lastTickMs = 0;
1529
1542
  bornMs;
1530
1543
  startupAnchorMs;
1531
1544
  startupTimeMs = 0;
1532
1545
  manifestLoadMs = 0;
1533
1546
  firstFragLoadMs = 0;
1534
1547
  onPagehide = () => this.end("END_REASON_PAGEHIDE");
1548
+ onFreeze = () => {
1549
+ this.endedFlag || this.flush(!0);
1550
+ };
1551
+ onResume = () => this.checkSuspension(this.now());
1535
1552
  onVisibility = () => {
1536
1553
  typeof document > "u" || (document.visibilityState === "hidden" ? (this.hiddenSinceMs === null && (this.hiddenSinceMs = this.now()), this.isHidden = !0) : (this.hiddenSinceMs !== null && (this.hiddenTotalMs += this.now() - this.hiddenSinceMs, this.hiddenSinceMs = null), this.isHidden = !1), this.syncActive(), this.syncBuffering());
1537
1554
  };
1538
1555
  constructor(e) {
1539
1556
  this.opts = {
1540
1557
  ...e,
1541
- heartbeatMs: e.heartbeatMs ?? rt
1558
+ heartbeatMs: e.heartbeatMs ?? tt,
1559
+ idleMs: e.idleMs ?? nt
1542
1560
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1543
1561
  }
1544
1562
  start() {
@@ -1548,42 +1566,55 @@ var dt = class {
1548
1566
  sdkVersion: this.opts.sdkVersion,
1549
1567
  ...this.opts.environment
1550
1568
  };
1551
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), at), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), this.onVisibility());
1569
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), at), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
1570
+ }
1571
+ checkSuspension(e) {
1572
+ if (this.endedFlag || !this.opts.idleMs) return !1;
1573
+ let t = Math.max(this.opts.idleMs, rt);
1574
+ return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1575
+ }
1576
+ syncIdle(e) {
1577
+ e === "paused" && this.opts.idleMs ? this.idleTimer === null && (this.idleTimer = setTimeout(() => {
1578
+ this.idleTimer = null, this.endIdle();
1579
+ }, this.opts.idleMs)) : this.idleTimer !== null && (clearTimeout(this.idleTimer), this.idleTimer = null);
1580
+ }
1581
+ endIdle(e) {
1582
+ this.endedFlag || (this.end("END_REASON_IDLE", e), this.opts.onIdle?.());
1552
1583
  }
1553
1584
  noteStateChange(e, t, n, r) {
1554
1585
  if (this.endedFlag || e === t) return;
1555
1586
  let i = this.now();
1556
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(W, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(W, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1587
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(J, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(J, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1557
1588
  this.stallIsSeekInduced = this.seekInduced(i);
1558
1589
  let e = !this.isHidden && !this.stallIsSeekInduced;
1559
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(W, Math.round(this.playingTotalMs)));
1590
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(J, Math.round(this.playingTotalMs)));
1560
1591
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1561
- this.syncBuffering(), t === "paused" && (this.pauseCount += 1);
1592
+ this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1562
1593
  let a = {
1563
- fromState: q[e] ?? "PLAYER_STATE_UNSPECIFIED",
1564
- toState: q[t] ?? "PLAYER_STATE_UNSPECIFIED",
1565
- presentation: st[this.presentation]
1594
+ fromState: Y[e] ?? "PLAYER_STATE_UNSPECIFIED",
1595
+ toState: Y[t] ?? "PLAYER_STATE_UNSPECIFIED",
1596
+ presentation: ct[this.presentation]
1566
1597
  }, o = this.causeOf(e, t, i);
1567
1598
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1568
1599
  }
1569
1600
  seekInduced(e) {
1570
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < ot;
1601
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < st;
1571
1602
  }
1572
1603
  causeOf(e, t, n) {
1573
1604
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
1574
1605
  if (t === "buffering") return this.seekInduced(n) ? "TRANSITION_CAUSE_SEEK" : "TRANSITION_CAUSE_NETWORK_STALL";
1575
1606
  if (t === "paused" || t === "playing" && e === "paused") return "TRANSITION_CAUSE_USER";
1576
1607
  }
1577
- syncActive() {
1578
- let e = this.isPlaying && !this.isHidden && !this.isMuted;
1579
- e && this.activeSinceMs === null ? this.activeSinceMs = this.now() : !e && this.activeSinceMs !== null && (this.activeTotalMs += this.now() - this.activeSinceMs, this.activeSinceMs = null);
1608
+ syncActive(e = this.now()) {
1609
+ let t = this.isPlaying && !this.isHidden && !this.isMuted;
1610
+ t && this.activeSinceMs === null ? this.activeSinceMs = e : !t && this.activeSinceMs !== null && (this.activeTotalMs += e - this.activeSinceMs, this.activeSinceMs = null);
1580
1611
  }
1581
1612
  syncBuffering() {
1582
1613
  let e = this.isBuffering && !this.isHidden && !this.stallIsSeekInduced;
1583
1614
  e && this.bufferingSinceMs === null ? this.bufferingSinceMs = this.now() : !e && this.bufferingSinceMs !== null && (this.rebufferTotalMs += this.now() - this.bufferingSinceMs, this.bufferingSinceMs = null);
1584
1615
  }
1585
- closePresentation() {
1586
- let e = this.now(), t = e - this.presentationSinceMs;
1616
+ closePresentation(e = this.now()) {
1617
+ let t = e - this.presentationSinceMs;
1587
1618
  this.presentation === "fullscreen" ? this.fullscreenTotalMs += t : this.presentation === "pip" && (this.pipTotalMs += t), this.presentationSinceMs = e;
1588
1619
  }
1589
1620
  noteAutoplay(e) {
@@ -1604,19 +1635,19 @@ var dt = class {
1604
1635
  }
1605
1636
  this.muteChanges += 1;
1606
1637
  let r = this.now();
1607
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(W, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1638
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(J, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1608
1639
  }
1609
1640
  notePresentation(e) {
1610
1641
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1611
1642
  }
1612
1643
  notePlayIntent() {
1613
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = W), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = W));
1644
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = J), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = J));
1614
1645
  }
1615
1646
  noteReady() {
1616
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(W, this.now() - this.startupAnchorMs));
1647
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
1617
1648
  }
1618
1649
  noteFirstBytes() {
1619
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(W, this.now() - this.startupAnchorMs));
1650
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
1620
1651
  }
1621
1652
  noteSeek() {
1622
1653
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -1635,7 +1666,7 @@ var dt = class {
1635
1666
  let r = n ?? "";
1636
1667
  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";
1637
1668
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
1638
- if (lt.has(e)) return "ERROR_STAGE_RESOLVE";
1669
+ if (dt.has(e)) return "ERROR_STAGE_RESOLVE";
1639
1670
  let i = t ?? "";
1640
1671
  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";
1641
1672
  }
@@ -1650,66 +1681,68 @@ var dt = class {
1650
1681
  }
1651
1682
  heartbeat() {
1652
1683
  if (this.endedFlag) return;
1653
- let e = this.opts.sample(), t = this.now(), n = this.playingTotalMs;
1654
- this.playingSinceMs !== null && (n += t - this.playingSinceMs);
1684
+ let e = this.now();
1685
+ if (this.checkSuspension(e)) return;
1686
+ let t = this.opts.sample(), n = this.playingTotalMs;
1687
+ this.playingSinceMs !== null && (n += e - this.playingSinceMs);
1655
1688
  let r = this.hiddenTotalMs;
1656
- this.hiddenSinceMs !== null && (r += t - this.hiddenSinceMs);
1689
+ this.hiddenSinceMs !== null && (r += e - this.hiddenSinceMs);
1657
1690
  let i = this.rebufferTotalMs;
1658
- this.bufferingSinceMs !== null && (i += t - this.bufferingSinceMs);
1691
+ this.bufferingSinceMs !== null && (i += e - this.bufferingSinceMs);
1659
1692
  let a = this.activeTotalMs;
1660
- this.activeSinceMs !== null && (a += t - this.activeSinceMs);
1661
- let o = {}, s = e.bytesLoaded ?? 0;
1693
+ this.activeSinceMs !== null && (a += e - this.activeSinceMs);
1694
+ let o = {}, s = t.bytesLoaded ?? 0;
1662
1695
  s > this.lastBytes && (o.bytesDownloadedDelta = s - this.lastBytes), this.lastBytes = s;
1663
- let c = e.playlistBytesLoaded ?? 0;
1696
+ let c = t.playlistBytesLoaded ?? 0;
1664
1697
  c > this.lastPlaylistBytes && (o.playlistBytesDelta = c - this.lastPlaylistBytes), this.lastPlaylistBytes = c;
1665
- let l = e.droppedFrames ?? 0;
1698
+ let l = t.droppedFrames ?? 0;
1666
1699
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
1667
- let u = e.renditionSwitches ?? 0;
1668
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof e.latencySeconds == "number" && (o.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (o.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (o.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof e.bufferedMs == "number" && e.bufferedMs > 0 && (o.bufferedMs = Math.round(e.bufferedMs)), o.playerState = q[e.state] ?? "PLAYER_STATE_UNSPECIFIED";
1700
+ let u = t.renditionSwitches ?? 0;
1701
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = Y[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
1669
1702
  let d = this.mutedTotalMs;
1670
- this.mutedSinceMs !== null && (d += t - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
1671
- let f = e.upshifts ?? 0;
1703
+ this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
1704
+ let f = t.upshifts ?? 0;
1672
1705
  f > this.lastUpshifts && (o.upshiftsDelta = f - this.lastUpshifts), this.lastUpshifts = f;
1673
- let p = e.downshifts ?? 0;
1706
+ let p = t.downshifts ?? 0;
1674
1707
  p > this.lastDownshifts && (o.downshiftsDelta = p - this.lastDownshifts), this.lastDownshifts = p;
1675
- let m = e.decodedFrames ?? 0;
1708
+ let m = t.decodedFrames ?? 0;
1676
1709
  m > this.lastDecoded && (o.decodedFramesDelta = m - this.lastDecoded), this.lastDecoded = m;
1677
- let h = e.requestErrors ?? 0;
1710
+ let h = t.requestErrors ?? 0;
1678
1711
  h > this.lastRequestErrors && (o.requestErrorsDelta = h - this.lastRequestErrors), this.lastRequestErrors = h;
1679
- let g = e.requestCount ?? 0, _ = g - this.lastRequestCount;
1712
+ let g = t.requestCount ?? 0, _ = g - this.lastRequestCount;
1680
1713
  if (this.lastRequestCount = g, _ > 0) {
1681
1714
  o.requestCountDelta = _;
1682
- let t = e.requestTimesMs ?? [], n = t.slice(Math.max(0, t.length - _)).sort((e, t) => e - t);
1683
- n.length > 0 && (o.requestTimeP50Ms = K(n, 50), o.requestTimeP95Ms = K(n, 95));
1715
+ let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
1716
+ n.length > 0 && (o.requestTimeP50Ms = ut(n, 50), o.requestTimeP95Ms = ut(n, 95));
1684
1717
  }
1685
- typeof e.latencySeconds == "number" && typeof e.targetLatencySeconds == "number" && (o.driftMs = Math.round((e.latencySeconds - e.targetLatencySeconds) * 1e3)), typeof e.playbackRate == "number" && e.playbackRate > 0 && (o.playbackRate = e.playbackRate), e.qualityPinned === !0 && (o.qualityPinned = !0), e.cdnHost && (o.cdnHost = e.cdnHost), this.maybeEmitMediaInfo(e), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
1718
+ 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();
1686
1719
  }
1687
1720
  maybeEmitMediaInfo(e) {
1688
1721
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
1689
1722
  let t = {};
1690
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ct[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);
1723
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = lt[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);
1691
1724
  let n = JSON.stringify(t);
1692
1725
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
1693
1726
  }
1694
- end(e) {
1727
+ end(e, t) {
1695
1728
  if (this.endedFlag) return;
1696
1729
  this.endedFlag = !0;
1697
- let t = this.now();
1698
- this.playingSinceMs !== null && (this.playingTotalMs += t - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += t - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += t - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += t - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += t - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(), this.closePresentation(), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && document.removeEventListener("visibilitychange", this.onVisibility);
1699
- let n = this.safeSample();
1700
- n && this.maybeEmitMediaInfo(n);
1701
- let r = { reason: e }, i = n?.bytesLoaded ?? this.lastBytes;
1702
- i > 0 && (r.bytesDownloadedTotal = i), this.playingTotalMs > 0 && (r.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (r.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (r.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (r.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (r.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstFragLoadMs > 0 && (r.firstFragLoadMs = Math.round(this.firstFragLoadMs));
1703
- let a = n?.licenseTimeMs ?? 0;
1704
- a > 0 && (r.licenseTimeMs = Math.round(a));
1705
- let o = n?.droppedFrames ?? this.lastDropped;
1706
- o > 0 && (r.droppedFramesTotal = o), this.errorCount > 0 && (r.errorCount = this.errorCount), this.hiddenTotalMs > 0 && (r.hiddenTimeMs = Math.round(this.hiddenTotalMs)), this.seekCount > 0 && (r.seekCount = this.seekCount), this.pauseCount > 0 && (r.pauseCount = this.pauseCount), this.firstAudioMs > 0 && (r.firstAudioMs = Math.round(this.firstAudioMs)), this.waitingTotalMs > 0 && (r.waitingForLiveMs = Math.round(this.waitingTotalMs)), this.timeToFirstStallMs > 0 && (r.timeToFirstStallMs = Math.round(this.timeToFirstStallMs));
1707
- let s = n?.positionMs ?? 0;
1708
- s > 0 && (r.exitPositionMs = Math.round(s)), this.activeTotalMs > 0 && (r.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (r.mutedTimeMs = Math.round(this.mutedTotalMs));
1709
- let c = e !== "END_REASON_ENDED";
1710
- c && this.lastStallMs > 0 && t - this.lastStallMs <= G && (r.abandonAfterStallMs = Math.max(W, Math.round(t - this.lastStallMs))), c && this.lastErrorMs > 0 && t - this.lastErrorMs <= G && (r.abandonAfterErrorMs = Math.max(W, Math.round(t - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (r.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (r.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (r.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (r.muteChanges = this.muteChanges);
1711
- let l = n?.decodedFrames ?? this.lastDecoded;
1712
- l > 0 && (r.decodedFramesTotal = l), this.startupTimeMs === 0 && (r.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: r })), this.flush(e === "END_REASON_PAGEHIDE");
1730
+ let n = t ?? this.now();
1731
+ this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
1732
+ let r = this.safeSample();
1733
+ r && this.maybeEmitMediaInfo(r);
1734
+ let i = { reason: e }, a = r?.bytesLoaded ?? this.lastBytes;
1735
+ a > 0 && (i.bytesDownloadedTotal = a), this.playingTotalMs > 0 && (i.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (i.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (i.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (i.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (i.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstFragLoadMs > 0 && (i.firstFragLoadMs = Math.round(this.firstFragLoadMs));
1736
+ let o = r?.licenseTimeMs ?? 0;
1737
+ o > 0 && (i.licenseTimeMs = Math.round(o));
1738
+ let s = r?.droppedFrames ?? this.lastDropped;
1739
+ s > 0 && (i.droppedFramesTotal = s), this.errorCount > 0 && (i.errorCount = this.errorCount), this.hiddenTotalMs > 0 && (i.hiddenTimeMs = Math.round(this.hiddenTotalMs)), this.seekCount > 0 && (i.seekCount = this.seekCount), this.pauseCount > 0 && (i.pauseCount = this.pauseCount), this.firstAudioMs > 0 && (i.firstAudioMs = Math.round(this.firstAudioMs)), this.waitingTotalMs > 0 && (i.waitingForLiveMs = Math.round(this.waitingTotalMs)), this.timeToFirstStallMs > 0 && (i.timeToFirstStallMs = Math.round(this.timeToFirstStallMs));
1740
+ let c = r?.positionMs ?? 0;
1741
+ 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));
1742
+ let l = e !== "END_REASON_ENDED";
1743
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= ot && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= ot && (i.abandonAfterErrorMs = Math.max(J, 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);
1744
+ let u = r?.decodedFrames ?? this.lastDecoded;
1745
+ u > 0 && (i.decodedFramesTotal = u), this.startupTimeMs === 0 && (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");
1713
1746
  }
1714
1747
  safeSample() {
1715
1748
  try {
@@ -1750,7 +1783,7 @@ var dt = class {
1750
1783
  };
1751
1784
  //#endregion
1752
1785
  //#region src/core/environment.ts
1753
- function ft() {
1786
+ function mt() {
1754
1787
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
1755
1788
  let e;
1756
1789
  try {
@@ -1775,14 +1808,14 @@ function ft() {
1775
1808
  integration: "INTEGRATION_KIND_IFRAME"
1776
1809
  };
1777
1810
  }
1778
- function pt() {
1811
+ function ht() {
1779
1812
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
1780
1813
  let e = navigator.userAgentData, t = e?.platform ?? "";
1781
1814
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
1782
1815
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
1783
1816
  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";
1784
1817
  }
1785
- function mt() {
1818
+ function gt() {
1786
1819
  let e = typeof navigator < "u" ? navigator.connection : void 0;
1787
1820
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
1788
1821
  let t = {
@@ -1801,17 +1834,17 @@ function mt() {
1801
1834
  }
1802
1835
  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;
1803
1836
  }
1804
- function ht(e) {
1805
- let t = ft(), n = {
1806
- deviceClass: pt(),
1837
+ function _t(e) {
1838
+ let t = mt(), n = {
1839
+ deviceClass: ht(),
1807
1840
  integration: t.integration,
1808
- ...mt()
1841
+ ...gt()
1809
1842
  };
1810
1843
  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);
1811
1844
  let r = e.getBoundingClientRect?.();
1812
1845
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
1813
1846
  }
1814
- async function gt() {
1847
+ async function vt() {
1815
1848
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
1816
1849
  if (!e?.getHighEntropyValues) return {};
1817
1850
  try {
@@ -1823,7 +1856,7 @@ async function gt() {
1823
1856
  }
1824
1857
  //#endregion
1825
1858
  //#region src/core/version.ts
1826
- var _t = "2.6.4", J = {
1859
+ var yt = "2.8.0", bt = {
1827
1860
  accent: "#E1B600",
1828
1861
  accentText: "#1B1C23",
1829
1862
  background: "#0e0f13",
@@ -1834,7 +1867,7 @@ var _t = "2.6.4", J = {
1834
1867
  border: "rgba(255, 255, 255, 0.1)",
1835
1868
  radius: "8px",
1836
1869
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1837
- }, Y = {
1870
+ }, xt = {
1838
1871
  accent: "--havik-accent",
1839
1872
  accentText: "--havik-accent-text",
1840
1873
  background: "--havik-bg",
@@ -1846,25 +1879,25 @@ var _t = "2.6.4", J = {
1846
1879
  radius: "--havik-radius",
1847
1880
  fontFamily: "--havik-font"
1848
1881
  };
1849
- function X(e, t) {
1882
+ function St(e, t) {
1850
1883
  let n = {
1851
- ...J,
1884
+ ...bt,
1852
1885
  ...t
1853
1886
  };
1854
- for (let t of Object.keys(Y)) e.style.setProperty(Y[t], n[t]);
1887
+ for (let t of Object.keys(xt)) e.style.setProperty(xt[t], n[t]);
1855
1888
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1856
1889
  }
1857
1890
  //#endregion
1858
1891
  //#region src/ui/styles.ts
1859
- var Z = "havik-player-styles", vt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{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";
1860
- function yt(e = document) {
1861
- if (e.getElementById(Z)) return;
1892
+ var Ct = "havik-player-styles", wt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{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";
1893
+ function Tt(e = document) {
1894
+ if (e.getElementById(Ct)) return;
1862
1895
  let t = e.createElement("style");
1863
- t.id = Z, t.textContent = vt, e.head.appendChild(t);
1896
+ t.id = Ct, t.textContent = wt, e.head.appendChild(t);
1864
1897
  }
1865
1898
  //#endregion
1866
1899
  //#region src/ui/icons.ts
1867
- var bt = {
1900
+ var Et = {
1868
1901
  play: "<path d=\"M8 5v14l11-7z\"/>",
1869
1902
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1870
1903
  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\"/>",
@@ -1877,21 +1910,21 @@ var bt = {
1877
1910
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
1878
1911
  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\"/>"
1879
1912
  };
1880
- function Q(e) {
1881
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${bt[e]}</svg>`;
1913
+ function X(e) {
1914
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Et[e]}</svg>`;
1882
1915
  }
1883
1916
  //#endregion
1884
1917
  //#region src/ui/controls.ts
1885
- var xt = 3e3, St = /* @__PURE__ */ new Set([
1918
+ var Dt = 3e3, Ot = /* @__PURE__ */ new Set([
1886
1919
  "GONE",
1887
1920
  "NOT_FOUND",
1888
1921
  "INVALID_URN",
1889
1922
  "UNAUTHORIZED"
1890
1923
  ]);
1891
- function Ct(e) {
1892
- return new wt(e);
1924
+ function kt(e) {
1925
+ return new At(e);
1893
1926
  }
1894
- var wt = class {
1927
+ var At = class {
1895
1928
  root;
1896
1929
  video;
1897
1930
  player;
@@ -1933,7 +1966,7 @@ var wt = class {
1933
1966
  scrubbing = !1;
1934
1967
  offFns = [];
1935
1968
  constructor(e) {
1936
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? xt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, yt(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1969
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Dt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Tt(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1937
1970
  let t = (e, t, n) => {
1938
1971
  let r = this.doc.createElement(e);
1939
1972
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1944,12 +1977,12 @@ var wt = class {
1944
1977
  "aria-label": r,
1945
1978
  title: r
1946
1979
  });
1947
- return i.innerHTML = Q(n), i;
1980
+ return i.innerHTML = X(n), i;
1948
1981
  };
1949
1982
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
1950
1983
  type: "button",
1951
1984
  "aria-label": "Play"
1952
- }), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
1985
+ }), this.center.innerHTML = X("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
1953
1986
  role: "slider",
1954
1987
  "aria-label": "Seek",
1955
1988
  "aria-valuemin": "0",
@@ -1967,7 +2000,7 @@ var wt = class {
1967
2000
  "aria-label": "Volume"
1968
2001
  });
1969
2002
  let a = t("div", "havik-vol");
1970
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
2003
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = X("liveDot");
1971
2004
  let o = this.doc.createElement("span");
1972
2005
  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";
1973
2006
  let s = t("div", "havik-spacer");
@@ -2021,12 +2054,12 @@ var wt = class {
2021
2054
  }
2022
2055
  if (e === "preplay") {
2023
2056
  let e = this.doc.createElement("button");
2024
- 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);
2057
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = X("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2025
2058
  } else {
2026
2059
  let r = this.doc.createElement("div");
2027
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !St.has(this.lastError.code)) {
2060
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Ot.has(this.lastError.code)) {
2028
2061
  let e = this.doc.createElement("button");
2029
- 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);
2062
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${X("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2030
2063
  }
2031
2064
  }
2032
2065
  this.root.append(n), this.statusBox = n, this.show();
@@ -2065,7 +2098,7 @@ var wt = class {
2065
2098
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2066
2099
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2067
2100
  }
2068
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Tt(this.video.currentTime)} / ${Tt(this.video.duration)}`);
2101
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${jt(this.video.currentTime)} / ${jt(this.video.duration)}`);
2069
2102
  }
2070
2103
  syncLive() {
2071
2104
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2115,17 +2148,17 @@ var wt = class {
2115
2148
  renderQualityMenu() {
2116
2149
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2117
2150
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2118
- for (let n of e) this.menu.append(this.menuItem(Et(n), t === n.index, () => this.player.setQuality(n.index)));
2151
+ for (let n of e) this.menu.append(this.menuItem(Mt(n), t === n.index, () => this.player.setQuality(n.index)));
2119
2152
  }
2120
2153
  renderAudioMenu() {
2121
2154
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2122
2155
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2123
- for (let t of e) this.menu.append(this.menuItem(Dt(t), t.default, () => this.player.setAudioTrack(t.id)));
2156
+ for (let t of e) this.menu.append(this.menuItem(Nt(t), t.default, () => this.player.setAudioTrack(t.id)));
2124
2157
  }
2125
2158
  renderCcMenu() {
2126
2159
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2127
2160
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2128
- for (let t of e) this.menu.append(this.menuItem(Ot(t), !1, () => this.player.setTextTrack(t.id)));
2161
+ for (let t of e) this.menu.append(this.menuItem(Pt(t), !1, () => this.player.setTextTrack(t.id)));
2129
2162
  }
2130
2163
  onTracksChanged() {
2131
2164
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2208,7 +2241,7 @@ var wt = class {
2208
2241
  }
2209
2242
  }
2210
2243
  setIcon(e, t) {
2211
- e.innerHTML = Q(t);
2244
+ e.innerHTML = X(t);
2212
2245
  }
2213
2246
  destroy() {
2214
2247
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2225,32 +2258,41 @@ var wt = class {
2225
2258
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2226
2259
  }
2227
2260
  };
2228
- function Tt(e) {
2261
+ function jt(e) {
2229
2262
  (!Number.isFinite(e) || e < 0) && (e = 0);
2230
2263
  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");
2231
2264
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2232
2265
  }
2233
- function Et(e) {
2266
+ function Mt(e) {
2234
2267
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2235
2268
  }
2236
- function Dt(e) {
2269
+ function Nt(e) {
2237
2270
  return e.name || e.lang || `Track ${e.id}`;
2238
2271
  }
2239
- function Ot(e) {
2272
+ function Pt(e) {
2240
2273
  return e.name || e.lang || `Track ${e.id}`;
2241
2274
  }
2242
2275
  //#endregion
2243
2276
  //#region src/managed/index.ts
2244
- var kt = 6e3, At = 45e3, jt = 2e3, Mt = 3, Nt = 2e3, Pt = 48e4;
2245
- async function Ft(e) {
2277
+ var Ft = 6e3, Z = 45e3, It = 2e3, Lt = 3, Rt = 2e3, zt = 48e4;
2278
+ function Bt(e) {
2279
+ 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)})`);
2280
+ if (e.env !== void 0) return z(e.env);
2281
+ if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2282
+ return e.baseUrl;
2283
+ }
2284
+ async function Q(e) {
2246
2285
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2247
- if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
2286
+ let t = Bt(e);
2248
2287
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2249
2288
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2250
- let t = new It(e);
2251
- return await t.start(), t;
2289
+ let r = new Vt({
2290
+ ...e,
2291
+ baseUrl: t
2292
+ });
2293
+ return await r.start(), r;
2252
2294
  }
2253
- var It = class {
2295
+ var Vt = class {
2254
2296
  opts;
2255
2297
  abort = new AbortController();
2256
2298
  listeners = {};
@@ -2276,6 +2318,7 @@ var It = class {
2276
2318
  analyticsSession = null;
2277
2319
  detachMediaListeners;
2278
2320
  playRequested = !1;
2321
+ idleClosed = !1;
2279
2322
  pendingStartLoad = !1;
2280
2323
  constructor(e) {
2281
2324
  this.opts = e;
@@ -2293,7 +2336,7 @@ var It = class {
2293
2336
  this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
2294
2337
  let e = ++this.loadGen, t = this.resolveOptions();
2295
2338
  try {
2296
- let n = await v(t);
2339
+ let n = await y(t);
2297
2340
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2298
2341
  let e = this._lastError;
2299
2342
  throw this.destroy(), e;
@@ -2320,7 +2363,7 @@ var It = class {
2320
2363
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2321
2364
  }
2322
2365
  beginArmingByPolling(e) {
2323
- y({
2366
+ b({
2324
2367
  ...this.resolveOptions(),
2325
2368
  signal: this.abort.signal,
2326
2369
  waitForLive: this.buildWaitConfig(e)
@@ -2337,7 +2380,7 @@ var It = class {
2337
2380
  setTimeout(() => {
2338
2381
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2339
2382
  phase: i ? "unavailable" : "tooEarly",
2340
- retryInMs: At,
2383
+ retryInMs: Z,
2341
2384
  attempt: 1,
2342
2385
  elapsedMs: 0,
2343
2386
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2354,7 +2397,7 @@ var It = class {
2354
2397
  }
2355
2398
  }
2356
2399
  }, h = () => {
2357
- a || s || p() || (s = !0, y({
2400
+ a || s || p() || (s = !0, b({
2358
2401
  ...this.resolveOptions(),
2359
2402
  signal: c.signal,
2360
2403
  waitForLive: this.buildWaitConfig(e)
@@ -2362,7 +2405,7 @@ var It = class {
2362
2405
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
2363
2406
  }));
2364
2407
  }, g = () => {
2365
- a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2408
+ a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2366
2409
  if (!(a || p())) {
2367
2410
  if (e instanceof n && o(e.code)) {
2368
2411
  h();
@@ -2376,13 +2419,13 @@ var It = class {
2376
2419
  !a && !p() && h();
2377
2420
  }, e);
2378
2421
  };
2379
- _(kt), this.armingSub = E({
2422
+ _(Ft), this.armingSub = E({
2380
2423
  eventsBaseUrl: t,
2381
2424
  matchUrn: this.opts.matchUrn,
2382
2425
  credential: this.opts.credential,
2383
- onAlive: () => _(At),
2426
+ onAlive: () => _(Z),
2384
2427
  onState: (e) => {
2385
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * jt);
2428
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * It);
2386
2429
  },
2387
2430
  onError: () => h()
2388
2431
  });
@@ -2405,7 +2448,7 @@ var It = class {
2405
2448
  let n = await s(this.opts.credential);
2406
2449
  if (this.destroyed || t !== this.loadGen) return;
2407
2450
  this.setState("loading");
2408
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ne(this.opts.video, (e) => {
2451
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = je(this.opts.video, (e) => {
2409
2452
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2410
2453
  });
2411
2454
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2420,20 +2463,25 @@ var It = class {
2420
2463
  this.destroyed || t !== this.loadGen || this.engine !== i || (this.analyticsSession?.noteReady(), this.emit("ready"));
2421
2464
  }, 0));
2422
2465
  }
2466
+ onAnalyticsIdle(e) {
2467
+ this.destroyed || this.engine !== e || (this.idleClosed = !0, this.pendingStartLoad = !1, e.stop());
2468
+ }
2423
2469
  startAnalytics(e, t) {
2424
2470
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2425
2471
  let n = e.analytics?.sid;
2426
2472
  if (!n) return;
2427
- let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ut(this.opts.baseUrl);
2473
+ let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ft(this.opts.baseUrl);
2428
2474
  if (!r) return;
2429
- let i = this.opts.video, a = new dt({
2475
+ let i = this.opts.video, a = new pt({
2430
2476
  endpoint: r,
2431
2477
  sid: n,
2432
2478
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2433
- sdkVersion: _t,
2434
- environment: ht(i),
2479
+ sdkVersion: yt,
2480
+ environment: _t(i),
2481
+ idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2482
+ onIdle: () => this.onAnalyticsIdle(t),
2435
2483
  sample: () => {
2436
- let e = this.engine?.getStats() ?? I, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
2484
+ let e = this.engine?.getStats() ?? B, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
2437
2485
  return {
2438
2486
  ...e,
2439
2487
  bufferedMs: Math.round(t * 1e3),
@@ -2447,7 +2495,7 @@ var It = class {
2447
2495
  let o = () => a.noteSeek(), s = () => a.noteVolume(i.muted, i.volume);
2448
2496
  i.addEventListener("seeking", o), i.addEventListener("volumechange", s), this.detachMediaListeners = () => {
2449
2497
  i.removeEventListener("seeking", o), i.removeEventListener("volumechange", s);
2450
- }, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), gt().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2498
+ }, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), vt().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2451
2499
  }
2452
2500
  currentPresentation() {
2453
2501
  let e = this.opts.video;
@@ -2471,11 +2519,11 @@ var It = class {
2471
2519
  hlsConfig: i,
2472
2520
  emit: (e) => this.onEngineEvent(e)
2473
2521
  }, o = this.opts.engine ?? "auto";
2474
- if (o === "native") return new V(a);
2475
- if (o === "hls") return new U(a);
2476
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && z(this.opts.video) && B()) return new V(a);
2477
- if (Ie()) return new U(a);
2478
- if (z(this.opts.video)) return new V(a);
2522
+ if (o === "native") return new G(a);
2523
+ if (o === "hls") return new q(a);
2524
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && U(this.opts.video) && W()) return new G(a);
2525
+ if (Pe()) return new q(a);
2526
+ if (U(this.opts.video)) return new G(a);
2479
2527
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2480
2528
  }
2481
2529
  onEngineEvent(e) {
@@ -2518,7 +2566,7 @@ var It = class {
2518
2566
  r = 0, i = !1;
2519
2567
  },
2520
2568
  onError: () => {
2521
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Mt && (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.`))));
2569
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Lt && (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.`))));
2522
2570
  }
2523
2571
  });
2524
2572
  }
@@ -2540,7 +2588,7 @@ var It = class {
2540
2588
  scheduleRejoin(e) {
2541
2589
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2542
2590
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2543
- }, Math.random() * jt));
2591
+ }, Math.random() * It));
2544
2592
  }
2545
2593
  cancelRejoin() {
2546
2594
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2550,7 +2598,7 @@ var It = class {
2550
2598
  this.teardownPlayback(), this.setState("waiting"), this.beginArming(e, void 0, !0);
2551
2599
  }
2552
2600
  teardownPlayback() {
2553
- this.stopStats(), this.stopRefresh(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null, this.pendingStartLoad = !1;
2601
+ this.stopStats(), this.stopRefresh(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null, this.pendingStartLoad = !1, this.idleClosed = !1;
2554
2602
  }
2555
2603
  mountControls() {
2556
2604
  let e = this.opts.controls ?? "custom", t = this.opts.video;
@@ -2564,7 +2612,7 @@ var It = class {
2564
2612
  }
2565
2613
  t.controls = !1;
2566
2614
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2567
- r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar = Ct({
2615
+ r && r.insertBefore(n, t), n.appendChild(t), St(n, this.opts.theme), this.container = n, this.controlBar = kt({
2568
2616
  root: n,
2569
2617
  video: t,
2570
2618
  player: this,
@@ -2594,7 +2642,7 @@ var It = class {
2594
2642
  }
2595
2643
  startStats() {
2596
2644
  this.stopStats();
2597
- let e = Math.max(500, this.opts.statsIntervalMs ?? Nt);
2645
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Rt);
2598
2646
  this.statsTimer = setInterval(() => {
2599
2647
  if (!this.engine) return;
2600
2648
  let e = this.engine.getStats();
@@ -2606,7 +2654,7 @@ var It = class {
2606
2654
  }
2607
2655
  scheduleLicenseRefresh() {
2608
2656
  this.stopRefresh();
2609
- let e = this.opts.licenseRefreshMs ?? Pt;
2657
+ let e = this.opts.licenseRefreshMs ?? zt;
2610
2658
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2611
2659
  }
2612
2660
  stopRefresh() {
@@ -2615,7 +2663,7 @@ var It = class {
2615
2663
  async refreshLicense() {
2616
2664
  let e = this.engine;
2617
2665
  if (!this.destroyed && e) try {
2618
- let t = await v(this.resolveOptions());
2666
+ let t = await y(this.resolveOptions());
2619
2667
  if (this.destroyed || this.engine !== e) return;
2620
2668
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
2621
2669
  (n || r) && (e.setLicenseUrls({
@@ -2629,7 +2677,10 @@ var It = class {
2629
2677
  async play() {
2630
2678
  if (this.destroyed) return;
2631
2679
  let e = !this.playRequested;
2632
- this.playRequested = !0;
2680
+ if (this.playRequested = !0, this.idleClosed && this._state !== "ended" && this._state !== "error") {
2681
+ this.idleClosed = !1, await this.reload();
2682
+ return;
2683
+ }
2633
2684
  let t = this.pendingStartLoad && this._state !== "ended" && this._state !== "error";
2634
2685
  this.opts.autoplay === !1 && this.analyticsSession?.notePlayIntent(), t && (this.pendingStartLoad = !1, this.setState("loading"), this.engine?.startLoad());
2635
2686
  try {
@@ -2648,7 +2699,7 @@ var It = class {
2648
2699
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
2649
2700
  }
2650
2701
  getStats() {
2651
- return this.engine?.getStats() ?? I;
2702
+ return this.engine?.getStats() ?? B;
2652
2703
  }
2653
2704
  getQualityLevels() {
2654
2705
  return this.engine?.getQualityLevels() ?? [];
@@ -2700,7 +2751,7 @@ var It = class {
2700
2751
  let e = ++this.loadGen;
2701
2752
  this.teardownPlayback();
2702
2753
  try {
2703
- let t = await y({
2754
+ let t = await b({
2704
2755
  ...this.resolveOptions(),
2705
2756
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
2706
2757
  });
@@ -2758,7 +2809,7 @@ function $(e) {
2758
2809
  }
2759
2810
  //#endregion
2760
2811
  //#region src/embed/host.ts
2761
- function Lt(e) {
2812
+ function Ht(e) {
2762
2813
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2763
2814
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2764
2815
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2817,8 +2868,8 @@ function Lt(e) {
2817
2868
  }
2818
2869
  //#endregion
2819
2870
  //#region src/embed/page.ts
2820
- var Rt = /^[A-Za-z0-9:_.-]{1,128}$/;
2821
- function zt() {
2871
+ var Ut = /^[A-Za-z0-9:_.-]{1,128}$/;
2872
+ function Wt() {
2822
2873
  let e = window.HAVIK_EMBED_CONFIG;
2823
2874
  if (e) return {
2824
2875
  baseUrl: e.baseUrl ?? "",
@@ -2840,9 +2891,9 @@ function zt() {
2840
2891
  waitForLive: !0
2841
2892
  };
2842
2893
  }
2843
- async function Bt() {
2844
- let e = zt();
2845
- Ht();
2894
+ async function Gt() {
2895
+ let e = Wt();
2896
+ qt();
2846
2897
  let t = document.createElement("video");
2847
2898
  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);
2848
2899
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2897,12 +2948,12 @@ async function Bt() {
2897
2948
  code: e.code,
2898
2949
  message: e.message
2899
2950
  })), e.on("autoplayblocked", () => {
2900
- i({ type: "oddin:autoplayblocked" }), Vt(t, e);
2951
+ i({ type: "oddin:autoplayblocked" }), Kt(t, e);
2901
2952
  });
2902
2953
  }, s = async (r) => {
2903
2954
  a?.destroy(), a = null;
2904
2955
  try {
2905
- let n = await Ft({
2956
+ let n = await Q({
2906
2957
  video: t,
2907
2958
  baseUrl: e.baseUrl,
2908
2959
  matchUrn: r,
@@ -2963,7 +3014,7 @@ async function Bt() {
2963
3014
  a?.retry();
2964
3015
  break;
2965
3016
  case "oddin:load":
2966
- typeof e.matchUrn == "string" && Rt.test(e.matchUrn) && s(e.matchUrn);
3017
+ typeof e.matchUrn == "string" && Ut.test(e.matchUrn) && s(e.matchUrn);
2967
3018
  break;
2968
3019
  case "oddin:destroy": c();
2969
3020
  }
@@ -2975,18 +3026,18 @@ async function Bt() {
2975
3026
  protocol: 1
2976
3027
  });
2977
3028
  }
2978
- function Vt(e, t) {
3029
+ function Kt(e, t) {
2979
3030
  if (document.getElementById("havik-tap")) return;
2980
3031
  let n = document.createElement("button");
2981
3032
  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", () => {
2982
3033
  n.remove(), t.play();
2983
3034
  }), document.body.appendChild(n);
2984
3035
  }
2985
- function Ht() {
3036
+ function qt() {
2986
3037
  let e = document.createElement("style");
2987
3038
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
2988
3039
  }
2989
3040
  //#endregion
2990
- export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme, Bt as bootEmbed, _e as clearDeviceId, Ft as createPlayer, D as deriveEventsBaseUrl, Oe as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, Ae as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, Lt as mountEmbed, oe as pollToLive, y as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
3041
+ export { bt as ODDIN_THEME, n as PlaybackError, St as applyTheme, z as baseUrlForEnv, Gt as bootEmbed, _e as clearDeviceId, Q as createPlayer, D as deriveEventsBaseUrl, Ee as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, Oe as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, Ht as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
2991
3042
 
2992
3043
  //# sourceMappingURL=index.js.map