@oddin-gg/havik-player 2.1.0 → 2.1.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
@@ -244,32 +244,32 @@ function ce(e, t) {
244
244
  function S(e) {
245
245
  return e.ownerDocument ?? document;
246
246
  }
247
- function C(e) {
247
+ function le(e) {
248
248
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
249
249
  }
250
- function w(e, t) {
251
- let n = C(S(e));
250
+ function C(e, t) {
251
+ let n = le(S(e));
252
252
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
253
253
  }
254
- async function T(e, t) {
254
+ async function w(e, t) {
255
255
  let n = t ?? e;
256
256
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
257
257
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
258
258
  let r = e;
259
259
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
260
260
  }
261
- async function E(e, t) {
261
+ async function T(e, t) {
262
262
  let n = e;
263
263
  if (n.webkitDisplayingFullscreen) {
264
264
  n.webkitExitFullscreen?.();
265
265
  return;
266
266
  }
267
- let r = S(e), i = C(r);
267
+ let r = S(e), i = le(r);
268
268
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
269
269
  }
270
270
  //#endregion
271
271
  //#region src/core/catalog.ts
272
- async function le(e) {
272
+ async function ue(e) {
273
273
  let t = new URLSearchParams();
274
274
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
275
275
  let i = t.toString(), a = c(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -287,12 +287,12 @@ async function le(e) {
287
287
  };
288
288
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
289
289
  return {
290
- tournaments: ue(await s.json()),
290
+ tournaments: de(await s.json()),
291
291
  etag: s.headers.get("etag") ?? void 0,
292
292
  notModified: !1
293
293
  };
294
294
  }
295
- function ue(e) {
295
+ function de(e) {
296
296
  return (e.tournaments ?? []).map((e) => {
297
297
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
298
298
  return {
@@ -312,7 +312,7 @@ function ue(e) {
312
312
  };
313
313
  });
314
314
  }
315
- async function de(e) {
315
+ async function fe(e) {
316
316
  let t = c(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
317
317
  e.etag && i.set("If-None-Match", e.etag);
318
318
  let a = await u(t, {
@@ -332,13 +332,13 @@ async function de(e) {
332
332
  };
333
333
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
334
334
  return {
335
- tournament: fe(await a.json()),
335
+ tournament: pe(await a.json()),
336
336
  etag: a.headers.get("etag") ?? void 0,
337
337
  notModified: !1,
338
338
  notFound: !1
339
339
  };
340
340
  }
341
- function fe(e) {
341
+ function pe(e) {
342
342
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
343
343
  return {
344
344
  urn: t,
@@ -356,12 +356,12 @@ function fe(e) {
356
356
  }))
357
357
  };
358
358
  }
359
- function pe(e) {
359
+ function me(e) {
360
360
  return e.tournaments.flatMap((e) => e.matches);
361
361
  }
362
362
  //#endregion
363
363
  //#region src/core/poll.ts
364
- function me(e) {
364
+ function he(e) {
365
365
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, l = !1, d = () => {
366
366
  l || (a = setTimeout(f, t));
367
367
  }, f = async () => {
@@ -397,7 +397,7 @@ function me(e) {
397
397
  }
398
398
  //#endregion
399
399
  //#region src/core/events.ts
400
- function D(e) {
400
+ function E(e) {
401
401
  let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = new AbortController(), i = !1, a = (e) => new Promise((t) => {
402
402
  if (r.signal.aborted) return t();
403
403
  let n = setTimeout(t, e);
@@ -464,7 +464,7 @@ function D(e) {
464
464
  i || (i = !0, r.abort());
465
465
  } };
466
466
  }
467
- function O(e) {
467
+ function D(e) {
468
468
  try {
469
469
  let t = new URL(e);
470
470
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -474,27 +474,27 @@ function O(e) {
474
474
  }
475
475
  //#endregion
476
476
  //#region src/core/drm/deviceId.ts
477
- var k = "havik.player.deviceId", A;
478
- function j() {
479
- if (A) return A;
477
+ var O = "havik.player.deviceId", k;
478
+ function A() {
479
+ if (k) return k;
480
480
  try {
481
- let e = globalThis.localStorage?.getItem(k);
482
- if (e) return A = e, e;
481
+ let e = globalThis.localStorage?.getItem(O);
482
+ if (e) return k = e, e;
483
483
  } catch {}
484
- let e = ge();
485
- A = e;
484
+ let e = _e();
485
+ k = e;
486
486
  try {
487
- globalThis.localStorage?.setItem(k, e);
487
+ globalThis.localStorage?.setItem(O, e);
488
488
  } catch {}
489
489
  return e;
490
490
  }
491
- function he() {
492
- A = void 0;
491
+ function ge() {
492
+ k = void 0;
493
493
  try {
494
- globalThis.localStorage?.removeItem(k);
494
+ globalThis.localStorage?.removeItem(O);
495
495
  } catch {}
496
496
  }
497
- function ge() {
497
+ function _e() {
498
498
  let e = globalThis.crypto;
499
499
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
500
500
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -506,22 +506,22 @@ function ge() {
506
506
  }
507
507
  //#endregion
508
508
  //#region src/core/drm/headers.ts
509
- function _e(e, t, n = {}) {
509
+ function ve(e, t, n = {}) {
510
510
  let r = {
511
511
  "x-api-key": t.apiKey,
512
512
  "X-Match-Urn": e.matchUrn,
513
- "X-Device-Id": n.deviceId ?? j(),
513
+ "X-Device-Id": n.deviceId ?? A(),
514
514
  "Content-Type": "application/octet-stream"
515
515
  };
516
516
  return n.userId && (r["X-User-Id"] = n.userId), r;
517
517
  }
518
518
  //#endregion
519
519
  //#region src/core/drm/support.ts
520
- var ve = 5e3, M = "video/mp4; codecs=\"avc1.42E01E\"", N = "audio/mp4; codecs=\"mp4a.40.2\"", ye = {
520
+ var ye = 5e3, j = "video/mp4; codecs=\"avc1.42E01E\"", M = "audio/mp4; codecs=\"mp4a.40.2\"", be = {
521
521
  widevine: ["com.widevine.alpha"],
522
522
  fairplay: ["com.apple.fps"]
523
523
  };
524
- function be(e) {
524
+ function xe(e) {
525
525
  return e === "fairplay" ? [{
526
526
  initDataTypes: [
527
527
  "sinf",
@@ -529,30 +529,30 @@ function be(e) {
529
529
  "cenc"
530
530
  ],
531
531
  videoCapabilities: [{
532
- contentType: M,
532
+ contentType: j,
533
533
  robustness: "",
534
534
  encryptionScheme: "cbcs"
535
535
  }],
536
536
  audioCapabilities: [{
537
- contentType: N,
537
+ contentType: M,
538
538
  robustness: "",
539
539
  encryptionScheme: "cbcs"
540
540
  }]
541
541
  }] : [{
542
542
  initDataTypes: ["cenc"],
543
543
  videoCapabilities: [{
544
- contentType: M,
544
+ contentType: j,
545
545
  robustness: "SW_SECURE_DECODE",
546
546
  encryptionScheme: "cbcs"
547
547
  }],
548
548
  audioCapabilities: [{
549
- contentType: N,
549
+ contentType: M,
550
550
  robustness: "SW_SECURE_CRYPTO",
551
551
  encryptionScheme: "cbcs"
552
552
  }]
553
553
  }];
554
554
  }
555
- function P(e, t) {
555
+ function N(e, t) {
556
556
  return new Promise((n, r) => {
557
557
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
558
558
  e.then((e) => {
@@ -562,8 +562,8 @@ function P(e, t) {
562
562
  });
563
563
  });
564
564
  }
565
- async function xe(e = {}) {
566
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? ve, r = {};
565
+ async function Se(e = {}) {
566
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? ye, r = {};
567
567
  if (typeof window < "u" && window.isSecureContext === !1) return {
568
568
  verdict: "insecure-context",
569
569
  detail: r
@@ -575,7 +575,7 @@ async function xe(e = {}) {
575
575
  };
576
576
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
577
577
  for (let e of t) {
578
- let t = ye[e];
578
+ let t = be[e];
579
579
  if (!t) {
580
580
  r[e] = "unknown system";
581
581
  continue;
@@ -586,7 +586,7 @@ async function xe(e = {}) {
586
586
  break;
587
587
  }
588
588
  try {
589
- return await P((await P(i(n, be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
589
+ return await N((await N(i(n, xe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
590
590
  verdict: "supported",
591
591
  system: e,
592
592
  detail: r
@@ -610,21 +610,44 @@ async function xe(e = {}) {
610
610
  }
611
611
  //#endregion
612
612
  //#region src/core/manifest.ts
613
- var Se = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
614
- function Ce(e) {
615
- return Se.test(e);
613
+ var Ce = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
614
+ function we(e) {
615
+ return Ce.test(e);
616
+ }
617
+ //#endregion
618
+ //#region src/core/drm/cdm.ts
619
+ var Te = /* @__PURE__ */ new WeakMap();
620
+ function Ee(e, t) {
621
+ let n = Te.get(e);
622
+ n || (n = /* @__PURE__ */ new Map(), Te.set(e, n));
623
+ let r = n.get(t.keySystem);
624
+ if (r) return r;
625
+ let i = t.createMediaKeys().catch((e) => {
626
+ throw n.get(t.keySystem) === i && n.delete(t.keySystem), e;
627
+ });
628
+ return n.set(t.keySystem, i), i;
629
+ }
630
+ function P() {
631
+ return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
632
+ }
633
+ function De(e) {
634
+ return (t, n) => P() ? navigator.requestMediaKeySystemAccess(t, n).then((t) => ({
635
+ keySystem: t.keySystem,
636
+ getConfiguration: () => t.getConfiguration(),
637
+ createMediaKeys: () => Ee(e, t)
638
+ })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
616
639
  }
617
640
  //#endregion
618
641
  //#region src/core/stats.ts
619
- var we = { droppedFrames: 0 };
620
- function F(e) {
642
+ var F = { droppedFrames: 0 };
643
+ function I(e) {
621
644
  let t = e.getVideoPlaybackQuality?.();
622
645
  return {
623
646
  dropped: t?.droppedVideoFrames ?? 0,
624
647
  decoded: t?.totalVideoFrames ?? 0
625
648
  };
626
649
  }
627
- function Te(e, t) {
650
+ function Oe(e, t) {
628
651
  let n = [
629
652
  ["playing", () => t("playing")],
630
653
  ["waiting", () => t("buffering")],
@@ -641,7 +664,7 @@ function Te(e, t) {
641
664
  }
642
665
  //#endregion
643
666
  //#region src/core/engine/native.ts
644
- function Ee(e) {
667
+ function ke(e) {
645
668
  try {
646
669
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
647
670
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -649,15 +672,15 @@ function Ee(e) {
649
672
  return;
650
673
  }
651
674
  }
652
- function I(e) {
675
+ function L(e) {
653
676
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
654
677
  }
655
- function L() {
678
+ function R() {
656
679
  if (typeof window > "u") return !1;
657
680
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
658
681
  return e || t;
659
682
  }
660
- var R = class {
683
+ var z = class {
661
684
  name = "native";
662
685
  deps;
663
686
  onLoaded;
@@ -691,7 +714,7 @@ var R = class {
691
714
  type: "error",
692
715
  error: new n("INTERNAL", 0, "native HLS playback error"),
693
716
  fatal: !0
694
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = De(t.manifestUrl, t.analytics?.sid), e.load();
717
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ae(t.manifestUrl, t.analytics?.sid), e.load();
695
718
  }
696
719
  startLoad() {
697
720
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -713,7 +736,7 @@ var R = class {
713
736
  });
714
737
  this.onEncrypted = (n) => {
715
738
  let i = n;
716
- !i.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = Ee(i.initData), (async () => {
739
+ !i.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = ke(i.initData), (async () => {
717
740
  try {
718
741
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
719
742
  initDataTypes: [i.initDataType],
@@ -808,7 +831,7 @@ var R = class {
808
831
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
809
832
  }
810
833
  getStats() {
811
- let e = this.deps.video, t = F(e), n = {
834
+ let e = this.deps.video, t = I(e), n = {
812
835
  droppedFrames: t.dropped,
813
836
  decodedFrames: t.decoded
814
837
  };
@@ -831,36 +854,36 @@ var R = class {
831
854
  } catch {}
832
855
  }
833
856
  };
834
- function De(e, t) {
857
+ function Ae(e, t) {
835
858
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
836
859
  }
837
860
  //#endregion
838
861
  //#region src/core/engine/hls.ts
839
- function Oe() {
862
+ function je() {
840
863
  return e.isSupported();
841
864
  }
842
- var ke = 3, Ae = 5, je = 3, Me = 3e4, Ne = 12e3, Pe = 3e3, z = 6e3, Fe = 4e3, Ie = 2, Le = 5, Re = 2, ze = 2, Be = 2e3, Ve = 3e4, He = 2, Ue = 9, We = .5, Ge = 64;
843
- function Ke(e) {
865
+ var Me = 3, Ne = 5, Pe = 3, Fe = 3e4, Ie = 12e3, Le = 3e3, B = 6e3, Re = 4e3, ze = 2, Be = 5, Ve = 2, He = 2, Ue = 2e3, We = 3e4, Ge = 2, Ke = 9, qe = .5, Je = 64;
866
+ function Ye(e) {
844
867
  try {
845
868
  return new URL(e).host;
846
869
  } catch {
847
870
  return "";
848
871
  }
849
872
  }
850
- function qe(e) {
873
+ function Xe(e) {
851
874
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
852
875
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
853
876
  return;
854
877
  }
855
- e.liveSyncDuration ??= He;
856
- let t = Math.max(12, e.liveSyncDuration + Ue);
857
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Je(e, e.liveSyncDuration);
878
+ e.liveSyncDuration ??= Ge;
879
+ let t = Math.max(12, e.liveSyncDuration + Ke);
880
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ze(e, e.liveSyncDuration);
858
881
  }
859
- function Je(e, t) {
882
+ function Ze(e, t) {
860
883
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
861
884
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
862
885
  }
863
- var B = class {
886
+ var V = class {
864
887
  name = "hls";
865
888
  hls = null;
866
889
  deps;
@@ -914,7 +937,7 @@ var B = class {
914
937
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
915
938
  }
916
939
  async load() {
917
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = I(r) && L(), o = !!e.drm?.widevine?.licenseUrl && !a;
940
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = L(r) && R(), o = !!e.drm?.widevine?.licenseUrl && !a;
918
941
  if (e.drmEnabled && !o) {
919
942
  i({
920
943
  type: "error",
@@ -954,7 +977,7 @@ var B = class {
954
977
  let t = e.liveSyncPosition;
955
978
  if (typeof t != "number" || !Number.isFinite(t)) return;
956
979
  let { video: n } = this.deps;
957
- n.currentTime <= t + We || (n.currentTime = t);
980
+ n.currentTime <= t + qe || (n.currentTime = t);
958
981
  }
959
982
  startHls() {
960
983
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -978,6 +1001,7 @@ var B = class {
978
1001
  videoEncryptionScheme: "cbcs",
979
1002
  audioEncryptionScheme: "cbcs"
980
1003
  },
1004
+ ...P() ? { requestMediaKeySystemAccessFunc: De(t) } : {},
981
1005
  licenseXhrSetup: (e, t) => {
982
1006
  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;
983
1007
  let o = performance.now();
@@ -993,7 +1017,7 @@ var B = class {
993
1017
  } } : {},
994
1018
  ...c
995
1019
  };
996
- qe(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1020
+ Xe(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
997
1021
  let f = new e(d);
998
1022
  this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
999
1023
  this.mediaRecoveries = 0, this.networkRecoveries = 0;
@@ -1002,17 +1026,17 @@ var B = class {
1002
1026
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1003
1027
  t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1004
1028
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1005
- }, Me)));
1029
+ }, Fe)));
1006
1030
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1007
1031
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1008
1032
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
1009
1033
  let n = t?.frag?.stats, r = n?.loaded;
1010
1034
  typeof r == "number" && (this.bytesLoaded += r);
1011
1035
  let i = n?.loading;
1012
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ge && this.requestTimesMs.shift());
1036
+ i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Je && this.requestTimesMs.shift());
1013
1037
  let a = t?.frag?.url;
1014
1038
  if (a) {
1015
- let e = Ke(a);
1039
+ let e = Ye(a);
1016
1040
  e && (this.cdnHost = e);
1017
1041
  }
1018
1042
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1025,7 +1049,7 @@ var B = class {
1025
1049
  }));
1026
1050
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1027
1051
  this.checkEndStale(), this.checkStarvation();
1028
- }, Pe), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1052
+ }, Le), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1029
1053
  this.renditionSwitches += 1;
1030
1054
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1031
1055
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1089,7 +1113,7 @@ var B = class {
1089
1113
  return;
1090
1114
  }
1091
1115
  this.capTimer && clearTimeout(this.capTimer);
1092
- let t = e > this.sizeCapLevel ? Be : Ve;
1116
+ let t = e > this.sizeCapLevel ? Ue : We;
1093
1117
  this.capTimer = setTimeout(() => {
1094
1118
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1095
1119
  }, t);
@@ -1136,7 +1160,7 @@ var B = class {
1136
1160
  e.widevine && (this.licenseUrl = e.widevine);
1137
1161
  }
1138
1162
  getStats() {
1139
- let e = this.hls, t = F(this.deps.video), n = {
1163
+ let e = this.hls, t = I(this.deps.video), n = {
1140
1164
  droppedFrames: t.dropped,
1141
1165
  decodedFrames: t.decoded,
1142
1166
  lowLatency: this.detectedLowLatency,
@@ -1178,7 +1202,7 @@ var B = class {
1178
1202
  return;
1179
1203
  }
1180
1204
  let e = Date.now() - this.lastAdvanceMs;
1181
- !this.chaseSuspended && e > z && this.suspendChasing(), e > Ne && this.emitEnded("stalled");
1205
+ !this.chaseSuspended && e > B && this.suspendChasing(), e > Ie && this.emitEnded("stalled");
1182
1206
  }
1183
1207
  checkStarvation() {
1184
1208
  let e = this.hls, { video: t } = this.deps;
@@ -1187,17 +1211,17 @@ var B = class {
1187
1211
  this.starvedTicks = 0;
1188
1212
  return;
1189
1213
  }
1190
- let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < z, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Fe;
1214
+ let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < B, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Re;
1191
1215
  if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
1192
1216
  this.starvedTicks = 0;
1193
1217
  return;
1194
1218
  }
1195
- if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ie)) {
1196
- if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Re && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < ze)) {
1219
+ if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < ze)) {
1220
+ if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ve && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < He)) {
1197
1221
  this.starvationRebuilds += 1, console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
1198
1222
  return;
1199
1223
  }
1200
- if (!(this.starvationKicks >= Le)) {
1224
+ if (!(this.starvationKicks >= Be)) {
1201
1225
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1202
1226
  try {
1203
1227
  e.stopLoad(), e.startLoad(-1);
@@ -1247,7 +1271,7 @@ var B = class {
1247
1271
  scheduleLicenseRetry(t) {
1248
1272
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1249
1273
  let n = t.response?.code ?? 0;
1250
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= je) return !1;
1274
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Pe) return !1;
1251
1275
  this.licenseRecoveries += 1;
1252
1276
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1253
1277
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1279,7 +1303,7 @@ var B = class {
1279
1303
  return;
1280
1304
  }
1281
1305
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1282
- if (this.networkRecoveries < Ae) {
1306
+ if (this.networkRecoveries < Ne) {
1283
1307
  this.networkRecoveries += 1;
1284
1308
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1285
1309
  this.networkRetryTimer = setTimeout(() => {
@@ -1296,7 +1320,7 @@ var B = class {
1296
1320
  return;
1297
1321
  }
1298
1322
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1299
- if (this.mediaRecoveries < ke) {
1323
+ if (this.mediaRecoveries < Me) {
1300
1324
  this.mediaRecoveries += 1, n.recoverMediaError();
1301
1325
  return;
1302
1326
  }
@@ -1320,19 +1344,19 @@ var B = class {
1320
1344
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1321
1345
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1322
1346
  }
1323
- }, Ye = 15e3, Xe = 100, V = 1, Ze = 1e3, H = 3e4, Qe = {
1347
+ }, Qe = 15e3, $e = 100, H = 1, et = 1e3, U = 3e4, tt = {
1324
1348
  inline: "PRESENTATION_INLINE",
1325
1349
  fullscreen: "PRESENTATION_FULLSCREEN",
1326
1350
  pip: "PRESENTATION_PIP"
1327
- }, $e = {
1351
+ }, nt = {
1328
1352
  widevine: "KEY_SYSTEM_WIDEVINE",
1329
1353
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1330
1354
  none: "KEY_SYSTEM_NONE"
1331
1355
  };
1332
- function U(e, t) {
1356
+ function W(e, t) {
1333
1357
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1334
1358
  }
1335
- var et = /* @__PURE__ */ new Set([
1359
+ var rt = /* @__PURE__ */ new Set([
1336
1360
  "INVALID_URN",
1337
1361
  "NOT_FOUND",
1338
1362
  "GONE",
@@ -1342,7 +1366,7 @@ var et = /* @__PURE__ */ new Set([
1342
1366
  "FORBIDDEN",
1343
1367
  "RATE_LIMITED",
1344
1368
  "TIMEOUT"
1345
- ]), W = {
1369
+ ]), G = {
1346
1370
  idle: "PLAYER_STATE_IDLE",
1347
1371
  waiting: "PLAYER_STATE_WAITING",
1348
1372
  loading: "PLAYER_STATE_LOADING",
@@ -1352,7 +1376,7 @@ var et = /* @__PURE__ */ new Set([
1352
1376
  ended: "PLAYER_STATE_ENDED",
1353
1377
  error: "PLAYER_STATE_ERROR"
1354
1378
  };
1355
- function tt(e) {
1379
+ function it(e) {
1356
1380
  try {
1357
1381
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1358
1382
  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);
@@ -1360,7 +1384,7 @@ function tt(e) {
1360
1384
  return;
1361
1385
  }
1362
1386
  }
1363
- var nt = class {
1387
+ var at = class {
1364
1388
  opts;
1365
1389
  url;
1366
1390
  now;
@@ -1426,7 +1450,7 @@ var nt = class {
1426
1450
  constructor(e) {
1427
1451
  this.opts = {
1428
1452
  ...e,
1429
- heartbeatMs: e.heartbeatMs ?? Ye
1453
+ heartbeatMs: e.heartbeatMs ?? Qe
1430
1454
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs;
1431
1455
  }
1432
1456
  start() {
@@ -1436,16 +1460,16 @@ var nt = class {
1436
1460
  sdkVersion: this.opts.sdkVersion,
1437
1461
  ...this.opts.environment
1438
1462
  };
1439
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ze), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), this.onVisibility());
1463
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), et), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), this.onVisibility());
1440
1464
  }
1441
1465
  noteStateChange(e, t, n, r) {
1442
1466
  if (this.endedFlag || e === t) return;
1443
1467
  let i = this.now();
1444
- t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(V, i - this.bornMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(V, i - this.bornMs)), 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" ? (this.rebufferCount += 1, this.bufferingSinceMs = i, this.lastStallMs = i, this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(V, Math.round(this.playingTotalMs)))) : e === "buffering" && this.bufferingSinceMs !== null && (this.rebufferTotalMs += i - this.bufferingSinceMs, this.bufferingSinceMs = null), t === "paused" && (this.pauseCount += 1);
1468
+ t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(H, i - this.bornMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(H, i - this.bornMs)), 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" ? (this.rebufferCount += 1, this.bufferingSinceMs = i, this.lastStallMs = i, this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(H, Math.round(this.playingTotalMs)))) : e === "buffering" && this.bufferingSinceMs !== null && (this.rebufferTotalMs += i - this.bufferingSinceMs, this.bufferingSinceMs = null), t === "paused" && (this.pauseCount += 1);
1445
1469
  let a = {
1446
- fromState: W[e] ?? "PLAYER_STATE_UNSPECIFIED",
1447
- toState: W[t] ?? "PLAYER_STATE_UNSPECIFIED",
1448
- presentation: Qe[this.presentation]
1470
+ fromState: G[e] ?? "PLAYER_STATE_UNSPECIFIED",
1471
+ toState: G[t] ?? "PLAYER_STATE_UNSPECIFIED",
1472
+ presentation: tt[this.presentation]
1449
1473
  }, o = this.causeOf(e, t, i);
1450
1474
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1451
1475
  }
@@ -1480,16 +1504,16 @@ var nt = class {
1480
1504
  }
1481
1505
  this.muteChanges += 1;
1482
1506
  let r = this.now();
1483
- 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(V, r - this.bornMs))), this.isMuted = n, this.syncActive();
1507
+ 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(H, r - this.bornMs))), this.isMuted = n, this.syncActive();
1484
1508
  }
1485
1509
  notePresentation(e) {
1486
1510
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1487
1511
  }
1488
1512
  noteReady() {
1489
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(V, this.now() - this.bornMs));
1513
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(H, this.now() - this.bornMs));
1490
1514
  }
1491
1515
  noteFirstBytes() {
1492
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(V, this.now() - this.bornMs));
1516
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(H, this.now() - this.bornMs));
1493
1517
  }
1494
1518
  noteSeek() {
1495
1519
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -1508,7 +1532,7 @@ var nt = class {
1508
1532
  let r = n ?? "";
1509
1533
  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";
1510
1534
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
1511
- if (et.has(e)) return "ERROR_STAGE_RESOLVE";
1535
+ if (rt.has(e)) return "ERROR_STAGE_RESOLVE";
1512
1536
  let i = t ?? "";
1513
1537
  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";
1514
1538
  }
@@ -1534,7 +1558,7 @@ var nt = class {
1534
1558
  let s = e.droppedFrames ?? 0;
1535
1559
  s > this.lastDropped && (i.droppedFramesDelta = s - this.lastDropped), this.lastDropped = s;
1536
1560
  let c = e.renditionSwitches ?? 0;
1537
- c > this.lastSwitches && (i.renditionSwitchesDelta = c - this.lastSwitches), this.lastSwitches = c, n > this.lastHbPlayingMs && (i.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (i.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, typeof e.latencySeconds == "number" && (i.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (i.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (i.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (i.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (i.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (i.atLiveEdge = !0), typeof e.bufferedMs == "number" && e.bufferedMs > 0 && (i.bufferedMs = Math.round(e.bufferedMs)), i.playerState = W[e.state] ?? "PLAYER_STATE_UNSPECIFIED";
1561
+ c > this.lastSwitches && (i.renditionSwitchesDelta = c - this.lastSwitches), this.lastSwitches = c, n > this.lastHbPlayingMs && (i.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (i.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, typeof e.latencySeconds == "number" && (i.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (i.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (i.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (i.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (i.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (i.atLiveEdge = !0), typeof e.bufferedMs == "number" && e.bufferedMs > 0 && (i.bufferedMs = Math.round(e.bufferedMs)), i.playerState = G[e.state] ?? "PLAYER_STATE_UNSPECIFIED";
1538
1562
  let l = this.mutedTotalMs;
1539
1563
  this.mutedSinceMs !== null && (l += t - this.mutedSinceMs), l > this.lastHbMutedMs && (i.mutedMsDelta = Math.round(l - this.lastHbMutedMs)), this.lastHbMutedMs = l;
1540
1564
  let u = e.upshifts ?? 0;
@@ -1549,14 +1573,14 @@ var nt = class {
1549
1573
  if (this.lastRequestCount = m, h > 0) {
1550
1574
  i.requestCountDelta = h;
1551
1575
  let t = e.requestTimesMs ?? [], n = t.slice(Math.max(0, t.length - h)).sort((e, t) => e - t);
1552
- n.length > 0 && (i.requestTimeP50Ms = U(n, 50), i.requestTimeP95Ms = U(n, 95));
1576
+ n.length > 0 && (i.requestTimeP50Ms = W(n, 50), i.requestTimeP95Ms = W(n, 95));
1553
1577
  }
1554
1578
  typeof e.latencySeconds == "number" && typeof e.targetLatencySeconds == "number" && (i.driftMs = Math.round((e.latencySeconds - e.targetLatencySeconds) * 1e3)), typeof e.playbackRate == "number" && e.playbackRate > 0 && (i.playbackRate = e.playbackRate), e.qualityPinned === !0 && (i.qualityPinned = !0), e.cdnHost && (i.cdnHost = e.cdnHost), this.maybeEmitMediaInfo(e), this.enqueue({ heartbeat: i }), this.flush(), a > 0 && this.noteFirstBytes();
1555
1579
  }
1556
1580
  maybeEmitMediaInfo(e) {
1557
1581
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
1558
1582
  let t = {};
1559
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = $e[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);
1583
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = nt[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);
1560
1584
  let n = JSON.stringify(t);
1561
1585
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
1562
1586
  }
@@ -1576,7 +1600,7 @@ var nt = class {
1576
1600
  let s = n?.positionMs ?? 0;
1577
1601
  s > 0 && (r.exitPositionMs = Math.round(s)), this.activeTotalMs > 0 && (r.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (r.mutedTimeMs = Math.round(this.mutedTotalMs));
1578
1602
  let c = e !== "END_REASON_ENDED";
1579
- c && this.lastStallMs > 0 && t - this.lastStallMs <= H && (r.abandonAfterStallMs = Math.max(V, Math.round(t - this.lastStallMs))), c && this.lastErrorMs > 0 && t - this.lastErrorMs <= H && (r.abandonAfterErrorMs = Math.max(V, Math.round(t - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (r.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (r.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (r.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (r.muteChanges = this.muteChanges);
1603
+ c && this.lastStallMs > 0 && t - this.lastStallMs <= U && (r.abandonAfterStallMs = Math.max(H, Math.round(t - this.lastStallMs))), c && this.lastErrorMs > 0 && t - this.lastErrorMs <= U && (r.abandonAfterErrorMs = Math.max(H, Math.round(t - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (r.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (r.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (r.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (r.muteChanges = this.muteChanges);
1580
1604
  let l = n?.decodedFrames ?? this.lastDecoded;
1581
1605
  l > 0 && (r.decodedFramesTotal = l), this.startupTimeMs === 0 && (r.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: r })), this.flush(e === "END_REASON_PAGEHIDE");
1582
1606
  }
@@ -1596,7 +1620,7 @@ var nt = class {
1596
1620
  };
1597
1621
  }
1598
1622
  enqueue(e) {
1599
- for (this.pending.push(this.wrap(e)); this.pending.length > Xe;) {
1623
+ for (this.pending.push(this.wrap(e)); this.pending.length > $e;) {
1600
1624
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
1601
1625
  this.pending.splice(e >= 0 ? e : 0, 1);
1602
1626
  }
@@ -1621,7 +1645,7 @@ var nt = class {
1621
1645
  };
1622
1646
  //#endregion
1623
1647
  //#region src/core/environment.ts
1624
- function rt() {
1648
+ function ot() {
1625
1649
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
1626
1650
  let e;
1627
1651
  try {
@@ -1646,14 +1670,14 @@ function rt() {
1646
1670
  integration: "INTEGRATION_KIND_IFRAME"
1647
1671
  };
1648
1672
  }
1649
- function it() {
1673
+ function st() {
1650
1674
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
1651
1675
  let e = navigator.userAgentData, t = e?.platform ?? "";
1652
1676
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
1653
1677
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
1654
1678
  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";
1655
1679
  }
1656
- function at() {
1680
+ function ct() {
1657
1681
  let e = typeof navigator < "u" ? navigator.connection : void 0;
1658
1682
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
1659
1683
  let t = { connectionType: e.type ? {
@@ -1663,17 +1687,17 @@ function at() {
1663
1687
  }[e.type] ?? "CONNECTION_TYPE_OTHER" : "CONNECTION_TYPE_UNKNOWN" };
1664
1688
  return typeof e.downlink == "number" && e.downlink > 0 && (t.downlinkKbps = Math.round(e.downlink * 1e3)), e.saveData && (t.saveData = !0), t;
1665
1689
  }
1666
- function ot(e) {
1667
- let t = rt(), n = {
1668
- deviceClass: it(),
1690
+ function lt(e) {
1691
+ let t = ot(), n = {
1692
+ deviceClass: st(),
1669
1693
  integration: t.integration,
1670
- ...at()
1694
+ ...ct()
1671
1695
  };
1672
1696
  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);
1673
1697
  let r = e.getBoundingClientRect?.();
1674
1698
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
1675
1699
  }
1676
- async function st() {
1700
+ async function ut() {
1677
1701
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
1678
1702
  if (!e?.getHighEntropyValues) return {};
1679
1703
  try {
@@ -1685,7 +1709,7 @@ async function st() {
1685
1709
  }
1686
1710
  //#endregion
1687
1711
  //#region src/core/version.ts
1688
- var ct = "2.1.0", G = {
1712
+ var dt = "2.1.1", K = {
1689
1713
  accent: "#E1B600",
1690
1714
  accentText: "#1B1C23",
1691
1715
  background: "#0e0f13",
@@ -1696,7 +1720,7 @@ var ct = "2.1.0", G = {
1696
1720
  border: "rgba(255, 255, 255, 0.1)",
1697
1721
  radius: "8px",
1698
1722
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1699
- }, K = {
1723
+ }, q = {
1700
1724
  accent: "--havik-accent",
1701
1725
  accentText: "--havik-accent-text",
1702
1726
  background: "--havik-bg",
@@ -1708,25 +1732,25 @@ var ct = "2.1.0", G = {
1708
1732
  radius: "--havik-radius",
1709
1733
  fontFamily: "--havik-font"
1710
1734
  };
1711
- function q(e, t) {
1735
+ function J(e, t) {
1712
1736
  let n = {
1713
- ...G,
1737
+ ...K,
1714
1738
  ...t
1715
1739
  };
1716
- for (let t of Object.keys(K)) e.style.setProperty(K[t], n[t]);
1740
+ for (let t of Object.keys(q)) e.style.setProperty(q[t], n[t]);
1717
1741
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1718
1742
  }
1719
1743
  //#endregion
1720
1744
  //#region src/ui/styles.ts
1721
- var J = "havik-player-styles", lt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
1722
- function ut(e = document) {
1723
- if (e.getElementById(J)) return;
1745
+ var Y = "havik-player-styles", ft = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
1746
+ function pt(e = document) {
1747
+ if (e.getElementById(Y)) return;
1724
1748
  let t = e.createElement("style");
1725
- t.id = J, t.textContent = lt, e.head.appendChild(t);
1749
+ t.id = Y, t.textContent = ft, e.head.appendChild(t);
1726
1750
  }
1727
1751
  //#endregion
1728
1752
  //#region src/ui/icons.ts
1729
- var dt = {
1753
+ var mt = {
1730
1754
  play: "<path d=\"M8 5v14l11-7z\"/>",
1731
1755
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1732
1756
  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\"/>",
@@ -1739,21 +1763,21 @@ var dt = {
1739
1763
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
1740
1764
  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\"/>"
1741
1765
  };
1742
- function Y(e) {
1743
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${dt[e]}</svg>`;
1766
+ function X(e) {
1767
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${mt[e]}</svg>`;
1744
1768
  }
1745
1769
  //#endregion
1746
1770
  //#region src/ui/controls.ts
1747
- var ft = 3e3, pt = /* @__PURE__ */ new Set([
1771
+ var ht = 3e3, gt = /* @__PURE__ */ new Set([
1748
1772
  "GONE",
1749
1773
  "NOT_FOUND",
1750
1774
  "INVALID_URN",
1751
1775
  "UNAUTHORIZED"
1752
1776
  ]);
1753
- function mt(e) {
1754
- return new ht(e);
1777
+ function _t(e) {
1778
+ return new vt(e);
1755
1779
  }
1756
- var ht = class {
1780
+ var vt = class {
1757
1781
  root;
1758
1782
  video;
1759
1783
  player;
@@ -1795,7 +1819,7 @@ var ht = class {
1795
1819
  scrubbing = !1;
1796
1820
  offFns = [];
1797
1821
  constructor(e) {
1798
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ft, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, ut(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1822
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ht, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, pt(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1799
1823
  let t = (e, t, n) => {
1800
1824
  let r = this.doc.createElement(e);
1801
1825
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1806,12 +1830,12 @@ var ht = class {
1806
1830
  "aria-label": r,
1807
1831
  title: r
1808
1832
  });
1809
- return i.innerHTML = Y(n), i;
1833
+ return i.innerHTML = X(n), i;
1810
1834
  };
1811
1835
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
1812
1836
  type: "button",
1813
1837
  "aria-label": "Play"
1814
- }), this.center.innerHTML = Y("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", {
1838
+ }), this.center.innerHTML = X("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
1815
1839
  role: "slider",
1816
1840
  "aria-label": "Seek",
1817
1841
  "aria-valuemin": "0",
@@ -1829,7 +1853,7 @@ var ht = class {
1829
1853
  "aria-label": "Volume"
1830
1854
  });
1831
1855
  let a = t("div", "havik-vol");
1832
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Y("liveDot");
1856
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = X("liveDot");
1833
1857
  let o = this.doc.createElement("span");
1834
1858
  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";
1835
1859
  let s = t("div", "havik-spacer");
@@ -1883,12 +1907,12 @@ var ht = class {
1883
1907
  }
1884
1908
  if (e === "preplay") {
1885
1909
  let e = this.doc.createElement("button");
1886
- e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Y("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
1910
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = X("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
1887
1911
  } else {
1888
1912
  let r = this.doc.createElement("div");
1889
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !pt.has(this.lastError.code)) {
1913
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !gt.has(this.lastError.code)) {
1890
1914
  let e = this.doc.createElement("button");
1891
- e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Y("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
1915
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${X("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
1892
1916
  }
1893
1917
  }
1894
1918
  this.root.append(n), this.statusBox = n, this.show();
@@ -1927,7 +1951,7 @@ var ht = class {
1927
1951
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
1928
1952
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
1929
1953
  }
1930
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${X(this.video.currentTime)} / ${X(this.video.duration)}`);
1954
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Z(this.video.currentTime)} / ${Z(this.video.duration)}`);
1931
1955
  }
1932
1956
  syncLive() {
1933
1957
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -1977,17 +2001,17 @@ var ht = class {
1977
2001
  renderQualityMenu() {
1978
2002
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
1979
2003
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
1980
- for (let n of e) this.menu.append(this.menuItem(gt(n), t === n.index, () => this.player.setQuality(n.index)));
2004
+ for (let n of e) this.menu.append(this.menuItem(yt(n), t === n.index, () => this.player.setQuality(n.index)));
1981
2005
  }
1982
2006
  renderAudioMenu() {
1983
2007
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
1984
2008
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
1985
- for (let t of e) this.menu.append(this.menuItem(_t(t), t.default, () => this.player.setAudioTrack(t.id)));
2009
+ for (let t of e) this.menu.append(this.menuItem(bt(t), t.default, () => this.player.setAudioTrack(t.id)));
1986
2010
  }
1987
2011
  renderCcMenu() {
1988
2012
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
1989
2013
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
1990
- for (let t of e) this.menu.append(this.menuItem(vt(t), !1, () => this.player.setTextTrack(t.id)));
2014
+ for (let t of e) this.menu.append(this.menuItem(xt(t), !1, () => this.player.setTextTrack(t.id)));
1991
2015
  }
1992
2016
  onTracksChanged() {
1993
2017
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2007,11 +2031,11 @@ var ht = class {
2007
2031
  }
2008
2032
  async toggleFullscreen() {
2009
2033
  try {
2010
- w(this.video, this.root) ? await E(this.video, this.root) : await T(this.video, this.root);
2034
+ C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
2011
2035
  } catch {}
2012
2036
  }
2013
2037
  syncFullscreen() {
2014
- let e = w(this.video, this.root);
2038
+ let e = C(this.video, this.root);
2015
2039
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2016
2040
  }
2017
2041
  poke() {
@@ -2070,7 +2094,7 @@ var ht = class {
2070
2094
  }
2071
2095
  }
2072
2096
  setIcon(e, t) {
2073
- e.innerHTML = Y(t);
2097
+ e.innerHTML = X(t);
2074
2098
  }
2075
2099
  destroy() {
2076
2100
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2087,32 +2111,32 @@ var ht = class {
2087
2111
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2088
2112
  }
2089
2113
  };
2090
- function X(e) {
2114
+ function Z(e) {
2091
2115
  (!Number.isFinite(e) || e < 0) && (e = 0);
2092
2116
  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");
2093
2117
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2094
2118
  }
2095
- function gt(e) {
2119
+ function yt(e) {
2096
2120
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2097
2121
  }
2098
- function _t(e) {
2122
+ function bt(e) {
2099
2123
  return e.name || e.lang || `Track ${e.id}`;
2100
2124
  }
2101
- function vt(e) {
2125
+ function xt(e) {
2102
2126
  return e.name || e.lang || `Track ${e.id}`;
2103
2127
  }
2104
2128
  //#endregion
2105
2129
  //#region src/managed/index.ts
2106
- var yt = 6e3, Z = 45e3, Q = 2e3, bt = 3, xt = 2e3, St = 48e4;
2107
- async function Ct(e) {
2130
+ var St = 6e3, Q = 45e3, Ct = 2e3, wt = 3, Tt = 2e3, Et = 48e4;
2131
+ async function Dt(e) {
2108
2132
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2109
2133
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
2110
2134
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2111
2135
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2112
- let t = new wt(e);
2136
+ let t = new Ot(e);
2113
2137
  return await t.start(), t;
2114
2138
  }
2115
- var wt = class {
2139
+ var Ot = class {
2116
2140
  opts;
2117
2141
  abort = new AbortController();
2118
2142
  listeners = {};
@@ -2178,7 +2202,7 @@ var wt = class {
2178
2202
  };
2179
2203
  }
2180
2204
  beginArming(e, t, n = !1) {
2181
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2205
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
2182
2206
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2183
2207
  }
2184
2208
  beginArmingByPolling(e) {
@@ -2199,7 +2223,7 @@ var wt = class {
2199
2223
  setTimeout(() => {
2200
2224
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2201
2225
  phase: i ? "unavailable" : "tooEarly",
2202
- retryInMs: Z,
2226
+ retryInMs: Q,
2203
2227
  attempt: 1,
2204
2228
  elapsedMs: 0,
2205
2229
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2238,13 +2262,13 @@ var wt = class {
2238
2262
  !a && !p() && h();
2239
2263
  }, e);
2240
2264
  };
2241
- _(yt), this.armingSub = D({
2265
+ _(St), this.armingSub = E({
2242
2266
  eventsBaseUrl: t,
2243
2267
  matchUrn: this.opts.matchUrn,
2244
2268
  credential: this.opts.credential,
2245
- onAlive: () => _(Z),
2269
+ onAlive: () => _(Q),
2246
2270
  onState: (e) => {
2247
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Q);
2271
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Ct);
2248
2272
  },
2249
2273
  onError: () => h()
2250
2274
  });
@@ -2267,7 +2291,7 @@ var wt = class {
2267
2291
  let n = await s(this.opts.credential);
2268
2292
  if (this.destroyed || t !== this.loadGen) return;
2269
2293
  this.setState("loading");
2270
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Te(this.opts.video, (e) => {
2294
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Oe(this.opts.video, (e) => {
2271
2295
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2272
2296
  });
2273
2297
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2286,17 +2310,17 @@ var wt = class {
2286
2310
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2287
2311
  let r = e.analytics?.sid;
2288
2312
  if (!r) return;
2289
- let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? tt(this.opts.baseUrl);
2313
+ let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? it(this.opts.baseUrl);
2290
2314
  if (!i) return;
2291
- let a = this.opts.video, o = new nt({
2315
+ let a = this.opts.video, o = new at({
2292
2316
  endpoint: i,
2293
2317
  sid: r,
2294
2318
  apiKey: n,
2295
2319
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2296
- sdkVersion: ct,
2297
- environment: ot(a),
2320
+ sdkVersion: dt,
2321
+ environment: lt(a),
2298
2322
  sample: () => {
2299
- let e = this.engine?.getStats() ?? we, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
2323
+ let e = this.engine?.getStats() ?? F, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
2300
2324
  return {
2301
2325
  ...e,
2302
2326
  bufferedMs: Math.round(t * 1e3),
@@ -2310,7 +2334,7 @@ var wt = class {
2310
2334
  let s = () => o.noteSeek(), c = () => o.noteVolume(a.muted, a.volume);
2311
2335
  a.addEventListener("seeking", s), a.addEventListener("volumechange", c), this.detachMediaListeners = () => {
2312
2336
  a.removeEventListener("seeking", s), a.removeEventListener("volumechange", c);
2313
- }, o.start(), o.seedVolume(a.muted, a.volume), o.notePresentation(this.currentPresentation()), st().then((e) => o.noteEnvironment(e)), this.opts.autoplay === !1 && o.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2337
+ }, o.start(), o.seedVolume(a.muted, a.volume), o.notePresentation(this.currentPresentation()), ut().then((e) => o.noteEnvironment(e)), this.opts.autoplay === !1 && o.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2314
2338
  }
2315
2339
  currentPresentation() {
2316
2340
  let e = this.opts.video;
@@ -2325,7 +2349,7 @@ var wt = class {
2325
2349
  video: this.opts.video,
2326
2350
  descriptor: e,
2327
2351
  credential: t,
2328
- deviceId: j(),
2352
+ deviceId: A(),
2329
2353
  userId: this.opts.userId,
2330
2354
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
2331
2355
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -2334,11 +2358,11 @@ var wt = class {
2334
2358
  hlsConfig: i,
2335
2359
  emit: (e) => this.onEngineEvent(e)
2336
2360
  }, o = this.opts.engine ?? "auto";
2337
- if (o === "native") return new R(a);
2338
- if (o === "hls") return new B(a);
2339
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && I(this.opts.video) && L()) return new R(a);
2340
- if (Oe()) return new B(a);
2341
- if (I(this.opts.video)) return new R(a);
2361
+ if (o === "native") return new z(a);
2362
+ if (o === "hls") return new V(a);
2363
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && L(this.opts.video) && R()) return new z(a);
2364
+ if (je()) return new V(a);
2365
+ if (L(this.opts.video)) return new z(a);
2342
2366
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2343
2367
  }
2344
2368
  onEngineEvent(e) {
@@ -2366,11 +2390,11 @@ var wt = class {
2366
2390
  }
2367
2391
  startLiveState(e) {
2368
2392
  if (this.opts.liveStateEvents === !1) return;
2369
- let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2393
+ let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
2370
2394
  if (!t) return;
2371
2395
  this.closeLiveState();
2372
2396
  let r = 0, i = !1;
2373
- this.liveStateSub = D({
2397
+ this.liveStateSub = E({
2374
2398
  eventsBaseUrl: t,
2375
2399
  matchUrn: this.opts.matchUrn,
2376
2400
  credential: this.opts.credential,
@@ -2381,7 +2405,7 @@ var wt = class {
2381
2405
  r = 0, i = !1;
2382
2406
  },
2383
2407
  onError: () => {
2384
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= bt && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2408
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= wt && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2385
2409
  }
2386
2410
  });
2387
2411
  }
@@ -2403,7 +2427,7 @@ var wt = class {
2403
2427
  scheduleRejoin(e) {
2404
2428
  !this.rejoinEnabled() || this.rejoinTimer || (this.rejoinTimer = setTimeout(() => {
2405
2429
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2406
- }, Math.random() * Q));
2430
+ }, Math.random() * Ct));
2407
2431
  }
2408
2432
  cancelRejoin() {
2409
2433
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2427,7 +2451,7 @@ var wt = class {
2427
2451
  }
2428
2452
  t.controls = !1;
2429
2453
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2430
- r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = mt({
2454
+ r && r.insertBefore(n, t), n.appendChild(t), J(n, this.opts.theme), this.container = n, this.controlBar = _t({
2431
2455
  root: n,
2432
2456
  video: t,
2433
2457
  player: this,
@@ -2457,7 +2481,7 @@ var wt = class {
2457
2481
  }
2458
2482
  startStats() {
2459
2483
  this.stopStats();
2460
- let e = Math.max(500, this.opts.statsIntervalMs ?? xt);
2484
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Tt);
2461
2485
  this.statsTimer = setInterval(() => {
2462
2486
  if (!this.engine) return;
2463
2487
  let e = this.engine.getStats();
@@ -2469,7 +2493,7 @@ var wt = class {
2469
2493
  }
2470
2494
  scheduleLicenseRefresh() {
2471
2495
  this.stopRefresh();
2472
- let e = this.opts.licenseRefreshMs ?? St;
2496
+ let e = this.opts.licenseRefreshMs ?? Et;
2473
2497
  !e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2474
2498
  }
2475
2499
  stopRefresh() {
@@ -2511,7 +2535,7 @@ var wt = class {
2511
2535
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
2512
2536
  }
2513
2537
  getStats() {
2514
- return this.engine?.getStats() ?? we;
2538
+ return this.engine?.getStats() ?? F;
2515
2539
  }
2516
2540
  getQualityLevels() {
2517
2541
  return this.engine?.getQualityLevels() ?? [];
@@ -2550,10 +2574,10 @@ var wt = class {
2550
2574
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
2551
2575
  }
2552
2576
  async enterFullscreen() {
2553
- return !this.destroyed && T(this.opts.video, this.container ?? void 0);
2577
+ return !this.destroyed && w(this.opts.video, this.container ?? void 0);
2554
2578
  }
2555
2579
  async exitFullscreen() {
2556
- await E(this.opts.video, this.container ?? void 0);
2580
+ await T(this.opts.video, this.container ?? void 0);
2557
2581
  }
2558
2582
  retry() {
2559
2583
  return this.reload();
@@ -2621,7 +2645,7 @@ function $(e) {
2621
2645
  }
2622
2646
  //#endregion
2623
2647
  //#region src/embed/host.ts
2624
- function Tt(e) {
2648
+ function kt(e) {
2625
2649
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2626
2650
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2627
2651
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2680,8 +2704,8 @@ function Tt(e) {
2680
2704
  }
2681
2705
  //#endregion
2682
2706
  //#region src/embed/page.ts
2683
- var Et = /^[A-Za-z0-9:_.-]{1,128}$/;
2684
- function Dt() {
2707
+ var At = /^[A-Za-z0-9:_.-]{1,128}$/;
2708
+ function jt() {
2685
2709
  let e = window.HAVIK_EMBED_CONFIG;
2686
2710
  if (e) return {
2687
2711
  baseUrl: e.baseUrl ?? "",
@@ -2703,9 +2727,9 @@ function Dt() {
2703
2727
  waitForLive: !0
2704
2728
  };
2705
2729
  }
2706
- async function Ot() {
2707
- let e = Dt();
2708
- At();
2730
+ async function Mt() {
2731
+ let e = jt();
2732
+ Pt();
2709
2733
  let t = document.createElement("video");
2710
2734
  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);
2711
2735
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2760,12 +2784,12 @@ async function Ot() {
2760
2784
  code: e.code,
2761
2785
  message: e.message
2762
2786
  })), e.on("autoplayblocked", () => {
2763
- i({ type: "oddin:autoplayblocked" }), kt(t, e);
2787
+ i({ type: "oddin:autoplayblocked" }), Nt(t, e);
2764
2788
  });
2765
2789
  }, s = async (r) => {
2766
2790
  a?.destroy(), a = null;
2767
2791
  try {
2768
- let n = await Ct({
2792
+ let n = await Dt({
2769
2793
  video: t,
2770
2794
  baseUrl: e.baseUrl,
2771
2795
  matchUrn: r,
@@ -2826,7 +2850,7 @@ async function Ot() {
2826
2850
  a?.retry();
2827
2851
  break;
2828
2852
  case "oddin:load":
2829
- typeof e.matchUrn == "string" && Et.test(e.matchUrn) && s(e.matchUrn);
2853
+ typeof e.matchUrn == "string" && At.test(e.matchUrn) && s(e.matchUrn);
2830
2854
  break;
2831
2855
  case "oddin:destroy": c();
2832
2856
  }
@@ -2838,18 +2862,18 @@ async function Ot() {
2838
2862
  protocol: 1
2839
2863
  });
2840
2864
  }
2841
- function kt(e, t) {
2865
+ function Nt(e, t) {
2842
2866
  if (document.getElementById("havik-tap")) return;
2843
2867
  let n = document.createElement("button");
2844
2868
  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", () => {
2845
2869
  n.remove(), t.play();
2846
2870
  }), document.body.appendChild(n);
2847
2871
  }
2848
- function At() {
2872
+ function Pt() {
2849
2873
  let e = document.createElement("style");
2850
2874
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
2851
2875
  }
2852
2876
  //#endregion
2853
- export { G as ODDIN_THEME, n as PlaybackError, q as applyTheme, Ot as bootEmbed, he as clearDeviceId, Ct as createPlayer, O as deriveEventsBaseUrl, xe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, le as fetchCatalog, de as fetchTournament, pe as flattenMatches, j as getDeviceId, Ce as isLowLatencyManifest, $ as isOddinMessage, _e as licenseRequestHeaders, Tt as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, me as watchStatus };
2877
+ export { K as ODDIN_THEME, n as PlaybackError, J as applyTheme, Mt as bootEmbed, ge as clearDeviceId, Dt as createPlayer, D as deriveEventsBaseUrl, Se as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, we as isLowLatencyManifest, $ as isOddinMessage, ve as licenseRequestHeaders, kt as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
2854
2878
 
2855
2879
  //# sourceMappingURL=index.js.map