@oddin-gg/havik-player 2.16.6 → 2.16.7

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
@@ -174,7 +174,7 @@ function ue(e, t) {
174
174
  t?.addEventListener("abort", a, { once: !0 });
175
175
  });
176
176
  }
177
- async function v(e, t, r) {
177
+ async function de(e, t, r) {
178
178
  let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
179
179
  for (;;) {
180
180
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
@@ -200,21 +200,21 @@ async function v(e, t, r) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/core/resolve.ts
203
- async function y(e) {
203
+ async function v(e) {
204
204
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
205
205
  let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
206
206
  credential: e.credential,
207
207
  signal: e.signal,
208
208
  apiHeaders: e.apiHeaders
209
209
  });
210
- if (!t.ok) throw await de(t);
211
- return me(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await fe(t);
211
+ return he(await t.json(), e.matchUrn);
212
212
  }
213
- function b(e) {
214
- let t = () => y(e);
215
- return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
213
+ function y(e) {
214
+ let t = () => v(e);
215
+ return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
216
216
  }
217
- async function de(e) {
217
+ async function fe(e) {
218
218
  let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
219
219
  try {
220
220
  let t = await e.json();
@@ -230,7 +230,7 @@ async function de(e) {
230
230
  liveStartsAtMs: s
231
231
  });
232
232
  }
233
- var fe = /* @__PURE__ */ new Set([
233
+ var pe = /* @__PURE__ */ new Set([
234
234
  "matchUrn",
235
235
  "protocol",
236
236
  "drmEnabled",
@@ -241,7 +241,7 @@ var fe = /* @__PURE__ */ new Set([
241
241
  "expiresAt",
242
242
  "analytics"
243
243
  ]);
244
- function x(e, t) {
244
+ function b(e, t) {
245
245
  let r;
246
246
  try {
247
247
  r = new URL(t);
@@ -251,7 +251,7 @@ function x(e, t) {
251
251
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
252
252
  return t;
253
253
  }
254
- function pe(e) {
254
+ function me(e) {
255
255
  if (e !== void 0) {
256
256
  if (typeof e == "string" && !e.endsWith("/")) try {
257
257
  let t = new URL(e);
@@ -260,41 +260,41 @@ function pe(e) {
260
260
  g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
261
  }
262
262
  }
263
- function me(e, t) {
263
+ function he(e, t) {
264
264
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
265
265
  let r = e.drmEnabled ?? !!e.drm, i = {
266
266
  matchUrn: e.matchUrn ?? t,
267
267
  protocol: "hls",
268
268
  drmEnabled: r,
269
- manifestUrl: x("manifestUrl", e.manifestUrl),
269
+ manifestUrl: b("manifestUrl", e.manifestUrl),
270
270
  serverTime: e.serverTime ?? ""
271
271
  };
272
272
  if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
273
273
  i.analytics = { sid: e.analytics.sid };
274
- let t = pe(e.analytics.endpoint);
274
+ let t = me(e.analytics.endpoint);
275
275
  t && (i.analytics.endpoint = t);
276
276
  }
277
277
  if (r && e.drm) {
278
278
  let t = {};
279
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
- certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
279
+ e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
+ licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
+ certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
282
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
283
283
  }
284
284
  let a = {};
285
- for (let [t, n] of Object.entries(e)) fe.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
286
286
  return Object.keys(a).length > 0 && (i.extensions = a), i;
287
287
  }
288
288
  //#endregion
289
289
  //#region src/core/fullscreen.ts
290
- function he(e) {
290
+ function ge(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function ge(e) {
293
+ function x(e) {
294
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
295
295
  }
296
296
  function S(e, t) {
297
- let n = ge(he(e));
297
+ let n = x(ge(e));
298
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
299
299
  }
300
300
  async function C(e, t) {
@@ -310,7 +310,7 @@ async function w(e, t) {
310
310
  n.webkitExitFullscreen?.();
311
311
  return;
312
312
  }
313
- let r = he(e), i = ge(r);
313
+ let r = ge(e), i = x(r);
314
314
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
315
315
  }
316
316
  //#endregion
@@ -671,14 +671,14 @@ function I(e) {
671
671
  function L(e) {
672
672
  return (e ?? "").trim().toLowerCase();
673
673
  }
674
- var R = {
674
+ var je = {
675
675
  hevc: "hvc1.1.6.L93.90",
676
676
  dv: "dvh1.05.06",
677
677
  av1: "av01.0.05M.08",
678
678
  vp9: "vp09.00.10.08"
679
- }, z = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map();
680
- function je(e) {
681
- let t = L(e), n = z.get(t);
679
+ }, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
680
+ function Ne(e) {
681
+ let t = L(e), n = Me.get(t);
682
682
  if (n) return n;
683
683
  let r = {
684
684
  initDataTypes: ["cenc"],
@@ -696,23 +696,23 @@ function je(e) {
696
696
  } catch {
697
697
  return !1;
698
698
  }
699
- })().then((e) => (B.set(t, e), e));
700
- return z.set(t, i), i;
699
+ })().then((e) => (R.set(t, e), e));
700
+ return Me.set(t, i), i;
701
701
  }
702
- function Me() {
703
- if (j()) for (let e of Object.values(R)) je(e);
702
+ function Pe() {
703
+ if (j()) for (let e of Object.values(je)) Ne(e);
704
704
  }
705
- function Ne(e) {
705
+ function Fe(e) {
706
706
  let t = I(e);
707
- if (t) return t === "avc" ? !0 : B.get(L(e)) ?? B.get(L(R[t]));
707
+ if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
708
708
  }
709
709
  //#endregion
710
710
  //#region src/core/drm/support.ts
711
- var Pe = 5e3, Fe = "video/mp4; codecs=\"avc1.42E01E\"", Ie = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
711
+ var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
712
712
  widevine: ["com.widevine.alpha"],
713
713
  fairplay: ["com.apple.fps"]
714
714
  };
715
- function Re(e) {
715
+ function Be(e) {
716
716
  return e === "fairplay" ? [{
717
717
  initDataTypes: [
718
718
  "sinf",
@@ -720,30 +720,30 @@ function Re(e) {
720
720
  "cenc"
721
721
  ],
722
722
  videoCapabilities: [{
723
- contentType: Fe,
723
+ contentType: Le,
724
724
  robustness: "",
725
725
  encryptionScheme: "cbcs"
726
726
  }],
727
727
  audioCapabilities: [{
728
- contentType: Ie,
728
+ contentType: Re,
729
729
  robustness: "",
730
730
  encryptionScheme: "cbcs"
731
731
  }]
732
732
  }] : N("com.widevine.alpha", [{
733
733
  initDataTypes: ["cenc"],
734
734
  videoCapabilities: [{
735
- contentType: Fe,
735
+ contentType: Le,
736
736
  robustness: F.video,
737
737
  encryptionScheme: F.scheme
738
738
  }],
739
739
  audioCapabilities: [{
740
- contentType: Ie,
740
+ contentType: Re,
741
741
  robustness: F.audio,
742
742
  encryptionScheme: F.scheme
743
743
  }]
744
744
  }]);
745
745
  }
746
- function ze(e, t) {
746
+ function Ve(e, t) {
747
747
  return new Promise((n, r) => {
748
748
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
749
749
  e.then((e) => {
@@ -753,8 +753,8 @@ function ze(e, t) {
753
753
  });
754
754
  });
755
755
  }
756
- async function Be(e = {}) {
757
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Pe, r = {};
756
+ async function He(e = {}) {
757
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
758
758
  if (typeof window < "u" && window.isSecureContext === !1) return {
759
759
  verdict: "insecure-context",
760
760
  detail: r
@@ -766,7 +766,7 @@ async function Be(e = {}) {
766
766
  };
767
767
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
768
768
  for (let e of t) {
769
- let t = Le[e];
769
+ let t = ze[e];
770
770
  if (!t) {
771
771
  r[e] = "unknown system";
772
772
  continue;
@@ -777,7 +777,7 @@ async function Be(e = {}) {
777
777
  break;
778
778
  }
779
779
  try {
780
- return await ze((await ze(i(n, Re(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
780
+ return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
781
781
  verdict: "supported",
782
782
  system: e,
783
783
  detail: r
@@ -801,49 +801,49 @@ async function Be(e = {}) {
801
801
  }
802
802
  //#endregion
803
803
  //#region src/core/manifest.ts
804
- var Ve = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
- function He(e) {
806
- return Ve.test(e);
804
+ var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function We(e) {
806
+ return Ue.test(e);
807
807
  }
808
808
  //#endregion
809
809
  //#region src/core/env.ts
810
- var Ue = {
810
+ var Ge = {
811
811
  integration: "https://feed-dev.oddin-video.gg",
812
812
  production: "https://feed.oddin-video.gg"
813
813
  };
814
- function We(e) {
815
- let t = Object.prototype.hasOwnProperty.call(Ue, e) ? Ue[e] : void 0;
814
+ function Ke(e) {
815
+ let t = Object.prototype.hasOwnProperty.call(Ge, e) ? Ge[e] : void 0;
816
816
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
817
817
  return t;
818
818
  }
819
819
  //#endregion
820
820
  //#region src/core/stats.ts
821
- var Ge = { droppedFrames: 0 };
822
- function Ke(e) {
821
+ var qe = { droppedFrames: 0 };
822
+ function z(e) {
823
823
  try {
824
824
  return new URL(e).host;
825
825
  } catch {
826
826
  return "";
827
827
  }
828
828
  }
829
- var qe = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
- function Je(e) {
829
+ var Je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
+ function Ye(e) {
831
831
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
832
832
  let t = "", n = -1, r = performance.getEntriesByType("resource");
833
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || qe.test(i.name)) && i.startTime >= n) {
834
- let e = Ke(i.name);
833
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
834
+ let e = z(i.name);
835
835
  e && (t = e, n = i.startTime);
836
836
  }
837
837
  return t;
838
838
  }
839
- function V(e) {
839
+ function B(e) {
840
840
  let t = e.getVideoPlaybackQuality?.();
841
841
  return {
842
842
  dropped: t?.droppedVideoFrames ?? 0,
843
843
  totalFrames: t?.totalVideoFrames ?? 0
844
844
  };
845
845
  }
846
- var Ye = class {
846
+ var V = class {
847
847
  video;
848
848
  baseFrames = 0;
849
849
  baseDropped = 0;
@@ -853,7 +853,7 @@ var Ye = class {
853
853
  this.video = e;
854
854
  }
855
855
  read() {
856
- let e = V(this.video);
856
+ let e = B(this.video);
857
857
  return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
858
858
  dropped: this.baseDropped + e.dropped,
859
859
  totalFrames: this.baseFrames + e.totalFrames
@@ -927,7 +927,7 @@ var G = class {
927
927
  frameCounter;
928
928
  detachFrames = null;
929
929
  constructor(e) {
930
- this.deps = e, this.frameCounter = new Ye(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
930
+ this.deps = e, this.frameCounter = new V(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
931
931
  }
932
932
  async load() {
933
933
  this.detachFrames ??= this.frameCounter.attach();
@@ -1069,7 +1069,7 @@ var G = class {
1069
1069
  droppedFrames: t.dropped,
1070
1070
  decodedFrames: t.totalFrames
1071
1071
  };
1072
- if (this.cdnHost ||= Je(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1072
+ if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1073
1073
  if (n.isLive = !0, e.seekable.length > 0) {
1074
1074
  let t = e.seekable.end(e.seekable.length - 1);
1075
1075
  n.atLiveEdge = e.currentTime >= t - 2;
@@ -1320,21 +1320,21 @@ function ft(e, t) {
1320
1320
  function pt() {
1321
1321
  return e.isSupported();
1322
1322
  }
1323
- var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt = 6e3, St = .5, Ct = 3, wt = .5, Tt = 1.1, Et = .25, Dt = 5e3, Ot = 4e3, kt = 2, At = 5, jt = 2, Mt = 2, Nt = 4, Pt = 4, Ft = 2e3, It = 3e4, Lt = .2, Rt = 30, zt = 2, Bt = 2, Vt = 9, Ht = .5, Ut = 64;
1324
- function Wt(e) {
1323
+ var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt = .02, St = 6e3, Ct = .5, wt = 3, Tt = .5, Et = 1.1, Dt = .25, Ot = 5e3, kt = 4e3, At = 2, jt = 5, Mt = 2, Nt = 2, Pt = 4, Ft = 4, It = 2e3, Lt = 3e4, Rt = .2, zt = 30, Bt = 2, Vt = 2, Ht = 9, Ut = .5, Wt = 64;
1324
+ function Gt(e) {
1325
1325
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1326
1326
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1327
1327
  return;
1328
1328
  }
1329
- e.liveSyncDuration ??= Bt;
1330
- let t = Math.max(12, e.liveSyncDuration + Vt);
1331
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Gt(e, e.liveSyncDuration);
1329
+ e.liveSyncDuration ??= Vt;
1330
+ let t = Math.max(12, e.liveSyncDuration + Ht);
1331
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Kt(e, e.liveSyncDuration);
1332
1332
  }
1333
- function Gt(e, t) {
1333
+ function Kt(e, t) {
1334
1334
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1335
1335
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1336
1336
  }
1337
- var Kt = class {
1337
+ var qt = class {
1338
1338
  name = "hls";
1339
1339
  hls = null;
1340
1340
  deps;
@@ -1414,7 +1414,7 @@ var Kt = class {
1414
1414
  frameCounter;
1415
1415
  detachFrames = null;
1416
1416
  constructor(e) {
1417
- this.deps = e, this.frameCounter = new Ye(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1417
+ this.deps = e, this.frameCounter = new V(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1418
1418
  }
1419
1419
  async load() {
1420
1420
  this.detachFrames ??= this.frameCounter.attach();
@@ -1427,7 +1427,7 @@ var Kt = class {
1427
1427
  });
1428
1428
  return;
1429
1429
  }
1430
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Me()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1430
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1431
1431
  let e = this.hls;
1432
1432
  if (document.visibilityState !== "visible" || !e) return;
1433
1433
  let t = e.liveSyncPosition;
@@ -1450,7 +1450,7 @@ var Kt = class {
1450
1450
  }
1451
1451
  this.loadSuspended = !0;
1452
1452
  }
1453
- }, Dt));
1453
+ }, Ot));
1454
1454
  }
1455
1455
  resumeLoading() {
1456
1456
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1482,7 +1482,22 @@ var Kt = class {
1482
1482
  let t = e.liveSyncPosition;
1483
1483
  if (typeof t != "number" || !Number.isFinite(t)) return;
1484
1484
  let { video: n } = this.deps;
1485
- n.currentTime <= t + Ht || (n.currentTime = t);
1485
+ n.currentTime <= t + Ut || (n.currentTime = t);
1486
+ }
1487
+ reanchorPartTimeline(e, t) {
1488
+ let { frag: n, part: r } = t;
1489
+ if (!r || r.index !== 0 || n.type !== "main" || typeof n.sn != "number") return;
1490
+ let i = e.levels[n.level]?.details;
1491
+ if (!i?.live) return;
1492
+ let a = r.elementaryStreams.video ?? r.elementaryStreams.audiovideo ?? r.elementaryStreams.audio;
1493
+ if (!a) return;
1494
+ let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1495
+ if (!s) return;
1496
+ let c = a.startPTS - s.start;
1497
+ if (!(!Number.isFinite(c) || Math.abs(c) < xt)) {
1498
+ for (let e of i.fragments) e && e.setStart(e.start + c);
1499
+ 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})`);
1500
+ }
1486
1501
  }
1487
1502
  startHls() {
1488
1503
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1540,9 +1555,9 @@ var Kt = class {
1540
1555
  }), t = lt(e);
1541
1556
  t && (this.prefetch = e, d.fLoader = t);
1542
1557
  }
1543
- Wt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1558
+ Gt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1544
1559
  let f = new e(d);
1545
- if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1560
+ if (this.hls = f, f.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(f, t)), f.on(e.Events.MANIFEST_PARSED, () => {
1546
1561
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1547
1562
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1548
1563
  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(() => {
@@ -1555,10 +1570,10 @@ var Kt = class {
1555
1570
  let n = t?.frag?.stats, r = n?.loaded;
1556
1571
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1557
1572
  let i = n?.loading;
1558
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ut && this.requestTimesMs.shift());
1573
+ i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Wt && this.requestTimesMs.shift());
1559
1574
  let a = t?.frag?.url;
1560
1575
  if (a) {
1561
- let e = Ke(a);
1576
+ let e = z(a);
1562
1577
  e && (this.cdnHost = e);
1563
1578
  }
1564
1579
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1644,7 +1659,7 @@ var Kt = class {
1644
1659
  return;
1645
1660
  }
1646
1661
  this.capTimer && clearTimeout(this.capTimer);
1647
- let t = e > this.sizeCapLevel ? Ft : It;
1662
+ let t = e > this.sizeCapLevel ? It : Lt;
1648
1663
  this.capTimer = setTimeout(() => {
1649
1664
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1650
1665
  }, t);
@@ -1654,9 +1669,9 @@ var Kt = class {
1654
1669
  this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
1655
1670
  }
1656
1671
  dropLevelsWidevineCannotPlay(e) {
1657
- this.removeLevelsWhere(e, (e) => Ne(e) !== !0);
1672
+ this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1658
1673
  let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1659
- for (let n of t) je(n).then((t) => {
1674
+ for (let n of t) Ne(n).then((t) => {
1660
1675
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1661
1676
  });
1662
1677
  }
@@ -1667,7 +1682,7 @@ var Kt = class {
1667
1682
  a && I(a) && t(a) && (r.push(n), i.add(a));
1668
1683
  }), !r.length) return !1;
1669
1684
  let a = [...i].join(", ");
1670
- if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Ne(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1685
+ if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1671
1686
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1672
1687
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1673
1688
  }
@@ -1765,7 +1780,7 @@ var Kt = class {
1765
1780
  return;
1766
1781
  }
1767
1782
  let e = Date.now() - this.lastAdvanceMs;
1768
- !this.chaseSuspended && e > xt && this.suspendChasing(), e > yt && this.emitEnded("stalled");
1783
+ !this.chaseSuspended && e > St && this.suspendChasing(), e > yt && this.emitEnded("stalled");
1769
1784
  }
1770
1785
  resetStarvationWindow() {
1771
1786
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1780,7 +1795,7 @@ var Kt = class {
1780
1795
  this.resetStarvationWindow();
1781
1796
  return;
1782
1797
  }
1783
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < xt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Ot, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = V(t), c = o - s, l = c !== this.starvedFrames;
1798
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < St, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > kt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1784
1799
  if (this.starvedFrames = c, !a || l) {
1785
1800
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1786
1801
  return;
@@ -1789,12 +1804,12 @@ var Kt = class {
1789
1804
  this.resetStarvationWindow();
1790
1805
  return;
1791
1806
  }
1792
- 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 > Nt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= jt && (this.clearKick(), this.starvationRebuilds < Mt)) {
1807
+ 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 > Pt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Mt && (this.clearKick(), this.starvationRebuilds < Nt)) {
1793
1808
  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");
1794
1809
  return;
1795
1810
  }
1796
- let u = i && this.starvedTicks >= kt, d = !i && this.deadTicks >= Nt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Pt;
1797
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= At))) {
1811
+ let u = i && this.starvedTicks >= At, d = !i && this.deadTicks >= Pt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Ft;
1812
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= jt))) {
1798
1813
  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");
1799
1814
  try {
1800
1815
  e.stopLoad(), e.startLoad(-1);
@@ -1809,7 +1824,7 @@ var Kt = class {
1809
1824
  let t = e.latency, n = e.targetLatency;
1810
1825
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1811
1826
  let r = t - n;
1812
- !this.catchUpEngaged && r > St ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= St && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1827
+ !this.catchUpEngaged && r > Ct ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Ct && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1813
1828
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1814
1829
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1815
1830
  }
@@ -1830,16 +1845,16 @@ var Kt = class {
1830
1845
  this.resetFrameDropWindow();
1831
1846
  return;
1832
1847
  }
1833
- let { totalFrames: n, dropped: r } = V(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1834
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Rt || o < 0) {
1848
+ let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1849
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < zt || o < 0) {
1835
1850
  this.fpsBadTicks = 0;
1836
1851
  return;
1837
1852
  }
1838
- if (o <= Lt * a) {
1853
+ if (o <= Rt * a) {
1839
1854
  this.fpsBadTicks = 0;
1840
1855
  return;
1841
1856
  }
1842
- if (this.fpsBadTicks += 1, this.fpsBadTicks < zt) return;
1857
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Bt) return;
1843
1858
  this.fpsBadTicks = 0;
1844
1859
  let s = e.levels, c = s[e.currentLevel];
1845
1860
  if (!c) return;
@@ -1856,20 +1871,20 @@ var Kt = class {
1856
1871
  return;
1857
1872
  }
1858
1873
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1859
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Tt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1874
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Et, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1860
1875
  this.resetChaseWindow();
1861
1876
  return;
1862
1877
  }
1863
- if (this.chaseLatency < 0 || this.chaseLatency - n >= wt) {
1878
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= Tt) {
1864
1879
  this.chaseLatency = n, this.chaseTicks = 0;
1865
1880
  return;
1866
1881
  }
1867
- if (this.chaseTicks += 1, this.chaseTicks < Ct) return;
1882
+ if (this.chaseTicks += 1, this.chaseTicks < wt) return;
1868
1883
  this.resetChaseWindow();
1869
1884
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1870
1885
  if (!(a > 1)) return;
1871
1886
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1872
- s < o + Et || (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);
1887
+ s < o + Dt || (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);
1873
1888
  }
1874
1889
  suspendChasing() {
1875
1890
  let e = this.hls;
@@ -1987,19 +2002,19 @@ var Kt = class {
1987
2002
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1988
2003
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1989
2004
  }
1990
- }, qt = 15e3, Jt = 6e5, Yt = 3e5, Xt = 100, q = 1, Zt = 1e3, Qt = 3e4, $t = 1e3, en = {
2005
+ }, Jt = 15e3, Yt = 6e5, Xt = 3e5, Zt = 100, q = 1, Qt = 1e3, $t = 3e4, en = 1e3, tn = {
1991
2006
  inline: "PRESENTATION_INLINE",
1992
2007
  fullscreen: "PRESENTATION_FULLSCREEN",
1993
2008
  pip: "PRESENTATION_PIP"
1994
- }, tn = {
2009
+ }, nn = {
1995
2010
  widevine: "KEY_SYSTEM_WIDEVINE",
1996
2011
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1997
2012
  none: "KEY_SYSTEM_NONE"
1998
2013
  };
1999
- function nn(e, t) {
2014
+ function rn(e, t) {
2000
2015
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
2001
2016
  }
2002
- var rn = /* @__PURE__ */ new Set([
2017
+ var an = /* @__PURE__ */ new Set([
2003
2018
  "INVALID_URN",
2004
2019
  "NOT_FOUND",
2005
2020
  "GONE",
@@ -2019,7 +2034,7 @@ var rn = /* @__PURE__ */ new Set([
2019
2034
  ended: "PLAYER_STATE_ENDED",
2020
2035
  error: "PLAYER_STATE_ERROR"
2021
2036
  };
2022
- function an(e) {
2037
+ function on(e) {
2023
2038
  try {
2024
2039
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2025
2040
  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);
@@ -2027,8 +2042,8 @@ function an(e) {
2027
2042
  return;
2028
2043
  }
2029
2044
  }
2030
- var on = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), sn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), cn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2031
- function ln(e) {
2045
+ var sn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), cn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), ln = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2046
+ function un(e) {
2032
2047
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2033
2048
  let t;
2034
2049
  try {
@@ -2037,19 +2052,19 @@ function ln(e) {
2037
2052
  } catch {
2038
2053
  return;
2039
2054
  }
2040
- if (sn.has(t) && !Y.has(t)) {
2041
- Y.add(t), g(cn(new URL(t).origin));
2055
+ if (cn.has(t) && !Y.has(t)) {
2056
+ Y.add(t), g(ln(new URL(t).origin));
2042
2057
  for (let e of X) e.noteCspBlocked();
2043
2058
  }
2044
2059
  }
2045
- function un(e, t) {
2060
+ function dn(e, t) {
2046
2061
  return g(t, e), { disabledReason: t };
2047
2062
  }
2048
- function dn(e, t, n) {
2049
- if (n) return t && !on(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2063
+ function fn(e, t, n) {
2064
+ if (n) return t && !sn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2050
2065
  if (t) return { endpoint: t };
2051
- if (t !== void 0) return un("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).");
2052
- let r = an(e);
2066
+ if (t !== void 0) return dn("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).");
2067
+ let r = on(e);
2053
2068
  if (r) return { endpoint: r };
2054
2069
  let i;
2055
2070
  try {
@@ -2057,9 +2072,9 @@ function dn(e, t, n) {
2057
2072
  } catch {
2058
2073
  i = e;
2059
2074
  }
2060
- return un(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).`);
2075
+ return dn(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).`);
2061
2076
  }
2062
- var fn = class {
2077
+ var pn = class {
2063
2078
  opts;
2064
2079
  url;
2065
2080
  cspKey;
@@ -2141,8 +2156,8 @@ var fn = class {
2141
2156
  constructor(e) {
2142
2157
  this.opts = {
2143
2158
  ...e,
2144
- heartbeatMs: e.heartbeatMs ?? qt,
2145
- idleMs: e.idleMs ?? Jt
2159
+ heartbeatMs: e.heartbeatMs ?? Jt,
2160
+ idleMs: e.idleMs ?? Yt
2146
2161
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2147
2162
  try {
2148
2163
  let e = new URL(this.url);
@@ -2159,11 +2174,11 @@ var fn = class {
2159
2174
  sdkVersion: this.opts.sdkVersion,
2160
2175
  ...this.opts.environment
2161
2176
  };
2162
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Zt), 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 && sn.add(this.cspKey), document.addEventListener("securitypolicyviolation", ln), X.add(this), this.noteCspBlocked(), this.onVisibility());
2177
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Qt), 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 && cn.add(this.cspKey), document.addEventListener("securitypolicyviolation", un), X.add(this), this.noteCspBlocked(), this.onVisibility());
2163
2178
  }
2164
2179
  checkSuspension(e) {
2165
2180
  if (this.endedFlag || !this.opts.idleMs) return !1;
2166
- let t = Math.max(this.opts.idleMs, Yt);
2181
+ let t = Math.max(this.opts.idleMs, Xt);
2167
2182
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2168
2183
  }
2169
2184
  syncIdle(e) {
@@ -2186,12 +2201,12 @@ var fn = class {
2186
2201
  let a = {
2187
2202
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2188
2203
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2189
- presentation: en[this.presentation]
2204
+ presentation: tn[this.presentation]
2190
2205
  }, o = this.causeOf(e, t, i);
2191
2206
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2192
2207
  }
2193
2208
  seekInduced(e) {
2194
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < $t;
2209
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < en;
2195
2210
  }
2196
2211
  causeOf(e, t, n) {
2197
2212
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2265,7 +2280,7 @@ var fn = class {
2265
2280
  let r = n ?? "";
2266
2281
  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";
2267
2282
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2268
- if (rn.has(e)) return "ERROR_STAGE_RESOLVE";
2283
+ if (an.has(e)) return "ERROR_STAGE_RESOLVE";
2269
2284
  let i = t ?? "";
2270
2285
  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";
2271
2286
  }
@@ -2312,14 +2327,14 @@ var fn = class {
2312
2327
  if (this.lastRequestCount = g, _ > 0) {
2313
2328
  o.requestCountDelta = _;
2314
2329
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2315
- n.length > 0 && (o.requestTimeP50Ms = nn(n, 50), o.requestTimeP95Ms = nn(n, 95));
2330
+ n.length > 0 && (o.requestTimeP50Ms = rn(n, 50), o.requestTimeP95Ms = rn(n, 95));
2316
2331
  }
2317
2332
  typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
2318
2333
  }
2319
2334
  maybeEmitMediaInfo(e) {
2320
2335
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2321
2336
  let t = {};
2322
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = tn[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);
2337
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = nn[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);
2323
2338
  let n = JSON.stringify(t);
2324
2339
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2325
2340
  }
@@ -2339,7 +2354,7 @@ var fn = class {
2339
2354
  let c = r?.positionMs ?? 0;
2340
2355
  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));
2341
2356
  let l = e !== "END_REASON_ENDED";
2342
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Qt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Qt && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2357
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= $t && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= $t && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2343
2358
  let u = r?.decodedFrames ?? this.lastDecoded;
2344
2359
  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");
2345
2360
  }
@@ -2359,13 +2374,13 @@ var fn = class {
2359
2374
  };
2360
2375
  }
2361
2376
  noteCspBlocked() {
2362
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(cn(new URL(this.url).origin)));
2377
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(ln(new URL(this.url).origin)));
2363
2378
  }
2364
2379
  cspBlocked() {
2365
2380
  return !!this.cspKey && Y.has(this.cspKey);
2366
2381
  }
2367
2382
  enqueue(e) {
2368
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Xt;) {
2383
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Zt;) {
2369
2384
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2370
2385
  this.pending.splice(e >= 0 ? e : 0, 1);
2371
2386
  }
@@ -2392,7 +2407,7 @@ var fn = class {
2392
2407
  };
2393
2408
  //#endregion
2394
2409
  //#region src/core/environment.ts
2395
- function pn() {
2410
+ function mn() {
2396
2411
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2397
2412
  let e;
2398
2413
  try {
@@ -2417,14 +2432,14 @@ function pn() {
2417
2432
  integration: "INTEGRATION_KIND_IFRAME"
2418
2433
  };
2419
2434
  }
2420
- function mn() {
2435
+ function hn() {
2421
2436
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2422
2437
  let e = navigator.userAgentData, t = e?.platform ?? "";
2423
2438
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2424
2439
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2425
2440
  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";
2426
2441
  }
2427
- function hn() {
2442
+ function gn() {
2428
2443
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2429
2444
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2430
2445
  let t = {
@@ -2443,17 +2458,17 @@ function hn() {
2443
2458
  }
2444
2459
  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;
2445
2460
  }
2446
- function gn(e) {
2447
- let t = pn(), n = {
2448
- deviceClass: mn(),
2461
+ function _n(e) {
2462
+ let t = mn(), n = {
2463
+ deviceClass: hn(),
2449
2464
  integration: t.integration,
2450
- ...hn()
2465
+ ...gn()
2451
2466
  };
2452
2467
  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);
2453
2468
  let r = e.getBoundingClientRect?.();
2454
2469
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2455
2470
  }
2456
- async function _n() {
2471
+ async function vn() {
2457
2472
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2458
2473
  if (!e?.getHighEntropyValues) return {};
2459
2474
  try {
@@ -2465,7 +2480,7 @@ async function _n() {
2465
2480
  }
2466
2481
  //#endregion
2467
2482
  //#region src/core/version.ts
2468
- var vn = "2.16.6", yn = {
2483
+ var yn = "2.16.7", bn = {
2469
2484
  accent: "#E1B600",
2470
2485
  accentText: "#1B1C23",
2471
2486
  background: "#0e0f13",
@@ -2476,7 +2491,7 @@ var vn = "2.16.6", yn = {
2476
2491
  border: "rgba(255, 255, 255, 0.1)",
2477
2492
  radius: "8px",
2478
2493
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2479
- }, bn = {
2494
+ }, xn = {
2480
2495
  accent: "--havik-accent",
2481
2496
  accentText: "--havik-accent-text",
2482
2497
  background: "--havik-bg",
@@ -2488,26 +2503,26 @@ var vn = "2.16.6", yn = {
2488
2503
  radius: "--havik-radius",
2489
2504
  fontFamily: "--havik-font"
2490
2505
  };
2491
- function xn(e, t) {
2506
+ function Sn(e, t) {
2492
2507
  let n = {
2493
- ...yn,
2508
+ ...bn,
2494
2509
  ...t
2495
2510
  };
2496
- for (let t of Object.keys(bn)) e.style.setProperty(bn[t], n[t]);
2511
+ for (let t of Object.keys(xn)) e.style.setProperty(xn[t], n[t]);
2497
2512
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2498
2513
  }
2499
2514
  //#endregion
2500
2515
  //#region src/ui/styles.ts
2501
- var Sn = "havik-player-styles", Cn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2502
- function wn(e = document, t) {
2503
- let n = e.querySelector(`style#${Sn}`);
2516
+ var Cn = "havik-player-styles", wn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2517
+ function Tn(e = document, t) {
2518
+ let n = e.querySelector(`style#${Cn}`);
2504
2519
  if (n && (!t || Z.get(n) === t)) return;
2505
2520
  let r = e.createElement("style");
2506
- r.id = Sn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Cn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2521
+ r.id = Cn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = wn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2507
2522
  }
2508
2523
  //#endregion
2509
2524
  //#region src/ui/icons.ts
2510
- var Tn = {
2525
+ var En = {
2511
2526
  play: "<path d=\"M8 5v14l11-7z\"/>",
2512
2527
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2513
2528
  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\"/>",
@@ -2521,20 +2536,20 @@ var Tn = {
2521
2536
  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\"/>"
2522
2537
  };
2523
2538
  function Q(e) {
2524
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Tn[e]}</svg>`;
2539
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${En[e]}</svg>`;
2525
2540
  }
2526
2541
  //#endregion
2527
2542
  //#region src/ui/controls.ts
2528
- var En = 3e3, Dn = 250, On = /* @__PURE__ */ new Set([
2543
+ var Dn = 3e3, On = 250, kn = /* @__PURE__ */ new Set([
2529
2544
  "GONE",
2530
2545
  "NOT_FOUND",
2531
2546
  "INVALID_URN",
2532
2547
  "UNAUTHORIZED"
2533
2548
  ]);
2534
- function kn(e) {
2535
- return new An(e);
2549
+ function An(e) {
2550
+ return new jn(e);
2536
2551
  }
2537
- var An = class {
2552
+ var jn = class {
2538
2553
  root;
2539
2554
  video;
2540
2555
  player;
@@ -2580,7 +2595,7 @@ var An = class {
2580
2595
  scrubbing = !1;
2581
2596
  offFns = [];
2582
2597
  constructor(e) {
2583
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? En, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, wn(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");
2598
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Dn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Tn(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");
2584
2599
  let t = (e, t, n) => {
2585
2600
  let r = this.doc.createElement(e);
2586
2601
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2666,7 +2681,7 @@ var An = class {
2666
2681
  let t = this.surfaceWasHidden;
2667
2682
  this.tapTimer = setTimeout(() => {
2668
2683
  this.tapTimer = void 0, this.toggleBar(t);
2669
- }, Dn);
2684
+ }, On);
2670
2685
  }
2671
2686
  toggleBar(e) {
2672
2687
  e ? this.poke() : this.hideIfIdle();
@@ -2701,7 +2716,7 @@ var An = class {
2701
2716
  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);
2702
2717
  } else {
2703
2718
  let r = this.doc.createElement("div");
2704
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !On.has(this.lastError.code)) {
2719
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !kn.has(this.lastError.code)) {
2705
2720
  let e = this.doc.createElement("button");
2706
2721
  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);
2707
2722
  }
@@ -2742,7 +2757,7 @@ var An = class {
2742
2757
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2743
2758
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2744
2759
  }
2745
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${jn(this.video.currentTime)} / ${jn(this.video.duration)}`);
2760
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Mn(this.video.currentTime)} / ${Mn(this.video.duration)}`);
2746
2761
  }
2747
2762
  syncLive() {
2748
2763
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2792,17 +2807,17 @@ var An = class {
2792
2807
  renderQualityMenu() {
2793
2808
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2794
2809
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2795
- for (let n of e) this.menu.append(this.menuItem(Mn(n), t === n.index, () => this.player.setQuality(n.index)));
2810
+ for (let n of e) this.menu.append(this.menuItem(Nn(n), t === n.index, () => this.player.setQuality(n.index)));
2796
2811
  }
2797
2812
  renderAudioMenu() {
2798
2813
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2799
2814
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2800
- for (let t of e) this.menu.append(this.menuItem(Nn(t), t.default, () => this.player.setAudioTrack(t.id)));
2815
+ for (let t of e) this.menu.append(this.menuItem(Pn(t), t.default, () => this.player.setAudioTrack(t.id)));
2801
2816
  }
2802
2817
  renderCcMenu() {
2803
2818
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2804
2819
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2805
- for (let t of e) this.menu.append(this.menuItem(Pn(t), !1, () => this.player.setTextTrack(t.id)));
2820
+ for (let t of e) this.menu.append(this.menuItem(Fn(t), !1, () => this.player.setTextTrack(t.id)));
2806
2821
  }
2807
2822
  onTracksChanged() {
2808
2823
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2903,41 +2918,41 @@ var An = class {
2903
2918
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2904
2919
  }
2905
2920
  };
2906
- function jn(e) {
2921
+ function Mn(e) {
2907
2922
  (!Number.isFinite(e) || e < 0) && (e = 0);
2908
2923
  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");
2909
2924
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2910
2925
  }
2911
- function Mn(e) {
2926
+ function Nn(e) {
2912
2927
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2913
2928
  }
2914
- function Nn(e) {
2929
+ function Pn(e) {
2915
2930
  return e.name || e.lang || `Track ${e.id}`;
2916
2931
  }
2917
- function Pn(e) {
2932
+ function Fn(e) {
2918
2933
  return e.name || e.lang || `Track ${e.id}`;
2919
2934
  }
2920
2935
  //#endregion
2921
2936
  //#region src/managed/index.ts
2922
- var Fn = 6e3, In = 45e3, Ln = 2e3, Rn = 3, zn = 2e3, Bn = 48e4, Vn = "keySystemLicenseRequestFailed";
2923
- function Hn(e) {
2937
+ var In = 6e3, Ln = 45e3, Rn = 2e3, zn = 3, Bn = 2e3, Vn = 48e4, Hn = "keySystemLicenseRequestFailed";
2938
+ function Un(e) {
2924
2939
  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)})`);
2925
- if (e.env !== void 0) return We(e.env);
2940
+ if (e.env !== void 0) return Ke(e.env);
2926
2941
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2927
2942
  return e.baseUrl;
2928
2943
  }
2929
- async function Un(e) {
2944
+ async function Wn(e) {
2930
2945
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2931
- let t = Hn(e);
2946
+ let t = Un(e);
2932
2947
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2933
2948
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2934
- let r = new Wn({
2949
+ let r = new Gn({
2935
2950
  ...e,
2936
2951
  baseUrl: t
2937
2952
  });
2938
2953
  return await r.start(), r;
2939
2954
  }
2940
- var Wn = class {
2955
+ var Gn = class {
2941
2956
  opts;
2942
2957
  abort = new AbortController();
2943
2958
  listeners = {};
@@ -2984,7 +2999,7 @@ var Wn = class {
2984
2999
  this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
2985
3000
  let e = ++this.loadGen, t = this.resolveOptions();
2986
3001
  try {
2987
- let n = await y(t);
3002
+ let n = await v(t);
2988
3003
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2989
3004
  let e = this._lastError;
2990
3005
  throw this.destroy(), e;
@@ -3011,7 +3026,7 @@ var Wn = class {
3011
3026
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
3012
3027
  }
3013
3028
  beginArmingByPolling(e) {
3014
- b({
3029
+ y({
3015
3030
  ...this.resolveOptions(),
3016
3031
  signal: this.abort.signal,
3017
3032
  waitForLive: this.buildWaitConfig(e)
@@ -3028,7 +3043,7 @@ var Wn = class {
3028
3043
  setTimeout(() => {
3029
3044
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3030
3045
  phase: i ? "unavailable" : "tooEarly",
3031
- retryInMs: In,
3046
+ retryInMs: Ln,
3032
3047
  attempt: 1,
3033
3048
  elapsedMs: 0,
3034
3049
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3045,7 +3060,7 @@ var Wn = class {
3045
3060
  }
3046
3061
  }
3047
3062
  }, h = () => {
3048
- a || s || p() || (s = !0, b({
3063
+ a || s || p() || (s = !0, y({
3049
3064
  ...this.resolveOptions(),
3050
3065
  signal: c.signal,
3051
3066
  waitForLive: this.buildWaitConfig(e)
@@ -3053,7 +3068,7 @@ var Wn = class {
3053
3068
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
3054
3069
  }));
3055
3070
  }, g = () => {
3056
- a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
3071
+ a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
3057
3072
  if (!(a || p())) {
3058
3073
  if (e instanceof n && o(e.code)) {
3059
3074
  h();
@@ -3067,13 +3082,13 @@ var Wn = class {
3067
3082
  !a && !p() && h();
3068
3083
  }, e);
3069
3084
  };
3070
- _(Fn), this.armingSub = T({
3085
+ _(In), this.armingSub = T({
3071
3086
  eventsBaseUrl: t,
3072
3087
  matchUrn: this.opts.matchUrn,
3073
3088
  credential: this.opts.credential,
3074
- onAlive: () => _(In),
3089
+ onAlive: () => _(Ln),
3075
3090
  onState: (e) => {
3076
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Ln);
3091
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Rn);
3077
3092
  },
3078
3093
  onError: () => h()
3079
3094
  });
@@ -3118,26 +3133,26 @@ var Wn = class {
3118
3133
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3119
3134
  let i = e.analytics?.sid;
3120
3135
  if (!i) return;
3121
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = dn(this.opts.baseUrl, a, e.analytics?.endpoint);
3136
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = fn(this.opts.baseUrl, a, e.analytics?.endpoint);
3122
3137
  if (!o) {
3123
3138
  s && setTimeout(() => {
3124
3139
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3125
3140
  }, 0);
3126
3141
  return;
3127
3142
  }
3128
- let c = this.opts.video, l = new fn({
3143
+ let c = this.opts.video, l = new pn({
3129
3144
  endpoint: o,
3130
3145
  sid: i,
3131
3146
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3132
- sdkVersion: vn,
3133
- environment: gn(c),
3147
+ sdkVersion: yn,
3148
+ environment: _n(c),
3134
3149
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3135
3150
  onIdle: () => this.onAnalyticsIdle(t),
3136
3151
  onBlocked: (e) => setTimeout(() => {
3137
3152
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3138
3153
  }, 0),
3139
3154
  sample: () => {
3140
- let e = this.engine?.getStats() ?? Ge, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3155
+ let e = this.engine?.getStats() ?? qe, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3141
3156
  return {
3142
3157
  ...e,
3143
3158
  bufferedMs: Math.round(t * 1e3),
@@ -3151,7 +3166,7 @@ var Wn = class {
3151
3166
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3152
3167
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3153
3168
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3154
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), _n().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3169
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), vn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3155
3170
  }
3156
3171
  currentPresentation() {
3157
3172
  let e = this.opts.video;
@@ -3178,9 +3193,9 @@ var Wn = class {
3178
3193
  freshLicenseUrl: () => this.refreshLicense()
3179
3194
  }, o = this.opts.engine ?? "auto";
3180
3195
  if (o === "native") return new G(a);
3181
- if (o === "hls") return new Kt(a);
3196
+ if (o === "hls") return new qt(a);
3182
3197
  if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && U(this.opts.video) && W() || !e.drmEnabled && nt() && U(this.opts.video)) return new G(a);
3183
- if (pt()) return new Kt(a);
3198
+ if (pt()) return new qt(a);
3184
3199
  if (U(this.opts.video)) return new G(a);
3185
3200
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3186
3201
  }
@@ -3243,7 +3258,7 @@ var Wn = class {
3243
3258
  r = 0, i = !1;
3244
3259
  },
3245
3260
  onError: () => {
3246
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Rn && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
3261
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= zn && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
3247
3262
  }
3248
3263
  });
3249
3264
  }
@@ -3265,7 +3280,7 @@ var Wn = class {
3265
3280
  scheduleRejoin(e) {
3266
3281
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3267
3282
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3268
- }, Math.random() * Ln));
3283
+ }, Math.random() * Rn));
3269
3284
  }
3270
3285
  cancelRejoin() {
3271
3286
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3289,7 +3304,7 @@ var Wn = class {
3289
3304
  }
3290
3305
  t.controls = !1;
3291
3306
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3292
- r && r.insertBefore(n, t), n.appendChild(t), xn(n, this.opts.theme), this.container = n, this.controlBar = kn({
3307
+ r && r.insertBefore(n, t), n.appendChild(t), Sn(n, this.opts.theme), this.container = n, this.controlBar = An({
3293
3308
  root: n,
3294
3309
  video: t,
3295
3310
  player: this,
@@ -3320,7 +3335,7 @@ var Wn = class {
3320
3335
  }
3321
3336
  startStats() {
3322
3337
  this.stopStats();
3323
- let e = Math.max(500, this.opts.statsIntervalMs ?? zn);
3338
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Bn);
3324
3339
  this.statsTimer = setInterval(() => {
3325
3340
  if (!this.engine) return;
3326
3341
  let e = this.engine.getStats();
@@ -3331,14 +3346,14 @@ var Wn = class {
3331
3346
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3332
3347
  }
3333
3348
  isStaleLicenseDenial(e) {
3334
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Vn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3349
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Hn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3335
3350
  }
3336
3351
  scheduleLicenseRefresh() {
3337
3352
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3338
3353
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3339
3354
  document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3340
3355
  }, document.addEventListener("visibilitychange", this.onRefocus));
3341
- let e = this.opts.licenseRefreshMs ?? Bn;
3356
+ let e = this.opts.licenseRefreshMs ?? Vn;
3342
3357
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3343
3358
  }
3344
3359
  stopRefresh() {
@@ -3350,7 +3365,7 @@ var Wn = class {
3350
3365
  if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
3351
3366
  let t = (async () => {
3352
3367
  try {
3353
- let t = await y(this.resolveOptions());
3368
+ let t = await v(this.resolveOptions());
3354
3369
  if (this.destroyed || this.engine !== e) return;
3355
3370
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3356
3371
  return (n || r) && (e.setLicenseUrls({
@@ -3394,7 +3409,7 @@ var Wn = class {
3394
3409
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3395
3410
  }
3396
3411
  getStats() {
3397
- return this.engine?.getStats() ?? Ge;
3412
+ return this.engine?.getStats() ?? qe;
3398
3413
  }
3399
3414
  getQualityLevels() {
3400
3415
  return this.engine?.getQualityLevels() ?? [];
@@ -3446,7 +3461,7 @@ var Wn = class {
3446
3461
  let e = ++this.loadGen;
3447
3462
  this.teardownPlayback();
3448
3463
  try {
3449
- let t = await b({
3464
+ let t = await y({
3450
3465
  ...this.resolveOptions(),
3451
3466
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3452
3467
  });
@@ -3504,7 +3519,7 @@ function $(e) {
3504
3519
  }
3505
3520
  //#endregion
3506
3521
  //#region src/embed/host.ts
3507
- function Gn(e) {
3522
+ function Kn(e) {
3508
3523
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3509
3524
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3510
3525
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3563,15 +3578,15 @@ function Gn(e) {
3563
3578
  }
3564
3579
  //#endregion
3565
3580
  //#region src/embed/page.ts
3566
- var Kn = /^[A-Za-z0-9:_.-]{1,128}$/;
3567
- function qn(e) {
3581
+ var qn = /^[A-Za-z0-9:_.-]{1,128}$/;
3582
+ function Jn(e) {
3568
3583
  if (typeof e == "boolean") return e;
3569
3584
  if (typeof e == "object" && e) {
3570
3585
  let t = e.endpoint;
3571
3586
  return typeof t == "string" ? { endpoint: t } : {};
3572
3587
  }
3573
3588
  }
3574
- function Jn() {
3589
+ function Yn() {
3575
3590
  let e = window.HAVIK_EMBED_CONFIG;
3576
3591
  if (e) return {
3577
3592
  baseUrl: e.baseUrl ?? "",
@@ -3581,7 +3596,7 @@ function Jn() {
3581
3596
  autoplay: e.autoplay ?? !0,
3582
3597
  muted: e.muted ?? !0,
3583
3598
  waitForLive: e.waitForLive ?? !0,
3584
- analytics: qn(e.analytics)
3599
+ analytics: Jn(e.analytics)
3585
3600
  };
3586
3601
  let t = new URLSearchParams(location.search);
3587
3602
  return {
@@ -3594,9 +3609,9 @@ function Jn() {
3594
3609
  waitForLive: !0
3595
3610
  };
3596
3611
  }
3597
- async function Yn() {
3598
- let e = Jn();
3599
- Zn();
3612
+ async function Xn() {
3613
+ let e = Yn();
3614
+ Qn();
3600
3615
  let t = document.createElement("video");
3601
3616
  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);
3602
3617
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3651,12 +3666,12 @@ async function Yn() {
3651
3666
  code: e.code,
3652
3667
  message: e.message
3653
3668
  })), e.on("autoplayblocked", () => {
3654
- i({ type: "oddin:autoplayblocked" }), Xn(t, e);
3669
+ i({ type: "oddin:autoplayblocked" }), Zn(t, e);
3655
3670
  });
3656
3671
  }, s = async (r) => {
3657
3672
  a?.destroy(), a = null;
3658
3673
  try {
3659
- let n = await Un({
3674
+ let n = await Wn({
3660
3675
  video: t,
3661
3676
  baseUrl: e.baseUrl,
3662
3677
  matchUrn: r,
@@ -3718,7 +3733,7 @@ async function Yn() {
3718
3733
  a?.retry();
3719
3734
  break;
3720
3735
  case "oddin:load":
3721
- typeof e.matchUrn == "string" && Kn.test(e.matchUrn) && s(e.matchUrn);
3736
+ typeof e.matchUrn == "string" && qn.test(e.matchUrn) && s(e.matchUrn);
3722
3737
  break;
3723
3738
  case "oddin:destroy": c();
3724
3739
  }
@@ -3730,18 +3745,18 @@ async function Yn() {
3730
3745
  protocol: 1
3731
3746
  });
3732
3747
  }
3733
- function Xn(e, t) {
3748
+ function Zn(e, t) {
3734
3749
  if (document.getElementById("havik-tap")) return;
3735
3750
  let n = document.createElement("button");
3736
3751
  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", () => {
3737
3752
  n.remove(), t.play();
3738
3753
  }), document.body.appendChild(n);
3739
3754
  }
3740
- function Zn() {
3755
+ function Qn() {
3741
3756
  let e = document.createElement("style");
3742
3757
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3743
3758
  }
3744
3759
  //#endregion
3745
- export { yn as ODDIN_THEME, n as PlaybackError, xn as applyTheme, We as baseUrlForEnv, Yn as bootEmbed, Te as clearDeviceId, Un as createPlayer, E as deriveEventsBaseUrl, Be as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, He as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Gn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3760
+ export { bn as ODDIN_THEME, n as PlaybackError, Sn as applyTheme, Ke as baseUrlForEnv, Xn as bootEmbed, Te as clearDeviceId, Wn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Kn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3746
3761
 
3747
3762
  //# sourceMappingURL=index.js.map