@sensiblestats/widget-react 0.51.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -36,7 +36,7 @@ __export(index_exports, {
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
38
  // src/StatsWidget.tsx
39
- var import_react39 = require("react");
39
+ var import_react40 = require("react");
40
40
  var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
41
41
 
42
42
  // src/kickoff.ts
@@ -1929,7 +1929,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
1929
1929
  }
1930
1930
 
1931
1931
  // src/components/ChatPanel.tsx
1932
- var import_react38 = require("react");
1932
+ var import_react39 = require("react");
1933
1933
 
1934
1934
  // src/components/ChatHeader.tsx
1935
1935
  var import_react11 = require("react");
@@ -4032,7 +4032,7 @@ function TodayPanel({ discovery, ui, monitor }) {
4032
4032
  }
4033
4033
 
4034
4034
  // src/components/GamesPanel.tsx
4035
- var import_react36 = require("react");
4035
+ var import_react37 = require("react");
4036
4036
 
4037
4037
  // src/components/GamesLoginWall.tsx
4038
4038
  var import_jsx_runtime52 = require("react/jsx-runtime");
@@ -4045,14 +4045,36 @@ var import_jsx_runtime53 = require("react/jsx-runtime");
4045
4045
  var GAME_ICONS = {
4046
4046
  "mystery-tiger": "\u{1F42F}",
4047
4047
  "daily-quiz": "\u{1F9E0}",
4048
- "career-path": "\u26BD",
4049
- "beat-the-grid": "\u{1F3AF}",
4050
- "guess-xi": "\u{1F4CB}",
4051
- "head-of-league": "\u{1F3C6}"
4048
+ "career-path": "\u{1F9ED}",
4049
+ "beat-the-grid": "\u{1F532}",
4050
+ "guess-the-xi": "\u{1F4CB}",
4051
+ "higher-or-lower": "\u{1F4C8}",
4052
+ "matchday-predictor": "\u{1F3AF}",
4053
+ "starting-xi": "\u{1F455}",
4054
+ "stat-ladder": "\u{1FA9C}",
4055
+ "fan-motm": "\u2B50"
4056
+ };
4057
+ var GAME_TITLES = {
4058
+ "mystery-tiger": "Mystery Tiger",
4059
+ "daily-quiz": "Daily Quiz",
4060
+ "career-path": "Career Path",
4061
+ "beat-the-grid": "Beat the Grid",
4062
+ "guess-the-xi": "Guess the XI",
4063
+ "higher-or-lower": "Higher or Lower",
4064
+ "matchday-predictor": "Matchday Predictor",
4065
+ "starting-xi": "Starting XI",
4066
+ "stat-ladder": "Stat Ladder",
4067
+ "fan-motm": "Fan MOTM"
4052
4068
  };
4053
4069
  function gameIcon(game) {
4054
4070
  return GAME_ICONS[game.gameId] ?? (game.kind === "fixture" ? "\u{1F4C5}" : "\u{1F3AE}");
4055
4071
  }
4072
+ function prettifyGameId(gameId) {
4073
+ return gameId.split("-").map((w) => w ? w[0].toUpperCase() + w.slice(1) : w).join(" ");
4074
+ }
4075
+ function gameTitle(game) {
4076
+ return game.title ?? GAME_TITLES[game.gameId] ?? prettifyGameId(game.gameId);
4077
+ }
4056
4078
  function formatCountdown(lockAtUtc) {
4057
4079
  const diff = new Date(lockAtUtc).getTime() - Date.now();
4058
4080
  if (diff <= 0) return null;
@@ -4093,7 +4115,7 @@ function GameTile({
4093
4115
  const statusClass = `ss-w-tile-status ss-w-tile-status--${game.status}`;
4094
4116
  const inner = /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
4095
4117
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "ss-w-tile-icon", children: gameIcon(game) }),
4096
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "ss-w-tile-title", children: game.title ?? game.gameId }),
4118
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "ss-w-tile-title", children: gameTitle(game) }),
4097
4119
  countdown !== null ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: statusClass, "data-testid": "tile-countdown", children: countdown }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: statusClass, children: statusLabel }),
4098
4120
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: `ss-w-tile-chip ss-w-tile-chip--${game.ranked ? "skill" : "fun"}`, children: game.ranked ? "Skill" : "For fun" })
4099
4121
  ] });
