@oddin-gg/havik-player 2.23.2 → 2.23.3

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
@@ -1500,7 +1500,10 @@ function mn(e, t, n) {
1500
1500
  return a;
1501
1501
  }
1502
1502
  var hn = .2, gn = 30, _n = 2, vn = 2, yn = 2, bn = 9, xn = .5, Sn = 64, Cn = 1e4, wn = 8, Tn = .6, En = .4, Dn = .4, On = 2, kn = 6e4, q = .5, An = 3.5, jn = 300;
1503
- function Mn() {
1503
+ function Mn(e) {
1504
+ return (e?.part ?? e?.frag)?.stats;
1505
+ }
1506
+ function Nn() {
1504
1507
  if (typeof navigator > "u") return 0;
1505
1508
  try {
1506
1509
  let e = navigator.connection?.rtt;
@@ -1509,20 +1512,20 @@ function Mn() {
1509
1512
  return 0;
1510
1513
  }
1511
1514
  }
1512
- function Nn(e) {
1515
+ function Pn(e) {
1513
1516
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1514
1517
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1515
1518
  return;
1516
1519
  }
1517
1520
  e.liveSyncDuration ??= yn;
1518
1521
  let t = Math.max(12, e.liveSyncDuration + bn);
1519
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Pn(e, e.liveSyncDuration);
1522
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Fn(e, e.liveSyncDuration);
1520
1523
  }
1521
- function Pn(e, t) {
1524
+ function Fn(e, t) {
1522
1525
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1523
1526
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1524
1527
  }
1525
- var Fn = class {
1528
+ var In = class {
1526
1529
  name = "hls";
1527
1530
  hls = null;
1528
1531
  deps;
@@ -1758,7 +1761,7 @@ var Fn = class {
1758
1761
  }), t = Nt(e);
1759
1762
  t && (this.prefetch = e, f.fLoader = t);
1760
1763
  }
1761
- Nn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1764
+ Pn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1762
1765
  let p = new e(f);
1763
1766
  if (this.hls = p, this.armHoldBack(p, f), p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
1764
1767
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
@@ -1770,13 +1773,13 @@ var Fn = class {
1770
1773
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1771
1774
  }), p.on(e.Events.FRAG_LOADED, (e, t) => {
1772
1775
  t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
1773
- let n = t?.frag, r = n?.stats?.loaded;
1774
- typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1775
- let i = (t?.part ?? n)?.stats?.loading;
1776
- 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 > Sn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
1777
- let a = n?.url;
1778
- if (a) {
1779
- let e = st(a);
1776
+ let n = t?.frag, r = Mn(t), i = r?.loaded;
1777
+ typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1778
+ let a = r?.loading;
1779
+ a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Sn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
1780
+ let o = n?.url;
1781
+ if (o) {
1782
+ let e = st(o);
1780
1783
  e && (this.cdnHost = e);
1781
1784
  }
1782
1785
  }), p.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -2127,7 +2130,7 @@ var Fn = class {
2127
2130
  if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
2128
2131
  let t = e.targetLatency;
2129
2132
  if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
2130
- let n = Mn();
2133
+ let n = Nn();
2131
2134
  if (!(n >= jn)) return;
2132
2135
  let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + q);
2133
2136
  i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
@@ -2142,7 +2145,7 @@ var Fn = class {
2142
2145
  if (t !== "main" && t !== "audio") return;
2143
2146
  let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
2144
2147
  if (typeof n != "number" || !(n > 0)) return;
2145
- let r = (e.part ?? e.frag)?.stats?.loading;
2148
+ let r = Mn(e)?.loading;
2146
2149
  if (!r || !(r.start > 0) || !(r.end > 0)) return;
2147
2150
  let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
2148
2151
  this.holdBackSamples.push({
@@ -2329,15 +2332,15 @@ var Fn = class {
2329
2332
  let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Dt(t.networkDetails)) : void 0;
2330
2333
  return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
2331
2334
  }
2332
- }, In = 15e3, Ln = 6e5, Rn = 3e5, zn = 100, J = 1, Bn = 1e3, Vn = 3e4, Hn = 1e3, Un = {
2335
+ }, Ln = 15e3, Rn = 6e5, zn = 3e5, Bn = 100, J = 1, Vn = 1e3, Hn = 3e4, Un = 1e3, Wn = {
2333
2336
  inline: "PRESENTATION_INLINE",
2334
2337
  fullscreen: "PRESENTATION_FULLSCREEN",
2335
2338
  pip: "PRESENTATION_PIP"
2336
- }, Wn = {
2339
+ }, Gn = {
2337
2340
  widevine: "KEY_SYSTEM_WIDEVINE",
2338
2341
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2339
2342
  none: "KEY_SYSTEM_NONE"
2340
- }, Gn = /* @__PURE__ */ new Set([
2343
+ }, Kn = /* @__PURE__ */ new Set([
2341
2344
  "INVALID_URN",
2342
2345
  "NOT_FOUND",
2343
2346
  "GEO_DENIED",
@@ -2358,7 +2361,7 @@ var Fn = class {
2358
2361
  ended: "PLAYER_STATE_ENDED",
2359
2362
  error: "PLAYER_STATE_ERROR"
2360
2363
  };
2361
- function Kn(e) {
2364
+ function qn(e) {
2362
2365
  try {
2363
2366
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2364
2367
  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);
@@ -2366,8 +2369,8 @@ function Kn(e) {
2366
2369
  return;
2367
2370
  }
2368
2371
  }
2369
- var qn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Jn = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Yn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2370
- function Xn(e) {
2372
+ var Jn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Yn = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Xn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2373
+ function Zn(e) {
2371
2374
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2372
2375
  let t;
2373
2376
  try {
@@ -2376,19 +2379,19 @@ function Xn(e) {
2376
2379
  } catch {
2377
2380
  return;
2378
2381
  }
2379
- if (Jn.has(t) && !X.has(t)) {
2380
- X.add(t), _(Yn(new URL(t).origin));
2382
+ if (Yn.has(t) && !X.has(t)) {
2383
+ X.add(t), _(Xn(new URL(t).origin));
2381
2384
  for (let e of Z) e.noteCspBlocked();
2382
2385
  }
2383
2386
  }
2384
- function Zn(e, t) {
2387
+ function Qn(e, t) {
2385
2388
  return _(t, e), { disabledReason: t };
2386
2389
  }
2387
- function Qn(e, t, n) {
2388
- if (n) return t && !qn(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2390
+ function $n(e, t, n) {
2391
+ if (n) return t && !Jn(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2389
2392
  if (t) return { endpoint: t };
2390
- if (t !== void 0) return Zn("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).");
2391
- let r = Kn(e);
2393
+ if (t !== void 0) return Qn("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).");
2394
+ let r = qn(e);
2392
2395
  if (r) return { endpoint: r };
2393
2396
  let i;
2394
2397
  try {
@@ -2396,9 +2399,9 @@ function Qn(e, t, n) {
2396
2399
  } catch {
2397
2400
  i = e;
2398
2401
  }
2399
- return Zn(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).`);
2402
+ return Qn(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).`);
2400
2403
  }
2401
- var $n = class {
2404
+ var er = class {
2402
2405
  opts;
2403
2406
  url;
2404
2407
  cspKey;
@@ -2480,8 +2483,8 @@ var $n = class {
2480
2483
  constructor(e) {
2481
2484
  this.opts = {
2482
2485
  ...e,
2483
- heartbeatMs: e.heartbeatMs ?? In,
2484
- idleMs: e.idleMs ?? Ln
2486
+ heartbeatMs: e.heartbeatMs ?? Ln,
2487
+ idleMs: e.idleMs ?? Rn
2485
2488
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2486
2489
  try {
2487
2490
  let e = new URL(this.url);
@@ -2498,11 +2501,11 @@ var $n = class {
2498
2501
  sdkVersion: this.opts.sdkVersion,
2499
2502
  ...this.opts.environment
2500
2503
  };
2501
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Bn), 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 && Jn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Xn), Z.add(this), this.noteCspBlocked(), this.onVisibility());
2504
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Vn), 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 && Yn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Zn), Z.add(this), this.noteCspBlocked(), this.onVisibility());
2502
2505
  }
2503
2506
  checkSuspension(e) {
2504
2507
  if (this.endedFlag || !this.opts.idleMs) return !1;
2505
- let t = Math.max(this.opts.idleMs, Rn);
2508
+ let t = Math.max(this.opts.idleMs, zn);
2506
2509
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2507
2510
  }
2508
2511
  syncIdle(e) {
@@ -2525,12 +2528,12 @@ var $n = class {
2525
2528
  let a = {
2526
2529
  fromState: Y[e] ?? "PLAYER_STATE_UNSPECIFIED",
2527
2530
  toState: Y[t] ?? "PLAYER_STATE_UNSPECIFIED",
2528
- presentation: Un[this.presentation]
2531
+ presentation: Wn[this.presentation]
2529
2532
  }, o = this.causeOf(e, t, i);
2530
2533
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2531
2534
  }
2532
2535
  seekInduced(e) {
2533
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Hn;
2536
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Un;
2534
2537
  }
2535
2538
  causeOf(e, t, n) {
2536
2539
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2604,7 +2607,7 @@ var $n = class {
2604
2607
  let r = n ?? "";
2605
2608
  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";
2606
2609
  if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
2607
- if (Gn.has(e)) return "ERROR_STAGE_RESOLVE";
2610
+ if (Kn.has(e)) return "ERROR_STAGE_RESOLVE";
2608
2611
  let i = t ?? "";
2609
2612
  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";
2610
2613
  }
@@ -2658,7 +2661,7 @@ var $n = class {
2658
2661
  maybeEmitMediaInfo(e) {
2659
2662
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2660
2663
  let t = {};
2661
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Wn[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);
2664
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Gn[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);
2662
2665
  let n = JSON.stringify(t);
2663
2666
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2664
2667
  }
@@ -2678,7 +2681,7 @@ var $n = class {
2678
2681
  let c = r?.positionMs ?? 0;
2679
2682
  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));
2680
2683
  let l = e !== "END_REASON_ENDED";
2681
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Vn && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Vn && (i.abandonAfterErrorMs = Math.max(J, 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);
2684
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Hn && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Hn && (i.abandonAfterErrorMs = Math.max(J, 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);
2682
2685
  let u = r?.decodedFrames ?? this.lastDecoded;
2683
2686
  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");
2684
2687
  }
@@ -2698,13 +2701,13 @@ var $n = class {
2698
2701
  };
2699
2702
  }
2700
2703
  noteCspBlocked() {
2701
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Yn(new URL(this.url).origin)));
2704
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Xn(new URL(this.url).origin)));
2702
2705
  }
2703
2706
  cspBlocked() {
2704
2707
  return !!this.cspKey && X.has(this.cspKey);
2705
2708
  }
2706
2709
  enqueue(e) {
2707
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > zn;) {
2710
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Bn;) {
2708
2711
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2709
2712
  this.pending.splice(e >= 0 ? e : 0, 1);
2710
2713
  }
@@ -2731,7 +2734,7 @@ var $n = class {
2731
2734
  };
2732
2735
  //#endregion
2733
2736
  //#region src/core/environment.ts
2734
- function er() {
2737
+ function tr() {
2735
2738
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2736
2739
  let e;
2737
2740
  try {
@@ -2756,14 +2759,14 @@ function er() {
2756
2759
  integration: "INTEGRATION_KIND_IFRAME"
2757
2760
  };
2758
2761
  }
2759
- function tr() {
2762
+ function nr() {
2760
2763
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2761
2764
  let e = navigator.userAgentData, t = e?.platform ?? "";
2762
2765
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2763
2766
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2764
2767
  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";
2765
2768
  }
2766
- function nr() {
2769
+ function rr() {
2767
2770
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2768
2771
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2769
2772
  let t = {
@@ -2782,17 +2785,17 @@ function nr() {
2782
2785
  }
2783
2786
  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;
2784
2787
  }
2785
- function rr(e) {
2786
- let t = er(), n = {
2787
- deviceClass: tr(),
2788
+ function ir(e) {
2789
+ let t = tr(), n = {
2790
+ deviceClass: nr(),
2788
2791
  integration: t.integration,
2789
- ...nr()
2792
+ ...rr()
2790
2793
  };
2791
2794
  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);
2792
2795
  let r = e.getBoundingClientRect?.();
2793
2796
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2794
2797
  }
2795
- async function ir() {
2798
+ async function ar() {
2796
2799
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2797
2800
  if (!e?.getHighEntropyValues) return {};
2798
2801
  try {
@@ -2804,7 +2807,7 @@ async function ir() {
2804
2807
  }
2805
2808
  //#endregion
2806
2809
  //#region src/core/version.ts
2807
- var ar = "2.23.2", or = {
2810
+ var or = "2.23.3", sr = {
2808
2811
  accent: "#E1B600",
2809
2812
  accentText: "#1B1C23",
2810
2813
  background: "#0e0f13",
@@ -2815,7 +2818,7 @@ var ar = "2.23.2", or = {
2815
2818
  border: "rgba(255, 255, 255, 0.1)",
2816
2819
  radius: "8px",
2817
2820
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2818
- }, sr = {
2821
+ }, cr = {
2819
2822
  accent: "--havik-accent",
2820
2823
  accentText: "--havik-accent-text",
2821
2824
  background: "--havik-bg",
@@ -2827,26 +2830,26 @@ var ar = "2.23.2", or = {
2827
2830
  radius: "--havik-radius",
2828
2831
  fontFamily: "--havik-font"
2829
2832
  };
2830
- function cr(e, t) {
2833
+ function lr(e, t) {
2831
2834
  let n = {
2832
- ...or,
2835
+ ...sr,
2833
2836
  ...t
2834
2837
  };
2835
- for (let t of Object.keys(sr)) e.style.setProperty(sr[t], n[t]);
2838
+ for (let t of Object.keys(cr)) e.style.setProperty(cr[t], n[t]);
2836
2839
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2837
2840
  }
2838
2841
  //#endregion
2839
2842
  //#region src/ui/styles.ts
2840
- var lr = "havik-player-styles", ur = "\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", dr = /* @__PURE__ */ new WeakMap();
2841
- function fr(e = document, t) {
2842
- let n = e.querySelector(`style#${lr}`);
2843
- if (n && (!t || dr.get(n) === t)) return;
2843
+ var ur = "havik-player-styles", dr = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", fr = /* @__PURE__ */ new WeakMap();
2844
+ function pr(e = document, t) {
2845
+ let n = e.querySelector(`style#${ur}`);
2846
+ if (n && (!t || fr.get(n) === t)) return;
2844
2847
  let r = e.createElement("style");
2845
- r.id = lr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = ur, dr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2848
+ r.id = ur, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = dr, fr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2846
2849
  }
2847
2850
  //#endregion
2848
2851
  //#region src/ui/icons.ts
2849
- var pr = {
2852
+ var mr = {
2850
2853
  play: "<path d=\"M8 5v14l11-7z\"/>",
2851
2854
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2852
2855
  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\"/>",
@@ -2860,11 +2863,11 @@ var pr = {
2860
2863
  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\"/>"
2861
2864
  };
2862
2865
  function Q(e) {
2863
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${pr[e]}</svg>`;
2866
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${mr[e]}</svg>`;
2864
2867
  }
2865
2868
  //#endregion
2866
2869
  //#region src/ui/controls.ts
2867
- var mr = 3e3, hr = 250, gr = /* @__PURE__ */ new Set([
2870
+ var hr = 3e3, gr = 250, _r = /* @__PURE__ */ new Set([
2868
2871
  "GONE",
2869
2872
  "NOT_FOUND",
2870
2873
  "GEO_DENIED",
@@ -2872,15 +2875,15 @@ var mr = 3e3, hr = 250, gr = /* @__PURE__ */ new Set([
2872
2875
  "UNAUTHORIZED",
2873
2876
  "DRM_DEVICE_REVOKED"
2874
2877
  ]);
2875
- function _r(e) {
2878
+ function vr(e) {
2876
2879
  let t = "This match isn't available in your country";
2877
2880
  return e ? `${t} (${e})` : t;
2878
2881
  }
2879
- var vr = "This device can't play protected video";
2880
- function yr(e) {
2881
- return new br(e);
2882
+ var yr = "This device can't play protected video";
2883
+ function br(e) {
2884
+ return new xr(e);
2882
2885
  }
2883
- var br = class {
2886
+ var xr = class {
2884
2887
  root;
2885
2888
  video;
2886
2889
  player;
@@ -2928,7 +2931,7 @@ var br = class {
2928
2931
  scrubbing = !1;
2929
2932
  offFns = [];
2930
2933
  constructor(e) {
2931
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? mr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, fr(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");
2934
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? hr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, pr(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2932
2935
  let t = (e, t, n) => {
2933
2936
  let r = this.doc.createElement(e);
2934
2937
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -3014,7 +3017,7 @@ var br = class {
3014
3017
  let t = this.surfaceWasHidden;
3015
3018
  this.tapTimer = setTimeout(() => {
3016
3019
  this.tapTimer = void 0, this.toggleBar(t);
3017
- }, hr);
3020
+ }, gr);
3018
3021
  }
3019
3022
  toggleBar(e) {
3020
3023
  e ? this.poke() : this.hideIfIdle();
@@ -3034,7 +3037,7 @@ var br = class {
3034
3037
  this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
3035
3038
  }
3036
3039
  statusMessageFor(e) {
3037
- return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? _r(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? vr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3040
+ return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? vr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? yr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3038
3041
  }
3039
3042
  renderStatus(e) {
3040
3043
  let t = this.statusMessageFor(e);
@@ -3049,7 +3052,7 @@ var br = class {
3049
3052
  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);
3050
3053
  } else {
3051
3054
  let r = this.doc.createElement("div");
3052
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !gr.has(this.lastError.code)) {
3055
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !_r.has(this.lastError.code)) {
3053
3056
  let e = this.doc.createElement("button");
3054
3057
  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);
3055
3058
  }
@@ -3090,7 +3093,7 @@ var br = class {
3090
3093
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
3091
3094
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
3092
3095
  }
3093
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${xr(this.video.currentTime)} / ${xr(this.video.duration)}`);
3096
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Sr(this.video.currentTime)} / ${Sr(this.video.duration)}`);
3094
3097
  }
3095
3098
  syncLive() {
3096
3099
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
@@ -3140,17 +3143,17 @@ var br = class {
3140
3143
  renderQualityMenu() {
3141
3144
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
3142
3145
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
3143
- for (let n of e) this.menu.append(this.menuItem(Sr(n), t === n.index, () => this.player.setQuality(n.index)));
3146
+ for (let n of e) this.menu.append(this.menuItem(Cr(n), t === n.index, () => this.player.setQuality(n.index)));
3144
3147
  }
3145
3148
  renderAudioMenu() {
3146
3149
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
3147
3150
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
3148
- for (let t of e) this.menu.append(this.menuItem(Cr(t), t.default, () => this.player.setAudioTrack(t.id)));
3151
+ for (let t of e) this.menu.append(this.menuItem(wr(t), t.default, () => this.player.setAudioTrack(t.id)));
3149
3152
  }
3150
3153
  renderCcMenu() {
3151
3154
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
3152
3155
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
3153
- for (let t of e) this.menu.append(this.menuItem(wr(t), !1, () => this.player.setTextTrack(t.id)));
3156
+ for (let t of e) this.menu.append(this.menuItem(Tr(t), !1, () => this.player.setTextTrack(t.id)));
3154
3157
  }
3155
3158
  onTracksChanged() {
3156
3159
  this.openMenu && this.renderMenu(this.openMenu);
@@ -3255,41 +3258,41 @@ var br = class {
3255
3258
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
3256
3259
  }
3257
3260
  };
3258
- function xr(e) {
3261
+ function Sr(e) {
3259
3262
  (!Number.isFinite(e) || e < 0) && (e = 0);
3260
3263
  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");
3261
3264
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3262
3265
  }
3263
- function Sr(e) {
3266
+ function Cr(e) {
3264
3267
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3265
3268
  }
3266
- function Cr(e) {
3269
+ function wr(e) {
3267
3270
  return e.name || e.lang || `Track ${e.id}`;
3268
3271
  }
3269
- function wr(e) {
3272
+ function Tr(e) {
3270
3273
  return e.name || e.lang || `Track ${e.id}`;
3271
3274
  }
3272
3275
  //#endregion
3273
3276
  //#region src/managed/index.ts
3274
- var Tr = 6e3, Er = 45e3, Dr = 2e3, Or = 3, kr = 5e3, Ar = 2e3, jr = 48e4, Mr = "keySystemLicenseRequestFailed";
3275
- function Nr(e) {
3277
+ var Er = 6e3, Dr = 45e3, Or = 2e3, kr = 3, Ar = 5e3, jr = 2e3, Mr = 48e4, Nr = "keySystemLicenseRequestFailed";
3278
+ function Pr(e) {
3276
3279
  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)})`);
3277
3280
  if (e.env !== void 0) return at(e.env);
3278
3281
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3279
3282
  return e.baseUrl;
3280
3283
  }
3281
- async function Pr(e) {
3284
+ async function Fr(e) {
3282
3285
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3283
- let t = Nr(e);
3286
+ let t = Pr(e);
3284
3287
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3285
3288
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3286
- let r = new Fr({
3289
+ let r = new Ir({
3287
3290
  ...e,
3288
3291
  baseUrl: t
3289
3292
  });
3290
3293
  return await r.start(), r;
3291
3294
  }
3292
- var Fr = class {
3295
+ var Ir = class {
3293
3296
  opts;
3294
3297
  abort = new AbortController();
3295
3298
  listeners = {};
@@ -3384,7 +3387,7 @@ var Fr = class {
3384
3387
  setTimeout(() => {
3385
3388
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3386
3389
  phase: i ? "unavailable" : "tooEarly",
3387
- retryInMs: Er,
3390
+ retryInMs: Dr,
3388
3391
  attempt: 1,
3389
3392
  elapsedMs: 0,
3390
3393
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3423,13 +3426,13 @@ var Fr = class {
3423
3426
  !a && !p() && h();
3424
3427
  }, e);
3425
3428
  };
3426
- _(Tr), this.armingSub = E({
3429
+ _(Er), this.armingSub = E({
3427
3430
  eventsBaseUrl: t,
3428
3431
  matchUrn: this.opts.matchUrn,
3429
3432
  credential: this.opts.credential,
3430
- onAlive: () => _(Er),
3433
+ onAlive: () => _(Dr),
3431
3434
  onState: (e) => {
3432
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Dr);
3435
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Or);
3433
3436
  },
3434
3437
  onError: () => h()
3435
3438
  });
@@ -3474,19 +3477,19 @@ var Fr = class {
3474
3477
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3475
3478
  let i = e.analytics?.sid;
3476
3479
  if (!i) return;
3477
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Qn(this.opts.baseUrl, a, e.analytics?.endpoint);
3480
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = $n(this.opts.baseUrl, a, e.analytics?.endpoint);
3478
3481
  if (!o) {
3479
3482
  s && setTimeout(() => {
3480
3483
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3481
3484
  }, 0);
3482
3485
  return;
3483
3486
  }
3484
- let c = this.opts.video, l = new $n({
3487
+ let c = this.opts.video, l = new er({
3485
3488
  endpoint: o,
3486
3489
  sid: i,
3487
3490
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3488
- sdkVersion: ar,
3489
- environment: rr(c),
3491
+ sdkVersion: or,
3492
+ environment: ir(c),
3490
3493
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3491
3494
  onIdle: () => this.onAnalyticsIdle(t),
3492
3495
  onBlocked: (e) => setTimeout(() => {
@@ -3507,7 +3510,7 @@ var Fr = class {
3507
3510
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3508
3511
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3509
3512
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3510
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ir().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3513
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ar().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3511
3514
  }
3512
3515
  currentPresentation() {
3513
3516
  let e = this.opts.video;
@@ -3538,9 +3541,9 @@ var Fr = class {
3538
3541
  freshLicenseUrl: () => this.refreshLicense()
3539
3542
  }, o = this.opts.engine ?? "auto";
3540
3543
  if (o === "native") return new U(a);
3541
- if (o === "hls") return new Fn(a);
3544
+ if (o === "hls") return new In(a);
3542
3545
  if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Ct() && V(this.opts.video)) return new U(a);
3543
- if (Lt()) return new Fn(a);
3546
+ if (Lt()) return new In(a);
3544
3547
  if (V(this.opts.video)) return new U(a);
3545
3548
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3546
3549
  }
@@ -3606,7 +3609,7 @@ var Fr = class {
3606
3609
  r = 0, i = !1;
3607
3610
  },
3608
3611
  onError: () => {
3609
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Or && (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.`))));
3612
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= kr && (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.`))));
3610
3613
  }
3611
3614
  });
3612
3615
  }
@@ -3620,7 +3623,7 @@ var Fr = class {
3620
3623
  return;
3621
3624
  }
3622
3625
  let e = this.hiddenAtMs;
3623
- this.hiddenAtMs = null, e != null && Date.now() - e >= kr && this.resyncLiveState();
3626
+ this.hiddenAtMs = null, e != null && Date.now() - e >= Ar && this.resyncLiveState();
3624
3627
  }, this.onReturnPageShow = (e) => {
3625
3628
  e.persisted && this.resyncLiveState();
3626
3629
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3652,7 +3655,7 @@ var Fr = class {
3652
3655
  scheduleRejoin(e) {
3653
3656
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3654
3657
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3655
- }, Math.random() * Dr));
3658
+ }, Math.random() * Or));
3656
3659
  }
3657
3660
  cancelRejoin() {
3658
3661
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3676,7 +3679,7 @@ var Fr = class {
3676
3679
  }
3677
3680
  t.controls = !1;
3678
3681
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3679
- r && r.insertBefore(n, t), n.appendChild(t), cr(n, this.opts.theme), this.container = n, this.controlBar = yr({
3682
+ r && r.insertBefore(n, t), n.appendChild(t), lr(n, this.opts.theme), this.container = n, this.controlBar = br({
3680
3683
  root: n,
3681
3684
  video: t,
3682
3685
  player: this,
@@ -3714,7 +3717,7 @@ var Fr = class {
3714
3717
  }
3715
3718
  startStats() {
3716
3719
  this.stopStats();
3717
- let e = Math.max(500, this.opts.statsIntervalMs ?? Ar);
3720
+ let e = Math.max(500, this.opts.statsIntervalMs ?? jr);
3718
3721
  this.statsTimer = setInterval(() => {
3719
3722
  if (!this.engine) return;
3720
3723
  let e = this.engine.getStats();
@@ -3725,14 +3728,14 @@ var Fr = class {
3725
3728
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3726
3729
  }
3727
3730
  isStaleLicenseDenial(e) {
3728
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Mr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
3731
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Nr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
3729
3732
  }
3730
3733
  scheduleLicenseRefresh() {
3731
3734
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3732
3735
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3733
3736
  document.visibilityState !== "visible" || this.destroyed || G(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3734
3737
  }, document.addEventListener("visibilitychange", this.onRefocus));
3735
- let e = this.opts.licenseRefreshMs ?? jr;
3738
+ let e = this.opts.licenseRefreshMs ?? Mr;
3736
3739
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3737
3740
  }
3738
3741
  stopRefresh() {
@@ -3902,7 +3905,7 @@ function $(e) {
3902
3905
  }
3903
3906
  //#endregion
3904
3907
  //#region src/embed/host.ts
3905
- function Ir(e) {
3908
+ function Lr(e) {
3906
3909
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3907
3910
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3908
3911
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3961,15 +3964,15 @@ function Ir(e) {
3961
3964
  }
3962
3965
  //#endregion
3963
3966
  //#region src/embed/page.ts
3964
- var Lr = /^[A-Za-z0-9:_.-]{1,128}$/;
3965
- function Rr(e) {
3967
+ var Rr = /^[A-Za-z0-9:_.-]{1,128}$/;
3968
+ function zr(e) {
3966
3969
  if (typeof e == "boolean") return e;
3967
3970
  if (typeof e == "object" && e) {
3968
3971
  let t = e.endpoint;
3969
3972
  return typeof t == "string" ? { endpoint: t } : {};
3970
3973
  }
3971
3974
  }
3972
- function zr() {
3975
+ function Br() {
3973
3976
  let e = window.HAVIK_EMBED_CONFIG;
3974
3977
  if (e) return {
3975
3978
  baseUrl: e.baseUrl ?? "",
@@ -3979,7 +3982,7 @@ function zr() {
3979
3982
  autoplay: e.autoplay ?? !0,
3980
3983
  muted: e.muted ?? !0,
3981
3984
  waitForLive: e.waitForLive ?? !0,
3982
- analytics: Rr(e.analytics)
3985
+ analytics: zr(e.analytics)
3983
3986
  };
3984
3987
  let t = new URLSearchParams(location.search);
3985
3988
  return {
@@ -3992,9 +3995,9 @@ function zr() {
3992
3995
  waitForLive: !0
3993
3996
  };
3994
3997
  }
3995
- async function Br() {
3996
- let e = zr();
3997
- Hr();
3998
+ async function Vr() {
3999
+ let e = Br();
4000
+ Ur();
3998
4001
  let t = document.createElement("video");
3999
4002
  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);
4000
4003
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -4050,12 +4053,12 @@ async function Br() {
4050
4053
  message: e.message,
4051
4054
  ...e.country === void 0 ? {} : { country: e.country }
4052
4055
  })), e.on("autoplayblocked", () => {
4053
- i({ type: "oddin:autoplayblocked" }), Vr(t, e);
4056
+ i({ type: "oddin:autoplayblocked" }), Hr(t, e);
4054
4057
  });
4055
4058
  }, s = async (r) => {
4056
4059
  a?.destroy(), a = null;
4057
4060
  try {
4058
- let n = await Pr({
4061
+ let n = await Fr({
4059
4062
  video: t,
4060
4063
  baseUrl: e.baseUrl,
4061
4064
  matchUrn: r,
@@ -4118,7 +4121,7 @@ async function Br() {
4118
4121
  a?.retry();
4119
4122
  break;
4120
4123
  case "oddin:load":
4121
- typeof e.matchUrn == "string" && Lr.test(e.matchUrn) && s(e.matchUrn);
4124
+ typeof e.matchUrn == "string" && Rr.test(e.matchUrn) && s(e.matchUrn);
4122
4125
  break;
4123
4126
  case "oddin:destroy": c();
4124
4127
  }
@@ -4130,18 +4133,18 @@ async function Br() {
4130
4133
  protocol: 1
4131
4134
  });
4132
4135
  }
4133
- function Vr(e, t) {
4136
+ function Hr(e, t) {
4134
4137
  if (document.getElementById("havik-tap")) return;
4135
4138
  let n = document.createElement("button");
4136
4139
  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", () => {
4137
4140
  n.remove(), t.play();
4138
4141
  }), document.body.appendChild(n);
4139
4142
  }
4140
- function Hr() {
4143
+ function Ur() {
4141
4144
  let e = document.createElement("style");
4142
4145
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
4143
4146
  }
4144
4147
  //#endregion
4145
- export { or as ODDIN_THEME, n as PlaybackError, cr as applyTheme, at as baseUrlForEnv, Br as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, Pr as createPlayer, D as deriveEventsBaseUrl, tt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, A as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, Ir as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4148
+ export { sr as ODDIN_THEME, n as PlaybackError, lr as applyTheme, at as baseUrlForEnv, Vr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, Fr as createPlayer, D as deriveEventsBaseUrl, tt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, A as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, Lr as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4146
4149
 
4147
4150
  //# sourceMappingURL=index.js.map