@sensiblestats/widget-react 0.51.0 → 0.52.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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/StatsWidget.tsx
2
- import { useCallback as useCallback9, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef13, useState as useState33 } from "react";
2
+ import { useCallback as useCallback9, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef13, useState as useState34 } from "react";
3
3
  import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
4
4
 
5
5
  // src/kickoff.ts
@@ -1892,7 +1892,7 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
1892
1892
  }
1893
1893
 
1894
1894
  // src/components/ChatPanel.tsx
1895
- import { useEffect as useEffect14, useState as useState32 } from "react";
1895
+ import { useEffect as useEffect14, useState as useState33 } from "react";
1896
1896
 
1897
1897
  // src/components/ChatHeader.tsx
1898
1898
  import { useEffect as useEffect8, useRef as useRef8, useState as useState8 } from "react";
@@ -3995,7 +3995,7 @@ function TodayPanel({ discovery, ui, monitor }) {
3995
3995
  }
3996
3996
 
3997
3997
  // src/components/GamesPanel.tsx
3998
- import { useState as useState30 } from "react";
3998
+ import { useState as useState31 } from "react";
3999
3999
 
4000
4000
  // src/components/GamesLoginWall.tsx
4001
4001
  import { jsx as jsx52 } from "react/jsx-runtime";
@@ -4008,14 +4008,36 @@ import { Fragment as Fragment8, jsx as jsx53, jsxs as jsxs47 } from "react/jsx-r
4008
4008
  var GAME_ICONS = {
4009
4009
  "mystery-tiger": "\u{1F42F}",
4010
4010
  "daily-quiz": "\u{1F9E0}",
4011
- "career-path": "\u26BD",
4012
- "beat-the-grid": "\u{1F3AF}",
4013
- "guess-xi": "\u{1F4CB}",
4014
- "head-of-league": "\u{1F3C6}"
4011
+ "career-path": "\u{1F9ED}",
4012
+ "beat-the-grid": "\u{1F532}",
4013
+ "guess-the-xi": "\u{1F4CB}",
4014
+ "higher-or-lower": "\u{1F4C8}",
4015
+ "matchday-predictor": "\u{1F3AF}",
4016
+ "starting-xi": "\u{1F455}",
4017
+ "stat-ladder": "\u{1FA9C}",
4018
+ "fan-motm": "\u2B50"
4019
+ };
4020
+ var GAME_TITLES = {
4021
+ "mystery-tiger": "Mystery Tiger",
4022
+ "daily-quiz": "Daily Quiz",
4023
+ "career-path": "Career Path",
4024
+ "beat-the-grid": "Beat the Grid",
4025
+ "guess-the-xi": "Guess the XI",
4026
+ "higher-or-lower": "Higher or Lower",
4027
+ "matchday-predictor": "Matchday Predictor",
4028
+ "starting-xi": "Starting XI",
4029
+ "stat-ladder": "Stat Ladder",
4030
+ "fan-motm": "Fan MOTM"
4015
4031
  };
4016
4032
  function gameIcon(game) {
4017
4033
  return GAME_ICONS[game.gameId] ?? (game.kind === "fixture" ? "\u{1F4C5}" : "\u{1F3AE}");
4018
4034
  }
