@oddin-gg/havik-player 1.6.3 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -95,27 +95,27 @@ function g(e) {
95
95
  ceilMs: r,
96
96
  imminentMs: i,
97
97
  sanityFloorMs: a,
98
- kickoffMs: _(t.kickoffAt),
98
+ kickoffMs: ee(t.kickoffAt),
99
99
  jitter: t.jitter ?? !0,
100
100
  onState: t.onState
101
101
  };
102
102
  }
103
- function _(e) {
103
+ function ee(e) {
104
104
  if (e == null) return;
105
105
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
106
106
  let t = Date.parse(e);
107
107
  return Number.isFinite(t) ? t : void 0;
108
108
  }
109
- function ee(e, t, n) {
109
+ function te(e, t, n) {
110
110
  return Math.min(n, Math.max(t, e));
111
111
  }
112
- function te(e) {
112
+ function ne(e) {
113
113
  return Math.round(e * (1 + .15 * Math.random()));
114
114
  }
115
- function ne(e, t, n, r) {
115
+ function _(e, t, n, r) {
116
116
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
117
117
  if (a == null || a <= n.imminentMs) return {
118
- delay: ee(e ?? n.floorMs, o, n.ceilMs),
118
+ delay: te(e ?? n.floorMs, o, n.ceilMs),
119
119
  ttkMs: a
120
120
  };
121
121
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -147,8 +147,8 @@ async function v(e, n, r) {
147
147
  } catch (e) {
148
148
  if (!(e instanceof t) || !i(e.code)) throw e;
149
149
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
150
- let n = Date.now(), u = ne(e.retryAfterMs, n, a, l), d = u.ttkMs, f = u.delay;
151
- if (a.jitter && (f = te(f)), n + f > s) throw new t("TIMEOUT", e.httpStatus, `timed out after ${a.timeoutMs}ms waiting for the stream to go live`, {
150
+ let n = Date.now(), u = _(e.retryAfterMs, n, a, l), d = u.ttkMs, f = u.delay;
151
+ if (a.jitter && (f = ne(f)), n + f > s) throw new t("TIMEOUT", e.httpStatus, `timed out after ${a.timeoutMs}ms waiting for the stream to go live`, {
152
152
  retryAfterMs: e.retryAfterMs,
153
153
  cause: e
154
154
  });
@@ -171,7 +171,7 @@ async function y(e) {
171
171
  signal: e.signal
172
172
  });
173
173
  if (!n.ok) throw await ie(n);
174
- return oe(await n.json(), e.matchUrn);
174
+ return C(await n.json(), e.matchUrn);
175
175
  }
176
176
  function b(e) {
177
177
  let t = () => y(e);
@@ -193,7 +193,7 @@ async function ie(e) {
193
193
  liveStartsAtMs: c
194
194
  });
195
195
  }
196
- var ae = /* @__PURE__ */ new Set([
196
+ var x = /* @__PURE__ */ new Set([
197
197
  "matchUrn",
198
198
  "protocol",
199
199
  "drmEnabled",
@@ -203,7 +203,7 @@ var ae = /* @__PURE__ */ new Set([
203
203
  "liveStartsAt",
204
204
  "expiresAt"
205
205
  ]);
206
- function x(e, n) {
206
+ function S(e, n) {
207
207
  let r;
208
208
  try {
209
209
  r = new URL(n);
@@ -213,29 +213,29 @@ function x(e, n) {
213
213
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new t("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
214
214
  return n;
215
215
  }
216
- function oe(e, n) {
216
+ function C(e, n) {
217
217
  if (!e.manifestUrl) throw new t("INTERNAL", 0, "playback response is missing manifestUrl");
218
218
  let r = e.drmEnabled ?? !!e.drm, i = {
219
219
  matchUrn: e.matchUrn ?? n,
220
220
  protocol: "hls",
221
221
  drmEnabled: r,
222
- manifestUrl: x("manifestUrl", e.manifestUrl),
222
+ manifestUrl: S("manifestUrl", e.manifestUrl),
223
223
  serverTime: e.serverTime ?? ""
224
224
  };
225
225
  if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), r && e.drm) {
226
226
  let t = {};
227
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
228
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
229
- certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
227
+ e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: S("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
228
+ licenseUrl: S("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
229
+ certificateUrl: S("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
230
230
  }), (t.widevine || t.fairplay) && (i.drm = t);
231
231
  }
232
232
  let a = {};
233
- for (let [t, n] of Object.entries(e)) ae.has(t) || (a[t] = n);
233
+ for (let [t, n] of Object.entries(e)) x.has(t) || (a[t] = n);
234
234
  return Object.keys(a).length > 0 && (i.extensions = a), i;
235
235
  }
236
236
  //#endregion
237
237
  //#region src/core/catalog.ts
238
- async function se(e) {
238
+ async function w(e) {
239
239
  let r = new URLSearchParams();
240
240
  e.status && r.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && r.set("sport", e.sport);
241
241
  let i = r.toString(), a = o(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), s = new Headers();
@@ -252,12 +252,12 @@ async function se(e) {
252
252
  };
253
253
  if (!l.ok) throw new t(n(l.status), l.status, `catalog request failed (HTTP ${l.status})`);
254
254
  return {
255
- tournaments: ce(await l.json()),
255
+ tournaments: ae(await l.json()),
256
256
  etag: l.headers.get("etag") ?? void 0,
257
257
  notModified: !1
258
258
  };
259
259
  }
260
- function ce(e) {
260
+ function ae(e) {
261
261
  return (e.tournaments ?? []).map((e) => {
262
262
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
263
263
  return {
@@ -277,7 +277,7 @@ function ce(e) {
277
277
  };
278
278
  });
279
279
  }
280
- async function le(e) {
280
+ async function oe(e) {
281
281
  let r = o(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
282
282
  e.etag && i.set("If-None-Match", e.etag);
283
283
  let a = await c(r, {
@@ -296,13 +296,13 @@ async function le(e) {
296
296
  };
297
297
  if (!a.ok) throw new t(n(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
298
298
  return {
299
- tournament: S(await a.json()),
299
+ tournament: se(await a.json()),
300
300
  etag: a.headers.get("etag") ?? void 0,
301
301
  notModified: !1,
302
302
  notFound: !1
303
303
  };
304
304
  }
305
- function S(e) {
305
+ function se(e) {
306
306
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
307
307
  return {
308
308
  urn: t,
@@ -320,12 +320,12 @@ function S(e) {
320
320
  }))
321
321
  };
322
322
  }
323
- function C(e) {
323
+ function ce(e) {
324
324
  return e.tournaments.flatMap((e) => e.matches);
325
325
  }
326
326
  //#endregion
327
327
  //#region src/core/poll.ts
328
- function w(e) {
328
+ function le(e) {
329
329
  let r = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, s, l, u = !1, d = () => {
330
330
  u || (a = setTimeout(f, r));
331
331
  }, f = async () => {
@@ -480,11 +480,11 @@ function fe(e, t, n = {}) {
480
480
  }
481
481
  //#endregion
482
482
  //#region src/core/drm/support.ts
483
- var A = 5e3, j = "video/mp4; codecs=\"avc1.42E01E\"", M = "audio/mp4; codecs=\"mp4a.40.2\"", N = {
483
+ var pe = 5e3, A = "video/mp4; codecs=\"avc1.42E01E\"", j = "audio/mp4; codecs=\"mp4a.40.2\"", M = {
484
484
  widevine: ["com.widevine.alpha"],
485
485
  fairplay: ["com.apple.fps"]
486
486
  };
487
- function P(e) {
487
+ function N(e) {
488
488
  return e === "fairplay" ? [{
489
489
  initDataTypes: [
490
490
  "sinf",
@@ -492,30 +492,30 @@ function P(e) {
492
492
  "cenc"
493
493
  ],
494
494
  videoCapabilities: [{
495
- contentType: j,
495
+ contentType: A,
496
496
  robustness: "",
497
497
  encryptionScheme: "cbcs"
498
498
  }],
499
499
  audioCapabilities: [{
500
- contentType: M,
500
+ contentType: j,
501
501
  robustness: "",
502
502
  encryptionScheme: "cbcs"
503
503
  }]
504
504
  }] : [{
505
505
  initDataTypes: ["cenc"],
506
506
  videoCapabilities: [{
507
- contentType: j,
507
+ contentType: A,
508
508
  robustness: "SW_SECURE_DECODE",
509
509
  encryptionScheme: "cbcs"
510
510
  }],
511
511
  audioCapabilities: [{
512
- contentType: M,
512
+ contentType: j,
513
513
  robustness: "SW_SECURE_CRYPTO",
514
514
  encryptionScheme: "cbcs"
515
515
  }]
516
516
  }];
517
517
  }
518
- function F(e, t) {
518
+ function P(e, t) {
519
519
  return new Promise((n, r) => {
520
520
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
521
521
  e.then((e) => {
@@ -525,8 +525,8 @@ function F(e, t) {
525
525
  });
526
526
  });
527
527
  }
528
- async function I(e = {}) {
529
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? A, r = {};
528
+ async function F(e = {}) {
529
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? pe, r = {};
530
530
  if (typeof window < "u" && window.isSecureContext === !1) return {
531
531
  verdict: "insecure-context",
532
532
  detail: r
@@ -538,7 +538,7 @@ async function I(e = {}) {
538
538
  };
539
539
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
540
540
  for (let e of t) {
541
- let t = N[e];
541
+ let t = M[e];
542
542
  if (!t) {
543
543
  r[e] = "unknown system";
544
544
  continue;
@@ -549,7 +549,7 @@ async function I(e = {}) {
549
549
  break;
550
550
  }
551
551
  try {
552
- return await F((await F(i(n, P(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
552
+ return await P((await P(i(n, N(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
553
553
  verdict: "supported",
554
554
  system: e,
555
555
  detail: r
@@ -573,17 +573,17 @@ async function I(e = {}) {
573
573
  }
574
574
  //#endregion
575
575
  //#region src/core/manifest.ts
576
- var L = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
577
- function R(e) {
578
- return L.test(e);
576
+ var I = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
577
+ function L(e) {
578
+ return I.test(e);
579
579
  }
580
580
  //#endregion
581
581
  //#region src/core/stats.ts
582
- var z = { droppedFrames: 0 };
583
- function B(e) {
582
+ var R = { droppedFrames: 0 };
583
+ function z(e) {
584
584
  return e.getVideoPlaybackQuality?.()?.droppedVideoFrames ?? 0;
585
585
  }
586
- function V(e, t) {
586
+ function B(e, t) {
587
587
  let n = [
588
588
  ["playing", () => t("playing")],
589
589
  ["waiting", () => t("buffering")],
@@ -600,14 +600,27 @@ function V(e, t) {
600
600
  }
601
601
  //#endregion
602
602
  //#region src/core/engine/native.ts
603
- function H(e) {
603
+ function me(e) {
604
+ try {
605
+ let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
606
+ return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
607
+ } catch {
608
+ return;
609
+ }
610
+ }
611
+ function V(e) {
604
612
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
605
613
  }
606
- var U = class {
614
+ var H = class {
607
615
  name = "native";
608
616
  deps;
609
617
  onLoaded;
610
618
  onError;
619
+ onEncrypted;
620
+ fairplayLicenseUrl;
621
+ keySession = null;
622
+ fairplayArmed = !1;
623
+ fairplayKeyIV;
611
624
  constructor(e) {
612
625
  this.deps = e;
613
626
  }
@@ -622,11 +635,7 @@ var U = class {
622
635
  });
623
636
  return;
624
637
  }
625
- r({
626
- type: "error",
627
- error: new t("INTERNAL", 0, "the native HLS fallback engine does not drive FairPlay EME; relying on OS-trusted passthrough"),
628
- fatal: !1
629
- });
638
+ this.armFairPlay();
630
639
  }
631
640
  this.onLoaded = () => r({ type: "ready" }), this.onError = () => r({
632
641
  type: "error",
@@ -634,7 +643,65 @@ var U = class {
634
643
  fatal: !0
635
644
  }), e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = n.manifestUrl, e.load();
636
645
  }
637
- setLicenseUrls(e) {}
646
+ armFairPlay() {
647
+ let { video: e, descriptor: n, credential: r, deviceId: i, userId: a, emit: o } = this.deps, s = n.drm?.fairplay;
648
+ if (!s) return;
649
+ this.fairplayLicenseUrl = s.licenseUrl;
650
+ let c = (e, n, r) => o({
651
+ type: "error",
652
+ error: new t(n === 403 ? "FORBIDDEN" : "INTERNAL", n, e),
653
+ fatal: r
654
+ });
655
+ this.onEncrypted = (t) => {
656
+ let o = t;
657
+ !o.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = me(o.initData), (async () => {
658
+ try {
659
+ let t = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
660
+ initDataTypes: [o.initDataType],
661
+ videoCapabilities: [{
662
+ contentType: "application/vnd.apple.mpegurl",
663
+ robustness: ""
664
+ }],
665
+ distinctiveIdentifier: "not-allowed",
666
+ persistentState: "not-allowed",
667
+ sessionTypes: ["temporary"]
668
+ }])).createMediaKeys(), l = await fetch(s.certificateUrl, { headers: { "x-api-key": r.apiKey } });
669
+ if (!l.ok) throw Error(`certificate ${l.status}`);
670
+ await t.setServerCertificate(await l.arrayBuffer()), await e.setMediaKeys(t);
671
+ let u = t.createSession();
672
+ this.keySession = u, u.addEventListener("message", (e) => {
673
+ (async () => {
674
+ try {
675
+ let t = await fetch(this.fairplayLicenseUrl ?? s.licenseUrl, {
676
+ method: "POST",
677
+ body: e.message,
678
+ headers: {
679
+ "x-api-key": r.apiKey,
680
+ "X-Match-Urn": n.matchUrn,
681
+ "X-Device-Id": i,
682
+ ...a ? { "X-User-Id": a } : {},
683
+ ...this.fairplayKeyIV ? { "X-Key-Iv": this.fairplayKeyIV } : {}
684
+ }
685
+ });
686
+ if (!t.ok) {
687
+ c(`FairPlay license request failed: ${t.status}`, t.status, !0);
688
+ return;
689
+ }
690
+ await u.update(new Uint8Array(await t.arrayBuffer()));
691
+ } catch (e) {
692
+ c(`FairPlay license request failed: ${String(e)}`, 0, !0);
693
+ }
694
+ })();
695
+ }), await u.generateRequest(o.initDataType, o.initData);
696
+ } catch (e) {
697
+ this.fairplayArmed = !1, c(`FairPlay key session failed: ${String(e)}`, 0, !0);
698
+ }
699
+ })());
700
+ }, e.addEventListener("encrypted", this.onEncrypted);
701
+ }
702
+ setLicenseUrls(e) {
703
+ e.fairplay && (this.fairplayLicenseUrl = e.fairplay);
704
+ }
638
705
  getQualityLevels() {
639
706
  return [];
640
707
  }
@@ -679,7 +746,7 @@ var U = class {
679
746
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
680
747
  }
681
748
  getStats() {
682
- let e = this.deps.video, t = { droppedFrames: B(e) };
749
+ let e = this.deps.video, t = { droppedFrames: z(e) };
683
750
  return e.duration === Infinity && (t.isLive = !0, e.seekable.length > 0 && (t.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), t;
684
751
  }
685
752
  stop() {
@@ -689,7 +756,7 @@ var U = class {
689
756
  }
690
757
  destroy() {
691
758
  let { video: e } = this.deps;
692
- this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError);
759
+ this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
693
760
  try {
694
761
  e.pause();
695
762
  } catch {}
@@ -701,30 +768,28 @@ var U = class {
701
768
  };
702
769
  //#endregion
703
770
  //#region src/core/engine/hls.ts
704
- function pe() {
771
+ function he() {
705
772
  return e.isSupported();
706
773
  }
707
- var me = 3, he = 5, ge = 3, _e = 3e4, ve = 12e3, ye = 3e3, be = 6e3, xe = 2, Se = 9, Ce = .5;
708
- function W(e) {
774
+ var ge = 3, _e = 5, ve = 3, ye = 3e4, be = 12e3, xe = 3e3, Se = 6e3, Ce = 2, we = 9, Te = .5;
775
+ function Ee(e) {
709
776
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
710
777
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
711
778
  return;
712
779
  }
713
- e.liveSyncDuration ??= xe;
714
- let t = Math.max(12, e.liveSyncDuration + Se);
715
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), we(e, e.liveSyncDuration);
780
+ e.liveSyncDuration ??= Ce;
781
+ let t = Math.max(12, e.liveSyncDuration + we);
782
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), De(e, e.liveSyncDuration);
716
783
  }
717
- function we(e, t) {
784
+ function De(e, t) {
718
785
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
719
786
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
720
787
  }
721
- var Te = class {
788
+ var U = class {
722
789
  name = "hls";
723
790
  hls = null;
724
791
  deps;
725
792
  licenseUrl;
726
- fairplayLicenseUrl;
727
- fairplayCertUrl;
728
793
  detectedLowLatency = !1;
729
794
  mediaRecoveries = 0;
730
795
  networkRecoveries = 0;
@@ -743,14 +808,14 @@ var Te = class {
743
808
  savedLiveMaxLatency;
744
809
  savedMaxSyncRate;
745
810
  constructor(e) {
746
- this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.fairplayLicenseUrl = e.descriptor.drm?.fairplay?.licenseUrl, this.fairplayCertUrl = e.descriptor.drm?.fairplay?.certificateUrl;
811
+ this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl;
747
812
  }
748
813
  async load() {
749
- let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a = H(r), o = !!e.drm?.widevine?.licenseUrl && !a, s = !!(e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && a);
750
- if (e.drmEnabled && !o && !s) {
814
+ let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a = V(r), o = !!e.drm?.widevine?.licenseUrl && !a;
815
+ if (e.drmEnabled && !o) {
751
816
  i({
752
817
  type: "error",
753
- error: new t("INTERNAL", 0, "DRM is required but none of the stream’s key systems is usable on this platform (WebKit takes FairPlay only; other browsers take Widevine only)"),
818
+ error: new t("INTERNAL", 0, e.drm?.fairplay?.licenseUrl && a ? "FairPlay cannot be played on the hls.js engine (WebKit binds keys via the media sinf box); use engine \"auto\" or \"native\"" : "DRM is required but none of the stream’s key systems is usable on this platform (WebKit takes FairPlay only; other browsers take Widevine only)"),
754
819
  fatal: !0
755
820
  });
756
821
  return;
@@ -770,10 +835,10 @@ var Te = class {
770
835
  let t = e.liveSyncPosition;
771
836
  if (typeof t != "number" || !Number.isFinite(t)) return;
772
837
  let { video: n } = this.deps;
773
- n.currentTime <= t + Ce || (n.currentTime = t);
838
+ n.currentTime <= t + Te || (n.currentTime = t);
774
839
  }
775
840
  startHls() {
776
- let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = !!(this.fairplayLicenseUrl && this.fairplayCertUrl && H(t)), f = {
841
+ let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
777
842
  debug: s === !0,
778
843
  enableWorker: !o,
779
844
  lowLatencyMode: o,
@@ -784,84 +849,44 @@ var Te = class {
784
849
  capLevelToPlayerSize: !0,
785
850
  ...u ? {
786
851
  emeEnabled: !0,
787
- drmSystems: {
788
- ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {},
789
- ...d ? { "com.apple.fps": {
790
- licenseUrl: this.fairplayLicenseUrl,
791
- serverCertificateUrl: this.fairplayCertUrl,
792
- generateRequest(e, t, n) {
793
- if (t) return {
794
- initDataType: e,
795
- initData: t
796
- };
797
- let r = n.decryptdata?.uri;
798
- return r?.startsWith("skd://") ? {
799
- initDataType: "skd",
800
- initData: new TextEncoder().encode(r).buffer
801
- } : {
802
- initDataType: e,
803
- initData: t
804
- };
805
- }
806
- } } : {}
807
- },
808
- drmSystemOptions: d ? {
809
- videoEncryptionScheme: "cbcs",
810
- audioEncryptionScheme: "cbcs"
811
- } : {
852
+ drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
853
+ drmSystemOptions: {
812
854
  videoRobustness: "SW_SECURE_DECODE",
813
855
  audioRobustness: "SW_SECURE_CRYPTO",
814
856
  videoEncryptionScheme: "cbcs",
815
857
  audioEncryptionScheme: "cbcs"
816
858
  },
817
- ...d ? { requestMediaKeySystemAccessFunc: (e, t) => {
818
- let n = e === "com.apple.fps" ? t.map((e) => ({
819
- ...e,
820
- initDataTypes: [.../* @__PURE__ */ new Set([...e.initDataTypes ?? [], "skd"])]
821
- })) : t;
822
- return navigator.requestMediaKeySystemAccess(e, n);
823
- } } : {},
824
859
  licenseXhrSetup: (e, t) => {
825
- let o = t.includes("/license/fairplay") ? this.fairplayLicenseUrl ?? t : this.licenseUrl ?? t;
826
- e.open("POST", o, !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);
860
+ 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);
827
861
  }
828
862
  } : {},
829
863
  ...c
830
864
  };
831
- if (d) {
832
- let e = f.xhrSetup, t = () => this.fairplayCertUrl;
833
- f.xhrSetup = (n, i) => {
834
- let a = e?.(n, i), o = () => {
835
- i === t() && (n.readyState === XMLHttpRequest.UNSENT && n.open("GET", i, !0), n.setRequestHeader("x-api-key", r.apiKey));
836
- };
837
- return a && typeof a.then == "function" ? a.then(() => o()) : (o(), a);
838
- };
839
- }
840
- W(f);
841
- let p = new e(f);
842
- this.hls = p, p.on(e.Events.MANIFEST_PARSED, () => {
865
+ Ee(d);
866
+ let f = new e(d);
867
+ this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
843
868
  this.mediaRecoveries = 0, this.networkRecoveries = 0, l({ type: "ready" });
844
- }), p.on(e.Events.FRAG_BUFFERED, () => {
869
+ }), f.on(e.Events.FRAG_BUFFERED, () => {
845
870
  (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
846
871
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.recoveryResetTimer = null;
847
- }, _e));
848
- }), p.on(e.Events.LEVEL_LOADED, (e, t) => {
872
+ }, ye));
873
+ }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
849
874
  if (this.detectedLowLatency) return;
850
875
  let n = t.details;
851
876
  (n?.partList?.length || (n?.partTarget ?? 0) > 0) && (this.detectedLowLatency = !0, l({
852
877
  type: "lowLatencyDetected",
853
878
  value: !0
854
879
  }));
855
- }), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() => this.checkEndStale(), ye), p.on(e.Events.LEVEL_SWITCHED, (e, t) => l({
880
+ }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() => this.checkEndStale(), xe), f.on(e.Events.LEVEL_SWITCHED, (e, t) => l({
856
881
  type: "qualitychange",
857
882
  index: t.level
858
- })), p.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
883
+ })), f.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
859
884
  type: "audiotrackchange",
860
885
  id: t.id
861
- })), p.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
886
+ })), f.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
862
887
  type: "texttrackchange",
863
888
  id: t.id
864
- })), p.on(e.Events.ERROR, (e, t) => this.onError(t)), p.loadSource(n.manifestUrl), p.attachMedia(t);
889
+ })), f.on(e.Events.ERROR, (e, t) => this.onError(t)), f.loadSource(n.manifestUrl), f.attachMedia(t);
865
890
  }
866
891
  getQualityLevels() {
867
892
  return this.hls ? this.hls.levels.map((e, t) => ({
@@ -917,11 +942,11 @@ var Te = class {
917
942
  e && typeof e.liveSyncPosition == "number" && (this.deps.video.currentTime = e.liveSyncPosition);
918
943
  }
919
944
  setLicenseUrls(e) {
920
- e.widevine && (this.licenseUrl = e.widevine), e.fairplay && (this.fairplayLicenseUrl = e.fairplay);
945
+ e.widevine && (this.licenseUrl = e.widevine);
921
946
  }
922
947
  getStats() {
923
948
  let e = this.hls, t = {
924
- droppedFrames: B(this.deps.video),
949
+ droppedFrames: z(this.deps.video),
925
950
  lowLatency: this.detectedLowLatency
926
951
  };
927
952
  if (e) {
@@ -950,7 +975,7 @@ var Te = class {
950
975
  return;
951
976
  }
952
977
  let e = Date.now() - this.lastAdvanceMs;
953
- !this.chaseSuspended && e > be && this.suspendChasing(), e > ve && this.emitEnded("stalled");
978
+ !this.chaseSuspended && e > Se && this.suspendChasing(), e > be && this.emitEnded("stalled");
954
979
  }
955
980
  suspendChasing() {
956
981
  let e = this.hls;
@@ -992,7 +1017,7 @@ var Te = class {
992
1017
  scheduleLicenseRetry(t) {
993
1018
  if (!(t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED || t.details === e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED)) return !1;
994
1019
  let n = t.response?.code ?? 0;
995
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ge) return !1;
1020
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ve) return !1;
996
1021
  this.licenseRecoveries += 1;
997
1022
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
998
1023
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1020,7 +1045,7 @@ var Te = class {
1020
1045
  return;
1021
1046
  }
1022
1047
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1023
- if (this.networkRecoveries < he) {
1048
+ if (this.networkRecoveries < _e) {
1024
1049
  this.networkRecoveries += 1;
1025
1050
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1026
1051
  this.networkRetryTimer = setTimeout(() => {
@@ -1036,7 +1061,7 @@ var Te = class {
1036
1061
  return;
1037
1062
  }
1038
1063
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1039
- if (this.mediaRecoveries < me) {
1064
+ if (this.mediaRecoveries < ge) {
1040
1065
  this.mediaRecoveries += 1, n.recoverMediaError();
1041
1066
  return;
1042
1067
  }
@@ -1058,7 +1083,7 @@ var Te = class {
1058
1083
  let r = e.response?.code ?? 0, i = e.details ?? e.type, a = e.reason ?? e.error?.message ?? "";
1059
1084
  return new t(r === 401 ? "UNAUTHORIZED" : r === 403 || n === "DRM" ? "FORBIDDEN" : "INTERNAL", r, `${n} error: ${i}${a ? ` (${a})` : ""}`);
1060
1085
  }
1061
- }, G = {
1086
+ }, W = {
1062
1087
  accent: "#E1B600",
1063
1088
  accentText: "#1B1C23",
1064
1089
  background: "#0e0f13",
@@ -1069,7 +1094,7 @@ var Te = class {
1069
1094
  border: "rgba(255, 255, 255, 0.1)",
1070
1095
  radius: "8px",
1071
1096
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1072
- }, K = {
1097
+ }, G = {
1073
1098
  accent: "--havik-accent",
1074
1099
  accentText: "--havik-accent-text",
1075
1100
  background: "--havik-bg",
@@ -1081,25 +1106,25 @@ var Te = class {
1081
1106
  radius: "--havik-radius",
1082
1107
  fontFamily: "--havik-font"
1083
1108
  };
1084
- function q(e, t) {
1109
+ function K(e, t) {
1085
1110
  let n = {
1086
- ...G,
1111
+ ...W,
1087
1112
  ...t
1088
1113
  };
1089
- for (let t of Object.keys(K)) e.style.setProperty(K[t], n[t]);
1114
+ for (let t of Object.keys(G)) e.style.setProperty(G[t], n[t]);
1090
1115
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1091
1116
  }
1092
1117
  //#endregion
1093
1118
  //#region src/ui/styles.ts
1094
- var J = "havik-player-styles", Ee = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\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.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;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";
1095
- function De(e = document) {
1096
- if (e.getElementById(J)) return;
1119
+ var q = "havik-player-styles", Oe = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\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.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;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";
1120
+ function ke(e = document) {
1121
+ if (e.getElementById(q)) return;
1097
1122
  let t = e.createElement("style");
1098
- t.id = J, t.textContent = Ee, e.head.appendChild(t);
1123
+ t.id = q, t.textContent = Oe, e.head.appendChild(t);
1099
1124
  }
1100
1125
  //#endregion
1101
1126
  //#region src/ui/icons.ts
1102
- var Oe = {
1127
+ var Ae = {
1103
1128
  play: "<path d=\"M8 5v14l11-7z\"/>",
1104
1129
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1105
1130
  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\"/>",
@@ -1112,21 +1137,21 @@ var Oe = {
1112
1137
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
1113
1138
  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\"/>"
1114
1139
  };
1115
- function Y(e) {
1116
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Oe[e]}</svg>`;
1140
+ function J(e) {
1141
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ae[e]}</svg>`;
1117
1142
  }
1118
1143
  //#endregion
1119
1144
  //#region src/ui/controls.ts
1120
- var ke = 3e3, Ae = /* @__PURE__ */ new Set([
1145
+ var je = 3e3, Me = /* @__PURE__ */ new Set([
1121
1146
  "GONE",
1122
1147
  "NOT_FOUND",
1123
1148
  "INVALID_URN",
1124
1149
  "UNAUTHORIZED"
1125
1150
  ]);
1126
- function je(e) {
1127
- return new Me(e);
1151
+ function Ne(e) {
1152
+ return new Pe(e);
1128
1153
  }
1129
- var Me = class {
1154
+ var Pe = class {
1130
1155
  root;
1131
1156
  video;
1132
1157
  player;
@@ -1166,7 +1191,7 @@ var Me = class {
1166
1191
  scrubbing = !1;
1167
1192
  offFns = [];
1168
1193
  constructor(e) {
1169
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ke, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, De(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1194
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? je, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, ke(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
1170
1195
  let t = (e, t, n) => {
1171
1196
  let r = this.doc.createElement(e);
1172
1197
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1177,12 +1202,12 @@ var Me = class {
1177
1202
  "aria-label": r,
1178
1203
  title: r
1179
1204
  });
1180
- return i.innerHTML = Y(n), i;
1205
+ return i.innerHTML = J(n), i;
1181
1206
  };
1182
1207
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
1183
1208
  type: "button",
1184
1209
  "aria-label": "Play"
1185
- }), this.center.innerHTML = Y("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
1210
+ }), this.center.innerHTML = J("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
1186
1211
  role: "slider",
1187
1212
  "aria-label": "Seek",
1188
1213
  "aria-valuemin": "0",
@@ -1200,7 +1225,7 @@ var Me = class {
1200
1225
  "aria-label": "Volume"
1201
1226
  });
1202
1227
  let a = t("div", "havik-vol");
1203
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Y("liveDot");
1228
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = J("liveDot");
1204
1229
  let o = this.doc.createElement("span");
1205
1230
  o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
1206
1231
  let s = t("div", "havik-spacer");
@@ -1250,12 +1275,12 @@ var Me = class {
1250
1275
  }
1251
1276
  if (e === "preplay") {
1252
1277
  let e = this.doc.createElement("button");
1253
- e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Y("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
1278
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = J("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
1254
1279
  } else {
1255
1280
  let n = this.doc.createElement("div");
1256
- if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !Ae.has(this.lastError.code)) {
1281
+ if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !Me.has(this.lastError.code)) {
1257
1282
  let e = this.doc.createElement("button");
1258
- e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Y("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
1283
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${J("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
1259
1284
  }
1260
1285
  }
1261
1286
  this.root.append(t), this.statusBox = t, this.show();
@@ -1289,7 +1314,7 @@ var Me = class {
1289
1314
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
1290
1315
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
1291
1316
  }
1292
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${X(this.video.currentTime)} / ${X(this.video.duration)}`);
1317
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Y(this.video.currentTime)} / ${Y(this.video.duration)}`);
1293
1318
  }
1294
1319
  syncLive() {
1295
1320
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -1339,17 +1364,17 @@ var Me = class {
1339
1364
  renderQualityMenu() {
1340
1365
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
1341
1366
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
1342
- for (let n of e) this.menu.append(this.menuItem(Ne(n), t === n.index, () => this.player.setQuality(n.index)));
1367
+ for (let n of e) this.menu.append(this.menuItem(Fe(n), t === n.index, () => this.player.setQuality(n.index)));
1343
1368
  }
1344
1369
  renderAudioMenu() {
1345
1370
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
1346
1371
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
1347
- for (let t of e) this.menu.append(this.menuItem(Pe(t), t.default, () => this.player.setAudioTrack(t.id)));
1372
+ for (let t of e) this.menu.append(this.menuItem(Ie(t), t.default, () => this.player.setAudioTrack(t.id)));
1348
1373
  }
1349
1374
  renderCcMenu() {
1350
1375
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
1351
1376
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
1352
- for (let t of e) this.menu.append(this.menuItem(Fe(t), !1, () => this.player.setTextTrack(t.id)));
1377
+ for (let t of e) this.menu.append(this.menuItem(Le(t), !1, () => this.player.setTextTrack(t.id)));
1353
1378
  }
1354
1379
  onTracksChanged() {
1355
1380
  this.openMenu && this.renderMenu(this.openMenu);
@@ -1433,7 +1458,7 @@ var Me = class {
1433
1458
  }
1434
1459
  }
1435
1460
  setIcon(e, t) {
1436
- e.innerHTML = Y(t);
1461
+ e.innerHTML = J(t);
1437
1462
  }
1438
1463
  destroy() {
1439
1464
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -1450,32 +1475,32 @@ var Me = class {
1450
1475
  this.root.classList.remove("havik-player", "havik-hide");
1451
1476
  }
1452
1477
  };
1453
- function X(e) {
1478
+ function Y(e) {
1454
1479
  (!Number.isFinite(e) || e < 0) && (e = 0);
1455
1480
  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");
1456
1481
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
1457
1482
  }
1458
- function Ne(e) {
1483
+ function Fe(e) {
1459
1484
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
1460
1485
  }
1461
- function Pe(e) {
1486
+ function Ie(e) {
1462
1487
  return e.name || e.lang || `Track ${e.id}`;
1463
1488
  }
1464
- function Fe(e) {
1489
+ function Le(e) {
1465
1490
  return e.name || e.lang || `Track ${e.id}`;
1466
1491
  }
1467
1492
  //#endregion
1468
1493
  //#region src/managed/index.ts
1469
- var Ie = 6e3, Z = 45e3, Le = 2e3, Re = 3, ze = 2e3, Be = 480 * 1e3;
1494
+ var Re = 6e3, X = 45e3, ze = 2e3, Z = 3, Be = 2e3, Ve = 480 * 1e3;
1470
1495
  async function Q(e) {
1471
1496
  if (!e.video || typeof e.video.play != "function") throw new t("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
1472
1497
  if (!e.baseUrl) throw new t("INTERNAL", 0, "createPlayer: baseUrl is required");
1473
1498
  if (!e.matchUrn) throw new t("INVALID_URN", 0, "createPlayer: matchUrn is required");
1474
1499
  if (!e.credential) throw new t("INTERNAL", 0, "createPlayer: credential is required");
1475
- let n = new Ve(e);
1500
+ let n = new He(e);
1476
1501
  return await n.start(), n;
1477
1502
  }
1478
- var Ve = class {
1503
+ var He = class {
1479
1504
  opts;
1480
1505
  abort = new AbortController();
1481
1506
  listeners = {};
@@ -1552,7 +1577,7 @@ var Ve = class {
1552
1577
  setTimeout(() => {
1553
1578
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
1554
1579
  phase: "tooEarly",
1555
- retryInMs: Z,
1580
+ retryInMs: X,
1556
1581
  attempt: 1,
1557
1582
  elapsedMs: 0,
1558
1583
  ...d !== void 0 && d > Date.now() ? { ttkMs: d - Date.now() } : {}
@@ -1585,13 +1610,13 @@ var Ve = class {
1585
1610
  !a && !f() && m();
1586
1611
  }, e);
1587
1612
  };
1588
- g(Ie), this.armingSub = T({
1613
+ g(Re), this.armingSub = T({
1589
1614
  eventsBaseUrl: n,
1590
1615
  matchUrn: this.opts.matchUrn,
1591
1616
  credential: this.opts.credential,
1592
- onAlive: () => g(Z),
1617
+ onAlive: () => g(X),
1593
1618
  onState: (e) => {
1594
- a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() * Le);
1619
+ a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() * ze);
1595
1620
  },
1596
1621
  onError: () => m()
1597
1622
  });
@@ -1614,7 +1639,7 @@ var Ve = class {
1614
1639
  let n = await a(this.opts.credential);
1615
1640
  if (this.destroyed || t !== this.loadGen) return;
1616
1641
  this.setState("loading");
1617
- let r = this.createEngine(e, n), i = V(this.opts.video, (e) => {
1642
+ let r = this.createEngine(e, n), i = B(this.opts.video, (e) => {
1618
1643
  this._state === "ended" || this._state === "error" || this.setState(e);
1619
1644
  });
1620
1645
  if (await r.load(), this.destroyed || t !== this.loadGen) {
@@ -1642,9 +1667,11 @@ var Ve = class {
1642
1667
  hlsConfig: r,
1643
1668
  emit: (e) => this.onEngineEvent(e)
1644
1669
  }, a = this.opts.engine ?? "auto";
1645
- if (a === "native") return new U(i);
1646
- if (a === "hls" || pe()) return new Te(i);
1647
- if (H(this.opts.video)) return new U(i);
1670
+ if (a === "native") return new H(i);
1671
+ if (a === "hls") return new U(i);
1672
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video)) return new H(i);
1673
+ if (he()) return new U(i);
1674
+ if (V(this.opts.video)) return new H(i);
1648
1675
  throw new t("INTERNAL", 0, "no supported HLS playback engine in this browser");
1649
1676
  }
1650
1677
  onEngineEvent(e) {
@@ -1689,7 +1716,7 @@ var Ve = class {
1689
1716
  r = 0, i = !1;
1690
1717
  },
1691
1718
  onError: () => {
1692
- this.destroyed || e !== this.loadGen || i || (r += 1, r >= Re && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} 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.`))));
1719
+ this.destroyed || e !== this.loadGen || i || (r += 1, r >= Z && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} 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.`))));
1693
1720
  }
1694
1721
  });
1695
1722
  }
@@ -1711,7 +1738,7 @@ var Ve = class {
1711
1738
  }
1712
1739
  t.controls = !1;
1713
1740
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
1714
- r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = je({
1741
+ r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = Ne({
1715
1742
  root: n,
1716
1743
  video: t,
1717
1744
  player: this,
@@ -1734,7 +1761,7 @@ var Ve = class {
1734
1761
  }
1735
1762
  startStats() {
1736
1763
  this.stopStats();
1737
- let e = Math.max(500, this.opts.statsIntervalMs ?? ze);
1764
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Be);
1738
1765
  this.statsTimer = setInterval(() => {
1739
1766
  this.engine && this.emit("stats", this.engine.getStats());
1740
1767
  }, e);
@@ -1744,7 +1771,7 @@ var Ve = class {
1744
1771
  }
1745
1772
  scheduleLicenseRefresh() {
1746
1773
  this.stopRefresh();
1747
- let e = this.opts.licenseRefreshMs ?? Be;
1774
+ let e = this.opts.licenseRefreshMs ?? Ve;
1748
1775
  !e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
1749
1776
  }
1750
1777
  stopRefresh() {
@@ -1781,7 +1808,7 @@ var Ve = class {
1781
1808
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
1782
1809
  }
1783
1810
  getStats() {
1784
- return this.engine?.getStats() ?? z;
1811
+ return this.engine?.getStats() ?? R;
1785
1812
  }
1786
1813
  getQualityLevels() {
1787
1814
  return this.engine?.getQualityLevels() ?? [];
@@ -1882,7 +1909,7 @@ function $(e) {
1882
1909
  }
1883
1910
  //#endregion
1884
1911
  //#region src/embed/host.ts
1885
- function He(e) {
1912
+ function Ue(e) {
1886
1913
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
1887
1914
  if (!e.src) throw Error("mountEmbed: opts.src is required");
1888
1915
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -1941,8 +1968,8 @@ function He(e) {
1941
1968
  }
1942
1969
  //#endregion
1943
1970
  //#region src/embed/page.ts
1944
- var Ue = /^[A-Za-z0-9:_.-]{1,128}$/;
1945
- function We() {
1971
+ var We = /^[A-Za-z0-9:_.-]{1,128}$/;
1972
+ function Ge() {
1946
1973
  let e = window.HAVIK_EMBED_CONFIG;
1947
1974
  if (e) return {
1948
1975
  baseUrl: e.baseUrl ?? "",
@@ -1964,9 +1991,9 @@ function We() {
1964
1991
  waitForLive: !0
1965
1992
  };
1966
1993
  }
1967
- async function Ge() {
1968
- let e = We();
1969
- qe();
1994
+ async function Ke() {
1995
+ let e = Ge();
1996
+ Je();
1970
1997
  let n = document.createElement("video");
1971
1998
  n.setAttribute("playsinline", ""), n.muted = e.muted ?? !0, n.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(n);
1972
1999
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2021,7 +2048,7 @@ async function Ge() {
2021
2048
  code: e.code,
2022
2049
  message: e.message
2023
2050
  })), e.on("autoplayblocked", () => {
2024
- i({ type: "oddin:autoplayblocked" }), Ke(n, e);
2051
+ i({ type: "oddin:autoplayblocked" }), qe(n, e);
2025
2052
  });
2026
2053
  }, s = async (r) => {
2027
2054
  a?.destroy(), a = null;
@@ -2087,7 +2114,7 @@ async function Ge() {
2087
2114
  a?.retry();
2088
2115
  break;
2089
2116
  case "oddin:load":
2090
- typeof e.matchUrn == "string" && Ue.test(e.matchUrn) && s(e.matchUrn);
2117
+ typeof e.matchUrn == "string" && We.test(e.matchUrn) && s(e.matchUrn);
2091
2118
  break;
2092
2119
  case "oddin:destroy":
2093
2120
  c();
@@ -2101,18 +2128,18 @@ async function Ge() {
2101
2128
  protocol: 1
2102
2129
  });
2103
2130
  }
2104
- function Ke(e, t) {
2131
+ function qe(e, t) {
2105
2132
  if (document.getElementById("havik-tap")) return;
2106
2133
  let n = document.createElement("button");
2107
2134
  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", () => {
2108
2135
  n.remove(), t.play();
2109
2136
  }), document.body.appendChild(n);
2110
2137
  }
2111
- function qe() {
2138
+ function Je() {
2112
2139
  let e = document.createElement("style");
2113
2140
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
2114
2141
  }
2115
2142
  //#endregion
2116
- export { G as ODDIN_THEME, t as PlaybackError, q as applyTheme, Ge as bootEmbed, ue as clearDeviceId, Q as createPlayer, E as deriveEventsBaseUrl, I as detectDrmSupport, se as fetchCatalog, le as fetchTournament, C as flattenMatches, k as getDeviceId, R as isLowLatencyManifest, $ as isOddinMessage, fe as licenseRequestHeaders, He as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, w as watchStatus };
2143
+ export { W as ODDIN_THEME, t as PlaybackError, K as applyTheme, Ke as bootEmbed, ue as clearDeviceId, Q as createPlayer, E as deriveEventsBaseUrl, F as detectDrmSupport, w as fetchCatalog, oe as fetchTournament, ce as flattenMatches, k as getDeviceId, L as isLowLatencyManifest, $ as isOddinMessage, fe as licenseRequestHeaders, Ue as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, le as watchStatus };
2117
2144
 
2118
2145
  //# sourceMappingURL=index.js.map