@oddin-gg/havik-player 2.15.6 → 2.16.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
@@ -860,7 +860,8 @@ function qe(e, t) {
860
860
  }
861
861
  //#endregion
862
862
  //#region src/core/engine/native.ts
863
- function Je(e) {
863
+ var Je = 2e3, Ye = 3;
864
+ function Xe(e) {
864
865
  try {
865
866
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
866
867
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -876,7 +877,7 @@ function G() {
876
877
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
877
878
  return e || t;
878
879
  }
879
- function Ye() {
880
+ function Ze() {
880
881
  if (typeof navigator > "u" || !G()) return !1;
881
882
  let e = navigator.userAgent ?? "";
882
883
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -890,6 +891,9 @@ var K = class {
890
891
  fairplayLicenseUrl;
891
892
  keySession = null;
892
893
  fairplayArmed = !1;
894
+ onVisibility = null;
895
+ onPageShow = null;
896
+ hiddenSince = null;
893
897
  fairplayKeyIV;
894
898
  loadStarted;
895
899
  preloadTouched = !1;
@@ -901,7 +905,7 @@ var K = class {
901
905
  }
902
906
  async load() {
903
907
  let { video: e, descriptor: t, emit: r } = this.deps;
904
- if (this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
908
+ if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
905
909
  if (!t.drm?.fairplay) {
906
910
  r({
907
911
  type: "error",
@@ -917,7 +921,7 @@ var K = class {
917
921
  type: "error",
918
922
  error: new n("INTERNAL", 0, "native HLS playback error"),
919
923
  fatal: !0
920
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Xe(t.manifestUrl, t.analytics?.sid), e.load();
924
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Qe(t.manifestUrl, t.analytics?.sid), e.load();
921
925
  }
922
926
  startLoad() {
923
927
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -939,7 +943,7 @@ var K = class {
939
943
  });
940
944
  this.onEncrypted = (n) => {
941
945
  let i = n;
942
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
946
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Xe(i.initData), (async () => {
943
947
  try {
944
948
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
945
949
  initDataTypes: [i.initDataType],
@@ -1038,14 +1042,46 @@ var K = class {
1038
1042
  droppedFrames: t.dropped,
1039
1043
  decodedFrames: t.totalFrames
1040
1044
  };
1041
- return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1045
+ if (this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1046
+ if (n.isLive = !0, e.seekable.length > 0) {
1047
+ let t = e.seekable.end(e.seekable.length - 1);
1048
+ n.atLiveEdge = e.currentTime >= t - 2;
1049
+ let r = t - e.currentTime;
1050
+ Number.isFinite(r) && r >= 0 && (n.latencySeconds = r);
1051
+ }
1052
+ } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1053
+ return n;
1042
1054
  }
1043
1055
  stop() {
1044
1056
  try {
1045
1057
  this.deps.video.pause();
1046
1058
  } catch {}
1047
1059
  }
1060
+ watchRefocus() {
1061
+ this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
1062
+ let e = typeof performance < "u" ? performance.now() : Date.now();
1063
+ if (document.visibilityState === "hidden") {
1064
+ this.hiddenSince = e;
1065
+ return;
1066
+ }
1067
+ let t = this.hiddenSince;
1068
+ this.hiddenSince = null, t != null && e - t >= Je && this.snapToLive();
1069
+ }, this.onPageShow = (e) => {
1070
+ e.persisted && this.snapToLive();
1071
+ }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
1072
+ }
1073
+ snapToLive() {
1074
+ let e = this.deps.video;
1075
+ if (e.duration !== Infinity || e.seekable.length === 0) return;
1076
+ let t = e.seekable.start(e.seekable.length - 1), n = e.seekable.end(e.seekable.length - 1);
1077
+ if (!Number.isFinite(n)) return;
1078
+ let r = Math.max(t, n - Ye);
1079
+ try {
1080
+ e.currentTime = r;
1081
+ } catch {}
1082
+ }
1048
1083
  destroy() {
1084
+ this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
1049
1085
  let { video: e } = this.deps;
1050
1086
  this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
1051
1087
  try {
@@ -1057,13 +1093,13 @@ var K = class {
1057
1093
  } catch {}
1058
1094
  }
1059
1095
  };
1060
- function Xe(e, t) {
1096
+ function Qe(e, t) {
1061
1097
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1062
1098
  }
1063
1099
  //#endregion
1064
1100
  //#region src/core/engine/prefetch.ts
1065
- var Ze = 15e3, Qe = 5e3, $e = 6;
1066
- function et(e) {
1101
+ var $e = 15e3, et = 5e3, tt = 6;
1102
+ function nt(e) {
1067
1103
  try {
1068
1104
  let t = new URL(e);
1069
1105
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1071,7 +1107,7 @@ function et(e) {
1071
1107
  return e;
1072
1108
  }
1073
1109
  }
1074
- var tt = class {
1110
+ var rt = class {
1075
1111
  cmcd;
1076
1112
  entries = /* @__PURE__ */ new Map();
1077
1113
  keyed = /* @__PURE__ */ new Set();
@@ -1094,10 +1130,10 @@ var tt = class {
1094
1130
  }
1095
1131
  prefetch(e, t, n) {
1096
1132
  if (!this.isActive(t)) return;
1097
- let r = et(e);
1133
+ let r = nt(e);
1098
1134
  if (this.entries.has(r)) return;
1099
1135
  let i = this.perTrack.get(t) ?? 0;
1100
- if (i >= $e) return;
1136
+ if (i >= tt) return;
1101
1137
  this.perTrack.set(t, i + 1);
1102
1138
  let a = new AbortController(), o = {
1103
1139
  started: performance.now(),
@@ -1111,10 +1147,10 @@ var tt = class {
1111
1147
  signal: a.signal
1112
1148
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1113
1149
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1114
- }, Ze);
1150
+ }, $e);
1115
1151
  }
1116
1152
  take(e) {
1117
- let t = et(e), n = this.entries.get(t);
1153
+ let t = nt(e), n = this.entries.get(t);
1118
1154
  return n && this.entries.delete(t), n;
1119
1155
  }
1120
1156
  destroy() {
@@ -1134,13 +1170,13 @@ var tt = class {
1134
1170
  }
1135
1171
  }
1136
1172
  };
1137
- function nt(t) {
1173
+ function it(t) {
1138
1174
  let n = e.DefaultConfig?.loader;
1139
1175
  if (typeof n != "function") return;
1140
1176
  class r extends n {
1141
1177
  served = !1;
1142
1178
  cancelled = !1;
1143
- stats = rt();
1179
+ stats = at();
1144
1180
  load(e, n, r) {
1145
1181
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1146
1182
  if (!i) {
@@ -1148,7 +1184,7 @@ function nt(t) {
1148
1184
  return;
1149
1185
  }
1150
1186
  this.served = !0;
1151
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Qe, s = setTimeout(() => {
1187
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || et, s = setTimeout(() => {
1152
1188
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1153
1189
  }, o);
1154
1190
  i.bytes.then((o) => {
@@ -1175,7 +1211,7 @@ function nt(t) {
1175
1211
  }
1176
1212
  return r;
1177
1213
  }
1178
- function rt() {
1214
+ function at() {
1179
1215
  return {
1180
1216
  aborted: !1,
1181
1217
  loaded: 0,
@@ -1199,10 +1235,10 @@ function rt() {
1199
1235
  }
1200
1236
  };
1201
1237
  }
1202
- function it(e) {
1238
+ function ot(e) {
1203
1239
  return e === "audio" ? "audio" : "main";
1204
1240
  }
1205
- function at(e, t) {
1241
+ function st(e, t) {
1206
1242
  let n = [];
1207
1243
  t.initSegment?.url && !t.initSegment.data && n.push({
1208
1244
  url: t.initSegment.url,
@@ -1221,24 +1257,24 @@ function at(e, t) {
1221
1257
  }
1222
1258
  //#endregion
1223
1259
  //#region src/core/engine/hls.ts
1224
- function ot() {
1260
+ function ct() {
1225
1261
  return e.isSupported();
1226
1262
  }
1227
- var st = 3, ct = 5, lt = 3, ut = 3e4, dt = 12e3, ft = 3e3, pt = 6e3, mt = .5, ht = 3, gt = .5, _t = 1.1, vt = .25, yt = 5e3, bt = 4e3, xt = 2, St = 5, Ct = 2, wt = 2, Tt = 4, Et = 4, Dt = 2e3, Ot = 3e4, kt = .2, At = 30, jt = 2, Mt = 2, Nt = 9, Pt = .5, Ft = 64;
1228
- function It(e) {
1263
+ var lt = 3, ut = 5, dt = 3, ft = 3e4, pt = 12e3, mt = 3e3, ht = 6e3, gt = .5, _t = 3, vt = .5, yt = 1.1, bt = .25, xt = 5e3, St = 4e3, Ct = 2, wt = 5, Tt = 2, Et = 2, Dt = 4, Ot = 4, kt = 2e3, At = 3e4, jt = .2, Mt = 30, Nt = 2, Pt = 2, Ft = 9, It = .5, Lt = 64;
1264
+ function Rt(e) {
1229
1265
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1230
1266
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1231
1267
  return;
1232
1268
  }
1233
- e.liveSyncDuration ??= Mt;
1234
- let t = Math.max(12, e.liveSyncDuration + Nt);
1235
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Lt(e, e.liveSyncDuration);
1269
+ e.liveSyncDuration ??= Pt;
1270
+ let t = Math.max(12, e.liveSyncDuration + Ft);
1271
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), zt(e, e.liveSyncDuration);
1236
1272
  }
1237
- function Lt(e, t) {
1273
+ function zt(e, t) {
1238
1274
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1239
1275
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1240
1276
  }
1241
- var Rt = class {
1277
+ var Bt = class {
1242
1278
  name = "hls";
1243
1279
  hls = null;
1244
1280
  deps;
@@ -1351,7 +1387,7 @@ var Rt = class {
1351
1387
  }
1352
1388
  this.loadSuspended = !0;
1353
1389
  }
1354
- }, yt));
1390
+ }, xt));
1355
1391
  }
1356
1392
  resumeLoading() {
1357
1393
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1383,7 +1419,7 @@ var Rt = class {
1383
1419
  let t = e.liveSyncPosition;
1384
1420
  if (typeof t != "number" || !Number.isFinite(t)) return;
1385
1421
  let { video: n } = this.deps;
1386
- n.currentTime <= t + Pt || (n.currentTime = t);
1422
+ n.currentTime <= t + It || (n.currentTime = t);
1387
1423
  }
1388
1424
  startHls() {
1389
1425
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1424,20 +1460,20 @@ var Rt = class {
1424
1460
  ...c
1425
1461
  };
1426
1462
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1427
- let e = new tt({
1463
+ let e = new rt({
1428
1464
  sessionId: n.analytics?.sid,
1429
1465
  contentId: n.matchUrn
1430
- }), t = nt(e);
1466
+ }), t = it(e);
1431
1467
  t && (this.prefetch = e, d.fLoader = t);
1432
1468
  }
1433
- It(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1469
+ Rt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1434
1470
  let f = new e(d);
1435
1471
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1436
1472
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1437
1473
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1438
1474
  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(() => {
1439
1475
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1440
- }, ut)));
1476
+ }, ft)));
1441
1477
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1442
1478
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1443
1479
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1445,7 +1481,7 @@ var Rt = class {
1445
1481
  let n = t?.frag?.stats, r = n?.loaded;
1446
1482
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1447
1483
  let i = n?.loading;
1448
- 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 > Ft && this.requestTimesMs.shift());
1484
+ 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 > Lt && this.requestTimesMs.shift());
1449
1485
  let a = t?.frag?.url;
1450
1486
  if (a) {
1451
1487
  let e = H(a);
@@ -1462,15 +1498,15 @@ var Rt = class {
1462
1498
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1463
1499
  let t = this.prefetch;
1464
1500
  f.on(e.Events.KEY_LOADING, (e, n) => {
1465
- let r = n?.frag, i = it(r?.type);
1466
- if (r && t.isActive(i)) for (let e of at(f, r)) t.prefetch(e.url, i, e.kind);
1467
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(it(n?.frag?.type)));
1501
+ let r = n?.frag, i = ot(r?.type);
1502
+ if (r && t.isActive(i)) for (let e of st(f, r)) t.prefetch(e.url, i, e.kind);
1503
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ot(n?.frag?.type)));
1468
1504
  }
1469
1505
  f.on(e.Events.KEY_LOADED, () => {
1470
1506
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1471
1507
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1472
1508
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1473
- }, ft), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1509
+ }, mt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1474
1510
  this.renditionSwitches += 1;
1475
1511
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1476
1512
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1534,7 +1570,7 @@ var Rt = class {
1534
1570
  return;
1535
1571
  }
1536
1572
  this.capTimer && clearTimeout(this.capTimer);
1537
- let t = e > this.sizeCapLevel ? Dt : Ot;
1573
+ let t = e > this.sizeCapLevel ? kt : At;
1538
1574
  this.capTimer = setTimeout(() => {
1539
1575
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1540
1576
  }, t);
@@ -1655,7 +1691,7 @@ var Rt = class {
1655
1691
  return;
1656
1692
  }
1657
1693
  let e = Date.now() - this.lastAdvanceMs;
1658
- !this.chaseSuspended && e > pt && this.suspendChasing(), e > dt && this.emitEnded("stalled");
1694
+ !this.chaseSuspended && e > ht && this.suspendChasing(), e > pt && this.emitEnded("stalled");
1659
1695
  }
1660
1696
  resetStarvationWindow() {
1661
1697
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1670,7 +1706,7 @@ var Rt = class {
1670
1706
  this.resetStarvationWindow();
1671
1707
  return;
1672
1708
  }
1673
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < pt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > bt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1709
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ht, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > St, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1674
1710
  if (this.starvedFrames = c, !a || l) {
1675
1711
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1676
1712
  return;
@@ -1679,12 +1715,12 @@ var Rt = class {
1679
1715
  this.resetStarvationWindow();
1680
1716
  return;
1681
1717
  }
1682
- 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 > Tt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Ct && (this.clearKick(), this.starvationRebuilds < wt)) {
1718
+ 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 > Dt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Tt && (this.clearKick(), this.starvationRebuilds < Et)) {
1683
1719
  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");
1684
1720
  return;
1685
1721
  }
1686
- let u = i && this.starvedTicks >= xt, d = !i && this.deadTicks >= Tt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Et;
1687
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= St))) {
1722
+ let u = i && this.starvedTicks >= Ct, d = !i && this.deadTicks >= Dt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Ot;
1723
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= wt))) {
1688
1724
  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");
1689
1725
  try {
1690
1726
  e.stopLoad(), e.startLoad(-1);
@@ -1699,7 +1735,7 @@ var Rt = class {
1699
1735
  let t = e.latency, n = e.targetLatency;
1700
1736
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1701
1737
  let r = t - n;
1702
- !this.catchUpEngaged && r > mt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= mt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1738
+ !this.catchUpEngaged && r > gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1703
1739
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1704
1740
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1705
1741
  }
@@ -1721,15 +1757,15 @@ var Rt = class {
1721
1757
  return;
1722
1758
  }
1723
1759
  let { totalFrames: n, dropped: r } = U(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1724
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < At || o < 0) {
1760
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Mt || o < 0) {
1725
1761
  this.fpsBadTicks = 0;
1726
1762
  return;
1727
1763
  }
1728
- if (o <= kt * a) {
1764
+ if (o <= jt * a) {
1729
1765
  this.fpsBadTicks = 0;
1730
1766
  return;
1731
1767
  }
1732
- if (this.fpsBadTicks += 1, this.fpsBadTicks < jt) return;
1768
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Nt) return;
1733
1769
  this.fpsBadTicks = 0;
1734
1770
  let s = e.levels, c = s[e.currentLevel];
1735
1771
  if (!c) return;
@@ -1746,20 +1782,20 @@ var Rt = class {
1746
1782
  return;
1747
1783
  }
1748
1784
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1749
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(_t, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1785
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(yt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1750
1786
  this.resetChaseWindow();
1751
1787
  return;
1752
1788
  }
1753
- if (this.chaseLatency < 0 || this.chaseLatency - n >= gt) {
1789
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= vt) {
1754
1790
  this.chaseLatency = n, this.chaseTicks = 0;
1755
1791
  return;
1756
1792
  }
1757
- if (this.chaseTicks += 1, this.chaseTicks < ht) return;
1793
+ if (this.chaseTicks += 1, this.chaseTicks < _t) return;
1758
1794
  this.resetChaseWindow();
1759
1795
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1760
1796
  if (!(a > 1)) return;
1761
1797
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1762
- s < o + vt || (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);
1798
+ s < o + bt || (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);
1763
1799
  }
1764
1800
  suspendChasing() {
1765
1801
  let e = this.hls;
@@ -1804,7 +1840,7 @@ var Rt = class {
1804
1840
  scheduleLicenseRetry(t) {
1805
1841
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1806
1842
  let n = t.response?.code ?? 0;
1807
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= lt) return !1;
1843
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= dt) return !1;
1808
1844
  this.licenseRecoveries += 1;
1809
1845
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1810
1846
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1836,7 +1872,7 @@ var Rt = class {
1836
1872
  return;
1837
1873
  }
1838
1874
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1839
- if (this.networkRecoveries < ct) {
1875
+ if (this.networkRecoveries < ut) {
1840
1876
  this.networkRecoveries += 1;
1841
1877
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1842
1878
  this.networkRetryTimer = setTimeout(() => {
@@ -1853,7 +1889,7 @@ var Rt = class {
1853
1889
  return;
1854
1890
  }
1855
1891
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1856
- if (this.mediaRecoveries < st) {
1892
+ if (this.mediaRecoveries < lt) {
1857
1893
  this.mediaRecoveries += 1, n.recoverMediaError();
1858
1894
  return;
1859
1895
  }
@@ -1877,19 +1913,19 @@ var Rt = class {
1877
1913
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1878
1914
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1879
1915
  }
1880
- }, zt = 15e3, Bt = 6e5, Vt = 3e5, Ht = 100, q = 1, Ut = 1e3, Wt = 3e4, Gt = 1e3, Kt = {
1916
+ }, Vt = 15e3, Ht = 6e5, Ut = 3e5, Wt = 100, q = 1, Gt = 1e3, Kt = 3e4, qt = 1e3, Jt = {
1881
1917
  inline: "PRESENTATION_INLINE",
1882
1918
  fullscreen: "PRESENTATION_FULLSCREEN",
1883
1919
  pip: "PRESENTATION_PIP"
1884
- }, qt = {
1920
+ }, Yt = {
1885
1921
  widevine: "KEY_SYSTEM_WIDEVINE",
1886
1922
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1887
1923
  none: "KEY_SYSTEM_NONE"
1888
1924
  };
1889
- function Jt(e, t) {
1925
+ function Xt(e, t) {
1890
1926
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1891
1927
  }
1892
- var Yt = /* @__PURE__ */ new Set([
1928
+ var Zt = /* @__PURE__ */ new Set([
1893
1929
  "INVALID_URN",
1894
1930
  "NOT_FOUND",
1895
1931
  "GONE",
@@ -1909,7 +1945,7 @@ var Yt = /* @__PURE__ */ new Set([
1909
1945
  ended: "PLAYER_STATE_ENDED",
1910
1946
  error: "PLAYER_STATE_ERROR"
1911
1947
  };
1912
- function Xt(e) {
1948
+ function Qt(e) {
1913
1949
  try {
1914
1950
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1915
1951
  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);
@@ -1917,8 +1953,8 @@ function Xt(e) {
1917
1953
  return;
1918
1954
  }
1919
1955
  }
1920
- var Zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Qt = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), $t = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1921
- function en(e) {
1956
+ var $t = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), en = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), tn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1957
+ function nn(e) {
1922
1958
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
1923
1959
  let t;
1924
1960
  try {
@@ -1927,19 +1963,19 @@ function en(e) {
1927
1963
  } catch {
1928
1964
  return;
1929
1965
  }
1930
- if (Qt.has(t) && !Y.has(t)) {
1931
- Y.add(t), g($t(new URL(t).origin));
1966
+ if (en.has(t) && !Y.has(t)) {
1967
+ Y.add(t), g(tn(new URL(t).origin));
1932
1968
  for (let e of X) e.noteCspBlocked();
1933
1969
  }
1934
1970
  }
1935
- function tn(e, t) {
1971
+ function rn(e, t) {
1936
1972
  return g(t, e), { disabledReason: t };
1937
1973
  }
1938
- function nn(e, t, n) {
1939
- if (n) return t && !Zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1974
+ function an(e, t, n) {
1975
+ if (n) return t && !$t(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1940
1976
  if (t) return { endpoint: t };
1941
- if (t !== void 0) return tn("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).");
1942
- let r = Xt(e);
1977
+ if (t !== void 0) return rn("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).");
1978
+ let r = Qt(e);
1943
1979
  if (r) return { endpoint: r };
1944
1980
  let i;
1945
1981
  try {
@@ -1947,9 +1983,9 @@ function nn(e, t, n) {
1947
1983
  } catch {
1948
1984
  i = e;
1949
1985
  }
1950
- return tn(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).`);
1986
+ return rn(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).`);
1951
1987
  }
1952
- var rn = class {
1988
+ var on = class {
1953
1989
  opts;
1954
1990
  url;
1955
1991
  cspKey;
@@ -2031,8 +2067,8 @@ var rn = class {
2031
2067
  constructor(e) {
2032
2068
  this.opts = {
2033
2069
  ...e,
2034
- heartbeatMs: e.heartbeatMs ?? zt,
2035
- idleMs: e.idleMs ?? Bt
2070
+ heartbeatMs: e.heartbeatMs ?? Vt,
2071
+ idleMs: e.idleMs ?? Ht
2036
2072
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2037
2073
  try {
2038
2074
  let e = new URL(this.url);
@@ -2049,11 +2085,11 @@ var rn = class {
2049
2085
  sdkVersion: this.opts.sdkVersion,
2050
2086
  ...this.opts.environment
2051
2087
  };
2052
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ut), 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 && Qt.add(this.cspKey), document.addEventListener("securitypolicyviolation", en), X.add(this), this.noteCspBlocked(), this.onVisibility());
2088
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Gt), 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 && en.add(this.cspKey), document.addEventListener("securitypolicyviolation", nn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2053
2089
  }
2054
2090
  checkSuspension(e) {
2055
2091
  if (this.endedFlag || !this.opts.idleMs) return !1;
2056
- let t = Math.max(this.opts.idleMs, Vt);
2092
+ let t = Math.max(this.opts.idleMs, Ut);
2057
2093
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2058
2094
  }
2059
2095
  syncIdle(e) {
@@ -2076,12 +2112,12 @@ var rn = class {
2076
2112
  let a = {
2077
2113
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2078
2114
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2079
- presentation: Kt[this.presentation]
2115
+ presentation: Jt[this.presentation]
2080
2116
  }, o = this.causeOf(e, t, i);
2081
2117
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2082
2118
  }
2083
2119
  seekInduced(e) {
2084
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Gt;
2120
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < qt;
2085
2121
  }
2086
2122
  causeOf(e, t, n) {
2087
2123
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2155,7 +2191,7 @@ var rn = class {
2155
2191
  let r = n ?? "";
2156
2192
  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";
2157
2193
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2158
- if (Yt.has(e)) return "ERROR_STAGE_RESOLVE";
2194
+ if (Zt.has(e)) return "ERROR_STAGE_RESOLVE";
2159
2195
  let i = t ?? "";
2160
2196
  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";
2161
2197
  }
@@ -2202,14 +2238,14 @@ var rn = class {
2202
2238
  if (this.lastRequestCount = g, _ > 0) {
2203
2239
  o.requestCountDelta = _;
2204
2240
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2205
- n.length > 0 && (o.requestTimeP50Ms = Jt(n, 50), o.requestTimeP95Ms = Jt(n, 95));
2241
+ n.length > 0 && (o.requestTimeP50Ms = Xt(n, 50), o.requestTimeP95Ms = Xt(n, 95));
2206
2242
  }
2207
2243
  typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
2208
2244
  }
2209
2245
  maybeEmitMediaInfo(e) {
2210
2246
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2211
2247
  let t = {};
2212
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = qt[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);
2248
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Yt[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);
2213
2249
  let n = JSON.stringify(t);
2214
2250
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2215
2251
  }
@@ -2229,7 +2265,7 @@ var rn = class {
2229
2265
  let c = r?.positionMs ?? 0;
2230
2266
  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));
2231
2267
  let l = e !== "END_REASON_ENDED";
2232
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Wt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Wt && (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);
2268
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Kt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Kt && (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);
2233
2269
  let u = r?.decodedFrames ?? this.lastDecoded;
2234
2270
  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");
2235
2271
  }
@@ -2249,13 +2285,13 @@ var rn = class {
2249
2285
  };
2250
2286
  }
2251
2287
  noteCspBlocked() {
2252
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.($t(new URL(this.url).origin)));
2288
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(tn(new URL(this.url).origin)));
2253
2289
  }
2254
2290
  cspBlocked() {
2255
2291
  return !!this.cspKey && Y.has(this.cspKey);
2256
2292
  }
2257
2293
  enqueue(e) {
2258
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Ht;) {
2294
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Wt;) {
2259
2295
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2260
2296
  this.pending.splice(e >= 0 ? e : 0, 1);
2261
2297
  }
@@ -2282,7 +2318,7 @@ var rn = class {
2282
2318
  };
2283
2319
  //#endregion
2284
2320
  //#region src/core/environment.ts
2285
- function an() {
2321
+ function sn() {
2286
2322
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2287
2323
  let e;
2288
2324
  try {
@@ -2307,14 +2343,14 @@ function an() {
2307
2343
  integration: "INTEGRATION_KIND_IFRAME"
2308
2344
  };
2309
2345
  }
2310
- function on() {
2346
+ function cn() {
2311
2347
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2312
2348
  let e = navigator.userAgentData, t = e?.platform ?? "";
2313
2349
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2314
2350
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2315
2351
  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";
2316
2352
  }
2317
- function sn() {
2353
+ function ln() {
2318
2354
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2319
2355
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2320
2356
  let t = {
@@ -2333,17 +2369,17 @@ function sn() {
2333
2369
  }
2334
2370
  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;
2335
2371
  }
2336
- function cn(e) {
2337
- let t = an(), n = {
2338
- deviceClass: on(),
2372
+ function un(e) {
2373
+ let t = sn(), n = {
2374
+ deviceClass: cn(),
2339
2375
  integration: t.integration,
2340
- ...sn()
2376
+ ...ln()
2341
2377
  };
2342
2378
  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);
2343
2379
  let r = e.getBoundingClientRect?.();
2344
2380
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2345
2381
  }
2346
- async function ln() {
2382
+ async function dn() {
2347
2383
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2348
2384
  if (!e?.getHighEntropyValues) return {};
2349
2385
  try {
@@ -2355,7 +2391,7 @@ async function ln() {
2355
2391
  }
2356
2392
  //#endregion
2357
2393
  //#region src/core/version.ts
2358
- var un = "2.15.6", dn = {
2394
+ var fn = "2.16.1", pn = {
2359
2395
  accent: "#E1B600",
2360
2396
  accentText: "#1B1C23",
2361
2397
  background: "#0e0f13",
@@ -2366,7 +2402,7 @@ var un = "2.15.6", dn = {
2366
2402
  border: "rgba(255, 255, 255, 0.1)",
2367
2403
  radius: "8px",
2368
2404
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2369
- }, fn = {
2405
+ }, mn = {
2370
2406
  accent: "--havik-accent",
2371
2407
  accentText: "--havik-accent-text",
2372
2408
  background: "--havik-bg",
@@ -2378,26 +2414,26 @@ var un = "2.15.6", dn = {
2378
2414
  radius: "--havik-radius",
2379
2415
  fontFamily: "--havik-font"
2380
2416
  };
2381
- function pn(e, t) {
2417
+ function hn(e, t) {
2382
2418
  let n = {
2383
- ...dn,
2419
+ ...pn,
2384
2420
  ...t
2385
2421
  };
2386
- for (let t of Object.keys(fn)) e.style.setProperty(fn[t], n[t]);
2422
+ for (let t of Object.keys(mn)) e.style.setProperty(mn[t], n[t]);
2387
2423
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2388
2424
  }
2389
2425
  //#endregion
2390
2426
  //#region src/ui/styles.ts
2391
- var mn = "havik-player-styles", hn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2392
- function gn(e = document, t) {
2393
- let n = e.querySelector(`style#${mn}`);
2427
+ var gn = "havik-player-styles", _n = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2428
+ function vn(e = document, t) {
2429
+ let n = e.querySelector(`style#${gn}`);
2394
2430
  if (n && (!t || Z.get(n) === t)) return;
2395
2431
  let r = e.createElement("style");
2396
- r.id = mn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = hn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2432
+ r.id = gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = _n, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2397
2433
  }
2398
2434
  //#endregion
2399
2435
  //#region src/ui/icons.ts
2400
- var _n = {
2436
+ var yn = {
2401
2437
  play: "<path d=\"M8 5v14l11-7z\"/>",
2402
2438
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2403
2439
  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\"/>",
@@ -2411,20 +2447,20 @@ var _n = {
2411
2447
  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\"/>"
2412
2448
  };
2413
2449
  function Q(e) {
2414
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${_n[e]}</svg>`;
2450
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yn[e]}</svg>`;
2415
2451
  }
2416
2452
  //#endregion
2417
2453
  //#region src/ui/controls.ts
2418
- var vn = 3e3, yn = 250, bn = /* @__PURE__ */ new Set([
2454
+ var bn = 3e3, xn = 250, Sn = /* @__PURE__ */ new Set([
2419
2455
  "GONE",
2420
2456
  "NOT_FOUND",
2421
2457
  "INVALID_URN",
2422
2458
  "UNAUTHORIZED"
2423
2459
  ]);
2424
- function xn(e) {
2425
- return new Sn(e);
2460
+ function Cn(e) {
2461
+ return new wn(e);
2426
2462
  }
2427
- var Sn = class {
2463
+ var wn = class {
2428
2464
  root;
2429
2465
  video;
2430
2466
  player;
@@ -2470,7 +2506,7 @@ var Sn = class {
2470
2506
  scrubbing = !1;
2471
2507
  offFns = [];
2472
2508
  constructor(e) {
2473
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? vn, 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, gn(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");
2509
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? bn, 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, vn(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");
2474
2510
  let t = (e, t, n) => {
2475
2511
  let r = this.doc.createElement(e);
2476
2512
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2556,7 +2592,7 @@ var Sn = class {
2556
2592
  let t = this.surfaceWasHidden;
2557
2593
  this.tapTimer = setTimeout(() => {
2558
2594
  this.tapTimer = void 0, this.toggleBar(t);
2559
- }, yn);
2595
+ }, xn);
2560
2596
  }
2561
2597
  toggleBar(e) {
2562
2598
  e ? this.poke() : this.hideIfIdle();
@@ -2591,7 +2627,7 @@ var Sn = class {
2591
2627
  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);
2592
2628
  } else {
2593
2629
  let r = this.doc.createElement("div");
2594
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !bn.has(this.lastError.code)) {
2630
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Sn.has(this.lastError.code)) {
2595
2631
  let e = this.doc.createElement("button");
2596
2632
  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);
2597
2633
  }
@@ -2632,7 +2668,7 @@ var Sn = class {
2632
2668
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2633
2669
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2634
2670
  }
2635
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Cn(this.video.currentTime)} / ${Cn(this.video.duration)}`);
2671
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Tn(this.video.currentTime)} / ${Tn(this.video.duration)}`);
2636
2672
  }
2637
2673
  syncLive() {
2638
2674
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2682,17 +2718,17 @@ var Sn = class {
2682
2718
  renderQualityMenu() {
2683
2719
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2684
2720
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2685
- for (let n of e) this.menu.append(this.menuItem(wn(n), t === n.index, () => this.player.setQuality(n.index)));
2721
+ for (let n of e) this.menu.append(this.menuItem(En(n), t === n.index, () => this.player.setQuality(n.index)));
2686
2722
  }
2687
2723
  renderAudioMenu() {
2688
2724
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2689
2725
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2690
- for (let t of e) this.menu.append(this.menuItem(Tn(t), t.default, () => this.player.setAudioTrack(t.id)));
2726
+ for (let t of e) this.menu.append(this.menuItem(Dn(t), t.default, () => this.player.setAudioTrack(t.id)));
2691
2727
  }
2692
2728
  renderCcMenu() {
2693
2729
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2694
2730
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2695
- for (let t of e) this.menu.append(this.menuItem(En(t), !1, () => this.player.setTextTrack(t.id)));
2731
+ for (let t of e) this.menu.append(this.menuItem(On(t), !1, () => this.player.setTextTrack(t.id)));
2696
2732
  }
2697
2733
  onTracksChanged() {
2698
2734
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2793,41 +2829,41 @@ var Sn = class {
2793
2829
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2794
2830
  }
2795
2831
  };
2796
- function Cn(e) {
2832
+ function Tn(e) {
2797
2833
  (!Number.isFinite(e) || e < 0) && (e = 0);
2798
2834
  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");
2799
2835
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2800
2836
  }
2801
- function wn(e) {
2837
+ function En(e) {
2802
2838
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2803
2839
  }
2804
- function Tn(e) {
2840
+ function Dn(e) {
2805
2841
  return e.name || e.lang || `Track ${e.id}`;
2806
2842
  }
2807
- function En(e) {
2843
+ function On(e) {
2808
2844
  return e.name || e.lang || `Track ${e.id}`;
2809
2845
  }
2810
2846
  //#endregion
2811
2847
  //#region src/managed/index.ts
2812
- var Dn = 6e3, On = 45e3, kn = 2e3, An = 3, jn = 2e3, Mn = 48e4;
2813
- function Nn(e) {
2848
+ var kn = 6e3, An = 45e3, jn = 2e3, Mn = 3, Nn = 2e3, Pn = 48e4;
2849
+ function Fn(e) {
2814
2850
  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)})`);
2815
2851
  if (e.env !== void 0) return B(e.env);
2816
2852
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2817
2853
  return e.baseUrl;
2818
2854
  }
2819
- async function Pn(e) {
2855
+ async function In(e) {
2820
2856
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2821
- let t = Nn(e);
2857
+ let t = Fn(e);
2822
2858
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2823
2859
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2824
- let r = new Fn({
2860
+ let r = new Ln({
2825
2861
  ...e,
2826
2862
  baseUrl: t
2827
2863
  });
2828
2864
  return await r.start(), r;
2829
2865
  }
2830
- var Fn = class {
2866
+ var Ln = class {
2831
2867
  opts;
2832
2868
  abort = new AbortController();
2833
2869
  listeners = {};
@@ -2915,7 +2951,7 @@ var Fn = class {
2915
2951
  setTimeout(() => {
2916
2952
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2917
2953
  phase: i ? "unavailable" : "tooEarly",
2918
- retryInMs: On,
2954
+ retryInMs: An,
2919
2955
  attempt: 1,
2920
2956
  elapsedMs: 0,
2921
2957
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2954,13 +2990,13 @@ var Fn = class {
2954
2990
  !a && !p() && h();
2955
2991
  }, e);
2956
2992
  };
2957
- _(Dn), this.armingSub = E({
2993
+ _(kn), this.armingSub = E({
2958
2994
  eventsBaseUrl: t,
2959
2995
  matchUrn: this.opts.matchUrn,
2960
2996
  credential: this.opts.credential,
2961
- onAlive: () => _(On),
2997
+ onAlive: () => _(An),
2962
2998
  onState: (e) => {
2963
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kn);
2999
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * jn);
2964
3000
  },
2965
3001
  onError: () => h()
2966
3002
  });
@@ -3005,19 +3041,19 @@ var Fn = class {
3005
3041
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3006
3042
  let i = e.analytics?.sid;
3007
3043
  if (!i) return;
3008
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = nn(this.opts.baseUrl, a, e.analytics?.endpoint);
3044
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = an(this.opts.baseUrl, a, e.analytics?.endpoint);
3009
3045
  if (!o) {
3010
3046
  s && setTimeout(() => {
3011
3047
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3012
3048
  }, 0);
3013
3049
  return;
3014
3050
  }
3015
- let c = this.opts.video, l = new rn({
3051
+ let c = this.opts.video, l = new on({
3016
3052
  endpoint: o,
3017
3053
  sid: i,
3018
3054
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3019
- sdkVersion: un,
3020
- environment: cn(c),
3055
+ sdkVersion: fn,
3056
+ environment: un(c),
3021
3057
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3022
3058
  onIdle: () => this.onAnalyticsIdle(t),
3023
3059
  onBlocked: (e) => setTimeout(() => {
@@ -3038,7 +3074,7 @@ var Fn = class {
3038
3074
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3039
3075
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3040
3076
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3041
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ln().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3077
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), dn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3042
3078
  }
3043
3079
  currentPresentation() {
3044
3080
  let e = this.opts.video;
@@ -3064,9 +3100,9 @@ var Fn = class {
3064
3100
  emit: (e) => this.onEngineEvent(e)
3065
3101
  }, o = this.opts.engine ?? "auto";
3066
3102
  if (o === "native") return new K(a);
3067
- if (o === "hls") return new Rt(a);
3068
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ye() && W(this.opts.video)) return new K(a);
3069
- if (ot()) return new Rt(a);
3103
+ if (o === "hls") return new Bt(a);
3104
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ze() && W(this.opts.video)) return new K(a);
3105
+ if (ct()) return new Bt(a);
3070
3106
  if (W(this.opts.video)) return new K(a);
3071
3107
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3072
3108
  }
@@ -3119,7 +3155,7 @@ var Fn = class {
3119
3155
  r = 0, i = !1;
3120
3156
  },
3121
3157
  onError: () => {
3122
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= An && (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.`))));
3158
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Mn && (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.`))));
3123
3159
  }
3124
3160
  });
3125
3161
  }
@@ -3141,7 +3177,7 @@ var Fn = class {
3141
3177
  scheduleRejoin(e) {
3142
3178
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3143
3179
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3144
- }, Math.random() * kn));
3180
+ }, Math.random() * jn));
3145
3181
  }
3146
3182
  cancelRejoin() {
3147
3183
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3165,7 +3201,7 @@ var Fn = class {
3165
3201
  }
3166
3202
  t.controls = !1;
3167
3203
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3168
- r && r.insertBefore(n, t), n.appendChild(t), pn(n, this.opts.theme), this.container = n, this.controlBar = xn({
3204
+ r && r.insertBefore(n, t), n.appendChild(t), hn(n, this.opts.theme), this.container = n, this.controlBar = Cn({
3169
3205
  root: n,
3170
3206
  video: t,
3171
3207
  player: this,
@@ -3196,7 +3232,7 @@ var Fn = class {
3196
3232
  }
3197
3233
  startStats() {
3198
3234
  this.stopStats();
3199
- let e = Math.max(500, this.opts.statsIntervalMs ?? jn);
3235
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Nn);
3200
3236
  this.statsTimer = setInterval(() => {
3201
3237
  if (!this.engine) return;
3202
3238
  let e = this.engine.getStats();
@@ -3208,7 +3244,7 @@ var Fn = class {
3208
3244
  }
3209
3245
  scheduleLicenseRefresh() {
3210
3246
  this.stopRefresh();
3211
- let e = this.opts.licenseRefreshMs ?? Mn;
3247
+ let e = this.opts.licenseRefreshMs ?? Pn;
3212
3248
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3213
3249
  }
3214
3250
  stopRefresh() {
@@ -3363,7 +3399,7 @@ function $(e) {
3363
3399
  }
3364
3400
  //#endregion
3365
3401
  //#region src/embed/host.ts
3366
- function In(e) {
3402
+ function Rn(e) {
3367
3403
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3368
3404
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3369
3405
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3422,15 +3458,15 @@ function In(e) {
3422
3458
  }
3423
3459
  //#endregion
3424
3460
  //#region src/embed/page.ts
3425
- var Ln = /^[A-Za-z0-9:_.-]{1,128}$/;
3426
- function Rn(e) {
3461
+ var zn = /^[A-Za-z0-9:_.-]{1,128}$/;
3462
+ function Bn(e) {
3427
3463
  if (typeof e == "boolean") return e;
3428
3464
  if (typeof e == "object" && e) {
3429
3465
  let t = e.endpoint;
3430
3466
  return typeof t == "string" ? { endpoint: t } : {};
3431
3467
  }
3432
3468
  }
3433
- function zn() {
3469
+ function Vn() {
3434
3470
  let e = window.HAVIK_EMBED_CONFIG;
3435
3471
  if (e) return {
3436
3472
  baseUrl: e.baseUrl ?? "",
@@ -3440,7 +3476,7 @@ function zn() {
3440
3476
  autoplay: e.autoplay ?? !0,
3441
3477
  muted: e.muted ?? !0,
3442
3478
  waitForLive: e.waitForLive ?? !0,
3443
- analytics: Rn(e.analytics)
3479
+ analytics: Bn(e.analytics)
3444
3480
  };
3445
3481
  let t = new URLSearchParams(location.search);
3446
3482
  return {
@@ -3453,9 +3489,9 @@ function zn() {
3453
3489
  waitForLive: !0
3454
3490
  };
3455
3491
  }
3456
- async function Bn() {
3457
- let e = zn();
3458
- Hn();
3492
+ async function Hn() {
3493
+ let e = Vn();
3494
+ Wn();
3459
3495
  let t = document.createElement("video");
3460
3496
  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);
3461
3497
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3510,12 +3546,12 @@ async function Bn() {
3510
3546
  code: e.code,
3511
3547
  message: e.message
3512
3548
  })), e.on("autoplayblocked", () => {
3513
- i({ type: "oddin:autoplayblocked" }), Vn(t, e);
3549
+ i({ type: "oddin:autoplayblocked" }), Un(t, e);
3514
3550
  });
3515
3551
  }, s = async (r) => {
3516
3552
  a?.destroy(), a = null;
3517
3553
  try {
3518
- let n = await Pn({
3554
+ let n = await In({
3519
3555
  video: t,
3520
3556
  baseUrl: e.baseUrl,
3521
3557
  matchUrn: r,
@@ -3577,7 +3613,7 @@ async function Bn() {
3577
3613
  a?.retry();
3578
3614
  break;
3579
3615
  case "oddin:load":
3580
- typeof e.matchUrn == "string" && Ln.test(e.matchUrn) && s(e.matchUrn);
3616
+ typeof e.matchUrn == "string" && zn.test(e.matchUrn) && s(e.matchUrn);
3581
3617
  break;
3582
3618
  case "oddin:destroy": c();
3583
3619
  }
@@ -3589,18 +3625,18 @@ async function Bn() {
3589
3625
  protocol: 1
3590
3626
  });
3591
3627
  }
3592
- function Vn(e, t) {
3628
+ function Un(e, t) {
3593
3629
  if (document.getElementById("havik-tap")) return;
3594
3630
  let n = document.createElement("button");
3595
3631
  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", () => {
3596
3632
  n.remove(), t.play();
3597
3633
  }), document.body.appendChild(n);
3598
3634
  }
3599
- function Hn() {
3635
+ function Wn() {
3600
3636
  let e = document.createElement("style");
3601
3637
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3602
3638
  }
3603
3639
  //#endregion
3604
- export { dn as ODDIN_THEME, n as PlaybackError, pn as applyTheme, B as baseUrlForEnv, Bn as bootEmbed, we as clearDeviceId, Pn as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, In as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
3640
+ export { pn as ODDIN_THEME, n as PlaybackError, hn as applyTheme, B as baseUrlForEnv, Hn as bootEmbed, we as clearDeviceId, In as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, Rn as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
3605
3641
 
3606
3642
  //# sourceMappingURL=index.js.map