4035
+ function prettifyGameId(gameId) {
4036
+ return gameId.split("-").map((w) => w ? w[0].toUpperCase() + w.slice(1) : w).join(" ");
4037
+ }
4038
+ function gameTitle(game) {
4039
+ return game.title ?? GAME_TITLES[game.gameId] ?? prettifyGameId(game.gameId);
4040
+ }
4019
4041
  function formatCountdown(lockAtUtc) {
4020
4042
  const diff = new Date(lockAtUtc).getTime() - Date.now();
4021
4043
  if (diff <= 0) return null;
@@ -4056,7 +4078,7 @@ function GameTile({
4056
4078
  const statusClass = `ss-w-tile-status ss-w-tile-status--${game.status}`;
4057
4079
  const inner = /* @__PURE__ */ jsxs47(Fragment8, { children: [
4058
4080
  /* @__PURE__ */ jsx53("span", { className: "ss-w-tile-icon", children: gameIcon(game) }),
4059
- /* @__PURE__ */ jsx53("span", { className: "ss-w-tile-title", children: game.title ?? game.gameId }),
4081
+ /* @__PURE__ */ jsx53("span", { className: "ss-w-tile-title", children: gameTitle(game) }),
4060
4082
  countdown !== null ? /* @__PURE__ */ jsx53("span", { className: statusClass, "data-testid": "tile-countdown", children: countdown }) : /* @__PURE__ */ jsx53("span", { className: statusClass, children: statusLabel }),
4061
4083
  /* @__PURE__ */ jsx53("span", { className: `ss-w-tile-chip ss-w-tile-chip--${game.ranked ? "skill" : "fun"}`, children: game.ranked ? "Skill" : "For fun" })
4062
4084
  ] });
@@ -4107,7 +4129,7 @@ function GamesHub({
4107
4129
  }
4108
4130
 
4109
4131
  // src/components/GameScreenHost.tsx
4110
- import { useEffect as useEffect13, useRef as useRef12, useState as useState29 } from "react";
4132
+ import { useEffect as useEffect13, useRef as useRef12, useState as useState30 } from "react";
4111
4133
 
4112
4134
  // src/useGamePlay.ts
4113
4135
  import { useCallback as useCallback8, useRef as useRef11, useState as useState22 } from "react";
@@ -4767,6 +4789,90 @@ function BeatTheGridGame({
4767
4789
  ] });
4768
4790
  }
4769
4791
 
4792
+ // src/components/games/GuessTheXiGame.tsx
4793
+ import { useState as useState26, useId as useId5 } from "react";
4794
+
4795
+ // src/components/games/nationFlags.ts
4796
+ var FLAGS = {
4797
+ england: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}",
4798
+ scotland: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}",
4799
+ wales: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}",
4800
+ "northern ireland": "\u{1F1EC}\u{1F1E7}",
4801
+ "republic of ireland": "\u{1F1EE}\u{1F1EA}",
4802
+ ireland: "\u{1F1EE}\u{1F1EA}",
4803
+ "united kingdom": "\u{1F1EC}\u{1F1E7}",
4804
+ france: "\u{1F1EB}\u{1F1F7}",
4805
+ spain: "\u{1F1EA}\u{1F1F8}",
4806
+ portugal: "\u{1F1F5}\u{1F1F9}",
4807
+ germany: "\u{1F1E9}\u{1F1EA}",
4808
+ italy: "\u{1F1EE}\u{1F1F9}",
4809
+ netherlands: "\u{1F1F3}\u{1F1F1}",
4810
+ belgium: "\u{1F1E7}\u{1F1EA}",
4811
+ switzerland: "\u{1F1E8}\u{1F1ED}",
4812
+ austria: "\u{1F1E6}\u{1F1F9}",
4813
+ denmark: "\u{1F1E9}\u{1F1F0}",
4814
+ sweden: "\u{1F1F8}\u{1F1EA}",
4815
+ norway: "\u{1F1F3}\u{1F1F4}",
4816
+ finland: "\u{1F1EB}\u{1F1EE}",
4817
+ iceland: "\u{1F1EE}\u{1F1F8}",
4818
+ poland: "\u{1F1F5}\u{1F1F1}",
4819
+ czechia: "\u{1F1E8}\u{1F1FF}",
4820
+ "czech republic": "\u{1F1E8}\u{1F1FF}",
4821
+ croatia: "\u{1F1ED}\u{1F1F7}",
4822
+ serbia: "\u{1F1F7}\u{1F1F8}",
4823
+ "bosnia and herzegovina": "\u{1F1E7}\u{1F1E6}",
4824
+ greece: "\u{1F1EC}\u{1F1F7}",
4825
+ romania: "\u{1F1F7}\u{1F1F4}",
4826
+ ukraine: "\u{1F1FA}\u{1F1E6}",
4827
+ russia: "\u{1F1F7}\u{1F1FA}",
4828
+ hungary: "\u{1F1ED}\u{1F1FA}",
4829
+ slovakia: "\u{1F1F8}\u{1F1F0}",
4830
+ slovenia: "\u{1F1F8}\u{1F1EE}",
4831
+ turkey: "\u{1F1F9}\u{1F1F7}",
4832
+ t\u00FCrkiye: "\u{1F1F9}\u{1F1F7}",
4833
+ albania: "\u{1F1E6}\u{1F1F1}",
4834
+ "north macedonia": "\u{1F1F2}\u{1F1F0}",
4835
+ brazil: "\u{1F1E7}\u{1F1F7}",
4836
+ argentina: "\u{1F1E6}\u{1F1F7}",
4837
+ uruguay: "\u{1F1FA}\u{1F1FE}",
4838
+ colombia: "\u{1F1E8}\u{1F1F4}",
4839
+ chile: "\u{1F1E8}\u{1F1F1}",
4840
+ peru: "\u{1F1F5}\u{1F1EA}",
4841
+ ecuador: "\u{1F1EA}\u{1F1E8}",
4842
+ paraguay: "\u{1F1F5}\u{1F1FE}",
4843
+ mexico: "\u{1F1F2}\u{1F1FD}",
4844
+ "united states": "\u{1F1FA}\u{1F1F8}",
4845
+ usa: "\u{1F1FA}\u{1F1F8}",
4846
+ canada: "\u{1F1E8}\u{1F1E6}",
4847
+ jamaica: "\u{1F1EF}\u{1F1F2}",
4848
+ nigeria: "\u{1F1F3}\u{1F1EC}",
4849
+ ghana: "\u{1F1EC}\u{1F1ED}",
4850
+ senegal: "\u{1F1F8}\u{1F1F3}",
4851
+ ivorycoast: "\u{1F1E8}\u{1F1EE}",
4852
+ "cote d'ivoire": "\u{1F1E8}\u{1F1EE}",
4853
+ "ivory coast": "\u{1F1E8}\u{1F1EE}",
4854
+ cameroon: "\u{1F1E8}\u{1F1F2}",
4855
+ egypt: "\u{1F1EA}\u{1F1EC}",
4856
+ morocco: "\u{1F1F2}\u{1F1E6}",
4857
+ algeria: "\u{1F1E9}\u{1F1FF}",
4858
+ tunisia: "\u{1F1F9}\u{1F1F3}",
4859
+ mali: "\u{1F1F2}\u{1F1F1}",
4860
+ "south africa": "\u{1F1FF}\u{1F1E6}",
4861
+ "dr congo": "\u{1F1E8}\u{1F1E9}",
4862
+ japan: "\u{1F1EF}\u{1F1F5}",
4863
+ "south korea": "\u{1F1F0}\u{1F1F7}",
4864
+ korea: "\u{1F1F0}\u{1F1F7}",
4865
+ australia: "\u{1F1E6}\u{1F1FA}",
4866
+ "saudi arabia": "\u{1F1F8}\u{1F1E6}",
4867
+ iran: "\u{1F1EE}\u{1F1F7}",
4868
+ "new zealand": "\u{1F1F3}\u{1F1FF}"
4869
+ };
4870
+ function nationalityFlag(nationality) {
4871
+ if (!nationality) return "\u{1F3F3}\uFE0F";
4872
+ const key = nationality.trim().toLowerCase();
4873
+ return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase();
4874
+ }
4875
+
4770
4876
  // src/components/games/GuessTheXiGame.tsx
