@sensiblestats/widget-react 0.50.2 → 0.51.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @sensiblestats/widget-react
2
2
 
3
+ ## 0.51.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Leaderboard: render a default state when the weekly board has no scores yet. Weekly boards reset each week, so the tab now shows a "new week, blank slate" panel (with a last-week champion strip when history exists) or a "be the first" cold-start panel, each with a CTA into the Games tab, instead of a blank screen. A configured weekly prize is shown when present. Adds optional `weeklyPrize` and `lastWeek` fields to `LeaderboardPayload` (backend populates them separately; absent = cold start).
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @sensiblestats/widget-sdk@0.35.4
13
+
3
14
  ## 0.50.2
4
15
 
5
16
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -138,6 +138,13 @@ var STRINGS = {
138
138
  leaderboardOffBoard: "Outside top 50",
139
139
  leaderboardThisWeek: "This week",
140
140
  leaderboardAllTime: "All time",
141
+ leaderboardEmptyFreshTitle: "New week, blank slate",
142
+ leaderboardEmptyFreshBody: "No scores yet. The first fan to play a game takes #1.",
143
+ leaderboardEmptyColdTitle: "Be the first up",
144
+ leaderboardEmptyColdBody: "Nobody's on the board yet. Play a game and you're #1.",
145
+ leaderboardEmptyCta: "Play today's games",
146
+ leaderboardLastWeekLabel: "Last week",
147
+ leaderboardAllTimeEmpty: "The all-time board fills as fans play \u2014 nothing here yet.",
141
148
  gamePlay: "Play",
142
149
  gameResume: "Resume",
143
150
  gameLocked: "Locked",
@@ -228,6 +235,13 @@ var STRINGS = {
228
235
  leaderboardOffBoard: "\u0130lk 50 d\u0131\u015F\u0131nda",
229
236
  leaderboardThisWeek: "Bu hafta",
230
237
  leaderboardAllTime: "T\xFCm zamanlar",
238
+ leaderboardEmptyFreshTitle: "Yeni hafta, temiz sayfa",
239
+ leaderboardEmptyFreshBody: "Hen\xFCz skor yok. Oynayan ilk taraftar 1. s\u0131raya ge\xE7er.",
240
+ leaderboardEmptyColdTitle: "\u0130lk sen ol",
241
+ leaderboardEmptyColdBody: "Panoda hen\xFCz kimse yok. Bir oyun oyna, 1. s\u0131ra senin.",
242
+ leaderboardEmptyCta: "Bug\xFCn\xFCn oyunlar\u0131n\u0131 oyna",
243
+ leaderboardLastWeekLabel: "Ge\xE7en hafta",
244
+ leaderboardAllTimeEmpty: "T\xFCm zamanlar panosu taraftarlar oynad\u0131k\xE7a dolar \u2014 hen\xFCz bir \u015Fey yok.",
231
245
  gamePlay: "Oyna",
232
246
  gameResume: "Devam et",
233
247
  gameLocked: "Kilitli",
@@ -337,6 +351,13 @@ function normalizeUi(cfg) {
337
351
  leaderboardOffBoard: strings.leaderboardOffBoard,
338
352
  leaderboardThisWeek: strings.leaderboardThisWeek,
339
353
  leaderboardAllTime: strings.leaderboardAllTime,
354
+ leaderboardEmptyFreshTitle: strings.leaderboardEmptyFreshTitle,
355
+ leaderboardEmptyFreshBody: strings.leaderboardEmptyFreshBody,
356
+ leaderboardEmptyColdTitle: strings.leaderboardEmptyColdTitle,
357
+ leaderboardEmptyColdBody: strings.leaderboardEmptyColdBody,
358
+ leaderboardEmptyCta: strings.leaderboardEmptyCta,
359
+ leaderboardLastWeekLabel: strings.leaderboardLastWeekLabel,
360
+ leaderboardAllTimeEmpty: strings.leaderboardAllTimeEmpty,
340
361
  gamePlay: strings.gamePlay,
341
362
  gameResume: strings.gameResume,
342
363
  gameLocked: strings.gameLocked,
@@ -5613,18 +5634,58 @@ function LeaderboardAllTimeRow({
5613
5634
  ] });
5614
5635
  }
5615
5636
 
5616
- // src/components/Leaderboard.tsx
5637
+ // src/components/LeaderboardEmpty.tsx
5617
5638
  var import_jsx_runtime68 = require("react/jsx-runtime");
5639
+ function LeaderboardEmpty({
5640
+ segment,
5641
+ lastWeek,
5642
+ weeklyPrize,
5643
+ onPlay,
5644
+ ui
5645
+ }) {
5646
+ if (segment === "alltime") {
5647
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb-empty ss-w-lb-empty--alltime", children: [
5648
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb-empty-icon", "aria-hidden": "true", children: "\u{1F4CA}" }),
5649
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("p", { className: "ss-w-lb-empty-body", children: ui.leaderboardAllTimeEmpty })
5650
+ ] });
5651
+ }
5652
+ const fresh = lastWeek != null;
5653
+ const title = fresh ? ui.leaderboardEmptyFreshTitle : ui.leaderboardEmptyColdTitle;
5654
+ const body = fresh ? ui.leaderboardEmptyFreshBody : ui.leaderboardEmptyColdBody;
5655
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb-empty", children: [
5656
+ weeklyPrize && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-prize", children: [
5657
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-prize-icon", "aria-hidden": "true", children: "\u{1F3C6}" }),
5658
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-prize-body", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-prize-text", children: weeklyPrize }) })
5659
+ ] }),
5660
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb-empty-hero", children: [
5661
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb-empty-icon", "aria-hidden": "true", children: fresh ? "\u{1F3C6}" : "\u{1F3AE}" }),
5662
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h4", { className: "ss-w-lb-empty-title", children: title }),
5663
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("p", { className: "ss-w-lb-empty-body", children: body }),
5664
+ onPlay && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "ss-w-lb-empty-cta", onClick: onPlay, children: ui.leaderboardEmptyCta })
5665
+ ] }),
5666
+ fresh && lastWeek && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb-last", children: [
5667
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb-last-label", children: ui.leaderboardLastWeekLabel }),
5668
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb-last-champ", "aria-hidden": "true", children: "\u{1F947}" }),
5669
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb-last-handle", children: lastWeek.handle }),
5670
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb-last-points", children: formatPoints(lastWeek.points) })
5671
+ ] })
5672
+ ] });
5673
+ }
5674
+
5675
+ // src/components/Leaderboard.tsx
5676
+ var import_jsx_runtime69 = require("react/jsx-runtime");
5618
5677
  function Leaderboard({
5619
5678
  data,
5620
- ui
5679
+ ui,
5680
+ onPlay
5621
5681
  }) {
5622
5682
  const [segment, setSegment] = (0, import_react37.useState)("weekly");
5623
5683
  const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
5624
5684
  const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
5625
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb2", children: [
5626
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-seg", children: [
5627
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
5685
+ const isEmpty = segment === "weekly" ? data.weeklyTop.length === 0 : data.allTimeTop.length === 0;
5686
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "ss-w-lb2", children: [
5687
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "ss-w-seg", children: [
5688
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
5628
5689
  "button",
5629
5690
  {
5630
5691
  type: "button",
@@ -5634,7 +5695,7 @@ function Leaderboard({
5634
5695
  children: ui.leaderboardThisWeek
5635
5696
  }
5636
5697
  ),
5637
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
5698
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
5638
5699
  "button",
5639
5700
  {
5640
5701
  type: "button",
@@ -5645,40 +5706,60 @@ function Leaderboard({
5645
5706
  }
5646
5707
  )
5647
5708
  ] }),
5648
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-rows", children: segment === "weekly" ? data.weeklyTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
5649
- LeaderboardWeeklyRow,
5650
- {
5651
- row,
5652
- isMe: row.operatorUserId === data.myWeeklyRow?.operatorUserId
5653
- },
5654
- row.operatorUserId
5655
- )) : data.allTimeTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
5656
- LeaderboardAllTimeRow,
5709
+ isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
5710
+ LeaderboardEmpty,
5657
5711
  {
5658
- row,
5659
- isMe: row.operatorUserId === data.myAllTimeRow?.operatorUserId
5660
- },
5661
- row.operatorUserId
5662
- )) }),
5663
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-kitline", children: "\u{1F3BD}" }),
5664
- myRow != null && (offBoard ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lbgap", children: ui.leaderboardOffBoard }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "ss-w-lb2-rows", children: [
5665
- segment === "weekly" && data.myWeeklyRow && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(LeaderboardWeeklyRow, { row: data.myWeeklyRow, isMe: true }),
5666
- segment === "alltime" && data.myAllTimeRow && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(LeaderboardAllTimeRow, { row: data.myAllTimeRow, isMe: true })
5667
- ] })),
5668
- segment === "alltime" && data.myAllTimeRow && !offBoard && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-rows", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "ss-w-lb2-row", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "ss-w-lb2-handle", children: formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0)) }) }) })
5712
+ segment,
5713
+ lastWeek: data.lastWeek,
5714
+ weeklyPrize: data.weeklyPrize,
5715
+ onPlay,
5716
+ ui
5717
+ }
5718
+ ) : /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
5719
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-lb2-rows", children: segment === "weekly" ? data.weeklyTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
5720
+ LeaderboardWeeklyRow,
5721
+ {
5722
+ row,
5723
+ isMe: row.operatorUserId === data.myWeeklyRow?.operatorUserId
5724
+ },
5725
+ row.operatorUserId
5726
+ )) : data.allTimeTop.map((row) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
5727
+ LeaderboardAllTimeRow,
5728
+ {
5729
+ row,
5730
+ isMe: row.operatorUserId === data.myAllTimeRow?.operatorUserId
5731
+ },
5732
+ row.operatorUserId
5733
+ )) }),
5734
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-kitline", children: "\u{1F3BD}" }),
5735
+ myRow != null && (offBoard ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-lbgap", children: ui.leaderboardOffBoard }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "ss-w-lb2-rows", children: [
5736
+ segment === "weekly" && data.myWeeklyRow && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(LeaderboardWeeklyRow, { row: data.myWeeklyRow, isMe: true }),
5737
+ segment === "alltime" && data.myAllTimeRow && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(LeaderboardAllTimeRow, { row: data.myAllTimeRow, isMe: true })
5738
+ ] })),
5739
+ segment === "alltime" && data.myAllTimeRow && !offBoard && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-lb2-rows", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-lb2-row", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "ss-w-lb2-handle", children: formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0)) }) }) })
5740
+ ] })
5669
5741
  ] });
