@hadoku/watchparty-ui 0.45.25 → 0.45.26

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.
@@ -1,23 +1,24 @@
1
- import { jsx as c, jsxs as _, Fragment as ce } from "react/jsx-runtime";
2
- import Gt, { useState as R, useRef as z, useMemo as Q, useCallback as k, useEffect as D, createContext as qt, useContext as Dn, useSyncExternalStore as On, useId as Mn, useEffectEvent as Vt } from "react";
3
- import { themePrefs as ie, Icon as Ln, THEMES as jn, useHadokuThemeOptional as Un } from "@wolffm/themes";
1
+ import { jsx as c, jsxs as v, Fragment as ce } from "react/jsx-runtime";
2
+ import Pe, { useState as R, useRef as K, useMemo as J, useCallback as k, useEffect as N, createContext as rt, useContext as ot, useSyncExternalStore as Ln, useId as jn, useEffectEvent as Yt } from "react";
3
+ import { themePrefs as ie, Icon as Un, THEMES as Fn, useHadokuThemeOptional as Hn } from "@wolffm/themes";
4
4
  import { z as o } from "zod";
5
- import { createCdnClient as Fn, kindOfType as Hn, MAX_BYTES as $n, measureImage as Bn, filesFromClipboard as Gn, filesFromDrop as qn, CdnError as Ye } from "@wolffm/cdn-client";
6
- import { create as Vn } from "zustand";
7
- import { createPrefsClient as Kn, getDeviceId as Wn, DEVICE_ID_KEY as Yn } from "@wolffm/prefs-client";
8
- import { io as zn } from "socket.io-client";
9
- import { createAvatarClient as Xn, AvatarError as vt } from "@wolffm/prefs-client/avatar";
10
- import { resolveIdentityReassert as Jn } from "@wolffm/rooms-protocol";
11
- import { createPortal as Zn } from "react-dom";
12
- import { useCatalogueSearch as Qn } from "@wolffm/cdn-client/react";
13
- const Kt = "https://cdn.hadoku.me", Wt = /^[0-9a-f]{64}\.(?:png|jpe?g|gif|webp|avif)$/;
14
- function tt(e) {
15
- return typeof e == "string" && Wt.test(e);
16
- }
17
- const nt = 8080, Yt = 5173, er = "/watchparty/ws", zt = 500, tr = 1e3, W = 4, Xt = typeof process < "u" && process.env ? process.env : {};
18
- Xt.PRODUCTION_UI_URL;
19
- Xt.PRODUCTION_SERVER_URL;
20
- const Ie = o.enum(["S", "A", "B", "C", "D", "F"]), St = 2e4, nr = 300;
5
+ import { createCdnClient as $n, kindOfType as Bn, MAX_BYTES as Gn, measureImage as qn, filesFromClipboard as Vn, filesFromDrop as Kn, CdnError as ze } from "@wolffm/cdn-client";
6
+ import { ensureCosmeticsStyles as Wn, cleanWorn as Yn, decorHtml as zn, messageHtml as Xn, nameHtml as Jn } from "@wolffm/prefs-client/cosmetics";
7
+ import { create as Zn } from "zustand";
8
+ import { createPrefsClient as Qn, getDeviceId as er, DEVICE_ID_KEY as tr } from "@wolffm/prefs-client";
9
+ import { io as nr } from "socket.io-client";
10
+ import { createAvatarClient as rr, AvatarError as It } from "@wolffm/prefs-client/avatar";
11
+ import { resolveIdentityReassert as or } from "@wolffm/rooms-protocol";
12
+ import { createPortal as ar } from "react-dom";
13
+ import { useCatalogueSearch as ir } from "@wolffm/cdn-client/react";
14
+ const zt = "https://cdn.hadoku.me", Xt = /^[0-9a-f]{64}\.(?:png|jpe?g|gif|webp|avif)$/;
15
+ function at(e) {
16
+ return typeof e == "string" && Xt.test(e);
17
+ }
18
+ const it = 8080, Jt = 5173, sr = "/watchparty/ws", Zt = 500, lr = 1e3, Y = 4, Qt = typeof process < "u" && process.env ? process.env : {};
19
+ Qt.PRODUCTION_UI_URL;
20
+ Qt.PRODUCTION_SERVER_URL;
21
+ const Ie = o.enum(["S", "A", "B", "C", "D", "F"]), Ct = 2e4, cr = 300;
21
22
  o.object({
22
23
  name: o.string().min(1).max(32).optional(),
23
24
  sprite: o.string().min(1).max(32).optional(),
@@ -26,7 +27,7 @@ o.object({
26
27
  * resolves it from prefs-api by registry userId, never from the client. */
27
28
  avatar: o.literal(!0).optional()
28
29
  });
29
- const w = {
30
+ const _ = {
30
31
  JOIN: "join",
31
32
  SNAPSHOT: "snapshot",
32
33
  CONTROL_ACK: "control_ack",
@@ -44,7 +45,7 @@ const w = {
44
45
  // 'ready_state' here = playback-readiness gate (distinct from READY_EVENTS.STATE = "ready check" UX feature)
45
46
  READY_STATE: "ready_state",
46
47
  ERROR: "error"
47
- }, rr = o.enum(["play", "pause", "seek", "load", "home"]), or = o.object({
48
+ }, dr = o.enum(["play", "pause", "seek", "load", "home"]), ur = o.object({
48
49
  framed: o.boolean(),
49
50
  depth: o.number().int().nonnegative().max(10)
50
51
  });
@@ -52,7 +53,7 @@ o.object({
52
53
  room_key: o.string(),
53
54
  name: o.string().min(1).max(32).optional(),
54
55
  sprite: o.string().min(1).max(32).optional(),
55
- embed: or.optional(),
56
+ embed: ur.optional(),
56
57
  /** Which media-delivery path this client resolved to ('range' | 'fragment').
57
58
  * Optional so older clients still validate. Reported so a party's logs can be split by
58
59
  * arm — without it an A/B rollout is unmeasurable, exactly as entry path was before
@@ -100,13 +101,13 @@ o.object({
100
101
  });
101
102
  o.object({
102
103
  client_seq: o.number().int().positive(),
103
- kind: rr,
104
+ kind: dr,
104
105
  to_ms: o.number().int().nonnegative().optional(),
105
106
  media_id: o.string().optional()
106
107
  // leader_id removed - not needed since set_leader control was removed
107
108
  });
108
- const Jt = o.object({
109
- key: o.string().regex(Wt, "not a CDN image key"),
109
+ const en = o.object({
110
+ key: o.string().regex(Xt, "not a CDN image key"),
110
111
  /**
111
112
  * Intrinsic pixels, or **0 meaning "unknown"**.
112
113
  *
@@ -119,8 +120,8 @@ const Jt = o.object({
119
120
  * text went with it, with nothing said. Widening is backward compatible —
120
121
  * every message already in history carries positive dimensions.
121
122
  */
122
- w: o.number().int().nonnegative().max(St),
123
- h: o.number().int().nonnegative().max(St),
123
+ w: o.number().int().nonnegative().max(Ct),
124
+ h: o.number().int().nonnegative().max(Ct),
124
125
  /**
125
126
  * Human-readable description, rendered as the `alt` text.
126
127
  *
@@ -134,14 +135,14 @@ const Jt = o.object({
134
135
  * value only, never as markup. Bounded so one message cannot carry a
135
136
  * paragraph; the library's own titles run well under this.
136
137
  */
137
- title: o.string().max(nr).optional()
138
+ title: o.string().max(cr).optional()
138
139
  });
139
140
  o.object({
140
- text: o.string().max(zt),
141
+ text: o.string().max(Zt),
141
142
  style: o.string().max(64).optional(),
142
- images: o.array(Jt).max(W).optional()
143
+ images: o.array(en).max(Y).optional()
143
144
  }).refine((e) => e.text.length > 0 || (e.images?.length ?? 0) > 0, { message: "message must carry text or at least one image" });
144
- const ar = o.enum(["join", "leave", "media_change", "identity_change", "recap"]);
145
+ const mr = o.enum(["join", "leave", "media_change", "identity_change", "recap"]);
145
146
  o.object({
146
147
  id: o.string(),
147
148
  client_id: o.string(),
@@ -154,11 +155,11 @@ o.object({
154
155
  ts: o.number(),
155
156
  // Optional so a client on an older bundle still validates a message that
156
157
  // has none, and so system messages (which never carry images) stay unchanged.
157
- images: o.array(Jt).max(W).optional(),
158
+ images: o.array(en).max(Y).optional(),
158
159
  isSystem: o.boolean().optional(),
159
- systemType: ar.optional()
160
+ systemType: mr.optional()
160
161
  });
161
- const ir = o.object({
162
+ const fr = o.object({
162
163
  avg_download_rate_bps: o.number().nonnegative(),
163
164
  buffered_ahead_ms: o.number().nonnegative(),
164
165
  rtt_ms: o.number().nonnegative(),
@@ -200,7 +201,7 @@ const ir = o.object({
200
201
  * socket shows here as a growing number while everything else looks fine. */
201
202
  pong_age_ms: o.number().int().nonnegative().optional(),
202
203
  reported_at: o.number().int().nonnegative()
203
- }), sr = ir.extend({
204
+ }), pr = fr.extend({
204
205
  client_id: o.string(),
205
206
  name: o.string(),
206
207
  sprite_id: o.string().nullable(),
@@ -211,10 +212,10 @@ const ir = o.object({
211
212
  stale_ms: o.number().int().nonnegative().optional()
212
213
  });
213
214
  o.object({
214
- clients: o.array(sr),
215
+ clients: o.array(pr),
215
216
  server_ts: o.number().int().nonnegative()
216
217
  });
217
- const lr = o.object({
218
+ const hr = o.object({
218
219
  client_id: o.string(),
219
220
  sprite_id: o.string().nullable(),
220
221
  name: o.string(),
@@ -232,13 +233,13 @@ const lr = o.object({
232
233
  video_ready_state: o.number().int().default(-1)
233
234
  });
234
235
  o.object({
235
- clients: o.array(lr),
236
+ clients: o.array(hr),
236
237
  server_ts: o.number().int().nonnegative()
237
238
  });
238
239
  o.object({
239
240
  media_id: o.string()
240
241
  });
241
- const rt = o.enum(["super_upvote", "upvote", "mid", "downvote"]), cr = o.object({
242
+ const st = o.enum(["super_upvote", "upvote", "mid", "downvote"]), gr = o.object({
242
243
  mediaId: o.string(),
243
244
  displayName: o.string(),
244
245
  // Enrichment fields — present for flat-playlist ingest output, absent for
@@ -249,11 +250,11 @@ const rt = o.enum(["super_upvote", "upvote", "mid", "downvote"]), cr = o.object(
249
250
  durationMs: o.number().optional(),
250
251
  uploadDate: o.string().optional()
251
252
  // YouTube upload date 'YYYY-MM-DD'; drives playlist order
252
- }), dr = o.enum(["basic", "vote"]), Zt = o.object({
253
+ }), yr = o.enum(["basic", "vote"]), tn = o.object({
253
254
  id: o.string(),
254
255
  name: o.string(),
255
- type: dr.default("vote"),
256
- videos: o.array(cr),
256
+ type: yr.default("vote"),
257
+ videos: o.array(gr),
257
258
  cover: o.string().optional()
258
259
  // media-relative path to the playlist cover image
259
260
  });
@@ -262,28 +263,28 @@ o.object({ index: o.number().int().min(0) });
262
263
  o.object({
263
264
  playlistId: o.string(),
264
265
  mediaId: o.string(),
265
- vote: rt
266
+ vote: st
266
267
  });
267
268
  o.object({ voterKey: o.string().min(1).max(128) });
268
269
  o.object({ playlistId: o.string(), mediaIds: o.array(o.string()) });
269
270
  o.object({
270
- playlist: Zt.nullable(),
271
+ playlist: tn.nullable(),
271
272
  activeIndex: o.number().int().nullable(),
272
- myVotes: o.record(o.string(), rt)
273
+ myVotes: o.record(o.string(), st)
273
274
  // mediaId -> VoteValue
274
275
  });
275
- const ur = o.object({
276
+ const br = o.object({
276
277
  clientId: o.string(),
277
278
  name: o.string(),
278
279
  votedCount: o.number().int().nonnegative(),
279
280
  totalVideos: o.number().int().nonnegative()
280
281
  });
281
282
  o.object({
282
- progress: o.array(ur)
283
+ progress: o.array(br)
283
284
  });
284
285
  o.object({
285
- playlist: Zt,
286
- votes: o.record(o.string(), o.record(o.string(), rt)),
286
+ playlist: tn,
287
+ votes: o.record(o.string(), o.record(o.string(), st)),
287
288
  // votes[clientId][mediaId]
288
289
  names: o.record(o.string(), o.string()),
289
290
  // clientId -> display name
@@ -304,17 +305,17 @@ const be = {
304
305
  RESULTS: "playlist_results",
305
306
  /** Server -> the removed voter: forget the ballot you hold in localStorage. */
306
307
  VOTES_CLEARED: "playlist_votes_cleared"
307
- }, Qt = o.object({
308
+ }, nn = o.object({
308
309
  id: o.string(),
309
310
  displayName: o.string(),
310
311
  thumbnail: o.string().optional()
311
312
  });
312
313
  o.object({
313
- items: o.array(Qt)
314
+ items: o.array(nn)
314
315
  });
315
- const en = o.partialRecord(Ie, o.array(o.string()));
316
- o.object({ board: en });
317
- const mr = o.object({
316
+ const rn = o.partialRecord(Ie, o.array(o.string()));
317
+ o.object({ board: rn });
318
+ const vr = o.object({
318
319
  mediaId: o.string(),
319
320
  tier: Ie,
320
321
  absoluteTier: Ie,
@@ -327,8 +328,8 @@ const mr = o.object({
327
328
  // opaque voterId -> the letter they gave
328
329
  });
329
330
  o.object({
330
- items: o.array(Qt),
331
- placed: o.array(mr),
331
+ items: o.array(nn),
332
+ placed: o.array(vr),
332
333
  unrated: o.array(o.string()),
333
334
  spread: o.number(),
334
335
  nudged: o.boolean(),
@@ -338,9 +339,9 @@ o.object({
338
339
  * browser on a newer bundle still reads an older server's board. */
339
340
  pictures: o.record(o.string(), o.string()).optional(),
340
341
  voterCount: o.number().int().nonnegative(),
341
- myBoard: en
342
+ myBoard: rn
342
343
  });
343
- const fr = {
344
+ const Sr = {
344
345
  /** Broadcast to EVERY connected socket when anyone saves. Carries no board —
345
346
  * it is a "re-fetch" ping, because the shared result is identical for all
346
347
  * viewers but `myBoard` is not, and one payload cannot serve both. */
@@ -353,10 +354,10 @@ o.object({
353
354
  ready: o.array(o.string())
354
355
  // clientIds who have flagged ready
355
356
  });
356
- const pr = {
357
+ const wr = {
357
358
  STATE: "ready_check_state"
358
359
  // distinct from buffer-readiness 'ready_state'
359
- }, tn = {
360
+ }, on = {
360
361
  ACTIVE: "game_active",
361
362
  // server -> room (the open game id; null = none)
362
363
  SYNC: "game_sync"
@@ -368,7 +369,7 @@ o.object({
368
369
  o.object({
369
370
  gameId: o.string().nullable()
370
371
  });
371
- const hr = [
372
+ const _r = [
372
373
  {
373
374
  id: "fantasy",
374
375
  characters: [
@@ -412,37 +413,37 @@ const hr = [
412
413
  { id: "mentor", color: "#e1e0dc" }
413
414
  ]
414
415
  }
415
- ], ot = hr.flatMap((e) => e.characters), Le = ot.map((e) => e.id), gr = Object.fromEntries(ot.map((e) => [e.id, e.color])), yr = Object.fromEntries(ot.map((e) => [e.id, "rev" in e ? e.rev : 1]));
416
- function br(e) {
417
- const t = yr[e];
416
+ ], lt = _r.flatMap((e) => e.characters), je = lt.map((e) => e.id), xr = Object.fromEntries(lt.map((e) => [e.id, e.color])), Ir = Object.fromEntries(lt.map((e) => [e.id, "rev" in e ? e.rev : 1]));
417
+ function Cr(e) {
418
+ const t = Ir[e];
418
419
  return `/media/sprites/square_${e}.png${t > 1 ? `?v=${t}` : ""}`;
419
420
  }
420
- function at(e) {
421
- return !!e && Le.includes(e);
421
+ function ct(e) {
422
+ return !!e && je.includes(e);
422
423
  }
423
- const vr = 5e3, nn = { mode: "off", percent: 0 }, Sr = ["off", "on", "ab"];
424
- function _r(e) {
425
- return typeof e == "string" && Sr.includes(e);
424
+ const Tr = 5e3, an = { mode: "off", percent: 0 }, Ar = ["off", "on", "ab"];
425
+ function Er(e) {
426
+ return typeof e == "string" && Ar.includes(e);
426
427
  }
427
- function wr(e) {
428
- const t = e && typeof e == "object" ? e : {}, n = _r(t.mode) ? t.mode : nn.mode, r = Number(t.percent), a = Number.isFinite(r) ? Math.min(100, Math.max(0, Math.round(r))) : 0;
428
+ function kr(e) {
429
+ const t = e && typeof e == "object" ? e : {}, n = Er(t.mode) ? t.mode : an.mode, r = Number(t.percent), a = Number.isFinite(r) ? Math.min(100, Math.max(0, Math.round(r))) : 0;
429
430
  return { mode: n, percent: a };
430
431
  }
431
- function xr(e) {
432
+ function Nr(e) {
432
433
  let t = 2166136261;
433
434
  for (let n = 0; n < e.length; n++)
434
435
  t ^= e.charCodeAt(n), t = Math.imul(t, 16777619) >>> 0;
435
436
  return t >>> 0;
436
437
  }
437
- function Ir(e, t, n) {
438
+ function Pr(e, t, n) {
438
439
  if (n === !0)
439
440
  return "fragment";
440
441
  if (n === !1)
441
442
  return "range";
442
- const r = wr(e);
443
- return r.mode === "on" ? "fragment" : r.mode === "off" || r.percent <= 0 ? "range" : r.percent >= 100 || t && xr(t) % 100 < r.percent ? "fragment" : "range";
443
+ const r = kr(e);
444
+ return r.mode === "on" ? "fragment" : r.mode === "off" || r.percent <= 0 ? "range" : r.percent >= 100 || t && Nr(t) % 100 < r.percent ? "fragment" : "range";
444
445
  }
445
- const rn = o.enum(["url", "magnet", "upload"]), Cr = o.enum([
446
+ const sn = o.enum(["url", "magnet", "upload"]), Rr = o.enum([
446
447
  "pending",
447
448
  "approved",
448
449
  "fetching",
@@ -450,7 +451,7 @@ const rn = o.enum(["url", "magnet", "upload"]), Cr = o.enum([
450
451
  "ready",
451
452
  "rejected",
452
453
  "failed"
453
- ]), _t = {
454
+ ]), Tt = {
454
455
  pending: ["approved", "rejected"],
455
456
  approved: ["fetching", "rejected", "failed"],
456
457
  fetching: ["ingesting", "failed"],
@@ -459,12 +460,12 @@ const rn = o.enum(["url", "magnet", "upload"]), Cr = o.enum([
459
460
  rejected: [],
460
461
  failed: ["approved"]
461
462
  };
462
- Object.keys(_t).filter((e) => _t[e].length === 0);
463
- const Tr = o.object({
463
+ Object.keys(Tt).filter((e) => Tt[e].length === 0);
464
+ const Or = o.object({
464
465
  id: o.string().min(1),
465
466
  /** Stable userId from whoami. Never the raw `X-User-Key`. */
466
467
  ownerUserId: o.string().min(1),
467
- kind: rn,
468
+ kind: sn,
468
469
  /** The magnet URI, the https URL, or the filetransfer binding id. */
469
470
  source: o.string().min(1),
470
471
  title: o.string().optional(),
@@ -479,7 +480,7 @@ const Tr = o.object({
479
480
  * misroute the copy.
480
481
  */
481
482
  series: o.string().optional(),
482
- state: Cr,
483
+ state: Rr,
483
484
  createdAt: o.number().int().nonnegative(),
484
485
  updatedAt: o.number().int().nonnegative(),
485
486
  /** Why it failed, or why an operator rejected it. */
@@ -487,19 +488,19 @@ const Tr = o.object({
487
488
  /** Size once known. 0 means "known to be empty"; absent means "not yet known" —
488
489
  * the same distinction `chatImages` draws for image dimensions. */
489
490
  bytes: o.number().int().nonnegative().optional()
490
- }), Ar = 4096, on = 300, Er = 100;
491
+ }), Dr = 4096, ln = 300, Mr = 100;
491
492
  o.object({
492
- kind: rn,
493
- source: o.string().min(1).max(Ar),
494
- title: o.string().min(1).max(on).optional(),
493
+ kind: sn,
494
+ source: o.string().min(1).max(Dr),
495
+ title: o.string().min(1).max(ln).optional(),
495
496
  /** Required for `kind: 'magnet'` by `checkSource`; ignored for `url`/`upload`. */
496
- series: o.string().min(1).max(Er).optional()
497
+ series: o.string().min(1).max(Mr).optional()
497
498
  });
498
499
  o.object({
499
- reason: o.string().min(1).max(on).optional()
500
+ reason: o.string().min(1).max(ln).optional()
500
501
  });
501
502
  o.object({
502
- submissions: o.array(Tr)
503
+ submissions: o.array(Or)
503
504
  });
504
505
  o.object({
505
506
  error: o.literal("submissions/quota_exceeded"),
@@ -508,26 +509,26 @@ o.object({
508
509
  /** The cap that was applied, from the server's config. */
509
510
  capBytes: o.number().int().nonnegative()
510
511
  });
511
- const kr = /^[a-z0-9][a-z0-9-]{0,31}$/, wt = "https://game-catalog.invalid";
512
- function Pr(e) {
512
+ const Lr = /^[a-z0-9][a-z0-9-]{0,31}$/, At = "https://game-catalog.invalid";
513
+ function jr(e) {
513
514
  if (!e.startsWith("/") || e.startsWith("//") || /[\\\s]/.test(e) || [...e].some((t) => t.charCodeAt(0) < 32 || t.charCodeAt(0) === 127))
514
515
  return !1;
515
516
  try {
516
- return new URL(e, wt).origin === wt;
517
+ return new URL(e, At).origin === At;
517
518
  } catch {
518
519
  return !1;
519
520
  }
520
521
  }
521
- const an = o.string().min(2).max(512).refine(Pr, {
522
+ const cn = o.string().min(2).max(512).refine(jr, {
522
523
  message: "must be a root-relative path on the page origin (e.g. /cardtable/embed/x.js)"
523
- }), Nr = {
524
- id: o.string().regex(kr),
524
+ }), Ur = {
525
+ id: o.string().regex(Lr),
525
526
  name: o.string().min(1).max(64),
526
- cover: an.optional()
527
- }, Rr = o.object({ ...Nr, kind: o.literal("module"), url: an }).strict();
528
- o.array(Rr).max(32).refine((e) => new Set(e.map((t) => t.id)).size === e.length, { message: "game ids must be unique" });
529
- const it = o.enum(["anilist", "tmdb"]), Dr = o.object({
530
- source: it,
527
+ cover: cn.optional()
528
+ }, Fr = o.object({ ...Ur, kind: o.literal("module"), url: cn }).strict();
529
+ o.array(Fr).max(32).refine((e) => new Set(e.map((t) => t.id)).size === e.length, { message: "game ids must be unique" });
530
+ const dt = o.enum(["anilist", "tmdb"]), Hr = o.object({
531
+ source: dt,
531
532
  /** The provider's own id, as a string (AniList and TMDB both use integers). */
532
533
  id: o.string(),
533
534
  title: o.string(),
@@ -548,11 +549,11 @@ const it = o.enum(["anilist", "tmdb"]), Dr = o.object({
548
549
  addable: o.boolean()
549
550
  });
550
551
  o.object({
551
- results: o.array(Dr),
552
+ results: o.array(Hr),
552
553
  /** Providers that answered. TMDB is absent when no token is configured. */
553
- sources: o.array(it)
554
+ sources: o.array(dt)
554
555
  });
555
- const Or = o.object({
556
+ const $r = o.object({
556
557
  id: o.string(),
557
558
  url: o.string(),
558
559
  title: o.string(),
@@ -560,30 +561,30 @@ const Or = o.object({
560
561
  durationS: o.number().nullable(),
561
562
  thumb: o.string().nullable()
562
563
  });
563
- o.object({ results: o.array(Or) });
564
+ o.object({ results: o.array($r) });
564
565
  o.object({
565
- source: it,
566
+ source: dt,
566
567
  id: o.string().regex(/^\d{1,12}$/)
567
568
  });
568
569
  o.object({ series: o.string(), title: o.string() });
569
- let ve = null, sn = Kt;
570
- function Mr(e) {
571
- e.cdnBase && (sn = e.cdnBase);
570
+ let ve = null, dn = zt;
571
+ function Br(e) {
572
+ e.cdnBase && (dn = e.cdnBase);
572
573
  }
573
- function ln() {
574
- return sn.replace(/\/+$/, "");
574
+ function un() {
575
+ return dn.replace(/\/+$/, "");
575
576
  }
576
- function je() {
577
- const e = ln();
578
- return (!ve || ve.base !== e) && (ve = { base: e, client: Fn({ cdnBase: e }) }), ve.client;
577
+ function Ue() {
578
+ const e = un();
579
+ return (!ve || ve.base !== e) && (ve = { base: e, client: $n({ cdnBase: e }) }), ve.client;
579
580
  }
580
- function Ne(e) {
581
- return !tt(e) || !ln() ? null : je().urlFor(e);
581
+ function Re(e) {
582
+ return !at(e) || !un() ? null : Ue().urlFor(e);
582
583
  }
583
- function Lr(e) {
584
+ function Gr(e) {
584
585
  return e.kind === "file";
585
586
  }
586
- class cn extends Error {
587
+ class mn extends Error {
587
588
  constructor(t) {
588
589
  super(t), this.name = "ChatImageUploadError";
589
590
  }
@@ -608,90 +609,90 @@ function Ce(e) {
608
609
  return "Image upload failed";
609
610
  }
610
611
  }
611
- function jr(e) {
612
- return e instanceof Ye ? Ce(e.reason) : e instanceof cn ? e.message : "Image upload failed";
612
+ function qr(e) {
613
+ return e instanceof ze ? Ce(e.reason) : e instanceof mn ? e.message : "Image upload failed";
613
614
  }
614
- function Ur(e) {
615
+ function Vr(e) {
615
616
  const t = e.type.toLowerCase().split(";")[0].trim();
616
- return t && Hn(t) !== "image" ? Ce("unsupported-type") : e.size > $n.image ? Ce("too-large") : e.size === 0 ? Ce("invalid") : null;
617
+ return t && Bn(t) !== "image" ? Ce("unsupported-type") : e.size > Gn.image ? Ce("too-large") : e.size === 0 ? Ce("invalid") : null;
617
618
  }
618
- function Fr(e) {
619
- return Gn(e);
619
+ function Kr(e) {
620
+ return Vn(e);
620
621
  }
621
- function Hr(e) {
622
- return qn(e);
622
+ function Wr(e) {
623
+ return Kn(e);
623
624
  }
624
- async function $r(e) {
625
- const t = await Bn(e);
625
+ async function Yr(e) {
626
+ const t = await qn(e);
626
627
  return { w: t?.width ?? 0, h: t?.height ?? 0 };
627
628
  }
628
- async function Br(e, t = {}) {
629
- const n = await je().upload(e, { signal: t.signal });
630
- if (!tt(n.key))
631
- throw new cn("Image upload returned an unusable key");
629
+ async function zr(e, t = {}) {
630
+ const n = await Ue().upload(e, { signal: t.signal });
631
+ if (!at(n.key))
632
+ throw new mn("Image upload returned an unusable key");
632
633
  return { key: n.key, deduplicated: n.deduplicated === !0 };
633
634
  }
634
- async function Gr(e, t = {}) {
635
+ async function Xr(e, t = {}) {
635
636
  const n = [];
636
637
  for (const r of e) {
637
638
  if (r.kind === "remote") {
638
639
  n.push({ key: r.key, w: r.w, h: r.h, ...r.title ? { title: r.title } : {} });
639
640
  continue;
640
641
  }
641
- const { key: a } = await Br(r.file, t);
642
+ const { key: a } = await zr(r.file, t);
642
643
  n.push({ key: a, w: r.w, h: r.h });
643
644
  }
644
645
  return n;
645
646
  }
646
- function qr(e) {
647
+ function Jr(e) {
647
648
  return {
648
649
  error: e instanceof Error ? e.message : String(e),
649
650
  name: e instanceof Error ? e.name : typeof e,
650
- reason: e instanceof Ye ? e.reason : void 0,
651
- status: e instanceof Ye ? e.status : void 0
651
+ reason: e instanceof ze ? e.reason : void 0,
652
+ status: e instanceof ze ? e.status : void 0
652
653
  };
653
654
  }
654
- const ze = 240, X = 8, Vr = 28, dn = 240;
655
- function Kr(e, t, n) {
656
- let r = t.left - ze - X;
657
- r < X && (r = t.right + X), r = Math.min(r, n.width - ze - X), r = Math.max(X, r);
658
- const a = dn + Vr;
655
+ const Xe = 240, X = 8, Zr = 28, fn = 240;
656
+ function Qr(e, t, n) {
657
+ let r = t.left - Xe - X;
658
+ r < X && (r = t.right + X), r = Math.min(r, n.width - Xe - X), r = Math.max(X, r);
659
+ const a = fn + Zr;
659
660
  let i = e.top + e.height / 2 - a / 2;
660
661
  return i = Math.min(i, n.height - a - X), i = Math.max(X, i), { left: r, top: i };
661
662
  }
662
- const un = "/dataplatform/api/memes", Wr = 120;
663
- function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
664
- const [r, a] = R(""), i = z(null), s = z(null), l = je(), { items: u, loading: h, error: f, hasMore: O, loadMore: M } = Qn(
663
+ const pn = "/dataplatform/api/memes", eo = 120;
664
+ function to({ onClose: e, onPick: t, onUnavailable: n }) {
665
+ const [r, a] = R(""), i = K(null), s = K(null), l = Ue(), { items: m, loading: h, error: u, hasMore: D, loadMore: M } = ir(
665
666
  l,
666
- un,
667
+ pn,
667
668
  r.trim()
668
- ), L = f?.reason ?? null, C = Q(() => {
669
+ ), L = u?.reason ?? null, C = J(() => {
669
670
  const x = /* @__PURE__ */ new Set();
670
- return u.filter((P) => x.has(P.key) ? !1 : (x.add(P.key), !0));
671
- }, [u]), [p, v] = R(null), b = z(null), I = k(() => {
671
+ return m.filter((P) => x.has(P.key) ? !1 : (x.add(P.key), !0));
672
+ }, [m]), [p, S] = R(null), b = K(null), I = k(() => {
672
673
  b.current !== null && (window.clearTimeout(b.current), b.current = null);
673
674
  }, []), g = k(() => {
674
- I(), v(null);
675
- }, [I]), E = typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(hover: hover)").matches, N = k(
675
+ I(), S(null);
676
+ }, [I]), E = typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(hover: hover)").matches, O = k(
676
677
  (x, P, T = !1) => {
677
678
  const he = i.current;
678
679
  if (!he) return;
679
- const ge = () => v({
680
+ const ge = () => S({
680
681
  item: x,
681
- ...Kr(P.getBoundingClientRect(), he.getBoundingClientRect(), {
682
+ ...Qr(P.getBoundingClientRect(), he.getBoundingClientRect(), {
682
683
  width: window.innerWidth,
683
684
  height: window.innerHeight
684
685
  })
685
686
  });
686
- I(), T ? ge() : b.current = window.setTimeout(ge, Wr);
687
+ I(), T ? ge() : b.current = window.setTimeout(ge, eo);
687
688
  },
688
689
  [I]
689
690
  );
690
- D(() => () => I(), [I]), D(() => {
691
+ N(() => () => I(), [I]), N(() => {
691
692
  L === "unavailable" && n?.();
692
- }, [L, n]), D(() => {
693
+ }, [L, n]), N(() => {
693
694
  s.current?.focus();
694
- }, []), D(() => {
695
+ }, []), N(() => {
695
696
  const x = (T) => {
696
697
  T.key === "Escape" && (T.stopPropagation(), e());
697
698
  }, P = (T) => {
@@ -703,8 +704,8 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
703
704
  }, [e]);
704
705
  const U = k((x) => {
705
706
  t(x), e();
706
- }, [t, e]), F = !h && !f && C.length === 0;
707
- return /* @__PURE__ */ _(
707
+ }, [t, e]), F = !h && !u && C.length === 0;
708
+ return /* @__PURE__ */ v(
708
709
  "div",
709
710
  {
710
711
  ref: i,
@@ -726,14 +727,14 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
726
727
  className: "w-full rounded border border-border-light bg-bg-alt px-2 py-1 text-sm text-text placeholder:text-text-secondary focus:outline-none focus:border-primary"
727
728
  }
728
729
  ) }),
729
- /* @__PURE__ */ _(
730
+ /* @__PURE__ */ v(
730
731
  "div",
731
732
  {
732
733
  className: "flex-1 overflow-y-auto p-2",
733
734
  onScroll: g,
734
735
  onMouseLeave: g,
735
736
  children: [
736
- f && /* @__PURE__ */ c(
737
+ u && /* @__PURE__ */ c(
737
738
  "p",
738
739
  {
739
740
  className: "m-2 p-2 text-center text-sm bg-danger-bg text-on-danger-bg rounded",
@@ -744,7 +745,7 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
744
745
  ),
745
746
  F && /* @__PURE__ */ c("p", { className: "p-4 text-center text-sm text-text-secondary", children: r.trim() ? `No memes match "${r.trim()}"` : "The meme library is empty" }),
746
747
  C.length > 0 && /* @__PURE__ */ c("div", { className: "grid grid-cols-3 gap-1.5 sm:grid-cols-4", children: C.map((x) => {
747
- const P = Ne(x.key);
748
+ const P = Re(x.key);
748
749
  return P ? /* @__PURE__ */ c(
749
750
  "button",
750
751
  {
@@ -753,10 +754,10 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
753
754
  title: x.title,
754
755
  "data-testid": "meme-result",
755
756
  onMouseEnter: (T) => {
756
- E && N(x, T.currentTarget);
757
+ E && O(x, T.currentTarget);
757
758
  },
758
759
  onMouseLeave: g,
759
- onFocus: (T) => N(x, T.currentTarget, !0),
760
+ onFocus: (T) => O(x, T.currentTarget, !0),
760
761
  onBlur: g,
761
762
  className: "group relative aspect-square overflow-hidden rounded border border-border-light bg-bg-alt focus:outline-none focus:border-primary hover:border-primary",
762
763
  children: /* @__PURE__ */ c(
@@ -774,7 +775,7 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
774
775
  ) : null;
775
776
  }) }),
776
777
  h && /* @__PURE__ */ c("p", { className: "p-2 text-center text-xs text-text-secondary", children: "Loading…" }),
777
- O && !h && /* @__PURE__ */ c(
778
+ D && !h && /* @__PURE__ */ c(
778
779
  "button",
779
780
  {
780
781
  type: "button",
@@ -787,7 +788,7 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
787
788
  ]
788
789
  }
789
790
  ),
790
- p && /* @__PURE__ */ _(
791
+ p && /* @__PURE__ */ v(
791
792
  "div",
792
793
  {
793
794
  "data-testid": "meme-preview",
@@ -795,7 +796,7 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
795
796
  style: {
796
797
  left: p.left,
797
798
  top: p.top,
798
- width: ze,
799
+ width: Xe,
799
800
  /* The placement maths reserves exactly PREVIEW_PX of width.
800
801
  Without border-box the padding and border sit OUTSIDE that
801
802
  number and the box laps over the panel it is meant to sit
@@ -809,10 +810,10 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
809
810
  /* @__PURE__ */ c(
810
811
  "img",
811
812
  {
812
- src: Ne(p.item.key) ?? void 0,
813
+ src: Re(p.item.key) ?? void 0,
813
814
  alt: "",
814
815
  className: "block w-full rounded bg-bg object-contain",
815
- style: { height: "auto", maxHeight: dn }
816
+ style: { height: "auto", maxHeight: fn }
816
817
  }
817
818
  ),
818
819
  p.item.title && /* One line. A long title must not change the box height, because
@@ -825,34 +826,34 @@ function Yr({ onClose: e, onPick: t, onUnavailable: n }) {
825
826
  }
826
827
  );
827
828
  }
828
- function zr({ open: e, ...t }) {
829
- return e ? /* @__PURE__ */ c(Yr, { ...t }) : null;
829
+ function no({ open: e, ...t }) {
830
+ return e ? /* @__PURE__ */ c(to, { ...t }) : null;
830
831
  }
831
- const st = {
832
- serverOrigin: `http://localhost:${nt}`,
832
+ const ut = {
833
+ serverOrigin: `http://localhost:${it}`,
833
834
  defaultRoomKey: "dev-room",
834
- cdnBase: Kt
835
+ cdnBase: zt
835
836
  };
836
- let Te = { ...st };
837
- function Xr(e) {
837
+ let Te = { ...ut };
838
+ function ro(e) {
838
839
  const t = Object.fromEntries(
839
840
  Object.entries(e).filter(([n, r]) => r !== void 0)
840
841
  );
841
- Te = { ...Te, ...t }, Mr({ cdnBase: Te.cdnBase });
842
+ Te = { ...Te, ...t }, Br({ cdnBase: Te.cdnBase });
842
843
  }
843
844
  function fe() {
844
845
  return Te;
845
846
  }
846
- const Jr = qt(st);
847
- function Zr(e) {
847
+ const oo = rt(ut);
848
+ function ao(e) {
848
849
  return e.serverOrigin?.replace(/\/$/, "") || "";
849
850
  }
850
- function mn() {
851
- return Zr(fe());
851
+ function hn() {
852
+ return ao(fe());
852
853
  }
853
- const fn = qt(null);
854
- function Qr() {
855
- return Dn(fn);
854
+ const gn = rt(null);
855
+ function io() {
856
+ return ot(gn);
856
857
  }
857
858
  const ne = {
858
859
  ANON_KEY: "watchparty_preferences",
@@ -860,7 +861,7 @@ const ne = {
860
861
  REPORT_LOGS_FLAG: "wp:reportLogs",
861
862
  voteKey: (e, t, n) => `watchparty_vote:${e}:${t}:${n}`
862
863
  };
863
- function Ue() {
864
+ function Fe() {
864
865
  try {
865
866
  return globalThis.localStorage ?? null;
866
867
  } catch {
@@ -869,22 +870,22 @@ function Ue() {
869
870
  }
870
871
  function B(e) {
871
872
  try {
872
- return Ue()?.getItem(e) ?? null;
873
+ return Fe()?.getItem(e) ?? null;
873
874
  } catch {
874
875
  return null;
875
876
  }
876
877
  }
877
- function lt(e, t) {
878
+ function mt(e, t) {
878
879
  try {
879
- const n = Ue();
880
+ const n = Fe();
880
881
  return n ? (n.setItem(e, t), !0) : !1;
881
882
  } catch {
882
883
  return !1;
883
884
  }
884
885
  }
885
- function eo() {
886
+ function so() {
886
887
  try {
887
- const e = Ue();
888
+ const e = Fe();
888
889
  if (!e) return [];
889
890
  const t = [];
890
891
  for (let n = 0; n < e.length; n++) {
@@ -896,51 +897,51 @@ function eo() {
896
897
  return [];
897
898
  }
898
899
  }
899
- function Re(e) {
900
+ function Oe(e) {
900
901
  try {
901
- Ue()?.removeItem(e);
902
+ Fe()?.removeItem(e);
902
903
  } catch {
903
904
  }
904
905
  }
905
- function to(e) {
906
+ function lo(e) {
906
907
  const t = B(e);
907
908
  return t === null ? null : t === "true" ? !0 : t === "false" ? !1 : null;
908
909
  }
909
- const pn = /* @__PURE__ */ new Map();
910
- let hn = !1;
911
- function Fe(e, t) {
912
- pn.set(e, t), hn && gn(e, t);
910
+ const yn = /* @__PURE__ */ new Map();
911
+ let bn = !1;
912
+ function He(e, t) {
913
+ yn.set(e, t), bn && vn(e, t);
913
914
  }
914
- function no() {
915
- hn = !0;
916
- for (const [e, t] of pn) gn(e, t);
915
+ function co() {
916
+ bn = !0;
917
+ for (const [e, t] of yn) vn(e, t);
917
918
  }
918
- function gn(e, t) {
919
+ function vn(e, t) {
919
920
  typeof window > "u" || (window[e] = t);
920
921
  }
921
- const se = [], ro = 500;
922
- let Ae = [], Xe = null;
923
- const oo = 1e3, ao = 200;
924
- let Je = null;
925
- function yn(e) {
926
- Je = e;
922
+ const se = [], uo = 500;
923
+ let Ae = [], Je = null;
924
+ const mo = 1e3, fo = 200;
925
+ let Ze = null;
926
+ function Sn(e) {
927
+ Ze = e;
927
928
  }
928
- function bn() {
929
+ function wn() {
929
930
  return B(ne.REPORT_LOGS_FLAG) === "true";
930
931
  }
931
- function io() {
932
+ function po() {
932
933
  if (typeof window > "u") return !1;
933
934
  if (window.__WP_DEBUG__ || new URLSearchParams(window.location.search).get("debug") === "true") return !0;
934
935
  const t = B(ne.DEBUG_FLAG);
935
936
  return t !== null && t !== "false";
936
937
  }
937
- function so() {
938
+ function ho() {
938
939
  const e = B(ne.DEBUG_FLAG);
939
940
  if (!e || e === "true") return null;
940
941
  const t = e.split(",").map((n) => n.trim().toLowerCase()).filter(Boolean);
941
942
  return t.length > 0 ? new Set(t) : null;
942
943
  }
943
- function lo() {
944
+ function go() {
944
945
  return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
945
946
  hour12: !1,
946
947
  hour: "2-digit",
@@ -949,24 +950,24 @@ function lo() {
949
950
  fractionalSecondDigits: 3
950
951
  });
951
952
  }
952
- function co(e) {
953
- se.push(e), se.length > ro && se.shift();
953
+ function yo(e) {
954
+ se.push(e), se.length > uo && se.shift();
954
955
  }
955
- const He = {
956
+ const $e = {
956
957
  debug: "color: #64748b; font-weight: normal;",
957
958
  warn: "color: #f59e0b; font-weight: bold;",
958
959
  error: "color: #ef4444; font-weight: bold;",
959
960
  category: "color: #3b82f6; font-weight: bold;",
960
961
  time: "color: #6b7280; font-weight: normal;"
961
962
  };
962
- function uo(e) {
963
+ function bo(e) {
963
964
  try {
964
965
  return JSON.stringify(e);
965
966
  } catch {
966
967
  return "[unserializable]";
967
968
  }
968
969
  }
969
- function ct(e, t, n, r, a, i, s) {
970
+ function ft(e, t, n, r, a, i, s) {
970
971
  const l = {
971
972
  level: e,
972
973
  category: a,
@@ -974,47 +975,47 @@ function ct(e, t, n, r, a, i, s) {
974
975
  data: s,
975
976
  timestamp: Date.now()
976
977
  };
977
- if (co(l), (n || bn()) && xt(l), !r) {
978
- if (!io()) return;
979
- const f = so();
980
- if (f && !f.has(a.toLowerCase())) return;
978
+ if (yo(l), (n || wn()) && Et(l), !r) {
979
+ if (!po()) return;
980
+ const u = ho();
981
+ if (u && !u.has(a.toLowerCase())) return;
981
982
  }
982
- const u = lo(), h = s !== void 0 ? " " + uo(s) : "";
983
+ const m = go(), h = s !== void 0 ? " " + bo(s) : "";
983
984
  t(
984
- `%c[${u}]%c [${a}]%c ${i}${h}`,
985
- He.time,
986
- He.category,
987
- He[e]
985
+ `%c[${m}]%c [${a}]%c ${i}${h}`,
986
+ $e.time,
987
+ $e.category,
988
+ $e[e]
988
989
  );
989
990
  }
990
991
  function d(e, t, n) {
991
- ct("debug", console.log, !1, !1, e, t, n);
992
+ ft("debug", console.log, !1, !1, e, t, n);
992
993
  }
993
994
  function A(e, t, n) {
994
- ct("warn", console.warn, !0, !1, e, t, n);
995
+ ft("warn", console.warn, !0, !1, e, t, n);
995
996
  }
996
997
  function Ee(e, t, n) {
997
- ct("error", console.error, !0, !0, e, t, n);
998
+ ft("error", console.error, !0, !0, e, t, n);
998
999
  }
999
- function mo() {
1000
+ function vo() {
1000
1001
  return [...se];
1001
1002
  }
1002
- function fo() {
1003
+ function So() {
1003
1004
  se.length = 0;
1004
1005
  }
1005
- function po(e) {
1006
+ function wo(e) {
1006
1007
  const t = e && e.length > 0 ? e.join(",") : "true";
1007
- lt(ne.DEBUG_FLAG, t), console.log("[wp] Debug mode enabled");
1008
+ mt(ne.DEBUG_FLAG, t), console.log("[wp] Debug mode enabled");
1008
1009
  }
1009
- function ho() {
1010
- Re(ne.DEBUG_FLAG), console.log("[wp] Debug mode disabled");
1010
+ function _o() {
1011
+ Oe(ne.DEBUG_FLAG), console.log("[wp] Debug mode disabled");
1011
1012
  }
1012
- const go = 1024, yo = 5e4;
1013
- function bo(e) {
1013
+ const xo = 1024, Io = 5e4;
1014
+ function Co(e) {
1014
1015
  if (e == null) return e;
1015
1016
  try {
1016
1017
  const t = JSON.stringify(e);
1017
- if (t.length <= go) return e;
1018
+ if (t.length <= xo) return e;
1018
1019
  if (typeof e == "object" && !Array.isArray(e)) {
1019
1020
  const n = {};
1020
1021
  for (const [r, a] of Object.entries(e)) {
@@ -1028,35 +1029,35 @@ function bo(e) {
1028
1029
  return "[unserializable]";
1029
1030
  }
1030
1031
  }
1031
- async function vo() {
1032
+ async function To() {
1032
1033
  if (Ae.length === 0) return;
1033
1034
  const e = Ae;
1034
- Ae = [], Xe = null;
1035
+ Ae = [], Je = null;
1035
1036
  try {
1036
1037
  let n = fe().serverOrigin || "";
1037
1038
  if ((n === "/" || !n) && typeof window < "u") {
1038
1039
  const l = window.location;
1039
- (l.hostname === "localhost" || l.hostname === "127.0.0.1") && l.port === String(Yt) ? n = `${l.protocol}//${l.hostname}:${nt}` : n = l.origin;
1040
+ (l.hostname === "localhost" || l.hostname === "127.0.0.1") && l.port === String(Jt) ? n = `${l.protocol}//${l.hostname}:${it}` : n = l.origin;
1040
1041
  }
1041
1042
  const r = `${n.replace(/\/$/, "")}/api/client-log`, a = e.map((l) => ({
1042
1043
  level: l.level,
1043
1044
  category: l.category,
1044
1045
  message: l.message,
1045
- data: bo(l.data),
1046
+ data: Co(l.data),
1046
1047
  timestamp: l.timestamp,
1047
1048
  url: typeof window < "u" ? window.location.href : void 0,
1048
1049
  userAgent: typeof navigator < "u" ? navigator.userAgent : void 0,
1049
- room_key: Je?.room_key,
1050
- client_id: Je?.client_id
1050
+ room_key: Ze?.room_key,
1051
+ client_id: Ze?.client_id
1051
1052
  }));
1052
1053
  let i = [], s = 0;
1053
1054
  for (const l of a) {
1054
- const u = JSON.stringify(l).length + 1;
1055
- s + u > yo && i.length > 0 && (await fetch(r, {
1055
+ const m = JSON.stringify(l).length + 1;
1056
+ s + m > Io && i.length > 0 && (await fetch(r, {
1056
1057
  method: "POST",
1057
1058
  headers: { "Content-Type": "application/json" },
1058
1059
  body: JSON.stringify({ logs: i })
1059
- }), i = [], s = 0), i.push(l), s += u;
1060
+ }), i = [], s = 0), i.push(l), s += m;
1060
1061
  }
1061
1062
  i.length > 0 && await fetch(r, {
1062
1063
  method: "POST",
@@ -1067,54 +1068,37 @@ async function vo() {
1067
1068
  console.warn("[wp] log flush failed (client logs may be lost):", pe(t).error);
1068
1069
  }
1069
1070
  }
1070
- function xt(e) {
1071
- if (Ae.push(e), !Xe) {
1072
- const t = bn() ? ao : oo;
1073
- Xe = setTimeout(() => {
1074
- vo();
1071
+ function Et(e) {
1072
+ if (Ae.push(e), !Je) {
1073
+ const t = wn() ? fo : mo;
1074
+ Je = setTimeout(() => {
1075
+ To();
1075
1076
  }, t);
1076
1077
  }
1077
1078
  }
1078
1079
  function pe(e) {
1079
1080
  return e instanceof Error ? { error: e.message, name: e.name } : { error: String(e), name: typeof e };
1080
1081
  }
1081
- Fe("__wpDebug", {
1082
- enable: po,
1083
- disable: ho,
1084
- history: mo,
1085
- clear: fo
1082
+ He("__wpDebug", {
1083
+ enable: wo,
1084
+ disable: _o,
1085
+ history: vo,
1086
+ clear: So
1086
1087
  });
1087
- const Y = {
1088
- resolved: !1,
1089
- userType: "public",
1090
- accountId: null
1091
- };
1092
- function dt() {
1093
- return Y.accountId ? Y.accountId : Y.resolved && Y.userType === "public" ? "anon" : null;
1094
- }
1095
- function So(e) {
1096
- Y.resolved = !0, e.userType && (Y.userType = e.userType), e.userId !== void 0 && (Y.accountId = e.userId && e.userId !== "public" ? e.userId : null);
1088
+ function _n(e) {
1089
+ return ct(e) ? xr[e] : "var(--color-neutral-bg)";
1097
1090
  }
1098
- function ut() {
1099
- return Y.accountId ?? "public";
1100
- }
1101
- function _o() {
1102
- return dt() ?? "unscoped";
1103
- }
1104
- function vn(e) {
1105
- return at(e) ? gr[e] : "var(--color-neutral-bg)";
1106
- }
1107
- function wo(e) {
1108
- return at(e) ? `${fe().serverOrigin.replace(/\/$/, "")}${br(e)}` : void 0;
1091
+ function Ao(e) {
1092
+ return ct(e) ? `${fe().serverOrigin.replace(/\/$/, "")}${Cr(e)}` : void 0;
1109
1093
  }
1110
1094
  let de = null, Se = null;
1111
- function xo() {
1095
+ function Eo() {
1112
1096
  return de ? Promise.resolve() : Se || (Se = (async () => {
1113
1097
  try {
1114
1098
  const e = fe().serverOrigin.replace(/\/$/, ""), t = await fetch(`${e}/media/sprites/names.json`, { cache: "no-cache" });
1115
1099
  if (!t.ok) return;
1116
1100
  const n = await t.json();
1117
- de = n, Fe("__DISPLAY_NAMES__", n), d("characters", "Loaded display names", n);
1101
+ de = n, He("__DISPLAY_NAMES__", n), d("characters", "Loaded display names", n);
1118
1102
  } catch (e) {
1119
1103
  d("characters", "display names fetch failed (degrading to sprite IDs)", pe(e));
1120
1104
  }
@@ -1123,11 +1107,28 @@ function xo() {
1123
1107
  function ue(e) {
1124
1108
  return de?.[e] || e.charAt(0).toUpperCase() + e.slice(1);
1125
1109
  }
1126
- function J(e) {
1110
+ function Z(e) {
1127
1111
  const t = e.toLowerCase();
1128
- return Le.some((n) => n === t) ? !0 : de ? Object.values(de).some((n) => n.toLowerCase() === t) : !1;
1112
+ return je.some((n) => n === t) ? !0 : de ? Object.values(de).some((n) => n.toLowerCase() === t) : !1;
1113
+ }
1114
+ const z = {
1115
+ resolved: !1,
1116
+ userType: "public",
1117
+ accountId: null
1118
+ };
1119
+ function pt() {
1120
+ return z.accountId ? z.accountId : z.resolved && z.userType === "public" ? "anon" : null;
1121
+ }
1122
+ function ko(e) {
1123
+ z.resolved = !0, e.userType && (z.userType = e.userType), e.userId !== void 0 && (z.accountId = e.userId && e.userId !== "public" ? e.userId : null);
1124
+ }
1125
+ function ht() {
1126
+ return z.accountId ?? "public";
1129
1127
  }
1130
- const Io = o.object({
1128
+ function No() {
1129
+ return pt() ?? "unscoped";
1130
+ }
1131
+ const Po = o.object({
1131
1132
  // Identity. There is deliberately NO `name`: a person's name is their
1132
1133
  // hadoku key-registry name, resolved by the server from whoami and renamed
1133
1134
  // through hadoku_site's POST /session/name (operator decision 2026-10-08).
@@ -1152,18 +1153,18 @@ const Io = o.object({
1152
1153
  preferredAudioLang: o.string().optional(),
1153
1154
  subtitlesEnabled: o.boolean().optional(),
1154
1155
  subtitleStyle: o.string().optional()
1155
- }), le = Kn({
1156
+ }), le = Qn({
1156
1157
  appId: "watchparty",
1157
- schema: Io
1158
- }), Co = /* @__PURE__ */ new Set(["theme", "themeMode"]);
1158
+ schema: Po
1159
+ }), Ro = /* @__PURE__ */ new Set(["theme", "themeMode"]);
1159
1160
  function De(e) {
1160
- const t = dt();
1161
+ const t = pt();
1161
1162
  return t ? `prefs-cache:${t}:${e}` : null;
1162
1163
  }
1163
- function To() {
1164
- return dt() === null;
1164
+ function Oo() {
1165
+ return pt() === null;
1165
1166
  }
1166
- function It(e) {
1167
+ function kt(e) {
1167
1168
  const t = De(e);
1168
1169
  if (!t) return {};
1169
1170
  const n = B(t);
@@ -1174,10 +1175,10 @@ function It(e) {
1174
1175
  return {};
1175
1176
  }
1176
1177
  }
1177
- function Ao() {
1178
+ function Do() {
1178
1179
  let e = 0;
1179
- for (const t of eo()) {
1180
- const n = t.startsWith("prefs-cache:") && t.endsWith(":watchparty"), r = t === Oe || t.startsWith(`${Oe}:`) && !t.endsWith(":_serverSynced_v1");
1180
+ for (const t of so()) {
1181
+ const n = t.startsWith("prefs-cache:") && t.endsWith(":watchparty"), r = t === Me || t.startsWith(`${Me}:`) && !t.endsWith(":_serverSynced_v1");
1181
1182
  if (!n && !r) continue;
1182
1183
  const a = B(t);
1183
1184
  if (!a) continue;
@@ -1189,18 +1190,18 @@ function Ao() {
1189
1190
  }
1190
1191
  const s = n ? i?.blob : i;
1191
1192
  if (!s || typeof s != "object" || !("name" in s)) continue;
1192
- const { name: l, ...u } = s, h = n ? { ...i, blob: u } : u;
1193
- lt(t, JSON.stringify(h)) && e++;
1193
+ const { name: l, ...m } = s, h = n ? { ...i, blob: m } : m;
1194
+ mt(t, JSON.stringify(h)) && e++;
1194
1195
  }
1195
1196
  return e > 0 && d("preferences", "Stripped retired name from cached prefs rows", { rewritten: e }), e;
1196
1197
  }
1197
- let Sn = null, _n = null;
1198
- const Ct = /* @__PURE__ */ new Set();
1199
- function mt() {
1200
- if (To())
1198
+ let xn = null, In = null;
1199
+ const Nt = /* @__PURE__ */ new Set();
1200
+ function gt() {
1201
+ if (Oo())
1201
1202
  return d("preferences", "Boot read deferred — session pending, identity unresolved"), {};
1202
- const e = It("portfolio"), t = It("watchparty"), n = Object.keys(e).length > 0 ? e : Sn ?? {}, r = Object.keys(t).length > 0 ? t : _n ?? {}, a = ut() || "public";
1203
- if (Ct.has(a))
1203
+ const e = kt("portfolio"), t = kt("watchparty"), n = Object.keys(e).length > 0 ? e : xn ?? {}, r = Object.keys(t).length > 0 ? t : In ?? {}, a = ht() || "public";
1204
+ if (Nt.has(a))
1204
1205
  return d("preferences", "Loaded (sync, SDK-only after first read)", {
1205
1206
  uid: a,
1206
1207
  sdkThemeKeys: Object.keys(n).length,
@@ -1210,8 +1211,8 @@ function mt() {
1210
1211
  themeSource: Object.keys(e).length > 0 ? "cache" : "mem",
1211
1212
  appSource: Object.keys(t).length > 0 ? "cache" : "mem"
1212
1213
  }), { ...r, ...n };
1213
- Ct.add(a);
1214
- const i = xn() ?? {}, s = { ...i, ...r, ...n };
1214
+ Nt.add(a);
1215
+ const i = Tn() ?? {}, s = { ...i, ...r, ...n };
1215
1216
  return d("preferences", "Loaded (sync, first read — legacy + SDK)", {
1216
1217
  uid: a,
1217
1218
  sdkThemeKeys: Object.keys(n).length,
@@ -1221,30 +1222,30 @@ function mt() {
1221
1222
  appSource: Object.keys(t).length > 0 ? "cache" : "mem"
1222
1223
  }), s;
1223
1224
  }
1224
- let wn = !1;
1225
- function Eo() {
1226
- const e = ut();
1225
+ let Cn = !1;
1226
+ function Mo() {
1227
+ const e = ht();
1227
1228
  return !e || e === "public";
1228
1229
  }
1229
1230
  function G(e, t) {
1230
- Eo() && (wn = !0), Co.has(e) ? ie.save({ [e]: t }, { scope: "device" }).catch((n) => A("preferences", "themePrefs.save failed", { key: e, err: n?.message })) : le.save({ [e]: t }).catch((n) => A("preferences", "watchpartyPrefs.save failed", { key: e, err: n?.message })), d("preferences", "Saved (via SDK)", { key: e, value: t });
1231
+ Mo() && (Cn = !0), Ro.has(e) ? ie.save({ [e]: t }, { scope: "device" }).catch((n) => A("preferences", "themePrefs.save failed", { key: e, err: n?.message })) : le.save({ [e]: t }).catch((n) => A("preferences", "watchpartyPrefs.save failed", { key: e, err: n?.message })), d("preferences", "Saved (via SDK)", { key: e, value: t });
1231
1232
  }
1232
- let _e = null, Tt = !1;
1233
- function ko() {
1234
- return _e || (_e = (async () => {
1233
+ let we = null, Pt = !1;
1234
+ function Lo() {
1235
+ return we || (we = (async () => {
1235
1236
  if (typeof window > "u") return !1;
1236
1237
  try {
1237
- Tt || (Tt = !0, ie.subscribe((s) => {
1238
- Sn = s, kt("portfolio", s), Pt("theme");
1238
+ Pt || (Pt = !0, ie.subscribe((s) => {
1239
+ xn = s, Dt("portfolio", s), Mt("theme");
1239
1240
  }), le.subscribe((s) => {
1240
- _n = s, kt("watchparty", s), Pt("watchparty");
1241
+ In = s, Dt("watchparty", s), Mt("watchparty");
1241
1242
  }));
1242
1243
  const [e, t] = await Promise.all([
1243
1244
  ie.read(),
1244
1245
  le.read()
1245
1246
  ]);
1246
1247
  try {
1247
- const { useAppStore: s } = await Promise.resolve().then(() => Cn);
1248
+ const { useAppStore: s } = await Promise.resolve().then(() => En);
1248
1249
  s.getState().rehydrateFromPrefs();
1249
1250
  } catch (s) {
1250
1251
  A("preferences", "inline rehydrate after SDK read failed", { err: s?.message });
@@ -1256,7 +1257,7 @@ function ko() {
1256
1257
  // Post-fetch cache state: should be non-zero if SDK wrote it.
1257
1258
  sdkThemeBytesPost: a?.length ?? 0,
1258
1259
  sdkAppBytesPost: i?.length ?? 0
1259
- }), await Po(e, t), wn ? (d("preferences", "Promoting this load's pre-auth picks to the signed-in user"), await Promise.all([
1260
+ }), await jo(e, t), Cn ? (d("preferences", "Promoting this load's pre-auth picks to the signed-in user"), await Promise.all([
1260
1261
  ie.promoteAnonPrefsToUser().catch(() => {
1261
1262
  }),
1262
1263
  le.promoteAnonPrefsToUser().catch(() => {
@@ -1265,16 +1266,16 @@ function ko() {
1265
1266
  } catch (e) {
1266
1267
  return A("preferences", "First-load SDK sync failed (non-fatal)", { err: e?.message }), !1;
1267
1268
  }
1268
- })(), _e);
1269
+ })(), we);
1269
1270
  }
1270
- const Oe = "watchparty_preferences";
1271
- Ao();
1272
- function Ze() {
1273
- const e = ut();
1274
- return !e || e === "public" ? Oe : `${Oe}:${e}`;
1271
+ const Me = "watchparty_preferences";
1272
+ Do();
1273
+ function Qe() {
1274
+ const e = ht();
1275
+ return !e || e === "public" ? Me : `${Me}:${e}`;
1275
1276
  }
1276
- function xn() {
1277
- const e = B(Ze());
1277
+ function Tn() {
1278
+ const e = B(Qe());
1278
1279
  if (!e) return null;
1279
1280
  try {
1280
1281
  const t = JSON.parse(e);
@@ -1283,39 +1284,39 @@ function xn() {
1283
1284
  return null;
1284
1285
  }
1285
1286
  }
1286
- function At() {
1287
- Re(Ze()), Re(`${Ze()}:_serverSynced_v1`);
1287
+ function Rt() {
1288
+ Oe(Qe()), Oe(`${Qe()}:_serverSynced_v1`);
1288
1289
  }
1289
- async function Po(e, t) {
1290
- const n = xn();
1290
+ async function jo(e, t) {
1291
+ const n = Tn();
1291
1292
  if (!n || Object.keys(n).length === 0) return;
1292
1293
  const r = Object.keys(e ?? {}).length > 0, a = Object.keys(t ?? {}).length > 0, i = {}, s = {};
1293
- for (const [h, f] of Object.entries(n))
1294
- r || (h === "theme" && typeof f == "string" ? i.theme = f : h === "themeMode" && (f === "simple" || f === "advanced") && (i.themeMode = f)), a || (h === "chatCollapsed" && typeof f == "boolean" ? s.chatCollapsed = f : h === "floatingChatEnabled" && typeof f == "boolean" ? s.floatingChatEnabled = f : h === "volume" && typeof f == "number" && f >= 0 && f <= 1 ? s.volume = f : h === "muted" && typeof f == "boolean" ? s.muted = f : h === "preferredAudioLang" && typeof f == "string" ? s.preferredAudioLang = f : h === "subtitlesEnabled" && typeof f == "boolean" ? s.subtitlesEnabled = f : h === "subtitleStyle" && typeof f == "string" && (s.subtitleStyle = f));
1295
- const l = Object.keys(i), u = Object.keys(s);
1296
- if (l.length === 0 && u.length === 0) {
1297
- At();
1294
+ for (const [h, u] of Object.entries(n))
1295
+ r || (h === "theme" && typeof u == "string" ? i.theme = u : h === "themeMode" && (u === "simple" || u === "advanced") && (i.themeMode = u)), a || (h === "chatCollapsed" && typeof u == "boolean" ? s.chatCollapsed = u : h === "floatingChatEnabled" && typeof u == "boolean" ? s.floatingChatEnabled = u : h === "volume" && typeof u == "number" && u >= 0 && u <= 1 ? s.volume = u : h === "muted" && typeof u == "boolean" ? s.muted = u : h === "preferredAudioLang" && typeof u == "string" ? s.preferredAudioLang = u : h === "subtitlesEnabled" && typeof u == "boolean" ? s.subtitlesEnabled = u : h === "subtitleStyle" && typeof u == "string" && (s.subtitleStyle = u));
1296
+ const l = Object.keys(i), m = Object.keys(s);
1297
+ if (l.length === 0 && m.length === 0) {
1298
+ Rt();
1298
1299
  return;
1299
1300
  }
1300
1301
  d("preferences", "Migrating legacy localStorage prefs to SDK", {
1301
1302
  themeKeys: l,
1302
- appKeys: u,
1303
+ appKeys: m,
1303
1304
  sdkHasTheme: r,
1304
1305
  sdkHasApp: a
1305
1306
  });
1306
1307
  try {
1307
1308
  await Promise.all([
1308
1309
  l.length > 0 ? ie.save(i, { scope: "device" }) : Promise.resolve(),
1309
- u.length > 0 ? le.save(s) : Promise.resolve()
1310
- ]), At(), d("preferences", "Legacy migration complete");
1310
+ m.length > 0 ? le.save(s) : Promise.resolve()
1311
+ ]), Rt(), d("preferences", "Legacy migration complete");
1311
1312
  } catch (h) {
1312
1313
  A("preferences", "Legacy migration save failed — will retry next load", {
1313
1314
  err: h?.message
1314
1315
  });
1315
1316
  }
1316
1317
  }
1317
- let Et = !1;
1318
- function kt(e, t) {
1318
+ let Ot = !1;
1319
+ function Dt(e, t) {
1319
1320
  const n = De(e);
1320
1321
  if (n)
1321
1322
  try {
@@ -1327,15 +1328,15 @@ function kt(e, t) {
1327
1328
  };
1328
1329
  localStorage.setItem(n, JSON.stringify(r));
1329
1330
  } catch (r) {
1330
- Et || (Et = !0, A("preferences", "writeThrough localStorage failed (in-memory backstop only)", {
1331
+ Ot || (Ot = !0, A("preferences", "writeThrough localStorage failed (in-memory backstop only)", {
1331
1332
  appId: e,
1332
1333
  err: r?.message,
1333
1334
  name: r?.name
1334
1335
  }));
1335
1336
  }
1336
1337
  }
1337
- function Pt(e) {
1338
- Promise.resolve().then(() => Cn).then(({ useAppStore: t }) => {
1338
+ function Mt(e) {
1339
+ Promise.resolve().then(() => En).then(({ useAppStore: t }) => {
1339
1340
  try {
1340
1341
  t.getState().rehydrateFromPrefs();
1341
1342
  } catch (n) {
@@ -1343,33 +1344,33 @@ function Pt(e) {
1343
1344
  }
1344
1345
  }).catch((t) => A("preferences", "store import failed", { reason: e, err: t?.message }));
1345
1346
  }
1346
- const In = 320, Me = 240, ft = 640, No = 320, Ro = 36, Nt = 16;
1347
+ const An = 320, Le = 240, yt = 640, Uo = 320, Fo = 36, Lt = 16;
1347
1348
  function V(e, t) {
1348
- if (!Number.isFinite(e)) return In;
1349
- let n = ft;
1350
- return t !== void 0 && Number.isFinite(t) && t > 0 && (n = Math.min(n, t - No)), n = Math.max(n, Me), Math.round(Math.min(n, Math.max(Me, e)));
1349
+ if (!Number.isFinite(e)) return An;
1350
+ let n = yt;
1351
+ return t !== void 0 && Number.isFinite(t) && t > 0 && (n = Math.min(n, t - Uo)), n = Math.max(n, Le), Math.round(Math.min(n, Math.max(Le, e)));
1351
1352
  }
1352
- function Rt(e, t, n, r) {
1353
+ function jt(e, t, n, r) {
1353
1354
  return V(e + (t - n), r);
1354
1355
  }
1355
- function Do(e, t, n) {
1356
+ function Ho(e, t, n) {
1356
1357
  switch (t) {
1357
1358
  case "ArrowLeft":
1358
- return V(e + Nt, n);
1359
+ return V(e + Lt, n);
1359
1360
  case "ArrowRight":
1360
- return V(e - Nt, n);
1361
+ return V(e - Lt, n);
1361
1362
  case "Home":
1362
- return V(Me, n);
1363
+ return V(Le, n);
1363
1364
  case "End":
1364
- return V(ft, n);
1365
+ return V(yt, n);
1365
1366
  default:
1366
1367
  return null;
1367
1368
  }
1368
1369
  }
1369
- function Oo(e, t) {
1370
- return { collapsed: e, width: e ? Ro : t };
1370
+ function $o(e, t) {
1371
+ return { collapsed: e, width: e ? Fo : t };
1371
1372
  }
1372
- const q = mt(), m = Vn((e, t) => ({
1373
+ const q = gt(), f = Zn((e, t) => ({
1373
1374
  ready: !1,
1374
1375
  name: "",
1375
1376
  sprite: null,
@@ -1379,7 +1380,7 @@ const q = mt(), m = Vn((e, t) => ({
1379
1380
  chat: [],
1380
1381
  chatCollapsed: q.chatCollapsed ?? !1,
1381
1382
  chromeChatCollapsed: q.chromeChatCollapsed ?? !1,
1382
- chromeChatWidth: V(q.chromeChatWidth ?? In),
1383
+ chromeChatWidth: V(q.chromeChatWidth ?? An),
1383
1384
  // Hardcoded on for everyone — the per-user toggle was removed from the
1384
1385
  // control bar; FloatingChat + toggleFloatingChat code is kept for future
1385
1386
  // re-enablement but the value is no longer user-controllable.
@@ -1431,7 +1432,7 @@ const q = mt(), m = Vn((e, t) => ({
1431
1432
  rosterSize: Object.keys(n.roster).length,
1432
1433
  usedSprites: Array.from(r)
1433
1434
  });
1434
- for (const a of Le)
1435
+ for (const a of je)
1435
1436
  if (!r.has(a)) {
1436
1437
  const i = ue(a);
1437
1438
  return d("store", "Auto-identity assigned", { name: i, sprite: a }), { name: i, sprite: a };
@@ -1444,7 +1445,7 @@ const q = mt(), m = Vn((e, t) => ({
1444
1445
  applySnapshot: (n) => e((r) => {
1445
1446
  const a = { ...r.roster };
1446
1447
  if (n.users)
1447
- for (const u of n.users) a[u.clientId] = u;
1448
+ for (const m of n.users) a[m.clientId] = m;
1448
1449
  const i = n.mediaId !== void 0 ? n.mediaId : r.snapshot.mediaId, s = n.leaderId !== void 0 ? n.leaderId : r.snapshot.leaderId;
1449
1450
  d("store", "Snapshot applied", {
1450
1451
  mediaId: i,
@@ -1519,8 +1520,8 @@ const q = mt(), m = Vn((e, t) => ({
1519
1520
  const s = [...i.drift.rtts, n].slice(-5);
1520
1521
  let l = i.drift.offsetMs;
1521
1522
  if (r && a) {
1522
- const u = a + n / 2;
1523
- l = r - u;
1523
+ const m = a + n / 2;
1524
+ l = r - m;
1524
1525
  }
1525
1526
  return { drift: { rtts: s, offsetMs: l } };
1526
1527
  }),
@@ -1574,13 +1575,13 @@ const q = mt(), m = Vn((e, t) => ({
1574
1575
  */
1575
1576
  moveTierlistItem: (n, r, a) => e((i) => {
1576
1577
  const s = {};
1577
- for (const [l, u] of Object.entries(i.tierlistDraft)) {
1578
- const h = (u ?? []).filter((f) => f !== n);
1578
+ for (const [l, m] of Object.entries(i.tierlistDraft)) {
1579
+ const h = (m ?? []).filter((u) => u !== n);
1579
1580
  h.length > 0 && (s[l] = h);
1580
1581
  }
1581
1582
  if (r !== null) {
1582
- const l = s[r] ?? [], u = Math.max(0, Math.min(a ?? l.length, l.length));
1583
- l.splice(u, 0, n), s[r] = l;
1583
+ const l = s[r] ?? [], m = Math.max(0, Math.min(a ?? l.length, l.length));
1584
+ l.splice(m, 0, n), s[r] = l;
1584
1585
  }
1585
1586
  return { tierlistDraft: s };
1586
1587
  }),
@@ -1589,7 +1590,7 @@ const q = mt(), m = Vn((e, t) => ({
1589
1590
  setGameSettings: (n) => e({ gameSettings: n }),
1590
1591
  setRoomKeyType: (n) => e({ roomKeyType: n }),
1591
1592
  rehydrateFromPrefs: () => e((n) => {
1592
- const r = mt(), a = {};
1593
+ const r = gt(), a = {};
1593
1594
  if (r.chatCollapsed !== void 0 && (a.chatCollapsed = r.chatCollapsed), r.chromeChatCollapsed !== void 0 && (a.chromeChatCollapsed = r.chromeChatCollapsed), r.chromeChatWidth !== void 0 && (a.chromeChatWidth = V(r.chromeChatWidth)), ["volume", "muted", "preferredAudioLang", "subtitlesEnabled", "subtitleStyle"].some((l) => r[l] !== void 0)) {
1594
1595
  const l = { ...n.mediaPrefs };
1595
1596
  r.volume !== void 0 && (l.volume = r.volume), r.muted !== void 0 && (l.muted = r.muted), r.preferredAudioLang !== void 0 && (l.preferredAudioLang = r.preferredAudioLang), r.subtitlesEnabled !== void 0 && (l.subtitlesEnabled = r.subtitlesEnabled), r.subtitleStyle !== void 0 && ["classic", "cinema", "minimal", "contrast"].includes(r.subtitleStyle) && (l.subtitleStyle = r.subtitleStyle), a.mediaPrefs = l;
@@ -1598,27 +1599,64 @@ const q = mt(), m = Vn((e, t) => ({
1598
1599
  }),
1599
1600
  setSidebarTab: (n) => e((r) => r.sidebarTab === n && n !== "chat" ? { sidebarTab: "chat" } : { sidebarTab: n, chatCollapsed: !1 })
1600
1601
  }));
1601
- Fe("__ZUSTAND_STORE__", m);
1602
- const Cn = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1602
+ He("__ZUSTAND_STORE__", f);
1603
+ const En = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1603
1604
  __proto__: null,
1604
- useAppStore: m
1605
- }, Symbol.toStringTag, { value: "Module" }));
1606
- function Mo(e) {
1607
- return `${mn()}/media/${e}`.replace(/\\/g, "/");
1605
+ useAppStore: f
1606
+ }, Symbol.toStringTag, { value: "Module" })), bt = rt(!0);
1607
+ function Bo() {
1608
+ const e = ot(bt);
1609
+ N(() => {
1610
+ e && Wn();
1611
+ }, [e]);
1612
+ }
1613
+ function Go(e, t) {
1614
+ if (!t) return "";
1615
+ for (const n of Object.values(e))
1616
+ if (n.author === t && n.cosmetics) return JSON.stringify(n.cosmetics);
1617
+ return "";
1608
1618
  }
1609
- function Lo(e, t) {
1610
- return Mo(t ?? `${e}/poster.jpg`);
1619
+ function qo(e) {
1620
+ const t = ot(bt), n = f((r) => t ? Go(r.roster, e) : "");
1621
+ return J(() => n ? JSON.parse(n) : void 0, [n]);
1611
1622
  }
1612
- function jo(e) {
1613
- return `${mn()}${e}`.replace(/\\/g, "/");
1623
+ function Vo(e) {
1624
+ return e ? { "--hc-base": e } : {};
1625
+ }
1626
+ const et = Pe.memo(
1627
+ function({ html: t, as: n = "span", className: r, style: a }) {
1628
+ return Pe.createElement(n, { className: r, style: a, dangerouslySetInnerHTML: { __html: t } });
1629
+ },
1630
+ (e, t) => e.html === t.html && e.as === t.as && e.className === t.className && JSON.stringify(e.style) === JSON.stringify(t.style)
1631
+ );
1632
+ function Ko(e, t) {
1633
+ N(() => {
1634
+ const n = e.current;
1635
+ if (!n || !t || typeof IntersectionObserver > "u") return;
1636
+ const r = new IntersectionObserver(([a]) => {
1637
+ n.classList.toggle("hc-idle", !a?.isIntersecting);
1638
+ }, { rootMargin: "64px" });
1639
+ return r.observe(n), () => {
1640
+ r.disconnect(), n.classList.remove("hc-idle");
1641
+ };
1642
+ }, [e, t]);
1614
1643
  }
1615
- async function Uo(e) {
1644
+ function Wo(e) {
1645
+ return `${hn()}/media/${e}`.replace(/\\/g, "/");
1646
+ }
1647
+ function Yo(e, t) {
1648
+ return Wo(t ?? `${e}/poster.jpg`);
1649
+ }
1650
+ function zo(e) {
1651
+ return `${hn()}${e}`.replace(/\\/g, "/");
1652
+ }
1653
+ async function Xo(e) {
1616
1654
  try {
1617
- const t = await fetch(jo("/api/tierlist"));
1655
+ const t = await fetch(zo("/api/tierlist"));
1618
1656
  if (!t.ok)
1619
1657
  return A("tierlist", "Board fetch failed", { status: t.status }), null;
1620
1658
  const n = await t.json();
1621
- return m.getState().setTierlistSnapshot(n, e), d("tierlist", "Board loaded", {
1659
+ return f.getState().setTierlistSnapshot(n, e), d("tierlist", "Board loaded", {
1622
1660
  items: n.items.length,
1623
1661
  voters: n.voterCount,
1624
1662
  placed: n.placed.length
@@ -1627,78 +1665,78 @@ async function Uo(e) {
1627
1665
  return A("tierlist", "Board fetch threw", pe(t)), null;
1628
1666
  }
1629
1667
  }
1630
- let Dt = !1;
1631
- function Fo() {
1632
- if (Dt || typeof Image > "u") return;
1633
- const e = m.getState().tierlist;
1668
+ let Ut = !1;
1669
+ function Jo() {
1670
+ if (Ut || typeof Image > "u") return;
1671
+ const e = f.getState().tierlist;
1634
1672
  if (!(!e || e.items.length === 0)) {
1635
- Dt = !0;
1673
+ Ut = !0;
1636
1674
  for (const t of e.items) {
1637
1675
  const n = new Image();
1638
- n.decoding = "async", n.src = Lo(t.id, t.thumbnail);
1676
+ n.decoding = "async", n.src = Yo(t.id, t.thumbnail);
1639
1677
  }
1640
1678
  d("tierlist", "Warming posters", { count: e.items.length });
1641
1679
  }
1642
1680
  }
1643
- function Ho() {
1644
- const e = m.getState(), t = new Set(Object.values(e.roster).map((i) => i.sprite).filter(Boolean)), n = Le.find((i) => !t.has(i));
1681
+ function Zo() {
1682
+ const e = f.getState(), t = new Set(Object.values(e.roster).map((i) => i.sprite).filter(Boolean)), n = je.find((i) => !t.has(i));
1645
1683
  if (!n)
1646
1684
  return A("socket", "sprite_taken: no available sprites to retry with"), null;
1647
- const r = !!e.name && !J(e.name), a = r ? e.name : ue(n);
1685
+ const r = !!e.name && !Z(e.name), a = r ? e.name : ue(n);
1648
1686
  return d("socket", "sprite_taken: retrying with next available", { from: e.sprite, to: n, name: a, keptCustomName: r }), e.setSessionIdentity(a, n), { name: a, sprite: n };
1649
1687
  }
1650
- function $o(e) {
1651
- const t = m.getState(), n = e ? t.roster[e] : void 0;
1688
+ function Qo(e) {
1689
+ const t = f.getState(), n = e ? t.roster[e] : void 0;
1652
1690
  return !n || !!n.sprite && n.sprite === t.sprite;
1653
1691
  }
1654
- const Ot = "hadoku:avatar";
1655
- function Tn(e) {
1692
+ const Ft = "hadoku:avatar";
1693
+ function kn(e) {
1656
1694
  const t = e?.sprite ?? e?.avatar?.sprite ?? null;
1657
- return at(t) ? t : null;
1695
+ return ct(t) ? t : null;
1658
1696
  }
1659
- async function Bo(e = {}) {
1697
+ async function ea(e = {}) {
1660
1698
  const t = e.fetch ?? (typeof fetch > "u" ? void 0 : fetch), n = typeof window > "u" ? void 0 : window.location?.origin, r = e.baseUrl ?? (n ? `${n}/prefs` : void 0);
1661
1699
  if (!t || !r) return null;
1662
1700
  try {
1663
- const a = await Xn({ baseUrl: r, fetch: t }).get(), i = Tn(a);
1701
+ const a = await rr({ baseUrl: r, fetch: t }).get(), i = kn(a);
1664
1702
  return d("avatar", "Requested character from prefs-api", { sprite: i }), i;
1665
1703
  } catch (a) {
1666
- return a instanceof vt && (a.status === 401 || a.status === 403 || a.status === 404) ? d("avatar", "No avatar settings here (signed out, or no prefs-api on this origin)", { status: a.status }) : A("avatar", "Avatar settings read failed — keeping the auto-assigned character", {
1667
- status: a instanceof vt ? a.status : void 0,
1704
+ return a instanceof It && (a.status === 401 || a.status === 403 || a.status === 404) ? d("avatar", "No avatar settings here (signed out, or no prefs-api on this origin)", { status: a.status }) : A("avatar", "Avatar settings read failed — keeping the auto-assigned character", {
1705
+ status: a instanceof It ? a.status : void 0,
1668
1706
  ...pe(a)
1669
1707
  }), null;
1670
1708
  }
1671
1709
  }
1672
- function Mt(e) {
1710
+ function Ht(e) {
1673
1711
  if (!e) return !1;
1674
- const t = m.getState();
1712
+ const t = f.getState();
1675
1713
  if (t.sprite === e) return !1;
1676
- const r = !!(t.me.clientId && t.roster[t.me.clientId]?.registryName) || !t.name || !J(t.name) ? t.name : ue(e);
1714
+ const r = !!(t.me.clientId && t.roster[t.me.clientId]?.registryName) || !t.name || !Z(t.name) ? t.name : ue(e);
1677
1715
  return t.setSessionIdentity(r, e), !0;
1678
1716
  }
1679
- function Go(e, t = typeof window > "u" ? void 0 : window) {
1717
+ function ta(e, t = typeof window > "u" ? void 0 : window) {
1680
1718
  if (!t) return () => {
1681
1719
  };
1682
1720
  const n = (r) => {
1683
1721
  const a = r.detail;
1684
1722
  !a || typeof a != "object" || e(a);
1685
1723
  };
1686
- return t.addEventListener(Ot, n), () => t.removeEventListener(Ot, n);
1724
+ return t.addEventListener(Ft, n), () => t.removeEventListener(Ft, n);
1687
1725
  }
1688
- const qo = 10;
1689
- function Vo(e = typeof window < "u" ? window : void 0) {
1726
+ const na = 10;
1727
+ function ra(e = typeof window < "u" ? window : void 0) {
1690
1728
  if (!e) return { framed: !1, depth: 0 };
1691
1729
  try {
1692
1730
  let t = 0, n = e;
1693
- for (; n !== n.parent && t < qo; )
1731
+ for (; n !== n.parent && t < na; )
1694
1732
  t++, n = n.parent;
1695
1733
  return { framed: e.top ? e.top !== e.self : t > 0, depth: t };
1696
1734
  } catch {
1697
1735
  return { framed: !1, depth: 0 };
1698
1736
  }
1699
1737
  }
1700
- const Ko = "watchparty_fragment_delivery";
1701
- function Wo() {
1738
+ const oa = "watchparty_fragment_delivery";
1739
+ function aa() {
1702
1740
  if (typeof window > "u") return null;
1703
1741
  try {
1704
1742
  const e = new URLSearchParams(window.location.search).get("fragmentDelivery");
@@ -1706,93 +1744,93 @@ function Wo() {
1706
1744
  if (e === "0" || e === "false") return !1;
1707
1745
  } catch {
1708
1746
  }
1709
- return to(Ko);
1747
+ return lo(oa);
1710
1748
  }
1711
- let Yo = { ...nn }, $e = null;
1712
- const Lt = "watchparty_delivery_client_id";
1713
- function zo() {
1714
- const e = B(Lt);
1749
+ let ia = { ...an }, Be = null;
1750
+ const $t = "watchparty_delivery_client_id";
1751
+ function sa() {
1752
+ const e = B($t);
1715
1753
  if (e) return e;
1716
1754
  const t = globalThis.crypto?.randomUUID?.() ?? `d${Math.random().toString(36).slice(2)}`;
1717
- return lt(Lt, t) ? t : "";
1755
+ return mt($t, t) ? t : "";
1718
1756
  }
1719
- function Xo() {
1720
- return $e === null && ($e = Ir(Yo, zo(), Wo())), $e;
1757
+ function la() {
1758
+ return Be === null && (Be = Pr(ia, sa(), aa())), Be;
1721
1759
  }
1722
- function Jo() {
1723
- return Xo();
1760
+ function ca() {
1761
+ return la();
1724
1762
  }
1725
1763
  let ke;
1726
- function An() {
1727
- return B(Yn) || void 0;
1764
+ function Nn() {
1765
+ return B(tr) || void 0;
1728
1766
  }
1729
- function Zo() {
1767
+ function da() {
1730
1768
  if (ke) return;
1731
- const e = An();
1769
+ const e = Nn();
1732
1770
  if (e) {
1733
1771
  ke = e;
1734
1772
  return;
1735
1773
  }
1736
- Wn().then((t) => {
1774
+ er().then((t) => {
1737
1775
  t && (ke = t);
1738
1776
  }).catch(() => {
1739
1777
  d("identity", "device id unavailable — joining without one");
1740
1778
  });
1741
1779
  }
1742
- function Qo() {
1743
- return ke ??= An();
1780
+ function ua() {
1781
+ return ke ??= Nn();
1744
1782
  }
1745
- function ea(e, t) {
1783
+ function ma(e, t) {
1746
1784
  let n = 0;
1747
1785
  for (const r of e.videos) {
1748
1786
  const a = ne.voteKey(t, e.id, r.mediaId);
1749
- globalThis.localStorage?.getItem(a) != null && n++, Re(a);
1787
+ globalThis.localStorage?.getItem(a) != null && n++, Oe(a);
1750
1788
  }
1751
1789
  return n;
1752
1790
  }
1753
- const ta = 2e4, na = 1e4;
1754
- function ra() {
1791
+ const fa = 2e4, pa = 1e4;
1792
+ function ha() {
1755
1793
  return { unansweredSince: null, lastPongAt: null, lastTickAt: null };
1756
1794
  }
1757
- function oa(e, t) {
1795
+ function ga(e, t) {
1758
1796
  e.lastPongAt = t, e.unansweredSince = null;
1759
1797
  }
1760
- function aa(e, t, n) {
1761
- const r = e.lastTickAt !== null && t - e.lastTickAt > na;
1762
- return e.lastTickAt = t, n ? r || e.unansweredSince === null ? (e.unansweredSince = t, !1) : t - e.unansweredSince > ta : (e.unansweredSince = null, !1);
1798
+ function ya(e, t, n) {
1799
+ const r = e.lastTickAt !== null && t - e.lastTickAt > pa;
1800
+ return e.lastTickAt = t, n ? r || e.unansweredSince === null ? (e.unansweredSince = t, !1) : t - e.unansweredSince > fa : (e.unansweredSince = null, !1);
1763
1801
  }
1764
- function ia(e, t) {
1802
+ function ba(e, t) {
1765
1803
  return e.lastPongAt === null ? void 0 : Math.max(0, t - e.lastPongAt);
1766
1804
  }
1767
- let S = null, H = null, Pe = null, $ = null, K = null;
1768
- const sa = da(), ee = ra();
1769
- let we = null, Be = null, jt = 0, pt = null, me = !1, ht = !1, ae = !1, En = null;
1770
- function la(e) {
1771
- const t = re(), n = m.getState();
1805
+ let w = null, H = null, Ne = null, $ = null, W = null;
1806
+ const va = _a(), ee = ha();
1807
+ let _e = null, Ge = null, Bt = 0, vt = null, me = !1, St = !1, ae = !1, Pn = null;
1808
+ function Sa(e) {
1809
+ const t = re(), n = f.getState();
1772
1810
  if (n.me.clientId && n.roster[n.me.clientId])
1773
- return (e.name || e.sprite) && (d("socket", "Identity update (already joined)", { name: e.name, sprite: e.sprite }), t.emit(w.IDENTITY_UPDATE, { name: e.name, sprite: e.sprite })), t;
1774
- const r = ca(e);
1775
- return K = r, pt = { name: r.name, sprite: r.sprite }, t.connected ? (d("socket", "Emitting join", r), t.emit(w.JOIN, r)) : t.once("connect", () => {
1776
- d("socket", "Emitting join", r), t.emit(w.JOIN, r);
1811
+ return (e.name || e.sprite) && (d("socket", "Identity update (already joined)", { name: e.name, sprite: e.sprite }), t.emit(_.IDENTITY_UPDATE, { name: e.name, sprite: e.sprite })), t;
1812
+ const r = wa(e);
1813
+ return W = r, vt = { name: r.name, sprite: r.sprite }, t.connected ? (d("socket", "Emitting join", r), t.emit(_.JOIN, r)) : t.once("connect", () => {
1814
+ d("socket", "Emitting join", r), t.emit(_.JOIN, r);
1777
1815
  }), t;
1778
1816
  }
1779
- function ca(e) {
1817
+ function wa(e) {
1780
1818
  return {
1781
1819
  room_key: e.room_key,
1782
1820
  name: e.name,
1783
1821
  sprite: e.sprite,
1784
1822
  // Entry-path telemetry — see lib/embedContext.ts. Sent on every join AND
1785
1823
  // rejoin (lastJoinPayload carries it), so a reconnect keeps the attribution.
1786
- embed: Vo(),
1787
- delivery_arm: Jo(),
1824
+ embed: ra(),
1825
+ delivery_arm: ca(),
1788
1826
  // Identity tier input — see lib/deviceId.ts. Sent on every join AND rejoin
1789
1827
  // (lastJoinPayload carries it) so a reconnect lands on the same
1790
1828
  // ParticipantId rather than minting a new person.
1791
- device_id: Qo(),
1792
- tab_id: sa
1829
+ device_id: ua(),
1830
+ tab_id: va
1793
1831
  };
1794
1832
  }
1795
- function da() {
1833
+ function _a() {
1796
1834
  const e = globalThis.crypto;
1797
1835
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
1798
1836
  const t = new Uint8Array(16);
@@ -1801,66 +1839,66 @@ function da() {
1801
1839
  return Array.from(t, (n) => n.toString(16).padStart(2, "0")).join("");
1802
1840
  }
1803
1841
  function re() {
1804
- if (!S) {
1842
+ if (!w) {
1805
1843
  let t = fe().serverOrigin || "/";
1806
1844
  if (t === "/" && typeof window < "u") {
1807
1845
  const r = window.location;
1808
- (r.hostname === "localhost" || r.hostname === "127.0.0.1") && r.port === String(Yt) && (t = `${r.protocol}//${r.hostname}:${nt}`, d("socket", "Using dev fallback origin", { origin: t }));
1846
+ (r.hostname === "localhost" || r.hostname === "127.0.0.1") && r.port === String(Jt) && (t = `${r.protocol}//${r.hostname}:${it}`, d("socket", "Using dev fallback origin", { origin: t }));
1809
1847
  }
1810
1848
  const n = new URL(t.startsWith("http") ? t : `${window.location.origin}${t}`).origin;
1811
- S = zn(n, { path: er, transports: ["websocket", "polling"] }), d("socket", "Socket initialized", { origin: t }), Fe("__SOCKET__", S), $ && (clearTimeout($), $ = null), H = null, Pe = setInterval(() => {
1812
- if (aa(ee, Date.now(), !!S?.connected)) {
1849
+ w = nr(n, { path: sr, transports: ["websocket", "polling"] }), d("socket", "Socket initialized", { origin: t }), He("__SOCKET__", w), $ && (clearTimeout($), $ = null), H = null, Ne = setInterval(() => {
1850
+ if (ya(ee, Date.now(), !!w?.connected)) {
1813
1851
  A("socket", "PONG-WATCHDOG no time_pong for 20s — replacing the connection", {
1814
- sid: S?.id,
1815
- lastPongAgeMs: ia(ee, Date.now()) ?? null
1816
- }), Be = "pong-watchdog", ee.unansweredSince = null, S?.io.engine?.close();
1852
+ sid: w?.id,
1853
+ lastPongAgeMs: ba(ee, Date.now()) ?? null
1854
+ }), Ge = "pong-watchdog", ee.unansweredSince = null, w?.io.engine?.close();
1817
1855
  return;
1818
1856
  }
1819
- _a();
1820
- }, vr), S.on("connect", () => {
1821
- ht = !1;
1822
- const r = S?.id;
1857
+ Da();
1858
+ }, Tr), w.on("connect", () => {
1859
+ St = !1;
1860
+ const r = w?.id;
1823
1861
  if (d("socket", "Connected", { id: r, isReconnect: ae }), r)
1824
1862
  try {
1825
- m.getState().ensureMe(r), m.setState((a) => ({ me: { ...a.me, nextClientSeq: 1 } })), d("socket", "Reset client sequence for new connection");
1863
+ f.getState().ensureMe(r), f.setState((a) => ({ me: { ...a.me, nextClientSeq: 1 } })), d("socket", "Reset client sequence for new connection");
1826
1864
  } catch (a) {
1827
1865
  Ee("socket", "Failed to initialize store on connect", { error: a.message, sid: r });
1828
1866
  }
1829
- if (ae && K) {
1830
- const a = m.getState();
1831
- jt += 1;
1867
+ if (ae && W) {
1868
+ const a = f.getState();
1869
+ Bt += 1;
1832
1870
  const i = {
1833
- ...K,
1871
+ ...W,
1834
1872
  name: a.name,
1835
1873
  sprite: a.sprite,
1836
1874
  reconnect: {
1837
- count: jt,
1838
- reason: (we?.reason ?? "unknown").slice(0, 64),
1839
- offline_ms: we ? Math.max(0, Date.now() - we.at) : 0
1875
+ count: Bt,
1876
+ reason: (_e?.reason ?? "unknown").slice(0, 64),
1877
+ offline_ms: _e ? Math.max(0, Date.now() - _e.at) : 0
1840
1878
  }
1841
- }, s = En;
1879
+ }, s = Pn;
1842
1880
  if (d("socket", "Re-emitting join after reconnect", { room_key: i.room_key, name: i.name, sprite: i.sprite }), s) {
1843
1881
  let l = !1;
1844
- const u = () => {
1845
- l || (l = !0, S.off(w.SNAPSHOT, u), S.emit(w.CLIENT_READY, { media_id: s }), d("socket", "Re-emitted client_ready after reconnect snapshot", { mediaId: s }));
1882
+ const m = () => {
1883
+ l || (l = !0, w.off(_.SNAPSHOT, m), w.emit(_.CLIENT_READY, { media_id: s }), d("socket", "Re-emitted client_ready after reconnect snapshot", { mediaId: s }));
1846
1884
  };
1847
- S.on(w.SNAPSHOT, u), setTimeout(() => {
1848
- l || (l = !0, S.off(w.SNAPSHOT, u), A("socket", "client_ready re-emit timed out waiting for snapshot", { mediaId: s }));
1885
+ w.on(_.SNAPSHOT, m), setTimeout(() => {
1886
+ l || (l = !0, w.off(_.SNAPSHOT, m), A("socket", "client_ready re-emit timed out waiting for snapshot", { mediaId: s }));
1849
1887
  }, 1e4);
1850
1888
  }
1851
- pt = { name: i.name, sprite: i.sprite }, S.emit(w.JOIN, i), window.dispatchEvent(new CustomEvent("watchparty:socket-reconnect"));
1889
+ vt = { name: i.name, sprite: i.sprite }, w.emit(_.JOIN, i), window.dispatchEvent(new CustomEvent("watchparty:socket-reconnect"));
1852
1890
  } else ae && A("socket", "Reconnected — no join payload, not re-joining any room");
1853
1891
  ae = !0;
1854
- }), S.on("disconnect", (r) => {
1855
- yn(null), we = { reason: Be ?? r, at: Date.now() }, Be = null, d("socket", "Disconnected", { reason: r });
1856
- }), S.on("connect_error", (r) => Ee("socket", "Connection error", { message: r?.message })), S.on("reconnect_attempt", (r) => A("socket", "Reconnect attempt", { attempt: r })), S.on("reconnect_failed", () => Ee("socket", "Reconnect failed")), va(S);
1892
+ }), w.on("disconnect", (r) => {
1893
+ Sn(null), _e = { reason: Ge ?? r, at: Date.now() }, Ge = null, d("socket", "Disconnected", { reason: r });
1894
+ }), w.on("connect_error", (r) => Ee("socket", "Connection error", { message: r?.message })), w.on("reconnect_attempt", (r) => A("socket", "Reconnect attempt", { attempt: r })), w.on("reconnect_failed", () => Ee("socket", "Reconnect failed")), Ra(w);
1857
1895
  }
1858
- return S;
1896
+ return w;
1859
1897
  }
1860
- function Ge(e) {
1898
+ function qe(e) {
1861
1899
  return e.play_state === "playing" || e.playing === !0;
1862
1900
  }
1863
- function Ut(e, t) {
1901
+ function Gt(e, t) {
1864
1902
  return {
1865
1903
  id: String(e.id ?? e.server_seq ?? t ?? `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`),
1866
1904
  clientId: e.client_id,
@@ -1872,52 +1910,52 @@ function Ut(e, t) {
1872
1910
  // Attachments arrive from other clients, so the key shape is re-checked
1873
1911
  // here at the boundary rather than trusted at render time. A malformed
1874
1912
  // entry is dropped, not rendered and not allowed near an <img src>.
1875
- images: Array.isArray(e.images) ? e.images.filter((n) => !!n && tt(n.key)).slice(0, W) : void 0,
1913
+ images: Array.isArray(e.images) ? e.images.filter((n) => !!n && at(n.key)).slice(0, Y) : void 0,
1876
1914
  isSystem: e.isSystem || !1,
1877
1915
  systemType: e.systemType
1878
1916
  };
1879
1917
  }
1880
- function ua(e) {
1881
- e.on(w.SNAPSHOT, (t) => {
1882
- e.emit(tn.SYNC), m.getState().applySnapshot({
1918
+ function xa(e) {
1919
+ e.on(_.SNAPSHOT, (t) => {
1920
+ e.emit(on.SYNC), f.getState().applySnapshot({
1883
1921
  roomId: t.room_id ?? null,
1884
1922
  mediaId: t.media_id ?? null,
1885
1923
  playheadMs: t.playhead_ms || 0,
1886
- playing: Ge(t),
1924
+ playing: qe(t),
1887
1925
  serverSeq: t.server_seq || 0,
1888
1926
  leaderId: t.leader_id || null
1889
- }), m.getState().name || d("socket", "Deferring identity to presence event (snapshot carries no roster)");
1890
- const n = m.getState(), r = S?.id, i = (r ? n.roster[r] : void 0) ?? pt, s = Jn(
1927
+ }), f.getState().name || d("socket", "Deferring identity to presence event (snapshot carries no roster)");
1928
+ const n = f.getState(), r = w?.id, i = (r ? n.roster[r] : void 0) ?? vt, s = or(
1891
1929
  { name: n.name, avatarId: n.sprite },
1892
1930
  i ? { name: i.name, avatarId: i.sprite ?? null } : void 0,
1893
1931
  // A join that carried no name counts as a default one, so a name that
1894
1932
  // landed after the join (prefs) is still asserted.
1895
- (l) => l === "" || J(l)
1933
+ (l) => l === "" || Z(l)
1896
1934
  );
1897
1935
  if (s) {
1898
1936
  const l = {
1899
1937
  ...s.name !== void 0 ? { name: s.name } : {},
1900
- ...s.avatarId !== void 0 && !ht ? { sprite: s.avatarId } : {}
1938
+ ...s.avatarId !== void 0 && !St ? { sprite: s.avatarId } : {}
1901
1939
  };
1902
- Object.keys(l).length > 0 && (d("socket", "Identity update on snapshot", l), e.emit(w.IDENTITY_UPDATE, l));
1940
+ Object.keys(l).length > 0 && (d("socket", "Identity update on snapshot", l), e.emit(_.IDENTITY_UPDATE, l));
1903
1941
  }
1904
1942
  d("socket", "Received snapshot", {
1905
1943
  mediaId: t.media_id ?? null,
1906
1944
  playheadMs: t.playhead_ms || 0,
1907
- playing: Ge(t),
1945
+ playing: qe(t),
1908
1946
  leaderId: t.leader_id || null,
1909
1947
  serverSeq: t.server_seq || 0,
1910
1948
  rosterSize: Object.keys(n.roster).length
1911
- }), K?.room_key && S?.id && yn({ room_key: K.room_key, client_id: S.id });
1912
- }), e.on(w.CONTROL_BROADCAST, (t) => {
1913
- const n = m.getState();
1949
+ }), W?.room_key && w?.id && Sn({ room_key: W.room_key, client_id: w.id });
1950
+ }), e.on(_.CONTROL_BROADCAST, (t) => {
1951
+ const n = f.getState();
1914
1952
  if (Object.prototype.hasOwnProperty.call(t, "media_id")) {
1915
1953
  const r = t.media_id ?? null;
1916
1954
  n.snapshot.mediaId !== r && (n.applySnapshot({ mediaId: r }), r && n.setReadiness({ mediaId: r, ready: !1, readyCount: 0, total: 0 }), n.bumpLoadGeneration());
1917
1955
  }
1918
1956
  n.updateControlState({
1919
1957
  playheadMs: t.playhead_ms,
1920
- playing: Ge(t),
1958
+ playing: qe(t),
1921
1959
  serverSeq: t.server_seq,
1922
1960
  leaderId: t.leader_id ?? n.snapshot.leaderId
1923
1961
  }), d("socket", "Control broadcast received", {
@@ -1927,21 +1965,25 @@ function ua(e) {
1927
1965
  playState: t.play_state,
1928
1966
  mediaId: t.media_id
1929
1967
  });
1930
- }), e.on(w.CONTROL_ACK, (t) => {
1968
+ }), e.on(_.CONTROL_ACK, (t) => {
1931
1969
  typeof t?.client_seq == "number" && typeof t?.server_seq == "number" && d("socket", "Control ack received", t);
1932
- }), e.on(w.TIME_PONG, (t) => {
1933
- if (oa(ee, Date.now()), H && H.ts) {
1970
+ }), e.on(_.TIME_PONG, (t) => {
1971
+ if (ga(ee, Date.now()), H && H.ts) {
1934
1972
  const n = Date.now() - H.ts;
1935
- m.getState().addRttSample(n, t?.server_ts, H.ts), H = null, $ && (clearTimeout($), $ = null), d("socket", "Time sync RTT", { rtt: n, offset: m.getState().drift.offsetMs });
1973
+ f.getState().addRttSample(n, t?.server_ts, H.ts), H = null, $ && (clearTimeout($), $ = null), d("socket", "Time sync RTT", { rtt: n, offset: f.getState().drift.offsetMs });
1936
1974
  }
1937
- }), e.on(w.READY_STATE, (t) => {
1975
+ }), e.on(_.READY_STATE, (t) => {
1938
1976
  if (!t) return;
1939
1977
  const n = t.media_id ?? null, r = typeof t.ready_count == "number" ? t.ready_count : 0, a = typeof t.total == "number" ? t.total : 0, i = t.ready === !0;
1940
- m.getState().setReadiness({ mediaId: n, ready: i, readyCount: r, total: a }), d("socket", "Ready state received", { mediaId: n, readyCount: r, total: a, ready: i });
1978
+ f.getState().setReadiness({ mediaId: n, ready: i, readyCount: r, total: a }), d("socket", "Ready state received", { mediaId: n, readyCount: r, total: a, ready: i });
1941
1979
  });
1942
1980
  }
1943
- function ma(e) {
1944
- e.on(w.PRESENCE, (t) => {
1981
+ function Ia(e) {
1982
+ const t = Yn(e);
1983
+ return t ? { cosmetics: t } : {};
1984
+ }
1985
+ function Ca(e) {
1986
+ e.on(_.PRESENCE, (t) => {
1945
1987
  if (!t) return;
1946
1988
  if (Array.isArray(t.users)) {
1947
1989
  const r = {};
@@ -1953,103 +1995,104 @@ function ma(e) {
1953
1995
  sprite: l.sprite_id ?? l.sprite ?? null,
1954
1996
  isLeader: l.is_leader,
1955
1997
  ...l.registry_name ? { registryName: !0 } : {},
1956
- ...l.avatar_url ? { avatarUrl: l.avatar_url } : {}
1998
+ ...l.avatar_url ? { avatarUrl: l.avatar_url } : {},
1999
+ ...Ia(l.cosmetics)
1957
2000
  };
1958
- const a = m.getState(), i = S?.id, s = i ? r[i] : void 0;
2001
+ const a = f.getState(), i = w?.id, s = i ? r[i] : void 0;
1959
2002
  if (s?.registryName)
1960
- m.setState({ roster: r }), (s.name !== a.name || s.sprite && s.sprite !== a.sprite) && (d("socket", "Adopting registry name", { from: a.name, to: s.name }), m.getState().setSessionIdentity(s.name, s.sprite ?? a.sprite));
2003
+ f.setState({ roster: r }), (s.name !== a.name || s.sprite && s.sprite !== a.sprite) && (d("socket", "Adopting registry name", { from: a.name, to: s.name }), f.getState().setSessionIdentity(s.name, s.sprite ?? a.sprite));
1961
2004
  else if (i && r[i]) {
1962
- const l = r[i].name, u = r[i].sprite;
1963
- if (a.name && !J(a.name) && (r[i].name = a.name), m.setState({ roster: r }), u && u !== a.sprite) {
1964
- const h = a.name && !J(a.name), f = h ? a.name : ue(u);
1965
- d("socket", "Server reassigned sprite", { from: a.sprite, to: u, newName: f, preservingCustomName: h }), m.getState().setSessionIdentity(f, u), f !== l && e.emit(w.IDENTITY_UPDATE, { name: f });
2005
+ const l = r[i].name, m = r[i].sprite;
2006
+ if (a.name && !Z(a.name) && (r[i].name = a.name), f.setState({ roster: r }), m && m !== a.sprite) {
2007
+ const h = a.name && !Z(a.name), u = h ? a.name : ue(m);
2008
+ d("socket", "Server reassigned sprite", { from: a.sprite, to: m, newName: u, preservingCustomName: h }), f.getState().setSessionIdentity(u, m), u !== l && e.emit(_.IDENTITY_UPDATE, { name: u });
1966
2009
  }
1967
2010
  }
1968
2011
  }
1969
2012
  d("socket", "Received presence update", t);
1970
- const n = m.getState();
2013
+ const n = f.getState();
1971
2014
  if (!n.name) {
1972
2015
  n.ensureAutoIdentity?.();
1973
- const r = m.getState();
1974
- r.name && (d("socket", "Auto-assigned identity on presence", { name: r.name, sprite: r.sprite }), e.emit(w.IDENTITY_UPDATE, { name: r.name, sprite: r.sprite || void 0 }));
2016
+ const r = f.getState();
2017
+ r.name && (d("socket", "Auto-assigned identity on presence", { name: r.name, sprite: r.sprite }), e.emit(_.IDENTITY_UPDATE, { name: r.name, sprite: r.sprite || void 0 }));
1975
2018
  }
1976
2019
  });
1977
2020
  }
1978
- function fa(e) {
1979
- e.on(w.CHAT_BROADCAST, (t) => {
1980
- const n = Ut(t, t.server_seq);
1981
- m.getState().appendChat(n), d("chat", "Message received", n);
1982
- }), e.on(w.CHAT_HISTORY, (t) => {
2021
+ function Ta(e) {
2022
+ e.on(_.CHAT_BROADCAST, (t) => {
2023
+ const n = { ...Gt(t, t.server_seq), live: !0 };
2024
+ f.getState().appendChat(n), d("chat", "Message received", n);
2025
+ }), e.on(_.CHAT_HISTORY, (t) => {
1983
2026
  if (!t?.messages || !Array.isArray(t.messages)) return;
1984
- const n = t.messages.map((r) => Ut(r));
1985
- m.getState().setChat(n), d("chat", "History loaded", { count: n.length });
2027
+ const n = t.messages.map((r) => Gt(r));
2028
+ f.getState().setChat(n), d("chat", "History loaded", { count: n.length });
1986
2029
  });
1987
2030
  }
1988
- function pa(e) {
2031
+ function Aa(e) {
1989
2032
  e.on(be.STATE, (t) => {
1990
- m.getState().applyPlaylistState({
2033
+ f.getState().applyPlaylistState({
1991
2034
  playlist: t?.playlist ?? null,
1992
2035
  activeIndex: t?.activeIndex ?? null,
1993
2036
  myVotes: t?.myVotes ?? {}
1994
2037
  }), d("playlist", "Playlist state received", { playlistId: t?.playlist?.id ?? null, activeIndex: t?.activeIndex, myVoteCount: Object.keys(t?.myVotes || {}).length });
1995
2038
  }), e.on(be.VOTE_PROGRESS, (t) => {
1996
- m.getState().setVoteProgress(t?.progress ?? []), d("playlist", "Vote progress", { progressCount: t?.progress?.length });
2039
+ f.getState().setVoteProgress(t?.progress ?? []), d("playlist", "Vote progress", { progressCount: t?.progress?.length });
1997
2040
  }), e.on(be.RESULTS, (t) => {
1998
- m.getState().setPlaylistResults(t ?? null), d("playlist", "Results received", { playlistId: t?.playlist?.id, update: t?.update === !0 });
2041
+ f.getState().setPlaylistResults(t ?? null), d("playlist", "Results received", { playlistId: t?.playlist?.id, update: t?.update === !0 });
1999
2042
  }), e.on(be.VOTES_CLEARED, (t) => {
2000
2043
  if (!t?.playlistId || !Array.isArray(t.mediaIds)) return;
2001
- const n = ea(
2044
+ const n = ma(
2002
2045
  { id: t.playlistId, videos: t.mediaIds.map((a) => ({ mediaId: a })) },
2003
- _o()
2004
- ), r = m.getState();
2046
+ No()
2047
+ ), r = f.getState();
2005
2048
  r.playlist?.id === t.playlistId && r.applyPlaylistState({ playlist: r.playlist, activeIndex: r.activePlaylistIndex, myVotes: {} }), d("playlist", "Votes cleared by leader", { playlistId: t.playlistId, removed: n });
2006
2049
  });
2007
2050
  }
2008
- function ha(e) {
2009
- e.on(fr.UPDATED, () => {
2010
- d("tierlist", "Someone saved — refreshing the board"), Uo(!1);
2051
+ function Ea(e) {
2052
+ e.on(Sr.UPDATED, () => {
2053
+ d("tierlist", "Someone saved — refreshing the board"), Xo(!1);
2011
2054
  });
2012
2055
  }
2013
- function ga(e) {
2014
- e.on(pr.STATE, (t) => {
2056
+ function ka(e) {
2057
+ e.on(wr.STATE, (t) => {
2015
2058
  if (!t || typeof t.active != "boolean") return;
2016
2059
  const n = Array.isArray(t.ready) ? t.ready.filter((r) => typeof r == "string") : [];
2017
- m.getState().setReadyCheckState({ active: t.active, ready: n }), d("ready-check", "State received", { active: t.active, readyCount: n.length });
2060
+ f.getState().setReadyCheckState({ active: t.active, ready: n }), d("ready-check", "State received", { active: t.active, readyCount: n.length });
2018
2061
  });
2019
2062
  }
2020
- function ya(e) {
2021
- e.on(tn.ACTIVE, (t) => {
2063
+ function Na(e) {
2064
+ e.on(on.ACTIVE, (t) => {
2022
2065
  const n = typeof t?.gameId == "string" ? t.gameId : null;
2023
- m.getState().setActiveGameId(n), d("game", "game_active", { gameId: n });
2066
+ f.getState().setActiveGameId(n), d("game", "game_active", { gameId: n });
2024
2067
  });
2025
2068
  }
2026
- function ba(e) {
2027
- e.on(w.HEALTH_SNAPSHOT, (t) => {
2028
- m.getState().setHealthSnapshot(t);
2029
- }), e.on(w.BUFFER_STATUS, (t) => {
2030
- m.getState().setBufferStatus(t);
2069
+ function Pa(e) {
2070
+ e.on(_.HEALTH_SNAPSHOT, (t) => {
2071
+ f.getState().setHealthSnapshot(t);
2072
+ }), e.on(_.BUFFER_STATUS, (t) => {
2073
+ f.getState().setBufferStatus(t);
2031
2074
  });
2032
2075
  }
2033
- function va(e) {
2034
- ua(e), ma(e), fa(e), ba(e), pa(e), ha(e), ga(e), ya(e), e.on(w.ERROR, (t) => {
2076
+ function Ra(e) {
2077
+ xa(e), Ca(e), Ta(e), Pa(e), Aa(e), Ea(e), ka(e), Na(e), e.on(_.ERROR, (t) => {
2035
2078
  const n = t?.code || "error/unknown";
2036
2079
  if (n === "conflict" && t?.message === "sprite_held_by_you") {
2037
- ht = !0, d("socket", "sprite held by this account's other connection: keeping the server-assigned sprite");
2080
+ St = !0, d("socket", "sprite held by this account's other connection: keeping the server-assigned sprite");
2038
2081
  return;
2039
2082
  }
2040
2083
  if (n === "conflict" && t?.message === "sprite_taken") {
2041
- if ($o(S?.id)) {
2084
+ if (Qo(w?.id)) {
2042
2085
  d("socket", "sprite_taken: stale, the server already has our sprite");
2043
2086
  return;
2044
2087
  }
2045
2088
  me = !0;
2046
2089
  let s;
2047
2090
  try {
2048
- s = Ho();
2091
+ s = Zo();
2049
2092
  } finally {
2050
2093
  me = !1;
2051
2094
  }
2052
- s && e.emit(w.IDENTITY_UPDATE, s);
2095
+ s && e.emit(_.IDENTITY_UPDATE, s);
2053
2096
  return;
2054
2097
  }
2055
2098
  const a = {
@@ -2070,55 +2113,55 @@ function va(e) {
2070
2113
  "recap/not_found": "No recap available for the previous episode."
2071
2114
  }[n] || n;
2072
2115
  if (n.startsWith("recap/")) {
2073
- d("socket", `recap unavailable: ${a}`, { code: n }), m.getState().pushToast("info", a);
2116
+ d("socket", `recap unavailable: ${a}`, { code: n }), f.getState().pushToast("info", a);
2074
2117
  return;
2075
2118
  }
2076
- (n.startsWith("auth/") ? A : Ee)("socket", `Server error: ${a}`, { code: n, raw: t }), m.getState().pushToast("error", a);
2119
+ (n.startsWith("auth/") ? A : Ee)("socket", `Server error: ${a}`, { code: n, raw: t }), f.getState().pushToast("error", a);
2077
2120
  });
2078
2121
  }
2079
- function Sa(e, t) {
2080
- re().emit(w.CHAT_SEND, t?.length ? { text: e, images: t } : { text: e });
2122
+ function Oa(e, t) {
2123
+ re().emit(_.CHAT_SEND, t?.length ? { text: e, images: t } : { text: e });
2081
2124
  }
2082
- function _a() {
2083
- H || (H = { ts: Date.now() }, re().emit(w.TIME_PING, {}), $ = setTimeout(() => {
2125
+ function Da() {
2126
+ H || (H = { ts: Date.now() }, re().emit(_.TIME_PING, {}), $ = setTimeout(() => {
2084
2127
  H && (d("socket", "Time ping timed out after 10s, clearing inflight"), H = null), $ = null;
2085
2128
  }, 1e4));
2086
2129
  }
2087
- function kn(e) {
2088
- const t = m.getState(), n = t.me.clientId;
2130
+ function Rn(e) {
2131
+ const t = f.getState(), n = t.me.clientId;
2089
2132
  if (!n || !t.roster[n]) {
2090
- Mt(e), d("socket", "Avatar change before join: the join will carry it", { sprite: e });
2133
+ Ht(e), d("socket", "Avatar change before join: the join will carry it", { sprite: e });
2091
2134
  return;
2092
2135
  }
2093
2136
  me = !0;
2094
2137
  try {
2095
- Mt(e);
2138
+ Ht(e);
2096
2139
  } finally {
2097
2140
  me = !1;
2098
2141
  }
2099
- const r = m.getState(), a = { avatar: !0 };
2100
- r.sprite && r.sprite !== t.sprite && (a.sprite = r.sprite), r.name && r.name !== t.name && (a.name = r.name), d("socket", "Sending avatar change", a), re().emit(w.IDENTITY_UPDATE, a);
2142
+ const r = f.getState(), a = { avatar: !0 };
2143
+ r.sprite && r.sprite !== t.sprite && (a.sprite = r.sprite), r.name && r.name !== t.name && (a.name = r.name), d("socket", "Sending avatar change", a), re().emit(_.IDENTITY_UPDATE, a);
2101
2144
  }
2102
2145
  let xe = { name: "", sprite: "" };
2103
- m.subscribe((e, t) => {
2146
+ f.subscribe((e, t) => {
2104
2147
  if (e.name === t.name && e.sprite === t.sprite || me) return;
2105
2148
  const n = e.me.clientId;
2106
2149
  if (!n) return;
2107
2150
  const r = e.roster[n];
2108
2151
  if (!r) return;
2109
- const a = !!e.name && !J(e.name) && e.name !== xe.name && (J(r.name || "") || r.name !== e.name), i = !!e.sprite && e.sprite !== xe.sprite && r.sprite !== e.sprite;
2152
+ const a = !!e.name && !Z(e.name) && e.name !== xe.name && (Z(r.name || "") || r.name !== e.name), i = !!e.sprite && e.sprite !== xe.sprite && r.sprite !== e.sprite;
2110
2153
  if (!a && !i) return;
2111
2154
  const s = {};
2112
- a && (s.name = e.name, xe.name = e.name), i && (s.sprite = e.sprite, xe.sprite = e.sprite), d("socket", "Identity reassert (store change)", s), S?.connected ? S.emit(w.IDENTITY_UPDATE, s) : re().emit(w.IDENTITY_UPDATE, s);
2155
+ a && (s.name = e.name, xe.name = e.name), i && (s.sprite = e.sprite, xe.sprite = e.sprite), d("socket", "Identity reassert (store change)", s), w?.connected ? w.emit(_.IDENTITY_UPDATE, s) : re().emit(_.IDENTITY_UPDATE, s);
2113
2156
  });
2114
- function wa() {
2115
- Pe && (clearInterval(Pe), Pe = null), $ && (clearTimeout($), $ = null), H = null, ee.unansweredSince = null, ee.lastTickAt = null;
2157
+ function Ma() {
2158
+ Ne && (clearInterval(Ne), Ne = null), $ && (clearTimeout($), $ = null), H = null, ee.unansweredSince = null, ee.lastTickAt = null;
2116
2159
  }
2117
- function xa() {
2118
- d("socket", "clearJoinState called", { hadPayload: K !== null, room_key: K?.room_key }), K = null, ae = !1, En = null;
2160
+ function La() {
2161
+ d("socket", "clearJoinState called", { hadPayload: W !== null, room_key: W?.room_key }), W = null, ae = !1, Pn = null;
2119
2162
  }
2120
- function Ft() {
2121
- d("socket", "leaveRoom called", { room_key: K?.room_key }), xa(), wa(), S && (S.disconnect(), S = null), m.setState({
2163
+ function qt() {
2164
+ d("socket", "leaveRoom called", { room_key: W?.room_key }), La(), Ma(), w && (w.disconnect(), w = null), f.setState({
2122
2165
  me: { clientId: null, nextClientSeq: 1 },
2123
2166
  roster: {},
2124
2167
  snapshot: { roomId: null, mediaId: null, playheadMs: 0, playing: !1, serverSeq: 0, leaderId: null },
@@ -2133,89 +2176,89 @@ function Ft() {
2133
2176
  activeGameId: null
2134
2177
  });
2135
2178
  }
2136
- function Ia() {
2179
+ function ja() {
2137
2180
  d("chat", "Emitting recap_request"), re().emit("recap_request");
2138
2181
  }
2139
- function Ca() {
2140
- D(() => Go((e) => {
2141
- const t = Tn(e);
2142
- d("avatar", "Avatar changed in the settings popout", { sprite: t, source: e.avatar?.source }), kn(t);
2182
+ function Ua() {
2183
+ N(() => ta((e) => {
2184
+ const t = kn(e);
2185
+ d("avatar", "Avatar changed in the settings popout", { sprite: t, source: e.avatar?.source }), Rn(t);
2143
2186
  }), []);
2144
2187
  }
2145
- const Ta = 0.3, Aa = 0.82, Z = 24, Ea = 32;
2146
- function ka(e) {
2188
+ const Fa = 0.3, Ha = 0.82, Q = 24, $a = 32;
2189
+ function Ba(e) {
2147
2190
  let t = 0, n = 0, r = 0, a = 0;
2148
2191
  for (let i = 0; i + 3 < e.length; i += 4) {
2149
2192
  const s = e[i + 3];
2150
- s < Ea || (t += e[i] * s, n += e[i + 1] * s, r += e[i + 2] * s, a += s);
2193
+ s < $a || (t += e[i] * s, n += e[i + 1] * s, r += e[i + 2] * s, a += s);
2151
2194
  }
2152
- return a === 0 ? null : Pa(t / a, n / a, r / a);
2195
+ return a === 0 ? null : Ga(t / a, n / a, r / a);
2153
2196
  }
2154
- function Pa(e, t, n) {
2155
- const [r, a, i] = Na(e / 255, t / 255, n / 255), s = Math.min(Aa, Math.max(Ta, i)), [l, u, h] = Ra(r, a, s), f = (O) => Math.round(O * 255).toString(16).padStart(2, "0");
2156
- return `#${f(l)}${f(u)}${f(h)}`;
2197
+ function Ga(e, t, n) {
2198
+ const [r, a, i] = qa(e / 255, t / 255, n / 255), s = Math.min(Ha, Math.max(Fa, i)), [l, m, h] = Va(r, a, s), u = (D) => Math.round(D * 255).toString(16).padStart(2, "0");
2199
+ return `#${u(l)}${u(m)}${u(h)}`;
2157
2200
  }
2158
- function Na(e, t, n) {
2201
+ function qa(e, t, n) {
2159
2202
  const r = Math.max(e, t, n), a = Math.min(e, t, n), i = (r + a) / 2;
2160
2203
  if (r === a) return [0, 0, i];
2161
2204
  const s = r - a, l = i > 0.5 ? s / (2 - r - a) : s / (r + a);
2162
- let u;
2163
- return r === e ? u = (t - n) / s + (t < n ? 6 : 0) : r === t ? u = (n - e) / s + 2 : u = (e - t) / s + 4, [u / 6, l, i];
2205
+ let m;
2206
+ return r === e ? m = (t - n) / s + (t < n ? 6 : 0) : r === t ? m = (n - e) / s + 2 : m = (e - t) / s + 4, [m / 6, l, i];
2164
2207
  }
2165
- function Ra(e, t, n) {
2208
+ function Va(e, t, n) {
2166
2209
  if (t === 0) return [n, n, n];
2167
2210
  const r = n < 0.5 ? n * (1 + t) : n + t - n * t, a = 2 * n - r, i = (s) => (s < 0 && (s += 1), s > 1 && (s -= 1), s < 1 / 6 ? a + (r - a) * 6 * s : s < 1 / 2 ? r : s < 2 / 3 ? a + (r - a) * (2 / 3 - s) * 6 : a);
2168
2211
  return [i(e + 1 / 3), i(e), i(e - 1 / 3)];
2169
2212
  }
2170
- const Qe = /* @__PURE__ */ new Map(), qe = /* @__PURE__ */ new Set(), et = /* @__PURE__ */ new Set();
2171
- function Da() {
2172
- for (const e of et) e();
2213
+ const tt = /* @__PURE__ */ new Map(), Ve = /* @__PURE__ */ new Set(), nt = /* @__PURE__ */ new Set();
2214
+ function Ka() {
2215
+ for (const e of nt) e();
2173
2216
  }
2174
- function Oa(e) {
2175
- if (Qe.has(e) || qe.has(e) || typeof Image > "u" || typeof document > "u") return;
2176
- qe.add(e);
2217
+ function Wa(e) {
2218
+ if (tt.has(e) || Ve.has(e) || typeof Image > "u" || typeof document > "u") return;
2219
+ Ve.add(e);
2177
2220
  const t = new Image();
2178
2221
  t.crossOrigin = "anonymous", t.referrerPolicy = "no-referrer";
2179
2222
  const n = (r) => {
2180
- qe.delete(e), Qe.set(e, r), Da();
2223
+ Ve.delete(e), tt.set(e, r), Ka();
2181
2224
  };
2182
2225
  t.onload = () => {
2183
2226
  try {
2184
2227
  const r = document.createElement("canvas");
2185
- r.width = Z, r.height = Z;
2228
+ r.width = Q, r.height = Q;
2186
2229
  const a = r.getContext("2d", { willReadFrequently: !0 });
2187
2230
  if (!a) {
2188
2231
  n(null);
2189
2232
  return;
2190
2233
  }
2191
- a.drawImage(t, 0, 0, Z, Z), n(ka(a.getImageData(0, 0, Z, Z).data));
2234
+ a.drawImage(t, 0, 0, Q, Q), n(Ba(a.getImageData(0, 0, Q, Q).data));
2192
2235
  } catch (r) {
2193
2236
  d("avatar", "picture colour unreadable", { url: e, error: r instanceof Error ? r.message : String(r) }), n(null);
2194
2237
  }
2195
2238
  }, t.onerror = () => n(null), t.src = e;
2196
2239
  }
2197
- function Ma(e) {
2198
- return et.add(e), () => et.delete(e);
2240
+ function Ya(e) {
2241
+ return nt.add(e), () => nt.delete(e);
2199
2242
  }
2200
- function La(e, t) {
2243
+ function za(e, t) {
2201
2244
  if (t) {
2202
- const n = Qe.get(t);
2245
+ const n = tt.get(t);
2203
2246
  if (n) return n;
2204
2247
  }
2205
- return vn(e);
2248
+ return _n(e);
2206
2249
  }
2207
- function Pn(e, t) {
2208
- return D(() => {
2209
- t && Oa(t);
2210
- }, [t]), On(Ma, () => La(e, t), () => vn(e));
2250
+ function On(e, t) {
2251
+ return N(() => {
2252
+ t && Wa(t);
2253
+ }, [t]), Ln(Ya, () => za(e, t), () => _n(e));
2211
2254
  }
2212
- function ja(e, t) {
2255
+ function Xa(e, t) {
2213
2256
  if (t) {
2214
2257
  for (const n of Object.values(e))
2215
2258
  if (n.author === t && n.avatarUrl) return n.avatarUrl;
2216
2259
  }
2217
2260
  }
2218
- function Nn({ sprite: e, url: t, alt: n = "", className: r, style: a, fallback: i }) {
2261
+ function Dn({ sprite: e, url: t, alt: n = "", className: r, style: a, fallback: i }) {
2219
2262
  const [s, l] = R(null);
2220
2263
  if (t && t !== s)
2221
2264
  return /* @__PURE__ */ c(
@@ -2230,22 +2273,37 @@ function Nn({ sprite: e, url: t, alt: n = "", className: r, style: a, fallback:
2230
2273
  onError: () => l(t)
2231
2274
  }
2232
2275
  );
2233
- const u = wo(e);
2234
- return u ? /* @__PURE__ */ c("img", { src: u, alt: n, crossOrigin: "anonymous", className: r, style: a, draggable: !1 }) : /* @__PURE__ */ c(ce, { children: i });
2276
+ const m = Ao(e);
2277
+ return m ? /* @__PURE__ */ c("img", { src: m, alt: n, crossOrigin: "anonymous", className: r, style: a, draggable: !1 }) : /* @__PURE__ */ c(ce, { children: i });
2278
+ }
2279
+ function Ja({ sprite: e, url: t, alt: n, worn: r }) {
2280
+ return /* @__PURE__ */ v("span", { className: "hc-av", style: { "--hc-sz": "32px" }, children: [
2281
+ /* @__PURE__ */ c("span", { className: "hc-pic", children: /* @__PURE__ */ c(
2282
+ Dn,
2283
+ {
2284
+ sprite: e,
2285
+ url: t,
2286
+ alt: n,
2287
+ className: "w-8 h-8 rounded-full object-cover flex-shrink-0",
2288
+ fallback: /* @__PURE__ */ c("span", { className: "inline-block w-8 h-8 bg-bg-alt/50 rounded-full flex-shrink-0" })
2289
+ }
2290
+ ) }),
2291
+ r?.overlay && /* @__PURE__ */ c(et, { html: zn(r), style: { display: "contents" } })
2292
+ ] });
2235
2293
  }
2236
- function Ua(e) {
2294
+ function Za(e) {
2237
2295
  return !(e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey);
2238
2296
  }
2239
- function Fa({ src: e, title: t, onClose: n }) {
2240
- D(() => {
2297
+ function Qa({ src: e, title: t, onClose: n }) {
2298
+ N(() => {
2241
2299
  const i = (s) => {
2242
2300
  s.key === "Escape" && (s.stopPropagation(), n());
2243
2301
  };
2244
2302
  return document.addEventListener("keydown", i, !0), () => document.removeEventListener("keydown", i, !0);
2245
2303
  }, [n]);
2246
- const r = Qr(), a = typeof document > "u" ? null : document.fullscreenElement ?? r ?? document.body;
2247
- return a ? Zn(
2248
- /* @__PURE__ */ _(
2304
+ const r = io(), a = typeof document > "u" ? null : document.fullscreenElement ?? r ?? document.body;
2305
+ return a ? ar(
2306
+ /* @__PURE__ */ v(
2249
2307
  "div",
2250
2308
  {
2251
2309
  className: "fixed inset-0 z-[10000] flex flex-col items-center justify-center bg-black/85 p-6",
@@ -2282,12 +2340,12 @@ function Fa({ src: e, title: t, onClose: n }) {
2282
2340
  a
2283
2341
  ) : null;
2284
2342
  }
2285
- const Ve = 240, Ha = 320;
2286
- function $a({ image: e }) {
2287
- const [t, n] = R(!1), r = Ne(e.key);
2343
+ const Ke = 240, ei = 320;
2344
+ function ti({ image: e }) {
2345
+ const [t, n] = R(!1), r = Re(e.key);
2288
2346
  if (!r) return null;
2289
- const a = e.w > 0 && e.h > 0, i = a ? Math.min(1, Ha / e.w, Ve / e.h) : 1;
2290
- return /* @__PURE__ */ _(ce, { children: [
2347
+ const a = e.w > 0 && e.h > 0, i = a ? Math.min(1, ei / e.w, Ke / e.h) : 1;
2348
+ return /* @__PURE__ */ v(ce, { children: [
2291
2349
  /* @__PURE__ */ c(
2292
2350
  "a",
2293
2351
  {
@@ -2297,7 +2355,7 @@ function $a({ image: e }) {
2297
2355
  className: "block max-w-full cursor-zoom-in",
2298
2356
  "data-testid": "chat-image",
2299
2357
  onClick: (s) => {
2300
- Ua(s) && (s.preventDefault(), n(!0));
2358
+ Za(s) && (s.preventDefault(), n(!0));
2301
2359
  },
2302
2360
  children: /* @__PURE__ */ c(
2303
2361
  "img",
@@ -2309,13 +2367,13 @@ function $a({ image: e }) {
2309
2367
  width: a ? Math.round(e.w * i) : void 0,
2310
2368
  height: a ? Math.round(e.h * i) : void 0,
2311
2369
  className: "rounded border border-border-light object-contain bg-bg-alt/30",
2312
- style: a ? { aspectRatio: `${e.w} / ${e.h}`, maxWidth: "100%", maxHeight: Ve } : { maxWidth: "100%", maxHeight: Ve }
2370
+ style: a ? { aspectRatio: `${e.w} / ${e.h}`, maxWidth: "100%", maxHeight: Ke } : { maxWidth: "100%", maxHeight: Ke }
2313
2371
  }
2314
2372
  )
2315
2373
  }
2316
2374
  ),
2317
2375
  t && /* @__PURE__ */ c(
2318
- Fa,
2376
+ Qa,
2319
2377
  {
2320
2378
  src: r,
2321
2379
  title: e.title,
@@ -2324,53 +2382,49 @@ function $a({ image: e }) {
2324
2382
  )
2325
2383
  ] });
2326
2384
  }
2327
- function Ba({ images: e }) {
2328
- return e?.length ? /* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1 mt-1", "data-testid": "chat-images", children: e.map((t, n) => /* @__PURE__ */ c($a, { image: t }, `${t.key}-${n}`)) }) : null;
2385
+ function ni({ images: e }) {
2386
+ return e?.length ? /* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1 mt-1", "data-testid": "chat-images", children: e.map((t, n) => /* @__PURE__ */ c(ti, { image: t }, `${t.key}-${n}`)) }) : null;
2329
2387
  }
2330
- function Ga(e, t) {
2388
+ function ri(e, t) {
2331
2389
  return e.author && t.author ? e.author === t.author : !!t.clientId && e.clientId === t.clientId;
2332
2390
  }
2333
- function Ke(e) {
2391
+ function We(e) {
2334
2392
  return new Date(e).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
2335
2393
  }
2336
- const qa = Gt.memo(function({ message: t }) {
2337
- const n = m((l) => l.me.clientId), r = m((l) => l.me.clientId ? l.roster[l.me.clientId]?.author : void 0), a = Ga(t, { clientId: n, author: r }), i = m((l) => ja(l.roster, t.author)), s = Pn(t.sprite, i);
2338
- return t.isSystem && t.systemType === "recap" ? /* @__PURE__ */ c("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ _("div", { className: "border-l-2 border-border-light pl-2.5 py-0.5", children: [
2339
- /* @__PURE__ */ _("div", { className: "text-[10px] uppercase tracking-wide text-text-muted mb-0.5", children: [
2394
+ const oi = Pe.memo(function({ message: t }) {
2395
+ const n = f((u) => u.me.clientId), r = f((u) => u.me.clientId ? u.roster[u.me.clientId]?.author : void 0), a = ri(t, { clientId: n, author: r }), i = f((u) => Xa(u.roster, t.author)), s = On(t.sprite, i), l = qo(t.isSystem ? void 0 : t.author), m = K(null);
2396
+ Ko(m, !!l);
2397
+ const [h] = R(
2398
+ () => t.live && t.text ? Xn(t.text, l) : null
2399
+ );
2400
+ return t.isSystem && t.systemType === "recap" ? /* @__PURE__ */ c("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ v("div", { className: "border-l-2 border-border-light pl-2.5 py-0.5", children: [
2401
+ /* @__PURE__ */ v("div", { className: "text-[10px] uppercase tracking-wide text-text-muted mb-0.5", children: [
2340
2402
  "Recap",
2341
- /* @__PURE__ */ c("span", { className: "ml-1.5 normal-case tracking-normal opacity-60", children: Ke(t.ts) })
2403
+ /* @__PURE__ */ c("span", { className: "ml-1.5 normal-case tracking-normal opacity-60", children: We(t.ts) })
2342
2404
  ] }),
2343
2405
  /* @__PURE__ */ c("p", { className: "text-[13px] text-text-secondary leading-relaxed whitespace-pre-wrap break-words", children: t.text })
2344
- ] }) }) : t.isSystem ? /* @__PURE__ */ _("div", { className: "px-2 py-0.5 text-[11px] text-text-muted italic text-center leading-tight", children: [
2406
+ ] }) }) : t.isSystem ? /* @__PURE__ */ v("div", { className: "px-2 py-0.5 text-[11px] text-text-muted italic text-center leading-tight", children: [
2345
2407
  t.text,
2346
- /* @__PURE__ */ c("span", { className: "ml-1 text-[10px] opacity-50", children: Ke(t.ts) })
2347
- ] }) : /* @__PURE__ */ _("div", { className: `flex items-start gap-2 px-2 py-1 hover:bg-bg-card/20 ${a ? "bg-bg-card/30" : ""}`, children: [
2348
- /* @__PURE__ */ c(
2349
- Nn,
2350
- {
2351
- sprite: t.sprite,
2352
- url: i,
2353
- alt: t.name,
2354
- className: "w-8 h-8 rounded-full object-cover flex-shrink-0",
2355
- fallback: /* @__PURE__ */ c("span", { className: "w-8 h-8 bg-bg-alt/50 rounded-full flex-shrink-0" })
2356
- }
2357
- ),
2358
- /* @__PURE__ */ _("div", { className: "flex-1 min-w-0 -mt-0.5", children: [
2359
- /* @__PURE__ */ c("span", { className: "font-medium text-[13px]", style: { color: s }, children: t.name }),
2360
- /* @__PURE__ */ c("span", { className: "text-[10px] text-text-muted opacity-60 ml-1.5", children: Ke(t.ts) }),
2361
- t.text && /* @__PURE__ */ c("p", { className: "text-[13px] text-text break-words leading-snug m-0", children: t.text }),
2362
- /* @__PURE__ */ c(Ba, { images: t.images })
2408
+ /* @__PURE__ */ c("span", { className: "ml-1 text-[10px] opacity-50", children: We(t.ts) })
2409
+ ] }) : /* @__PURE__ */ v("div", { ref: m, style: Vo(s), className: `flex items-start gap-2 px-2 py-1 hover:bg-bg-card/20 ${a ? "bg-bg-card/30" : ""}`, children: [
2410
+ /* @__PURE__ */ c(Ja, { sprite: t.sprite, url: i, alt: t.name, worn: l }),
2411
+ /* @__PURE__ */ v("div", { className: "flex-1 min-w-0 -mt-0.5", children: [
2412
+ l ? /* @__PURE__ */ c(et, { html: Jn(t.name, l), className: "text-[13px]", style: { color: s } }) : /* @__PURE__ */ c("span", { className: "font-medium text-[13px]", style: { color: s }, children: t.name }),
2413
+ /* @__PURE__ */ c("span", { className: "text-[10px] text-text-muted opacity-60 ml-1.5", children: We(t.ts) }),
2414
+ t.text && (h ? /* @__PURE__ */ c(et, { as: "p", html: h, className: "text-[13px] text-text break-words leading-snug m-0" }) : /* @__PURE__ */ c("p", { className: "text-[13px] text-text break-words leading-snug m-0", children: t.text })),
2415
+ /* @__PURE__ */ c(ni, { images: t.images })
2363
2416
  ] })
2364
2417
  ] });
2365
2418
  });
2366
- function Va() {
2367
- const e = m((a) => a.chat), t = z(null), n = z(!1), r = k(() => {
2419
+ function ai() {
2420
+ Bo();
2421
+ const e = f((a) => a.chat), t = K(null), n = K(!1), r = k(() => {
2368
2422
  const a = t.current;
2369
2423
  if (!a) return;
2370
- const { scrollHeight: i, scrollTop: s, clientHeight: l } = a, u = i - s - l;
2371
- n.current = u > 40;
2424
+ const { scrollHeight: i, scrollTop: s, clientHeight: l } = a, m = i - s - l;
2425
+ n.current = m > 40;
2372
2426
  }, []);
2373
- return D(() => {
2427
+ return N(() => {
2374
2428
  const a = t.current;
2375
2429
  a && !n.current && a.scrollTo({ top: a.scrollHeight, behavior: "smooth" });
2376
2430
  }, [e.length]), /* @__PURE__ */ c(
@@ -2381,19 +2435,19 @@ function Va() {
2381
2435
  className: "flex-1 overflow-y-auto overflow-x-hidden chat-messages",
2382
2436
  children: e.length === 0 ? /* @__PURE__ */ c("div", { className: "p-4 text-xs text-text-muted text-center", children: "No messages yet. Be the first to say something!" }) : /* @__PURE__ */ c(ce, { children: e.map((a, i) => {
2383
2437
  const s = i > 0 ? e[i - 1] : null, l = s && a.ts - s.ts > 1440 * 60 * 1e3;
2384
- return /* @__PURE__ */ _(Gt.Fragment, { children: [
2385
- l && /* @__PURE__ */ _("div", { className: "flex items-center gap-2 px-4 py-2 my-1", children: [
2438
+ return /* @__PURE__ */ v(Pe.Fragment, { children: [
2439
+ l && /* @__PURE__ */ v("div", { className: "flex items-center gap-2 px-4 py-2 my-1", children: [
2386
2440
  /* @__PURE__ */ c("div", { className: "flex-1 h-px bg-border" }),
2387
2441
  /* @__PURE__ */ c("span", { className: "text-[10px] text-text-muted whitespace-nowrap", children: new Date(a.ts).toLocaleDateString([], { weekday: "short", month: "short", day: "numeric" }) }),
2388
2442
  /* @__PURE__ */ c("div", { className: "flex-1 h-px bg-border" })
2389
2443
  ] }),
2390
- /* @__PURE__ */ c(qa, { message: a })
2444
+ /* @__PURE__ */ c(oi, { message: a })
2391
2445
  ] }, a.id);
2392
2446
  }) })
2393
2447
  }
2394
2448
  );
2395
2449
  }
2396
- const gt = [
2450
+ const wt = [
2397
2451
  {
2398
2452
  name: "recap",
2399
2453
  description: "Summarise the previous episode of what is loaded",
@@ -2414,12 +2468,12 @@ const gt = [
2414
2468
  scope: "local"
2415
2469
  }
2416
2470
  ], te = "/";
2417
- function Ka(e) {
2471
+ function ii(e) {
2418
2472
  if (!e.startsWith(te)) return null;
2419
2473
  const t = e.slice(te.length);
2420
2474
  return /\s/.test(t) ? null : t.toLowerCase();
2421
2475
  }
2422
- function Wa(e, t = gt) {
2476
+ function si(e, t = wt) {
2423
2477
  const n = e.toLowerCase();
2424
2478
  if (!n) return [...t].sort((a, i) => a.name.localeCompare(i.name));
2425
2479
  const r = [];
@@ -2429,23 +2483,23 @@ function Wa(e, t = gt) {
2429
2483
  }
2430
2484
  return r.sort((a, i) => a.rank - i.rank || a.cmd.name.localeCompare(i.cmd.name)).map((a) => a.cmd);
2431
2485
  }
2432
- function Ya(e) {
2486
+ function li(e) {
2433
2487
  return `${te}${e.name} `;
2434
2488
  }
2435
- function We(e, t) {
2489
+ function Ye(e, t) {
2436
2490
  return t <= 0 ? 0 : (e % t + t) % t;
2437
2491
  }
2438
- function za(e, t = gt) {
2492
+ function ci(e, t = wt) {
2439
2493
  const n = e.trim();
2440
2494
  if (!n) return null;
2441
2495
  if (!n.startsWith(te)) return { kind: "chat", text: n };
2442
- const r = n.slice(te.length), a = r.search(/\s/), i = (a === -1 ? r : r.slice(0, a)).toLowerCase(), s = a === -1 ? "" : r.slice(a).trim(), l = t.find((u) => u.name.toLowerCase() === i);
2496
+ const r = n.slice(te.length), a = r.search(/\s/), i = (a === -1 ? r : r.slice(0, a)).toLowerCase(), s = a === -1 ? "" : r.slice(a).trim(), l = t.find((m) => m.name.toLowerCase() === i);
2443
2497
  return l ? { kind: "command", command: l, args: s } : { kind: "chat", text: n };
2444
2498
  }
2445
- function Xa(e, t) {
2499
+ function di(e, t) {
2446
2500
  return e.requiresMedia && !t.hasMedia ? `${te}${e.name} needs an episode loaded.` : null;
2447
2501
  }
2448
- function Ja({
2502
+ function ui({
2449
2503
  commands: e,
2450
2504
  activeIndex: t,
2451
2505
  hasMedia: n,
@@ -2463,22 +2517,22 @@ function Ja({
2463
2517
  bg-bg-card border border-border-light rounded shadow-lg
2464
2518
  list-none m-0 p-0 py-1 mb-1`,
2465
2519
  children: e.map((s, l) => {
2466
- const u = !!s.requiresMedia && !n, h = l === t;
2467
- return /* @__PURE__ */ _(
2520
+ const m = !!s.requiresMedia && !n, h = l === t;
2521
+ return /* @__PURE__ */ v(
2468
2522
  "li",
2469
2523
  {
2470
2524
  id: `${i}-opt-${s.name}`,
2471
2525
  role: "option",
2472
2526
  "aria-selected": h,
2473
- "aria-disabled": u,
2474
- onMouseDown: (f) => {
2475
- f.preventDefault(), r(s);
2527
+ "aria-disabled": m,
2528
+ onMouseDown: (u) => {
2529
+ u.preventDefault(), r(s);
2476
2530
  },
2477
2531
  onMouseEnter: () => a(l),
2478
- className: `px-3 py-1.5 cursor-pointer flex items-baseline gap-2 ${h ? "bg-bg-alt" : ""} ${u ? "opacity-50" : ""}`,
2532
+ className: `px-3 py-1.5 cursor-pointer flex items-baseline gap-2 ${h ? "bg-bg-alt" : ""} ${m ? "opacity-50" : ""}`,
2479
2533
  children: [
2480
2534
  /* @__PURE__ */ c("span", { className: "text-sm font-semibold text-text shrink-0", children: s.usage }),
2481
- /* @__PURE__ */ c("span", { className: "text-xs text-text-secondary truncate", children: u ? "needs an episode loaded" : s.description })
2535
+ /* @__PURE__ */ c("span", { className: "text-xs text-text-secondary truncate", children: m ? "needs an episode loaded" : s.description })
2482
2536
  ]
2483
2537
  },
2484
2538
  s.name
@@ -2487,12 +2541,12 @@ function Ja({
2487
2541
  }
2488
2542
  );
2489
2543
  }
2490
- function Za({
2544
+ function mi({
2491
2545
  pending: e,
2492
2546
  uploading: t,
2493
2547
  onRemove: n
2494
2548
  }) {
2495
- return e.length ? /* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1.5 pb-1.5", "data-testid": "chat-attachment-strip", children: e.map((r) => /* @__PURE__ */ _("div", { className: "relative", children: [
2549
+ return e.length ? /* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1.5 pb-1.5", "data-testid": "chat-attachment-strip", children: e.map((r) => /* @__PURE__ */ v("div", { className: "relative", children: [
2496
2550
  /* @__PURE__ */ c(
2497
2551
  "img",
2498
2552
  {
@@ -2514,84 +2568,84 @@ function Za({
2514
2568
  )
2515
2569
  ] }, r.id)) }) : null;
2516
2570
  }
2517
- function Qa() {
2518
- const [e, t] = R([]), [n, r] = R(!1), a = m((p) => p.pushToast), i = z(/* @__PURE__ */ new Set());
2519
- D(() => () => {
2571
+ function fi() {
2572
+ const [e, t] = R([]), [n, r] = R(!1), a = f((p) => p.pushToast), i = K(/* @__PURE__ */ new Set());
2573
+ N(() => () => {
2520
2574
  for (const p of i.current) URL.revokeObjectURL(p);
2521
2575
  i.current.clear();
2522
2576
  }, []);
2523
2577
  const s = k((p) => {
2524
- Lr(p) && (URL.revokeObjectURL(p.previewUrl), i.current.delete(p.previewUrl));
2578
+ Gr(p) && (URL.revokeObjectURL(p.previewUrl), i.current.delete(p.previewUrl));
2525
2579
  }, []), l = k(async (p) => {
2526
2580
  if (!p.length) return;
2527
- const v = [];
2581
+ const S = [];
2528
2582
  for (const b of p) {
2529
- const I = Ur(b);
2583
+ const I = Vr(b);
2530
2584
  if (I) {
2531
2585
  a("error", I);
2532
2586
  continue;
2533
2587
  }
2534
- const { w: g, h: E } = await $r(b), N = URL.createObjectURL(b);
2535
- i.current.add(N), v.push({
2588
+ const { w: g, h: E } = await Yr(b), O = URL.createObjectURL(b);
2589
+ i.current.add(O), S.push({
2536
2590
  kind: "file",
2537
2591
  id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
2538
2592
  file: b,
2539
- previewUrl: N,
2593
+ previewUrl: O,
2540
2594
  w: g,
2541
2595
  h: E
2542
2596
  });
2543
2597
  }
2544
- v.length && t((b) => {
2545
- const I = W - b.length;
2598
+ S.length && t((b) => {
2599
+ const I = Y - b.length;
2546
2600
  if (I <= 0) {
2547
- a("info", `Up to ${W} images per message`);
2548
- for (const g of v) s(g);
2601
+ a("info", `Up to ${Y} images per message`);
2602
+ for (const g of S) s(g);
2549
2603
  return b;
2550
2604
  }
2551
- if (v.length > I) {
2552
- a("info", `Up to ${W} images per message`);
2553
- for (const g of v.slice(I)) s(g);
2605
+ if (S.length > I) {
2606
+ a("info", `Up to ${Y} images per message`);
2607
+ for (const g of S.slice(I)) s(g);
2554
2608
  }
2555
- return [...b, ...v.slice(0, I)];
2609
+ return [...b, ...S.slice(0, I)];
2556
2610
  });
2557
- }, [a, s]), u = k((p) => {
2558
- const v = Ne(p.key);
2559
- v && (t((b) => b.length >= W ? (a("info", `Up to ${W} images per message`), b) : [...b, {
2611
+ }, [a, s]), m = k((p) => {
2612
+ const S = Re(p.key);
2613
+ S && (t((b) => b.length >= Y ? (a("info", `Up to ${Y} images per message`), b) : [...b, {
2560
2614
  kind: "remote",
2561
2615
  id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
2562
2616
  key: p.key,
2563
- previewUrl: v,
2617
+ previewUrl: S,
2564
2618
  // The catalogue spells "unknown" as null; the wire schema spells it
2565
2619
  // as 0, and the renderer falls back to natural flow on that.
2566
2620
  w: p.width ?? 0,
2567
2621
  h: p.height ?? 0,
2568
2622
  title: p.title || void 0
2569
- }]), je().catalogue(un).recordUse(p.key));
2623
+ }]), Ue().catalogue(pn).recordUse(p.key));
2570
2624
  }, [a]), h = k((p) => {
2571
- t((v) => {
2572
- const b = v.find((I) => I.id === p);
2573
- return b && s(b), v.filter((I) => I.id !== p);
2625
+ t((S) => {
2626
+ const b = S.find((I) => I.id === p);
2627
+ return b && s(b), S.filter((I) => I.id !== p);
2574
2628
  });
2575
- }, [s]), f = k(() => {
2629
+ }, [s]), u = k(() => {
2576
2630
  t((p) => {
2577
- for (const v of p) s(v);
2631
+ for (const S of p) s(S);
2578
2632
  return [];
2579
2633
  });
2580
- }, [s]), O = k((p) => {
2581
- const v = Fr(p.clipboardData);
2582
- v.length && (p.preventDefault(), l(v));
2634
+ }, [s]), D = k((p) => {
2635
+ const S = Kr(p.clipboardData);
2636
+ S.length && (p.preventDefault(), l(S));
2583
2637
  }, [l]), M = k((p) => {
2584
- const v = Hr(p.dataTransfer);
2585
- v.length && (p.preventDefault(), l(v));
2638
+ const S = Wr(p.dataTransfer);
2639
+ S.length && (p.preventDefault(), l(S));
2586
2640
  }, [l]), L = k((p) => {
2587
2641
  p.dataTransfer?.types?.includes("Files") && p.preventDefault();
2588
2642
  }, []), C = k(async () => {
2589
2643
  if (!e.length) return [];
2590
2644
  r(!0);
2591
2645
  try {
2592
- return await Gr(e);
2646
+ return await Xr(e);
2593
2647
  } catch (p) {
2594
- return A("chat", "Image upload failed", qr(p)), a("error", jr(p)), null;
2648
+ return A("chat", "Image upload failed", Jr(p)), a("error", qr(p)), null;
2595
2649
  } finally {
2596
2650
  r(!1);
2597
2651
  }
@@ -2600,47 +2654,47 @@ function Qa() {
2600
2654
  pending: e,
2601
2655
  uploading: n,
2602
2656
  addFiles: l,
2603
- addMeme: u,
2657
+ addMeme: m,
2604
2658
  remove: h,
2605
- clear: f,
2659
+ clear: u,
2606
2660
  uploadPending: C,
2607
- onPaste: O,
2661
+ onPaste: D,
2608
2662
  onDrop: M,
2609
2663
  onDragOver: L
2610
2664
  };
2611
2665
  }
2612
- const Ht = zt, ei = tr;
2613
- function ti({ commands: e = gt }) {
2614
- const [t, n] = R(""), [r, a] = R(!1), [i, s] = R({ q: null, i: 0 }), [l, u] = R(!1), h = z(null), f = Mn(), [O, M] = R(!1), [L, C] = R(!1), p = Qa(), v = m((y) => y.snapshot.mediaId), b = m((y) => y.pushToast), I = m((y) => y.setTierlistOpen), g = !!v, E = Ka(t), N = Q(
2615
- () => E === null ? [] : Wa(E, e),
2666
+ const Vt = Zt, pi = lr;
2667
+ function hi({ commands: e = wt }) {
2668
+ const [t, n] = R(""), [r, a] = R(!1), [i, s] = R({ q: null, i: 0 }), [l, m] = R(!1), h = K(null), u = jn(), [D, M] = R(!1), [L, C] = R(!1), p = fi(), S = f((y) => y.snapshot.mediaId), b = f((y) => y.pushToast), I = f((y) => y.setTierlistOpen), g = !!S, E = ii(t), O = J(
2669
+ () => E === null ? [] : si(E, e),
2616
2670
  [E, e]
2617
- ), U = E !== null && !l && N.length > 0, F = i.q === E ? We(i.i, N.length) : 0, x = k(
2671
+ ), U = E !== null && !l && O.length > 0, F = i.q === E ? Ye(i.i, O.length) : 0, x = k(
2618
2672
  (y) => s({ q: E, i: y }),
2619
2673
  [E]
2620
2674
  ), P = k((y, j) => {
2621
- const oe = Xa(y, { hasMedia: g });
2675
+ const oe = di(y, { hasMedia: g });
2622
2676
  if (oe) {
2623
2677
  b("info", oe);
2624
2678
  return;
2625
2679
  }
2626
2680
  switch (y.name) {
2627
2681
  case "help":
2628
- b("info", e.map((Rn) => Rn.usage).join(" "));
2682
+ b("info", e.map((Mn) => Mn.usage).join(" "));
2629
2683
  break;
2630
2684
  case "recap":
2631
- Ia();
2685
+ ja();
2632
2686
  break;
2633
2687
  case "tierlist":
2634
- Fo(), I(!0);
2688
+ Jo(), I(!0);
2635
2689
  break;
2636
2690
  default:
2637
2691
  b("info", `${y.usage} is not implemented yet.`);
2638
2692
  }
2639
2693
  }, [g, b, e, I]), T = k((y) => {
2640
- n(Ya(y)), u(!1), h.current?.focus();
2694
+ n(li(y)), m(!1), h.current?.focus();
2641
2695
  }, []), he = k(async (y) => {
2642
2696
  if (y.preventDefault(), r || p.uploading) return;
2643
- const j = za(t, e);
2697
+ const j = ci(t, e);
2644
2698
  if (!j && !p.pending.length) return;
2645
2699
  if (j?.kind === "command" && p.pending.length) {
2646
2700
  b("info", "Send images on their own, not with a command.");
@@ -2651,36 +2705,36 @@ function ti({ commands: e = gt }) {
2651
2705
  return;
2652
2706
  }
2653
2707
  const oe = await p.uploadPending();
2654
- oe !== null && (Sa(j?.text ?? "", oe), n(""), p.clear(), a(!0), setTimeout(() => a(!1), ei), !document.hidden && document.hasFocus() && h.current?.focus());
2708
+ oe !== null && (Oa(j?.text ?? "", oe), n(""), p.clear(), a(!0), setTimeout(() => a(!1), pi), !document.hidden && document.hasFocus() && h.current?.focus());
2655
2709
  }, [t, r, P, p, b, e]), ge = k((y) => {
2656
2710
  if (y.key === "Escape" && U) {
2657
- y.preventDefault(), u(!0);
2711
+ y.preventDefault(), m(!0);
2658
2712
  return;
2659
2713
  }
2660
2714
  if (U) {
2661
2715
  if (y.key === "ArrowDown")
2662
- y.preventDefault(), x(We(F + 1, N.length));
2716
+ y.preventDefault(), x(Ye(F + 1, O.length));
2663
2717
  else if (y.key === "ArrowUp")
2664
- y.preventDefault(), x(We(F - 1, N.length));
2718
+ y.preventDefault(), x(Ye(F - 1, O.length));
2665
2719
  else if (y.key === "Tab") {
2666
2720
  y.preventDefault();
2667
- const j = N[F];
2721
+ const j = O[F];
2668
2722
  j && T(j);
2669
2723
  } else if (y.key === "Enter") {
2670
2724
  y.preventDefault();
2671
- const j = N[F];
2725
+ const j = O[F];
2672
2726
  j && T(j);
2673
2727
  }
2674
2728
  }
2675
- }, [U, N, F, T, x]);
2676
- D(() => {
2729
+ }, [U, O, F, T, x]);
2730
+ N(() => {
2677
2731
  const y = () => {
2678
2732
  document.hidden || !document.hasFocus() || (h.current?.focus(), h.current?.scrollIntoView({ block: "nearest" }));
2679
2733
  };
2680
2734
  return window.addEventListener("watchparty:focus-chat-input", y), () => window.removeEventListener("watchparty:focus-chat-input", y);
2681
2735
  }, []);
2682
- const ye = Ht - t.length, yt = ye <= 100, bt = U ? N[F] : void 0;
2683
- return /* @__PURE__ */ _(
2736
+ const ye = Vt - t.length, _t = ye <= 100, xt = U ? O[F] : void 0;
2737
+ return /* @__PURE__ */ v(
2684
2738
  "form",
2685
2739
  {
2686
2740
  onSubmit: (y) => {
@@ -2691,23 +2745,23 @@ function ti({ commands: e = gt }) {
2691
2745
  onDragOver: p.onDragOver,
2692
2746
  className: "p-2 border-t border-border",
2693
2747
  children: [
2694
- /* @__PURE__ */ c(Za, { pending: p.pending, uploading: p.uploading, onRemove: p.remove }),
2695
- /* @__PURE__ */ _("div", { className: "relative", children: [
2748
+ /* @__PURE__ */ c(mi, { pending: p.pending, uploading: p.uploading, onRemove: p.remove }),
2749
+ /* @__PURE__ */ v("div", { className: "relative", children: [
2696
2750
  U && /* @__PURE__ */ c(
2697
- Ja,
2751
+ ui,
2698
2752
  {
2699
- commands: N,
2753
+ commands: O,
2700
2754
  activeIndex: F,
2701
2755
  hasMedia: g,
2702
2756
  onPick: T,
2703
2757
  onHover: x,
2704
- listboxId: f
2758
+ listboxId: u
2705
2759
  }
2706
2760
  ),
2707
2761
  /* @__PURE__ */ c(
2708
- zr,
2762
+ no,
2709
2763
  {
2710
- open: O,
2764
+ open: D,
2711
2765
  onClose: () => M(!1),
2712
2766
  onPick: p.addMeme,
2713
2767
  onUnavailable: () => {
@@ -2715,8 +2769,8 @@ function ti({ commands: e = gt }) {
2715
2769
  }
2716
2770
  }
2717
2771
  ),
2718
- /* @__PURE__ */ _("div", { className: "flex items-center gap-1.5", children: [
2719
- /* @__PURE__ */ _("div", { className: "relative flex-1", children: [
2772
+ /* @__PURE__ */ v("div", { className: "flex items-center gap-1.5", children: [
2773
+ /* @__PURE__ */ v("div", { className: "relative flex-1", children: [
2720
2774
  /* @__PURE__ */ c(
2721
2775
  "input",
2722
2776
  {
@@ -2724,20 +2778,20 @@ function ti({ commands: e = gt }) {
2724
2778
  type: "text",
2725
2779
  value: t,
2726
2780
  onChange: (y) => {
2727
- n(y.target.value), u(!1);
2781
+ n(y.target.value), m(!1);
2728
2782
  },
2729
2783
  onKeyDown: ge,
2730
- maxLength: Ht,
2784
+ maxLength: Vt,
2731
2785
  placeholder: "Send a message",
2732
2786
  role: "combobox",
2733
2787
  "aria-expanded": U,
2734
- "aria-controls": U ? f : void 0,
2735
- "aria-activedescendant": bt ? `${f}-opt-${bt.name}` : void 0,
2788
+ "aria-controls": U ? u : void 0,
2789
+ "aria-activedescendant": xt ? `${u}-opt-${xt.name}` : void 0,
2736
2790
  "aria-autocomplete": "list",
2737
- className: `w-full bg-bg-card border border-border-light rounded px-3 py-1.5 text-sm focus:outline-none focus:border-text-muted ${yt ? "pr-12" : ""}`
2791
+ className: `w-full bg-bg-card border border-border-light rounded px-3 py-1.5 text-sm focus:outline-none focus:border-text-muted ${_t ? "pr-12" : ""}`
2738
2792
  }
2739
2793
  ),
2740
- /* @__PURE__ */ c("span", { className: `absolute right-2 top-1/2 -translate-y-1/2 text-[10px] ${ye <= 50 ? ye <= 0 ? "bg-danger-bg text-on-danger-bg px-1 rounded" : "bg-primary-bg text-on-primary-bg px-1 rounded" : "text-text-muted"}`, children: yt && ye })
2794
+ /* @__PURE__ */ c("span", { className: `absolute right-2 top-1/2 -translate-y-1/2 text-[10px] ${ye <= 50 ? ye <= 0 ? "bg-danger-bg text-on-danger-bg px-1 rounded" : "bg-primary-bg text-on-primary-bg px-1 rounded" : "text-text-muted"}`, children: _t && ye })
2741
2795
  ] }),
2742
2796
  !L && /* @__PURE__ */ c(
2743
2797
  "button",
@@ -2745,11 +2799,11 @@ function ti({ commands: e = gt }) {
2745
2799
  type: "button",
2746
2800
  onClick: () => M((y) => !y),
2747
2801
  "aria-label": "Add a meme",
2748
- "aria-expanded": O,
2802
+ "aria-expanded": D,
2749
2803
  title: "Add a meme",
2750
2804
  "data-testid": "meme-button",
2751
- className: `shrink-0 rounded border border-border-light px-2 py-1.5 text-sm hover:border-primary ${O ? "text-text border-primary" : "text-text-secondary"}`,
2752
- children: /* @__PURE__ */ c(Ln, { name: "image" })
2805
+ className: `shrink-0 rounded border border-border-light px-2 py-1.5 text-sm hover:border-primary ${D ? "text-text border-primary" : "text-text-secondary"}`,
2806
+ children: /* @__PURE__ */ c(Un, { name: "image" })
2753
2807
  }
2754
2808
  )
2755
2809
  ] })
@@ -2758,15 +2812,15 @@ function ti({ commands: e = gt }) {
2758
2812
  }
2759
2813
  );
2760
2814
  }
2761
- function ni() {
2762
- const e = m((n) => n.roster), t = Object.values(e);
2763
- return t.length ? /* @__PURE__ */ c("div", { className: "flex flex-col gap-1", children: t.map((n) => /* @__PURE__ */ c(ri, { u: n }, n.clientId)) }) : /* @__PURE__ */ c("div", { className: "text-xs text-text-muted", children: "No users online" });
2815
+ function gi() {
2816
+ const e = f((n) => n.roster), t = Object.values(e);
2817
+ return t.length ? /* @__PURE__ */ c("div", { className: "flex flex-col gap-1", children: t.map((n) => /* @__PURE__ */ c(yi, { u: n }, n.clientId)) }) : /* @__PURE__ */ c("div", { className: "text-xs text-text-muted", children: "No users online" });
2764
2818
  }
2765
- function ri({ u: e }) {
2766
- const t = Pn(e.sprite, e.avatarUrl);
2767
- return /* @__PURE__ */ _("div", { className: "flex items-center gap-2 py-0.5", children: [
2819
+ function yi({ u: e }) {
2820
+ const t = On(e.sprite, e.avatarUrl);
2821
+ return /* @__PURE__ */ v("div", { className: "flex items-center gap-2 py-0.5", children: [
2768
2822
  /* @__PURE__ */ c(
2769
- Nn,
2823
+ Dn,
2770
2824
  {
2771
2825
  sprite: e.sprite,
2772
2826
  url: e.avatarUrl,
@@ -2779,16 +2833,16 @@ function ri({ u: e }) {
2779
2833
  e.isLeader && /* @__PURE__ */ c("span", { className: "ml-auto px-1.5 py-0.5 rounded text-[9px] font-medium bg-success/20 text-success", children: "Leader" })
2780
2834
  ] });
2781
2835
  }
2782
- function oi() {
2783
- const e = m((a) => Object.keys(a.roster).length), [t, n] = R(!1), r = z(null);
2784
- return D(() => {
2836
+ function bi() {
2837
+ const e = f((a) => Object.keys(a.roster).length), [t, n] = R(!1), r = K(null);
2838
+ return N(() => {
2785
2839
  if (!t) return;
2786
2840
  function a(i) {
2787
2841
  r.current && !r.current.contains(i.target) && n(!1);
2788
2842
  }
2789
2843
  return document.addEventListener("mousedown", a), () => document.removeEventListener("mousedown", a);
2790
- }, [t]), /* @__PURE__ */ _("div", { className: "relative", ref: r, children: [
2791
- /* @__PURE__ */ _(
2844
+ }, [t]), /* @__PURE__ */ v("div", { className: "relative", ref: r, children: [
2845
+ /* @__PURE__ */ v(
2792
2846
  "button",
2793
2847
  {
2794
2848
  onClick: () => {
@@ -2802,57 +2856,57 @@ function oi() {
2802
2856
  ]
2803
2857
  }
2804
2858
  ),
2805
- t && /* @__PURE__ */ _("div", { className: "absolute top-full right-0 mt-1 bg-bg-card rounded-lg shadow-xl p-3 max-h-64 overflow-y-auto z-50 w-max min-w-[180px] max-w-[220px]", children: [
2806
- /* @__PURE__ */ _("div", { className: "text-[10px] uppercase tracking-wide text-text-muted mb-2", children: [
2859
+ t && /* @__PURE__ */ v("div", { className: "absolute top-full right-0 mt-1 bg-bg-card rounded-lg shadow-xl p-3 max-h-64 overflow-y-auto z-50 w-max min-w-[180px] max-w-[220px]", children: [
2860
+ /* @__PURE__ */ v("div", { className: "text-[10px] uppercase tracking-wide text-text-muted mb-2", children: [
2807
2861
  e,
2808
2862
  " online"
2809
2863
  ] }),
2810
- /* @__PURE__ */ c(ni, {})
2864
+ /* @__PURE__ */ c(gi, {})
2811
2865
  ] })
2812
2866
  ] });
2813
2867
  }
2814
- function $t({ className: e = "fixed bottom-4 left-1/2 -translate-x-1/2" }) {
2815
- const t = m((r) => r.toasts), n = m((r) => r.popToast);
2816
- return D(() => {
2868
+ function Kt({ className: e = "fixed bottom-4 left-1/2 -translate-x-1/2" }) {
2869
+ const t = f((r) => r.toasts), n = f((r) => r.popToast);
2870
+ return N(() => {
2817
2871
  const r = t.map((a) => setTimeout(() => n(a.id), 4e3));
2818
2872
  return () => {
2819
2873
  r.forEach(clearTimeout);
2820
2874
  };
2821
2875
  }, [t, n]), /* @__PURE__ */ c("div", { className: `${e} flex flex-col gap-2 z-50`, children: t.map((r) => /* @__PURE__ */ c("div", { className: `px-3 py-2 rounded text-sm shadow font-medium border ${r.kind === "error" ? "bg-danger-bg text-on-danger-bg border-danger" : "bg-bg-card border-border-light text-text"}`, children: r.msg }, r.id)) });
2822
2876
  }
2823
- const Bt = (e) => typeof e == "string" && jn.includes(e);
2824
- function ai(e, t, n) {
2825
- return e || (Bt(t) ? t : Bt(n) ? n : "dark");
2877
+ const Wt = (e) => typeof e == "string" && Fn.includes(e);
2878
+ function vi(e, t, n) {
2879
+ return e || (Wt(t) ? t : Wt(n) ? n : "dark");
2826
2880
  }
2827
- function ii(e, t) {
2881
+ function Si(e, t) {
2828
2882
  if (t(e.clientWidth), typeof ResizeObserver > "u") return () => {
2829
2883
  };
2830
2884
  const n = new ResizeObserver(() => t(e.clientWidth));
2831
2885
  return n.observe(e), () => n.disconnect();
2832
2886
  }
2833
- function si(e) {
2887
+ function wi(e) {
2834
2888
  const t = e?.trim() ?? "";
2835
2889
  return t ? { source: "host", name: t } : { source: "auto" };
2836
2890
  }
2837
- function li(e) {
2891
+ function _i(e) {
2838
2892
  if (e.source !== "host") return;
2839
- const { setSessionIdentity: t, sprite: n } = m.getState();
2893
+ const { setSessionIdentity: t, sprite: n } = f.getState();
2840
2894
  t(e.name, n);
2841
2895
  }
2842
- function ci({ className: e = "w-4 h-4" }) {
2843
- return /* @__PURE__ */ _("svg", { className: e, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
2896
+ function xi({ className: e = "w-4 h-4" }) {
2897
+ return /* @__PURE__ */ v("svg", { className: e, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
2844
2898
  /* @__PURE__ */ c("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 4v16" }),
2845
2899
  /* @__PURE__ */ c("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12l-5 4v-8l5 4z" })
2846
2900
  ] });
2847
2901
  }
2848
- function di({ className: e = "w-4 h-4" }) {
2849
- return /* @__PURE__ */ _("svg", { className: e, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
2902
+ function Ii({ className: e = "w-4 h-4" }) {
2903
+ return /* @__PURE__ */ v("svg", { className: e, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
2850
2904
  /* @__PURE__ */ c("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M20 4v16" }),
2851
2905
  /* @__PURE__ */ c("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l5 4v-8l-5 4z" })
2852
2906
  ] });
2853
2907
  }
2854
- const ui = 1500;
2855
- function Ci({
2908
+ const Ci = 1500;
2909
+ function Hi({
2856
2910
  roomKey: e,
2857
2911
  serverOrigin: t,
2858
2912
  userType: n,
@@ -2861,52 +2915,52 @@ function Ci({
2861
2915
  name: i,
2862
2916
  onLeave: s,
2863
2917
  onLayoutChange: l,
2864
- collapsible: u = !0,
2918
+ collapsible: m = !0,
2865
2919
  debug: h,
2866
- children: f
2920
+ children: u
2867
2921
  }) {
2868
- const [O, M] = R(null), { setFrame: L, ...C } = mi(l, u), p = Vt(() => i), v = Q(() => (So({ userType: n, userId: r ?? null }), mt().theme), [n, r]), b = Un(), I = b?.theme, g = Q(
2869
- () => ai(a, I, v),
2870
- [a, I, v]
2922
+ const [D, M] = R(null), { setFrame: L, ...C } = Ti(l, m), p = Yt(() => i), S = J(() => (ko({ userType: n, userId: r ?? null }), gt().theme), [n, r]), b = Hn(), I = b?.theme, g = J(
2923
+ () => vi(a, I, S),
2924
+ [a, I, S]
2871
2925
  );
2872
- D(() => {
2926
+ N(() => {
2873
2927
  }, [a, b !== null]);
2874
- const N = Q(
2875
- () => ({ ...st, serverOrigin: t, defaultRoomKey: e }),
2928
+ const O = J(
2929
+ () => ({ ...ut, serverOrigin: t, defaultRoomKey: e }),
2876
2930
  [t, e]
2877
2931
  );
2878
- return D(() => {
2879
- h && no();
2880
- }, [h]), Ca(), D(() => {
2881
- Xr({ serverOrigin: t, defaultRoomKey: e }), m.getState().rehydrateFromPrefs(), Zo();
2932
+ return N(() => {
2933
+ h && co();
2934
+ }, [h]), Ua(), N(() => {
2935
+ ro({ serverOrigin: t, defaultRoomKey: e }), f.getState().rehydrateFromPrefs(), da();
2882
2936
  let U = !1;
2883
- const F = xo();
2937
+ const F = Eo();
2884
2938
  return (async () => {
2885
2939
  try {
2886
2940
  await Promise.race([
2887
2941
  Promise.all([
2888
2942
  F,
2889
- ko().then((T) => {
2890
- T && m.getState().rehydrateFromPrefs();
2943
+ Lo().then((T) => {
2944
+ T && f.getState().rehydrateFromPrefs();
2891
2945
  }),
2892
2946
  // The character chosen in the settings popout (lib/avatar.ts).
2893
- Bo().then(kn)
2947
+ ea().then(Rn)
2894
2948
  ]),
2895
- new Promise((T) => setTimeout(T, ui))
2949
+ new Promise((T) => setTimeout(T, Ci))
2896
2950
  ]);
2897
2951
  } catch (T) {
2898
2952
  A("room-chrome", "pre-join wait threw, proceeding anyway", pe(T));
2899
2953
  }
2900
2954
  if (U) return;
2901
- const x = si(p());
2902
- m.getState().ensureAutoIdentity(), li(x);
2903
- const P = m.getState();
2904
- d("room-chrome", "Joining room", { roomKey: e, name: P.name, sprite: P.sprite }), la({ room_key: e, name: P.name || void 0, sprite: P.sprite || void 0 });
2955
+ const x = wi(p());
2956
+ f.getState().ensureAutoIdentity(), _i(x);
2957
+ const P = f.getState();
2958
+ d("room-chrome", "Joining room", { roomKey: e, name: P.name, sprite: P.sprite }), Sa({ room_key: e, name: P.name || void 0, sprite: P.sprite || void 0 });
2905
2959
  })(), () => {
2906
- U = !0, Ft();
2960
+ U = !0, qt();
2907
2961
  };
2908
- }, [e, t, n, r]), /* @__PURE__ */ c(Jr.Provider, { value: N, children: /* @__PURE__ */ c(fn.Provider, { value: O, children: /* @__PURE__ */ _("div", { ref: L, className: "wp-room-chrome-frame", children: [
2909
- /* @__PURE__ */ c("div", { className: "wp-room-chrome-frame__content", children: f }),
2962
+ }, [e, t, n, r]), /* @__PURE__ */ c(oo.Provider, { value: O, children: /* @__PURE__ */ c(bt.Provider, { value: !1, children: /* @__PURE__ */ c(gn.Provider, { value: D, children: /* @__PURE__ */ v("div", { ref: L, className: "wp-room-chrome-frame", children: [
2963
+ /* @__PURE__ */ c("div", { className: "wp-room-chrome-frame__content", children: u }),
2910
2964
  /* @__PURE__ */ c(
2911
2965
  "aside",
2912
2966
  {
@@ -2915,7 +2969,7 @@ function Ci({
2915
2969
  "data-theme": g,
2916
2970
  "data-collapsed": C.collapsed ? "1" : "0",
2917
2971
  style: { "--wp-room-chrome-width": `${C.state.width}px` },
2918
- children: C.collapsed ? /* @__PURE__ */ _(ce, { children: [
2972
+ children: C.collapsed ? /* @__PURE__ */ v(ce, { children: [
2919
2973
  /* @__PURE__ */ c(
2920
2974
  "button",
2921
2975
  {
@@ -2924,19 +2978,19 @@ function Ci({
2924
2978
  title: "Show chat",
2925
2979
  "aria-label": "Show chat",
2926
2980
  "aria-expanded": !1,
2927
- children: /* @__PURE__ */ c(di, {})
2981
+ children: /* @__PURE__ */ c(Ii, {})
2928
2982
  }
2929
2983
  ),
2930
- /* @__PURE__ */ c($t, { className: "absolute bottom-2 right-full mr-2 w-72" })
2931
- ] }) : /* @__PURE__ */ _(ce, { children: [
2984
+ /* @__PURE__ */ c(Kt, { className: "absolute bottom-2 right-full mr-2 w-72" })
2985
+ ] }) : /* @__PURE__ */ v(ce, { children: [
2932
2986
  /* @__PURE__ */ c(
2933
2987
  "div",
2934
2988
  {
2935
2989
  role: "separator",
2936
2990
  "aria-orientation": "vertical",
2937
2991
  "aria-label": "Resize chat",
2938
- "aria-valuemin": Me,
2939
- "aria-valuemax": ft,
2992
+ "aria-valuemin": Le,
2993
+ "aria-valuemax": yt,
2940
2994
  "aria-valuenow": C.state.width,
2941
2995
  tabIndex: 0,
2942
2996
  className: "wp-room-chrome__resize",
@@ -2948,14 +3002,14 @@ function Ci({
2948
3002
  onKeyDown: C.onKeyDown
2949
3003
  }
2950
3004
  ),
2951
- /* @__PURE__ */ _("div", { className: "flex items-center gap-1 px-2 py-1.5 border-b border-border", children: [
2952
- /* @__PURE__ */ c(oi, {}),
3005
+ /* @__PURE__ */ v("div", { className: "flex items-center gap-1 px-2 py-1.5 border-b border-border", children: [
3006
+ /* @__PURE__ */ c(bi, {}),
2953
3007
  /* @__PURE__ */ c("div", { className: "flex-1" }),
2954
3008
  s && /* @__PURE__ */ c(
2955
3009
  "button",
2956
3010
  {
2957
3011
  onClick: () => {
2958
- Ft(), s();
3012
+ qt(), s();
2959
3013
  },
2960
3014
  className: "wp-room-chrome__leave",
2961
3015
  title: "Leave room",
@@ -2963,7 +3017,7 @@ function Ci({
2963
3017
  children: "Leave"
2964
3018
  }
2965
3019
  ),
2966
- u && /* @__PURE__ */ c(
3020
+ m && /* @__PURE__ */ c(
2967
3021
  "button",
2968
3022
  {
2969
3023
  onClick: C.toggleCollapsed,
@@ -2971,51 +3025,51 @@ function Ci({
2971
3025
  title: "Hide chat",
2972
3026
  "aria-label": "Hide chat",
2973
3027
  "aria-expanded": !0,
2974
- children: /* @__PURE__ */ c(ci, {})
3028
+ children: /* @__PURE__ */ c(xi, {})
2975
3029
  }
2976
3030
  )
2977
3031
  ] }),
2978
- /* @__PURE__ */ c(Va, {}),
2979
- /* @__PURE__ */ c(ti, { commands: [] }),
2980
- /* @__PURE__ */ c($t, { className: "absolute bottom-14 left-2 right-2" })
3032
+ /* @__PURE__ */ c(ai, {}),
3033
+ /* @__PURE__ */ c(hi, { commands: [] }),
3034
+ /* @__PURE__ */ c(Kt, { className: "absolute bottom-14 left-2 right-2" })
2981
3035
  ] })
2982
3036
  }
2983
3037
  )
2984
- ] }) }) });
3038
+ ] }) }) }) });
2985
3039
  }
2986
- function mi(e, t) {
2987
- const n = m((g) => g.chromeChatCollapsed) && t, r = m((g) => g.chromeChatWidth), a = m((g) => g.toggleChromeChatCollapsed), i = m((g) => g.setChromeChatWidth), [s, l] = R(null), [u, h] = R(void 0), [f, O] = R(null);
2988
- D(() => {
3040
+ function Ti(e, t) {
3041
+ const n = f((g) => g.chromeChatCollapsed) && t, r = f((g) => g.chromeChatWidth), a = f((g) => g.toggleChromeChatCollapsed), i = f((g) => g.setChromeChatWidth), [s, l] = R(null), [m, h] = R(void 0), [u, D] = R(null);
3042
+ N(() => {
2989
3043
  if (s)
2990
- return ii(s, h);
3044
+ return Si(s, h);
2991
3045
  }, [s]);
2992
- const M = V(f?.current ?? r, u), L = Q(() => Oo(n, M), [n, M]), C = Vt((g) => e?.(g));
2993
- return D(() => {
3046
+ const M = V(u?.current ?? r, m), L = J(() => $o(n, M), [n, M]), C = Yt((g) => e?.(g));
3047
+ return N(() => {
2994
3048
  C(L);
2995
3049
  }, [L]), {
2996
3050
  setFrame: l,
2997
3051
  collapsed: n,
2998
3052
  state: L,
2999
- dragging: f !== null,
3053
+ dragging: u !== null,
3000
3054
  toggleCollapsed: a,
3001
3055
  onPointerDown: (g) => {
3002
- g.button === 0 && (g.preventDefault(), g.currentTarget.setPointerCapture(g.pointerId), O({ pointerId: g.pointerId, startX: g.clientX, startWidth: M, current: M }));
3056
+ g.button === 0 && (g.preventDefault(), g.currentTarget.setPointerCapture(g.pointerId), D({ pointerId: g.pointerId, startX: g.clientX, startWidth: M, current: M }));
3003
3057
  },
3004
3058
  onPointerMove: (g) => {
3005
- !f || f.pointerId !== g.pointerId || O({ ...f, current: Rt(f.startWidth, f.startX, g.clientX, u) });
3059
+ !u || u.pointerId !== g.pointerId || D({ ...u, current: jt(u.startWidth, u.startX, g.clientX, m) });
3006
3060
  },
3007
3061
  onPointerEnd: (g) => {
3008
- if (!f || f.pointerId !== g.pointerId) return;
3009
- const E = Rt(f.startWidth, f.startX, g.clientX, u);
3010
- O(null), E !== r && i(E);
3062
+ if (!u || u.pointerId !== g.pointerId) return;
3063
+ const E = jt(u.startWidth, u.startX, g.clientX, m);
3064
+ D(null), E !== r && i(E);
3011
3065
  },
3012
3066
  onKeyDown: (g) => {
3013
- const E = Do(M, g.key, u);
3067
+ const E = Ho(M, g.key, m);
3014
3068
  E !== null && (g.preventDefault(), E !== r && i(E));
3015
3069
  }
3016
3070
  };
3017
3071
  }
3018
3072
  export {
3019
- Ci as RoomChrome
3073
+ Hi as RoomChrome
3020
3074
  };
3021
3075
  //# sourceMappingURL=room-chrome.js.map