@oddin-gg/havik-player 2.0.1 → 2.0.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
@@ -819,17 +819,17 @@ function Ee(e, t) {
819
819
  function De() {
820
820
  return e.isSupported();
821
821
  }
822
- var Oe = 3, ke = 5, Ae = 3, je = 3e4, Me = 12e3, Ne = 3e3, B = 6e3, Pe = 4e3, Fe = 2, Ie = 5, Le = 2e3, Re = 3e4, ze = 2, Be = 9, Ve = .5;
823
- function He(e) {
822
+ var Oe = 3, ke = 5, Ae = 3, je = 3e4, Me = 12e3, Ne = 3e3, B = 6e3, Pe = 4e3, Fe = 2, Ie = 5, Le = 2, Re = 2, ze = 2e3, Be = 3e4, Ve = 2, He = 9, Ue = .5;
823
+ function We(e) {
824
824
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
825
825
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
826
826
  return;
827
827
  }
828
- e.liveSyncDuration ??= ze;
829
- let t = Math.max(12, e.liveSyncDuration + Be);
830
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ue(e, e.liveSyncDuration);
828
+ e.liveSyncDuration ??= Ve;
829
+ let t = Math.max(12, e.liveSyncDuration + He);
830
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ge(e, e.liveSyncDuration);
831
831
  }
832
- function Ue(e, t) {
832
+ function Ge(e, t) {
833
833
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
834
834
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
835
835
  }
@@ -859,6 +859,9 @@ var V = class {
859
859
  lastFragLoadingMs = 0;
860
860
  starvedTicks = 0;
861
861
  starvationKicks = 0;
862
+ kickPending = !1;
863
+ kickTicks = 0;
864
+ starvationRebuilds = 0;
862
865
  chaseSuspended = !1;
863
866
  savedLiveMaxLatency;
864
867
  savedMaxSyncRate;
@@ -910,10 +913,12 @@ var V = class {
910
913
  let t = e.liveSyncPosition;
911
914
  if (typeof t != "number" || !Number.isFinite(t)) return;
912
915
  let { video: n } = this.deps;
913
- n.currentTime <= t + Ve || (n.currentTime = t);
916
+ n.currentTime <= t + Ue || (n.currentTime = t);
914
917
  }
915
918
  startHls() {
916
- let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
919
+ let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
920
+ this.kickPending = !1, this.kickTicks = 0, this.starvedTicks = 0, this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
921
+ let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
917
922
  debug: s === !0,
918
923
  enableWorker: !o,
919
924
  lowLatencyMode: o,
@@ -946,14 +951,14 @@ var V = class {
946
951
  } } : {},
947
952
  ...c
948
953
  };
949
- He(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0;
954
+ We(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0;
950
955
  let f = new e(d);
951
956
  this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
952
957
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.applySizeCap(), l({ type: "ready" });
953
958
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
954
- t?.frag?.type === "main" && (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
955
- this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.recoveryResetTimer = null;
956
- }, je));
959
+ 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(() => {
960
+ this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
961
+ }, je)));
957
962
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
958
963
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
959
964
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -967,7 +972,7 @@ var V = class {
967
972
  type: "lowLatencyDetected",
968
973
  value: !0
969
974
  }));
970
- }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() => {
975
+ }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
971
976
  this.checkEndStale(), this.checkStarvation();
972
977
  }, Ne), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
973
978
  this.renditionSwitches += 1, l({
@@ -1031,7 +1036,7 @@ var V = class {
1031
1036
  return;
1032
1037
  }
1033
1038
  this.capTimer && clearTimeout(this.capTimer);
1034
- let t = e > this.sizeCapLevel ? Le : Re;
1039
+ let t = e > this.sizeCapLevel ? ze : Be;
1035
1040
  this.capTimer = setTimeout(() => {
1036
1041
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1037
1042
  }, t);
@@ -1126,12 +1131,18 @@ var V = class {
1126
1131
  this.starvedTicks = 0;
1127
1132
  return;
1128
1133
  }
1129
- if (!(++this.starvedTicks < Fe) && (this.starvedTicks = 0, !(this.starvationKicks >= Ie))) {
1130
- this.starvationKicks += 1, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting load at the live edge");
1131
- try {
1132
- e.stopLoad(), e.startLoad(-1);
1133
- } catch (e) {
1134
- console.warn("havik-player: starvation kick failed", e);
1134
+ if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Fe)) {
1135
+ if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Le && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Re)) {
1136
+ 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");
1137
+ return;
1138
+ }
1139
+ if (!(this.starvationKicks >= Ie)) {
1140
+ 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");
1141
+ try {
1142
+ e.stopLoad(), e.startLoad(-1);
1143
+ } catch (e) {
1144
+ console.warn("havik-player: starvation kick failed", e);
1145
+ }
1135
1146
  }
1136
1147
  }