@@ -4144,7 +4166,7 @@ function GamesHub({
4144
4166
  }
4145
4167
 
4146
4168
  // src/components/GameScreenHost.tsx
4147
- var import_react35 = require("react");
4169
+ var import_react36 = require("react");
4148
4170
 
4149
4171
  // src/useGamePlay.ts
4150
4172
  var import_react28 = require("react");
@@ -4207,6 +4229,89 @@ function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
4207
4229
 
4208
4230
  // src/components/games/MysteryTigerGame.tsx
4209
4231
  var import_react29 = require("react");
4232
+
4233
+ // src/components/games/nationFlags.ts
4234
+ var FLAGS = {
4235
+ england: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}",
4236
+ scotland: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}",
4237
+ wales: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}",
4238
+ "northern ireland": "\u{1F1EC}\u{1F1E7}",
4239
+ "republic of ireland": "\u{1F1EE}\u{1F1EA}",
4240
+ ireland: "\u{1F1EE}\u{1F1EA}",
4241
+ "united kingdom": "\u{1F1EC}\u{1F1E7}",
4242
+ france: "\u{1F1EB}\u{1F1F7}",
4243
+ spain: "\u{1F1EA}\u{1F1F8}",
4244
+ portugal: "\u{1F1F5}\u{1F1F9}",
4245
+ germany: "\u{1F1E9}\u{1F1EA}",
4246
+ italy: "\u{1F1EE}\u{1F1F9}",
4247
+ netherlands: "\u{1F1F3}\u{1F1F1}",
4248
+ belgium: "\u{1F1E7}\u{1F1EA}",
4249
+ switzerland: "\u{1F1E8}\u{1F1ED}",
4250
+ austria: "\u{1F1E6}\u{1F1F9}",
4251
+ denmark: "\u{1F1E9}\u{1F1F0}",
4252
+ sweden: "\u{1F1F8}\u{1F1EA}",
4253
+ norway: "\u{1F1F3}\u{1F1F4}",
4254
+ finland: "\u{1F1EB}\u{1F1EE}",
4255
+ iceland: "\u{1F1EE}\u{1F1F8}",
4256
+ poland: "\u{1F1F5}\u{1F1F1}",
4257
+ czechia: "\u{1F1E8}\u{1F1FF}",
4258
+ "czech republic": "\u{1F1E8}\u{1F1FF}",
4259
+ croatia: "\u{1F1ED}\u{1F1F7}",
4260
+ serbia: "\u{1F1F7}\u{1F1F8}",
4261
+ "bosnia and herzegovina": "\u{1F1E7}\u{1F1E6}",
4262
+ greece: "\u{1F1EC}\u{1F1F7}",
4263
+ romania: "\u{1F1F7}\u{1F1F4}",
4264
+ ukraine: "\u{1F1FA}\u{1F1E6}",
4265
+ russia: "\u{1F1F7}\u{1F1FA}",
4266
+ hungary: "\u{1F1ED}\u{1F1FA}",
4267
+ slovakia: "\u{1F1F8}\u{1F1F0}",
4268
+ slovenia: "\u{1F1F8}\u{1F1EE}",
4269
+ turkey: "\u{1F1F9}\u{1F1F7}",
4270
+ t\u00FCrkiye: "\u{1F1F9}\u{1F1F7}",
4271
+ albania: "\u{1F1E6}\u{1F1F1}",
4272
+ "north macedonia": "\u{1F1F2}\u{1F1F0}",
4273
+ brazil: "\u{1F1E7}\u{1F1F7}",
4274
+ argentina: "\u{1F1E6}\u{1F1F7}",
4275
+ uruguay: "\u{1F1FA}\u{1F1FE}",
4276
+ colombia: "\u{1F1E8}\u{1F1F4}",
4277
+ chile: "\u{1F1E8}\u{1F1F1}",
4278
+ peru: "\u{1F1F5}\u{1F1EA}",
4279
+ ecuador: "\u{1F1EA}\u{1F1E8}",
4280
+ paraguay: "\u{1F1F5}\u{1F1FE}",
4281
+ mexico: "\u{1F1F2}\u{1F1FD}",
4282
+ "united states": "\u{1F1FA}\u{1F1F8}",
4283
+ usa: "\u{1F1FA}\u{1F1F8}",
4284
+ canada: "\u{1F1E8}\u{1F1E6}",
4285
+ jamaica: "\u{1F1EF}\u{1F1F2}",
4286
+ nigeria: "\u{1F1F3}\u{1F1EC}",
4287
+ ghana: "\u{1F1EC}\u{1F1ED}",
4288
+ senegal: "\u{1F1F8}\u{1F1F3}",
4289
+ ivorycoast: "\u{1F1E8}\u{1F1EE}",
4290
+ "cote d'ivoire": "\u{1F1E8}\u{1F1EE}",
4291
+ "ivory coast": "\u{1F1E8}\u{1F1EE}",
4292
+ cameroon: "\u{1F1E8}\u{1F1F2}",
4293
+ egypt: "\u{1F1EA}\u{1F1EC}",
4294
+ morocco: "\u{1F1F2}\u{1F1E6}",
4295
+ algeria: "\u{1F1E9}\u{1F1FF}",
4296
+ tunisia: "\u{1F1F9}\u{1F1F3}",
4297
+ mali: "\u{1F1F2}\u{1F1F1}",
4298
+ "south africa": "\u{1F1FF}\u{1F1E6}",
4299
+ "dr congo": "\u{1F1E8}\u{1F1E9}",
4300
+ japan: "\u{1F1EF}\u{1F1F5}",
4301
+ "south korea": "\u{1F1F0}\u{1F1F7}",
4302
+ korea: "\u{1F1F0}\u{1F1F7}",
4303
+ australia: "\u{1F1E6}\u{1F1FA}",
4304
+ "saudi arabia": "\u{1F1F8}\u{1F1E6}",
4305
+ iran: "\u{1F1EE}\u{1F1F7}",
4306
+ "new zealand": "\u{1F1F3}\u{1F1FF}"
4307
+ };
4308
+ function nationalityFlag(nationality) {
4309
+ if (!nationality) return "\u{1F3F3}\uFE0F";
4310
+ const key = nationality.trim().toLowerCase();
4311
+ return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase();
4312
+ }
4313
+
4314
+ // src/components/games/MysteryTigerGame.tsx
4210
4315
  var import_jsx_runtime55 = require("react/jsx-runtime");
