@oddin-gg/havik-player 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -43,9 +43,12 @@ async function s(e) {
43
43
  if (!t || !t.apiKey) throw Error("havik-player: credential is missing an apiKey");
44
44
  return t;
45
45
  }
46
+ function c(e) {
47
+ return e === "live" || e === "ended" || e === "upcoming" ? e : "upcoming";
48
+ }
46
49
  //#endregion
47
50
  //#region src/core/http.ts
48
- function c(e, t) {
51
+ function l(e, t) {
49
52
  let r = e.replace(/\/+$/, ""), i;
50
53
  try {
51
54
  i = new URL(r + t);
@@ -55,14 +58,14 @@ function c(e, t) {
55
58
  if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
56
59
  return i.toString();
57
60
  }
58
- function l(e) {
61
+ function u(e) {
59
62
  if (!e) return;
60
63
  let t = Number(e);
61
64
  if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
62
65
  let n = Date.parse(e);
63
66
  if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
64
67
  }
65
- async function u(e, t) {
68
+ async function d(e, t) {
66
69
  let r = await s(t.credential), i = t.headers ?? new Headers();
67
70
  if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
68
71
  i.set("x-api-key", r.apiKey);
@@ -77,49 +80,49 @@ async function u(e, t) {
77
80
  mode: "cors"
78
81
  });
79
82
  } catch (e) {
80
- throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${d(e)}`, { cause: e });
83
+ throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${f(e)}`, { cause: e });
81
84
  }
82
85
  }
83
- function d(e) {
86
+ function f(e) {
84
87
  return e instanceof Error ? e.message : String(e);
85
88
  }
86
89
  //#endregion
87
90
  //#region src/core/waitForLive.ts
88
- var f = 1e3, p = 3e4, m = 6e5, h = 3e5, g = 1e3, _ = {
91
+ var p = 1e3, m = 3e4, h = 6e5, g = 3e5, _ = 1e3, ee = {
89
92
  TOO_EARLY: "tooEarly",
90
93
  UNAVAILABLE: "unavailable",
91
94
  RATE_LIMITED: "rateLimited",
92
95
  NETWORK: "network"
93
96
  };
94
- function ee(e) {
95
- let t = e === !0 || e === !1 ? {} : e, n = Math.max(g, t.floorMs ?? f), r = Math.max(n, t.ceilMs ?? p), i = Math.max(0, t.imminentMs ?? m), a = Math.max(r, t.sanityFloorMs ?? h);
97
+ function te(e) {
98
+ let t = e === !0 || e === !1 ? {} : e, n = Math.max(_, t.floorMs ?? p), r = Math.max(n, t.ceilMs ?? m), i = Math.max(0, t.imminentMs ?? h), a = Math.max(r, t.sanityFloorMs ?? g);
96
99
  return {
97
100
  timeoutMs: t.timeoutMs,
98
101
  floorMs: n,
99
102
  ceilMs: r,
100
103
  imminentMs: i,
101
104
  sanityFloorMs: a,
102
- kickoffMs: te(t.kickoffAt),
105
+ kickoffMs: ne(t.kickoffAt),
103
106
  jitter: t.jitter ?? !0,
104
107
  onState: t.onState
105
108
  };
106
109
  }
107
- function te(e) {
110
+ function ne(e) {
108
111
  if (e == null) return;
109
112
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
110
113
  let t = Date.parse(e);
111
114
  return Number.isFinite(t) ? t : void 0;
112
115
  }
113
- function ne(e, t, n) {
116
+ function re(e, t, n) {
114
117
  return Math.min(n, Math.max(t, e));
115
118
  }
116
- function re(e) {
119
+ function ie(e) {
117
120
  return Math.round(e * (1 + .15 * Math.random()));
118
121
  }
119
- function ie(e, t, n, r) {
122
+ function ae(e, t, n, r) {
120
123
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
121
124
  if (a == null || a <= n.imminentMs) return {
122
- delay: ne(e ?? n.floorMs, o, n.ceilMs),
125
+ delay: re(e ?? n.floorMs, o, n.ceilMs),
123
126
  ttkMs: a
124
127
  };
125
128
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -128,7 +131,7 @@ function ie(e, t, n, r) {
128
131
  ttkMs: a
129
132
  };
130
133
  }
131
- function ae(e, t) {
134
+ function oe(e, t) {
132
135
  return new Promise((r, i) => {
133
136
  if (t?.aborted) {
134
137
  i(new n("ABORTED", 0, "wait-for-live aborted"));
@@ -143,7 +146,7 @@ function ae(e, t) {
143
146
  });
144
147
  }
145
148
  async function v(e, t, r) {
146
- let i = ee(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
149
+ let i = te(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
147
150
  for (;;) {
148
151
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
149
152
  try {
@@ -151,18 +154,18 @@ async function v(e, t, r) {
151
154
  } catch (e) {
152
155
  if (!(e instanceof n) || !o(e.code)) throw e;
153
156
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
154
- let t = Date.now(), u = ie(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
155
- if (i.jitter && (f = re(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
157
+ let t = Date.now(), u = ae(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
158
+ if (i.jitter && (f = ie(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
156
159
  retryAfterMs: e.retryAfterMs,
157
160
  cause: e
158
161
  });
159
162
  i.onState?.({
160
- phase: _[e.code] ?? "unavailable",
163
+ phase: ee[e.code] ?? "unavailable",
161
164
  retryInMs: f,
162
165
  attempt: c,
163
166
  elapsedMs: t - a,
164
167
  ttkMs: d
165
- }), await ae(f, r);
168
+ }), await oe(f, r);
166
169
  }
167
170
  }
168
171
  }
@@ -170,20 +173,20 @@ async function v(e, t, r) {
170
173
  //#region src/core/resolve.ts
171
174
  async function y(e) {
172
175
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
173
- let t = await u(c(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
176
+ let t = await d(l(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
174
177
  credential: e.credential,
175
178
  signal: e.signal,
176
179
  apiHeaders: e.apiHeaders
177
180
  });
178
- if (!t.ok) throw await oe(t);
179
- return ce(await t.json(), e.matchUrn);
181
+ if (!t.ok) throw await se(t);
182
+ return le(await t.json(), e.matchUrn);
180
183
  }
181
184
  function b(e) {
182
185
  let t = () => y(e);
183
186
  return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
184
187
  }
185
- async function oe(e) {
186
- let t = l(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
188
+ async function se(e) {
189
+ let t = u(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
187
190
  try {
188
191
  let t = await e.json();
189
192
  if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
@@ -198,7 +201,7 @@ async function oe(e) {
198
201
  liveStartsAtMs: s
199
202
  });
200
203
  }
201
- var se = /* @__PURE__ */ new Set([
204
+ var ce = /* @__PURE__ */ new Set([
202
205
  "matchUrn",
203
206
  "protocol",
204
207
  "drmEnabled",
@@ -219,7 +222,7 @@ function x(e, t) {
219
222
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
220
223
  return t;
221
224
  }
222
- function ce(e, t) {
225
+ function le(e, t) {
223
226
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
224
227
  let r = e.drmEnabled ?? !!e.drm, i = {
225
228
  matchUrn: e.matchUrn ?? t,
@@ -236,7 +239,7 @@ function ce(e, t) {
236
239
  }), (t.widevine || t.fairplay) && (i.drm = t);
237
240
  }
238
241
  let a = {};
239
- for (let [t, n] of Object.entries(e)) se.has(t) || (a[t] = n);
242
+ for (let [t, n] of Object.entries(e)) ce.has(t) || (a[t] = n);
240
243
  return Object.keys(a).length > 0 && (i.extensions = a), i;
241
244
  }
242
245
  //#endregion
@@ -244,11 +247,11 @@ function ce(e, t) {
244
247
  function S(e) {
245
248
  return e.ownerDocument ?? document;
246
249
  }
247
- function le(e) {
250
+ function ue(e) {
248
251
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
249
252
  }
250
253
  function C(e, t) {
251
- let n = le(S(e));
254
+ let n = ue(S(e));
252
255
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
253
256
  }
254
257
  async function w(e, t) {
@@ -264,17 +267,17 @@ async function T(e, t) {
264
267
  n.webkitExitFullscreen?.();
265
268
  return;
266
269
  }
267
- let r = S(e), i = le(r);
270
+ let r = S(e), i = ue(r);
268
271
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
269
272
  }
270
273
  //#endregion
271
274
  //#region src/core/catalog.ts
272
- async function ue(e) {
275
+ async function de(e) {
273
276
  let t = new URLSearchParams();
274
277
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
275
- let i = t.toString(), a = c(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
278
+ let i = t.toString(), a = l(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
276
279
  e.etag && o.set("If-None-Match", e.etag);
277
- let s = await u(a, {
280
+ let s = await d(a, {
278
281
  credential: e.credential,
279
282
  signal: e.signal,
280
283
  headers: o,
@@ -287,12 +290,12 @@ async function ue(e) {
287
290
  };
288
291
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
289
292
  return {
290
- tournaments: de(await s.json()),
293
+ tournaments: fe(await s.json()),
291
294
  etag: s.headers.get("etag") ?? void 0,
292
295
  notModified: !1
293
296
  };
294
297
  }
295
- function de(e) {
298
+ function fe(e) {
296
299
  return (e.tournaments ?? []).map((e) => {
297
300
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
298
301
  return {
@@ -303,7 +306,8 @@ function de(e) {
303
306
  matches: (e.matches ?? []).map((e) => ({
304
307
  matchUrn: e.matchUrn ?? "",
305
308
  matchName: e.matchName ?? "",
306
- status: e.status ?? "upcoming",
309
+ status: c(e.status),
310
+ statusRaw: e.status,
307
311
  datePlannedStart: e.datePlannedStart,
308
312
  tournamentUrn: t,
309
313
  tournamentName: n,
@@ -312,10 +316,10 @@ function de(e) {
312
316
  };
313
317
  });
314
318
  }
315
- async function fe(e) {
316
- let t = c(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
319
+ async function pe(e) {
320
+ let t = l(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
317
321
  e.etag && i.set("If-None-Match", e.etag);
318
- let a = await u(t, {
322
+ let a = await d(t, {
319
323
  credential: e.credential,
320
324
  signal: e.signal,
321
325
  headers: i,
@@ -332,13 +336,13 @@ async function fe(e) {
332
336
  };
333
337
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
334
338
  return {
335
- tournament: pe(await a.json()),
339
+ tournament: me(await a.json()),
336
340
  etag: a.headers.get("etag") ?? void 0,
337
341
  notModified: !1,
338
342
  notFound: !1
339
343
  };
340
344
  }
341
- function pe(e) {
345
+ function me(e) {
342
346
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
343
347
  return {
344
348
  urn: t,
@@ -348,7 +352,8 @@ function pe(e) {
348
352
  matches: (e.matches ?? []).map((e) => ({
349
353
  matchUrn: e.matchUrn ?? "",
350
354
  matchName: e.matchName ?? "",
351
- status: e.status ?? "upcoming",
355
+ status: c(e.status),
356
+ statusRaw: e.status,
352
357
  datePlannedStart: e.datePlannedStart,
353
358
  tournamentUrn: t,
354
359
  tournamentName: n,
@@ -356,50 +361,51 @@ function pe(e) {
356
361
  }))
357
362
  };
358
363
  }
359
- function me(e) {
364
+ function he(e) {
360
365
  return e.tournaments.flatMap((e) => e.matches);
361
366
  }
362
367
  //#endregion
363
368
  //#region src/core/poll.ts
364
- function he(e) {
365
- let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, l = !1, d = () => {
366
- l || (a = setTimeout(f, t));
367
- }, f = async () => {
369
+ function ge(e) {
370
+ let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
371
+ u || (a = setTimeout(p, t));
372
+ }, p = async () => {
368
373
  try {
369
- let t = c(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
374
+ let t = l(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
370
375
  o && a.set("If-None-Match", o);
371
- let l = await u(t, {
376
+ let u = await d(t, {
372
377
  credential: e.credential,
373
378
  signal: i.signal,
374
379
  headers: a,
375
380
  apiHeaders: e.apiHeaders
376
381
  });
377
- if (l.status !== 304) {
378
- if (!l.ok) throw new n(r(l.status), l.status, `match status request failed (HTTP ${l.status})`);
379
- o = l.headers.get("etag") ?? o;
380
- let t = await l.json(), i = t.status ?? "upcoming";
381
- i !== s && (s = i, e.onChange({
382
+ if (u.status !== 304) {
383
+ if (!u.ok) throw new n(r(u.status), u.status, `match status request failed (HTTP ${u.status})`);
384
+ o = u.headers.get("etag") ?? o;
385
+ let t = await u.json(), i = c(t.status), a = typeof t.status == "string" ? t.status : i;
386
+ a !== s && (s = a, e.onChange({
382
387
  matchUrn: t.matchUrn ?? e.matchUrn,
383
388
  matchName: t.matchName,
384
389
  status: i,
390
+ statusRaw: t.status,
385
391
  datePlannedStart: t.datePlannedStart
386
392
  }));
387
393
  }
388
394
  } catch (t) {
389
395
  i.signal.aborted || e.onError?.(t instanceof n ? t : new n("NETWORK", 0, String(t)));
390
396
  } finally {
391
- d();
397
+ f();
392
398
  }
393
399
  };
394
- return f(), { stop() {
395
- l = !0, i.abort(), a && clearTimeout(a);
400
+ return p(), { stop() {
401
+ u = !0, i.abort(), a && clearTimeout(a);
396
402
  } };
397
403
  }
398
404
  //#endregion
399
405
  //#region src/core/events.ts
400
- var ge = 45e3;
406
+ var _e = 45e3;
401
407
  function E(e) {
402
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ge, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, l = (e) => new Promise((t) => {
408
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? _e, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
403
409
  if (a.signal.aborted) return t();
404
410
  let n = setTimeout(t, e);
405
411
  a.signal.addEventListener("abort", () => {
@@ -448,11 +454,11 @@ function E(e) {
448
454
  try {
449
455
  let n = await s(e.credential);
450
456
  if (o) return;
451
- let a = c(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
457
+ let a = l(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
452
458
  i && (m = setTimeout(() => {
453
459
  p = `no response headers within ${i}ms`, u.abort();
454
460
  }, i));
455
- let l = await fetch(a, {
461
+ let c = await fetch(a, {
456
462
  method: "GET",
457
463
  headers: {
458
464
  "x-api-key": n.apiKey,
@@ -464,7 +470,7 @@ function E(e) {
464
470
  mode: "cors"
465
471
  });
466
472
  if (clearTimeout(m), o) return;
467
- !l.ok || !l.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${l.status}`)) : await f(l.body, () => {
473
+ !c.ok || !c.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${c.status}`)) : await f(c.body, () => {
468
474
  r = t;
469
475
  }, h);
470
476
  } catch (t) {
@@ -474,7 +480,7 @@ function E(e) {
474
480
  clearTimeout(m), a.signal.removeEventListener("abort", d), u.abort();
475
481
  }
476
482
  if (o) return;
477
- p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await l(r), r = Math.min(n, r * 2);
483
+ p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await c(r), r = Math.min(n, r * 2);
478
484
  }
479
485
  })(), { close() {
480
486
  o || (o = !0, a.abort());
@@ -497,20 +503,20 @@ function A() {
497
503
  let e = globalThis.localStorage?.getItem(O);
498
504
  if (e) return k = e, e;
499
505
  } catch {}
500
- let e = ve();
506
+ let e = ye();
501
507
  k = e;
502
508
  try {
503
509
  globalThis.localStorage?.setItem(O, e);
504
510
  } catch {}
505
511
  return e;
506
512
  }
507
- function _e() {
513
+ function ve() {
508
514
  k = void 0;
509
515
  try {
510
516
  globalThis.localStorage?.removeItem(O);
511
517
  } catch {}
512
518
  }
513
- function ve() {
519
+ function ye() {
514
520
  let e = globalThis.crypto;
515
521
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
516
522
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -522,7 +528,7 @@ function ve() {
522
528
  }
523
529
  //#endregion
524
530
  //#region src/core/drm/headers.ts
525
- function ye(e, t, n = {}) {
531
+ function be(e, t, n = {}) {
526
532
  let r = {
527
533
  "x-api-key": t.apiKey,
528
534
  "X-Match-Urn": e.matchUrn,
@@ -534,7 +540,7 @@ function ye(e, t, n = {}) {
534
540
  //#endregion
535
541
  //#region src/core/drm/cdm.ts
536
542
  var j = /* @__PURE__ */ new WeakMap();
537
- function be(e, t) {
543
+ function xe(e, t) {
538
544
  let n = j.get(e);
539
545
  n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
540
546
  let r = n.get(t.keySystem);
@@ -548,11 +554,11 @@ function M() {
548
554
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
549
555
  }
550
556
  var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
551
- function xe(e) {
557
+ function Se(e) {
552
558
  return e.startsWith("com.widevine");
553
559
  }
554
- function Se(e, t) {
555
- if (!xe(e)) return t;
560
+ function Ce(e, t) {
561
+ if (!Se(e)) return t;
556
562
  let n = (e, t) => {
557
563
  let n = e.videoCapabilities;
558
564
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
@@ -568,20 +574,20 @@ function Se(e, t) {
568
574
  })));
569
575
  return [...t, ...r];
570
576
  }
571
- function Ce(e) {
572
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Se(t, n)).then((t) => ({
577
+ function we(e) {
578
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Ce(t, n)).then((t) => ({
573
579
  keySystem: t.keySystem,
574
580
  getConfiguration: () => t.getConfiguration(),
575
- createMediaKeys: () => be(e, t)
581
+ createMediaKeys: () => xe(e, t)
576
582
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
577
583
  }
578
584
  //#endregion
579
585
  //#region src/core/drm/support.ts
580
- var we = 5e3, Te = "video/mp4; codecs=\"avc1.42E01E\"", Ee = "audio/mp4; codecs=\"mp4a.40.2\"", De = {
586
+ var Te = 5e3, Ee = "video/mp4; codecs=\"avc1.42E01E\"", De = "audio/mp4; codecs=\"mp4a.40.2\"", Oe = {
581
587
  widevine: ["com.widevine.alpha"],
582
588
  fairplay: ["com.apple.fps"]
583
589
  };
584
- function Oe(e) {
590
+ function ke(e) {
585
591
  return e === "fairplay" ? [{
586
592
  initDataTypes: [
587
593
  "sinf",
@@ -589,24 +595,24 @@ function Oe(e) {
589
595
  "cenc"
590
596
  ],
591
597
  videoCapabilities: [{
592
- contentType: Te,
598
+ contentType: Ee,
593
599
  robustness: "",
594
600
  encryptionScheme: "cbcs"
595
601
  }],
596
602
  audioCapabilities: [{
597
- contentType: Ee,
603
+ contentType: De,
598
604
  robustness: "",
599
605
  encryptionScheme: "cbcs"
600
606
  }]
601
- }] : Se("com.widevine.alpha", [{
607
+ }] : Ce("com.widevine.alpha", [{
602
608
  initDataTypes: ["cenc"],
603
609
  videoCapabilities: [{
604
- contentType: Te,
610
+ contentType: Ee,
605
611
  robustness: "SW_SECURE_DECODE",
606
612
  encryptionScheme: "cbcs"
607
613
  }],
608
614
  audioCapabilities: [{
609
- contentType: Ee,
615
+ contentType: De,
610
616
  robustness: "SW_SECURE_CRYPTO",
611
617
  encryptionScheme: "cbcs"
612
618
  }]
@@ -622,8 +628,8 @@ function P(e, t) {
622
628
  });
623
629
  });
624
630
  }
625
- async function ke(e = {}) {
626
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? we, r = {};
631
+ async function Ae(e = {}) {
632
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Te, r = {};
627
633
  if (typeof window < "u" && window.isSecureContext === !1) return {
628
634
  verdict: "insecure-context",
629
635
  detail: r
@@ -635,7 +641,7 @@ async function ke(e = {}) {
635
641
  };
636
642
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
637
643
  for (let e of t) {
638
- let t = De[e];
644
+ let t = Oe[e];
639
645
  if (!t) {
640
646
  r[e] = "unknown system";
641
647
  continue;
@@ -646,7 +652,7 @@ async function ke(e = {}) {
646
652
  break;
647
653
  }
648
654
  try {
649
- return await P((await P(i(n, Oe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
655
+ return await P((await P(i(n, ke(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
650
656
  verdict: "supported",
651
657
  system: e,
652
658
  detail: r
@@ -670,9 +676,9 @@ async function ke(e = {}) {
670
676
  }
671
677
  //#endregion
672
678
  //#region src/core/manifest.ts
673
- var Ae = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
674
- function je(e) {
675
- return Ae.test(e);
679
+ var je = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
680
+ function Me(e) {
681
+ return je.test(e);
676
682
  }
677
683
  //#endregion
678
684
  //#region src/core/env.ts
@@ -695,11 +701,11 @@ function R(e) {
695
701
  return "";
696
702
  }
697
703
  }
698
- var Me = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
699
- function Ne(e) {
704
+ var Ne = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
705
+ function Pe(e) {
700
706
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
701
707
  let t = "", n = -1, r = performance.getEntriesByType("resource");
702
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Me.test(i.name)) && i.startTime >= n) {
708
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ne.test(i.name)) && i.startTime >= n) {
703
709
  let e = R(i.name);
704
710
  e && (t = e, n = i.startTime);
705
711
  }
@@ -712,7 +718,7 @@ function z(e) {
712
718
  totalFrames: t?.totalVideoFrames ?? 0
713
719
  };
714
720
  }
715
- function Pe(e, t) {
721
+ function Fe(e, t) {
716
722
  let n = [
717
723
  ["playing", () => t("playing")],
718
724
  ["waiting", () => t("buffering")],
@@ -729,7 +735,7 @@ function Pe(e, t) {
729
735
  }
730
736
  //#endregion
731
737
  //#region src/core/engine/native.ts
732
- function Fe(e) {
738
+ function Ie(e) {
733
739
  try {
734
740
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
735
741
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -781,7 +787,7 @@ var H = class {
781
787
  type: "error",
782
788
  error: new n("INTERNAL", 0, "native HLS playback error"),
783
789
  fatal: !0
784
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ie(t.manifestUrl, t.analytics?.sid), e.load();
790
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Le(t.manifestUrl, t.analytics?.sid), e.load();
785
791
  }
786
792
  startLoad() {
787
793
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -803,7 +809,7 @@ var H = class {
803
809
  });
804
810
  this.onEncrypted = (n) => {
805
811
  let i = n;
806
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Fe(i.initData), (async () => {
812
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ie(i.initData), (async () => {
807
813
  try {
808
814
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
809
815
  initDataTypes: [i.initDataType],
@@ -902,7 +908,7 @@ var H = class {
902
908
  droppedFrames: t.dropped,
903
909
  decodedFrames: t.totalFrames
904
910
  };
905
- return this.cdnHost ||= Ne(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
911
+ return this.cdnHost ||= Pe(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
906
912
  }
907
913
  stop() {
908
914
  try {
@@ -921,25 +927,25 @@ var H = class {
921
927
  } catch {}
922
928
  }
923
929
  };
924
- function Ie(e, t) {
930
+ function Le(e, t) {
925
931
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
926
932
  }
927
933
  //#endregion
928
934
  //#region src/core/engine/hls.ts
929
- function Le() {
935
+ function Re() {
930
936
  return e.isSupported();
931
937
  }
932
- var Re = 3, ze = 5, Be = 3, Ve = 3e4, He = 12e3, Ue = 3e3, U = 6e3, We = 5e3, Ge = 4e3, Ke = 2, qe = 5, Je = 2, Ye = 2, Xe = 2e3, Ze = 3e4, Qe = 2, $e = 9, et = .5, tt = 64;
933
- function nt(e) {
938
+ var ze = 3, Be = 5, Ve = 3, He = 3e4, Ue = 12e3, We = 3e3, U = 6e3, Ge = 5e3, Ke = 4e3, qe = 2, Je = 5, Ye = 2, Xe = 2, Ze = 2e3, Qe = 3e4, $e = 2, et = 9, tt = .5, nt = 64;
939
+ function rt(e) {
934
940
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
935
941
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
936
942
  return;
937
943
  }
938
- e.liveSyncDuration ??= Qe;
939
- let t = Math.max(12, e.liveSyncDuration + $e);
940
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), rt(e, e.liveSyncDuration);
944
+ e.liveSyncDuration ??= $e;
945
+ let t = Math.max(12, e.liveSyncDuration + et);
946
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), it(e, e.liveSyncDuration);
941
947
  }
942
- function rt(e, t) {
948
+ function it(e, t) {
943
949
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
944
950
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
945
951
  }
@@ -1034,7 +1040,7 @@ var W = class {
1034
1040
  }
1035
1041
  this.loadSuspended = !0;
1036
1042
  }
1037
- }, We));
1043
+ }, Ge));
1038
1044
  }
1039
1045
  resumeLoading() {
1040
1046
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1066,7 +1072,7 @@ var W = class {
1066
1072
  let t = e.liveSyncPosition;
1067
1073
  if (typeof t != "number" || !Number.isFinite(t)) return;
1068
1074
  let { video: n } = this.deps;
1069
- n.currentTime <= t + et || (n.currentTime = t);
1075
+ n.currentTime <= t + tt || (n.currentTime = t);
1070
1076
  }
1071
1077
  startHls() {
1072
1078
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1090,7 +1096,7 @@ var W = class {
1090
1096
  videoEncryptionScheme: "cbcs",
1091
1097
  audioEncryptionScheme: "cbcs"
1092
1098
  },
1093
- ...M() ? { requestMediaKeySystemAccessFunc: Ce(t) } : {},
1099
+ ...M() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
1094
1100
  licenseXhrSetup: (e, t) => {
1095
1101
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
1096
1102
  let o = performance.now();
@@ -1106,7 +1112,7 @@ var W = class {
1106
1112
  } } : {},
1107
1113
  ...c
1108
1114
  };
1109
- nt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1115
+ rt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1110
1116
  let f = new e(d);
1111
1117
  this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1112
1118
  this.mediaRecoveries = 0, this.networkRecoveries = 0;
@@ -1115,14 +1121,14 @@ var W = class {
1115
1121
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1116
1122
  t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1117
1123
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1118
- }, Ve)));
1124
+ }, He)));
1119
1125
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1120
1126
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1121
1127
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
1122
1128
  let n = t?.frag?.stats, r = n?.loaded;
1123
1129
  typeof r == "number" && (this.bytesLoaded += r);
1124
1130
  let i = n?.loading;
1125
- 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 > tt && this.requestTimesMs.shift());
1131
+ 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 > nt && this.requestTimesMs.shift());
1126
1132
  let a = t?.frag?.url;
1127
1133
  if (a) {
1128
1134
  let e = R(a);
@@ -1138,7 +1144,7 @@ var W = class {
1138
1144
  }));
1139
1145
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1140
1146
  this.checkEndStale(), this.checkStarvation();
1141
- }, Ue), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1147
+ }, We), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1142
1148
  this.renditionSwitches += 1;
1143
1149
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1144
1150
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1202,7 +1208,7 @@ var W = class {
1202
1208
  return;
1203
1209
  }
1204
1210
  this.capTimer && clearTimeout(this.capTimer);
1205
- let t = e > this.sizeCapLevel ? Xe : Ze;
1211
+ let t = e > this.sizeCapLevel ? Ze : Qe;
1206
1212
  this.capTimer = setTimeout(() => {
1207
1213
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1208
1214
  }, t);
@@ -1295,7 +1301,7 @@ var W = class {
1295
1301
  return;
1296
1302
  }
1297
1303
  let e = Date.now() - this.lastAdvanceMs;
1298
- !this.chaseSuspended && e > U && this.suspendChasing(), e > He && this.emitEnded("stalled");
1304
+ !this.chaseSuspended && e > U && this.suspendChasing(), e > Ue && this.emitEnded("stalled");
1299
1305
  }
1300
1306
  checkStarvation() {
1301
1307
  let e = this.hls, { video: t } = this.deps;
@@ -1304,17 +1310,17 @@ var W = class {
1304
1310
  this.starvedTicks = 0;
1305
1311
  return;
1306
1312
  }
1307
- let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ge;
1313
+ let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ke;
1308
1314
  if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
1309
1315
  this.starvedTicks = 0;
1310
1316
  return;
1311
1317
  }
1312
- if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ke)) {
1313
- if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Je && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Ye)) {
1318
+ if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < qe)) {
1319
+ if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ye && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Xe)) {
1314
1320
  this.starvationRebuilds += 1, console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
1315
1321
  return;
1316
1322
  }
1317
- if (!(this.starvationKicks >= qe)) {
1323
+ if (!(this.starvationKicks >= Je)) {
1318
1324
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1319
1325
  try {
1320
1326
  e.stopLoad(), e.startLoad(-1);
@@ -1364,7 +1370,7 @@ var W = class {
1364
1370
  scheduleLicenseRetry(t) {
1365
1371
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1366
1372
  let n = t.response?.code ?? 0;
1367
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Be) return !1;
1373
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ve) return !1;
1368
1374
  this.licenseRecoveries += 1;
1369
1375
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1370
1376
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1396,7 +1402,7 @@ var W = class {
1396
1402
  return;
1397
1403
  }
1398
1404
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1399
- if (this.networkRecoveries < ze) {
1405
+ if (this.networkRecoveries < Be) {
1400
1406
  this.networkRecoveries += 1;
1401
1407
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1402
1408
  this.networkRetryTimer = setTimeout(() => {
@@ -1413,7 +1419,7 @@ var W = class {
1413
1419
  return;
1414
1420
  }
1415
1421
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1416
- if (this.mediaRecoveries < Re) {
1422
+ if (this.mediaRecoveries < ze) {
1417
1423
  this.mediaRecoveries += 1, n.recoverMediaError();
1418
1424
  return;
1419
1425
  }
@@ -1437,11 +1443,11 @@ var W = class {
1437
1443
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1438
1444
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1439
1445
  }
1440
- }, it = 15e3, at = 6e5, ot = 3e5, st = 100, G = 1, ct = 1e3, K = 3e4, lt = 1e3, ut = {
1446
+ }, at = 15e3, ot = 6e5, st = 3e5, ct = 100, G = 1, lt = 1e3, K = 3e4, ut = 1e3, dt = {
1441
1447
  inline: "PRESENTATION_INLINE",
1442
1448
  fullscreen: "PRESENTATION_FULLSCREEN",
1443
1449
  pip: "PRESENTATION_PIP"
1444
- }, dt = {
1450
+ }, ft = {
1445
1451
  widevine: "KEY_SYSTEM_WIDEVINE",
1446
1452
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1447
1453
  none: "KEY_SYSTEM_NONE"
@@ -1449,7 +1455,7 @@ var W = class {
1449
1455
  function q(e, t) {
1450
1456
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1451
1457
  }
1452
- var ft = /* @__PURE__ */ new Set([
1458
+ var pt = /* @__PURE__ */ new Set([
1453
1459
  "INVALID_URN",
1454
1460
  "NOT_FOUND",
1455
1461
  "GONE",
@@ -1469,7 +1475,7 @@ var ft = /* @__PURE__ */ new Set([
1469
1475
  ended: "PLAYER_STATE_ENDED",
1470
1476
  error: "PLAYER_STATE_ERROR"
1471
1477
  };
1472
- function pt(e) {
1478
+ function mt(e) {
1473
1479
  try {
1474
1480
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1475
1481
  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);
@@ -1481,10 +1487,10 @@ var Y = /* @__PURE__ */ new Set();
1481
1487
  function X(e, t) {
1482
1488
  return Y.has(e) || (Y.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
1483
1489
  }
1484
- function mt(e, t) {
1490
+ function ht(e, t) {
1485
1491
  if (t) return { endpoint: t };
1486
1492
  if (t !== void 0) return X("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).");
1487
- let n = pt(e);
1493
+ let n = mt(e);
1488
1494
  if (n) return { endpoint: n };
1489
1495
  let r;
1490
1496
  try {
@@ -1494,7 +1500,7 @@ function mt(e, t) {
1494
1500
  }
1495
1501
  return X(r, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${r}" — 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).`);
1496
1502
  }
1497
- var ht = class {
1503
+ var gt = class {
1498
1504
  opts;
1499
1505
  url;
1500
1506
  now;
@@ -1572,8 +1578,8 @@ var ht = class {
1572
1578
  constructor(e) {
1573
1579
  this.opts = {
1574
1580
  ...e,
1575
- heartbeatMs: e.heartbeatMs ?? it,
1576
- idleMs: e.idleMs ?? at
1581
+ heartbeatMs: e.heartbeatMs ?? at,
1582
+ idleMs: e.idleMs ?? ot
1577
1583
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1578
1584
  }
1579
1585
  start() {
@@ -1583,11 +1589,11 @@ var ht = class {
1583
1589
  sdkVersion: this.opts.sdkVersion,
1584
1590
  ...this.opts.environment
1585
1591
  };
1586
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), ct), 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.onVisibility());
1592
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), lt), 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.onVisibility());
1587
1593
  }
1588
1594
  checkSuspension(e) {
1589
1595
  if (this.endedFlag || !this.opts.idleMs) return !1;
1590
- let t = Math.max(this.opts.idleMs, ot);
1596
+ let t = Math.max(this.opts.idleMs, st);
1591
1597
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1592
1598
  }
1593
1599
  syncIdle(e) {
@@ -1610,12 +1616,12 @@ var ht = class {
1610
1616
  let a = {
1611
1617
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
1612
1618
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
1613
- presentation: ut[this.presentation]
1619
+ presentation: dt[this.presentation]
1614
1620
  }, o = this.causeOf(e, t, i);
1615
1621
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1616
1622
  }
1617
1623
  seekInduced(e) {
1618
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < lt;
1624
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < ut;
1619
1625
  }
1620
1626
  causeOf(e, t, n) {
1621
1627
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1683,7 +1689,7 @@ var ht = class {
1683
1689
  let r = n ?? "";
1684
1690
  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";
1685
1691
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
1686
- if (ft.has(e)) return "ERROR_STAGE_RESOLVE";
1692
+ if (pt.has(e)) return "ERROR_STAGE_RESOLVE";
1687
1693
  let i = t ?? "";
1688
1694
  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";
1689
1695
  }
@@ -1737,7 +1743,7 @@ var ht = class {
1737
1743
  maybeEmitMediaInfo(e) {
1738
1744
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
1739
1745
  let t = {};
1740
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = dt[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);
1746
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ft[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);
1741
1747
  let n = JSON.stringify(t);
1742
1748
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
1743
1749
  }
@@ -1777,7 +1783,7 @@ var ht = class {
1777
1783
  };
1778
1784
  }
1779
1785
  enqueue(e) {
1780
- for (this.pending.push(this.wrap(e)); this.pending.length > st;) {
1786
+ for (this.pending.push(this.wrap(e)); this.pending.length > ct;) {
1781
1787
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
1782
1788
  this.pending.splice(e >= 0 ? e : 0, 1);
1783
1789
  }
@@ -1800,7 +1806,7 @@ var ht = class {
1800
1806
  };
1801
1807
  //#endregion
1802
1808
  //#region src/core/environment.ts
1803
- function gt() {
1809
+ function _t() {
1804
1810
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
1805
1811
  let e;
1806
1812
  try {
@@ -1825,14 +1831,14 @@ function gt() {
1825
1831
  integration: "INTEGRATION_KIND_IFRAME"
1826
1832
  };
1827
1833
  }
1828
- function _t() {
1834
+ function vt() {
1829
1835
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
1830
1836
  let e = navigator.userAgentData, t = e?.platform ?? "";
1831
1837
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
1832
1838
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
1833
1839
  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";
1834
1840
  }
1835
- function vt() {
1841
+ function yt() {
1836
1842
  let e = typeof navigator < "u" ? navigator.connection : void 0;
1837
1843
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
1838
1844
  let t = {
@@ -1851,17 +1857,17 @@ function vt() {
1851
1857
  }
1852
1858
  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;
1853
1859
  }
1854
- function yt(e) {
1855
- let t = gt(), n = {
1856
- deviceClass: _t(),
1860
+ function bt(e) {
1861
+ let t = _t(), n = {
1862
+ deviceClass: vt(),
1857
1863
  integration: t.integration,
1858
- ...vt()
1864
+ ...yt()
1859
1865
  };
1860
1866
  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);
1861
1867
  let r = e.getBoundingClientRect?.();
1862
1868
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
1863
1869
  }
1864
- async function bt() {
1870
+ async function xt() {
1865
1871
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
1866
1872
  if (!e?.getHighEntropyValues) return {};
1867
1873
  try {
@@ -1873,7 +1879,7 @@ async function bt() {
1873
1879
  }
1874
1880
  //#endregion
1875
1881
  //#region src/core/version.ts
1876
- var xt = "2.9.1", St = {
1882
+ var St = "2.9.2", Ct = {
1877
1883
  accent: "#E1B600",
1878
1884
  accentText: "#1B1C23",
1879
1885
  background: "#0e0f13",
@@ -1884,7 +1890,7 @@ var xt = "2.9.1", St = {
1884
1890
  border: "rgba(255, 255, 255, 0.1)",
1885
1891
  radius: "8px",
1886
1892
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1887
- }, Ct = {
1893
+ }, wt = {
1888
1894
  accent: "--havik-accent",
1889
1895
  accentText: "--havik-accent-text",
1890
1896
  background: "--havik-bg",
@@ -1896,25 +1902,25 @@ var xt = "2.9.1", St = {
1896
1902
  radius: "--havik-radius",
1897
1903
  fontFamily: "--havik-font"
1898
1904
  };
1899
- function wt(e, t) {
1905
+ function Tt(e, t) {
1900
1906
  let n = {
1901
- ...St,
1907
+ ...Ct,
1902
1908
  ...t
1903
1909
  };
1904
- for (let t of Object.keys(Ct)) e.style.setProperty(Ct[t], n[t]);
1910
+ for (let t of Object.keys(wt)) e.style.setProperty(wt[t], n[t]);
1905
1911
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1906
1912
  }
1907
1913
  //#endregion
1908
1914
  //#region src/ui/styles.ts
1909
- var Tt = "havik-player-styles", Et = "\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/* 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";
1910
- function Dt(e = document) {
1911
- if (e.getElementById(Tt)) return;
1915
+ var Et = "havik-player-styles", Dt = "\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/* 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";
1916
+ function Ot(e = document) {
1917
+ if (e.getElementById(Et)) return;
1912
1918
  let t = e.createElement("style");
1913
- t.id = Tt, t.textContent = Et, e.head.appendChild(t);
1919
+ t.id = Et, t.textContent = Dt, e.head.appendChild(t);
1914
1920
  }
1915
1921
  //#endregion
1916
1922
  //#region src/ui/icons.ts
1917
- var Ot = {
1923
+ var kt = {
1918
1924
  play: "<path d=\"M8 5v14l11-7z\"/>",
1919
1925
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1920
1926
  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\"/>",
@@ -1928,20 +1934,20 @@ var Ot = {
1928
1934
  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\"/>"
1929
1935
  };
1930
1936
  function Z(e) {
1931
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ot[e]}</svg>`;
1937
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${kt[e]}</svg>`;
1932
1938
  }
1933
1939
  //#endregion
1934
1940
  //#region src/ui/controls.ts
1935
- var kt = 3e3, At = /* @__PURE__ */ new Set([
1941
+ var At = 3e3, jt = /* @__PURE__ */ new Set([
1936
1942
  "GONE",
1937
1943
  "NOT_FOUND",
1938
1944
  "INVALID_URN",
1939
1945
  "UNAUTHORIZED"
1940
1946
  ]);
1941
- function jt(e) {
1942
- return new Mt(e);
1947
+ function Mt(e) {
1948
+ return new Nt(e);
1943
1949
  }
1944
- var Mt = class {
1950
+ var Nt = class {
1945
1951
  root;
1946
1952
  video;
1947
1953
  player;
@@ -1983,7 +1989,7 @@ var Mt = class {
1983
1989
  scrubbing = !1;
1984
1990
  offFns = [];
1985
1991
  constructor(e) {
1986
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? kt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Dt(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");
1992
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? At, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Ot(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");
1987
1993
  let t = (e, t, n) => {
1988
1994
  let r = this.doc.createElement(e);
1989
1995
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2074,7 +2080,7 @@ var Mt = class {
2074
2080
  e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2075
2081
  } else {
2076
2082
  let r = this.doc.createElement("div");
2077
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !At.has(this.lastError.code)) {
2083
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !jt.has(this.lastError.code)) {
2078
2084
  let e = this.doc.createElement("button");
2079
2085
  e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2080
2086
  }
@@ -2115,7 +2121,7 @@ var Mt = class {
2115
2121
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2116
2122
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2117
2123
  }
2118
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Nt(this.video.currentTime)} / ${Nt(this.video.duration)}`);
2124
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Pt(this.video.currentTime)} / ${Pt(this.video.duration)}`);
2119
2125
  }
2120
2126
  syncLive() {
2121
2127
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2165,17 +2171,17 @@ var Mt = class {
2165
2171
  renderQualityMenu() {
2166
2172
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2167
2173
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2168
- for (let n of e) this.menu.append(this.menuItem(Pt(n), t === n.index, () => this.player.setQuality(n.index)));
2174
+ for (let n of e) this.menu.append(this.menuItem(Ft(n), t === n.index, () => this.player.setQuality(n.index)));
2169
2175
  }
2170
2176
  renderAudioMenu() {
2171
2177
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2172
2178
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2173
- for (let t of e) this.menu.append(this.menuItem(Ft(t), t.default, () => this.player.setAudioTrack(t.id)));
2179
+ for (let t of e) this.menu.append(this.menuItem(It(t), t.default, () => this.player.setAudioTrack(t.id)));
2174
2180
  }
2175
2181
  renderCcMenu() {
2176
2182
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2177
2183
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2178
- for (let t of e) this.menu.append(this.menuItem(It(t), !1, () => this.player.setTextTrack(t.id)));
2184
+ for (let t of e) this.menu.append(this.menuItem(Lt(t), !1, () => this.player.setTextTrack(t.id)));
2179
2185
  }
2180
2186
  onTracksChanged() {
2181
2187
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2275,41 +2281,41 @@ var Mt = class {
2275
2281
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2276
2282
  }
2277
2283
  };
2278
- function Nt(e) {
2284
+ function Pt(e) {
2279
2285
  (!Number.isFinite(e) || e < 0) && (e = 0);
2280
2286
  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");
2281
2287
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2282
2288
  }
2283
- function Pt(e) {
2289
+ function Ft(e) {
2284
2290
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2285
2291
  }
2286
- function Ft(e) {
2292
+ function It(e) {
2287
2293
  return e.name || e.lang || `Track ${e.id}`;
2288
2294
  }
2289
- function It(e) {
2295
+ function Lt(e) {
2290
2296
  return e.name || e.lang || `Track ${e.id}`;
2291
2297
  }
2292
2298
  //#endregion
2293
2299
  //#region src/managed/index.ts
2294
- var Lt = 6e3, Q = 45e3, Rt = 2e3, zt = 3, Bt = 2e3, Vt = 48e4;
2295
- function Ht(e) {
2300
+ var Rt = 6e3, Q = 45e3, zt = 2e3, Bt = 3, Vt = 2e3, Ht = 48e4;
2301
+ function Ut(e) {
2296
2302
  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)})`);
2297
2303
  if (e.env !== void 0) return I(e.env);
2298
2304
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2299
2305
  return e.baseUrl;
2300
2306
  }
2301
- async function Ut(e) {
2307
+ async function Wt(e) {
2302
2308
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2303
- let t = Ht(e);
2309
+ let t = Ut(e);
2304
2310
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2305
2311
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2306
- let r = new Wt({
2312
+ let r = new Gt({
2307
2313
  ...e,
2308
2314
  baseUrl: t
2309
2315
  });
2310
2316
  return await r.start(), r;
2311
2317
  }
2312
- var Wt = class {
2318
+ var Gt = class {
2313
2319
  opts;
2314
2320
  abort = new AbortController();
2315
2321
  listeners = {};
@@ -2436,13 +2442,13 @@ var Wt = class {
2436
2442
  !a && !p() && h();
2437
2443
  }, e);
2438
2444
  };
2439
- _(Lt), this.armingSub = E({
2445
+ _(Rt), this.armingSub = E({
2440
2446
  eventsBaseUrl: t,
2441
2447
  matchUrn: this.opts.matchUrn,
2442
2448
  credential: this.opts.credential,
2443
2449
  onAlive: () => _(Q),
2444
2450
  onState: (e) => {
2445
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Rt);
2451
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * zt);
2446
2452
  },
2447
2453
  onError: () => h()
2448
2454
  });
@@ -2465,7 +2471,7 @@ var Wt = class {
2465
2471
  let n = await s(this.opts.credential);
2466
2472
  if (this.destroyed || t !== this.loadGen) return;
2467
2473
  this.setState("loading");
2468
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Pe(this.opts.video, (e) => {
2474
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Fe(this.opts.video, (e) => {
2469
2475
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2470
2476
  });
2471
2477
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2487,19 +2493,19 @@ var Wt = class {
2487
2493
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2488
2494
  let i = e.analytics?.sid;
2489
2495
  if (!i) return;
2490
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = mt(this.opts.baseUrl, a);
2496
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ht(this.opts.baseUrl, a);
2491
2497
  if (!o) {
2492
2498
  s && setTimeout(() => {
2493
2499
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2494
2500
  }, 0);
2495
2501
  return;
2496
2502
  }
2497
- let c = this.opts.video, l = new ht({
2503
+ let c = this.opts.video, l = new gt({
2498
2504
  endpoint: o,
2499
2505
  sid: i,
2500
2506
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2501
- sdkVersion: xt,
2502
- environment: yt(c),
2507
+ sdkVersion: St,
2508
+ environment: bt(c),
2503
2509
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2504
2510
  onIdle: () => this.onAnalyticsIdle(t),
2505
2511
  sample: () => {
@@ -2517,7 +2523,7 @@ var Wt = class {
2517
2523
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2518
2524
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2519
2525
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
2520
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), bt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2526
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), xt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2521
2527
  }
2522
2528
  currentPresentation() {
2523
2529
  let e = this.opts.video;
@@ -2544,7 +2550,7 @@ var Wt = class {
2544
2550
  if (o === "native") return new H(a);
2545
2551
  if (o === "hls") return new W(a);
2546
2552
  if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V()) return new H(a);
2547
- if (Le()) return new W(a);
2553
+ if (Re()) return new W(a);
2548
2554
  if (B(this.opts.video)) return new H(a);
2549
2555
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2550
2556
  }
@@ -2588,7 +2594,7 @@ var Wt = class {
2588
2594
  r = 0, i = !1;
2589
2595
  },
2590
2596
  onError: () => {
2591
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= zt && (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.`))));
2597
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Bt && (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.`))));
2592
2598
  }
2593
2599
  });
2594
2600
  }
@@ -2610,7 +2616,7 @@ var Wt = class {
2610
2616
  scheduleRejoin(e) {
2611
2617
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2612
2618
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2613
- }, Math.random() * Rt));
2619
+ }, Math.random() * zt));
2614
2620
  }
2615
2621
  cancelRejoin() {
2616
2622
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2634,7 +2640,7 @@ var Wt = class {
2634
2640
  }
2635
2641
  t.controls = !1;
2636
2642
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2637
- r && r.insertBefore(n, t), n.appendChild(t), wt(n, this.opts.theme), this.container = n, this.controlBar = jt({
2643
+ r && r.insertBefore(n, t), n.appendChild(t), Tt(n, this.opts.theme), this.container = n, this.controlBar = Mt({
2638
2644
  root: n,
2639
2645
  video: t,
2640
2646
  player: this,
@@ -2664,7 +2670,7 @@ var Wt = class {
2664
2670
  }
2665
2671
  startStats() {
2666
2672
  this.stopStats();
2667
- let e = Math.max(500, this.opts.statsIntervalMs ?? Bt);
2673
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Vt);
2668
2674
  this.statsTimer = setInterval(() => {
2669
2675
  if (!this.engine) return;
2670
2676
  let e = this.engine.getStats();
@@ -2676,7 +2682,7 @@ var Wt = class {
2676
2682
  }
2677
2683
  scheduleLicenseRefresh() {
2678
2684
  this.stopRefresh();
2679
- let e = this.opts.licenseRefreshMs ?? Vt;
2685
+ let e = this.opts.licenseRefreshMs ?? Ht;
2680
2686
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2681
2687
  }
2682
2688
  stopRefresh() {
@@ -2831,7 +2837,7 @@ function $(e) {
2831
2837
  }
2832
2838
  //#endregion
2833
2839
  //#region src/embed/host.ts
2834
- function Gt(e) {
2840
+ function Kt(e) {
2835
2841
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2836
2842
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2837
2843
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2890,15 +2896,15 @@ function Gt(e) {
2890
2896
  }
2891
2897
  //#endregion
2892
2898
  //#region src/embed/page.ts
2893
- var Kt = /^[A-Za-z0-9:_.-]{1,128}$/;
2894
- function qt(e) {
2899
+ var qt = /^[A-Za-z0-9:_.-]{1,128}$/;
2900
+ function Jt(e) {
2895
2901
  if (typeof e == "boolean") return e;
2896
2902
  if (typeof e == "object" && e) {
2897
2903
  let t = e.endpoint;
2898
2904
  return typeof t == "string" ? { endpoint: t } : {};
2899
2905
  }
2900
2906
  }
2901
- function Jt() {
2907
+ function Yt() {
2902
2908
  let e = window.HAVIK_EMBED_CONFIG;
2903
2909
  if (e) return {
2904
2910
  baseUrl: e.baseUrl ?? "",
@@ -2908,7 +2914,7 @@ function Jt() {
2908
2914
  autoplay: e.autoplay ?? !0,
2909
2915
  muted: e.muted ?? !0,
2910
2916
  waitForLive: e.waitForLive ?? !0,
2911
- analytics: qt(e.analytics)
2917
+ analytics: Jt(e.analytics)
2912
2918
  };
2913
2919
  let t = new URLSearchParams(location.search);
2914
2920
  return {
@@ -2921,9 +2927,9 @@ function Jt() {
2921
2927
  waitForLive: !0
2922
2928
  };
2923
2929
  }
2924
- async function Yt() {
2925
- let e = Jt();
2926
- Zt();
2930
+ async function Xt() {
2931
+ let e = Yt();
2932
+ Qt();
2927
2933
  let t = document.createElement("video");
2928
2934
  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);
2929
2935
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2978,12 +2984,12 @@ async function Yt() {
2978
2984
  code: e.code,
2979
2985
  message: e.message
2980
2986
  })), e.on("autoplayblocked", () => {
2981
- i({ type: "oddin:autoplayblocked" }), Xt(t, e);
2987
+ i({ type: "oddin:autoplayblocked" }), Zt(t, e);
2982
2988
  });
2983
2989
  }, s = async (r) => {
2984
2990
  a?.destroy(), a = null;
2985
2991
  try {
2986
- let n = await Ut({
2992
+ let n = await Wt({
2987
2993
  video: t,
2988
2994
  baseUrl: e.baseUrl,
2989
2995
  matchUrn: r,
@@ -3045,7 +3051,7 @@ async function Yt() {
3045
3051
  a?.retry();
3046
3052
  break;
3047
3053
  case "oddin:load":
3048
- typeof e.matchUrn == "string" && Kt.test(e.matchUrn) && s(e.matchUrn);
3054
+ typeof e.matchUrn == "string" && qt.test(e.matchUrn) && s(e.matchUrn);
3049
3055
  break;
3050
3056
  case "oddin:destroy": c();
3051
3057
  }
@@ -3057,18 +3063,18 @@ async function Yt() {
3057
3063
  protocol: 1
3058
3064
  });
3059
3065
  }
3060
- function Xt(e, t) {
3066
+ function Zt(e, t) {
3061
3067
  if (document.getElementById("havik-tap")) return;
3062
3068
  let n = document.createElement("button");
3063
3069
  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", () => {
3064
3070
  n.remove(), t.play();
3065
3071
  }), document.body.appendChild(n);
3066
3072
  }
3067
- function Zt() {
3073
+ function Qt() {
3068
3074
  let e = document.createElement("style");
3069
3075
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3070
3076
  }
3071
3077
  //#endregion
3072
- export { St as ODDIN_THEME, n as PlaybackError, wt as applyTheme, I as baseUrlForEnv, Yt as bootEmbed, _e as clearDeviceId, Ut as createPlayer, D as deriveEventsBaseUrl, ke as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, je as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, Gt as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
3078
+ export { Ct as ODDIN_THEME, n as PlaybackError, Tt as applyTheme, I as baseUrlForEnv, Xt as bootEmbed, ve as clearDeviceId, Wt as createPlayer, D as deriveEventsBaseUrl, Ae as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, de as fetchCatalog, pe as fetchTournament, he as flattenMatches, A as getDeviceId, Me as isLowLatencyManifest, $ as isOddinMessage, be as licenseRequestHeaders, Kt as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, ge as watchStatus };
3073
3079
 
3074
3080
  //# sourceMappingURL=index.js.map