1137
1148
  }
@@ -1151,7 +1162,7 @@ var V = class {
1151
1162
  }));
1152
1163
  }
1153
1164
  stop() {
1154
- this.endWatchdog &&= (clearInterval(this.endWatchdog), null);
1165
+ this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0;
1155
1166
  try {
1156
1167
  this.hls?.stopLoad();
1157
1168
  } catch {}
@@ -1179,16 +1190,19 @@ var V = class {
1179
1190
  this.licenseRecoveries += 1;
1180
1191
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1181
1192
  return this.licenseRetryTimer = setTimeout(() => {
1182
- if (this.licenseRetryTimer = null, this.hls) {
1183
- try {
1184
- this.hls.destroy();
1185
- } catch (e) {
1186
- console.warn("havik-player: hls.js destroy() threw during license retry", e);
1187
- }
1188
- this.hls = null, this.startHls();
1189
- }
1193
+ this.licenseRetryTimer = null, this.rebuildInstance("license retry");
1190
1194
  }, r), !0;
1191
1195
  }
1196
+ rebuildInstance(e) {
1197
+ if (this.hls) {
1198
+ try {
1199
+ this.hls.destroy();
1200
+ } catch (t) {
1201
+ console.warn(`havik-player: hls.js destroy() threw during ${e}`, t);
1202
+ }
1203
+ this.hls = null, this.startHls();
1204
+ }
1205
+ }
1192
1206
  onError(t) {
1193
1207
  if (!t.fatal) return;
1194
1208
  let n = this.hls;
@@ -1241,7 +1255,7 @@ var V = class {
1241
1255
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1242
1256
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1243
1257
  }
1244
- }, We = 15e3, Ge = 100, H = 1, U = {
1258
+ }, Ke = 15e3, qe = 100, H = 1, U = {
1245
1259
  idle: "PLAYER_STATE_IDLE",
1246
1260
  waiting: "PLAYER_STATE_WAITING",
1247
1261
  loading: "PLAYER_STATE_LOADING",
@@ -1251,7 +1265,7 @@ var V = class {
1251
1265
  ended: "PLAYER_STATE_ENDED",
1252
1266
  error: "PLAYER_STATE_ERROR"
1253
1267
  };
1254
- function Ke(e) {
1268
+ function Je(e) {
1255
1269
  try {
1256
1270
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1257
1271
  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);
@@ -1259,7 +1273,7 @@ function Ke(e) {
1259
1273
  return;
1260
1274
  }
1261
1275
  }
1262
- var qe = class {
1276
+ var Ye = class {
1263
1277
  opts;
1264
1278
  url;
1265
1279
  now;
@@ -1294,7 +1308,7 @@ var qe = class {
1294
1308
  constructor(e) {
1295
1309
  this.opts = {
1296
1310
  ...e,
1297
- heartbeatMs: e.heartbeatMs ?? We
1311
+ heartbeatMs: e.heartbeatMs ?? Ke
1298
1312
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now();
1299
1313
  }
1300
1314
  start() {
@@ -1386,7 +1400,7 @@ var qe = class {
1386
1400
  };
1387
1401
  }
1388
1402
  enqueue(e) {
1389
- for (this.pending.push(this.wrap(e)); this.pending.length > Ge;) {
1403
+ for (this.pending.push(this.wrap(e)); this.pending.length > qe;) {
1390
1404
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
1391
1405
  this.pending.splice(e >= 0 ? e : 0, 1);
1392
1406
  }
@@ -1408,7 +1422,7 @@ var qe = class {
1408
1422
  keepalive: !0
1409
1423
  }).catch(() => {});
1410
1424
  }
1411
- }, Je = "2.0.1", W = {
1425
+ }, Xe = "2.0.3", W = {
1412
1426
  accent: "#E1B600",
1413
1427
  accentText: "#1B1C23",
1414
1428
  background: "#0e0f13",
@@ -1441,15 +1455,15 @@ function K(e, t) {
1441
1455
  }
1442
1456
  //#endregion
1443
1457
  //#region src/ui/styles.ts
1444
- var q = "havik-player-styles", Ye = "\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";
1445
- function Xe(e = document) {
1458
+ var q = "havik-player-styles", Ze = "\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";
1459
+ function Qe(e = document) {
1446
1460
  if (e.getElementById(q)) return;
1447
1461
  let t = e.createElement("style");
1448
- t.id = q, t.textContent = Ye, e.head.appendChild(t);
1462
+ t.id = q, t.textContent = Ze, e.head.appendChild(t);
1449
1463
  }
1450
1464
  //#endregion
1451
1465
  //#region src/ui/icons.ts
1452
- var Ze = {
1466
+ var $e = {
1453
1467
  play: "<path d=\"M8 5v14l11-7z\"/>",
1454
1468
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1455
1469
  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\"/>",
@@ -1463,20 +1477,20 @@ var Ze = {
1463
1477
  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\"/>"
1464
1478
  };
1465
1479
  function J(e) {
1466
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ze[e]}</svg>`;
1480
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${$e[e]}</svg>`;
1467
1481
  }
1468
1482
  //#endregion
1469
1483
  //#region src/ui/controls.ts
1470
- var Qe = 3e3, $e = /* @__PURE__ */ new Set([
1484
+ var et = 3e3, tt = /* @__PURE__ */ new Set([
1471
1485
  "GONE",
1472
1486
  "NOT_FOUND",
1473
1487
  "INVALID_URN",
1474
1488
  "UNAUTHORIZED"
1475
1489
  ]);
1476
- function et(e) {
1477
- return new tt(e);
1490
+ function nt(e) {
1491
+ return new rt(e);
1478
1492
  }
1479
- var tt = class {
1493
+ var rt = class {
1480
1494
  root;
1481
1495
  video;
1482
1496
  player;
@@ -1518,7 +1532,7 @@ var tt = class {
1518
1532
  scrubbing = !1;
1519
1533
  offFns = [];
1520
1534
  constructor(e) {
1521
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Qe, 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, Xe(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");
1535
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? et, 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, Qe(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");
1522
1536
  let t = (e, t, n) => {
1523
1537
  let r = this.doc.createElement(e);
1524
1538
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1609,7 +1623,7 @@ var tt = class {
1609
1623
  e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = J("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
1610
1624
  } else {
1611
1625
  let r = this.doc.createElement("div");
1612
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !$e.has(this.lastError.code)) {
1626
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !tt.has(this.lastError.code)) {
1613
1627
  let e = this.doc.createElement("button");
1614
1628
  e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${J("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
1615
1629
  }
@@ -1700,17 +1714,17 @@ var tt = class {
1700
1714
  renderQualityMenu() {
1701
1715
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
1702
1716
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
1703
- for (let n of e) this.menu.append(this.menuItem(nt(n), t === n.index, () => this.player.setQuality(n.index)));
1717
+ for (let n of e) this.menu.append(this.menuItem(it(n), t === n.index, () => this.player.setQuality(n.index)));
1704
1718
  }
1705
1719
  renderAudioMenu() {
1706
1720
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
1707
1721
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
1708
- for (let t of e) this.menu.append(this.menuItem(rt(t), t.default, () => this.player.setAudioTrack(t.id)));
1722
+ for (let t of e) this.menu.append(this.menuItem(at(t), t.default, () => this.player.setAudioTrack(t.id)));
1709
1723
  }
1710
1724
  renderCcMenu() {
1711
1725
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
1712
1726
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
1713
- for (let t of e) this.menu.append(this.menuItem(it(t), !1, () => this.player.setTextTrack(t.id)));
1727
+ for (let t of e) this.menu.append(this.menuItem(ot(t), !1, () => this.player.setTextTrack(t.id)));
1714
1728
  }
1715
1729
  onTracksChanged() {
1716
1730
  this.openMenu && this.renderMenu(this.openMenu);
@@ -1815,27 +1829,27 @@ function Y(e) {
1815
1829
  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");
1816
1830
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
1817
1831
  }
1818
- function nt(e) {
1832
+ function it(e) {
1819
1833
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
1820
1834
  }
1821
- function rt(e) {
1835
+ function at(e) {
1822
1836
  return e.name || e.lang || `Track ${e.id}`;
1823
1837
  }
1824
- function it(e) {
1838
+ function ot(e) {
1825
1839
  return e.name || e.lang || `Track ${e.id}`;
1826
1840
  }
1827
1841
  //#endregion
1828
1842
  //#region src/managed/index.ts
1829
- var at = 6e3, X = 45e3, Z = 2e3, ot = 3, st = 2e3, ct = 48e4;
1843
+ var st = 6e3, X = 45e3, Z = 2e3, ct = 3, lt = 2e3, ut = 48e4;
1830
1844
  async function Q(e) {
1831
1845
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
1832
1846
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
1833
1847
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
1834
1848
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
1835
- let t = new lt(e);
1849
+ let t = new dt(e);
1836
1850
  return await t.start(), t;
1837
1851
  }
1838
- var lt = class {
1852
+ var dt = class {
1839
1853
  opts;
1840
1854
  abort = new AbortController();
1841
1855
  listeners = {};
@@ -1959,7 +1973,7 @@ var lt = class {
1959
1973
  !a && !p() && h();
1960
1974
  }, e);
1961
1975
  };
1962
- _(at), this.armingSub = D({
1976
+ _(st), this.armingSub = D({
1963
1977
  eventsBaseUrl: t,
1964
1978
  matchUrn: this.opts.matchUrn,
1965
1979
  credential: this.opts.credential,
@@ -2005,14 +2019,14 @@ var lt = class {
2005
2019
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachSeekListener?.(), this.opts.analytics === !1) return;
2006
2020
  let r = e.analytics?.sid;
2007
2021
  if (!r) return;
2008
- let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? Ke(this.opts.baseUrl);
2022
+ let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? Je(this.opts.baseUrl);
2009
2023
  if (!i) return;
2010
- let a = this.opts.video, o = new qe({
2024
+ let a = this.opts.video, o = new Ye({
2011
2025
  endpoint: i,
2012
2026
  sid: r,
2013
2027
  apiKey: n,
2014
2028
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2015
- sdkVersion: Je,
2029
+ sdkVersion: Xe,
2016
2030
  sample: () => {
2017
2031
  let e = this.engine?.getStats() ?? F, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
2018
2032
  return {
@@ -2089,7 +2103,7 @@ var lt = class {
2089
2103
  r = 0, i = !1;
2090
2104
  },
2091
2105
  onError: () => {
2092
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= ot && (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.`))));
2106
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= ct && (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.`))));
2093
2107
  }
2094
2108
  });
2095
2109
  }
@@ -2135,7 +2149,7 @@ var lt = class {
2135
2149
  }
2136
2150
  t.controls = !1;
2137
2151
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2138
- r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = et({
2152
+ r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = nt({
2139
2153
  root: n,
2140
2154
  video: t,
2141
2155
  player: this,
@@ -2159,7 +2173,7 @@ var lt = class {
2159
2173
  }
2160
2174
  startStats() {
2161
2175
  this.stopStats();
2162
- let e = Math.max(500, this.opts.statsIntervalMs ?? st);
2176
+ let e = Math.max(500, this.opts.statsIntervalMs ?? lt);
2163
2177
  this.statsTimer = setInterval(() => {
2164
2178
  if (!this.engine) return;
2165
2179
  let e = this.engine.getStats();
@@ -2171,7 +2185,7 @@ var lt = class {
2171
2185
  }
2172
2186
  scheduleLicenseRefresh() {
2173
2187
  this.stopRefresh();
2174
- let e = this.opts.licenseRefreshMs ?? ct;
2188
+ let e = this.opts.licenseRefreshMs ?? ut;
2175
2189
  !e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2176
2190
  }
2177
2191
  stopRefresh() {
@@ -2318,7 +2332,7 @@ function $(e) {
2318
2332
  }
2319
2333
  //#endregion
2320
2334
  //#region src/embed/host.ts
2321
- function ut(e) {
2335
+ function ft(e) {
2322
2336
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2323
2337
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2324
2338
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2377,8 +2391,8 @@ function ut(e) {
2377
2391
  }
2378
2392
  //#endregion
2379
2393
  //#region src/embed/page.ts
2380
- var dt = /^[A-Za-z0-9:_.-]{1,128}$/;
2381
- function ft() {
2394
+ var pt = /^[A-Za-z0-9:_.-]{1,128}$/;
2395
+ function mt() {
2382
2396
  let e = window.HAVIK_EMBED_CONFIG;
2383
2397
  if (e) return {
2384
2398
  baseUrl: e.baseUrl ?? "",
@@ -2400,9 +2414,9 @@ function ft() {
2400
2414
  waitForLive: !0
2401
2415
  };
2402
2416
  }
2403
- async function pt() {
2404
- let e = ft();
2405
- ht();
2417
+ async function ht() {
2418
+ let e = mt();
2419
+ _t();
2406
2420
  let t = document.createElement("video");
2407
2421
  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);
2408
2422
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2457,7 +2471,7 @@ async function pt() {
2457
2471
  code: e.code,
2458
2472
  message: e.message
2459
2473
  })), e.on("autoplayblocked", () => {
2460
- i({ type: "oddin:autoplayblocked" }), mt(t, e);
2474
+ i({ type: "oddin:autoplayblocked" }), gt(t, e);
2461
2475
  });
2462
2476
  }, s = async (r) => {
2463
2477
  a?.destroy(), a = null;
@@ -2523,7 +2537,7 @@ async function pt() {
2523
2537
  a?.retry();
2524
2538
  break;
2525
2539
  case "oddin:load":
2526
- typeof e.matchUrn == "string" && dt.test(e.matchUrn) && s(e.matchUrn);
2540
+ typeof e.matchUrn == "string" && pt.test(e.matchUrn) && s(e.matchUrn);
2527
2541
  break;
2528
2542
  case "oddin:destroy": c();
2529
2543
  }
@@ -2535,18 +2549,18 @@ async function pt() {
2535
2549
  protocol: 1
2536
2550
  });
2537
2551
  }
2538
- function mt(e, t) {
2552
+ function gt(e, t) {
2539
2553
  if (document.getElementById("havik-tap")) return;
2540
2554
  let n = document.createElement("button");
2541
2555
  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", () => {
2542
2556
  n.remove(), t.play();
2543
2557
  }), document.body.appendChild(n);
2544
2558
  }
2545
- function ht() {
2559
+ function _t() {
2546
2560
  let e = document.createElement("style");
2547
2561
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
2548
2562
  }
2549
2563
  //#endregion
2550
- export { W as ODDIN_THEME, n as PlaybackError, K as applyTheme, pt as bootEmbed, he as clearDeviceId, Q as createPlayer, O as deriveEventsBaseUrl, xe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, le as fetchCatalog, de as fetchTournament, pe as flattenMatches, j as getDeviceId, Ce as isLowLatencyManifest, $ as isOddinMessage, _e as licenseRequestHeaders, ut as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, me as watchStatus };
2564
+ export { W as ODDIN_THEME, n as PlaybackError, K as applyTheme, ht as bootEmbed, he as clearDeviceId, Q as createPlayer, O as deriveEventsBaseUrl, xe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, le as fetchCatalog, de as fetchTournament, pe as flattenMatches, j as getDeviceId, Ce as isLowLatencyManifest, $ as isOddinMessage, _e as licenseRequestHeaders, ft as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, me as watchStatus };
2551
2565
 
2552
2566
  //# sourceMappingURL=index.js.map