@oddin-gg/havik-player 2.15.4 → 2.15.6

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 de(e, t, r) {
177
+ async function v(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 de(e, t, r) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/core/resolve.ts
203
- async function v(e) {
203
+ async function y(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 fe(t);
211
- return he(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await de(t);
211
+ return me(await t.json(), e.matchUrn);
212
212
  }
213
- function y(e) {
214
- let t = () => v(e);
215
- return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
213
+ function b(e) {
214
+ let t = () => y(e);
215
+ return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
216
216
  }
217
- async function fe(e) {
217
+ async function de(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 fe(e) {
230
230
  liveStartsAtMs: s
231
231
  });
232
232
  }
233
- var pe = /* @__PURE__ */ new Set([
233
+ var fe = /* @__PURE__ */ new Set([
234
234
  "matchUrn",
235
235
  "protocol",
236
236
  "drmEnabled",
@@ -241,7 +241,7 @@ var pe = /* @__PURE__ */ new Set([
241
241
  "expiresAt",
242
242
  "analytics"
243
243
  ]);
244
- function b(e, t) {
244
+ function x(e, t) {
245
245
  let r;
246
246
  try {
247
247
  r = new URL(t);
@@ -251,7 +251,7 @@ function b(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 me(e) {
254
+ function pe(e) {
255
255
  if (e !== void 0) {
256
256
  if (typeof e == "string" && !e.endsWith("/")) try {
257
257
  let t = new URL(e);
@@ -260,62 +260,62 @@ function me(e) {
260
260
  g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
261
  }
262
262
  }
263
- function he(e, t) {
263
+ function me(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: b("manifestUrl", e.manifestUrl),
269
+ manifestUrl: x("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 = me(e.analytics.endpoint);
274
+ let t = pe(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: 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)
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)
282
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
283
283
  }
284
284
  let a = {};
285
- for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) fe.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 ge(e) {
290
+ function he(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function x(e) {
293
+ function S(e) {
294
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
295
295
  }
296
- function S(e, t) {
297
- let n = x(ge(e));
296
+ function C(e, t) {
297
+ let n = S(he(e));
298
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
299
299
  }
300
- async function C(e, t) {
300
+ async function w(e, t) {
301
301
  let n = t ?? e;
302
302
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
303
303
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
304
304
  let r = e;
305
305
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
306
306
  }
307
- async function w(e, t) {
307
+ async function T(e, t) {
308
308
  let n = e;
309
309
  if (n.webkitDisplayingFullscreen) {
310
310
  n.webkitExitFullscreen?.();
311
311
  return;
312
312
  }
313
- let r = ge(e), i = x(r);
313
+ let r = he(e), i = S(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
317
317
  //#region src/core/catalog.ts
318
- async function _e(e) {
318
+ async function ge(e) {
319
319
  let t = new URLSearchParams();
320
320
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
321
321
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -333,12 +333,12 @@ async function _e(e) {
333
333
  };
334
334
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
335
335
  return {
336
- tournaments: ve(await s.json()),
336
+ tournaments: _e(await s.json()),
337
337
  etag: s.headers.get("etag") ?? void 0,
338
338
  notModified: !1
339
339
  };
340
340
  }
341
- function ve(e) {
341
+ function _e(e) {
342
342
  return (e.tournaments ?? []).map((e) => {
343
343
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
344
344
  return {
@@ -360,7 +360,7 @@ function ve(e) {
360
360
  };
361
361
  });
362
362
  }
363
- async function ye(e) {
363
+ async function ve(e) {
364
364
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
365
365
  e.etag && i.set("If-None-Match", e.etag);
366
366
  let a = await p(t, {
@@ -380,13 +380,13 @@ async function ye(e) {
380
380
  };
381
381
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
382
382
  return {
383
- tournament: be(await a.json()),
383
+ tournament: ye(await a.json()),
384
384
  etag: a.headers.get("etag") ?? void 0,
385
385
  notModified: !1,
386
386
  notFound: !1
387
387
  };
388
388
  }
389
- function be(e) {
389
+ function ye(e) {
390
390
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
391
391
  return {
392
392
  urn: t,
@@ -406,17 +406,17 @@ function be(e) {
406
406
  }))
407
407
  };
408
408
  }
409
- function xe(e) {
409
+ function be(e) {
410
410
  return e.tournaments.flatMap((e) => e.matches);
411
411
  }
412
412
  //#endregion
413
413
  //#region src/core/poll.ts
414
- var Se = /* @__PURE__ */ new Set([
414
+ var xe = /* @__PURE__ */ new Set([
415
415
  "NOT_FOUND",
416
416
  "GONE",
417
417
  "INVALID_URN"
418
418
  ]);
419
- function Ce(e) {
419
+ function Se(e) {
420
420
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
421
421
  u || (a = setTimeout(m, t));
422
422
  }, m = async () => {
@@ -449,7 +449,7 @@ function Ce(e) {
449
449
  } catch (t) {
450
450
  if (!i.signal.aborted) {
451
451
  let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
- Se.has(r.code) && (u = !0), e.onError?.(r);
452
+ xe.has(r.code) && (u = !0), e.onError?.(r);
453
453
  }
454
454
  } finally {
455
455
  f();
@@ -461,9 +461,9 @@ function Ce(e) {
461
461
  }
462
462
  //#endregion
463
463
  //#region src/core/events.ts
464
- var we = 45e3;
465
- function T(e) {
466
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
464
+ var Ce = 45e3;
465
+ function E(e) {
466
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Ce, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
467
467
  if (a.signal.aborted) return t();
468
468
  let n = setTimeout(t, e);
469
469
  a.signal.addEventListener("abort", () => {
@@ -544,7 +544,7 @@ function T(e) {
544
544
  o || (o = !0, a.abort());
545
545
  } };
546
546
  }
547
- function E(e) {
547
+ function D(e) {
548
548
  try {
549
549
  let t = new URL(e);
550
550
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -554,27 +554,27 @@ function E(e) {
554
554
  }
555
555
  //#endregion
556
556
  //#region src/core/drm/deviceId.ts
557
- var D = "havik.player.deviceId", O;
558
- function k() {
559
- if (O) return O;
557
+ var O = "havik.player.deviceId", k;
558
+ function A() {
559
+ if (k) return k;
560
560
  try {
561
- let e = globalThis.localStorage?.getItem(D);
562
- if (e) return O = e, e;
561
+ let e = globalThis.localStorage?.getItem(O);
562
+ if (e) return k = e, e;
563
563
  } catch {}
564
- let e = Ee();
565
- O = e;
564
+ let e = Te();
565
+ k = e;
566
566
  try {
567
- globalThis.localStorage?.setItem(D, e);
567
+ globalThis.localStorage?.setItem(O, e);
568
568
  } catch {}
569
569
  return e;
570
570
  }
571
- function Te() {
572
- O = void 0;
571
+ function we() {
572
+ k = void 0;
573
573
  try {
574
- globalThis.localStorage?.removeItem(D);
574
+ globalThis.localStorage?.removeItem(O);
575
575
  } catch {}
576
576
  }
577
- function Ee() {
577
+ function Te() {
578
578
  let e = globalThis.crypto;
579
579
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
580
580
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -586,21 +586,21 @@ function Ee() {
586
586
  }
587
587
  //#endregion
588
588
  //#region src/core/drm/headers.ts
589
- function De(e, t, n = {}) {
589
+ function Ee(e, t, n = {}) {
590
590
  let r = {
591
591
  "x-api-key": t.apiKey,
592
592
  "X-Match-Urn": e.matchUrn,
593
- "X-Device-Id": n.deviceId ?? k(),
593
+ "X-Device-Id": n.deviceId ?? A(),
594
594
  "Content-Type": "application/octet-stream"
595
595
  };
596
596
  return n.userId && (r["X-User-Id"] = n.userId), r;
597
597
  }
598
598
  //#endregion
599
599
  //#region src/core/drm/cdm.ts
600
- var A = /* @__PURE__ */ new WeakMap();
601
- function Oe(e, t) {
602
- let n = A.get(e);
603
- n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
600
+ var j = /* @__PURE__ */ new WeakMap();
601
+ function De(e, t) {
602
+ let n = j.get(e);
603
+ n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
604
604
  let r = n.get(t.keySystem);
605
605
  if (r) return r;
606
606
  let i = t.createMediaKeys().catch((e) => {
@@ -608,22 +608,22 @@ function Oe(e, t) {
608
608
  });
609
609
  return n.set(t.keySystem, i), i;
610
610
  }
611
- function j() {
611
+ function M() {
612
612
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
613
613
  }
614
- var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
615
- function ke(e) {
614
+ var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
615
+ function Oe(e) {
616
616
  return e.startsWith("com.widevine");
617
617
  }
618
- function N(e, t) {
619
- if (!ke(e)) return t;
618
+ function P(e, t) {
619
+ if (!Oe(e)) return t;
620
620
  let n = (e, t) => {
621
621
  let n = e.videoCapabilities;
622
622
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
623
- let n = M.indexOf(e.robustness);
624
- return n === -1 || M.indexOf(t) > n;
623
+ let n = N.indexOf(e.robustness);
624
+ return n === -1 || N.indexOf(t) > n;
625
625
  });
626
- }, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
626
+ }, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
627
627
  ...t,
628
628
  videoCapabilities: t.videoCapabilities?.map((t) => ({
629
629
  ...t,
@@ -632,53 +632,53 @@ function N(e, t) {
632
632
  })));
633
633
  return [...t, ...r];
634
634
  }
635
- function P(e) {
636
- return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
635
+ function F(e) {
636
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
637
637
  keySystem: t.keySystem,
638
638
  getConfiguration: () => t.getConfiguration(),
639
- createMediaKeys: () => Oe(e, t)
639
+ createMediaKeys: () => De(e, t)
640
640
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
641
641
  }
642
- var F = {
642
+ var I = {
643
643
  video: "SW_SECURE_DECODE",
644
644
  audio: "SW_SECURE_CRYPTO",
645
645
  scheme: "cbcs"
646
646
  };
647
- function Ae(e) {
648
- if (!j()) return;
647
+ function ke(e) {
648
+ if (!M()) return;
649
649
  let t = (e, t) => ({
650
650
  contentType: e,
651
651
  robustness: t,
652
- encryptionScheme: F.scheme
652
+ encryptionScheme: I.scheme
653
653
  });
654
- P(e)("com.widevine.alpha", [{
654
+ F(e)("com.widevine.alpha", [{
655
655
  initDataTypes: ["cenc"],
656
656
  distinctiveIdentifier: "optional",
657
657
  persistentState: "optional",
658
658
  sessionTypes: ["temporary"],
659
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
660
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
659
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
660
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
661
661
  }]).then((e) => e.createMediaKeys()).catch(() => {});
662
662
  }
663
- function I(e) {
664
- let t = L(e);
663
+ function L(e) {
664
+ let t = R(e);
665
665
  if (/^avc[13]/.test(t)) return "avc";
666
666
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
667
667
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
668
668
  if (t.startsWith("av01")) return "av1";
669
669
  if (/^vp0?9/.test(t)) return "vp9";
670
670
  }
671
- function L(e) {
671
+ function R(e) {
672
672
  return (e ?? "").trim().toLowerCase();
673
673
  }
674
- var je = {
674
+ var Ae = {
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
- }, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
680
- function Ne(e) {
681
- let t = L(e), n = Me.get(t);
679
+ }, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
680
+ function Me(e) {
681
+ let t = R(e), n = je.get(t);
682
682
  if (n) return n;
683
683
  let r = {
684
684
  initDataTypes: ["cenc"],
@@ -687,32 +687,32 @@ function Ne(e) {
687
687
  sessionTypes: ["temporary"],
688
688
  videoCapabilities: [{
689
689
  contentType: `video/mp4; codecs="${e.trim()}"`,
690
- robustness: F.video,
691
- encryptionScheme: F.scheme
690
+ robustness: I.video,
691
+ encryptionScheme: I.scheme
692
692
  }]
693
693
  }, i = (async () => {
694
694
  try {
695
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
695
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
696
696
  } catch {
697
697
  return !1;
698
698
  }
699
- })().then((e) => (R.set(t, e), e));
700
- return Me.set(t, i), i;
699
+ })().then((e) => (z.set(t, e), e));
700
+ return je.set(t, i), i;
701
701
  }
702
- function Pe() {
703
- if (j()) for (let e of Object.values(je)) Ne(e);
702
+ function Ne() {
703
+ if (M()) for (let e of Object.values(Ae)) Me(e);
704
704
  }
705
- function Fe(e) {
706
- let t = I(e);
707
- if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
705
+ function Pe(e) {
706
+ let t = L(e);
707
+ if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ae[t]));
708
708
  }
709
709
  //#endregion
710
710
  //#region src/core/drm/support.ts
711
- var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
711
+ var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
712
712
  widevine: ["com.widevine.alpha"],
713
713
  fairplay: ["com.apple.fps"]
714
714
  };
715
- function Be(e) {
715
+ function ze(e) {
716
716
  return e === "fairplay" ? [{
717
717
  initDataTypes: [
718
718
  "sinf",
@@ -720,30 +720,30 @@ function Be(e) {
720
720
  "cenc"
721
721
  ],
722
722
  videoCapabilities: [{
723
- contentType: Le,
723
+ contentType: Ie,
724
724
  robustness: "",
725
725
  encryptionScheme: "cbcs"
726
726
  }],
727
727
  audioCapabilities: [{
728
- contentType: Re,
728
+ contentType: Le,
729
729
  robustness: "",
730
730
  encryptionScheme: "cbcs"
731
731
  }]
732
- }] : N("com.widevine.alpha", [{
732
+ }] : P("com.widevine.alpha", [{
733
733
  initDataTypes: ["cenc"],
734
734
  videoCapabilities: [{
735
- contentType: Le,
736
- robustness: F.video,
737
- encryptionScheme: F.scheme
735
+ contentType: Ie,
736
+ robustness: I.video,
737
+ encryptionScheme: I.scheme
738
738
  }],
739
739
  audioCapabilities: [{
740
- contentType: Re,
741
- robustness: F.audio,
742
- encryptionScheme: F.scheme
740
+ contentType: Le,
741
+ robustness: I.audio,
742
+ encryptionScheme: I.scheme
743
743
  }]
744
744
  }]);
745
745
  }
746
- function Ve(e, t) {
746
+ function Be(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 Ve(e, t) {
753
753
  });
754
754
  });
755
755
  }
756
- async function He(e = {}) {
757
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
756
+ async function Ve(e = {}) {
757
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, 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 He(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 = ze[e];
769
+ let t = Re[e];
770
770
  if (!t) {
771
771
  r[e] = "unknown system";
772
772
  continue;
@@ -777,7 +777,7 @@ async function He(e = {}) {
777
777
  break;
778
778
  }
779
779
  try {
780
- return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
780
+ return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
781
781
  verdict: "supported",
782
782
  system: e,
783
783
  detail: r
@@ -801,18 +801,18 @@ async function He(e = {}) {
801
801
  }
802
802
  //#endregion
803
803
  //#region src/core/manifest.ts
804
- var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
- function We(e) {
806
- return Ue.test(e);
804
+ var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function Ue(e) {
806
+ return He.test(e);
807
807
  }
808
808
  //#endregion
809
809
  //#region src/core/env.ts
810
- var z = {
810
+ var We = {
811
811
  integration: "https://feed-dev.oddin-video.gg",
812
812
  production: "https://feed.oddin-video.gg"
813
813
  };
814
814
  function B(e) {
815
- let t = Object.prototype.hasOwnProperty.call(z, e) ? z[e] : void 0;
815
+ let t = Object.prototype.hasOwnProperty.call(We, e) ? We[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
  }
@@ -876,6 +876,11 @@ function G() {
876
876
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
877
877
  return e || t;
878
878
  }
879
+ function Ye() {
880
+ if (typeof navigator > "u" || !G()) return !1;
881
+ let e = navigator.userAgent ?? "";
882
+ return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
883
+ }
879
884
  var K = class {
880
885
  name = "native";
881
886
  deps;
@@ -912,7 +917,7 @@ var K = class {
912
917
  type: "error",
913
918
  error: new n("INTERNAL", 0, "native HLS playback error"),
914
919
  fatal: !0
915
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ye(t.manifestUrl, t.analytics?.sid), e.load();
920
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Xe(t.manifestUrl, t.analytics?.sid), e.load();
916
921
  }
917
922
  startLoad() {
918
923
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -1052,13 +1057,13 @@ var K = class {
1052
1057
  } catch {}
1053
1058
  }
1054
1059
  };
1055
- function Ye(e, t) {
1060
+ function Xe(e, t) {
1056
1061
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1057
1062
  }
1058
1063
  //#endregion
1059
1064
  //#region src/core/engine/prefetch.ts
1060
- var Xe = 15e3, Ze = 5e3, Qe = 6;
1061
- function $e(e) {
1065
+ var Ze = 15e3, Qe = 5e3, $e = 6;
1066
+ function et(e) {
1062
1067
  try {
1063
1068
  let t = new URL(e);
1064
1069
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1066,7 +1071,7 @@ function $e(e) {
1066
1071
  return e;
1067
1072
  }
1068
1073
  }
1069
- var et = class {
1074
+ var tt = class {
1070
1075
  cmcd;
1071
1076
  entries = /* @__PURE__ */ new Map();
1072
1077
  keyed = /* @__PURE__ */ new Set();
@@ -1089,10 +1094,10 @@ var et = class {
1089
1094
  }
1090
1095
  prefetch(e, t, n) {
1091
1096
  if (!this.isActive(t)) return;
1092
- let r = $e(e);
1097
+ let r = et(e);
1093
1098
  if (this.entries.has(r)) return;
1094
1099
  let i = this.perTrack.get(t) ?? 0;
1095
- if (i >= Qe) return;
1100
+ if (i >= $e) return;
1096
1101
  this.perTrack.set(t, i + 1);
1097
1102
  let a = new AbortController(), o = {
1098
1103
  started: performance.now(),
@@ -1106,10 +1111,10 @@ var et = class {
1106
1111
  signal: a.signal
1107
1112
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1108
1113
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1109
- }, Xe);
1114
+ }, Ze);
1110
1115
  }
1111
1116
  take(e) {
1112
- let t = $e(e), n = this.entries.get(t);
1117
+ let t = et(e), n = this.entries.get(t);
1113
1118
  return n && this.entries.delete(t), n;
1114
1119
  }
1115
1120
  destroy() {
@@ -1129,13 +1134,13 @@ var et = class {
1129
1134
  }
1130
1135
  }
1131
1136
  };
1132
- function tt(t) {
1137
+ function nt(t) {
1133
1138
  let n = e.DefaultConfig?.loader;
1134
1139
  if (typeof n != "function") return;
1135
1140
  class r extends n {
1136
1141
  served = !1;
1137
1142
  cancelled = !1;
1138
- stats = nt();
1143
+ stats = rt();
1139
1144
  load(e, n, r) {
1140
1145
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1141
1146
  if (!i) {
@@ -1143,7 +1148,7 @@ function tt(t) {
1143
1148
  return;
1144
1149
  }
1145
1150
  this.served = !0;
1146
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ze, s = setTimeout(() => {
1151
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Qe, s = setTimeout(() => {
1147
1152
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1148
1153
  }, o);
1149
1154
  i.bytes.then((o) => {
@@ -1170,7 +1175,7 @@ function tt(t) {
1170
1175
  }
1171
1176
  return r;
1172
1177
  }
1173
- function nt() {
1178
+ function rt() {
1174
1179
  return {
1175
1180
  aborted: !1,
1176
1181
  loaded: 0,
@@ -1194,10 +1199,10 @@ function nt() {
1194
1199
  }
1195
1200
  };
1196
1201
  }
1197
- function rt(e) {
1202
+ function it(e) {
1198
1203
  return e === "audio" ? "audio" : "main";
1199
1204
  }
1200
- function it(e, t) {
1205
+ function at(e, t) {
1201
1206
  let n = [];
1202
1207
  t.initSegment?.url && !t.initSegment.data && n.push({
1203
1208
  url: t.initSegment.url,
@@ -1216,24 +1221,24 @@ function it(e, t) {
1216
1221
  }
1217
1222
  //#endregion
1218
1223
  //#region src/core/engine/hls.ts
1219
- function at() {
1224
+ function ot() {
1220
1225
  return e.isSupported();
1221
1226
  }
1222
- var ot = 3, st = 5, ct = 3, lt = 3e4, ut = 12e3, dt = 3e3, ft = 6e3, pt = .5, mt = 3, ht = .5, gt = 1.1, _t = .25, vt = 5e3, yt = 4e3, bt = 2, xt = 5, St = 2, Ct = 2, wt = 4, Tt = 4, Et = 2e3, Dt = 3e4, Ot = .2, kt = 30, At = 2, jt = 2, Mt = 9, Nt = .5, Pt = 64;
1223
- function Ft(e) {
1227
+ var st = 3, ct = 5, lt = 3, ut = 3e4, dt = 12e3, ft = 3e3, pt = 6e3, mt = .5, ht = 3, gt = .5, _t = 1.1, vt = .25, yt = 5e3, bt = 4e3, xt = 2, St = 5, Ct = 2, wt = 2, Tt = 4, Et = 4, Dt = 2e3, Ot = 3e4, kt = .2, At = 30, jt = 2, Mt = 2, Nt = 9, Pt = .5, Ft = 64;
1228
+ function It(e) {
1224
1229
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1225
1230
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1226
1231
  return;
1227
1232
  }
1228
- e.liveSyncDuration ??= jt;
1229
- let t = Math.max(12, e.liveSyncDuration + Mt);
1230
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), It(e, e.liveSyncDuration);
1233
+ e.liveSyncDuration ??= Mt;
1234
+ let t = Math.max(12, e.liveSyncDuration + Nt);
1235
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Lt(e, e.liveSyncDuration);
1231
1236
  }
1232
- function It(e, t) {
1237
+ function Lt(e, t) {
1233
1238
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1234
1239
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1235
1240
  }
1236
- var Lt = class {
1241
+ var Rt = class {
1237
1242
  name = "hls";
1238
1243
  hls = null;
1239
1244
  deps;
@@ -1323,7 +1328,7 @@ var Lt = class {
1323
1328
  });
1324
1329
  return;
1325
1330
  }
1326
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1331
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (ke(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1327
1332
  let e = this.hls;
1328
1333
  if (document.visibilityState !== "visible" || !e) return;
1329
1334
  let t = e.liveSyncPosition;
@@ -1346,7 +1351,7 @@ var Lt = class {
1346
1351
  }
1347
1352
  this.loadSuspended = !0;
1348
1353
  }
1349
- }, vt));
1354
+ }, yt));
1350
1355
  }
1351
1356
  resumeLoading() {
1352
1357
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1378,7 +1383,7 @@ var Lt = class {
1378
1383
  let t = e.liveSyncPosition;
1379
1384
  if (typeof t != "number" || !Number.isFinite(t)) return;
1380
1385
  let { video: n } = this.deps;
1381
- n.currentTime <= t + Nt || (n.currentTime = t);
1386
+ n.currentTime <= t + Pt || (n.currentTime = t);
1382
1387
  }
1383
1388
  startHls() {
1384
1389
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1397,12 +1402,12 @@ var Lt = class {
1397
1402
  emeEnabled: !0,
1398
1403
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1399
1404
  drmSystemOptions: {
1400
- videoRobustness: F.video,
1401
- audioRobustness: F.audio,
1402
- videoEncryptionScheme: F.scheme,
1403
- audioEncryptionScheme: F.scheme
1405
+ videoRobustness: I.video,
1406
+ audioRobustness: I.audio,
1407
+ videoEncryptionScheme: I.scheme,
1408
+ audioEncryptionScheme: I.scheme
1404
1409
  },
1405
- ...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
1410
+ ...M() ? { requestMediaKeySystemAccessFunc: F(t) } : {},
1406
1411
  licenseXhrSetup: (e, t) => {
1407
1412
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
1408
1413
  let o = performance.now();
@@ -1419,20 +1424,20 @@ var Lt = class {
1419
1424
  ...c
1420
1425
  };
1421
1426
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1422
- let e = new et({
1427
+ let e = new tt({
1423
1428
  sessionId: n.analytics?.sid,
1424
1429
  contentId: n.matchUrn
1425
- }), t = tt(e);
1430
+ }), t = nt(e);
1426
1431
  t && (this.prefetch = e, d.fLoader = t);
1427
1432
  }
1428
- Ft(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;
1433
+ It(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1429
1434
  let f = new e(d);
1430
1435
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1431
1436
  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" });
1432
1437
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1433
1438
  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(() => {
1434
1439
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1435
- }, lt)));
1440
+ }, ut)));
1436
1441
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1437
1442
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1438
1443
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1440,7 +1445,7 @@ var Lt = class {
1440
1445
  let n = t?.frag?.stats, r = n?.loaded;
1441
1446
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1442
1447
  let i = n?.loading;
1443
- 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 > Pt && this.requestTimesMs.shift());
1448
+ i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ft && this.requestTimesMs.shift());
1444
1449
  let a = t?.frag?.url;
1445
1450
  if (a) {
1446
1451
  let e = H(a);
@@ -1457,15 +1462,15 @@ var Lt = class {
1457
1462
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1458
1463
  let t = this.prefetch;
1459
1464
  f.on(e.Events.KEY_LOADING, (e, n) => {
1460
- let r = n?.frag, i = rt(r?.type);
1461
- if (r && t.isActive(i)) for (let e of it(f, r)) t.prefetch(e.url, i, e.kind);
1462
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(rt(n?.frag?.type)));
1465
+ let r = n?.frag, i = it(r?.type);
1466
+ if (r && t.isActive(i)) for (let e of at(f, r)) t.prefetch(e.url, i, e.kind);
1467
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(it(n?.frag?.type)));
1463
1468
  }
1464
1469
  f.on(e.Events.KEY_LOADED, () => {
1465
1470
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1466
1471
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1467
1472
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1468
- }, dt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1473
+ }, ft), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1469
1474
  this.renditionSwitches += 1;
1470
1475
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1471
1476
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1529,7 +1534,7 @@ var Lt = class {
1529
1534
  return;
1530
1535
  }
1531
1536
  this.capTimer && clearTimeout(this.capTimer);
1532
- let t = e > this.sizeCapLevel ? Et : Dt;
1537
+ let t = e > this.sizeCapLevel ? Dt : Ot;
1533
1538
  this.capTimer = setTimeout(() => {
1534
1539
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1535
1540
  }, t);
@@ -1539,9 +1544,9 @@ var Lt = class {
1539
1544
  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;
1540
1545
  }
1541
1546
  dropLevelsWidevineCannotPlay(e) {
1542
- this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1543
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1544
- for (let n of t) Ne(n).then((t) => {
1547
+ this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
1548
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
1549
+ for (let n of t) Me(n).then((t) => {
1545
1550
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1546
1551
  });
1547
1552
  }
@@ -1549,10 +1554,10 @@ var Lt = class {
1549
1554
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1550
1555
  if (n.forEach((e, n) => {
1551
1556
  let a = e.videoCodec;
1552
- a && I(a) && t(a) && (r.push(n), i.add(a));
1557
+ a && L(a) && t(a) && (r.push(n), i.add(a));
1553
1558
  }), !r.length) return !1;
1554
1559
  let a = [...i].join(", ");
1555
- 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;
1560
+ if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1556
1561
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1557
1562
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1558
1563
  }
@@ -1650,7 +1655,7 @@ var Lt = class {
1650
1655
  return;
1651
1656
  }
1652
1657
  let e = Date.now() - this.lastAdvanceMs;
1653
- !this.chaseSuspended && e > ft && this.suspendChasing(), e > ut && this.emitEnded("stalled");
1658
+ !this.chaseSuspended && e > pt && this.suspendChasing(), e > dt && this.emitEnded("stalled");
1654
1659
  }
1655
1660
  resetStarvationWindow() {
1656
1661
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1665,7 +1670,7 @@ var Lt = class {
1665
1670
  this.resetStarvationWindow();
1666
1671
  return;
1667
1672
  }
1668
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ft, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > yt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1673
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < pt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > bt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1669
1674
  if (this.starvedFrames = c, !a || l) {
1670
1675
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1671
1676
  return;
@@ -1674,12 +1679,12 @@ var Lt = class {
1674
1679
  this.resetStarvationWindow();
1675
1680
  return;
1676
1681
  }
1677
- 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 > wt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= St && (this.clearKick(), this.starvationRebuilds < Ct)) {
1682
+ if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > Tt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Ct && (this.clearKick(), this.starvationRebuilds < wt)) {
1678
1683
  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");
1679
1684
  return;
1680
1685
  }
1681
- let u = i && this.starvedTicks >= bt, d = !i && this.deadTicks >= wt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Tt;
1682
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= xt))) {
1686
+ let u = i && this.starvedTicks >= xt, d = !i && this.deadTicks >= Tt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Et;
1687
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= St))) {
1683
1688
  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");
1684
1689
  try {
1685
1690
  e.stopLoad(), e.startLoad(-1);
@@ -1694,7 +1699,7 @@ var Lt = class {
1694
1699
  let t = e.latency, n = e.targetLatency;
1695
1700
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1696
1701
  let r = t - n;
1697
- !this.catchUpEngaged && r > pt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= pt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1702
+ !this.catchUpEngaged && r > mt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= mt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1698
1703
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1699
1704
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1700
1705
  }
@@ -1716,15 +1721,15 @@ var Lt = class {
1716
1721
  return;
1717
1722
  }
1718
1723
  let { totalFrames: n, dropped: r } = U(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1719
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < kt || o < 0) {
1724
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < At || o < 0) {
1720
1725
  this.fpsBadTicks = 0;
1721
1726
  return;
1722
1727
  }
1723
- if (o <= Ot * a) {
1728
+ if (o <= kt * a) {
1724
1729
  this.fpsBadTicks = 0;
1725
1730
  return;
1726
1731
  }
1727
- if (this.fpsBadTicks += 1, this.fpsBadTicks < At) return;
1732
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < jt) return;
1728
1733
  this.fpsBadTicks = 0;
1729
1734
  let s = e.levels, c = s[e.currentLevel];
1730
1735
  if (!c) return;
@@ -1741,20 +1746,20 @@ var Lt = class {
1741
1746
  return;
1742
1747
  }
1743
1748
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1744
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(gt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1749
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(_t, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1745
1750
  this.resetChaseWindow();
1746
1751
  return;
1747
1752
  }
1748
- if (this.chaseLatency < 0 || this.chaseLatency - n >= ht) {
1753
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= gt) {
1749
1754
  this.chaseLatency = n, this.chaseTicks = 0;
1750
1755
  return;
1751
1756
  }
1752
- if (this.chaseTicks += 1, this.chaseTicks < mt) return;
1757
+ if (this.chaseTicks += 1, this.chaseTicks < ht) return;
1753
1758
  this.resetChaseWindow();
1754
1759
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1755
1760
  if (!(a > 1)) return;
1756
1761
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1757
- s < o + _t || (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);
1762
+ s < o + vt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
1758
1763
  }
1759
1764
  suspendChasing() {
1760
1765
  let e = this.hls;
@@ -1799,7 +1804,7 @@ var Lt = class {
1799
1804
  scheduleLicenseRetry(t) {
1800
1805
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1801
1806
  let n = t.response?.code ?? 0;
1802
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ct) return !1;
1807
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= lt) return !1;
1803
1808
  this.licenseRecoveries += 1;
1804
1809
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1805
1810
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1831,7 +1836,7 @@ var Lt = class {
1831
1836
  return;
1832
1837
  }
1833
1838
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1834
- if (this.networkRecoveries < st) {
1839
+ if (this.networkRecoveries < ct) {
1835
1840
  this.networkRecoveries += 1;
1836
1841
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1837
1842
  this.networkRetryTimer = setTimeout(() => {
@@ -1848,7 +1853,7 @@ var Lt = class {
1848
1853
  return;
1849
1854
  }
1850
1855
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1851
- if (this.mediaRecoveries < ot) {
1856
+ if (this.mediaRecoveries < st) {
1852
1857
  this.mediaRecoveries += 1, n.recoverMediaError();
1853
1858
  return;
1854
1859
  }
@@ -1872,19 +1877,19 @@ var Lt = class {
1872
1877
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1873
1878
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1874
1879
  }
1875
- }, Rt = 15e3, zt = 6e5, Bt = 3e5, Vt = 100, q = 1, Ht = 1e3, Ut = 3e4, Wt = 1e3, Gt = {
1880
+ }, zt = 15e3, Bt = 6e5, Vt = 3e5, Ht = 100, q = 1, Ut = 1e3, Wt = 3e4, Gt = 1e3, Kt = {
1876
1881
  inline: "PRESENTATION_INLINE",
1877
1882
  fullscreen: "PRESENTATION_FULLSCREEN",
1878
1883
  pip: "PRESENTATION_PIP"
1879
- }, Kt = {
1884
+ }, qt = {
1880
1885
  widevine: "KEY_SYSTEM_WIDEVINE",
1881
1886
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1882
1887
  none: "KEY_SYSTEM_NONE"
1883
1888
  };
1884
- function qt(e, t) {
1889
+ function Jt(e, t) {
1885
1890
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1886
1891
  }
1887
- var Jt = /* @__PURE__ */ new Set([
1892
+ var Yt = /* @__PURE__ */ new Set([
1888
1893
  "INVALID_URN",
1889
1894
  "NOT_FOUND",
1890
1895
  "GONE",
@@ -1904,7 +1909,7 @@ var Jt = /* @__PURE__ */ new Set([
1904
1909
  ended: "PLAYER_STATE_ENDED",
1905
1910
  error: "PLAYER_STATE_ERROR"
1906
1911
  };
1907
- function Yt(e) {
1912
+ function Xt(e) {
1908
1913
  try {
1909
1914
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1910
1915
  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);
@@ -1912,8 +1917,8 @@ function Yt(e) {
1912
1917
  return;
1913
1918
  }
1914
1919
  }
1915
- var Xt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Zt = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Qt = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1916
- function $t(e) {
1920
+ var Zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Qt = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), $t = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1921
+ function en(e) {
1917
1922
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
1918
1923
  let t;
1919
1924
  try {
@@ -1922,19 +1927,19 @@ function $t(e) {
1922
1927
  } catch {
1923
1928
  return;
1924
1929
  }
1925
- if (Zt.has(t) && !Y.has(t)) {
1926
- Y.add(t), g(Qt(new URL(t).origin));
1930
+ if (Qt.has(t) && !Y.has(t)) {
1931
+ Y.add(t), g($t(new URL(t).origin));
1927
1932
  for (let e of X) e.noteCspBlocked();
1928
1933
  }
1929
1934
  }
1930
- function en(e, t) {
1935
+ function tn(e, t) {
1931
1936
  return g(t, e), { disabledReason: t };
1932
1937
  }
1933
- function tn(e, t, n) {
1934
- if (n) return t && !Xt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1938
+ function nn(e, t, n) {
1939
+ if (n) return t && !Zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1935
1940
  if (t) return { endpoint: t };
1936
- if (t !== void 0) return en("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).");
1937
- let r = Yt(e);
1941
+ if (t !== void 0) return tn("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
1942
+ let r = Xt(e);
1938
1943
  if (r) return { endpoint: r };
1939
1944
  let i;
1940
1945
  try {
@@ -1942,9 +1947,9 @@ function tn(e, t, n) {
1942
1947
  } catch {
1943
1948
  i = e;
1944
1949
  }
1945
- return en(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).`);
1950
+ return tn(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
1946
1951
  }
1947
- var nn = class {
1952
+ var rn = class {
1948
1953
  opts;
1949
1954
  url;
1950
1955
  cspKey;
@@ -2026,8 +2031,8 @@ var nn = class {
2026
2031
  constructor(e) {
2027
2032
  this.opts = {
2028
2033
  ...e,
2029
- heartbeatMs: e.heartbeatMs ?? Rt,
2030
- idleMs: e.idleMs ?? zt
2034
+ heartbeatMs: e.heartbeatMs ?? zt,
2035
+ idleMs: e.idleMs ?? Bt
2031
2036
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2032
2037
  try {
2033
2038
  let e = new URL(this.url);
@@ -2044,11 +2049,11 @@ var nn = class {
2044
2049
  sdkVersion: this.opts.sdkVersion,
2045
2050
  ...this.opts.environment
2046
2051
  };
2047
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ht), 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 && Zt.add(this.cspKey), document.addEventListener("securitypolicyviolation", $t), X.add(this), this.noteCspBlocked(), this.onVisibility());
2052
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ut), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && Qt.add(this.cspKey), document.addEventListener("securitypolicyviolation", en), X.add(this), this.noteCspBlocked(), this.onVisibility());
2048
2053
  }
2049
2054
  checkSuspension(e) {
2050
2055
  if (this.endedFlag || !this.opts.idleMs) return !1;
2051
- let t = Math.max(this.opts.idleMs, Bt);
2056
+ let t = Math.max(this.opts.idleMs, Vt);
2052
2057
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2053
2058
  }
2054
2059
  syncIdle(e) {
@@ -2071,12 +2076,12 @@ var nn = class {
2071
2076
  let a = {
2072
2077
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2073
2078
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2074
- presentation: Gt[this.presentation]
2079
+ presentation: Kt[this.presentation]
2075
2080
  }, o = this.causeOf(e, t, i);
2076
2081
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2077
2082
  }
2078
2083
  seekInduced(e) {
2079
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Wt;
2084
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Gt;
2080
2085
  }
2081
2086
  causeOf(e, t, n) {
2082
2087
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2150,7 +2155,7 @@ var nn = class {
2150
2155
  let r = n ?? "";
2151
2156
  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";
2152
2157
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2153
- if (Jt.has(e)) return "ERROR_STAGE_RESOLVE";
2158
+ if (Yt.has(e)) return "ERROR_STAGE_RESOLVE";
2154
2159
  let i = t ?? "";
2155
2160
  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";
2156
2161
  }
@@ -2197,14 +2202,14 @@ var nn = class {
2197
2202
  if (this.lastRequestCount = g, _ > 0) {
2198
2203
  o.requestCountDelta = _;
2199
2204
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2200
- n.length > 0 && (o.requestTimeP50Ms = qt(n, 50), o.requestTimeP95Ms = qt(n, 95));
2205
+ n.length > 0 && (o.requestTimeP50Ms = Jt(n, 50), o.requestTimeP95Ms = Jt(n, 95));
2201
2206
  }
2202
2207
  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();
2203
2208
  }
2204
2209
  maybeEmitMediaInfo(e) {
2205
2210
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2206
2211
  let t = {};
2207
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Kt[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);
2212
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = qt[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2208
2213
  let n = JSON.stringify(t);
2209
2214
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2210
2215
  }
@@ -2224,7 +2229,7 @@ var nn = class {
2224
2229
  let c = r?.positionMs ?? 0;
2225
2230
  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));
2226
2231
  let l = e !== "END_REASON_ENDED";
2227
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Ut && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ut && (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);
2232
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Wt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Wt && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2228
2233
  let u = r?.decodedFrames ?? this.lastDecoded;
2229
2234
  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");
2230
2235
  }
@@ -2244,13 +2249,13 @@ var nn = class {
2244
2249
  };
2245
2250
  }
2246
2251
  noteCspBlocked() {
2247
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Qt(new URL(this.url).origin)));
2252
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.($t(new URL(this.url).origin)));
2248
2253
  }
2249
2254
  cspBlocked() {
2250
2255
  return !!this.cspKey && Y.has(this.cspKey);
2251
2256
  }
2252
2257
  enqueue(e) {
2253
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Vt;) {
2258
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Ht;) {
2254
2259
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2255
2260
  this.pending.splice(e >= 0 ? e : 0, 1);
2256
2261
  }
@@ -2277,7 +2282,7 @@ var nn = class {
2277
2282
  };
2278
2283
  //#endregion
2279
2284
  //#region src/core/environment.ts
2280
- function rn() {
2285
+ function an() {
2281
2286
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2282
2287
  let e;
2283
2288
  try {
@@ -2302,14 +2307,14 @@ function rn() {
2302
2307
  integration: "INTEGRATION_KIND_IFRAME"
2303
2308
  };
2304
2309
  }
2305
- function an() {
2310
+ function on() {
2306
2311
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2307
2312
  let e = navigator.userAgentData, t = e?.platform ?? "";
2308
2313
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2309
2314
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2310
2315
  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";
2311
2316
  }
2312
- function on() {
2317
+ function sn() {
2313
2318
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2314
2319
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2315
2320
  let t = {
@@ -2328,17 +2333,17 @@ function on() {
2328
2333
  }
2329
2334
  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;
2330
2335
  }
2331
- function sn(e) {
2332
- let t = rn(), n = {
2333
- deviceClass: an(),
2336
+ function cn(e) {
2337
+ let t = an(), n = {
2338
+ deviceClass: on(),
2334
2339
  integration: t.integration,
2335
- ...on()
2340
+ ...sn()
2336
2341
  };
2337
2342
  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);
2338
2343
  let r = e.getBoundingClientRect?.();
2339
2344
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2340
2345
  }
2341
- async function cn() {
2346
+ async function ln() {
2342
2347
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2343
2348
  if (!e?.getHighEntropyValues) return {};
2344
2349
  try {
@@ -2350,7 +2355,7 @@ async function cn() {
2350
2355
  }
2351
2356
  //#endregion
2352
2357
  //#region src/core/version.ts
2353
- var ln = "2.15.4", un = {
2358
+ var un = "2.15.6", dn = {
2354
2359
  accent: "#E1B600",
2355
2360
  accentText: "#1B1C23",
2356
2361
  background: "#0e0f13",
@@ -2361,7 +2366,7 @@ var ln = "2.15.4", un = {
2361
2366
  border: "rgba(255, 255, 255, 0.1)",
2362
2367
  radius: "8px",
2363
2368
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2364
- }, dn = {
2369
+ }, fn = {
2365
2370
  accent: "--havik-accent",
2366
2371
  accentText: "--havik-accent-text",
2367
2372
  background: "--havik-bg",
@@ -2373,26 +2378,26 @@ var ln = "2.15.4", un = {
2373
2378
  radius: "--havik-radius",
2374
2379
  fontFamily: "--havik-font"
2375
2380
  };
2376
- function fn(e, t) {
2381
+ function pn(e, t) {
2377
2382
  let n = {
2378
- ...un,
2383
+ ...dn,
2379
2384
  ...t
2380
2385
  };
2381
- for (let t of Object.keys(dn)) e.style.setProperty(dn[t], n[t]);
2386
+ for (let t of Object.keys(fn)) e.style.setProperty(fn[t], n[t]);
2382
2387
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2383
2388
  }
2384
2389
  //#endregion
2385
2390
  //#region src/ui/styles.ts
2386
- var pn = "havik-player-styles", mn = "\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();
2387
- function hn(e = document, t) {
2388
- let n = e.querySelector(`style#${pn}`);
2391
+ var mn = "havik-player-styles", hn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
2392
+ function gn(e = document, t) {
2393
+ let n = e.querySelector(`style#${mn}`);
2389
2394
  if (n && (!t || Z.get(n) === t)) return;
2390
2395
  let r = e.createElement("style");
2391
- r.id = pn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = mn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2396
+ r.id = mn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = hn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2392
2397
  }
2393
2398
  //#endregion
2394
2399
  //#region src/ui/icons.ts
2395
- var gn = {
2400
+ var _n = {
2396
2401
  play: "<path d=\"M8 5v14l11-7z\"/>",
2397
2402
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2398
2403
  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\"/>",
@@ -2406,20 +2411,20 @@ var gn = {
2406
2411
  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\"/>"
2407
2412
  };
2408
2413
  function Q(e) {
2409
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${gn[e]}</svg>`;
2414
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${_n[e]}</svg>`;
2410
2415
  }
2411
2416
  //#endregion
2412
2417
  //#region src/ui/controls.ts
2413
- var _n = 3e3, vn = 250, yn = /* @__PURE__ */ new Set([
2418
+ var vn = 3e3, yn = 250, bn = /* @__PURE__ */ new Set([
2414
2419
  "GONE",
2415
2420
  "NOT_FOUND",
2416
2421
  "INVALID_URN",
2417
2422
  "UNAUTHORIZED"
2418
2423
  ]);
2419
- function bn(e) {
2420
- return new xn(e);
2424
+ function xn(e) {
2425
+ return new Sn(e);
2421
2426
  }
2422
- var xn = class {
2427
+ var Sn = class {
2423
2428
  root;
2424
2429
  video;
2425
2430
  player;
@@ -2465,7 +2470,7 @@ var xn = class {
2465
2470
  scrubbing = !1;
2466
2471
  offFns = [];
2467
2472
  constructor(e) {
2468
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? _n, 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, hn(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");
2473
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? vn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, gn(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2469
2474
  let t = (e, t, n) => {
2470
2475
  let r = this.doc.createElement(e);
2471
2476
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2551,7 +2556,7 @@ var xn = class {
2551
2556
  let t = this.surfaceWasHidden;
2552
2557
  this.tapTimer = setTimeout(() => {
2553
2558
  this.tapTimer = void 0, this.toggleBar(t);
2554
- }, vn);
2559
+ }, yn);
2555
2560
  }
2556
2561
  toggleBar(e) {
2557
2562
  e ? this.poke() : this.hideIfIdle();
@@ -2586,7 +2591,7 @@ var xn = class {
2586
2591
  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);
2587
2592
  } else {
2588
2593
  let r = this.doc.createElement("div");
2589
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !yn.has(this.lastError.code)) {
2594
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !bn.has(this.lastError.code)) {
2590
2595
  let e = this.doc.createElement("button");
2591
2596
  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);
2592
2597
  }
@@ -2627,7 +2632,7 @@ var xn = class {
2627
2632
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2628
2633
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2629
2634
  }
2630
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Sn(this.video.currentTime)} / ${Sn(this.video.duration)}`);
2635
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Cn(this.video.currentTime)} / ${Cn(this.video.duration)}`);
2631
2636
  }
2632
2637
  syncLive() {
2633
2638
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2677,17 +2682,17 @@ var xn = class {
2677
2682
  renderQualityMenu() {
2678
2683
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2679
2684
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2680
- for (let n of e) this.menu.append(this.menuItem(Cn(n), t === n.index, () => this.player.setQuality(n.index)));
2685
+ for (let n of e) this.menu.append(this.menuItem(wn(n), t === n.index, () => this.player.setQuality(n.index)));
2681
2686
  }
2682
2687
  renderAudioMenu() {
2683
2688
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2684
2689
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2685
- for (let t of e) this.menu.append(this.menuItem(wn(t), t.default, () => this.player.setAudioTrack(t.id)));
2690
+ for (let t of e) this.menu.append(this.menuItem(Tn(t), t.default, () => this.player.setAudioTrack(t.id)));
2686
2691
  }
2687
2692
  renderCcMenu() {
2688
2693
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2689
2694
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2690
- for (let t of e) this.menu.append(this.menuItem(Tn(t), !1, () => this.player.setTextTrack(t.id)));
2695
+ for (let t of e) this.menu.append(this.menuItem(En(t), !1, () => this.player.setTextTrack(t.id)));
2691
2696
  }
2692
2697
  onTracksChanged() {
2693
2698
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2707,11 +2712,11 @@ var xn = class {
2707
2712
  }
2708
2713
  async toggleFullscreen() {
2709
2714
  try {
2710
- S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
2715
+ C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
2711
2716
  } catch {}
2712
2717
  }
2713
2718
  syncFullscreen() {
2714
- let e = S(this.video, this.root);
2719
+ let e = C(this.video, this.root);
2715
2720
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2716
2721
  }
2717
2722
  poke() {
@@ -2788,41 +2793,41 @@ var xn = class {
2788
2793
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2789
2794
  }
2790
2795
  };
2791
- function Sn(e) {
2796
+ function Cn(e) {
2792
2797
  (!Number.isFinite(e) || e < 0) && (e = 0);
2793
2798
  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");
2794
2799
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2795
2800
  }
2796
- function Cn(e) {
2801
+ function wn(e) {
2797
2802
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2798
2803
  }
2799
- function wn(e) {
2804
+ function Tn(e) {
2800
2805
  return e.name || e.lang || `Track ${e.id}`;
2801
2806
  }
2802
- function Tn(e) {
2807
+ function En(e) {
2803
2808
  return e.name || e.lang || `Track ${e.id}`;
2804
2809
  }
2805
2810
  //#endregion
2806
2811
  //#region src/managed/index.ts
2807
- var En = 6e3, Dn = 45e3, On = 2e3, kn = 3, An = 2e3, jn = 48e4;
2808
- function Mn(e) {
2812
+ var Dn = 6e3, On = 45e3, kn = 2e3, An = 3, jn = 2e3, Mn = 48e4;
2813
+ function Nn(e) {
2809
2814
  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)})`);
2810
2815
  if (e.env !== void 0) return B(e.env);
2811
2816
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2812
2817
  return e.baseUrl;
2813
2818
  }
2814
- async function Nn(e) {
2819
+ async function Pn(e) {
2815
2820
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2816
- let t = Mn(e);
2821
+ let t = Nn(e);
2817
2822
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2818
2823
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2819
- let r = new Pn({
2824
+ let r = new Fn({
2820
2825
  ...e,
2821
2826
  baseUrl: t
2822
2827
  });
2823
2828
  return await r.start(), r;
2824
2829
  }
2825
- var Pn = class {
2830
+ var Fn = class {
2826
2831
  opts;
2827
2832
  abort = new AbortController();
2828
2833
  listeners = {};
@@ -2866,7 +2871,7 @@ var Pn = class {
2866
2871
  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");
2867
2872
  let e = ++this.loadGen, t = this.resolveOptions();
2868
2873
  try {
2869
- let n = await v(t);
2874
+ let n = await y(t);
2870
2875
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2871
2876
  let e = this._lastError;
2872
2877
  throw this.destroy(), e;
@@ -2889,11 +2894,11 @@ var Pn = class {
2889
2894
  };
2890
2895
  }
2891
2896
  beginArming(e, t, n = !1) {
2892
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2897
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
2893
2898
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2894
2899
  }
2895
2900
  beginArmingByPolling(e) {
2896
- y({
2901
+ b({
2897
2902
  ...this.resolveOptions(),
2898
2903
  signal: this.abort.signal,
2899
2904
  waitForLive: this.buildWaitConfig(e)
@@ -2910,7 +2915,7 @@ var Pn = class {
2910
2915
  setTimeout(() => {
2911
2916
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2912
2917
  phase: i ? "unavailable" : "tooEarly",
2913
- retryInMs: Dn,
2918
+ retryInMs: On,
2914
2919
  attempt: 1,
2915
2920
  elapsedMs: 0,
2916
2921
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2927,7 +2932,7 @@ var Pn = class {
2927
2932
  }
2928
2933
  }
2929
2934
  }, h = () => {
2930
- a || s || p() || (s = !0, y({
2935
+ a || s || p() || (s = !0, b({
2931
2936
  ...this.resolveOptions(),
2932
2937
  signal: c.signal,
2933
2938
  waitForLive: this.buildWaitConfig(e)
@@ -2935,7 +2940,7 @@ var Pn = class {
2935
2940
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
2936
2941
  }));
2937
2942
  }, g = () => {
2938
- a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2943
+ a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2939
2944
  if (!(a || p())) {
2940
2945
  if (e instanceof n && o(e.code)) {
2941
2946
  h();
@@ -2949,13 +2954,13 @@ var Pn = class {
2949
2954
  !a && !p() && h();
2950
2955
  }, e);
2951
2956
  };
2952
- _(En), this.armingSub = T({
2957
+ _(Dn), this.armingSub = E({
2953
2958
  eventsBaseUrl: t,
2954
2959
  matchUrn: this.opts.matchUrn,
2955
2960
  credential: this.opts.credential,
2956
- onAlive: () => _(Dn),
2961
+ onAlive: () => _(On),
2957
2962
  onState: (e) => {
2958
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * On);
2963
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kn);
2959
2964
  },
2960
2965
  onError: () => h()
2961
2966
  });
@@ -3000,19 +3005,19 @@ var Pn = class {
3000
3005
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3001
3006
  let i = e.analytics?.sid;
3002
3007
  if (!i) return;
3003
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = tn(this.opts.baseUrl, a, e.analytics?.endpoint);
3008
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = nn(this.opts.baseUrl, a, e.analytics?.endpoint);
3004
3009
  if (!o) {
3005
3010
  s && setTimeout(() => {
3006
3011
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3007
3012
  }, 0);
3008
3013
  return;
3009
3014
  }
3010
- let c = this.opts.video, l = new nn({
3015
+ let c = this.opts.video, l = new rn({
3011
3016
  endpoint: o,
3012
3017
  sid: i,
3013
3018
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3014
- sdkVersion: ln,
3015
- environment: sn(c),
3019
+ sdkVersion: un,
3020
+ environment: cn(c),
3016
3021
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3017
3022
  onIdle: () => this.onAnalyticsIdle(t),
3018
3023
  onBlocked: (e) => setTimeout(() => {
@@ -3033,7 +3038,7 @@ var Pn = class {
3033
3038
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3034
3039
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3035
3040
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3036
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), cn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3041
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ln().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3037
3042
  }
3038
3043
  currentPresentation() {
3039
3044
  let e = this.opts.video;
@@ -3048,7 +3053,7 @@ var Pn = class {
3048
3053
  video: this.opts.video,
3049
3054
  descriptor: e,
3050
3055
  credential: t,
3051
- deviceId: k(),
3056
+ deviceId: A(),
3052
3057
  userId: this.opts.userId,
3053
3058
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3054
3059
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -3059,9 +3064,9 @@ var Pn = class {
3059
3064
  emit: (e) => this.onEngineEvent(e)
3060
3065
  }, o = this.opts.engine ?? "auto";
3061
3066
  if (o === "native") return new K(a);
3062
- if (o === "hls") return new Lt(a);
3063
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
3064
- if (at()) return new Lt(a);
3067
+ if (o === "hls") return new Rt(a);
3068
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ye() && W(this.opts.video)) return new K(a);
3069
+ if (ot()) return new Rt(a);
3065
3070
  if (W(this.opts.video)) return new K(a);
3066
3071
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3067
3072
  }
@@ -3099,11 +3104,11 @@ var Pn = class {
3099
3104
  }
3100
3105
  startLiveState(e) {
3101
3106
  if (this.opts.liveStateEvents === !1) return;
3102
- let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
3107
+ let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3103
3108
  if (!t) return;
3104
3109
  this.closeLiveState();
3105
3110
  let r = 0, i = !1;
3106
- this.liveStateSub = T({
3111
+ this.liveStateSub = E({
3107
3112
  eventsBaseUrl: t,
3108
3113
  matchUrn: this.opts.matchUrn,
3109
3114
  credential: this.opts.credential,
@@ -3114,7 +3119,7 @@ var Pn = class {
3114
3119
  r = 0, i = !1;
3115
3120
  },
3116
3121
  onError: () => {
3117
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= kn && (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.`))));
3122
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= An && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
3118
3123
  }
3119
3124
  });
3120
3125
  }
@@ -3136,7 +3141,7 @@ var Pn = class {
3136
3141
  scheduleRejoin(e) {
3137
3142
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3138
3143
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3139
- }, Math.random() * On));
3144
+ }, Math.random() * kn));
3140
3145
  }
3141
3146
  cancelRejoin() {
3142
3147
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3160,7 +3165,7 @@ var Pn = class {
3160
3165
  }
3161
3166
  t.controls = !1;
3162
3167
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3163
- r && r.insertBefore(n, t), n.appendChild(t), fn(n, this.opts.theme), this.container = n, this.controlBar = bn({
3168
+ r && r.insertBefore(n, t), n.appendChild(t), pn(n, this.opts.theme), this.container = n, this.controlBar = xn({
3164
3169
  root: n,
3165
3170
  video: t,
3166
3171
  player: this,
@@ -3191,7 +3196,7 @@ var Pn = class {
3191
3196
  }
3192
3197
  startStats() {
3193
3198
  this.stopStats();
3194
- let e = Math.max(500, this.opts.statsIntervalMs ?? An);
3199
+ let e = Math.max(500, this.opts.statsIntervalMs ?? jn);
3195
3200
  this.statsTimer = setInterval(() => {
3196
3201
  if (!this.engine) return;
3197
3202
  let e = this.engine.getStats();
@@ -3203,7 +3208,7 @@ var Pn = class {
3203
3208
  }
3204
3209
  scheduleLicenseRefresh() {
3205
3210
  this.stopRefresh();
3206
- let e = this.opts.licenseRefreshMs ?? jn;
3211
+ let e = this.opts.licenseRefreshMs ?? Mn;
3207
3212
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3208
3213
  }
3209
3214
  stopRefresh() {
@@ -3212,7 +3217,7 @@ var Pn = class {
3212
3217
  async refreshLicense() {
3213
3218
  let e = this.engine;
3214
3219
  if (!this.destroyed && e) try {
3215
- let t = await v(this.resolveOptions());
3220
+ let t = await y(this.resolveOptions());
3216
3221
  if (this.destroyed || this.engine !== e) return;
3217
3222
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3218
3223
  (n || r) && (e.setLicenseUrls({
@@ -3287,10 +3292,10 @@ var Pn = class {
3287
3292
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3288
3293
  }
3289
3294
  async enterFullscreen() {
3290
- return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3295
+ return !this.destroyed && w(this.opts.video, this.container ?? void 0);
3291
3296
  }
3292
3297
  async exitFullscreen() {
3293
- await w(this.opts.video, this.container ?? void 0);
3298
+ await T(this.opts.video, this.container ?? void 0);
3294
3299
  }
3295
3300
  retry() {
3296
3301
  return this.reload();
@@ -3300,7 +3305,7 @@ var Pn = class {
3300
3305
  let e = ++this.loadGen;
3301
3306
  this.teardownPlayback();
3302
3307
  try {
3303
- let t = await y({
3308
+ let t = await b({
3304
3309
  ...this.resolveOptions(),
3305
3310
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3306
3311
  });
@@ -3358,7 +3363,7 @@ function $(e) {
3358
3363
  }
3359
3364
  //#endregion
3360
3365
  //#region src/embed/host.ts
3361
- function Fn(e) {
3366
+ function In(e) {
3362
3367
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3363
3368
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3364
3369
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3417,15 +3422,15 @@ function Fn(e) {
3417
3422
  }
3418
3423
  //#endregion
3419
3424
  //#region src/embed/page.ts
3420
- var In = /^[A-Za-z0-9:_.-]{1,128}$/;
3421
- function Ln(e) {
3425
+ var Ln = /^[A-Za-z0-9:_.-]{1,128}$/;
3426
+ function Rn(e) {
3422
3427
  if (typeof e == "boolean") return e;
3423
3428
  if (typeof e == "object" && e) {
3424
3429
  let t = e.endpoint;
3425
3430
  return typeof t == "string" ? { endpoint: t } : {};
3426
3431
  }
3427
3432
  }
3428
- function Rn() {
3433
+ function zn() {
3429
3434
  let e = window.HAVIK_EMBED_CONFIG;
3430
3435
  if (e) return {
3431
3436
  baseUrl: e.baseUrl ?? "",
@@ -3435,7 +3440,7 @@ function Rn() {
3435
3440
  autoplay: e.autoplay ?? !0,
3436
3441
  muted: e.muted ?? !0,
3437
3442
  waitForLive: e.waitForLive ?? !0,
3438
- analytics: Ln(e.analytics)
3443
+ analytics: Rn(e.analytics)
3439
3444
  };
3440
3445
  let t = new URLSearchParams(location.search);
3441
3446
  return {
@@ -3448,9 +3453,9 @@ function Rn() {
3448
3453
  waitForLive: !0
3449
3454
  };
3450
3455
  }
3451
- async function zn() {
3452
- let e = Rn();
3453
- Vn();
3456
+ async function Bn() {
3457
+ let e = zn();
3458
+ Hn();
3454
3459
  let t = document.createElement("video");
3455
3460
  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);
3456
3461
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3505,12 +3510,12 @@ async function zn() {
3505
3510
  code: e.code,
3506
3511
  message: e.message
3507
3512
  })), e.on("autoplayblocked", () => {
3508
- i({ type: "oddin:autoplayblocked" }), Bn(t, e);
3513
+ i({ type: "oddin:autoplayblocked" }), Vn(t, e);
3509
3514
  });
3510
3515
  }, s = async (r) => {
3511
3516
  a?.destroy(), a = null;
3512
3517
  try {
3513
- let n = await Nn({
3518
+ let n = await Pn({
3514
3519
  video: t,
3515
3520
  baseUrl: e.baseUrl,
3516
3521
  matchUrn: r,
@@ -3572,7 +3577,7 @@ async function zn() {
3572
3577
  a?.retry();
3573
3578
  break;
3574
3579
  case "oddin:load":
3575
- typeof e.matchUrn == "string" && In.test(e.matchUrn) && s(e.matchUrn);
3580
+ typeof e.matchUrn == "string" && Ln.test(e.matchUrn) && s(e.matchUrn);
3576
3581
  break;
3577
3582
  case "oddin:destroy": c();
3578
3583
  }
@@ -3584,18 +3589,18 @@ async function zn() {
3584
3589
  protocol: 1
3585
3590
  });
3586
3591
  }
3587
- function Bn(e, t) {
3592
+ function Vn(e, t) {
3588
3593
  if (document.getElementById("havik-tap")) return;
3589
3594
  let n = document.createElement("button");
3590
3595
  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", () => {
3591
3596
  n.remove(), t.play();
3592
3597
  }), document.body.appendChild(n);
3593
3598
  }
3594
- function Vn() {
3599
+ function Hn() {
3595
3600
  let e = document.createElement("style");
3596
3601
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3597
3602
  }
3598
3603
  //#endregion
3599
- export { un as ODDIN_THEME, n as PlaybackError, fn as applyTheme, B as baseUrlForEnv, zn as bootEmbed, Te as clearDeviceId, Nn 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, Fn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3604
+ export { dn as ODDIN_THEME, n as PlaybackError, pn as applyTheme, B as baseUrlForEnv, Bn as bootEmbed, we as clearDeviceId, Pn as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, In as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
3600
3605
 
3601
3606
  //# sourceMappingURL=index.js.map