@oddin-gg/havik-player 2.27.0 → 2.27.2

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
@@ -975,26 +975,43 @@ var ht = class {
975
975
  this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
976
976
  };
977
977
  }
978
- };
979
- function gt(e, t) {
980
- let n = [
981
- ["playing", () => t("playing")],
982
- ["waiting", () => t("buffering")],
983
- ["stalled", () => t("buffering")],
978
+ }, gt = .25, _t = 1e3;
979
+ function vt(e, t) {
980
+ let n = null, r = (r) => {
981
+ n = r === "buffering" ? e.currentTime : null, t(r);
982
+ }, i = () => typeof performance < "u" ? performance.now() : Date.now(), a = i(), o = e.currentTime, s = () => {
983
+ let t = e.currentTime;
984
+ t > o && !e.seeking && !e.paused && (a = i()), o = t;
985
+ }, c = [
986
+ ["playing", () => {
987
+ a = i(), o = e.currentTime, r("playing");
988
+ }],
989
+ ["waiting", () => r("buffering")],
990
+ ["stalled", () => {
991
+ if (e.paused) return;
992
+ let t = e.readyState < HTMLMediaElement.HAVE_FUTURE_DATA, n = i() - a >= _t;
993
+ (t || n) && r("buffering");
994
+ }],
995
+ ["seeked", () => {
996
+ o = e.currentTime, n !== null && (n = e.currentTime);
997
+ }],
998
+ ["timeupdate", () => {
999
+ s(), n !== null && !e.paused && !e.seeking && e.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA && e.currentTime - n >= gt && r("playing");
1000
+ }],
984
1001
  ["pause", () => {
985
- e.ended || t("paused");
1002
+ e.ended || r("paused");
986
1003
  }],
987
- ["ended", () => t("ended")]
1004
+ ["ended", () => r("ended")]
988
1005
  ];
989
- for (let [t, r] of n) e.addEventListener(t, r);
1006
+ for (let [t, n] of c) e.addEventListener(t, n);
990
1007
  return () => {
991
- for (let [t, r] of n) e.removeEventListener(t, r);
1008
+ for (let [t, n] of c) e.removeEventListener(t, n);
992
1009
  };
993
1010
  }
994
1011
  //#endregion
995
1012
  //#region src/core/engine/native.ts
996
- var _t = 2e3, vt = 3, z = 500, yt = 6e3, bt = .25, xt = 250, St = .05, Ct = 4, wt = 12e3, Tt = .25, Et = 1e3;
997
- function Dt(e) {
1013
+ var yt = 2e3, bt = 3, z = 500, xt = 6e3, St = .25, Ct = 250, wt = .05, Tt = 4, Et = 12e3, Dt = .25, Ot = 1e3;
1014
+ function kt(e) {
998
1015
  try {
999
1016
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
1000
1017
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -1010,7 +1027,7 @@ function V() {
1010
1027
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
1011
1028
  return e || t;
1012
1029
  }
1013
- function Ot() {
1030
+ function At() {
1014
1031
  if (typeof navigator > "u" || !V()) return !1;
1015
1032
  let e = navigator.userAgent ?? "";
1016
1033
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -1066,7 +1083,7 @@ var H = class {
1066
1083
  type: "error",
1067
1084
  error: L() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
1068
1085
  fatal: !0
1069
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = At(t.manifestUrl, t.analytics?.sid), e.load();
1086
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Mt(t.manifestUrl, t.analytics?.sid), e.load();
1070
1087
  }
1071
1088
  startLoad() {
1072
1089
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -1094,7 +1111,7 @@ var H = class {
1094
1111
  };
1095
1112
  this.onEncrypted = (n) => {
1096
1113
  let a = n;
1097
- a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Dt(a.initData), (async () => {
1114
+ a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = kt(a.initData), (async () => {
1098
1115
  try {
1099
1116
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
1100
1117
  initDataTypes: [a.initDataType],
@@ -1197,7 +1214,7 @@ var H = class {
1197
1214
  if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1198
1215
  n.isLive = !0;
1199
1216
  let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1200
- Number.isFinite(r) && (n.atLiveEdge = r <= Ct, !e.paused && r >= 0 && (n.latencySeconds = r));
1217
+ Number.isFinite(r) && (n.atLiveEdge = r <= Tt, !e.paused && r >= 0 && (n.latencySeconds = r));
1201
1218
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1202
1219
  return n;
1203
1220
  }
@@ -1215,7 +1232,7 @@ var H = class {
1215
1232
  return;
1216
1233
  }
1217
1234
  let t = this.hiddenSince;
1218
- this.hiddenSince = null, t != null && e - t >= _t && this.armRefocus();
1235
+ this.hiddenSince = null, t != null && e - t >= yt && this.armRefocus();
1219
1236
  }, this.onPageShow = (e) => {
1220
1237
  e.persisted && this.armRefocus();
1221
1238
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
@@ -1225,7 +1242,7 @@ var H = class {
1225
1242
  let e = this.liveEnd(), t = U, n = t(), r = 0, i = () => {
1226
1243
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1227
1244
  r += z;
1228
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + bt), s = Math.max(r, t() - n) >= yt;
1245
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + St), s = Math.max(r, t() - n) >= xt;
1229
1246
  if (o || s && a != null) {
1230
1247
  this.snapToLive();
1231
1248
  return;
@@ -1245,9 +1262,9 @@ var H = class {
1245
1262
  }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1246
1263
  if (e.duration !== Infinity) return;
1247
1264
  this.checkEndStale();
1248
- let t = kt(e, e.currentTime);
1249
- t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= St) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
1250
- }, xt);
1265
+ let t = jt(e, e.currentTime);
1266
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= wt) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
1267
+ }, Ct);
1251
1268
  }
1252
1269
  checkEndStale() {
1253
1270
  if (this.endedEmitted) return;
@@ -1255,14 +1272,14 @@ var H = class {
1255
1272
  this.lastTickAt = e;
1256
1273
  let n = this.liveEnd();
1257
1274
  if (n == null) return;
1258
- let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Tt;
1275
+ let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Dt;
1259
1276
  this.lastSeekableEnd = n;
1260
1277
  let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
1261
- if (r || t > Et || a || i.paused) {
1278
+ if (r || t > Ot || a || i.paused) {
1262
1279
  this.edgeStampedAt = e;
1263
1280
  return;
1264
1281
  }
1265
- e - (this.edgeStampedAt ?? e) > wt && (this.endedEmitted = !0, this.deps.emit({
1282
+ e - (this.edgeStampedAt ?? e) > Et && (this.endedEmitted = !0, this.deps.emit({
1266
1283
  type: "ended",
1267
1284
  reason: "stalled"
1268
1285
  }));
@@ -1276,7 +1293,7 @@ var H = class {
1276
1293
  liveEdgeEstimate() {
1277
1294
  let e = this.deps.video;
1278
1295
  if (e.duration !== Infinity) return null;
1279
- let t = this.liveEnd(), n = kt(e, e.currentTime) ?? this.lastBufferedEnd;
1296
+ let t = this.liveEnd(), n = jt(e, e.currentTime) ?? this.lastBufferedEnd;
1280
1297
  if (n != null) {
1281
1298
  let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (U() - e) / 1e3));
1282
1299
  (t == null || r > t) && (t = r);
@@ -1292,7 +1309,7 @@ var H = class {
1292
1309
  snapToLive() {
1293
1310
  let e = this.deps.video, t = this.liveEnd();
1294
1311
  if (t == null) return;
1295
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - vt, r);
1312
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - bt, r);
1296
1313
  try {
1297
1314
  e.currentTime = i;
1298
1315
  } catch {}
@@ -1313,7 +1330,7 @@ var H = class {
1313
1330
  function U() {
1314
1331
  return typeof performance < "u" ? performance.now() : Date.now();
1315
1332
  }
1316
- function kt(e, t) {
1333
+ function jt(e, t) {
1317
1334
  let n = e.buffered;
1318
1335
  if (!n || !Number.isFinite(t)) return null;
1319
1336
  for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
@@ -1322,7 +1339,7 @@ function kt(e, t) {
1322
1339
  }
1323
1340
  return null;
1324
1341
  }
1325
- function At(e, t) {
1342
+ function Mt(e, t) {
1326
1343
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1327
1344
  }
1328
1345
  //#endregion
@@ -1339,13 +1356,13 @@ function W(e, t = Date.now()) {
1339
1356
  }
1340
1357
  //#endregion
1341
1358
  //#region src/core/drm/xhrBody.ts
1342
- var jt = 4096;
1343
- function Mt(e) {
1359
+ var Nt = 4096;
1360
+ function Pt(e) {
1344
1361
  if (!e || typeof e != "object") return;
1345
1362
  let { response: t } = e;
1346
1363
  if (typeof t == "string") return t;
1347
1364
  let n;
1348
- if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > jt)) try {
1365
+ if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Nt)) try {
1349
1366
  return new TextDecoder().decode(n);
1350
1367
  } catch {
1351
1368
  return;
@@ -1353,7 +1370,7 @@ function Mt(e) {
1353
1370
  }
1354
1371
  //#endregion
1355
1372
  //#region src/core/engine/prefetch.ts
1356
- var Nt = 15e3, Pt = 5e3, Ft = 6, It = 4e3, Lt = 2;
1373
+ var Ft = 15e3, It = 5e3, Lt = 6, Rt = 4e3, zt = 2;
1357
1374
  function G(e) {
1358
1375
  try {
1359
1376
  let t = new URL(e);
@@ -1362,7 +1379,7 @@ function G(e) {
1362
1379
  return e;
1363
1380
  }
1364
1381
  }
1365
- var Rt = class {
1382
+ var Bt = class {
1366
1383
  cmcd;
1367
1384
  entries = /* @__PURE__ */ new Map();
1368
1385
  keyed = /* @__PURE__ */ new Set();
@@ -1394,17 +1411,17 @@ var Rt = class {
1394
1411
  let r = G(e);
1395
1412
  if (this.entries.has(r)) return;
1396
1413
  let i = this.perTrack.get(t) ?? 0;
1397
- i >= Ft || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Nt), this.stats.started += 1);
1414
+ i >= Lt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Ft), this.stats.started += 1);
1398
1415
  }
1399
1416
  prefetchHint(e, t) {
1400
1417
  let n = G(e);
1401
1418
  if (this.entries.has(n)) return;
1402
1419
  let r = this.hints.get(t) ?? [];
1403
- for (; r.length >= Lt;) {
1420
+ for (; r.length >= zt;) {
1404
1421
  let e = r.shift();
1405
1422
  e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
1406
1423
  }
1407
- r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, It), this.stats.hintStarted += 1;
1424
+ r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Rt), this.stats.hintStarted += 1;
1408
1425
  }
1409
1426
  dropHints(e) {
1410
1427
  for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
@@ -1457,14 +1474,14 @@ var Rt = class {
1457
1474
  }
1458
1475
  }
1459
1476
  };
1460
- function zt(t, n) {
1477
+ function Vt(t, n) {
1461
1478
  let r = typeof n == "function" ? n : e.DefaultConfig?.loader;
1462
1479
  if (typeof r != "function") return;
1463
1480
  class i extends r {
1464
1481
  served = !1;
1465
1482
  cancelled = !1;
1466
1483
  entry;
1467
- stats = Bt();
1484
+ stats = Ht();
1468
1485
  load(e, n, r) {
1469
1486
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1470
1487
  if (!i) {
@@ -1476,7 +1493,7 @@ function zt(t, n) {
1476
1493
  i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
1477
1494
  }, s = () => {
1478
1495
  !this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
1479
- }, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Pt, u = setTimeout(s, l);
1496
+ }, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || It, u = setTimeout(s, l);
1480
1497
  i.headers.then(() => {
1481
1498
  clearTimeout(u);
1482
1499
  let e = c?.maxLoadTimeMs;
@@ -1509,7 +1526,7 @@ function zt(t, n) {
1509
1526
  }
1510
1527
  return i;
1511
1528
  }
1512
- function Bt() {
1529
+ function Ht() {
1513
1530
  return {
1514
1531
  aborted: !1,
1515
1532
  loaded: 0,
@@ -1533,10 +1550,10 @@ function Bt() {
1533
1550
  }
1534
1551
  };
1535
1552
  }
1536
- function Vt(e) {
1553
+ function Ut(e) {
1537
1554
  return e === "audio" ? "audio" : "main";
1538
1555
  }
1539
- function Ht(e, t) {
1556
+ function Wt(e, t) {
1540
1557
  let n = [];
1541
1558
  t.initSegment?.url && !t.initSegment.data && n.push({
1542
1559
  url: t.initSegment.url,
@@ -1553,7 +1570,7 @@ function Ht(e, t) {
1553
1570
  });
1554
1571
  return n;
1555
1572
  }
1556
- function Ut(e) {
1573
+ function Gt(e) {
1557
1574
  let t = e, n = t?.preloadHint;
1558
1575
  if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
1559
1576
  let r = n.URI;
@@ -1571,15 +1588,15 @@ function K(e, t) {
1571
1588
  }
1572
1589
  //#endregion
1573
1590
  //#region src/core/engine/hls.ts
1574
- function Wt() {
1591
+ function Kt() {
1575
1592
  return e.isSupported();
1576
1593
  }
1577
- var Gt = 3, Kt = 1e6, qt = 20, Jt = 1e4, Yt = 3, Xt = 5, Zt = 3, Qt = 1e4, $t = 3e4, en = 12e3, tn = 3e3, nn = .02, rn = 6e3, an = .5, on = 3, sn = .5, cn = 1.1, ln = .25, un = 5e3, dn = 4e3, fn = 2, pn = 5, mn = 2, hn = 2, gn = 4, _n = 4, vn = 2e3, yn = 3e4, bn = 1, xn = 2, Sn = .5, Cn = .6, wn = 2, Tn = 1.5, En = 1e4, Dn = 18e4, On = .5, kn = 2;
1578
- function An(e) {
1594
+ var qt = 3, Jt = 1e6, Yt = 20, Xt = 1e4, Zt = 3, Qt = 5, $t = 3, en = 1e4, tn = 3e4, nn = 12e3, rn = 3e3, an = .02, on = 6e3, sn = .5, cn = 3, ln = .5, un = 1.1, dn = .25, fn = 5e3, pn = 4e3, mn = 2, hn = 5, gn = 2, _n = 2, vn = 4, yn = 4, bn = 2e3, xn = 3e4, Sn = 1, Cn = 2, wn = .5, Tn = .6, En = 2, Dn = 1.5, On = 1e4, kn = 18e4, An = .5, jn = 2;
1595
+ function Mn(e) {
1579
1596
  let t = e.config ?? {};
1580
1597
  return t.capLevelToPlayerSize === !0 || t.capLevelOnFPSDrop === !0;
1581
1598
  }
1582
- var q = 8, jn = 12e4, Mn = 6e4;
1599
+ var q = 8, Nn = 12e4, Pn = 6e4;
1583
1600
  function J(e, t, n) {
1584
1601
  if (n <= 0 || t < 0 || t >= e.length) return t;
1585
1602
  let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
@@ -1592,11 +1609,11 @@ function J(e, t, n) {
1592
1609
  function Y() {
1593
1610
  return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
1594
1611
  }
1595
- var Nn = .2, Pn = 30, Fn = 2, In = 2, Ln = 2, Rn = 9, zn = .5, Bn = 64, Vn = 1e4, Hn = 8, Un = .6, Wn = .4, Gn = .4, Kn = 2, qn = 6e4, X = .5, Jn = 3.5, Yn = 300;
1596
- function Xn(e) {
1612
+ var Fn = .2, In = 30, Ln = 2, Rn = 2, zn = 2, Bn = 9, Vn = .5, Hn = 64, Un = 1e4, Wn = 8, Gn = .6, Kn = .4, qn = .4, Jn = 2, Yn = 6e4, X = .5, Xn = 3.5, Zn = 300;
1613
+ function Qn(e) {
1597
1614
  return (e?.part ?? e?.frag)?.stats;
1598
1615
  }
1599
- function Zn() {
1616
+ function $n() {
1600
1617
  if (typeof navigator > "u") return 0;
1601
1618
  try {
1602
1619
  let e = navigator.connection?.rtt;
@@ -1605,20 +1622,20 @@ function Zn() {
1605
1622
  return 0;
1606
1623
  }
1607
1624
  }
1608
- function Qn(e) {
1625
+ function er(e) {
1609
1626
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1610
1627
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1611
1628
  return;
1612
1629
  }
1613
- e.liveSyncDuration ??= Ln;
1614
- let t = Math.max(12, e.liveSyncDuration + Rn);
1615
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), $n(e, e.liveSyncDuration);
1630
+ e.liveSyncDuration ??= zn;
1631
+ let t = Math.max(12, e.liveSyncDuration + Bn);
1632
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), tr(e, e.liveSyncDuration);
1616
1633
  }
1617
- function $n(e, t) {
1634
+ function tr(e, t) {
1618
1635
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1619
1636
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1620
1637
  }
1621
- var er = class {
1638
+ var nr = class {
1622
1639
  name = "hls";
1623
1640
  hls = null;
1624
1641
  deps;
@@ -1771,7 +1788,7 @@ var er = class {
1771
1788
  }
1772
1789
  this.loadSuspended = !0;
1773
1790
  }
1774
- }, un));
1791
+ }, fn));
1775
1792
  }
1776
1793
  resumeLoading() {
1777
1794
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1803,7 +1820,7 @@ var er = class {
1803
1820
  let t = e.liveSyncPosition;
1804
1821
  if (typeof t != "number" || !Number.isFinite(t)) return;
1805
1822
  let { video: n } = this.deps;
1806
- n.currentTime <= t + zn || (n.currentTime = t);
1823
+ n.currentTime <= t + Vn || (n.currentTime = t);
1807
1824
  }
1808
1825
  reanchorPartTimeline(e, t) {
1809
1826
  let { frag: n, part: r } = t;
@@ -1815,7 +1832,7 @@ var er = class {
1815
1832
  let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1816
1833
  if (!s) return;
1817
1834
  let c = a.startPTS - s.start;
1818
- if (!(!Number.isFinite(c) || Math.abs(c) < nn)) {
1835
+ if (!(!Number.isFinite(c) || Math.abs(c) < an)) {
1819
1836
  for (let e of i.fragments) e && e.setStart(e.start + c);
1820
1837
  i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
1821
1838
  }
@@ -1855,7 +1872,7 @@ var er = class {
1855
1872
  return;
1856
1873
  }
1857
1874
  let l = this.hls, u, d = new Promise((e) => {
1858
- u = setTimeout(() => e(void 0), Qt);
1875
+ u = setTimeout(() => e(void 0), en);
1859
1876
  });
1860
1877
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1861
1878
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1873,28 +1890,28 @@ var er = class {
1873
1890
  this.prefetch?.destroy(), this.prefetch = null;
1874
1891
  let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints !== !1;
1875
1892
  if ((h || g) && !f.fLoader) {
1876
- let e = new Rt({
1893
+ let e = new Bt({
1877
1894
  sessionId: n.analytics?.sid,
1878
1895
  contentId: n.matchUrn
1879
- }), t = zt(e, f.loader);
1896
+ }), t = Vt(e, f.loader);
1880
1897
  t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
1881
1898
  }
1882
- Qn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1899
+ er(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1883
1900
  let _ = new e(f);
1884
1901
  if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
1885
1902
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1886
1903
  }), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
1887
1904
  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(() => {
1888
1905
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1889
- }, $t)));
1906
+ }, tn)));
1890
1907
  }), _.on(e.Events.FRAG_LOADING, (e, t) => {
1891
1908
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1892
1909
  }), _.on(e.Events.FRAG_LOADED, (e, t) => {
1893
1910
  t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
1894
- let n = t?.frag, r = Xn(t), i = r?.loaded;
1911
+ let n = t?.frag, r = Qn(t), i = r?.loaded;
1895
1912
  typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1896
1913
  let a = r?.loading;
1897
- a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Bn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
1914
+ a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Hn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
1898
1915
  let o = n?.url;
1899
1916
  if (o) {
1900
1917
  let e = ft(o);
@@ -1914,8 +1931,8 @@ var er = class {
1914
1931
  let i = e;
1915
1932
  if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
1916
1933
  let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
1917
- if (i.edge - o > Gt * (i.partTarget || .5)) return;
1918
- let s = Ut(e);
1934
+ if (i.edge - o > qt * (i.partTarget || .5)) return;
1935
+ let s = Gt(e);
1919
1936
  s && t.prefetchHint(s, r);
1920
1937
  };
1921
1938
  _.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1927,15 +1944,15 @@ var er = class {
1927
1944
  if (this.prefetch && p) {
1928
1945
  let t = this.prefetch;
1929
1946
  _.on(e.Events.KEY_LOADING, (e, n) => {
1930
- let r = n?.frag, i = Vt(r?.type);
1931
- if (r && t.isActive(i)) for (let e of Ht(_, r)) t.prefetch(e.url, i, e.kind);
1932
- }), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Vt(n?.frag?.type)));
1947
+ let r = n?.frag, i = Ut(r?.type);
1948
+ if (r && t.isActive(i)) for (let e of Wt(_, r)) t.prefetch(e.url, i, e.kind);
1949
+ }), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Ut(n?.frag?.type)));
1933
1950
  }
1934
1951
  _.on(e.Events.KEY_LOADED, () => {
1935
1952
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1936
1953
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1937
1954
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.releaseStallCap(), this.checkFrameDrops();
1938
- }, tn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1955
+ }, rn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1939
1956
  this.renditionSwitches += 1;
1940
1957
  let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
1941
1958
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
@@ -1996,8 +2013,8 @@ var er = class {
1996
2013
  let e = this.hls, t = this.sizeCapCover();
1997
2014
  if (!e || !t) return null;
1998
2015
  let { cover: n, deviceRatio: r } = t, i = this.deps.sizeCapHeadroom, a = i == null || Number.isNaN(i);
1999
- if (a && r >= xn) return n;
2000
- if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, bn) : n;
2016
+ if (a && r >= Cn) return n;
2017
+ if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, Sn) : n;
2001
2018
  let o = i === Infinity ? e.levels.length : Math.max(0, Math.floor(i));
2002
2019
  return J(e.levels, n, o);
2003
2020
  }
@@ -2014,11 +2031,11 @@ var er = class {
2014
2031
  return;
2015
2032
  }
2016
2033
  this.capTimer && clearTimeout(this.capTimer);
2017
- let t = e > this.sizeCapLevel ? vn : yn;
2034
+ let t = e > this.sizeCapLevel ? bn : xn;
2018
2035
  this.capTimer = setTimeout(() => {
2019
2036
  this.capTimer = null;
2020
2037
  let n = this.computeSizeCapTarget();
2021
- n === e || t === yn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
2038
+ n === e || t === xn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
2022
2039
  }, t);
2023
2040
  }
2024
2041
  measureLadder(e) {
@@ -2045,7 +2062,7 @@ var er = class {
2045
2062
  }
2046
2063
  defaultHeadroomApplies() {
2047
2064
  let e = this.deps.sizeCapHeadroom;
2048
- return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < xn;
2065
+ return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < Cn;
2049
2066
  }
2050
2067
  applySizeCapUnlessPending() {
2051
2068
  this.capTimer || this.applySizeCap();
@@ -2054,7 +2071,7 @@ var er = class {
2054
2071
  if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
2055
2072
  let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
2056
2073
  if (typeof t != "number" || !(t > 0)) return;
2057
- let n = Xn(e)?.loading;
2074
+ let n = Qn(e)?.loading;
2058
2075
  if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
2059
2076
  let r = this.hls?.levels?.[e.frag.level]?.bitrate;
2060
2077
  if (!(typeof r == "number" && r > 0)) return;
@@ -2067,7 +2084,7 @@ var er = class {
2067
2084
  }
2068
2085
  onPlaybackStall(e) {
2069
2086
  let t = Date.now();
2070
- this.deps.video.seeking || !this.playingSince || t - this.playingSince < En || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
2087
+ this.deps.video.seeking || !this.playingSince || t - this.playingSince < On || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
2071
2088
  }
2072
2089
  stallCapLevel(e) {
2073
2090
  if (this.stallCapBitrate == null) return -1;
@@ -2078,7 +2095,7 @@ var er = class {
2078
2095
  }
2079
2096
  stepStallCapDown(e, t) {
2080
2097
  let n = this.hls;
2081
- if (!n || !this.stallCapEnabled || An(n) || !n.autoLevelEnabled || typeof t == "number" && t >= On || this.isLiveEdgeWait(n, t ?? 0)) return;
2098
+ if (!n || !this.stallCapEnabled || Mn(n) || !n.autoLevelEnabled || typeof t == "number" && t >= An || this.isLiveEdgeWait(n, t ?? 0)) return;
2082
2099
  this.stallCapBitrate != null && (this.stallCapSince = e);
2083
2100
  let r = Math.max(n.levels[n.currentLevel]?.bitrate ?? 0, n.levels[n.loadLevel]?.bitrate ?? 0);
2084
2101
  if (!(r > 0)) return;
@@ -2089,7 +2106,7 @@ var er = class {
2089
2106
  let n = e.latestLevelDetails;
2090
2107
  if (!n?.live) return !1;
2091
2108
  let r = n.partTarget || n.targetduration;
2092
- return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < kn * r;
2109
+ return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < jn * r;
2093
2110
  }
2094
2111
  releaseStallCap() {
2095
2112
  let e = this.hls, t = Date.now(), n = this.stallCapTickAt;
@@ -2098,7 +2115,7 @@ var er = class {
2098
2115
  n && (this.stallCapSince += t - Math.max(n, this.stallCapSince));
2099
2116
  return;
2100
2117
  }
2101
- if (t - this.stallCapSince < Dn) return;
2118
+ if (t - this.stallCapSince < kn) return;
2102
2119
  let r = this.stallCapBitrate, i = e.levels.map((e) => e.bitrate).filter((e) => e > r).sort((e, t) => e - t)[0];
2103
2120
  this.stallCapBitrate = i ?? null, this.stallCapSince = t, this.pushCap();
2104
2121
  }
@@ -2111,26 +2128,26 @@ var er = class {
2111
2128
  this.headroomGranted = !1, this.headroomSamples = [];
2112
2129
  return;
2113
2130
  }
2114
- this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Vn);
2131
+ this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Un);
2115
2132
  let r = this.headroomEarned(n, e);
2116
- r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Mn), this.headroomGranted = r, this.applySizeCapUnlessPending());
2133
+ r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Pn), this.headroomGranted = r, this.applySizeCapUnlessPending());
2117
2134
  }
2118
2135
  headroomEarned(e, t) {
2119
- if (t - this.lastStallAt < jn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
2136
+ if (t - this.lastStallAt < Nn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
2120
2137
  let n = e.levels, r = this.sizeCapCoverLevel();
2121
2138
  if (r == null) return this.headroomGranted;
2122
- let i = J(n, r, bn);
2139
+ let i = J(n, r, Sn);
2123
2140
  if (i === r) return this.headroomGranted;
2124
- let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? Tn : wn;
2141
+ let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? Dn : En;
2125
2142
  if (!(a > 0) || !(o >= s * a)) return !1;
2126
2143
  let c = (e) => K([...e].sort((e, t) => e - t), 90);
2127
2144
  if (this.headroomGranted) {
2128
2145
  let e = this.headroomSamples.filter((e) => e.bitrate >= a).map((e) => e.ratio);
2129
- return e.length < q || c(e) <= Cn;
2146
+ return e.length < q || c(e) <= Tn;
2130
2147
  }
2131
2148
  let l = [];
2132
2149
  for (let e of this.headroomSamples) e.bitrate < a && l.push(e.ratio * (a / e.bitrate));
2133
- return l.length >= q && c(l) <= Sn;
2150
+ return l.length >= q && c(l) <= wn;
2134
2151
  }
2135
2152
  applySizeCap() {
2136
2153
  if (!this.sizeCapManaged) return;
@@ -2205,7 +2222,7 @@ var er = class {
2205
2222
  let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
2206
2223
  t && (n.levelHeight = t.height);
2207
2224
  let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
2208
- i && i.height > 0 && (n.maxLevelHeight = i.height, !An(e) && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason)), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
2225
+ i && i.height > 0 && (n.maxLevelHeight = i.height, !Mn(e) && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason)), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
2209
2226
  }
2210
2227
  return n;
2211
2228
  }
@@ -2233,7 +2250,7 @@ var er = class {
2233
2250
  return;
2234
2251
  }
2235
2252
  let e = Date.now() - this.lastAdvanceMs;
2236
- !this.chaseSuspended && e > rn && this.suspendChasing(), e > en && this.emitEnded("stalled");
2253
+ !this.chaseSuspended && e > on && this.suspendChasing(), e > nn && this.emitEnded("stalled");
2237
2254
  }
2238
2255
  resetStarvationWindow() {
2239
2256
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -2248,7 +2265,7 @@ var er = class {
2248
2265
  this.resetStarvationWindow();
2249
2266
  return;
2250
2267
  }
2251
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < rn, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
2268
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < on, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > pn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
2252
2269
  if (this.starvedFrames = c, !a || l) {
2253
2270
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
2254
2271
  return;
@@ -2257,12 +2274,12 @@ var er = class {
2257
2274
  this.resetStarvationWindow();
2258
2275
  return;
2259
2276
  }
2260
- if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > gn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mn && (this.clearKick(), this.starvationRebuilds < hn)) {
2277
+ 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 > vn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= gn && (this.clearKick(), this.starvationRebuilds < _n)) {
2261
2278
  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");
2262
2279
  return;
2263
2280
  }
2264
- let u = i && this.starvedTicks >= fn, d = !i && this.deadTicks >= gn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _n;
2265
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pn))) {
2281
+ let u = i && this.starvedTicks >= mn, d = !i && this.deadTicks >= vn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= yn;
2282
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= hn))) {
2266
2283
  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");
2267
2284
  try {
2268
2285
  e.stopLoad(), e.startLoad(-1);
@@ -2277,7 +2294,7 @@ var er = class {
2277
2294
  let t = e.latency, n = e.targetLatency;
2278
2295
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
2279
2296
  let r = t - n;
2280
- !this.catchUpEngaged && r > an ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= an && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2297
+ !this.catchUpEngaged && r > sn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= sn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2281
2298
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
2282
2299
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
2283
2300
  }
@@ -2290,7 +2307,7 @@ var er = class {
2290
2307
  }), n < 0 ? 0 : n;
2291
2308
  }
2292
2309
  armFrameDropGrace() {
2293
- this.fpsGraceTicks > 0 || (this.fpsGraceTicks = In, this.fpsBadTicks = 0);
2310
+ this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Rn, this.fpsBadTicks = 0);
2294
2311
  }
2295
2312
  resetFrameDropWindow() {
2296
2313
  this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
@@ -2302,7 +2319,7 @@ var er = class {
2302
2319
  return;
2303
2320
  }
2304
2321
  let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
2305
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Pn || o < 0) {
2322
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < In || o < 0) {
2306
2323
  this.fpsBadTicks = 0;
2307
2324
  return;
2308
2325
  }
@@ -2310,11 +2327,11 @@ var er = class {
2310
2327
  --this.fpsGraceTicks, this.fpsBadTicks = 0;
2311
2328
  return;
2312
2329
  }
2313
- if (o <= Nn * a) {
2330
+ if (o <= Fn * a) {
2314
2331
  this.fpsBadTicks = 0;
2315
2332
  return;
2316
2333
  }
2317
- if (this.fpsBadTicks += 1, this.fpsBadTicks < Fn) return;
2334
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Ln) return;
2318
2335
  this.fpsBadTicks = 0;
2319
2336
  let s = e.levels, c = s[e.currentLevel];
2320
2337
  if (!c) return;
@@ -2331,22 +2348,22 @@ var er = class {
2331
2348
  return;
2332
2349
  }
2333
2350
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
2334
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(cn, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2351
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(un, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2335
2352
  this.resetChaseWindow();
2336
2353
  return;
2337
2354
  }
2338
- if (this.chaseLatency < 0 || this.chaseLatency - n >= sn) {
2355
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= ln) {
2339
2356
  this.chaseLatency = n, this.chaseTicks = 0;
2340
2357
  return;
2341
2358
  }
2342
- if (this.chaseTicks += 1, this.chaseTicks < on) return;
2359
+ if (this.chaseTicks += 1, this.chaseTicks < cn) return;
2343
2360
  this.resetChaseWindow();
2344
2361
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2345
2362
  if (!(a > 1)) return;
2346
2363
  let o = e.targetLatency;
2347
2364
  if (typeof o != "number" || !(o > 0)) return;
2348
2365
  let s = Math.min(n, a - 1);
2349
- s < o + ln || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
2366
+ s < o + dn || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
2350
2367
  type: "livetargetchange",
2351
2368
  change: {
2352
2369
  targetSeconds: s,
@@ -2363,13 +2380,13 @@ var er = class {
2363
2380
  if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
2364
2381
  let t = e.targetLatency;
2365
2382
  if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
2366
- let n = Zn();
2367
- if (!(n >= Yn)) return;
2383
+ let n = $n();
2384
+ if (!(n >= Zn)) return;
2368
2385
  let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
2369
2386
  i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
2370
2387
  }
2371
2388
  holdBackCeiling(e) {
2372
- let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Jn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2389
+ let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Xn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2373
2390
  return r > 1 ? Math.min(n, r - 1) : n;
2374
2391
  }
2375
2392
  sampleHoldBack(e) {
@@ -2378,7 +2395,7 @@ var er = class {
2378
2395
  if (t !== "main" && t !== "audio") return;
2379
2396
  let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
2380
2397
  if (typeof n != "number" || !(n > 0)) return;
2381
- let r = Xn(e)?.loading;
2398
+ let r = Qn(e)?.loading;
2382
2399
  if (!r || !(r.start > 0) || !(r.end > 0)) return;
2383
2400
  let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
2384
2401
  this.holdBackSamples.push({
@@ -2393,20 +2410,20 @@ var er = class {
2393
2410
  this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
2394
2411
  return;
2395
2412
  }
2396
- let t = Date.now(), n = t - Vn, r = this.holdBackSamples, i = 0;
2413
+ let t = Date.now(), n = t - Un, r = this.holdBackSamples, i = 0;
2397
2414
  for (; i < r.length && r[i].t < n;) i += 1;
2398
2415
  i > 0 && r.splice(0, i);
2399
2416
  let a = e.targetLatency;
2400
2417
  if (typeof a != "number" || !(a > 0)) return;
2401
2418
  this.holdBackBase < 0 && (this.holdBackBase = a);
2402
2419
  let o = this.holdBackBase, s = this.holdBackCeiling(e);
2403
- if (r.length < Hn) {
2420
+ if (r.length < Wn) {
2404
2421
  this.holdBackSlowTicks = 0;
2405
2422
  return;
2406
2423
  }
2407
2424
  let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
2408
- if (l >= Un && u >= Wn) {
2409
- if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Kn) return;
2425
+ if (l >= Gn && u >= Kn) {
2426
+ if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Jn) return;
2410
2427
  this.holdBackSlowTicks = 0;
2411
2428
  let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
2412
2429
  if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
@@ -2416,7 +2433,7 @@ var er = class {
2416
2433
  this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
2417
2434
  return;
2418
2435
  }
2419
- if (this.holdBackSlowTicks = 0, l >= Gn) {
2436
+ if (this.holdBackSlowTicks = 0, l >= qn) {
2420
2437
  this.holdBackFastSince = 0;
2421
2438
  return;
2422
2439
  }
@@ -2424,7 +2441,7 @@ var er = class {
2424
2441
  this.holdBackFastSince = t;
2425
2442
  return;
2426
2443
  }
2427
- if (t - this.holdBackFastSince < qn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2444
+ if (t - this.holdBackFastSince < Yn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2428
2445
  --this.holdBackStepCount;
2429
2446
  let f = Math.max(o, o + this.holdBackStepCount * X);
2430
2447
  f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
@@ -2467,12 +2484,12 @@ var er = class {
2467
2484
  } catch {}
2468
2485
  }
2469
2486
  startEstimate() {
2470
- return this.deps.rememberBandwidth === !1 ? Kt : Be() ?? Kt;
2487
+ return this.deps.rememberBandwidth === !1 ? Jt : Be() ?? Jt;
2471
2488
  }
2472
2489
  maybeRememberBandwidth(e) {
2473
- if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < qt) return;
2490
+ if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Yt) return;
2474
2491
  let t = Date.now();
2475
- if (!e && t - this.bwSavedAt < Jt) return;
2492
+ if (!e && t - this.bwSavedAt < Xt) return;
2476
2493
  let n = this.hls?.bandwidthEstimate;
2477
2494
  typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ve(n));
2478
2495
  }
@@ -2492,7 +2509,7 @@ var er = class {
2492
2509
  scheduleLicenseRetry(t) {
2493
2510
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
2494
2511
  let n = t.response?.code ?? 0;
2495
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Zt) return !1;
2512
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= $t) return !1;
2496
2513
  this.licenseRecoveries += 1;
2497
2514
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
2498
2515
  return this.licenseRetryTimer = setTimeout(() => {
@@ -2528,7 +2545,7 @@ var er = class {
2528
2545
  this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
2529
2546
  return;
2530
2547
  }
2531
- if (this.networkRecoveries < Xt) {
2548
+ if (this.networkRecoveries < Qt) {
2532
2549
  this.networkRecoveries += 1;
2533
2550
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
2534
2551
  this.networkRetryTimer = setTimeout(() => {
@@ -2545,7 +2562,7 @@ var er = class {
2545
2562
  return;
2546
2563
  }
2547
2564
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
2548
- if (this.mediaRecoveries < Yt) {
2565
+ if (this.mediaRecoveries < Zt) {
2549
2566
  this.mediaRecoveries += 1, n.recoverMediaError();
2550
2567
  return;
2551
2568
  }
@@ -2566,18 +2583,18 @@ var er = class {
2566
2583
  }
2567
2584
  }
2568
2585
  toError(t, r = "PLAYBACK") {
2569
- let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Mt(t.networkDetails)) : void 0;
2586
+ let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Pt(t.networkDetails)) : void 0;
2570
2587
  return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
2571
2588
  }
2572
- }, tr = 15e3, nr = 6e5, rr = 3e5, ir = 100, Z = 1, ar = 1e3, or = 3e4, sr = 1e3, cr = {
2589
+ }, rr = 15e3, ir = 6e5, ar = 3e5, or = 100, Z = 1, sr = 1e3, cr = 3e4, lr = 1e3, ur = {
2573
2590
  inline: "PRESENTATION_INLINE",
2574
2591
  fullscreen: "PRESENTATION_FULLSCREEN",
2575
2592
  pip: "PRESENTATION_PIP"
2576
- }, lr = {
2593
+ }, dr = {
2577
2594
  widevine: "KEY_SYSTEM_WIDEVINE",
2578
2595
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2579
2596
  none: "KEY_SYSTEM_NONE"
2580
- }, ur = /* @__PURE__ */ new Set([
2597
+ }, fr = /* @__PURE__ */ new Set([
2581
2598
  "INVALID_URN",
2582
2599
  "NOT_FOUND",
2583
2600
  "GEO_DENIED",
@@ -2588,7 +2605,7 @@ var er = class {
2588
2605
  "FORBIDDEN",
2589
2606
  "RATE_LIMITED",
2590
2607
  "TIMEOUT"
2591
- ]), dr = {
2608
+ ]), pr = {
2592
2609
  idle: "PLAYER_STATE_IDLE",
2593
2610
  waiting: "PLAYER_STATE_WAITING",
2594
2611
  loading: "PLAYER_STATE_LOADING",
@@ -2598,7 +2615,7 @@ var er = class {
2598
2615
  ended: "PLAYER_STATE_ENDED",
2599
2616
  error: "PLAYER_STATE_ERROR"
2600
2617
  };
2601
- function fr(e) {
2618
+ function mr(e) {
2602
2619
  try {
2603
2620
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2604
2621
  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);
@@ -2606,8 +2623,8 @@ function fr(e) {
2606
2623
  return;
2607
2624
  }
2608
2625
  }
2609
- var pr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), mr = /* @__PURE__ */ new Set(), hr = /* @__PURE__ */ new Set(), gr = /* @__PURE__ */ new Set(), _r = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2610
- function vr(e) {
2626
+ var hr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), gr = /* @__PURE__ */ new Set(), _r = /* @__PURE__ */ new Set(), vr = /* @__PURE__ */ new Set(), yr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2627
+ function br(e) {
2611
2628
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2612
2629
  let t;
2613
2630
  try {
@@ -2616,19 +2633,19 @@ function vr(e) {
2616
2633
  } catch {
2617
2634
  return;
2618
2635
  }
2619
- if (mr.has(t) && !hr.has(t)) {
2620
- hr.add(t), _(_r(new URL(t).origin));
2621
- for (let e of gr) e.noteCspBlocked();
2636
+ if (gr.has(t) && !_r.has(t)) {
2637
+ _r.add(t), _(yr(new URL(t).origin));
2638
+ for (let e of vr) e.noteCspBlocked();
2622
2639
  }
2623
2640
  }
2624
- function yr(e, t) {
2641
+ function xr(e, t) {
2625
2642
  return _(t, e), { disabledReason: t };
2626
2643
  }
2627
- function br(e, t, n) {
2628
- if (n) return t && !pr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2644
+ function Sr(e, t, n) {
2645
+ if (n) return t && !hr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2629
2646
  if (t) return { endpoint: t };
2630
- if (t !== void 0) return yr("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
2631
- let r = fr(e);
2647
+ if (t !== void 0) return xr("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).");
2648
+ let r = mr(e);
2632
2649
  if (r) return { endpoint: r };
2633
2650
  let i;
2634
2651
  try {
@@ -2636,9 +2653,9 @@ function br(e, t, n) {
2636
2653
  } catch {
2637
2654
  i = e;
2638
2655
  }
2639
- return yr(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
2656
+ return xr(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).`);
2640
2657
  }
2641
- var xr = class {
2658
+ var Cr = class {
2642
2659
  opts;
2643
2660
  url;
2644
2661
  cspKey;
@@ -2720,8 +2737,8 @@ var xr = class {
2720
2737
  constructor(e) {
2721
2738
  this.opts = {
2722
2739
  ...e,
2723
- heartbeatMs: e.heartbeatMs ?? tr,
2724
- idleMs: e.idleMs ?? nr
2740
+ heartbeatMs: e.heartbeatMs ?? rr,
2741
+ idleMs: e.idleMs ?? ir
2725
2742
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2726
2743
  try {
2727
2744
  let e = new URL(this.url);
@@ -2738,11 +2755,11 @@ var xr = class {
2738
2755
  sdkVersion: this.opts.sdkVersion,
2739
2756
  ...this.opts.environment
2740
2757
  };
2741
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), ar), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && mr.add(this.cspKey), document.addEventListener("securitypolicyviolation", vr), gr.add(this), this.noteCspBlocked(), this.onVisibility());
2758
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), sr), 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 && gr.add(this.cspKey), document.addEventListener("securitypolicyviolation", br), vr.add(this), this.noteCspBlocked(), this.onVisibility());
2742
2759
  }
2743
2760
  checkSuspension(e) {
2744
2761
  if (this.endedFlag || !this.opts.idleMs) return !1;
2745
- let t = Math.max(this.opts.idleMs, rr);
2762
+ let t = Math.max(this.opts.idleMs, ar);
2746
2763
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2747
2764
  }
2748
2765
  syncIdle(e) {
@@ -2763,14 +2780,14 @@ var xr = class {
2763
2780
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
2764
2781
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
2765
2782
  let a = {
2766
- fromState: dr[e] ?? "PLAYER_STATE_UNSPECIFIED",
2767
- toState: dr[t] ?? "PLAYER_STATE_UNSPECIFIED",
2768
- presentation: cr[this.presentation]
2783
+ fromState: pr[e] ?? "PLAYER_STATE_UNSPECIFIED",
2784
+ toState: pr[t] ?? "PLAYER_STATE_UNSPECIFIED",
2785
+ presentation: ur[this.presentation]
2769
2786
  }, o = this.causeOf(e, t, i);
2770
2787
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2771
2788
  }
2772
2789
  seekInduced(e) {
2773
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < sr;
2790
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < lr;
2774
2791
  }
2775
2792
  causeOf(e, t, n) {
2776
2793
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2844,7 +2861,7 @@ var xr = class {
2844
2861
  let r = n ?? "";
2845
2862
  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";
2846
2863
  if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
2847
- if (ur.has(e)) return "ERROR_STAGE_RESOLVE";
2864
+ if (fr.has(e)) return "ERROR_STAGE_RESOLVE";
2848
2865
  let i = t ?? "";
2849
2866
  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";
2850
2867
  }
@@ -2876,7 +2893,7 @@ var xr = class {
2876
2893
  let l = t.droppedFrames ?? 0;
2877
2894
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2878
2895
  let u = t.renditionSwitches ?? 0;
2879
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = dr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2896
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = pr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2880
2897
  let d = this.mutedTotalMs;
2881
2898
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2882
2899
  let f = t.upshifts ?? 0;
@@ -2898,13 +2915,13 @@ var xr = class {
2898
2915
  maybeEmitMediaInfo(e) {
2899
2916
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2900
2917
  let t = {};
2901
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = lr[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2918
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = dr[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);
2902
2919
  let n = JSON.stringify(t);
2903
2920
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2904
2921
  }
2905
2922
  end(e, t) {
2906
2923
  if (this.endedFlag) return;
2907
- this.endedFlag = !0, gr.delete(this);
2924
+ this.endedFlag = !0, vr.delete(this);
2908
2925
  let n = t ?? this.now();
2909
2926
  this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
2910
2927
  let r = this.safeSample();
@@ -2918,7 +2935,7 @@ var xr = class {
2918
2935
  let c = r?.positionMs ?? 0;
2919
2936
  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));
2920
2937
  let l = e !== "END_REASON_ENDED";
2921
- l && this.lastStallMs > 0 && n - this.lastStallMs <= or && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= or && (i.abandonAfterErrorMs = Math.max(Z, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2938
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= cr && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= cr && (i.abandonAfterErrorMs = Math.max(Z, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2922
2939
  let u = r?.decodedFrames ?? this.lastDecoded;
2923
2940
  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");
2924
2941
  }
@@ -2938,13 +2955,13 @@ var xr = class {
2938
2955
  };
2939
2956
  }
2940
2957
  noteCspBlocked() {
2941
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(_r(new URL(this.url).origin)));
2958
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(yr(new URL(this.url).origin)));
2942
2959
  }
2943
2960
  cspBlocked() {
2944
- return !!this.cspKey && hr.has(this.cspKey);
2961
+ return !!this.cspKey && _r.has(this.cspKey);
2945
2962
  }
2946
2963
  enqueue(e) {
2947
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > ir;) {
2964
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > or;) {
2948
2965
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2949
2966
  this.pending.splice(e >= 0 ? e : 0, 1);
2950
2967
  }
@@ -2971,7 +2988,7 @@ var xr = class {
2971
2988
  };
2972
2989
  //#endregion
2973
2990
  //#region src/core/environment.ts
2974
- function Sr() {
2991
+ function wr() {
2975
2992
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2976
2993
  let e;
2977
2994
  try {
@@ -2996,14 +3013,14 @@ function Sr() {
2996
3013
  integration: "INTEGRATION_KIND_IFRAME"
2997
3014
  };
2998
3015
  }
2999
- function Cr() {
3016
+ function Tr() {
3000
3017
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
3001
3018
  let e = navigator.userAgentData, t = e?.platform ?? "";
3002
3019
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
3003
3020
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
3004
3021
  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";
3005
3022
  }
3006
- function wr() {
3023
+ function Er() {
3007
3024
  let e = typeof navigator < "u" ? navigator.connection : void 0;
3008
3025
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
3009
3026
  let t = {
@@ -3022,17 +3039,17 @@ function wr() {
3022
3039
  }
3023
3040
  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;
3024
3041
  }
3025
- function Tr(e) {
3026
- let t = Sr(), n = {
3027
- deviceClass: Cr(),
3042
+ function Dr(e) {
3043
+ let t = wr(), n = {
3044
+ deviceClass: Tr(),
3028
3045
  integration: t.integration,
3029
- ...wr()
3046
+ ...Er()
3030
3047
  };
3031
3048
  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);
3032
3049
  let r = e.getBoundingClientRect?.();
3033
3050
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
3034
3051
  }
3035
- async function Er() {
3052
+ async function Or() {
3036
3053
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
3037
3054
  if (!e?.getHighEntropyValues) return {};
3038
3055
  try {
@@ -3044,7 +3061,7 @@ async function Er() {
3044
3061
  }
3045
3062
  //#endregion
3046
3063
  //#region src/core/version.ts
3047
- var Dr = "2.27.0", Or = {
3064
+ var kr = "2.27.2", Ar = {
3048
3065
  accent: "#E1B600",
3049
3066
  accentText: "#1B1C23",
3050
3067
  background: "#0e0f13",
@@ -3055,7 +3072,7 @@ var Dr = "2.27.0", Or = {
3055
3072
  border: "rgba(255, 255, 255, 0.1)",
3056
3073
  radius: "8px",
3057
3074
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
3058
- }, kr = {
3075
+ }, jr = {
3059
3076
  accent: "--havik-accent",
3060
3077
  accentText: "--havik-accent-text",
3061
3078
  background: "--havik-bg",
@@ -3067,26 +3084,26 @@ var Dr = "2.27.0", Or = {
3067
3084
  radius: "--havik-radius",
3068
3085
  fontFamily: "--havik-font"
3069
3086
  };
3070
- function Ar(e, t) {
3087
+ function Mr(e, t) {
3071
3088
  let n = {
3072
- ...Or,
3089
+ ...Ar,
3073
3090
  ...t
3074
3091
  };
3075
- for (let t of Object.keys(kr)) e.style.setProperty(kr[t], n[t]);
3092
+ for (let t of Object.keys(jr)) e.style.setProperty(jr[t], n[t]);
3076
3093
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
3077
3094
  }
3078
3095
  //#endregion
3079
3096
  //#region src/ui/styles.ts
3080
- var jr = "havik-player-styles", Mr = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Nr = /* @__PURE__ */ new WeakMap();
3081
- function Pr(e = document, t) {
3082
- let n = e.querySelector(`style#${jr}`);
3083
- if (n && (!t || Nr.get(n) === t)) return;
3097
+ var Nr = "havik-player-styles", Pr = "\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", Fr = /* @__PURE__ */ new WeakMap();
3098
+ function Ir(e = document, t) {
3099
+ let n = e.querySelector(`style#${Nr}`);
3100
+ if (n && (!t || Fr.get(n) === t)) return;
3084
3101
  let r = e.createElement("style");
3085
- r.id = jr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Mr, Nr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
3102
+ r.id = Nr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Pr, Fr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
3086
3103
  }
3087
3104
  //#endregion
3088
3105
  //#region src/ui/icons.ts
3089
- var Fr = {
3106
+ var Lr = {
3090
3107
  play: "<path d=\"M8 5v14l11-7z\"/>",
3091
3108
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
3092
3109
  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\"/>",
@@ -3100,11 +3117,11 @@ var Fr = {
3100
3117
  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\"/>"
3101
3118
  };
3102
3119
  function Q(e) {
3103
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Fr[e]}</svg>`;
3120
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Lr[e]}</svg>`;
3104
3121
  }
3105
3122
  //#endregion
3106
3123
  //#region src/ui/controls.ts
3107
- var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
3124
+ var Rr = 3e3, zr = 250, Br = /* @__PURE__ */ new Set([
3108
3125
  "GONE",
3109
3126
  "NOT_FOUND",
3110
3127
  "GEO_DENIED",
@@ -3112,15 +3129,15 @@ var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
3112
3129
  "UNAUTHORIZED",
3113
3130
  "DRM_DEVICE_REVOKED"
3114
3131
  ]);
3115
- function zr(e) {
3132
+ function Vr(e) {
3116
3133
  let t = "This match isn't available in your country";
3117
3134
  return e ? `${t} (${e})` : t;
3118
3135
  }
3119
- var Br = "This device can't play protected video";
3120
- function Vr(e) {
3121
- return new Hr(e);
3136
+ var Hr = "This device can't play protected video";
3137
+ function Ur(e) {
3138
+ return new Wr(e);
3122
3139
  }
3123
- var Hr = class {
3140
+ var Wr = class {
3124
3141
  root;
3125
3142
  video;
3126
3143
  player;
@@ -3169,7 +3186,7 @@ var Hr = class {
3169
3186
  scrubbing = !1;
3170
3187
  offFns = [];
3171
3188
  constructor(e) {
3172
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Ir, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Pr(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
3189
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Rr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Ir(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");
3173
3190
  let t = (e, t, n) => {
3174
3191
  let r = this.doc.createElement(e);
3175
3192
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -3255,7 +3272,7 @@ var Hr = class {
3255
3272
  let t = this.surfaceWasHidden;
3256
3273
  this.tapTimer = setTimeout(() => {
3257
3274
  this.tapTimer = void 0, this.toggleBar(t);
3258
- }, Lr);
3275
+ }, zr);
3259
3276
  }
3260
3277
  toggleBar(e) {
3261
3278
  e ? this.poke() : this.hideIfIdle();
@@ -3282,7 +3299,7 @@ var Hr = class {
3282
3299
  this.renderStatus(t);
3283
3300
  }
3284
3301
  statusMessageFor(e) {
3285
- return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? zr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Br : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3302
+ return e === "ended" ? this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Vr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Hr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3286
3303
  }
3287
3304
  renderStatus(e) {
3288
3305
  let t = this.statusMessageFor(e);
@@ -3297,7 +3314,7 @@ var Hr = class {
3297
3314
  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);
3298
3315
  } else {
3299
3316
  let r = this.doc.createElement("div");
3300
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Rr.has(this.lastError.code)) {
3317
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Br.has(this.lastError.code)) {
3301
3318
  let e = this.doc.createElement("button");
3302
3319
  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);
3303
3320
  }
@@ -3338,7 +3355,7 @@ var Hr = class {
3338
3355
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
3339
3356
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
3340
3357
  }
3341
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ur(this.video.currentTime)} / ${Ur(this.video.duration)}`);
3358
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Gr(this.video.currentTime)} / ${Gr(this.video.duration)}`);
3342
3359
  }
3343
3360
  syncLive() {
3344
3361
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.isGone(), r = this.player.state === "ended" || n, i = !t && !this.streamEnded() && !n;
@@ -3388,17 +3405,17 @@ var Hr = class {
3388
3405
  renderQualityMenu() {
3389
3406
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
3390
3407
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
3391
- for (let n of e) this.menu.append(this.menuItem(Wr(n), t === n.index, () => this.player.setQuality(n.index)));
3408
+ for (let n of e) this.menu.append(this.menuItem(Kr(n), t === n.index, () => this.player.setQuality(n.index)));
3392
3409
  }
3393
3410
  renderAudioMenu() {
3394
3411
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
3395
3412
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
3396
- for (let t of e) this.menu.append(this.menuItem(Gr(t), t.default, () => this.player.setAudioTrack(t.id)));
3413
+ for (let t of e) this.menu.append(this.menuItem(qr(t), t.default, () => this.player.setAudioTrack(t.id)));
3397
3414
  }
3398
3415
  renderCcMenu() {
3399
3416
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
3400
3417
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
3401
- for (let t of e) this.menu.append(this.menuItem(Kr(t), !1, () => this.player.setTextTrack(t.id)));
3418
+ for (let t of e) this.menu.append(this.menuItem(Jr(t), !1, () => this.player.setTextTrack(t.id)));
3402
3419
  }
3403
3420
  onTracksChanged() {
3404
3421
  this.openMenu && this.renderMenu(this.openMenu);
@@ -3503,23 +3520,23 @@ var Hr = class {
3503
3520
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
3504
3521
  }
3505
3522
  };
3506
- function Ur(e) {
3523
+ function Gr(e) {
3507
3524
  (!Number.isFinite(e) || e < 0) && (e = 0);
3508
3525
  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");
3509
3526
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3510
3527
  }
3511
- function Wr(e) {
3528
+ function Kr(e) {
3512
3529
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3513
3530
  }
3514
- function Gr(e) {
3531
+ function qr(e) {
3515
3532
  return e.name || e.lang || `Track ${e.id}`;
3516
3533
  }
3517
- function Kr(e) {
3534
+ function Jr(e) {
3518
3535
  return e.name || e.lang || `Track ${e.id}`;
3519
3536
  }
3520
3537
  //#endregion
3521
3538
  //#region src/managed/index.ts
3522
- var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "keySystemLicenseRequestFailed", ti = /* @__PURE__ */ new Set([
3539
+ var Yr = 6e3, Xr = 45e3, Zr = 2e3, Qr = 3, $r = 5e3, ei = 2e3, ti = 48e4, ni = "keySystemLicenseRequestFailed", ri = /* @__PURE__ */ new Set([
3523
3540
  "GONE",
3524
3541
  "NOT_FOUND",
3525
3542
  "INVALID_URN",
@@ -3527,27 +3544,27 @@ var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "
3527
3544
  "GEO_DENIED",
3528
3545
  "DRM_DEVICE_REVOKED"
3529
3546
  ]);
3530
- function ni(e) {
3531
- return !ti.has(e);
3547
+ function ii(e) {
3548
+ return !ri.has(e);
3532
3549
  }
3533
- function ri(e) {
3550
+ function ai(e) {
3534
3551
  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)})`);
3535
3552
  if (e.env !== void 0) return lt(e.env);
3536
3553
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3537
3554
  return e.baseUrl;
3538
3555
  }
3539
- async function ii(e) {
3556
+ async function oi(e) {
3540
3557
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3541
- let t = ri(e);
3558
+ let t = ai(e);
3542
3559
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3543
3560
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3544
- let r = new ai({
3561
+ let r = new si({
3545
3562
  ...e,
3546
3563
  baseUrl: t
3547
3564
  });
3548
3565
  return await r.start(), r;
3549
3566
  }
3550
- var ai = class {
3567
+ var si = class {
3551
3568
  opts;
3552
3569
  abort = new AbortController();
3553
3570
  listeners = {};
@@ -3647,7 +3664,7 @@ var ai = class {
3647
3664
  setTimeout(() => {
3648
3665
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3649
3666
  phase: i ? "unavailable" : "tooEarly",
3650
- retryInMs: Jr,
3667
+ retryInMs: Xr,
3651
3668
  attempt: 1,
3652
3669
  elapsedMs: 0,
3653
3670
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3686,13 +3703,13 @@ var ai = class {
3686
3703
  !a && !p() && h();
3687
3704
  }, e);
3688
3705
  };
3689
- _(qr), this.armingSub = D({
3706
+ _(Yr), this.armingSub = D({
3690
3707
  eventsBaseUrl: t,
3691
3708
  matchUrn: this.opts.matchUrn,
3692
3709
  credential: this.opts.credential,
3693
- onAlive: () => _(Jr),
3710
+ onAlive: () => _(Xr),
3694
3711
  onState: (e) => {
3695
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Yr);
3712
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Zr);
3696
3713
  },
3697
3714
  onError: () => h()
3698
3715
  });
@@ -3715,7 +3732,7 @@ var ai = class {
3715
3732
  let n = await c(this.opts.credential);
3716
3733
  if (this.destroyed || t !== this.loadGen) return;
3717
3734
  this.setState("loading");
3718
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = gt(this.opts.video, (e) => {
3735
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = vt(this.opts.video, (e) => {
3719
3736
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3720
3737
  });
3721
3738
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3737,19 +3754,19 @@ var ai = class {
3737
3754
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3738
3755
  let i = e.analytics?.sid;
3739
3756
  if (!i) return;
3740
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = br(this.opts.baseUrl, a, e.analytics?.endpoint);
3757
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Sr(this.opts.baseUrl, a, e.analytics?.endpoint);
3741
3758
  if (!o) {
3742
3759
  s && setTimeout(() => {
3743
3760
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3744
3761
  }, 0);
3745
3762
  return;
3746
3763
  }
3747
- let c = this.opts.video, l = new xr({
3764
+ let c = this.opts.video, l = new Cr({
3748
3765
  endpoint: o,
3749
3766
  sid: i,
3750
3767
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3751
- sdkVersion: Dr,
3752
- environment: Tr(c),
3768
+ sdkVersion: kr,
3769
+ environment: Dr(c),
3753
3770
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3754
3771
  onIdle: () => this.onAnalyticsIdle(t),
3755
3772
  onBlocked: (e) => setTimeout(() => {
@@ -3770,7 +3787,7 @@ var ai = class {
3770
3787
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3771
3788
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3772
3789
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3773
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Er().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3790
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Or().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3774
3791
  }
3775
3792
  currentPresentation() {
3776
3793
  let e = this.opts.video;
@@ -3803,9 +3820,9 @@ var ai = class {
3803
3820
  freshLicenseUrl: () => this.refreshLicense()
3804
3821
  }, o = this.opts.engine ?? "auto";
3805
3822
  if (o === "native") return new H(a);
3806
- if (o === "hls") return new er(a);
3807
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && Ot() && B(this.opts.video)) return new H(a);
3808
- if (Wt()) return new er(a);
3823
+ if (o === "hls") return new nr(a);
3824
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && At() && B(this.opts.video)) return new H(a);
3825
+ if (Kt()) return new nr(a);
3809
3826
  if (B(this.opts.video)) return new H(a);
3810
3827
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3811
3828
  }
@@ -3876,7 +3893,7 @@ var ai = class {
3876
3893
  a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
3877
3894
  return;
3878
3895
  }
3879
- i += 1, i >= Xr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`)));
3896
+ i += 1, i >= Qr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`)));
3880
3897
  }
3881
3898
  }
3882
3899
  });
@@ -3893,7 +3910,7 @@ var ai = class {
3893
3910
  }
3894
3911
  if (this.emit("online"), this._state !== "error" || !this._lastError) return;
3895
3912
  let t = this._lastError.code;
3896
- ni(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
3913
+ ii(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
3897
3914
  }));
3898
3915
  }
3899
3916
  watchReturn() {
@@ -3903,7 +3920,7 @@ var ai = class {
3903
3920
  return;
3904
3921
  }
3905
3922
  let e = this.hiddenAtMs;
3906
- this.hiddenAtMs = null, e != null && Date.now() - e >= Zr && this.resyncLiveState();
3923
+ this.hiddenAtMs = null, e != null && Date.now() - e >= $r && this.resyncLiveState();
3907
3924
  }, this.onReturnPageShow = (e) => {
3908
3925
  e.persisted && this.resyncLiveState();
3909
3926
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3935,7 +3952,7 @@ var ai = class {
3935
3952
  scheduleRejoin(e) {
3936
3953
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3937
3954
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3938
- }, Math.random() * Yr));
3955
+ }, Math.random() * Zr));
3939
3956
  }
3940
3957
  cancelRejoin() {
3941
3958
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3959,7 +3976,7 @@ var ai = class {
3959
3976
  }
3960
3977
  t.controls = !1;
3961
3978
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3962
- r && r.insertBefore(n, t), n.appendChild(t), Ar(n, this.opts.theme), this.container = n, this.controlBar = Vr({
3979
+ r && r.insertBefore(n, t), n.appendChild(t), Mr(n, this.opts.theme), this.container = n, this.controlBar = Ur({
3963
3980
  root: n,
3964
3981
  video: t,
3965
3982
  player: this,
@@ -3998,7 +4015,7 @@ var ai = class {
3998
4015
  }
3999
4016
  startStats() {
4000
4017
  this.stopStats();
4001
- let e = Math.max(500, this.opts.statsIntervalMs ?? Qr);
4018
+ let e = Math.max(500, this.opts.statsIntervalMs ?? ei);
4002
4019
  this.statsTimer = setInterval(() => {
4003
4020
  if (!this.engine) return;
4004
4021
  let e = this.engine.getStats();
@@ -4009,14 +4026,14 @@ var ai = class {
4009
4026
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
4010
4027
  }
4011
4028
  isStaleLicenseDenial(e) {
4012
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== ei || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
4029
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== ni || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
4013
4030
  }
4014
4031
  scheduleLicenseRefresh() {
4015
4032
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
4016
4033
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
4017
4034
  document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
4018
4035
  }, document.addEventListener("visibilitychange", this.onRefocus));
4019
- let e = this.opts.licenseRefreshMs ?? $r;
4036
+ let e = this.opts.licenseRefreshMs ?? ti;
4020
4037
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
4021
4038
  }
4022
4039
  stopRefresh() {
@@ -4186,7 +4203,7 @@ function $(e) {
4186
4203
  }
4187
4204
  //#endregion
4188
4205
  //#region src/embed/host.ts
4189
- function oi(e) {
4206
+ function ci(e) {
4190
4207
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
4191
4208
  if (!e.src) throw Error("mountEmbed: opts.src is required");
4192
4209
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -4245,15 +4262,15 @@ function oi(e) {
4245
4262
  }
4246
4263
  //#endregion
4247
4264
  //#region src/embed/page.ts
4248
- var si = /^[A-Za-z0-9:_.-]{1,128}$/;
4249
- function ci(e) {
4265
+ var li = /^[A-Za-z0-9:_.-]{1,128}$/;
4266
+ function ui(e) {
4250
4267
  if (typeof e == "boolean") return e;
4251
4268
  if (typeof e == "object" && e) {
4252
4269
  let t = e.endpoint;
4253
4270
  return typeof t == "string" ? { endpoint: t } : {};
4254
4271
  }
4255
4272
  }
4256
- function li() {
4273
+ function di() {
4257
4274
  let e = window.HAVIK_EMBED_CONFIG;
4258
4275
  if (e) return {
4259
4276
  baseUrl: e.baseUrl ?? "",
@@ -4263,7 +4280,7 @@ function li() {
4263
4280
  autoplay: e.autoplay ?? !0,
4264
4281
  muted: e.muted ?? !0,
4265
4282
  waitForLive: e.waitForLive ?? !0,
4266
- analytics: ci(e.analytics)
4283
+ analytics: ui(e.analytics)
4267
4284
  };
4268
4285
  let t = new URLSearchParams(location.search);
4269
4286
  return {
@@ -4276,9 +4293,9 @@ function li() {
4276
4293
  waitForLive: !0
4277
4294
  };
4278
4295
  }
4279
- async function ui() {
4280
- let e = li();
4281
- fi();
4296
+ async function fi() {
4297
+ let e = di();
4298
+ mi();
4282
4299
  let t = document.createElement("video");
4283
4300
  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);
4284
4301
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -4334,12 +4351,12 @@ async function ui() {
4334
4351
  message: e.message,
4335
4352
  ...e.country === void 0 ? {} : { country: e.country }
4336
4353
  })), e.on("autoplayblocked", () => {
4337
- i({ type: "oddin:autoplayblocked" }), di(t, e);
4354
+ i({ type: "oddin:autoplayblocked" }), pi(t, e);
4338
4355
  });
4339
4356
  }, s = async (r) => {
4340
4357
  a?.destroy(), a = null;
4341
4358
  try {
4342
- let n = await ii({
4359
+ let n = await oi({
4343
4360
  video: t,
4344
4361
  baseUrl: e.baseUrl,
4345
4362
  matchUrn: r,
@@ -4402,7 +4419,7 @@ async function ui() {
4402
4419
  a?.retry();
4403
4420
  break;
4404
4421
  case "oddin:load":
4405
- typeof e.matchUrn == "string" && si.test(e.matchUrn) && s(e.matchUrn);
4422
+ typeof e.matchUrn == "string" && li.test(e.matchUrn) && s(e.matchUrn);
4406
4423
  break;
4407
4424
  case "oddin:destroy": c();
4408
4425
  }
@@ -4414,18 +4431,18 @@ async function ui() {
4414
4431
  protocol: 1
4415
4432
  });
4416
4433
  }
4417
- function di(e, t) {
4434
+ function pi(e, t) {
4418
4435
  if (document.getElementById("havik-tap")) return;
4419
4436
  let n = document.createElement("button");
4420
4437
  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", () => {
4421
4438
  n.remove(), t.play();
4422
4439
  }), document.body.appendChild(n);
4423
4440
  }
4424
- function fi() {
4441
+ function mi() {
4425
4442
  let e = document.createElement("style");
4426
4443
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
4427
4444
  }
4428
4445
  //#endregion
4429
- export { E as LiveStateHttpError, Or as ODDIN_THEME, n as PlaybackError, Ar as applyTheme, lt as baseUrlForEnv, ui as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, ii as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, oi as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4446
+ export { E as LiveStateHttpError, Ar as ODDIN_THEME, n as PlaybackError, Mr as applyTheme, lt as baseUrlForEnv, fi as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, oi as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, ci as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4430
4447
 
4431
4448
  //# sourceMappingURL=index.js.map