4771
4877
  import { Fragment as Fragment14, jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
4772
4878
  function parseClientState5(json) {
@@ -4777,6 +4883,16 @@ function parseClientState5(json) {
4777
4883
  return null;
4778
4884
  }
4779
4885
  }
4886
+ function toRows(positions) {
4887
+ const byRow = /* @__PURE__ */ new Map();
4888
+ positions.forEach((p, i) => {
4889
+ const rowKey = Number(p.slot?.split(":")[0]) || i + 1;
4890
+ const bucket = byRow.get(rowKey) ?? [];
4891
+ bucket.push(p);
4892
+ byRow.set(rowKey, bucket);
4893
+ });
4894
+ return [...byRow.keys()].sort((a, b) => a - b).map((k) => byRow.get(k));
4895
+ }
4780
4896
  function RevealCard({ reveal }) {
4781
4897
  return /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-reveal", "data-reveal-type": reveal.type ?? "", children: [
4782
4898
  reveal.slot && /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-reveal-slot", children: reveal.slot }),
@@ -4789,51 +4905,90 @@ function GuessTheXiGame({
4789
4905
  submitting,
4790
4906
  onSubmit
4791
4907
  }) {
4908
+ const [query, setQuery] = useState26("");
4909
+ const inputId = useId5();
4792
4910
  const clientState = parseClientState5(result?.clientStateJson);
4793
4911
  const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
4794
4912
  const solved = clientState?.status === "solved";
4913
+ const guessedTeamIds = new Set(clientState?.guessHistory.map((g) => g.teamId) ?? []);
4914
+ const rows = config ? toRows(config.positions) : [];
4915
+ const filtered = config && !isOver ? config.teamPool.filter(
4916
+ (t) => !guessedTeamIds.has(t.teamId) && t.teamName.toLowerCase().includes(query.toLowerCase())
4917
+ ) : [];
4795
4918
  function handlePick(teamId) {
4796
4919
  if (!config || isOver || submitting) return;
4797
4920
  const prevGuesses = clientState?.guessHistory.map((g) => ({ teamId: g.teamId })) ?? [];
4798
4921
  const newGuesses = [...prevGuesses, { teamId }];
4922
+ setQuery("");
4799
4923
  onSubmit(JSON.stringify({ guesses: newGuesses }));
4800
4924
  }
4925
+ const wrongGuesses = (clientState?.guessHistory ?? []).filter((g) => !g.wasCorrect);
4801
4926
  return /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi", "data-testid": "game-screen-guess-the-xi", children: [
4802
4927
  !config && /* @__PURE__ */ jsx59("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
4803
4928
  config && /* @__PURE__ */ jsxs53(Fragment14, { children: [
4804
4929
  /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-head", children: [
4805
4930
  /* @__PURE__ */ jsxs53("div", { children: [
4806
4931
  /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-title", children: "Guess the XI" }),
4807
- /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-sub", children: config.poolLabel })
4932
+ /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-sub", children: [
4933
+ "Which team? \xB7 ",
4934
+ config.poolLabel
4935
+ ] })
4808
4936
  ] }),
4809
4937
  clientState && !isOver && /* @__PURE__ */ jsxs53("span", { className: "ss-w-gxi-left", children: [
4810
- "Guess ",
4811
- clientState.guessesUsed + 1,
4812
- "/6"
4938
+ Math.max(0, 6 - clientState.guessesUsed),
4939
+ " left"
4813
4940
  ] })
4814
4941
  ] }),
4815
- config.positions.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-pitch", children: config.positions.map((pos, i) => /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-pslot", children: [
4816
- /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-pslot-pos", children: pos.slot }),
4817
- /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-pslot-nat", children: pos.nationality })
4818
- ] }, `${pos.slot}-${i}`)) }),
4942
+ rows.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-pitch", children: rows.map((row, r) => /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-prow", children: row.map((pos, c) => /* @__PURE__ */ jsx59(
4943
+ "div",
4944
+ {
4945
+ className: "ss-w-gxi-flag",
4946
+ title: pos.nationality,
4947
+ "aria-label": pos.nationality,
4948
+ children: nationalityFlag(pos.nationality)
4949
+ },
4950
+ `${pos.slot}-${c}`
4951
+ )) }, r)) }),
4819
4952
  clientState && clientState.earnedReveals.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-reveals", children: clientState.earnedReveals.map((r, i) => /* @__PURE__ */ jsx59(RevealCard, { reveal: r }, i)) }),