5670
5742
  }
5671
5743
 
5672
5744
  // src/components/LeaderboardPanel.tsx
5673
- var import_jsx_runtime69 = require("react/jsx-runtime");
5674
- function LeaderboardPanel({ loggedIn, data, ui }) {
5675
- if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(GamesLoginWall, { ui });
5676
- if (data === null) return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-mon-list" });
5677
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Leaderboard, { data, ui }) });
5745
+ var import_jsx_runtime70 = require("react/jsx-runtime");
5746
+ var EMPTY_PAYLOAD = {
5747
+ week: "",
5748
+ weeklyTop: [],
5749
+ myWeeklyRow: null,
5750
+ allTimeTop: [],
5751
+ myAllTimeRow: null,
5752
+ weeklyPrize: null,
5753
+ lastWeek: null
5754
+ };
5755
+ function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }) {
5756
+ if (!loggedIn) return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(GamesLoginWall, { ui });
5757
+ if (data === null && loading) return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "ss-w-mon-list" });
5758
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(Leaderboard, { data: data ?? EMPTY_PAYLOAD, ui, onPlay }) });
5678
5759
  }
5679
5760
 
5680
5761
  // src/components/ChatPanel.tsx
5681
- var import_jsx_runtime70 = require("react/jsx-runtime");
5762
+ var import_jsx_runtime71 = require("react/jsx-runtime");
5682
5763
  var FULLSCREEN_QUERY = "(max-width: 639px)";