4211
4316
  function parseClientState(json) {
4212
4317
  if (!json) return null;
@@ -4237,6 +4342,15 @@ function verdictGlyph(v) {
4237
4342
  if (v.direction === "down") return "\u2193";
4238
4343
  return "\u2248";
4239
4344
  }
4345
+ function directionArrow(v) {
4346
+ if (v.direction === "up") return "\u25B2";
4347
+ if (v.direction === "down") return "\u25BC";
4348
+ return "";
4349
+ }
4350
+ function tileFace(key, v) {
4351
+ if (!v.value) return verdictGlyph(v);
4352
+ return key === "nationality" ? nationalityFlag(v.value) : v.value;
4353
+ }
4240
4354
  function MysteryTigerGame({
4241
4355
  config,
4242
4356
  result,
@@ -4282,16 +4396,20 @@ function MysteryTigerGame({
4282
4396
  ] }),
4283
4397
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "ss-w-gtrow", children: ATTR_KEYS.map((key) => {
4284
4398
  const v = gr[key];
4399
+ const arrow = directionArrow(v);
4285
4400
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
4286
4401
  "div",
4287
4402
  {
4288
4403
  className: `ss-w-gtile ss-w-gtile--${v.verdict}`,
4289
4404
  "data-testid": `verdict-${key}-${i}`,
4290
4405
  "data-verdict": v.verdict,
4291
- "aria-label": `${ATTR_LABELS[key]}: ${v.verdict}${v.direction ? ` ${v.direction}` : ""}`,
4406
+ "aria-label": `${ATTR_LABELS[key]}: ${v.value ?? v.verdict}${v.direction ? ` ${v.direction}` : ""}`,
4292
4407
  children: [
4293
4408
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-lab", children: ATTR_LABELS[key] }),
4294
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-v", "aria-hidden": "true", children: verdictGlyph(v) })
4409
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "ss-w-gtile-v", "aria-hidden": "true", children: [
4410
+ tileFace(key, v),
4411
+ arrow && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "ss-w-gtile-dir", children: arrow })
4412
+ ] })
4295
4413
  ]
4296
4414
  },
4297
4415
  key
@@ -4805,6 +4923,7 @@ function BeatTheGridGame({
4805
4923
  }
4806
4924
 
4807
4925
  // src/components/games/GuessTheXiGame.tsx
4926
+ var import_react32 = require("react");
4808
4927
  var import_jsx_runtime59 = require("react/jsx-runtime");
4809
4928
  function parseClientState5(json) {
4810
4929
  if (!json) return null;
@@ -4814,6 +4933,16 @@ function parseClientState5(json) {
4814
4933
  return null;
4815
4934
  }
4816
4935
  }
4936
+ function toRows(positions) {
4937
+ const byRow = /* @__PURE__ */ new Map();
4938
+ positions.forEach((p, i) => {
4939
+ const rowKey = Number(p.slot?.split(":")[0]) || i + 1;
4940
+ const bucket = byRow.get(rowKey) ?? [];
4941
+ bucket.push(p);
4942
+ byRow.set(rowKey, bucket);
4943
+ });
4944
+ return [...byRow.keys()].sort((a, b) => a - b).map((k) => byRow.get(k));
4945
+ }
4817
4946
  function RevealCard({ reveal }) {
4818
4947
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-reveal", "data-reveal-type": reveal.type ?? "", children: [
4819
4948
  reveal.slot && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-reveal-slot", children: reveal.slot }),
@@ -4826,51 +4955,90 @@ function GuessTheXiGame({
4826
4955
  submitting,
4827
4956
  onSubmit
4828
4957
  }) {
4958
+ const [query, setQuery] = (0, import_react32.useState)("");
4959
+ const inputId = (0, import_react32.useId)();
4829
4960
  const clientState = parseClientState5(result?.clientStateJson);
4830
4961
  const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
4831
4962
  const solved = clientState?.status === "solved";
4963
+ const guessedTeamIds = new Set(clientState?.guessHistory.map((g) => g.teamId) ?? []);
4964
+ const rows = config ? toRows(config.positions) : [];
4965
+ const filtered = config && !isOver ? config.teamPool.filter(
4966
+ (t) => !guessedTeamIds.has(t.teamId) && t.teamName.toLowerCase().includes(query.toLowerCase())
4967
+ ) : [];
4832
4968
  function handlePick(teamId) {
4833
4969
  if (!config || isOver || submitting) return;
4834
4970
  const prevGuesses = clientState?.guessHistory.map((g) => ({ teamId: g.teamId })) ?? [];
4835
4971
  const newGuesses = [...prevGuesses, { teamId }];
4972
+ setQuery("");
4836
4973
  onSubmit(JSON.stringify({ guesses: newGuesses }));
4837
4974
  }
4975
+ const wrongGuesses = (clientState?.guessHistory ?? []).filter((g) => !g.wasCorrect);
4838
4976
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi", "data-testid": "game-screen-guess-the-xi", children: [
4839
4977
  !config && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
4840
4978
  config && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
4841
4979
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-head", children: [
4842
4980
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { children: [
4843
4981
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-title", children: "Guess the XI" }),
4844
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-sub", children: config.poolLabel })
4982
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-sub", children: [
4983
+ "Which team? \xB7 ",
4984
+ config.poolLabel
4985
+ ] })
4845
4986
  ] }),
4846
4987
  clientState && !isOver && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "ss-w-gxi-left", children: [
4847
- "Guess ",
4848
- clientState.guessesUsed + 1,
4849
- "/6"
4988
+ Math.max(0, 6 - clientState.guessesUsed),
4989
+ " left"
4850
4990
  ] })