4820
- !isOver ? /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-pool", children: config.teamPool.map((team) => {
4821
- const guessRecord = clientState?.guessHistory.find((g) => g.teamId === team.teamId);
4822
- return /* @__PURE__ */ jsx59(
4823
- "button",
4824
- {
4825
- type: "button",
4826
- className: [
4827
- "ss-w-gxi-team-btn",
4828
- guessRecord ? guessRecord.wasCorrect ? "ss-w-gxi-team-btn--correct" : "ss-w-gxi-team-btn--wrong" : ""
4829
- ].filter(Boolean).join(" "),
4830
- disabled: submitting,
4831
- onClick: () => handlePick(team.teamId),
4832
- children: team.teamName
4833
- },
4834
- team.teamId
4835
- );
4836
- }) }) : clientState && /* @__PURE__ */ jsxs53("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${solved ? "solved" : "failed"}`, children: [
4953
+ !isOver ? /* @__PURE__ */ jsxs53(Fragment14, { children: [
4954
+ wrongGuesses.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-wrong", children: wrongGuesses.map((g) => {
4955
+ const team = config.teamPool.find((t) => t.teamId === g.teamId);
4956
+ return /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-wrong-pill", children: team?.teamName ?? `#${g.teamId}` }, g.teamId);
4957
+ }) }),
4958
+ /* @__PURE__ */ jsxs53("div", { className: "ss-w-gtta", children: [
4959
+ /* @__PURE__ */ jsx59(
4960
+ "input",
4961
+ {
4962
+ id: inputId,
4963
+ type: "text",
4964
+ role: "textbox",
4965
+ className: "ss-w-gtta-i",
4966
+ placeholder: "Name the team\u2026",
4967
+ value: query,
4968
+ disabled: submitting || isOver,
4969
+ onChange: (e) => setQuery(e.target.value),
4970
+ autoComplete: "off",
4971
+ "aria-label": "Name the team",
4972
+ "aria-autocomplete": "list"
4973
+ }
4974
+ ),
4975
+ query.length > 0 && filtered.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((t) => /* @__PURE__ */ jsx59(
4976
+ "div",
4977
+ {
4978
+ className: "ss-w-gtta-opt",
4979
+ role: "option",
4980
+ "aria-selected": false,
4981
+ onClick: () => handlePick(t.teamId),
4982
+ onKeyDown: (e) => {
4983
+ if (e.key === "Enter") handlePick(t.teamId);
4984
+ },
4985
+ tabIndex: 0,
4986
+ children: t.teamName
4987
+ },
4988
+ t.teamId
4989
+ )) })
4990
+ ] })
4991
+ ] }) : clientState && /* @__PURE__ */ jsxs53("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${solved ? "solved" : "failed"}`, children: [
4837
4992
  /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-banner-label", children: solved ? "\u2705 Solved!" : "\u{1F614} Out of guesses" }),
4838
4993
  /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-banner-score", children: clientState.score }),
4839
4994
  /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-banner-sub", children: [
@@ -4848,7 +5003,7 @@ function GuessTheXiGame({
4848
5003
  }
4849
5004
 
4850
5005
  // src/components/games/DailyQuizGame.tsx
4851
- import { useState as useState26 } from "react";
5006
+ import { useState as useState27 } from "react";
4852
5007
  import { Fragment as Fragment15, jsx as jsx60, jsxs as jsxs54 } from "react/jsx-runtime";
4853
5008
  function parseClientState6(json) {
4854
5009
  if (!json) return null;
@@ -4867,7 +5022,7 @@ function DailyQuizGame({
4867
5022
  submitting,
4868
5023
  onSubmit
4869
5024
  }) {
4870
- const [selections, setSelections] = useState26(/* @__PURE__ */ new Map());
5025
+ const [selections, setSelections] = useState27(/* @__PURE__ */ new Map());
4871
5026
  const clientState = parseClientState6(result?.clientStateJson);
4872
5027
  const isRevealed = (clientState?.results.length ?? 0) > 0 || result?.alreadyPlayed === true;
4873
5028
  const allAnswered = config != null && selections.size === config.questions.length;
@@ -4947,7 +5102,7 @@ function DailyQuizGame({
4947
5102
  }
4948
5103
 
4949
5104
  // src/components/games/MatchdayPredictorGame.tsx
4950
- import { useState as useState27 } from "react";
5105
+ import { useState as useState28 } from "react";
4951
5106
  import { jsx as jsx61, jsxs as jsxs55 } from "react/jsx-runtime";
4952
5107
  function parseClientState7(json) {
4953
5108
  if (!json) return null;
@@ -4970,9 +5125,9 @@ function MatchdayPredictorGame({
4970
5125
  submitting,
4971
5126
  onSubmit
4972
5127
  }) {
4973
- const [homeScore, setHomeScore] = useState27(0);
4974
- const [awayScore, setAwayScore] = useState27(0);
4975
- const [firstScorerPlayerId, setFirstScorerPlayerId] = useState27(null);
5128
+ const [homeScore, setHomeScore] = useState28(0);
5129
+ const [awayScore, setAwayScore] = useState28(0);
5130
+ const [firstScorerPlayerId, setFirstScorerPlayerId] = useState28(null);
4976
5131
  const clientState = parseClientState7(result?.clientStateJson);
4977
5132
  const alreadyPlayed = result?.alreadyPlayed === true;
4978
5133
  if (alreadyPlayed && clientState) {
@@ -5122,7 +5277,7 @@ function MatchdayPredictorGame({
5122
5277
  }
5123
5278
 
5124
5279
  // src/components/games/StartingXiGame.tsx
5125
- import { useState as useState28 } from "react";
5280
+ import { useState as useState29 } from "react";
5126
5281
  import { jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
5127
5282
  function parseClientState8(json) {
5128
5283
  if (!json) return null;
@@ -5143,7 +5298,7 @@ function StartingXiGame({
5143
5298
  submitting,
5144
5299
  onSubmit
5145
5300
  }) {
5146
- const [picked, setPicked] = useState28([]);
5301
+ const [picked, setPicked] = useState29([]);
5147
5302
  const clientState = parseClientState8(result?.clientStateJson);
5148
5303
  const alreadyPlayed = result?.alreadyPlayed === true;
5149
5304
  if (alreadyPlayed) {
@@ -5387,7 +5542,7 @@ function GameScreenHost({
5387
5542
  ui
5388
5543
  }) {
5389
5544
  const { gameId, fixtureId, gameDay = "" } = selected;
5390
- const [configJson, setConfigJson] = useState29(null);
5545
+ const [configJson, setConfigJson] = useState30(null);
5391
5546
  useEffect13(() => {
5392
5547
  setConfigJson(null);
5393
5548
  if (!conversation) return;
@@ -5533,7 +5688,7 @@ function GamesPanel({
5533
5688
  ui,
5534
5689
  conversation
5535
5690
  }) {
5536
- const [selected, setSelected] = useState30(null);
5691
+ const [selected, setSelected] = useState31(null);
5537
5692
  if (!loggedIn) return /* @__PURE__ */ jsx66(GamesLoginWall, { ui });
5538
5693
  if (selected !== null) {
5539
5694
  return /* @__PURE__ */ jsx66("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ jsx66(
@@ -5557,7 +5712,7 @@ function GamesPanel({
5557
5712
  }
5558
5713
 
5559
5714
  // src/components/Leaderboard.tsx
5560
- import { useState as useState31 } from "react";
5715
+ import { useState as useState32 } from "react";
5561
5716
 
5562
5717
  // src/components/LeaderboardRow.tsx
5563
5718
  import { jsx as jsx67, jsxs as jsxs60 } from "react/jsx-runtime";
@@ -5642,7 +5797,7 @@ function Leaderboard({
5642
5797
  ui,
5643
5798
  onPlay
5644
5799
  }) {
5645
- const [segment, setSegment] = useState31("weekly");
5800
+ const [segment, setSegment] = useState32("weekly");
5646
5801
  const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
5647
5802
  const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
5648
5803
  const isEmpty = segment === "weekly" ? data.weeklyTop.length === 0 : data.allTimeTop.length === 0;
@@ -5725,7 +5880,7 @@ function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }) {
5725
5880
  import { jsx as jsx71, jsxs as jsxs63 } from "react/jsx-runtime";
5726
5881
  var FULLSCREEN_QUERY = "(max-width: 639px)";
5727
5882
  function useIsModal() {
5728
- const [modal, setModal] = useState32(false);
5883
+ const [modal, setModal] = useState33(false);
5729
5884
  useEffect14(() => {
5730
5885
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
5731
5886
  const mql = window.matchMedia(FULLSCREEN_QUERY);
@@ -5800,7 +5955,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5800
5955
  ui
5801
5956
  }
5802
5957
  ),
5803
- /* @__PURE__ */ jsx71(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
5958
+ (!monitor || monitor.activeTab !== "games" && monitor.activeTab !== "leaderboard") && /* @__PURE__ */ jsx71(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
5804
5959
  ] });
5805
5960
  }
5806
5961
 
@@ -6827,9 +6982,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6827
6982
  .ss-w-hlbtns { display: flex; flex-direction: column; gap: 6px; justify-content: center; }
6828
6983
  .ss-w-hl-or { text-align: center; font-size: 11px; font-weight: 700; color: var(--ss-w-faint); }
6829
6984
  .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; }
6830
- .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)); }
6831
- .ss-w-hlbtn--dn { background: var(--ss-w-panel); color: var(--ss-w-ink); }
6832
- .ss-w-hlbtn:hover:not(:disabled) { border-color: var(--ss-w-accent); }
6985
+ /* Both options are neutral until picked \u2014 an amber default read as "already selected". */
6986
+ .ss-w-hlbtn--up, .ss-w-hlbtn--dn { background: var(--ss-w-panel); color: var(--ss-w-ink); }
6987
+ .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); }
6833
6988
  .ss-w-hlbtn:disabled { opacity: .5; cursor: not-allowed; }
6834
6989
  /* Run-over terminal panel */
6835
6990
  .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; }
@@ -6856,18 +7011,18 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6856
7011
  .ss-w-cpath-sub { font-size: 11px; color: var(--ss-w-faint); margin-top: 4px; }
6857
7012
  .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; }
6858
7013
  /* Career sequence \u2014 horizontal crests with arrows */
6859
- .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; }
6860
- .ss-w-cpath-arrow { align-self: center; color: var(--ss-w-faint); font-size: 13px; padding-top: 10px; }
7014
+ .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; }
7015
+ .ss-w-cpath-arrow { align-self: center; flex: none; color: var(--ss-w-faint); font-size: 13px; padding-top: 10px; }
6861
7016
  /* Single club \u2014 small vertical card */
6862
- .ss-w-cpath-club { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 58px; }
7017
+ .ss-w-cpath-club { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 56px; flex: none; }
6863
7018
  .ss-w-cpath-crest { width: 34px; height: 34px; object-fit: contain; flex: none; border-radius: 8px; }
6864
7019
  .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); }
6865
- .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; }
7020
+ .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; }
6866
7021
  .ss-w-cpath-spell-yr { font-size: 8px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; }
6867
7022
  .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)); }
6868
7023
  .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)); }