5683
5764
  function useIsModal() {
5684
5765
  const [modal, setModal] = (0, import_react38.useState)(false);
@@ -5709,8 +5790,8 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5709
5790
  (0, import_react38.useEffect)(() => {
5710
5791
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
5711
5792
  }, [monitor, state.isStreaming, state.messages.length]);
5712
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
5713
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
5793
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
5794
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
5714
5795
  ChatHeader,
5715
5796
  {
5716
5797
  onClose: close,
@@ -5723,7 +5804,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5723
5804
  moreOptionsLabel: ui.moreOptions
5724
5805
  }
5725
5806
  ),
5726
- monitor && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
5807
+ monitor && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
5727
5808
  TabBar,
5728
5809
  {
5729
5810
  monitor,
@@ -5735,19 +5816,28 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, g
5735
5816
  gamesEnabled: gamesResult?.enabled ?? false
5736
5817
  }
5737
5818
  ),
5738
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
5819
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
5739
5820
  "div",
5740
5821
  {
5741
5822
  style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
5742
- children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
5823
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
5743
5824
  }
5744
5825
  ),
5745
- monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(TodayPanel, { discovery, ui, monitor }),
5746
- monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(MatchesPanel, { monitor, ui, slip }),
5747
- monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(OddsPanel, { monitor, ui, slip }),
5748
- monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(GamesPanel, { loggedIn: !!loggedIn, games: gamesResult.games, ui, conversation }),
5749
- monitor && monitor.activeTab === "leaderboard" && leaderboardResult && /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LeaderboardPanel, { loggedIn: !!loggedIn, data: leaderboardResult.data, ui }),
5750
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
5826
+ monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(TodayPanel, { discovery, ui, monitor }),
5827
+ monitor && monitor.activeTab === "following" && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(MatchesPanel, { monitor, ui, slip }),
5828
+ monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(OddsPanel, { monitor, ui, slip }),
5829
+ monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(GamesPanel, { loggedIn: !!loggedIn, games: gamesResult.games, ui, conversation }),
5830
+ monitor && monitor.activeTab === "leaderboard" && leaderboardResult && /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
5831
+ LeaderboardPanel,
5832
+ {
5833
+ loggedIn: !!loggedIn,
5834
+ data: leaderboardResult.data,
5835
+ loading: leaderboardResult.loading,
5836
+ onPlay: () => monitor.setActiveTab("games"),
5837
+ ui
5838
+ }
5839
+ ),
5840
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
5751
5841
  ] });