4851
4991
  ] }),
4852
- config.positions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-pitch", children: config.positions.map((pos, i) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-pslot", children: [
4853
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-pslot-pos", children: pos.slot }),
4854
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-pslot-nat", children: pos.nationality })
4855
- ] }, `${pos.slot}-${i}`)) }),
4992
+ rows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-pitch", children: rows.map((row, r) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-prow", children: row.map((pos, c) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4993
+ "div",
4994
+ {
4995
+ className: "ss-w-gxi-flag",
4996
+ title: pos.nationality,
4997
+ "aria-label": pos.nationality,
4998
+ children: nationalityFlag(pos.nationality)
4999
+ },
5000
+ `${pos.slot}-${c}`
5001
+ )) }, r)) }),
4856
5002
  clientState && clientState.earnedReveals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-reveals", children: clientState.earnedReveals.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RevealCard, { reveal: r }, i)) }),
4857
- !isOver ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-pool", children: config.teamPool.map((team) => {
4858
- const guessRecord = clientState?.guessHistory.find((g) => g.teamId === team.teamId);
4859
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4860
- "button",
4861
- {
4862
- type: "button",
4863
- className: [
4864
- "ss-w-gxi-team-btn",
4865
- guessRecord ? guessRecord.wasCorrect ? "ss-w-gxi-team-btn--correct" : "ss-w-gxi-team-btn--wrong" : ""
4866
- ].filter(Boolean).join(" "),
4867
- disabled: submitting,
4868
- onClick: () => handlePick(team.teamId),
4869
- children: team.teamName
4870
- },
4871
- team.teamId
4872
- );
4873
- }) }) : clientState && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${solved ? "solved" : "failed"}`, children: [
5003
+ !isOver ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
5004
+ wrongGuesses.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-wrong", children: wrongGuesses.map((g) => {
5005
+ const team = config.teamPool.find((t) => t.teamId === g.teamId);
5006
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "ss-w-gxi-wrong-pill", children: team?.teamName ?? `#${g.teamId}` }, g.teamId);
5007
+ }) }),
5008
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gtta", children: [
5009
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
5010
+ "input",
5011
+ {
5012
+ id: inputId,
5013
+ type: "text",
5014
+ role: "textbox",
5015
+ className: "ss-w-gtta-i",
5016
+ placeholder: "Name the team\u2026",
5017
+ value: query,
5018
+ disabled: submitting || isOver,
5019
+ onChange: (e) => setQuery(e.target.value),
5020
+ autoComplete: "off",
5021
+ "aria-label": "Name the team",
5022
+ "aria-autocomplete": "list"
5023
+ }
5024
+ ),
5025
+ query.length > 0 && filtered.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((t) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
5026
+ "div",
5027
+ {
5028
+ className: "ss-w-gtta-opt",
5029
+ role: "option",
5030
+ "aria-selected": false,
5031
+ onClick: () => handlePick(t.teamId),
5032
+ onKeyDown: (e) => {
5033
+ if (e.key === "Enter") handlePick(t.teamId);
5034
+ },
5035
+ tabIndex: 0,
5036
+ children: t.teamName
5037
+ },
5038
+ t.teamId
5039
+ )) })
5040
+ ] })
5041
+ ] }) : clientState && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${solved ? "solved" : "failed"}`, children: [
4874
5042
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-banner-label", children: solved ? "\u2705 Solved!" : "\u{1F614} Out of guesses" }),
4875
5043
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "ss-w-gxi-banner-score", children: clientState.score }),
4876
5044
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "ss-w-gxi-banner-sub", children: [
@@ -4885,7 +5053,7 @@ function GuessTheXiGame({
4885
5053
  }
4886
5054
 
4887
5055
  // src/components/games/DailyQuizGame.tsx
4888
- var import_react32 = require("react");
5056
+ var import_react33 = require("react");
4889
5057
  var import_jsx_runtime60 = require("react/jsx-runtime");
4890
5058
  function parseClientState6(json) {
4891
5059
  if (!json) return null;
@@ -4904,7 +5072,7 @@ function DailyQuizGame({
4904
5072
  submitting,
4905
5073
  onSubmit
4906
5074
  }) {
4907
- const [selections, setSelections] = (0, import_react32.useState)(/* @__PURE__ */ new Map());
5075
+ const [selections, setSelections] = (0, import_react33.useState)(/* @__PURE__ */ new Map());
4908
5076
  const clientState = parseClientState6(result?.clientStateJson);
4909
5077
  const isRevealed = (clientState?.results.length ?? 0) > 0 || result?.alreadyPlayed === true;
4910
5078
  const allAnswered = config != null && selections.size === config.questions.length;
@@ -4984,7 +5152,7 @@ function DailyQuizGame({
4984
5152
  }
4985
5153
 
4986
5154
  // src/components/games/MatchdayPredictorGame.tsx
4987
- var import_react33 = require("react");
5155
+ var import_react34 = require("react");
4988
5156
  var import_jsx_runtime61 = require("react/jsx-runtime");
4989
5157
  function parseClientState7(json) {
4990
5158
  if (!json) return null;
@@ -5007,9 +5175,9 @@ function MatchdayPredictorGame({
5007
5175
  submitting,
5008
5176
  onSubmit
5009
5177
  }) {
5010
- const [homeScore, setHomeScore] = (0, import_react33.useState)(0);
5011
- const [awayScore, setAwayScore] = (0, import_react33.useState)(0);
5012
- const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react33.useState)(null);
5178
+ const [homeScore, setHomeScore] = (0, import_react34.useState)(0);
5179
+ const [awayScore, setAwayScore] = (0, import_react34.useState)(0);
5180
+ const [firstScorerPlayerId, setFirstScorerPlayerId] = (0, import_react34.useState)(null);
5013
5181
  const clientState = parseClientState7(result?.clientStateJson);
5014
5182
  const alreadyPlayed = result?.alreadyPlayed === true;
5015
5183
  if (alreadyPlayed && clientState) {
@@ -5159,7 +5327,7 @@ function MatchdayPredictorGame({
5159
5327
  }
5160
5328
 
5161
5329
  // src/components/games/StartingXiGame.tsx
5162
- var import_react34 = require("react");
5330
+ var import_react35 = require("react");
5163
5331
  var import_jsx_runtime62 = require("react/jsx-runtime");
5164
5332
  function parseClientState8(json) {
5165
5333
  if (!json) return null;
@@ -5180,7 +5348,7 @@ function StartingXiGame({
5180
5348
  submitting,
5181
5349
  onSubmit
5182
5350
  }) {
5183
- const [picked, setPicked] = (0, import_react34.useState)([]);
5351
+ const [picked, setPicked] = (0, import_react35.useState)([]);
5184
5352
  const clientState = parseClientState8(result?.clientStateJson);
5185
5353
  const alreadyPlayed = result?.alreadyPlayed === true;
5186
5354
  if (alreadyPlayed) {
@@ -5424,8 +5592,8 @@ function GameScreenHost({
5424
5592
  ui
5425
5593
  }) {
5426
5594
  const { gameId, fixtureId, gameDay = "" } = selected;
5427
- const [configJson, setConfigJson] = (0, import_react35.useState)(null);
5428
- (0, import_react35.useEffect)(() => {
5595
+ const [configJson, setConfigJson] = (0, import_react36.useState)(null);
5596
+ (0, import_react36.useEffect)(() => {
5429
5597
  setConfigJson(null);
5430
5598
  if (!conversation) return;
5431
5599
  let cancelled = false;
@@ -5447,12 +5615,12 @@ function GameScreenHost({
5447
5615
  gameDay,
5448
5616
  fixtureId: fixtureId || void 0
5449
5617
  });
5450
- (0, import_react35.useEffect)(() => {
5618
+ (0, import_react36.useEffect)(() => {
5451
5619
  if (conversation) hydrate();
5452
5620
  }, [conversation, gameId]);
5453
- const hydrateRef = (0, import_react35.useRef)(hydrate);
5621
+ const hydrateRef = (0, import_react36.useRef)(hydrate);
5454
5622
  hydrateRef.current = hydrate;
5455
- (0, import_react35.useEffect)(() => {
5623
+ (0, import_react36.useEffect)(() => {
5456
5624
  if (!FIXTURE_GAME_IDS.has(gameId)) return;
5457
5625
  if (rawStatus !== "pending") return;
5458
5626
  const timerId = setInterval(() => {
@@ -5492,15 +5660,17 @@ function GameScreenHost({
5492
5660
  config: safeParseConfig(configJson)
5493
5661
  }
5494
5662
  );
5495
- case "beat-the-grid":
5663
+ case "beat-the-grid": {
5664
+ const btgConfig = safeParseConfig(configJson);
5496
5665
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
5497
5666
  BeatTheGridGame,
5498
5667
  {
5499
5668
  ...sharedProps,
5500
- config: safeParseConfig(configJson),
5501
- playerPool: []
5669
+ config: btgConfig,
5670
+ playerPool: btgConfig?.playerPool ?? []
5502
5671
  }
5503
5672
  );
5673
+ }
5504
5674
  case "guess-the-xi":
5505
5675
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
5506
5676
  GuessTheXiGame,
@@ -5570,7 +5740,7 @@ function GamesPanel({
5570
5740
  ui,
5571
5741
  conversation
5572
5742
  }) {
5573
- const [selected, setSelected] = (0, import_react36.useState)(null);
5743
+ const [selected, setSelected] = (0, import_react37.useState)(null);
5574
5744
  if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(GamesLoginWall, { ui });
5575
5745
  if (selected !== null) {
5576
5746
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
@@ -5594,7 +5764,7 @@ function GamesPanel({
5594
5764
  }
5595
5765
 
5596
5766
  // src/components/Leaderboard.tsx
5597
- var import_react37 = require("react");
5767
+ var import_react38 = require("react");
5598
5768
 
5599
5769
  // src/components/LeaderboardRow.tsx
5600
5770
  var import_jsx_runtime67 = require("react/jsx-runtime");
@@ -5679,7 +5849,7 @@ function Leaderboard({
5679
5849
  ui,
5680
5850
  onPlay
5681
5851
  }) {
5682
- const [segment, setSegment] = (0, import_react37.useState)("weekly");
5852
+ const [segment, setSegment] = (0, import_react38.useState)("weekly");
5683
5853
  const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
5684
5854
  const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
5685
5855
  const isEmpty = segment === "weekly" ? data.weeklyTop.length === 0 : data.allTimeTop.length === 0;
@@ -5762,8 +5932,8 @@ function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }) {
5762
5932
  var import_jsx_runtime71 = require("react/jsx-runtime");
5763
5933
  var FULLSCREEN_QUERY = "(max-width: 639px)";
5764
5934
  function useIsModal() {
5765
- const [modal, setModal] = (0, import_react38.useState)(false);
5766
- (0, import_react38.useEffect)(() => {
5935
+ const [modal, setModal] = (0, import_react39.useState)(false);
5936
+ (0, import_react39.useEffect)(() => {
5767
5937
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
5768
5938
  const mql = window.matchMedia(FULLSCREEN_QUERY);
5769
5939
  const sync = () => setModal(mql.matches);
@@ -5776,7 +5946,7 @@ function useIsModal() {
5776
5946
  function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }) {
5777
5947
  const { state, close, stop, send, reset } = controller;
5778
5948
  const isModal = useIsModal();
5779
- (0, import_react38.useEffect)(() => {
5949
+ (0, import_react39.useEffect)(() => {
5780
5950
  const onKey = (e) => {
5781
5951
  if (e.key === "Escape") close();
5782
5952
  };
@@ -5787,7 +5957,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5787
5957
  monitor?.setActiveTab("chat");
5788
5958
  send(text);
5789
5959
  };
5790
- (0, import_react38.useEffect)(() => {
5960
+ (0, import_react39.useEffect)(() => {
5791
5961
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
5792
5962
  }, [monitor, state.isStreaming, state.messages.length]);
5793
5963
  return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
@@ -5837,7 +6007,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5837
6007
  ui
5838
6008
  }
5839
6009
  ),
5840
- /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
6010
+ (!monitor || monitor.activeTab !== "games" && monitor.activeTab !== "leaderboard") && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
5841
6011
  ] });
5842
6012
  }
5843
6013
 
@@ -6829,7 +6999,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6829
6999
  /* Verdict tiles: label on top, verdict glyph below */
6830
7000
  .ss-w-gtile { display: flex; flex-direction: column; align-items: center; justify-content: center; aspect-ratio: 1; border-radius: 8px; gap: 2px; min-width: 0; }
6831
7001
  .ss-w-gtile-lab { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; opacity: .75; }
6832
- .ss-w-gtile-v { font-size: 15px; font-weight: 800; line-height: 1; }
7002
+ .ss-w-gtile-v { display: inline-flex; align-items: center; gap: 1px; font-size: 13px; font-weight: 800; line-height: 1; max-width: 100%; padding: 0 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
7003
+ .ss-w-gtile-dir { font-size: 9px; line-height: 1; }
6833
7004
  .ss-w-gtile--exact { background: var(--ss-w-correct); color: #062611; }
6834
7005
  .ss-w-gtile--near { background: var(--ss-w-accent); color: #241700; }
6835
7006
  .ss-w-gtile--miss { background: var(--ss-w-bubble); color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); }
@@ -6864,9 +7035,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6864
7035
  .ss-w-hlbtns { display: flex; flex-direction: column; gap: 6px; justify-content: center; }
6865
7036
  .ss-w-hl-or { text-align: center; font-size: 11px; font-weight: 700; color: var(--ss-w-faint); }
6866
7037
  .ss-w-hlbtn { font: inherit; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; border-radius: 9px; padding: 10px 12px; cursor: pointer; border: 1px solid var(--ss-w-line); white-space: nowrap; transition: border-color .1s, background .1s; }
6867
- .ss-w-hlbtn--up { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); color: var(--ss-w-accent); border-color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-w-line)); }
6868
- .ss-w-hlbtn--dn { background: var(--ss-w-panel); color: var(--ss-w-ink); }
6869
- .ss-w-hlbtn:hover:not(:disabled) { border-color: var(--ss-w-accent); }
7038
+ /* Both options are neutral until picked \u2014 an amber default read as "already selected". */
7039
+ .ss-w-hlbtn--up, .ss-w-hlbtn--dn { background: var(--ss-w-panel); color: var(--ss-w-ink); }
7040
+ .ss-w-hlbtn:hover:not(:disabled) { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); color: var(--ss-w-accent); }
6870
7041
  .ss-w-hlbtn:disabled { opacity: .5; cursor: not-allowed; }
6871
7042
  /* Run-over terminal panel */
6872
7043
  .ss-w-hl-over { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 16px; text-align: center; display: flex; flex-direction: column; gap: 5px; }
@@ -6893,18 +7064,18 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6893
7064
  .ss-w-cpath-sub { font-size: 11px; color: var(--ss-w-faint); margin-top: 4px; }
6894
7065
  .ss-w-cpath-left { margin-left: auto; flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 11%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, var(--ss-w-line)); border-radius: 999px; padding: 4px 10px; white-space: nowrap; }
6895
7066
  /* Career sequence \u2014 horizontal crests with arrows */
6896
- .ss-w-cpath-seq { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 13px 11px; }
6897
- .ss-w-cpath-arrow { align-self: center; color: var(--ss-w-faint); font-size: 13px; padding-top: 10px; }
7067
+ .ss-w-cpath-seq { display: flex; flex-wrap: nowrap; align-items: flex-start; gap: 4px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 13px 11px; overflow-x: auto; overscroll-behavior-x: contain; }
7068
+ .ss-w-cpath-arrow { align-self: center; flex: none; color: var(--ss-w-faint); font-size: 13px; padding-top: 10px; }
6898
7069
  /* Single club \u2014 small vertical card */
6899
- .ss-w-cpath-club { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 58px; }
7070
+ .ss-w-cpath-club { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 56px; flex: none; }
6900
7071
  .ss-w-cpath-crest { width: 34px; height: 34px; object-fit: contain; flex: none; border-radius: 8px; }
6901
7072
  .ss-w-cpath-crest--fallback { background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); display: grid; place-items: center; font-size: 9px; font-weight: 800; letter-spacing: .02em; color: var(--ss-w-faint); }
6902
- .ss-w-cpath-club-name { font-size: 9px; font-weight: 600; color: var(--ss-w-ink); text-align: center; line-height: 1.1; overflow-wrap: anywhere; }
7073
+ .ss-w-cpath-club-name { font-size: 9px; font-weight: 600; color: var(--ss-w-ink); text-align: center; line-height: 1.15; max-width: 56px; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
6903
7074
  .ss-w-cpath-spell-yr { font-size: 8px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; }
6904
7075
  .ss-w-cpath-loan-badge { font-size: 7.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 0 5px; border-radius: 999px; background: color-mix(in srgb, var(--ss-w-accent) 15%, var(--ss-w-panel)); color: var(--ss-w-accent); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }
6905
7076
  .ss-w-cpath-club--loan .ss-w-cpath-crest { border: 1px dashed color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-w-line)); }
6906
7077
  /* Hidden clubs chip */
6907
- .ss-w-cpath-hidden { align-self: center; font-size: 9px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px dashed var(--ss-w-line); border-radius: 8px; padding: 6px 8px; }
7078
+ .ss-w-cpath-hidden { align-self: center; flex: none; white-space: nowrap; font-size: 9px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px dashed var(--ss-w-line); border-radius: 8px; padding: 6px 8px; }
6908
7079
  /* Hint line */
6909
7080
  .ss-w-cpath-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; padding: 6px 10px; border-radius: 10px; background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); border: 1px dashed color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }
6910
7081
  /* Terminal outcome */
@@ -6968,23 +7139,18 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6968
7139
  .ss-w-gxi-title { font-size: 18px; font-weight: 800; text-transform: uppercase; letter-spacing: .02em; color: var(--ss-w-ink); line-height: 1; }
6969
7140
  .ss-w-gxi-sub { font-size: 11px; color: var(--ss-w-faint); margin-top: 4px; }
6970
7141
  .ss-w-gxi-left { margin-left: auto; flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 11%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, var(--ss-w-line)); border-radius: 999px; padding: 4px 10px; white-space: nowrap; }
6971
- /* Positions pitch: compact slot grid */
6972
- .ss-w-gxi-pitch { display: flex; flex-wrap: wrap; gap: 5px; }
6973
- .ss-w-gxi-pslot { display: flex; flex-direction: column; align-items: center; gap: 2px; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 10px; min-width: 52px; }
6974
- .ss-w-gxi-pslot-pos { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-accent); }
6975
- .ss-w-gxi-pslot-nat { font-size: 10px; color: var(--ss-w-faint); font-weight: 500; text-align: center; line-height: 1.2; }
7142
+ /* Pitch: a flag per slot laid out in formation rows on a green field */
7143
+ .ss-w-gxi-pitch { display: flex; flex-direction: column; justify-content: space-between; gap: 10px; padding: 16px 10px; border-radius: 14px; border: 1px solid color-mix(in srgb, var(--ss-w-correct) 22%, var(--ss-w-line)); background: linear-gradient(180deg, color-mix(in srgb, var(--ss-w-correct) 10%, var(--ss-w-panel)), color-mix(in srgb, var(--ss-w-correct) 4%, var(--ss-w-panel))); }
7144
+ .ss-w-gxi-prow { display: flex; justify-content: space-around; align-items: center; gap: 8px; }
7145
+ .ss-w-gxi-flag { width: 34px; height: 34px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 19px; line-height: 1; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); box-shadow: 0 1px 3px rgba(0,0,0,.14); overflow: hidden; }
7146
+ /* Wrong-guess trail */
7147
+ .ss-w-gxi-wrong { display: flex; flex-wrap: wrap; gap: 6px; }
7148
+ .ss-w-gxi-wrong-pill { font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: color-mix(in srgb, var(--ss-w-wrong) 10%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); text-decoration: line-through; }
6976
7149
  /* Earned reveals */
6977
7150
  .ss-w-gxi-reveals { display: flex; flex-direction: column; gap: 4px; }
6978
7151
  .ss-w-gxi-reveal { display: flex; align-items: center; gap: 6px; padding: 7px 10px; background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 22%, var(--ss-w-line)); border-radius: 8px; }
6979
7152
  .ss-w-gxi-reveal-slot { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-cta-ink, #1b1300); background: var(--ss-w-cta); border-radius: 6px; padding: 1px 6px; flex: none; }
6980
7153
  .ss-w-gxi-reveal-val { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
6981
- /* Team pool: responsive flex grid of buttons */
6982
- .ss-w-gxi-pool { display: flex; flex-wrap: wrap; gap: 6px; }
6983
- .ss-w-gxi-team-btn { font: inherit; font-size: 12.5px; font-weight: 650; border-radius: 10px; padding: 9px 14px; cursor: pointer; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); transition: background .1s, border-color .1s; }
6984
- .ss-w-gxi-team-btn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
6985
- .ss-w-gxi-team-btn:disabled { opacity: .5; cursor: not-allowed; }
6986
- .ss-w-gxi-team-btn--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); color: var(--ss-w-correct); }
6987
- .ss-w-gxi-team-btn--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); text-decoration: line-through; opacity: .65; }
6988
7154
  /* Terminal outcome banner */
6989
7155
  .ss-w-gxi-banner { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 16px 12px; border-radius: 14px; text-align: center; }
6990
7156
  .ss-w-gxi-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
@@ -7161,23 +7327,23 @@ function injectStyles(root) {
7161
7327
  function StatsWidget(props) {
7162
7328
  const injectedClient = "client" in props ? props.client : void 0;
7163
7329
  const cfg = props.config;
7164
- const built = (0, import_react39.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
7165
- const logger = (0, import_react39.useMemo)(
7330
+ const built = (0, import_react40.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
7331
+ const logger = (0, import_react40.useMemo)(
7166
7332
  () => built ? built.client.createEventLogger({
7167
7333
  operatorUserId: cfg?.userContext?.operatorUserId,
7168
7334
  anonymousUserId: cfg?.userContext?.anonymousUserId
7169
7335
  }) : null,
7170
7336
  [built?.client]
7171
7337
  );
7172
- const ui = (0, import_react39.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
7173
- const rootRef = (0, import_react39.useRef)(null);
7174
- const introDoneRef = (0, import_react39.useRef)(false);
7175
- const markIntroDone = (0, import_react39.useCallback)(() => {
7338
+ const ui = (0, import_react40.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
7339
+ const rootRef = (0, import_react40.useRef)(null);
7340
+ const introDoneRef = (0, import_react40.useRef)(false);
7341
+ const markIntroDone = (0, import_react40.useCallback)(() => {
7176
7342
  introDoneRef.current = true;
7177
7343
  }, []);
7178
7344
  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
7179
7345
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
7180
- const [hasToday, setHasToday] = (0, import_react39.useState)(false);
7346
+ const [hasToday, setHasToday] = (0, import_react40.useState)(false);
7181
7347
  const monitor = useLiveMonitor({
7182
7348
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
7183
7349
  getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
@@ -7185,15 +7351,15 @@ function StatsWidget(props) {
7185
7351
  isOpen: controller.state.isOpen,
7186
7352
  hasToday
7187
7353
  });
7188
- const getSchedule = (0, import_react39.useCallback)(
7354
+ const getSchedule = (0, import_react40.useCallback)(
7189
7355
  (localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
7190
7356
  [built]
7191
7357
  );
7192
- const getStates = (0, import_react39.useCallback)(
7358
+ const getStates = (0, import_react40.useCallback)(
7193
7359
  (matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
7194
7360
  [built]
7195
7361
  );
7196
- const pinnedMatchIds = (0, import_react39.useMemo)(
7362
+ const pinnedMatchIds = (0, import_react40.useMemo)(
7197
7363
  () => monitor.pins.filter((p) => p.kind === "match").map((p) => p.matchId),
7198
7364
  [monitor.pins]
7199
7365
  );
@@ -7205,19 +7371,19 @@ function StatsWidget(props) {
7205
7371
  pinnedMatchIds
7206
7372
  });
7207
7373
  const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
7208
- (0, import_react39.useEffect)(() => {
7374
+ (0, import_react40.useEffect)(() => {
7209
7375
  setHasToday(todayHasContent);
7210
7376
  }, [todayHasContent]);
7211
7377
  const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
7212
7378
  const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
7213
7379
  const markTodayActivity = monitor.markTodayActivity;
7214
- const prevLiveCountRef = (0, import_react39.useRef)(0);
7215
- (0, import_react39.useEffect)(() => {
7380
+ const prevLiveCountRef = (0, import_react40.useRef)(0);
7381
+ (0, import_react40.useEffect)(() => {
7216
7382
  const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
7217
7383
  prevLiveCountRef.current = discovery.liveCount;
7218
7384
  if (rose) markTodayActivity();
7219
7385
  }, [discovery.liveCount, markTodayActivity]);
7220
- const slip = (0, import_react39.useMemo)(
7386
+ const slip = (0, import_react40.useMemo)(
7221
7387
  () => {
7222
7388
  const handler = props.config?.onAddToSlip;
7223
7389
  return {
@@ -7240,18 +7406,18 @@ function StatsWidget(props) {
7240
7406
  },
7241
7407
  [props.config?.onAddToSlip, controller.state.conversationId, built, monitor.markInSlip]
7242
7408
  );
7243
- const onDashboardTap = (0, import_react39.useMemo)(
7409
+ const onDashboardTap = (0, import_react40.useMemo)(
7244
7410
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : void 0,
7245
7411
  [built, logger]
7246
7412
  );
7247
7413
  const operatorUserId = cfg?.userContext?.operatorUserId;
7248
7414
  const anonymousUserId = cfg?.userContext?.anonymousUserId;
7249
7415
  const conversationId = controller.state.conversationId ?? void 0;
7250
- (0, import_react39.useEffect)(() => {
7416
+ (0, import_react40.useEffect)(() => {
7251
7417
  if (!logger) return;
7252
7418
  logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
7253
7419
  }, [logger, operatorUserId, anonymousUserId, conversationId]);
7254
- (0, import_react39.useEffect)(() => {
7420
+ (0, import_react40.useEffect)(() => {
7255
7421
  if (!logger) return;
7256
7422
  const onHide = () => {
7257
7423
  logger.flushOnHide();
@@ -7268,7 +7434,7 @@ function StatsWidget(props) {
7268
7434
  logger.dispose();
7269
7435
  };
7270
7436
  }, [logger]);
7271
- (0, import_react39.useEffect)(() => {
7437
+ (0, import_react40.useEffect)(() => {
7272
7438
  if (!built || !ui.injectStyles) return;
7273
7439
  const node = rootRef.current?.getRootNode();
7274
7440
  if (node) injectStyles(node);