@oddin-gg/havik-player 2.26.1 → 2.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -315,25 +315,25 @@ function x(e) {
315
315
  function _e(e) {
316
316
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
317
317
  }
318
- function S(e, t) {
318
+ function ve(e, t) {
319
319
  let n = _e(x(e));
320
320
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
321
321
  }
322
- function C(e, t) {
322
+ function S(e, t) {
323
323
  let n = t ?? e, r = x(e);
324
324
  if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
325
325
  if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
326
326
  let i = e;
327
327
  return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
328
328
  }
329
- async function w(e, t) {
329
+ async function C(e, t) {
330
330
  let n = t ?? e;
331
331
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
332
332
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
333
333
  let r = e;
334
334
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
335
335
  }
336
- async function T(e, t) {
336
+ async function w(e, t) {
337
337
  let n = e;
338
338
  if (n.webkitDisplayingFullscreen) {
339
339
  n.webkitExitFullscreen?.();
@@ -344,7 +344,7 @@ async function T(e, t) {
344
344
  }
345
345
  //#endregion
346
346
  //#region src/core/catalog.ts
347
- async function ve(e) {
347
+ async function ye(e) {
348
348
  let t = new URLSearchParams();
349
349
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
350
350
  let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -362,12 +362,12 @@ async function ve(e) {
362
362
  };
363
363
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
364
364
  return {
365
- tournaments: ye(await s.json()),
365
+ tournaments: be(await s.json()),
366
366
  etag: s.headers.get("etag") ?? void 0,
367
367
  notModified: !1
368
368
  };
369
369
  }
370
- function ye(e) {
370
+ function be(e) {
371
371
  return (e.tournaments ?? []).map((e) => {
372
372
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
373
373
  return {
@@ -389,7 +389,7 @@ function ye(e) {
389
389
  };
390
390
  });
391
391
  }
392
- async function be(e) {
392
+ async function xe(e) {
393
393
  let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
394
394
  e.etag && i.set("If-None-Match", e.etag);
395
395
  let a = await m(t, {
@@ -409,13 +409,13 @@ async function be(e) {
409
409
  };
410
410
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
411
411
  return {
412
- tournament: xe(await a.json()),
412
+ tournament: Se(await a.json()),
413
413
  etag: a.headers.get("etag") ?? void 0,
414
414
  notModified: !1,
415
415
  notFound: !1
416
416
  };
417
417
  }
418
- function xe(e) {
418
+ function Se(e) {
419
419
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
420
420
  return {
421
421
  urn: t,
@@ -435,18 +435,18 @@ function xe(e) {
435
435
  }))
436
436
  };
437
437
  }
438
- function Se(e) {
438
+ function Ce(e) {
439
439
  return e.tournaments.flatMap((e) => e.matches);
440
440
  }
441
441
  //#endregion
442
442
  //#region src/core/poll.ts
443
- var Ce = /* @__PURE__ */ new Set([
443
+ var we = /* @__PURE__ */ new Set([
444
444
  "NOT_FOUND",
445
445
  "GEO_DENIED",
446
446
  "GONE",
447
447
  "INVALID_URN"
448
448
  ]);
449
- function we(e) {
449
+ function Te(e) {
450
450
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, c = !1, d = () => {
451
451
  c || (a = setTimeout(p, t));
452
452
  }, p = async () => {
@@ -479,7 +479,7 @@ function we(e) {
479
479
  } catch (t) {
480
480
  if (!i.signal.aborted) {
481
481
  let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
482
- Ce.has(r.code) && (c = !0), e.onError?.(r);
482
+ we.has(r.code) && (c = !0), e.onError?.(r);
483
483
  }
484
484
  } finally {
485
485
  d();
@@ -491,16 +491,16 @@ function we(e) {
491
491
  }
492
492
  //#endregion
493
493
  //#region src/core/events.ts
494
- var Te = 45e3, E = class extends Error {
494
+ var Ee = 45e3, T = class extends Error {
495
495
  status;
496
496
  terminal;
497
497
  constructor(e) {
498
498
  let t = e === 410;
499
499
  super(t ? `live-state subscribe failed: HTTP ${e} — match is gone, not retrying` : e === 404 ? `live-state subscribe failed: HTTP ${e} — match not in the catalog, retrying slowly` : `live-state subscribe failed: HTTP ${e}`), this.name = "LiveStateHttpError", this.status = e, this.terminal = t;
500
500
  }
501
- }, Ee = 3e5;
502
- function D(e) {
503
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? Ee), i = e.idleTimeoutMs ?? Te, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
501
+ }, De = 3e5;
502
+ function E(e) {
503
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? De), i = e.idleTimeoutMs ?? Ee, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
504
504
  if (o.signal.aborted) return t();
505
505
  let n = setTimeout(t, e);
506
506
  o.signal.addEventListener("abort", () => {
@@ -567,7 +567,7 @@ function D(e) {
567
567
  });
568
568
  if (clearTimeout(_), s) return;
569
569
  if (!o.ok || !o.body) {
570
- let t = new E(o.status);
570
+ let t = new T(o.status);
571
571
  h = t.terminal, g = o.status === 404, e.onError?.(t);
572
572
  } else await p(o.body, () => {
573
573
  i = t;
@@ -585,7 +585,7 @@ function D(e) {
585
585
  s || (s = !0, o.abort());
586
586
  } };
587
587
  }
588
- function O(e) {
588
+ function D(e) {
589
589
  try {
590
590
  let t = new URL(e);
591
591
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -595,27 +595,27 @@ function O(e) {
595
595
  }
596
596
  //#endregion
597
597
  //#region src/core/drm/deviceId.ts
598
- var De = "havik.player.deviceId", k;
599
- function Oe() {
598
+ var O = "havik.player.deviceId", k;
599
+ function A() {
600
600
  if (k) return k;
601
601
  try {
602
- let e = globalThis.localStorage?.getItem(De);
602
+ let e = globalThis.localStorage?.getItem(O);
603
603
  if (e) return k = e, e;
604
604
  } catch {}
605
- let e = Ae();
605
+ let e = ke();
606
606
  k = e;
607
607
  try {
608
- globalThis.localStorage?.setItem(De, e);
608
+ globalThis.localStorage?.setItem(O, e);
609
609
  } catch {}
610
610
  return e;
611
611
  }
612
- function ke() {
612
+ function Oe() {
613
613
  k = void 0;
614
614
  try {
615
- globalThis.localStorage?.removeItem(De);
615
+ globalThis.localStorage?.removeItem(O);
616
616
  } catch {}
617
617
  }
618
- function Ae() {
618
+ function ke() {
619
619
  let e = globalThis.crypto;
620
620
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
621
621
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -627,32 +627,32 @@ function Ae() {
627
627
  }
628
628
  //#endregion
629
629
  //#region src/core/drm/headers.ts
630
- function je(e, t, n = {}) {
630
+ function Ae(e, t, n = {}) {
631
631
  let r = {
632
632
  "x-api-key": t.apiKey,
633
633
  "X-Match-Urn": e.matchUrn,
634
- "X-Device-Id": n.deviceId ?? Oe(),
634
+ "X-Device-Id": n.deviceId ?? A(),
635
635
  "Content-Type": "application/octet-stream"
636
636
  };
637
637
  return n.userId && (r["X-User-Id"] = n.userId), r;
638
638
  }
639
639
  //#endregion
640
640
  //#region src/core/bandwidthMemory.ts
641
- var Me = "havik.player.bandwidth", Ne = .8, Pe = 2e7, Fe = 3e5;
642
- function Ie() {
641
+ var j = "havik.player.bandwidth", je = .8, Me = 2e7, Ne = 3e5;
642
+ function Pe() {
643
643
  return globalThis.navigator?.connection;
644
644
  }
645
- function Le() {
646
- let e = Ie()?.type;
645
+ function Fe() {
646
+ let e = Pe()?.type;
647
647
  return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
648
648
  }
649
- function Re() {
650
- let e = Ie()?.downlink;
649
+ function Ie() {
650
+ let e = Pe()?.downlink;
651
651
  return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
652
652
  }
653
- function ze() {
653
+ function Le() {
654
654
  try {
655
- let e = globalThis.localStorage?.getItem(Me);
655
+ let e = globalThis.localStorage?.getItem(j);
656
656
  if (!e) return {};
657
657
  let t = JSON.parse(e);
658
658
  return t && typeof t == "object" && !Array.isArray(t) ? t : {};
@@ -660,36 +660,36 @@ function ze() {
660
660
  return {};
661
661
  }
662
662
  }
663
- function Be(e = Date.now()) {
664
- let t = ze()[Le()];
663
+ function Re(e = Date.now()) {
664
+ let t = Le()[Fe()];
665
665
  if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
666
666
  let n = e - t.at;
667
667
  if (n < 0 || n > 2592e5) return;
668
- let r = Re(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
669
- return Math.round(Math.min(Pe, Math.max(Fe, i * Ne)));
668
+ let r = Ie(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
669
+ return Math.round(Math.min(Me, Math.max(Ne, i * je)));
670
670
  }
671
- function Ve(e, t = Date.now()) {
671
+ function ze(e, t = Date.now()) {
672
672
  if (!Number.isFinite(e) || e <= 0) return;
673
- let n = ze();
674
- n[Le()] = {
673
+ let n = Le();
674
+ n[Fe()] = {
675
675
  bps: Math.round(e),
676
676
  at: t
677
677
  };
678
678
  try {
679
- globalThis.localStorage?.setItem(Me, JSON.stringify(n));
679
+ globalThis.localStorage?.setItem(j, JSON.stringify(n));
680
680
  } catch {}
681
681
  }
682
- function He() {
682
+ function Be() {
683
683
  try {
684
- globalThis.localStorage?.removeItem(Me);
684
+ globalThis.localStorage?.removeItem(j);
685
685
  } catch {}
686
686
  }
687
687
  //#endregion
688
688
  //#region src/core/drm/cdm.ts
689
- var Ue = /* @__PURE__ */ new WeakMap();
690
- function We(e, t) {
691
- let n = Ue.get(e);
692
- n || (n = /* @__PURE__ */ new Map(), Ue.set(e, n));
689
+ var Ve = /* @__PURE__ */ new WeakMap();
690
+ function He(e, t) {
691
+ let n = Ve.get(e);
692
+ n || (n = /* @__PURE__ */ new Map(), Ve.set(e, n));
693
693
  let r = n.get(t.keySystem);
694
694
  if (r) return r;
695
695
  let i = t.createMediaKeys().catch((e) => {
@@ -697,22 +697,22 @@ function We(e, t) {
697
697
  });
698
698
  return n.set(t.keySystem, i), i;
699
699
  }
700
- function A() {
700
+ function M() {
701
701
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
702
702
  }
703
- var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
704
- function Ge(e) {
703
+ var Ue = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
704
+ function We(e) {
705
705
  return e.startsWith("com.widevine");
706
706
  }
707
- function M(e, t) {
708
- if (!Ge(e)) return t;
707
+ function Ge(e, t) {
708
+ if (!We(e)) return t;
709
709
  let n = (e, t) => {
710
710
  let n = e.videoCapabilities;
711
711
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
712
- let n = j.indexOf(e.robustness);
713
- return n === -1 || j.indexOf(t) > n;
712
+ let n = Ue.indexOf(e.robustness);
713
+ return n === -1 || Ue.indexOf(t) > n;
714
714
  });
715
- }, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
715
+ }, r = Ue.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
716
716
  ...t,
717
717
  videoCapabilities: t.videoCapabilities?.map((t) => ({
718
718
  ...t,
@@ -722,10 +722,10 @@ function M(e, t) {
722
722
  return [...t, ...r];
723
723
  }
724
724
  function Ke(e) {
725
- return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
725
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Ge(t, n)).then((t) => ({
726
726
  keySystem: t.keySystem,
727
727
  getConfiguration: () => t.getConfiguration(),
728
- createMediaKeys: () => We(e, t)
728
+ createMediaKeys: () => He(e, t)
729
729
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
730
730
  }
731
731
  var N = {
@@ -734,7 +734,7 @@ var N = {
734
734
  scheme: "cbcs"
735
735
  };
736
736
  function qe(e) {
737
- if (!A()) return;
737
+ if (!M()) return;
738
738
  let t = (e, t) => ({
739
739
  contentType: e,
740
740
  robustness: t,
@@ -781,7 +781,7 @@ function Xe(e) {
781
781
  }]
782
782
  }, i = (async () => {
783
783
  try {
784
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
784
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", Ge("com.widevine.alpha", [r])), !0;
785
785
  } catch {
786
786
  return !1;
787
787
  }
@@ -789,7 +789,7 @@ function Xe(e) {
789
789
  return Ye.set(t, i), i;
790
790
  }
791
791
  function Ze() {
792
- if (A()) for (let e of Object.values(Je)) Xe(e);
792
+ if (M()) for (let e of Object.values(Je)) Xe(e);
793
793
  }
794
794
  function Qe(e) {
795
795
  let t = P(e);
@@ -818,7 +818,7 @@ function rt(e) {
818
818
  robustness: "",
819
819
  encryptionScheme: "cbcs"
820
820
  }]
821
- }] : M("com.widevine.alpha", [{
821
+ }] : Ge("com.widevine.alpha", [{
822
822
  initDataTypes: ["cenc"],
823
823
  videoCapabilities: [{
824
824
  contentType: et,
@@ -975,26 +975,36 @@ var ht = class {
975
975
  this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
976
976
  };
977
977
  }
978
- };
979
- function gt(e, t) {
980
- let n = [
981
- ["playing", () => t("playing")],
982
- ["waiting", () => t("buffering")],
983
- ["stalled", () => t("buffering")],
978
+ }, gt = .25;
979
+ function _t(e, t) {
980
+ let n = null, r = (r) => {
981
+ n = r === "buffering" ? e.currentTime : null, t(r);
982
+ }, i = [
983
+ ["playing", () => r("playing")],
984
+ ["waiting", () => r("buffering")],
985
+ ["stalled", () => {
986
+ !e.paused && e.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && r("buffering");
987
+ }],
988
+ ["seeked", () => {
989
+ n !== null && (n = e.currentTime);
990
+ }],
991
+ ["timeupdate", () => {
992
+ n !== null && !e.paused && !e.seeking && e.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA && e.currentTime - n >= gt && r("playing");
993
+ }],
984
994
  ["pause", () => {
985
- e.ended || t("paused");
995
+ e.ended || r("paused");
986
996
  }],
987
- ["ended", () => t("ended")]
997
+ ["ended", () => r("ended")]
988
998
  ];
989
- for (let [t, r] of n) e.addEventListener(t, r);
999
+ for (let [t, n] of i) e.addEventListener(t, n);
990
1000
  return () => {
991
- for (let [t, r] of n) e.removeEventListener(t, r);
1001
+ for (let [t, n] of i) e.removeEventListener(t, n);
992
1002
  };
993
1003
  }
994
1004
  //#endregion
995
1005
  //#region src/core/engine/native.ts
996
- var _t = 2e3, vt = 3, z = 500, yt = 6e3, bt = .25, xt = 250, St = .05, Ct = 4, wt = 12e3, Tt = .25, Et = 1e3;
997
- function Dt(e) {
1006
+ var vt = 2e3, yt = 3, z = 500, bt = 6e3, xt = .25, St = 250, Ct = .05, wt = 4, Tt = 12e3, Et = .25, Dt = 1e3;
1007
+ function Ot(e) {
998
1008
  try {
999
1009
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
1000
1010
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -1010,7 +1020,7 @@ function V() {
1010
1020
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
1011
1021
  return e || t;
1012
1022
  }
1013
- function Ot() {
1023
+ function kt() {
1014
1024
  if (typeof navigator > "u" || !V()) return !1;
1015
1025
  let e = navigator.userAgent ?? "";
1016
1026
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -1066,7 +1076,7 @@ var H = class {
1066
1076
  type: "error",
1067
1077
  error: L() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
1068
1078
  fatal: !0
1069
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = At(t.manifestUrl, t.analytics?.sid), e.load();
1079
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = jt(t.manifestUrl, t.analytics?.sid), e.load();
1070
1080
  }
1071
1081
  startLoad() {
1072
1082
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -1094,7 +1104,7 @@ var H = class {
1094
1104
  };
1095
1105
  this.onEncrypted = (n) => {
1096
1106
  let a = n;
1097
- a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Dt(a.initData), (async () => {
1107
+ a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ot(a.initData), (async () => {
1098
1108
  try {
1099
1109
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
1100
1110
  initDataTypes: [a.initDataType],
@@ -1197,7 +1207,7 @@ var H = class {
1197
1207
  if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1198
1208
  n.isLive = !0;
1199
1209
  let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1200
- Number.isFinite(r) && (n.atLiveEdge = r <= Ct, !e.paused && r >= 0 && (n.latencySeconds = r));
1210
+ Number.isFinite(r) && (n.atLiveEdge = r <= wt, !e.paused && r >= 0 && (n.latencySeconds = r));
1201
1211
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1202
1212
  return n;
1203
1213
  }
@@ -1215,7 +1225,7 @@ var H = class {
1215
1225
  return;
1216
1226
  }
1217
1227
  let t = this.hiddenSince;
1218
- this.hiddenSince = null, t != null && e - t >= _t && this.armRefocus();
1228
+ this.hiddenSince = null, t != null && e - t >= vt && this.armRefocus();
1219
1229
  }, this.onPageShow = (e) => {
1220
1230
  e.persisted && this.armRefocus();
1221
1231
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
@@ -1225,7 +1235,7 @@ var H = class {
1225
1235
  let e = this.liveEnd(), t = U, n = t(), r = 0, i = () => {
1226
1236
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1227
1237
  r += z;
1228
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + bt), s = Math.max(r, t() - n) >= yt;
1238
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + xt), s = Math.max(r, t() - n) >= bt;
1229
1239
  if (o || s && a != null) {
1230
1240
  this.snapToLive();
1231
1241
  return;
@@ -1245,9 +1255,9 @@ var H = class {
1245
1255
  }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1246
1256
  if (e.duration !== Infinity) return;
1247
1257
  this.checkEndStale();
1248
- let t = kt(e, e.currentTime);
1249
- t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= St) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
1250
- }, xt);
1258
+ let t = At(e, e.currentTime);
1259
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= Ct) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
1260
+ }, St);
1251
1261
  }
1252
1262
  checkEndStale() {
1253
1263
  if (this.endedEmitted) return;
@@ -1255,14 +1265,14 @@ var H = class {
1255
1265
  this.lastTickAt = e;
1256
1266
  let n = this.liveEnd();
1257
1267
  if (n == null) return;
1258
- let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Tt;
1268
+ let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Et;
1259
1269
  this.lastSeekableEnd = n;
1260
1270
  let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
1261
- if (r || t > Et || a || i.paused) {
1271
+ if (r || t > Dt || a || i.paused) {
1262
1272
  this.edgeStampedAt = e;
1263
1273
  return;
1264
1274
  }
1265
- e - (this.edgeStampedAt ?? e) > wt && (this.endedEmitted = !0, this.deps.emit({
1275
+ e - (this.edgeStampedAt ?? e) > Tt && (this.endedEmitted = !0, this.deps.emit({
1266
1276
  type: "ended",
1267
1277
  reason: "stalled"
1268
1278
  }));
@@ -1276,7 +1286,7 @@ var H = class {
1276
1286
  liveEdgeEstimate() {
1277
1287
  let e = this.deps.video;
1278
1288
  if (e.duration !== Infinity) return null;
1279
- let t = this.liveEnd(), n = kt(e, e.currentTime) ?? this.lastBufferedEnd;
1289
+ let t = this.liveEnd(), n = At(e, e.currentTime) ?? this.lastBufferedEnd;
1280
1290
  if (n != null) {
1281
1291
  let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (U() - e) / 1e3));
1282
1292
  (t == null || r > t) && (t = r);
@@ -1292,7 +1302,7 @@ var H = class {
1292
1302
  snapToLive() {
1293
1303
  let e = this.deps.video, t = this.liveEnd();
1294
1304
  if (t == null) return;
1295
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - vt, r);
1305
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - yt, r);
1296
1306
  try {
1297
1307
  e.currentTime = i;
1298
1308
  } catch {}
@@ -1313,7 +1323,7 @@ var H = class {
1313
1323
  function U() {
1314
1324
  return typeof performance < "u" ? performance.now() : Date.now();
1315
1325
  }
1316
- function kt(e, t) {
1326
+ function At(e, t) {
1317
1327
  let n = e.buffered;
1318
1328
  if (!n || !Number.isFinite(t)) return null;
1319
1329
  for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
@@ -1322,7 +1332,7 @@ function kt(e, t) {
1322
1332
  }
1323
1333
  return null;
1324
1334
  }
1325
- function At(e, t) {
1335
+ function jt(e, t) {
1326
1336
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1327
1337
  }
1328
1338
  //#endregion
@@ -1339,13 +1349,13 @@ function W(e, t = Date.now()) {
1339
1349
  }
1340
1350
  //#endregion
1341
1351
  //#region src/core/drm/xhrBody.ts
1342
- var jt = 4096;
1343
- function Mt(e) {
1352
+ var Mt = 4096;
1353
+ function Nt(e) {
1344
1354
  if (!e || typeof e != "object") return;
1345
1355
  let { response: t } = e;
1346
1356
  if (typeof t == "string") return t;
1347
1357
  let n;
1348
- if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > jt)) try {
1358
+ if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Mt)) try {
1349
1359
  return new TextDecoder().decode(n);
1350
1360
  } catch {
1351
1361
  return;
@@ -1353,7 +1363,7 @@ function Mt(e) {
1353
1363
  }
1354
1364
  //#endregion
1355
1365
  //#region src/core/engine/prefetch.ts
1356
- var Nt = 15e3, Pt = 5e3, Ft = 6, It = 4e3, Lt = 2;
1366
+ var Pt = 15e3, Ft = 5e3, It = 6, Lt = 4e3, Rt = 2;
1357
1367
  function G(e) {
1358
1368
  try {
1359
1369
  let t = new URL(e);
@@ -1362,7 +1372,7 @@ function G(e) {
1362
1372
  return e;
1363
1373
  }
1364
1374
  }
1365
- var Rt = class {
1375
+ var zt = class {
1366
1376
  cmcd;
1367
1377
  entries = /* @__PURE__ */ new Map();
1368
1378
  keyed = /* @__PURE__ */ new Set();
@@ -1394,17 +1404,17 @@ var Rt = class {
1394
1404
  let r = G(e);
1395
1405
  if (this.entries.has(r)) return;
1396
1406
  let i = this.perTrack.get(t) ?? 0;
1397
- i >= Ft || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Nt), this.stats.started += 1);
1407
+ i >= It || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Pt), this.stats.started += 1);
1398
1408
  }
1399
1409
  prefetchHint(e, t) {
1400
1410
  let n = G(e);
1401
1411
  if (this.entries.has(n)) return;
1402
1412
  let r = this.hints.get(t) ?? [];
1403
- for (; r.length >= Lt;) {
1413
+ for (; r.length >= Rt;) {
1404
1414
  let e = r.shift();
1405
1415
  e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
1406
1416
  }
1407
- r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, It), this.stats.hintStarted += 1;
1417
+ r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Lt), this.stats.hintStarted += 1;
1408
1418
  }
1409
1419
  dropHints(e) {
1410
1420
  for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
@@ -1457,14 +1467,14 @@ var Rt = class {
1457
1467
  }
1458
1468
  }
1459
1469
  };
1460
- function zt(t, n) {
1470
+ function Bt(t, n) {
1461
1471
  let r = typeof n == "function" ? n : e.DefaultConfig?.loader;
1462
1472
  if (typeof r != "function") return;
1463
1473
  class i extends r {
1464
1474
  served = !1;
1465
1475
  cancelled = !1;
1466
1476
  entry;
1467
- stats = Bt();
1477
+ stats = Vt();
1468
1478
  load(e, n, r) {
1469
1479
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1470
1480
  if (!i) {
@@ -1476,7 +1486,7 @@ function zt(t, n) {
1476
1486
  i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
1477
1487
  }, s = () => {
1478
1488
  !this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
1479
- }, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Pt, u = setTimeout(s, l);
1489
+ }, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Ft, u = setTimeout(s, l);
1480
1490
  i.headers.then(() => {
1481
1491
  clearTimeout(u);
1482
1492
  let e = c?.maxLoadTimeMs;
@@ -1509,7 +1519,7 @@ function zt(t, n) {
1509
1519
  }
1510
1520
  return i;
1511
1521
  }
1512
- function Bt() {
1522
+ function Vt() {
1513
1523
  return {
1514
1524
  aborted: !1,
1515
1525
  loaded: 0,
@@ -1533,10 +1543,10 @@ function Bt() {
1533
1543
  }
1534
1544
  };
1535
1545
  }
1536
- function Vt(e) {
1546
+ function Ht(e) {
1537
1547
  return e === "audio" ? "audio" : "main";
1538
1548
  }
1539
- function Ht(e, t) {
1549
+ function Ut(e, t) {
1540
1550
  let n = [];
1541
1551
  t.initSegment?.url && !t.initSegment.data && n.push({
1542
1552
  url: t.initSegment.url,
@@ -1553,7 +1563,7 @@ function Ht(e, t) {
1553
1563
  });
1554
1564
  return n;
1555
1565
  }
1556
- function Ut(e) {
1566
+ function Wt(e) {
1557
1567
  let t = e, n = t?.preloadHint;
1558
1568
  if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
1559
1569
  let r = n.URI;
@@ -1571,10 +1581,15 @@ function K(e, t) {
1571
1581
  }
1572
1582
  //#endregion
1573
1583
  //#region src/core/engine/hls.ts
1574
- function Wt() {
1584
+ function Gt() {
1575
1585
  return e.isSupported();
1576
1586
  }
1577
- var Gt = 3, Kt = 1e6, qt = 20, Jt = 1e4, Yt = 3, Xt = 5, Zt = 3, Qt = 1e4, $t = 3e4, en = 12e3, tn = 3e3, nn = .02, rn = 6e3, an = .5, on = 3, sn = .5, cn = 1.1, ln = .25, un = 5e3, dn = 4e3, fn = 2, pn = 5, mn = 2, hn = 2, gn = 4, _n = 4, vn = 2e3, yn = 3e4, bn = 1, xn = 2, Sn = .5, Cn = .6, wn = 2, Tn = 1.5, En = 1e4, q = 8, Dn = 12e4, On = 6e4;
1587
+ var Kt = 3, qt = 1e6, Jt = 20, Yt = 1e4, Xt = 3, Zt = 5, Qt = 3, $t = 1e4, en = 3e4, tn = 12e3, nn = 3e3, rn = .02, an = 6e3, on = .5, sn = 3, cn = .5, ln = 1.1, un = .25, dn = 5e3, fn = 4e3, pn = 2, mn = 5, hn = 2, gn = 2, _n = 4, vn = 4, yn = 2e3, bn = 3e4, xn = 1, Sn = 2, Cn = .5, wn = .6, Tn = 2, En = 1.5, Dn = 1e4, On = 18e4, kn = .5, An = 2;
1588
+ function jn(e) {
1589
+ let t = e.config ?? {};
1590
+ return t.capLevelToPlayerSize === !0 || t.capLevelOnFPSDrop === !0;
1591
+ }
1592
+ var q = 8, Mn = 12e4, Nn = 6e4;
1578
1593
  function J(e, t, n) {
1579
1594
  if (n <= 0 || t < 0 || t >= e.length) return t;
1580
1595
  let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
@@ -1587,11 +1602,11 @@ function J(e, t, n) {
1587
1602
  function Y() {
1588
1603
  return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
1589
1604
  }
1590
- var kn = .2, An = 30, jn = 2, Mn = 2, Nn = 2, Pn = 9, Fn = .5, In = 64, Ln = 1e4, Rn = 8, zn = .6, Bn = .4, Vn = .4, Hn = 2, Un = 6e4, X = .5, Wn = 3.5, Gn = 300;
1591
- function Kn(e) {
1605
+ var Pn = .2, Fn = 30, In = 2, Ln = 2, Rn = 2, zn = 9, Bn = .5, Vn = 64, Hn = 1e4, Un = 8, Wn = .6, Gn = .4, Kn = .4, qn = 2, Jn = 6e4, X = .5, Yn = 3.5, Xn = 300;
1606
+ function Z(e) {
1592
1607
  return (e?.part ?? e?.frag)?.stats;
1593
1608
  }
1594
- function qn() {
1609
+ function Zn() {
1595
1610
  if (typeof navigator > "u") return 0;
1596
1611
  try {
1597
1612
  let e = navigator.connection?.rtt;
@@ -1600,20 +1615,20 @@ function qn() {
1600
1615
  return 0;
1601
1616
  }
1602
1617
  }
1603
- function Jn(e) {
1618
+ function Qn(e) {
1604
1619
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1605
1620
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1606
1621
  return;
1607
1622
  }
1608
- e.liveSyncDuration ??= Nn;
1609
- let t = Math.max(12, e.liveSyncDuration + Pn);
1610
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Yn(e, e.liveSyncDuration);
1623
+ e.liveSyncDuration ??= Rn;
1624
+ let t = Math.max(12, e.liveSyncDuration + zn);
1625
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), $n(e, e.liveSyncDuration);
1611
1626
  }
1612
- function Yn(e, t) {
1627
+ function $n(e, t) {
1613
1628
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1614
1629
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1615
1630
  }
1616
- var Xn = class {
1631
+ var er = class {
1617
1632
  name = "hls";
1618
1633
  hls = null;
1619
1634
  deps;
@@ -1702,6 +1717,11 @@ var Xn = class {
1702
1717
  pushedCapLevel = -1;
1703
1718
  pushedCapReason = null;
1704
1719
  fpsCapBitrate = null;
1720
+ stallCapBitrate = null;
1721
+ stallCapSince = 0;
1722
+ stallCapTickAt = 0;
1723
+ stallDownCaps = 0;
1724
+ stallCapEnabled;
1705
1725
  fpsCapFailedHeight = null;
1706
1726
  fpsCapManaged = !0;
1707
1727
  fpsLastFrames = -1;
@@ -1716,7 +1736,7 @@ var Xn = class {
1716
1736
  frameCounter;
1717
1737
  detachFrames = null;
1718
1738
  constructor(e) {
1719
- this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ht(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1739
+ this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.stallCapEnabled = e.stallCap !== !1, this.frameCounter = new ht(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1720
1740
  }
1721
1741
  async load() {
1722
1742
  this.detachFrames ??= this.frameCounter.attach();
@@ -1761,7 +1781,7 @@ var Xn = class {
1761
1781
  }
1762
1782
  this.loadSuspended = !0;
1763
1783
  }
1764
- }, un));
1784
+ }, dn));
1765
1785
  }
1766
1786
  resumeLoading() {
1767
1787
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1793,7 +1813,7 @@ var Xn = class {
1793
1813
  let t = e.liveSyncPosition;
1794
1814
  if (typeof t != "number" || !Number.isFinite(t)) return;
1795
1815
  let { video: n } = this.deps;
1796
- n.currentTime <= t + Fn || (n.currentTime = t);
1816
+ n.currentTime <= t + Bn || (n.currentTime = t);
1797
1817
  }
1798
1818
  reanchorPartTimeline(e, t) {
1799
1819
  let { frag: n, part: r } = t;
@@ -1805,7 +1825,7 @@ var Xn = class {
1805
1825
  let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1806
1826
  if (!s) return;
1807
1827
  let c = a.startPTS - s.start;
1808
- if (!(!Number.isFinite(c) || Math.abs(c) < nn)) {
1828
+ if (!(!Number.isFinite(c) || Math.abs(c) < rn)) {
1809
1829
  for (let e of i.fragments) e && e.setStart(e.start + c);
1810
1830
  i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
1811
1831
  }
@@ -1833,7 +1853,7 @@ var Xn = class {
1833
1853
  videoEncryptionScheme: N.scheme,
1834
1854
  audioEncryptionScheme: N.scheme
1835
1855
  },
1836
- ...A() ? { requestMediaKeySystemAccessFunc: Ke(t) } : {},
1856
+ ...M() ? { requestMediaKeySystemAccessFunc: Ke(t) } : {},
1837
1857
  licenseXhrSetup: (e, t) => {
1838
1858
  let o = performance.now(), s = () => {
1839
1859
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
@@ -1845,7 +1865,7 @@ var Xn = class {
1845
1865
  return;
1846
1866
  }
1847
1867
  let l = this.hls, u, d = new Promise((e) => {
1848
- u = setTimeout(() => e(void 0), Qt);
1868
+ u = setTimeout(() => e(void 0), $t);
1849
1869
  });
1850
1870
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1851
1871
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1863,28 +1883,28 @@ var Xn = class {
1863
1883
  this.prefetch?.destroy(), this.prefetch = null;
1864
1884
  let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints !== !1;
1865
1885
  if ((h || g) && !f.fLoader) {
1866
- let e = new Rt({
1886
+ let e = new zt({
1867
1887
  sessionId: n.analytics?.sid,
1868
1888
  contentId: n.matchUrn
1869
- }), t = zt(e, f.loader);
1889
+ }), t = Bt(e, f.loader);
1870
1890
  t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
1871
1891
  }
1872
- Jn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1892
+ Qn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1873
1893
  let _ = new e(f);
1874
1894
  if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
1875
1895
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1876
1896
  }), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
1877
1897
  t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1878
1898
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1879
- }, $t)));
1899
+ }, en)));
1880
1900
  }), _.on(e.Events.FRAG_LOADING, (e, t) => {
1881
1901
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1882
1902
  }), _.on(e.Events.FRAG_LOADED, (e, t) => {
1883
1903
  t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
1884
- let n = t?.frag, r = Kn(t), i = r?.loaded;
1904
+ let n = t?.frag, r = Z(t), i = r?.loaded;
1885
1905
  typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1886
1906
  let a = r?.loading;
1887
- a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > In && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
1907
+ a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Vn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
1888
1908
  let o = n?.url;
1889
1909
  if (o) {
1890
1910
  let e = ft(o);
@@ -1904,8 +1924,8 @@ var Xn = class {
1904
1924
  let i = e;
1905
1925
  if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
1906
1926
  let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
1907
- if (i.edge - o > Gt * (i.partTarget || .5)) return;
1908
- let s = Ut(e);
1927
+ if (i.edge - o > Kt * (i.partTarget || .5)) return;
1928
+ let s = Wt(e);
1909
1929
  s && t.prefetchHint(s, r);
1910
1930
  };
1911
1931
  _.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1917,15 +1937,15 @@ var Xn = class {
1917
1937
  if (this.prefetch && p) {
1918
1938
  let t = this.prefetch;
1919
1939
  _.on(e.Events.KEY_LOADING, (e, n) => {
1920
- let r = n?.frag, i = Vt(r?.type);
1921
- if (r && t.isActive(i)) for (let e of Ht(_, r)) t.prefetch(e.url, i, e.kind);
1922
- }), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Vt(n?.frag?.type)));
1940
+ let r = n?.frag, i = Ht(r?.type);
1941
+ if (r && t.isActive(i)) for (let e of Ut(_, r)) t.prefetch(e.url, i, e.kind);
1942
+ }), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Ht(n?.frag?.type)));
1923
1943
  }
1924
1944
  _.on(e.Events.KEY_LOADED, () => {
1925
1945
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1926
1946
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1927
- this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.checkFrameDrops();
1928
- }, tn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1947
+ this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.releaseStallCap(), this.checkFrameDrops();
1948
+ }, nn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1929
1949
  this.renditionSwitches += 1;
1930
1950
  let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
1931
1951
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
@@ -1986,8 +2006,8 @@ var Xn = class {
1986
2006
  let e = this.hls, t = this.sizeCapCover();
1987
2007
  if (!e || !t) return null;
1988
2008
  let { cover: n, deviceRatio: r } = t, i = this.deps.sizeCapHeadroom, a = i == null || Number.isNaN(i);
1989
- if (a && r >= xn) return n;
1990
- if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, bn) : n;
2009
+ if (a && r >= Sn) return n;
2010
+ if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, xn) : n;
1991
2011
  let o = i === Infinity ? e.levels.length : Math.max(0, Math.floor(i));
1992
2012
  return J(e.levels, n, o);
1993
2013
  }
@@ -2004,11 +2024,11 @@ var Xn = class {
2004
2024
  return;
2005
2025
  }
2006
2026
  this.capTimer && clearTimeout(this.capTimer);
2007
- let t = e > this.sizeCapLevel ? vn : yn;
2027
+ let t = e > this.sizeCapLevel ? yn : bn;
2008
2028
  this.capTimer = setTimeout(() => {
2009
2029
  this.capTimer = null;
2010
2030
  let n = this.computeSizeCapTarget();
2011
- n === e || t === yn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
2031
+ n === e || t === bn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
2012
2032
  }, t);
2013
2033
  }
2014
2034
  measureLadder(e) {
@@ -2035,7 +2055,7 @@ var Xn = class {
2035
2055
  }
2036
2056
  defaultHeadroomApplies() {
2037
2057
  let e = this.deps.sizeCapHeadroom;
2038
- return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < xn;
2058
+ return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < Sn;
2039
2059
  }
2040
2060
  applySizeCapUnlessPending() {
2041
2061
  this.capTimer || this.applySizeCap();
@@ -2044,7 +2064,7 @@ var Xn = class {
2044
2064
  if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
2045
2065
  let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
2046
2066
  if (typeof t != "number" || !(t > 0)) return;
2047
- let n = Kn(e)?.loading;
2067
+ let n = Z(e)?.loading;
2048
2068
  if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
2049
2069
  let r = this.hls?.levels?.[e.frag.level]?.bitrate;
2050
2070
  if (!(typeof r == "number" && r > 0)) return;
@@ -2055,9 +2075,42 @@ var Xn = class {
2055
2075
  bitrate: r
2056
2076
  }), this.headroomSamples.length > 256 && this.headroomSamples.shift();
2057
2077
  }
2058
- onPlaybackStall() {
2059
- let e = Date.now();
2060
- this.deps.video.seeking || !this.playingSince || e - this.playingSince < En || (this.lastStallAt = e, this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
2078
+ onPlaybackStall(e) {
2079
+ let t = Date.now();
2080
+ this.deps.video.seeking || !this.playingSince || t - this.playingSince < Dn || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
2081
+ }
2082
+ stallCapLevel(e) {
2083
+ if (this.stallCapBitrate == null) return -1;
2084
+ let t = -1;
2085
+ return e.levels.forEach((e, n) => {
2086
+ e.bitrate <= this.stallCapBitrate && (t = n);
2087
+ }), t < 0 ? 0 : t;
2088
+ }
2089
+ stepStallCapDown(e, t) {
2090
+ let n = this.hls;
2091
+ if (!n || !this.stallCapEnabled || jn(n) || !n.autoLevelEnabled || typeof t == "number" && t >= kn || this.isLiveEdgeWait(n, t ?? 0)) return;
2092
+ this.stallCapBitrate != null && (this.stallCapSince = e);
2093
+ let r = Math.max(n.levels[n.currentLevel]?.bitrate ?? 0, n.levels[n.loadLevel]?.bitrate ?? 0);
2094
+ if (!(r > 0)) return;
2095
+ let i = n.levels.map((e) => e.bitrate).filter((e) => e > 0 && e < r).sort((e, t) => t - e)[0];
2096
+ i != null && (this.stallCapBitrate != null && i >= this.stallCapBitrate || (this.stallCapBitrate = i, this.stallCapSince = e, this.stallDownCaps += 1, this.pushCap()));
2097
+ }
2098
+ isLiveEdgeWait(e, t) {
2099
+ let n = e.latestLevelDetails;
2100
+ if (!n?.live) return !1;
2101
+ let r = n.partTarget || n.targetduration;
2102
+ return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < An * r;
2103
+ }
2104
+ releaseStallCap() {
2105
+ let e = this.hls, t = Date.now(), n = this.stallCapTickAt;
2106
+ if (this.stallCapTickAt = t, !e || this.stallCapBitrate == null) return;
2107
+ if (this.deps.video.paused || this.loadSuspended || this.offlineHold) {
2108
+ n && (this.stallCapSince += t - Math.max(n, this.stallCapSince));
2109
+ return;
2110
+ }
2111
+ if (t - this.stallCapSince < On) return;
2112
+ let r = this.stallCapBitrate, i = e.levels.map((e) => e.bitrate).filter((e) => e > r).sort((e, t) => e - t)[0];
2113
+ this.stallCapBitrate = i ?? null, this.stallCapSince = t, this.pushCap();
2061
2114
  }
2062
2115
  reviewSizeCapHeadroom() {
2063
2116
  let e = Date.now(), { video: t } = this.deps;
@@ -2068,26 +2121,26 @@ var Xn = class {
2068
2121
  this.headroomGranted = !1, this.headroomSamples = [];
2069
2122
  return;
2070
2123
  }
2071
- this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Ln);
2124
+ this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Hn);
2072
2125
  let r = this.headroomEarned(n, e);
2073
- r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + On), this.headroomGranted = r, this.applySizeCapUnlessPending());
2126
+ r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Nn), this.headroomGranted = r, this.applySizeCapUnlessPending());
2074
2127
  }
2075
2128
  headroomEarned(e, t) {
2076
- if (t - this.lastStallAt < Dn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
2129
+ if (t - this.lastStallAt < Mn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
2077
2130
  let n = e.levels, r = this.sizeCapCoverLevel();
2078
2131
  if (r == null) return this.headroomGranted;
2079
- let i = J(n, r, bn);
2132
+ let i = J(n, r, xn);
2080
2133
  if (i === r) return this.headroomGranted;
2081
- let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? Tn : wn;
2134
+ let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? En : Tn;
2082
2135
  if (!(a > 0) || !(o >= s * a)) return !1;
2083
2136
  let c = (e) => K([...e].sort((e, t) => e - t), 90);
2084
2137
  if (this.headroomGranted) {
2085
2138
  let e = this.headroomSamples.filter((e) => e.bitrate >= a).map((e) => e.ratio);
2086
- return e.length < q || c(e) <= Cn;
2139
+ return e.length < q || c(e) <= wn;
2087
2140
  }
2088
2141
  let l = [];
2089
2142
  for (let e of this.headroomSamples) e.bitrate < a && l.push(e.ratio * (a / e.bitrate));
2090
- return l.length >= q && c(l) <= Sn;
2143
+ return l.length >= q && c(l) <= Cn;
2091
2144
  }
2092
2145
  applySizeCap() {
2093
2146
  if (!this.sizeCapManaged) return;
@@ -2101,7 +2154,8 @@ var Xn = class {
2101
2154
  let t = [
2102
2155
  ["size", this.sizeCapLevel ?? -1],
2103
2156
  ["bitrate", this.bitrateCapLevel],
2104
- ["fps", this.fpsCapLevel(e)]
2157
+ ["fps", this.fpsCapLevel(e)],
2158
+ ["stall", this.stallCapLevel(e)]
2105
2159
  ], n = -1, r = null;
2106
2160
  for (let [e, i] of t) i >= 0 && (n < 0 || i < n) && (n = i, r = e);
2107
2161
  e.autoLevelCapping = n, this.pushedCapLevel = n, this.pushedCapReason = r;
@@ -2146,6 +2200,7 @@ var Xn = class {
2146
2200
  liveRetargets: this.liveRetargets,
2147
2201
  holdBackSteps: this.holdBackSteps,
2148
2202
  fpsDownCaps: this.fpsDownCaps,
2203
+ stallDownCaps: this.stallDownCaps,
2149
2204
  licenseTimeMs: this.licenseTimeMs,
2150
2205
  upshifts: this.upshifts,
2151
2206
  downshifts: this.downshifts,
@@ -2160,12 +2215,7 @@ var Xn = class {
2160
2215
  let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
2161
2216
  t && (n.levelHeight = t.height);
2162
2217
  let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
2163
- if (i && i.height > 0) {
2164
- n.maxLevelHeight = i.height;
2165
- let t = e.config ?? {};
2166
- t.capLevelToPlayerSize !== !0 && t.capLevelOnFPSDrop !== !0 && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason);
2167
- }
2168
- t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
2218
+ i && i.height > 0 && (n.maxLevelHeight = i.height, !jn(e) && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason)), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
2169
2219
  }
2170
2220
  return n;
2171
2221
  }
@@ -2193,7 +2243,7 @@ var Xn = class {
2193
2243
  return;
2194
2244
  }
2195
2245
  let e = Date.now() - this.lastAdvanceMs;
2196
- !this.chaseSuspended && e > rn && this.suspendChasing(), e > en && this.emitEnded("stalled");
2246
+ !this.chaseSuspended && e > an && this.suspendChasing(), e > tn && this.emitEnded("stalled");
2197
2247
  }
2198
2248
  resetStarvationWindow() {
2199
2249
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -2208,7 +2258,7 @@ var Xn = class {
2208
2258
  this.resetStarvationWindow();
2209
2259
  return;
2210
2260
  }
2211
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < rn, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
2261
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < an, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > fn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
2212
2262
  if (this.starvedFrames = c, !a || l) {
2213
2263
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
2214
2264
  return;
@@ -2217,12 +2267,12 @@ var Xn = class {
2217
2267
  this.resetStarvationWindow();
2218
2268
  return;
2219
2269
  }
2220
- if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > gn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mn && (this.clearKick(), this.starvationRebuilds < hn)) {
2270
+ if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > _n && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= hn && (this.clearKick(), this.starvationRebuilds < gn)) {
2221
2271
  this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
2222
2272
  return;
2223
2273
  }
2224
- let u = i && this.starvedTicks >= fn, d = !i && this.deadTicks >= gn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _n;
2225
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pn))) {
2274
+ let u = i && this.starvedTicks >= pn, d = !i && this.deadTicks >= _n && this.recentMainFrags.reduce((e, t) => e + t, 0) >= vn;
2275
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= mn))) {
2226
2276
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
2227
2277
  try {
2228
2278
  e.stopLoad(), e.startLoad(-1);
@@ -2237,7 +2287,7 @@ var Xn = class {
2237
2287
  let t = e.latency, n = e.targetLatency;
2238
2288
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
2239
2289
  let r = t - n;
2240
- !this.catchUpEngaged && r > an ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= an && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2290
+ !this.catchUpEngaged && r > on ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= on && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2241
2291
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
2242
2292
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
2243
2293
  }
@@ -2250,7 +2300,7 @@ var Xn = class {
2250
2300
  }), n < 0 ? 0 : n;
2251
2301
  }
2252
2302
  armFrameDropGrace() {
2253
- this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Mn, this.fpsBadTicks = 0);
2303
+ this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Ln, this.fpsBadTicks = 0);
2254
2304
  }
2255
2305
  resetFrameDropWindow() {
2256
2306
  this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
@@ -2262,7 +2312,7 @@ var Xn = class {
2262
2312
  return;
2263
2313
  }
2264
2314
  let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
2265
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < An || o < 0) {
2315
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Fn || o < 0) {
2266
2316
  this.fpsBadTicks = 0;
2267
2317
  return;
2268
2318
  }
@@ -2270,11 +2320,11 @@ var Xn = class {
2270
2320
  --this.fpsGraceTicks, this.fpsBadTicks = 0;
2271
2321
  return;
2272
2322
  }
2273
- if (o <= kn * a) {
2323
+ if (o <= Pn * a) {
2274
2324
  this.fpsBadTicks = 0;
2275
2325
  return;
2276
2326
  }
2277
- if (this.fpsBadTicks += 1, this.fpsBadTicks < jn) return;
2327
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < In) return;
2278
2328
  this.fpsBadTicks = 0;
2279
2329
  let s = e.levels, c = s[e.currentLevel];
2280
2330
  if (!c) return;
@@ -2291,22 +2341,22 @@ var Xn = class {
2291
2341
  return;
2292
2342
  }
2293
2343
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
2294
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(cn, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2344
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(ln, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2295
2345
  this.resetChaseWindow();
2296
2346
  return;
2297
2347
  }
2298
- if (this.chaseLatency < 0 || this.chaseLatency - n >= sn) {
2348
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= cn) {
2299
2349
  this.chaseLatency = n, this.chaseTicks = 0;
2300
2350
  return;
2301
2351
  }
2302
- if (this.chaseTicks += 1, this.chaseTicks < on) return;
2352
+ if (this.chaseTicks += 1, this.chaseTicks < sn) return;
2303
2353
  this.resetChaseWindow();
2304
2354
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2305
2355
  if (!(a > 1)) return;
2306
2356
  let o = e.targetLatency;
2307
2357
  if (typeof o != "number" || !(o > 0)) return;
2308
2358
  let s = Math.min(n, a - 1);
2309
- s < o + ln || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
2359
+ s < o + un || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
2310
2360
  type: "livetargetchange",
2311
2361
  change: {
2312
2362
  targetSeconds: s,
@@ -2323,13 +2373,13 @@ var Xn = class {
2323
2373
  if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
2324
2374
  let t = e.targetLatency;
2325
2375
  if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
2326
- let n = qn();
2327
- if (!(n >= Gn)) return;
2376
+ let n = Zn();
2377
+ if (!(n >= Xn)) return;
2328
2378
  let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
2329
2379
  i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
2330
2380
  }
2331
2381
  holdBackCeiling(e) {
2332
- let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Wn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2382
+ let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Yn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2333
2383
  return r > 1 ? Math.min(n, r - 1) : n;
2334
2384
  }
2335
2385
  sampleHoldBack(e) {
@@ -2338,7 +2388,7 @@ var Xn = class {
2338
2388
  if (t !== "main" && t !== "audio") return;
2339
2389
  let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
2340
2390
  if (typeof n != "number" || !(n > 0)) return;
2341
- let r = Kn(e)?.loading;
2391
+ let r = Z(e)?.loading;
2342
2392
  if (!r || !(r.start > 0) || !(r.end > 0)) return;
2343
2393
  let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
2344
2394
  this.holdBackSamples.push({
@@ -2353,20 +2403,20 @@ var Xn = class {
2353
2403
  this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
2354
2404
  return;
2355
2405
  }
2356
- let t = Date.now(), n = t - Ln, r = this.holdBackSamples, i = 0;
2406
+ let t = Date.now(), n = t - Hn, r = this.holdBackSamples, i = 0;
2357
2407
  for (; i < r.length && r[i].t < n;) i += 1;
2358
2408
  i > 0 && r.splice(0, i);
2359
2409
  let a = e.targetLatency;
2360
2410
  if (typeof a != "number" || !(a > 0)) return;
2361
2411
  this.holdBackBase < 0 && (this.holdBackBase = a);
2362
2412
  let o = this.holdBackBase, s = this.holdBackCeiling(e);
2363
- if (r.length < Rn) {
2413
+ if (r.length < Un) {
2364
2414
  this.holdBackSlowTicks = 0;
2365
2415
  return;
2366
2416
  }
2367
2417
  let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
2368
- if (l >= zn && u >= Bn) {
2369
- if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Hn) return;
2418
+ if (l >= Wn && u >= Gn) {
2419
+ if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < qn) return;
2370
2420
  this.holdBackSlowTicks = 0;
2371
2421
  let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
2372
2422
  if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
@@ -2376,7 +2426,7 @@ var Xn = class {
2376
2426
  this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
2377
2427
  return;
2378
2428
  }
2379
- if (this.holdBackSlowTicks = 0, l >= Vn) {
2429
+ if (this.holdBackSlowTicks = 0, l >= Kn) {
2380
2430
  this.holdBackFastSince = 0;
2381
2431
  return;
2382
2432
  }
@@ -2384,7 +2434,7 @@ var Xn = class {
2384
2434
  this.holdBackFastSince = t;
2385
2435
  return;
2386
2436
  }
2387
- if (t - this.holdBackFastSince < Un || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2437
+ if (t - this.holdBackFastSince < Jn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2388
2438
  --this.holdBackStepCount;
2389
2439
  let f = Math.max(o, o + this.holdBackStepCount * X);
2390
2440
  f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
@@ -2427,14 +2477,14 @@ var Xn = class {
2427
2477
  } catch {}
2428
2478
  }
2429
2479
  startEstimate() {
2430
- return this.deps.rememberBandwidth === !1 ? Kt : Be() ?? Kt;
2480
+ return this.deps.rememberBandwidth === !1 ? qt : Re() ?? qt;
2431
2481
  }
2432
2482
  maybeRememberBandwidth(e) {
2433
- if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < qt) return;
2483
+ if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Jt) return;
2434
2484
  let t = Date.now();
2435
- if (!e && t - this.bwSavedAt < Jt) return;
2485
+ if (!e && t - this.bwSavedAt < Yt) return;
2436
2486
  let n = this.hls?.bandwidthEstimate;
2437
- typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ve(n));
2487
+ typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, ze(n));
2438
2488
  }
2439
2489
  destroy() {
2440
2490
  if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onOffline && typeof window < "u" && (window.removeEventListener("offline", this.onOffline), this.onOffline = null), this.onOnline && typeof window < "u" && (window.removeEventListener("online", this.onOnline), this.onOnline = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
@@ -2452,7 +2502,7 @@ var Xn = class {
2452
2502
  scheduleLicenseRetry(t) {
2453
2503
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
2454
2504
  let n = t.response?.code ?? 0;
2455
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Zt) return !1;
2505
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Qt) return !1;
2456
2506
  this.licenseRecoveries += 1;
2457
2507
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
2458
2508
  return this.licenseRetryTimer = setTimeout(() => {
@@ -2470,7 +2520,7 @@ var Xn = class {
2470
2520
  }
2471
2521
  }
2472
2522
  onError(t) {
2473
- if (t.details === e.ErrorDetails.BUFFER_STALLED_ERROR && this.onPlaybackStall(), t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
2523
+ if (t.details === e.ErrorDetails.BUFFER_STALLED_ERROR && this.onPlaybackStall(t.buffer), t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
2474
2524
  let n = this.hls;
2475
2525
  if (n) {
2476
2526
  if (this.clearRecoveryReset(), t.type === e.ErrorTypes.KEY_SYSTEM_ERROR) {
@@ -2488,7 +2538,7 @@ var Xn = class {
2488
2538
  this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
2489
2539
  return;
2490
2540
  }
2491
- if (this.networkRecoveries < Xt) {
2541
+ if (this.networkRecoveries < Zt) {
2492
2542
  this.networkRecoveries += 1;
2493
2543
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
2494
2544
  this.networkRetryTimer = setTimeout(() => {
@@ -2505,7 +2555,7 @@ var Xn = class {
2505
2555
  return;
2506
2556
  }
2507
2557
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
2508
- if (this.mediaRecoveries < Yt) {
2558
+ if (this.mediaRecoveries < Xt) {
2509
2559
  this.mediaRecoveries += 1, n.recoverMediaError();
2510
2560
  return;
2511
2561
  }
@@ -2526,18 +2576,18 @@ var Xn = class {
2526
2576
  }
2527
2577
  }
2528
2578
  toError(t, r = "PLAYBACK") {
2529
- let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Mt(t.networkDetails)) : void 0;
2579
+ let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Nt(t.networkDetails)) : void 0;
2530
2580
  return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
2531
2581
  }
2532
- }, Zn = 15e3, Qn = 6e5, $n = 3e5, er = 100, Z = 1, tr = 1e3, nr = 3e4, rr = 1e3, ir = {
2582
+ }, tr = 15e3, nr = 6e5, rr = 3e5, ir = 100, Q = 1, ar = 1e3, or = 3e4, sr = 1e3, cr = {
2533
2583
  inline: "PRESENTATION_INLINE",
2534
2584
  fullscreen: "PRESENTATION_FULLSCREEN",
2535
2585
  pip: "PRESENTATION_PIP"
2536
- }, ar = {
2586
+ }, lr = {
2537
2587
  widevine: "KEY_SYSTEM_WIDEVINE",
2538
2588
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2539
2589
  none: "KEY_SYSTEM_NONE"
2540
- }, or = /* @__PURE__ */ new Set([
2590
+ }, ur = /* @__PURE__ */ new Set([
2541
2591
  "INVALID_URN",
2542
2592
  "NOT_FOUND",
2543
2593
  "GEO_DENIED",
@@ -2548,7 +2598,7 @@ var Xn = class {
2548
2598
  "FORBIDDEN",
2549
2599
  "RATE_LIMITED",
2550
2600
  "TIMEOUT"
2551
- ]), sr = {
2601
+ ]), dr = {
2552
2602
  idle: "PLAYER_STATE_IDLE",
2553
2603
  waiting: "PLAYER_STATE_WAITING",
2554
2604
  loading: "PLAYER_STATE_LOADING",
@@ -2558,7 +2608,7 @@ var Xn = class {
2558
2608
  ended: "PLAYER_STATE_ENDED",
2559
2609
  error: "PLAYER_STATE_ERROR"
2560
2610
  };
2561
- function cr(e) {
2611
+ function fr(e) {
2562
2612
  try {
2563
2613
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2564
2614
  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);
@@ -2566,8 +2616,8 @@ function cr(e) {
2566
2616
  return;
2567
2617
  }
2568
2618
  }
2569
- var lr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), ur = /* @__PURE__ */ new Set(), dr = /* @__PURE__ */ new Set(), fr = /* @__PURE__ */ new Set(), pr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2570
- function mr(e) {
2619
+ var pr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), mr = /* @__PURE__ */ new Set(), hr = /* @__PURE__ */ new Set(), gr = /* @__PURE__ */ new Set(), _r = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2620
+ function vr(e) {
2571
2621
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2572
2622
  let t;
2573
2623
  try {
@@ -2576,19 +2626,19 @@ function mr(e) {
2576
2626
  } catch {
2577
2627
  return;
2578
2628
  }
2579
- if (ur.has(t) && !dr.has(t)) {
2580
- dr.add(t), _(pr(new URL(t).origin));
2581
- for (let e of fr) e.noteCspBlocked();
2629
+ if (mr.has(t) && !hr.has(t)) {
2630
+ hr.add(t), _(_r(new URL(t).origin));
2631
+ for (let e of gr) e.noteCspBlocked();
2582
2632
  }
2583
2633
  }
2584
- function hr(e, t) {
2634
+ function yr(e, t) {
2585
2635
  return _(t, e), { disabledReason: t };
2586
2636
  }
2587
- function gr(e, t, n) {
2588
- if (n) return t && !lr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2637
+ function br(e, t, n) {
2638
+ if (n) return t && !pr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2589
2639
  if (t) return { endpoint: t };
2590
- if (t !== void 0) return hr("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
2591
- let r = cr(e);
2640
+ if (t !== void 0) return yr("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
2641
+ let r = fr(e);
2592
2642
  if (r) return { endpoint: r };
2593
2643
  let i;
2594
2644
  try {
@@ -2596,9 +2646,9 @@ function gr(e, t, n) {
2596
2646
  } catch {
2597
2647
  i = e;
2598
2648
  }
2599
- return hr(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
2649
+ return yr(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
2600
2650
  }
2601
- var _r = class {
2651
+ var xr = class {
2602
2652
  opts;
2603
2653
  url;
2604
2654
  cspKey;
@@ -2680,8 +2730,8 @@ var _r = class {
2680
2730
  constructor(e) {
2681
2731
  this.opts = {
2682
2732
  ...e,
2683
- heartbeatMs: e.heartbeatMs ?? Zn,
2684
- idleMs: e.idleMs ?? Qn
2733
+ heartbeatMs: e.heartbeatMs ?? tr,
2734
+ idleMs: e.idleMs ?? nr
2685
2735
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2686
2736
  try {
2687
2737
  let e = new URL(this.url);
@@ -2698,11 +2748,11 @@ var _r = class {
2698
2748
  sdkVersion: this.opts.sdkVersion,
2699
2749
  ...this.opts.environment
2700
2750
  };
2701
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), tr), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && ur.add(this.cspKey), document.addEventListener("securitypolicyviolation", mr), fr.add(this), this.noteCspBlocked(), this.onVisibility());
2751
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), ar), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && mr.add(this.cspKey), document.addEventListener("securitypolicyviolation", vr), gr.add(this), this.noteCspBlocked(), this.onVisibility());
2702
2752
  }
2703
2753
  checkSuspension(e) {
2704
2754
  if (this.endedFlag || !this.opts.idleMs) return !1;
2705
- let t = Math.max(this.opts.idleMs, $n);
2755
+ let t = Math.max(this.opts.idleMs, rr);
2706
2756
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2707
2757
  }
2708
2758
  syncIdle(e) {
@@ -2716,21 +2766,21 @@ var _r = class {
2716
2766
  noteStateChange(e, t, n, r) {
2717
2767
  if (this.endedFlag || e === t) return;
2718
2768
  let i = this.now();
2719
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Z, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Z, 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") {
2769
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
2720
2770
  this.stallIsSeekInduced = this.seekInduced(i);
2721
2771
  let e = !this.isHidden && !this.stallIsSeekInduced;
2722
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Z, Math.round(this.playingTotalMs)));
2772
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Q, Math.round(this.playingTotalMs)));
2723
2773
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
2724
2774
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
2725
2775
  let a = {
2726
- fromState: sr[e] ?? "PLAYER_STATE_UNSPECIFIED",
2727
- toState: sr[t] ?? "PLAYER_STATE_UNSPECIFIED",
2728
- presentation: ir[this.presentation]
2776
+ fromState: dr[e] ?? "PLAYER_STATE_UNSPECIFIED",
2777
+ toState: dr[t] ?? "PLAYER_STATE_UNSPECIFIED",
2778
+ presentation: cr[this.presentation]
2729
2779
  }, o = this.causeOf(e, t, i);
2730
2780
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2731
2781
  }
2732
2782
  seekInduced(e) {
2733
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < rr;
2783
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < sr;
2734
2784
  }
2735
2785
  causeOf(e, t, n) {
2736
2786
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2767,25 +2817,25 @@ var _r = class {
2767
2817
  }
2768
2818
  this.muteChanges += 1;
2769
2819
  let r = this.now();
2770
- 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(Z, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2820
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2771
2821
  }
2772
2822
  notePresentation(e) {
2773
2823
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
2774
2824
  }
2775
2825
  notePlayIntent() {
2776
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Z), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Z), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Z), this.drmSetupMs > 0 && (this.drmSetupMs = Z));
2826
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Q), this.drmSetupMs > 0 && (this.drmSetupMs = Q));
2777
2827
  }
2778
2828
  noteReady() {
2779
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
2829
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Q, this.now() - this.startupAnchorMs));
2780
2830
  }
2781
2831
  noteFirstPlaylist() {
2782
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Z, this.now() - this.startupAnchorMs));
2832
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Q, this.now() - this.startupAnchorMs));
2783
2833
  }
2784
2834
  noteDrmReady() {
2785
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Z, this.now() - this.startupAnchorMs));
2835
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Q, this.now() - this.startupAnchorMs));
2786
2836
  }
2787
2837
  noteFirstBytes() {
2788
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
2838
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Q, this.now() - this.startupAnchorMs));
2789
2839
  }
2790
2840
  noteSeek() {
2791
2841
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2804,7 +2854,7 @@ var _r = class {
2804
2854
  let r = n ?? "";
2805
2855
  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";
2806
2856
  if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
2807
- if (or.has(e)) return "ERROR_STAGE_RESOLVE";
2857
+ if (ur.has(e)) return "ERROR_STAGE_RESOLVE";
2808
2858
  let i = t ?? "";
2809
2859
  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";
2810
2860
  }
@@ -2836,7 +2886,7 @@ var _r = class {
2836
2886
  let l = t.droppedFrames ?? 0;
2837
2887
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2838
2888
  let u = t.renditionSwitches ?? 0;
2839
- 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 = sr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2889
+ 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 = dr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2840
2890
  let d = this.mutedTotalMs;
2841
2891
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2842
2892
  let f = t.upshifts ?? 0;
@@ -2858,13 +2908,13 @@ var _r = class {
2858
2908
  maybeEmitMediaInfo(e) {
2859
2909
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2860
2910
  let t = {};
2861
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ar[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);
2911
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = lr[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);
2862
2912
  let n = JSON.stringify(t);
2863
2913
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2864
2914
  }
2865
2915
  end(e, t) {
2866
2916
  if (this.endedFlag) return;
2867
- this.endedFlag = !0, fr.delete(this);
2917
+ this.endedFlag = !0, gr.delete(this);
2868
2918
  let n = t ?? this.now();
2869
2919
  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));
2870
2920
  let r = this.safeSample();
@@ -2878,7 +2928,7 @@ var _r = class {
2878
2928
  let c = r?.positionMs ?? 0;
2879
2929
  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));
2880
2930
  let l = e !== "END_REASON_ENDED";
2881
- l && this.lastStallMs > 0 && n - this.lastStallMs <= nr && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= nr && (i.abandonAfterErrorMs = Math.max(Z, 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);
2931
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= or && (i.abandonAfterStallMs = Math.max(Q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= or && (i.abandonAfterErrorMs = Math.max(Q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2882
2932
  let u = r?.decodedFrames ?? this.lastDecoded;
2883
2933
  u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
2884
2934
  }
@@ -2898,13 +2948,13 @@ var _r = class {
2898
2948
  };
2899
2949
  }
2900
2950
  noteCspBlocked() {
2901
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(pr(new URL(this.url).origin)));
2951
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(_r(new URL(this.url).origin)));
2902
2952
  }
2903
2953
  cspBlocked() {
2904
- return !!this.cspKey && dr.has(this.cspKey);
2954
+ return !!this.cspKey && hr.has(this.cspKey);
2905
2955
  }
2906
2956
  enqueue(e) {
2907
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > er;) {
2957
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > ir;) {
2908
2958
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2909
2959
  this.pending.splice(e >= 0 ? e : 0, 1);
2910
2960
  }
@@ -2931,7 +2981,7 @@ var _r = class {
2931
2981
  };
2932
2982
  //#endregion
2933
2983
  //#region src/core/environment.ts
2934
- function vr() {
2984
+ function Sr() {
2935
2985
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2936
2986
  let e;
2937
2987
  try {
@@ -2956,14 +3006,14 @@ function vr() {
2956
3006
  integration: "INTEGRATION_KIND_IFRAME"
2957
3007
  };
2958
3008
  }
2959
- function yr() {
3009
+ function Cr() {
2960
3010
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2961
3011
  let e = navigator.userAgentData, t = e?.platform ?? "";
2962
3012
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2963
3013
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2964
3014
  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";
2965
3015
  }
2966
- function br() {
3016
+ function wr() {
2967
3017
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2968
3018
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2969
3019
  let t = {
@@ -2982,17 +3032,17 @@ function br() {
2982
3032
  }
2983
3033
  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;
2984
3034
  }
2985
- function xr(e) {
2986
- let t = vr(), n = {
2987
- deviceClass: yr(),
3035
+ function Tr(e) {
3036
+ let t = Sr(), n = {
3037
+ deviceClass: Cr(),
2988
3038
  integration: t.integration,
2989
- ...br()
3039
+ ...wr()
2990
3040
  };
2991
3041
  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);
2992
3042
  let r = e.getBoundingClientRect?.();
2993
3043
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2994
3044
  }
2995
- async function Sr() {
3045
+ async function Er() {
2996
3046
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2997
3047
  if (!e?.getHighEntropyValues) return {};
2998
3048
  try {
@@ -3004,7 +3054,7 @@ async function Sr() {
3004
3054
  }
3005
3055
  //#endregion
3006
3056
  //#region src/core/version.ts
3007
- var Cr = "2.26.1", wr = {
3057
+ var Dr = "2.27.1", Or = {
3008
3058
  accent: "#E1B600",
3009
3059
  accentText: "#1B1C23",
3010
3060
  background: "#0e0f13",
@@ -3015,7 +3065,7 @@ var Cr = "2.26.1", wr = {
3015
3065
  border: "rgba(255, 255, 255, 0.1)",
3016
3066
  radius: "8px",
3017
3067
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
3018
- }, Tr = {
3068
+ }, kr = {
3019
3069
  accent: "--havik-accent",
3020
3070
  accentText: "--havik-accent-text",
3021
3071
  background: "--havik-bg",
@@ -3027,26 +3077,26 @@ var Cr = "2.26.1", wr = {
3027
3077
  radius: "--havik-radius",
3028
3078
  fontFamily: "--havik-font"
3029
3079
  };
3030
- function Er(e, t) {
3080
+ function Ar(e, t) {
3031
3081
  let n = {
3032
- ...wr,
3082
+ ...Or,
3033
3083
  ...t
3034
3084
  };
3035
- for (let t of Object.keys(Tr)) e.style.setProperty(Tr[t], n[t]);
3085
+ for (let t of Object.keys(kr)) e.style.setProperty(kr[t], n[t]);
3036
3086
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
3037
3087
  }
3038
3088
  //#endregion
3039
3089
  //#region src/ui/styles.ts
3040
- var Dr = "havik-player-styles", Or = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", kr = /* @__PURE__ */ new WeakMap();
3041
- function Ar(e = document, t) {
3042
- let n = e.querySelector(`style#${Dr}`);
3043
- if (n && (!t || kr.get(n) === t)) return;
3090
+ var jr = "havik-player-styles", Mr = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Nr = /* @__PURE__ */ new WeakMap();
3091
+ function Pr(e = document, t) {
3092
+ let n = e.querySelector(`style#${jr}`);
3093
+ if (n && (!t || Nr.get(n) === t)) return;
3044
3094
  let r = e.createElement("style");
3045
- r.id = Dr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Or, kr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
3095
+ r.id = jr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Mr, Nr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
3046
3096
  }
3047
3097
  //#endregion
3048
3098
  //#region src/ui/icons.ts
3049
- var jr = {
3099
+ var Fr = {
3050
3100
  play: "<path d=\"M8 5v14l11-7z\"/>",
3051
3101
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
3052
3102
  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\"/>",
@@ -3059,12 +3109,12 @@ var jr = {
3059
3109
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
3060
3110
  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\"/>"
3061
3111
  };
3062
- function Q(e) {
3063
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${jr[e]}</svg>`;
3112
+ function $(e) {
3113
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Fr[e]}</svg>`;
3064
3114
  }
3065
3115
  //#endregion
3066
3116
  //#region src/ui/controls.ts
3067
- var Mr = 3e3, Nr = 250, Pr = /* @__PURE__ */ new Set([
3117
+ var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
3068
3118
  "GONE",
3069
3119
  "NOT_FOUND",
3070
3120
  "GEO_DENIED",
@@ -3072,15 +3122,15 @@ var Mr = 3e3, Nr = 250, Pr = /* @__PURE__ */ new Set([
3072
3122
  "UNAUTHORIZED",
3073
3123
  "DRM_DEVICE_REVOKED"
3074
3124
  ]);
3075
- function Fr(e) {
3125
+ function zr(e) {
3076
3126
  let t = "This match isn't available in your country";
3077
3127
  return e ? `${t} (${e})` : t;
3078
3128
  }
3079
- var Ir = "This device can't play protected video";
3080
- function Lr(e) {
3081
- return new Rr(e);
3129
+ var Br = "This device can't play protected video";
3130
+ function Vr(e) {
3131
+ return new Hr(e);
3082
3132
  }
3083
- var Rr = class {
3133
+ var Hr = class {
3084
3134
  root;
3085
3135
  video;
3086
3136
  player;
@@ -3129,7 +3179,7 @@ var Rr = class {
3129
3179
  scrubbing = !1;
3130
3180
  offFns = [];
3131
3181
  constructor(e) {
3132
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Ar(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
3182
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Ir, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Pr(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
3133
3183
  let t = (e, t, n) => {
3134
3184
  let r = this.doc.createElement(e);
3135
3185
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -3140,12 +3190,12 @@ var Rr = class {
3140
3190
  "aria-label": r,
3141
3191
  title: r
3142
3192
  });
3143
- return i.innerHTML = Q(n), i;
3193
+ return i.innerHTML = $(n), i;
3144
3194
  };
3145
3195
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
3146
3196
  type: "button",
3147
3197
  "aria-label": "Play"
3148
- }), 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", {
3198
+ }), this.center.innerHTML = $("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", {
3149
3199
  role: "slider",
3150
3200
  "aria-label": "Seek",
3151
3201
  "aria-valuemin": "0",
@@ -3163,7 +3213,7 @@ var Rr = class {
3163
3213
  "aria-label": "Volume"
3164
3214
  });
3165
3215
  let a = t("div", "havik-vol");
3166
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
3216
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = $("liveDot");
3167
3217
  let o = this.doc.createElement("span");
3168
3218
  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";
3169
3219
  let s = t("div", "havik-spacer");
@@ -3215,7 +3265,7 @@ var Rr = class {
3215
3265
  let t = this.surfaceWasHidden;
3216
3266
  this.tapTimer = setTimeout(() => {
3217
3267
  this.tapTimer = void 0, this.toggleBar(t);
3218
- }, Nr);
3268
+ }, Lr);
3219
3269
  }
3220
3270
  toggleBar(e) {
3221
3271
  e ? this.poke() : this.hideIfIdle();
@@ -3242,7 +3292,7 @@ var Rr = class {
3242
3292
  this.renderStatus(t);
3243
3293
  }
3244
3294
  statusMessageFor(e) {
3245
- return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Fr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Ir : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3295
+ return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? zr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Br : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3246
3296
  }
3247
3297
  renderStatus(e) {
3248
3298
  let t = this.statusMessageFor(e);
@@ -3254,12 +3304,12 @@ var Rr = class {
3254
3304
  }
3255
3305
  if (e === "preplay") {
3256
3306
  let e = this.doc.createElement("button");
3257
- 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);
3307
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = $("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
3258
3308
  } else {
3259
3309
  let r = this.doc.createElement("div");
3260
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Pr.has(this.lastError.code)) {
3310
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Rr.has(this.lastError.code)) {
3261
3311
  let e = this.doc.createElement("button");
3262
- 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);
3312
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${$("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
3263
3313
  }
3264
3314
  }
3265
3315
  this.root.append(n), this.statusBox = n, this.show();
@@ -3298,7 +3348,7 @@ var Rr = class {
3298
3348
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
3299
3349
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
3300
3350
  }
3301
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${zr(this.video.currentTime)} / ${zr(this.video.duration)}`);
3351
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ur(this.video.currentTime)} / ${Ur(this.video.duration)}`);
3302
3352
  }
3303
3353
  syncLive() {
3304
3354
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.isGone(), r = this.player.state === "ended" || n, i = !t && !this.streamEnded() && !n;
@@ -3348,17 +3398,17 @@ var Rr = class {
3348
3398
  renderQualityMenu() {
3349
3399
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
3350
3400
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
3351
- for (let n of e) this.menu.append(this.menuItem(Br(n), t === n.index, () => this.player.setQuality(n.index)));
3401
+ for (let n of e) this.menu.append(this.menuItem(Wr(n), t === n.index, () => this.player.setQuality(n.index)));
3352
3402
  }
3353
3403
  renderAudioMenu() {
3354
3404
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
3355
3405
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
3356
- for (let t of e) this.menu.append(this.menuItem(Vr(t), t.default, () => this.player.setAudioTrack(t.id)));
3406
+ for (let t of e) this.menu.append(this.menuItem(Gr(t), t.default, () => this.player.setAudioTrack(t.id)));
3357
3407
  }
3358
3408
  renderCcMenu() {
3359
3409
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
3360
3410
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
3361
- for (let t of e) this.menu.append(this.menuItem(Hr(t), !1, () => this.player.setTextTrack(t.id)));
3411
+ for (let t of e) this.menu.append(this.menuItem(Kr(t), !1, () => this.player.setTextTrack(t.id)));
3362
3412
  }
3363
3413
  onTracksChanged() {
3364
3414
  this.openMenu && this.renderMenu(this.openMenu);
@@ -3378,14 +3428,14 @@ var Rr = class {
3378
3428
  }
3379
3429
  async toggleFullscreen() {
3380
3430
  try {
3381
- S(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
3431
+ ve(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
3382
3432
  } catch {}
3383
3433
  }
3384
3434
  syncFullscreenSupport() {
3385
- this.fsSupported = C(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
3435
+ this.fsSupported = S(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
3386
3436
  }
3387
3437
  syncFullscreen() {
3388
- let e = S(this.video, this.root);
3438
+ let e = ve(this.video, this.root);
3389
3439
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
3390
3440
  }
3391
3441
  poke() {
@@ -3446,7 +3496,7 @@ var Rr = class {
3446
3496
  }
3447
3497
  }
3448
3498
  setIcon(e, t) {
3449
- e.innerHTML = Q(t);
3499
+ e.innerHTML = $(t);
3450
3500
  }
3451
3501
  destroy() {
3452
3502
  this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
@@ -3463,23 +3513,23 @@ var Rr = class {
3463
3513
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
3464
3514
  }
3465
3515
  };
3466
- function zr(e) {
3516
+ function Ur(e) {
3467
3517
  (!Number.isFinite(e) || e < 0) && (e = 0);
3468
3518
  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");
3469
3519
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3470
3520
  }
3471
- function Br(e) {
3521
+ function Wr(e) {
3472
3522
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3473
3523
  }
3474
- function Vr(e) {
3524
+ function Gr(e) {
3475
3525
  return e.name || e.lang || `Track ${e.id}`;
3476
3526
  }
3477
- function Hr(e) {
3527
+ function Kr(e) {
3478
3528
  return e.name || e.lang || `Track ${e.id}`;
3479
3529
  }
3480
3530
  //#endregion
3481
3531
  //#region src/managed/index.ts
3482
- var Ur = 6e3, Wr = 45e3, Gr = 2e3, Kr = 3, qr = 5e3, Jr = 2e3, Yr = 48e4, Xr = "keySystemLicenseRequestFailed", Zr = /* @__PURE__ */ new Set([
3532
+ var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "keySystemLicenseRequestFailed", ti = /* @__PURE__ */ new Set([
3483
3533
  "GONE",
3484
3534
  "NOT_FOUND",
3485
3535
  "INVALID_URN",
@@ -3487,27 +3537,27 @@ var Ur = 6e3, Wr = 45e3, Gr = 2e3, Kr = 3, qr = 5e3, Jr = 2e3, Yr = 48e4, Xr = "
3487
3537
  "GEO_DENIED",
3488
3538
  "DRM_DEVICE_REVOKED"
3489
3539
  ]);
3490
- function Qr(e) {
3491
- return !Zr.has(e);
3540
+ function ni(e) {
3541
+ return !ti.has(e);
3492
3542
  }
3493
- function $r(e) {
3543
+ function ri(e) {
3494
3544
  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)})`);
3495
3545
  if (e.env !== void 0) return lt(e.env);
3496
3546
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3497
3547
  return e.baseUrl;
3498
3548
  }
3499
- async function ei(e) {
3549
+ async function ii(e) {
3500
3550
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3501
- let t = $r(e);
3551
+ let t = ri(e);
3502
3552
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3503
3553
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3504
- let r = new ti({
3554
+ let r = new ai({
3505
3555
  ...e,
3506
3556
  baseUrl: t
3507
3557
  });
3508
3558
  return await r.start(), r;
3509
3559
  }
3510
- var ti = class {
3560
+ var ai = class {
3511
3561
  opts;
3512
3562
  abort = new AbortController();
3513
3563
  listeners = {};
@@ -3586,7 +3636,7 @@ var ti = class {
3586
3636
  };
3587
3637
  }
3588
3638
  beginArming(e, t, n = !1) {
3589
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
3639
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3590
3640
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
3591
3641
  }
3592
3642
  beginArmingByPolling(e) {
@@ -3607,7 +3657,7 @@ var ti = class {
3607
3657
  setTimeout(() => {
3608
3658
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3609
3659
  phase: i ? "unavailable" : "tooEarly",
3610
- retryInMs: Wr,
3660
+ retryInMs: Jr,
3611
3661
  attempt: 1,
3612
3662
  elapsedMs: 0,
3613
3663
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3646,13 +3696,13 @@ var ti = class {
3646
3696
  !a && !p() && h();
3647
3697
  }, e);
3648
3698
  };
3649
- _(Ur), this.armingSub = D({
3699
+ _(qr), this.armingSub = E({
3650
3700
  eventsBaseUrl: t,
3651
3701
  matchUrn: this.opts.matchUrn,
3652
3702
  credential: this.opts.credential,
3653
- onAlive: () => _(Wr),
3703
+ onAlive: () => _(Jr),
3654
3704
  onState: (e) => {
3655
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Gr);
3705
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Yr);
3656
3706
  },
3657
3707
  onError: () => h()
3658
3708
  });
@@ -3675,7 +3725,7 @@ var ti = class {
3675
3725
  let n = await c(this.opts.credential);
3676
3726
  if (this.destroyed || t !== this.loadGen) return;
3677
3727
  this.setState("loading");
3678
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = gt(this.opts.video, (e) => {
3728
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = _t(this.opts.video, (e) => {
3679
3729
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3680
3730
  });
3681
3731
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3697,19 +3747,19 @@ var ti = class {
3697
3747
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3698
3748
  let i = e.analytics?.sid;
3699
3749
  if (!i) return;
3700
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = gr(this.opts.baseUrl, a, e.analytics?.endpoint);
3750
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = br(this.opts.baseUrl, a, e.analytics?.endpoint);
3701
3751
  if (!o) {
3702
3752
  s && setTimeout(() => {
3703
3753
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3704
3754
  }, 0);
3705
3755
  return;
3706
3756
  }
3707
- let c = this.opts.video, l = new _r({
3757
+ let c = this.opts.video, l = new xr({
3708
3758
  endpoint: o,
3709
3759
  sid: i,
3710
3760
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3711
- sdkVersion: Cr,
3712
- environment: xr(c),
3761
+ sdkVersion: Dr,
3762
+ environment: Tr(c),
3713
3763
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3714
3764
  onIdle: () => this.onAnalyticsIdle(t),
3715
3765
  onBlocked: (e) => setTimeout(() => {
@@ -3730,7 +3780,7 @@ var ti = class {
3730
3780
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3731
3781
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3732
3782
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3733
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Sr().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3783
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Er().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3734
3784
  }
3735
3785
  currentPresentation() {
3736
3786
  let e = this.opts.video;
@@ -3745,7 +3795,7 @@ var ti = class {
3745
3795
  video: this.opts.video,
3746
3796
  descriptor: e,
3747
3797
  credential: t,
3748
- deviceId: Oe(),
3798
+ deviceId: A(),
3749
3799
  userId: this.opts.userId,
3750
3800
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3751
3801
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -3753,6 +3803,7 @@ var ti = class {
3753
3803
  sizeCapHeadroom: this.opts.sizeCapHeadroom,
3754
3804
  adaptiveHoldBack: this.opts.adaptiveHoldBack,
3755
3805
  adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
3806
+ stallCap: this.opts.stallCap,
3756
3807
  mediaDuringKey: this.opts.mediaDuringKey,
3757
3808
  preloadHints: this.opts.preloadHints,
3758
3809
  debug: this.opts.debug,
@@ -3762,9 +3813,9 @@ var ti = class {
3762
3813
  freshLicenseUrl: () => this.refreshLicense()
3763
3814
  }, o = this.opts.engine ?? "auto";
3764
3815
  if (o === "native") return new H(a);
3765
- if (o === "hls") return new Xn(a);
3766
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && Ot() && B(this.opts.video)) return new H(a);
3767
- if (Wt()) return new Xn(a);
3816
+ if (o === "hls") return new er(a);
3817
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && kt() && B(this.opts.video)) return new H(a);
3818
+ if (Gt()) return new er(a);
3768
3819
  if (B(this.opts.video)) return new H(a);
3769
3820
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3770
3821
  }
@@ -3815,11 +3866,11 @@ var ti = class {
3815
3866
  }
3816
3867
  startLiveState(e) {
3817
3868
  if (this.opts.liveStateEvents === !1) return;
3818
- let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
3869
+ let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3819
3870
  if (!t) return;
3820
3871
  this.closeLiveState();
3821
3872
  let i = 0, a = !1;
3822
- this.liveStateSub = D({
3873
+ this.liveStateSub = E({
3823
3874
  eventsBaseUrl: t,
3824
3875
  matchUrn: this.opts.matchUrn,
3825
3876
  credential: this.opts.credential,
@@ -3831,11 +3882,11 @@ var ti = class {
3831
3882
  },
3832
3883
  onError: (o) => {
3833
3884
  if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
3834
- if (o instanceof E && (o.terminal || o.status === 404)) {
3885
+ if (o instanceof T && (o.terminal || o.status === 404)) {
3835
3886
  a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
3836
3887
  return;
3837
3888
  }
3838
- i += 1, i >= Kr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
3889
+ i += 1, i >= Xr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
3839
3890
  }
3840
3891
  }
3841
3892
  });
@@ -3852,7 +3903,7 @@ var ti = class {
3852
3903
  }
3853
3904
  if (this.emit("online"), this._state !== "error" || !this._lastError) return;
3854
3905
  let t = this._lastError.code;
3855
- Qr(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
3906
+ ni(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
3856
3907
  }));
3857
3908
  }
3858
3909
  watchReturn() {
@@ -3862,7 +3913,7 @@ var ti = class {
3862
3913
  return;
3863
3914
  }
3864
3915
  let e = this.hiddenAtMs;
3865
- this.hiddenAtMs = null, e != null && Date.now() - e >= qr && this.resyncLiveState();
3916
+ this.hiddenAtMs = null, e != null && Date.now() - e >= Zr && this.resyncLiveState();
3866
3917
  }, this.onReturnPageShow = (e) => {
3867
3918
  e.persisted && this.resyncLiveState();
3868
3919
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3894,7 +3945,7 @@ var ti = class {
3894
3945
  scheduleRejoin(e) {
3895
3946
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3896
3947
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3897
- }, Math.random() * Gr));
3948
+ }, Math.random() * Yr));
3898
3949
  }
3899
3950
  cancelRejoin() {
3900
3951
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3918,7 +3969,7 @@ var ti = class {
3918
3969
  }
3919
3970
  t.controls = !1;
3920
3971
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3921
- r && r.insertBefore(n, t), n.appendChild(t), Er(n, this.opts.theme), this.container = n, this.controlBar = Lr({
3972
+ r && r.insertBefore(n, t), n.appendChild(t), Ar(n, this.opts.theme), this.container = n, this.controlBar = Vr({
3922
3973
  root: n,
3923
3974
  video: t,
3924
3975
  player: this,
@@ -3957,7 +4008,7 @@ var ti = class {
3957
4008
  }
3958
4009
  startStats() {
3959
4010
  this.stopStats();
3960
- let e = Math.max(500, this.opts.statsIntervalMs ?? Jr);
4011
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Qr);
3961
4012
  this.statsTimer = setInterval(() => {
3962
4013
  if (!this.engine) return;
3963
4014
  let e = this.engine.getStats();
@@ -3968,14 +4019,14 @@ var ti = class {
3968
4019
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3969
4020
  }
3970
4021
  isStaleLicenseDenial(e) {
3971
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Xr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
4022
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== ei || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
3972
4023
  }
3973
4024
  scheduleLicenseRefresh() {
3974
4025
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3975
4026
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3976
4027
  document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3977
4028
  }, document.addEventListener("visibilitychange", this.onRefocus));
3978
- let e = this.opts.licenseRefreshMs ?? Yr;
4029
+ let e = this.opts.licenseRefreshMs ?? $r;
3979
4030
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3980
4031
  }
3981
4032
  stopRefresh() {
@@ -4071,13 +4122,13 @@ var ti = class {
4071
4122
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
4072
4123
  }
4073
4124
  async enterFullscreen() {
4074
- return !this.destroyed && w(this.opts.video, this.container ?? void 0);
4125
+ return !this.destroyed && C(this.opts.video, this.container ?? void 0);
4075
4126
  }
4076
4127
  async exitFullscreen() {
4077
- await T(this.opts.video, this.container ?? void 0);
4128
+ await w(this.opts.video, this.container ?? void 0);
4078
4129
  }
4079
4130
  fullscreenSupported() {
4080
- return !this.destroyed && C(this.opts.video, this.container ?? void 0);
4131
+ return !this.destroyed && S(this.opts.video, this.container ?? void 0);
4081
4132
  }
4082
4133
  retry() {
4083
4134
  return this.reload();
@@ -4140,12 +4191,12 @@ var ti = class {
4140
4191
  };
4141
4192
  //#endregion
4142
4193
  //#region src/embed/protocol.ts
4143
- function $(e) {
4194
+ function oi(e) {
4144
4195
  return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
4145
4196
  }
4146
4197
  //#endregion
4147
4198
  //#region src/embed/host.ts
4148
- function ni(e) {
4199
+ function si(e) {
4149
4200
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
4150
4201
  if (!e.src) throw Error("mountEmbed: opts.src is required");
4151
4202
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -4154,7 +4205,7 @@ function ni(e) {
4154
4205
  let r = document.createElement("iframe");
4155
4206
  r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
4156
4207
  let i = /* @__PURE__ */ new Set(), a = (t) => {
4157
- if (t.source !== r.contentWindow || t.origin !== n || !$(t.data)) return;
4208
+ if (t.source !== r.contentWindow || t.origin !== n || !oi(t.data)) return;
4158
4209
  let a = t.data;
4159
4210
  a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
4160
4211
  };
@@ -4204,15 +4255,15 @@ function ni(e) {
4204
4255
  }
4205
4256
  //#endregion
4206
4257
  //#region src/embed/page.ts
4207
- var ri = /^[A-Za-z0-9:_.-]{1,128}$/;
4208
- function ii(e) {
4258
+ var ci = /^[A-Za-z0-9:_.-]{1,128}$/;
4259
+ function li(e) {
4209
4260
  if (typeof e == "boolean") return e;
4210
4261
  if (typeof e == "object" && e) {
4211
4262
  let t = e.endpoint;
4212
4263
  return typeof t == "string" ? { endpoint: t } : {};
4213
4264
  }
4214
4265
  }
4215
- function ai() {
4266
+ function ui() {
4216
4267
  let e = window.HAVIK_EMBED_CONFIG;
4217
4268
  if (e) return {
4218
4269
  baseUrl: e.baseUrl ?? "",
@@ -4222,7 +4273,7 @@ function ai() {
4222
4273
  autoplay: e.autoplay ?? !0,
4223
4274
  muted: e.muted ?? !0,
4224
4275
  waitForLive: e.waitForLive ?? !0,
4225
- analytics: ii(e.analytics)
4276
+ analytics: li(e.analytics)
4226
4277
  };
4227
4278
  let t = new URLSearchParams(location.search);
4228
4279
  return {
@@ -4235,9 +4286,9 @@ function ai() {
4235
4286
  waitForLive: !0
4236
4287
  };
4237
4288
  }
4238
- async function oi() {
4239
- let e = ai();
4240
- ci();
4289
+ async function di() {
4290
+ let e = ui();
4291
+ pi();
4241
4292
  let t = document.createElement("video");
4242
4293
  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);
4243
4294
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -4293,12 +4344,12 @@ async function oi() {
4293
4344
  message: e.message,
4294
4345
  ...e.country === void 0 ? {} : { country: e.country }
4295
4346
  })), e.on("autoplayblocked", () => {
4296
- i({ type: "oddin:autoplayblocked" }), si(t, e);
4347
+ i({ type: "oddin:autoplayblocked" }), fi(t, e);
4297
4348
  });
4298
4349
  }, s = async (r) => {
4299
4350
  a?.destroy(), a = null;
4300
4351
  try {
4301
- let n = await ei({
4352
+ let n = await ii({
4302
4353
  video: t,
4303
4354
  baseUrl: e.baseUrl,
4304
4355
  matchUrn: r,
@@ -4361,30 +4412,30 @@ async function oi() {
4361
4412
  a?.retry();
4362
4413
  break;
4363
4414
  case "oddin:load":
4364
- typeof e.matchUrn == "string" && ri.test(e.matchUrn) && s(e.matchUrn);
4415
+ typeof e.matchUrn == "string" && ci.test(e.matchUrn) && s(e.matchUrn);
4365
4416
  break;
4366
4417
  case "oddin:destroy": c();
4367
4418
  }
4368
4419
  }, u = (e) => {
4369
- r && e.origin === r && $(e.data) && l(e.data);
4420
+ r && e.origin === r && oi(e.data) && l(e.data);
4370
4421
  };
4371
4422
  r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
4372
4423
  type: "oddin:ready",
4373
4424
  protocol: 1
4374
4425
  });
4375
4426
  }
4376
- function si(e, t) {
4427
+ function fi(e, t) {
4377
4428
  if (document.getElementById("havik-tap")) return;
4378
4429
  let n = document.createElement("button");
4379
4430
  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", () => {
4380
4431
  n.remove(), t.play();
4381
4432
  }), document.body.appendChild(n);
4382
4433
  }
4383
- function ci() {
4434
+ function pi() {
4384
4435
  let e = document.createElement("style");
4385
4436
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
4386
4437
  }
4387
4438
  //#endregion
4388
- export { E as LiveStateHttpError, wr as ODDIN_THEME, n as PlaybackError, Er as applyTheme, lt as baseUrlForEnv, oi as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, ei as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, ni as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4439
+ export { T as LiveStateHttpError, Or as ODDIN_THEME, n as PlaybackError, Ar as applyTheme, lt as baseUrlForEnv, di as bootEmbed, Oe as clearDeviceId, Be as clearRememberedBandwidth, ii as createPlayer, D as deriveEventsBaseUrl, at as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, ye as fetchCatalog, xe as fetchTournament, Ce as flattenMatches, S as fullscreenSupported, A as getDeviceId, st as isLowLatencyManifest, oi as isOddinMessage, Ae as licenseRequestHeaders, si as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, ve as videoFullscreenActive, Te as watchStatus };
4389
4440
 
4390
4441
  //# sourceMappingURL=index.js.map