6869
7024
  /* Hidden clubs chip */
6870
- .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; }
7025
+ .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; }
6871
7026
  /* Hint line */
6872
7027
  .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)); }
6873
7028
  /* Terminal outcome */
@@ -6931,23 +7086,18 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6931
7086
  .ss-w-gxi-title { font-size: 18px; font-weight: 800; text-transform: uppercase; letter-spacing: .02em; color: var(--ss-w-ink); line-height: 1; }
6932
7087
  .ss-w-gxi-sub { font-size: 11px; color: var(--ss-w-faint); margin-top: 4px; }
6933
7088
  .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; }
6934
- /* Positions pitch: compact slot grid */
6935
- .ss-w-gxi-pitch { display: flex; flex-wrap: wrap; gap: 5px; }
6936
- .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; }
6937
- .ss-w-gxi-pslot-pos { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-accent); }
6938
- .ss-w-gxi-pslot-nat { font-size: 10px; color: var(--ss-w-faint); font-weight: 500; text-align: center; line-height: 1.2; }
7089
+ /* Pitch: a flag per slot laid out in formation rows on a green field */
7090
+ .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))); }
7091
+ .ss-w-gxi-prow { display: flex; justify-content: space-around; align-items: center; gap: 8px; }
7092
+ .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; }
7093
+ /* Wrong-guess trail */
7094
+ .ss-w-gxi-wrong { display: flex; flex-wrap: wrap; gap: 6px; }
7095
+ .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; }
6939
7096
  /* Earned reveals */
6940
7097
  .ss-w-gxi-reveals { display: flex; flex-direction: column; gap: 4px; }
6941
7098
  .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; }
6942
7099
  .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; }
6943
7100
  .ss-w-gxi-reveal-val { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
6944
- /* Team pool: responsive flex grid of buttons */
6945
- .ss-w-gxi-pool { display: flex; flex-wrap: wrap; gap: 6px; }
6946
- .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; }
6947
- .ss-w-gxi-team-btn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
6948
- .ss-w-gxi-team-btn:disabled { opacity: .5; cursor: not-allowed; }
6949
- .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); }
6950
- .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; }
6951
7101
  /* Terminal outcome banner */
6952
7102
  .ss-w-gxi-banner { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 16px 12px; border-radius: 14px; text-align: center; }
6953
7103
  .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)); }
@@ -7140,7 +7290,7 @@ function StatsWidget(props) {
7140
7290
  }, []);
7141
7291
  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
7142
7292
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
7143
- const [hasToday, setHasToday] = useState33(false);
7293
+ const [hasToday, setHasToday] = useState34(false);
7144
7294
  const monitor = useLiveMonitor({
7145
7295
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
7146
7296
  getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),