5752
5842
  }
5753
5843
 
@@ -6701,6 +6791,20 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
6701
6791
  /* Off-board treatment: dashed pill indicating rank is outside top N */
6702
6792
  .ss-w-lbgap { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 12px; font-size: 11.5px; color: var(--ss-w-faint); border: 1px dashed var(--ss-w-line); border-radius: 10px; }
6703
6793
 
6794
+ /* ---- Leaderboard empty / weekly-reset default state ---- */
6795
+ .ss-w-lb-empty { display: flex; flex-direction: column; gap: 12px; flex: 1; }
6796
+ .ss-w-lb-empty-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 20px 16px; border: 1px dashed color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); border-radius: 14px; background: color-mix(in srgb, var(--ss-w-cta) 6%, var(--ss-w-panel)); }
6797
+ .ss-w-lb-empty--alltime { align-items: center; justify-content: center; text-align: center; padding: 24px 16px; }
6798
+ .ss-w-lb-empty-icon { font-size: 30px; line-height: 1; }
6799
+ .ss-w-lb-empty-title { margin: 2px 0 0; font-size: 16px; font-weight: 800; color: var(--ss-w-ink); }
6800
+ .ss-w-lb-empty-body { margin: 0; max-width: 30ch; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-faint); }
6801
+ .ss-w-lb-empty-cta { margin-top: 6px; border: none; border-radius: 10px; padding: 9px 18px; font: inherit; font-size: 13px; font-weight: 700; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); cursor: pointer; }
6802
+ .ss-w-lb-empty-cta:hover { filter: brightness(1.04); }
6803
+ .ss-w-lb-last { display: flex; align-items: center; gap: 7px; padding-top: 10px; border-top: 1px solid var(--ss-w-line); font-size: 11px; }
6804
+ .ss-w-lb-last-label { text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--ss-w-faint); }
6805
+ .ss-w-lb-last-handle { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
6806
+ .ss-w-lb-last-points { flex: none; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
6807
+
6704
6808
  /* ---- Mystery Tiger game screen (D3) ---- */
6705
6809
  .ss-w-gt { display: flex; flex-direction: column; gap: 10px; }
6706
6810
  /* Typeahead wrapper: relative so the dropdown can position under it */
@@ -7032,7 +7136,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
7032
7136
  `;
7033
7137
 
7034
7138
  // src/StatsWidget.tsx
7035
- var import_jsx_runtime71 = require("react/jsx-runtime");
7139
+ var import_jsx_runtime72 = require("react/jsx-runtime");
7036
7140
  function buildClient(props) {
7037
7141
  try {
7038
7142
  if ("client" in props && props.client) {
@@ -7171,7 +7275,7 @@ function StatsWidget(props) {
7171
7275
  }, [built, ui.injectStyles]);
7172
7276
  if (!built) return null;
7173
7277
  const attrs = themeAttrs(ui);
7174
- return /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
7278
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
7175
7279
  ChatPanel,
7176
7280
  {
7177
7281
  controller,
@@ -7185,7 +7289,7 @@ function StatsWidget(props) {
7185
7289
  loggedIn: !!operatorUserId,
7186
7290
  conversation: built?.conversation ?? null
7187
7291
  }
7188
- ) : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
7292
+ ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
7189
7293
  ChatFab,
7190
7294
  {
7191
7295
  label: ui.launcherLabel,