@sensiblestats/widget-react 0.21.0 → 0.23.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_react13 = require("react");
39
+ var import_react12 = require("react");
40
40
  var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
41
41
 
42
42
  // src/kickoff.ts
@@ -92,12 +92,6 @@ var STRINGS = {
92
92
  const drift = direction ? `, ${direction}` : "";
93
93
  return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
94
94
  },
95
- clubMatchPreviewHeading: "Match preview",
96
- clubTeamDnaHeading: "How they play",
97
- clubFormHeading: "Recent form",
98
- clubCountdownLabel: "Countdown to kick-off",
99
- clubKickoff: (ms) => new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
100
- clubKickoffAria: (ms) => `Kick-off ${new Intl.DateTimeFormat("en-GB", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
101
95
  inSlip: "In slip",
102
96
  slipAdded: (n) => n === void 0 ? "Added to slip" : `Added to slip (${n} selection${n === 1 ? "" : "s"})`,
103
97
  slipDuplicate: "Already in your slip",
@@ -149,12 +143,6 @@ var STRINGS = {
149
143
  const drift = direction ? `, ${direction}` : "";
150
144
  return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
151
145
  },
152
- clubMatchPreviewHeading: "Ma\xE7 \xF6nizlemesi",
153
- clubTeamDnaHeading: "Nas\u0131l oynuyorlar",
154
- clubFormHeading: "Son form",
155
- clubCountdownLabel: "Ba\u015Flama vuru\u015Funa kalan",
156
- clubKickoff: (ms) => new Intl.DateTimeFormat("tr-TR", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
157
- clubKickoffAria: (ms) => `Ba\u015Flama vuru\u015Fu ${new Intl.DateTimeFormat("tr-TR", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }).format(new Date(ms))}`,
158
146
  inSlip: "Kuponda",
159
147
  slipAdded: (n) => n === void 0 ? "Kupona eklendi" : `Kupona eklendi (${n} se\xE7im)`,
160
148
  slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
@@ -218,12 +206,6 @@ function normalizeUi(cfg) {
218
206
  excludedSuspended: strings.excludedSuspended,
219
207
  chartTimeLabel: strings.chartTimeLabel,
220
208
  chartAria: strings.chartAria,
221
- clubMatchPreviewHeading: strings.clubMatchPreviewHeading,
222
- clubTeamDnaHeading: strings.clubTeamDnaHeading,
223
- clubFormHeading: strings.clubFormHeading,
224
- clubCountdownLabel: strings.clubCountdownLabel,
225
- clubKickoff: strings.clubKickoff,
226
- clubKickoffAria: strings.clubKickoffAria,
227
209
  addToSlip: strings.addToSlip,
228
210
  inSlip: strings.inSlip,
229
211
  slipAdded: strings.slipAdded,
@@ -574,8 +556,8 @@ function applyEvent(state, event) {
574
556
  return { ...state, actionsLoading: true, status: event.data.message };
575
557
  case "turn_complete": {
576
558
  const active = activeTurn(state);
577
- const text = active?.text.trim() ?? "";
578
- const popupText = active?.isGreeting && !state.isOpen && text ? text.slice(0, POPUP_MAX) : state.popupText;
559
+ const greetingLine = event.data.clubFanDashboard?.greeting?.trim() || (active?.text.trim() ?? "");
560
+ const popupText = active?.isGreeting && !state.isOpen && greetingLine ? greetingLine.slice(0, POPUP_MAX) : state.popupText;
579
561
  return {
580
562
  ...state,
581
563
  isStreaming: false,
@@ -587,7 +569,7 @@ function applyEvent(state, event) {
587
569
  ...t,
588
570
  done: true,
589
571
  greetingDashboard: event.data.dashboard ?? void 0,
590
- clubDashboard: event.data.clubDashboard ?? void 0
572
+ clubFanDashboard: event.data.clubFanDashboard ?? void 0
591
573
  }))
592
574
  };
593
575
  }
@@ -784,7 +766,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
784
766
  }
785
767
 
786
768
  // src/components/ChatPanel.tsx
787
- var import_react12 = require("react");
769
+ var import_react11 = require("react");
788
770
 
789
771
  // src/components/ChatHeader.tsx
790
772
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -797,7 +779,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
797
779
  }
798
780
 
799
781
  // src/components/MessageList.tsx
800
- var import_react10 = require("react");
782
+ var import_react9 = require("react");
801
783
 
802
784
  // src/components/Markdown.tsx
803
785
  var import_react_markdown = __toESM(require("react-markdown"), 1);
@@ -1343,246 +1325,286 @@ function GreetingDashboard({ dashboard, onTap }) {
1343
1325
  ] });
1344
1326
  }
1345
1327
 
1346
- // src/components/club-dashboard/GreetingHeaderBlock.tsx
1328
+ // src/components/dashboard/FixtureCard.tsx
1347
1329
  var import_jsx_runtime17 = require("react/jsx-runtime");
1348
- function GreetingHeaderBlock({ block }) {
1349
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
1350
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1351
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1330
+ function resultClass(result) {
1331
+ const upper = result.toUpperCase();
1332
+ if (upper === "W") return "ss-w-fandash-form-pill--win";
1333
+ if (upper === "L") return "ss-w-fandash-form-pill--loss";
1334
+ return "ss-w-fandash-form-pill--draw";
1335
+ }
1336
+ function FormStrip({ form }) {
1337
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-form", children: form.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: `ss-w-fandash-form-pill ${resultClass(r)}`, children: r }, `${r}-${i}`)) });
1338
+ }
1339
+ function FormRow({ name, form }) {
1340
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-formrow", children: [
1341
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-formrow-name", children: name }),
1342
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormStrip, { form })
1352
1343
  ] });
1353
1344
  }
1354
-
1355
- // src/components/club-dashboard/FixtureHeroBlock.tsx
1356
- var import_react8 = require("react");
1357
- var import_jsx_runtime18 = require("react/jsx-runtime");
1358
- function initials3(name) {
1359
- return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
1360
- }
1361
- function Crest3({ url, name }) {
1362
- const [broken, setBroken] = (0, import_react8.useState)(false);
1363
- if (!url || broken) {
1364
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
1365
- }
1366
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1367
- }
1368
- function FixtureHeroBlock({
1369
- block,
1370
- ui,
1371
- onAction
1372
- }) {
1373
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
1374
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-tie", children: [
1375
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
1376
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
1377
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
1378
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
1379
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
1345
+ function FixtureCard({ card, onTap }) {
1346
+ const { data } = card;
1347
+ const h2h = data.h2H;
1348
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
1349
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-fixture", onClick: () => onTap(card), children: [
1350
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-eyebrow", children: [
1351
+ card.title,
1352
+ " \xB7 ",
1353
+ data.competition
1354
+ ] }),
1355
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-teams", children: [
1356
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-fixture-team", children: [
1357
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: data.homeCrestUrl ?? void 0, name: data.homeName, kind: "team" }),
1358
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-name", children: data.homeName })
1359
+ ] }),
1360
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-vs", children: "v" }),
1361
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-fixture-team ss-w-fandash-fixture-team--away", children: [
1362
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-name", children: data.awayName }),
1363
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: data.awayCrestUrl ?? void 0, name: data.awayName, kind: "team" })
1364
+ ] })
1365
+ ] }),
1366
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-meta", children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-metarow", children: [
1368
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metakey", children: data.dateLabel }),
1369
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metaval", children: data.kickoffLabel })
1370
+ ] }),
1371
+ data.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-metarow", children: [
1372
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metakey", children: data.venueLabel }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fixture-metaval", children: data.venue })
1374
+ ] }) : null
1375
+ ] }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
1380
1377
  ] }),
1381
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
1382
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1383
- block.venue ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1384
- block.competition ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1378
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-lastfive", children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-eyebrow", children: data.formLabel }),
1380
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-fixture-form", children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.homeName, form: data.homeForm }),
1382
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormRow, { name: data.awayName, form: data.awayForm })
1383
+ ] })
1385
1384
  ] }),
1386
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaLabel, { actionRef: block.ctaActionRef }), children: block.ctaLabel })
1385
+ h2h || data.fact ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-h2h", children: [
1386
+ h2h ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
1387
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-eyebrow", children: h2h.label }),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-fandash-split", children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-split-cell", children: [
1390
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-value", children: h2h.wins }),
1391
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-label", children: h2h.homeWinsLabel })
1392
+ ] }),
1393
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-split-cell", children: [
1394
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-value", children: h2h.draws }),
1395
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-label", children: h2h.drawsLabel })
1396
+ ] }),
1397
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ss-w-fandash-split-cell", children: [
1398
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-value", children: h2h.losses }),
1399
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-split-label", children: h2h.awayWinsLabel })
1400
+ ] })
1401
+ ] })
1402
+ ] }) : null,
1403
+ data.fact ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-fandash-fact", children: data.fact }) : null
1404
+ ] }) : null
1387
1405
  ] });
1388
1406
  }
1389
1407
 
1390
- // src/components/club-dashboard/ResultPills.tsx
1408
+ // src/components/dashboard/CountdownCard.tsx
1409
+ var import_react8 = require("react");
1410
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1411
+ var DAY_MS = 864e5;
1412
+ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
1413
+ const totalSeconds = Math.floor((kickoffUnix * 1e3 - nowMs) / 1e3);
1414
+ if (totalSeconds <= 0) return null;
1415
+ const days = Math.floor(totalSeconds / 86400);
1416
+ const hours = Math.floor(totalSeconds % 86400 / 3600);
1417
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
1418
+ const seconds = totalSeconds % 60;
1419
+ const pad = (n) => String(n).padStart(2, "0");
1420
+ if (days > 0) return [{ value: pad(days), unit: "d" }, { value: pad(hours), unit: "h" }];
1421
+ const segs = [{ value: pad(hours), unit: "h" }, { value: pad(minutes), unit: "m" }];
1422
+ if (withSeconds) segs.push({ value: pad(seconds), unit: "s" });
1423
+ return segs;
1424
+ }
1425
+ function CountdownCard({ card }) {
1426
+ const { data } = card;
1427
+ const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
1428
+ const [nowMs, setNowMs] = (0, import_react8.useState)(() => Date.now());
1429
+ const [reduced] = (0, import_react8.useState)(
1430
+ () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
1431
+ );
1432
+ const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
1433
+ (0, import_react8.useEffect)(() => {
1434
+ if (reduced) return;
1435
+ const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
1436
+ return () => window.clearInterval(id);
1437
+ }, [reduced, withinDay]);
1438
+ const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced);
1439
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-fandash-card ss-w-fandash-countdown", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-fandash-countdown-top", children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title ?? "Kick-off in" }),
1441
+ segments ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-fandash-countdown-clock", children: segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react8.Fragment, { children: [
1442
+ i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-fandash-countdown-colon", children: ":" }) : null,
1443
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "ss-w-fandash-countdown-seg", children: [
1444
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-fandash-countdown-value", children: s.value }),
1445
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-fandash-countdown-unit", children: unitLabel[s.unit] })
1446
+ ] })
1447
+ ] }, s.unit)) }) : null
1448
+ ] }) });
1449
+ }
1450
+
1451
+ // src/components/dashboard/InjuriesCard.tsx
1391
1452
  var import_jsx_runtime19 = require("react/jsx-runtime");
1392
- function ResultPills({ results }) {
1393
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children: results.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) });
1453
+ function ColHead({ name, crestUrl }) {
1454
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-fandash-injuries-col-head", children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Crest2, { url: crestUrl ?? void 0, name, kind: "team" }),
1456
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injuries-col-head-name", children: name })
1457
+ ] });
1458
+ }
1459
+ function InjuryList({ rows, emptyLabel }) {
1460
+ if (rows.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injuries-empty", children: emptyLabel });
1461
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "ss-w-fandash-injury-list", children: rows.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "ss-w-fandash-injury-row", children: [
1462
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-name", children: r.playerName }),
1463
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-fandash-injury-meta", children: [
1464
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-status", children: r.status }),
1465
+ r.injuryType ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-type", children: r.injuryType }) : null,
1466
+ r.expectedReturnLabel ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-injury-return", children: r.expectedReturnLabel }) : null
1467
+ ] })
1468
+ ] }, `${r.playerName}-${i}`)) });
1469
+ }
1470
+ function InjuriesCard({ card }) {
1471
+ const { data } = card;
1472
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-injuries", children: [
1473
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1474
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-cols", children: [
1475
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-col", children: [
1476
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColHead, { name: data.oursName, crestUrl: data.oursCrestUrl }),
1477
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.ours, emptyLabel: data.emptyLabel })
1478
+ ] }),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-fandash-injuries-divider" }),
1480
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-fandash-injuries-col", children: [
1481
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColHead, { name: data.theirsName, crestUrl: data.theirsCrestUrl }),
1482
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InjuryList, { rows: data.theirs, emptyLabel: data.emptyLabel })
1483
+ ] })
1484
+ ] })
1485
+ ] });
1394
1486
  }
1395
1487
 
1396
- // src/components/club-dashboard/FormGuideBlock.tsx
1488
+ // src/components/dashboard/ReasonToBetCard.tsx
1397
1489
  var import_jsx_runtime20 = require("react/jsx-runtime");
1398
- function FormGuideBlock({ block }) {
1399
- if (block.rows.length === 0) return null;
1400
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
1401
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
1402
- row.name,
1403
- row.position != null ? ` #${row.position}` : ""
1404
- ] }),
1405
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-form-pills", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ResultPills, { results: row.last5 }) })
1406
- ] }, row.name)) });
1490
+ function ReasonToBetCard({ card }) {
1491
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-reasons", children: [
1492
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1493
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "ss-w-fandash-reason-list", children: card.data.angles.map((angle, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { className: "ss-w-fandash-reason-item", children: angle }, `${angle}-${i}`)) })
1494
+ ] });
1407
1495
  }
1408
1496
 
1409
- // src/components/club-dashboard/MatchPreviewBlock.tsx
1497
+ // src/components/dashboard/WhereToWatchCard.tsx
1410
1498
  var import_jsx_runtime21 = require("react/jsx-runtime");
1411
- function MatchPreviewBlock({
1412
- block,
1413
- ui,
1414
- onAction
1415
- }) {
1416
- if (block.facts.length === 0) return null;
1417
- const heading = ui.clubMatchPreviewHeading;
1418
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1420
- block.facts.map(
1421
- (f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1422
- "button",
1423
- {
1424
- type: "button",
1425
- className: "ss-w-cdash-fact",
1426
- onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
1427
- children: [
1428
- f.sentence,
1429
- f.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1430
- " ",
1431
- f.label
1432
- ] }) : null
1433
- ]
1434
- },
1435
- i
1436
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: f.sentence }, i)
1437
- )
1499
+ function WhereToWatchCard({ card }) {
1500
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-watch", children: [
1501
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1502
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-fandash-stations", children: card.data.stations.map((station, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-fandash-station-chip", children: station }, `${station}-${i}`)) })
1438
1503
  ] });
1439
1504
  }
1440
1505
 
1441
- // src/components/club-dashboard/MatchPreviewCardBlock.tsx
1506
+ // src/components/dashboard/CongestedWeekCard.tsx
1442
1507
  var import_jsx_runtime22 = require("react/jsx-runtime");
1443
- function position(p) {
1444
- return p != null ? `#${p}` : "\u2014";
1445
- }
1446
- function MatchPreviewCardBlock({ block }) {
1447
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-preview", children: [
1448
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-preview-header", children: [
1449
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
1451
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName })
1452
- ] }),
1453
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-preview-row", children: [
1454
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-value", children: position(block.homePosition) }),
1455
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-label", children: block.tableLabel }),
1456
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-value", children: position(block.awayPosition) })
1457
- ] }),
1458
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-preview-row", children: [
1459
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-pills", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ResultPills, { results: block.homeLast5 }) }),
1460
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-label", children: block.last5Label }),
1461
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-preview-pills", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ResultPills, { results: block.awayLast5 }) })
1462
- ] }),
1463
- block.edgeTeamName ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-preview-edge", children: [
1464
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-hidden": "true", children: "\u25B8" }),
1465
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("strong", { children: block.edgeTeamName }),
1466
- block.edgeReason ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { children: [
1467
- " \u2014 ",
1468
- block.edgeReason
1469
- ] }) : null
1470
- ] }) : null,
1471
- block.h2HLines.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-preview-h2h", children: block.h2HLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: line }, i)) }) : null
1508
+ function CongestedWeekCard({ card, onTap }) {
1509
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("button", { type: "button", className: "ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-congested", onClick: () => onTap(card), children: [
1510
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1511
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-fandash-congested-grid", children: card.data.entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "ss-w-fandash-congested-cell", children: [
1512
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-congested-day", children: entry.dayLabel }),
1513
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-congested-opponent", children: entry.opponent }),
1514
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-congested-comp", children: entry.competition }),
1515
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-congested-time", children: entry.timeLabel })
1516
+ ] }, `${entry.opponent}-${i}`)) }),
1517
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-fandash-card-cta", children: card.actionLabel })
1472
1518
  ] });
1473
1519
  }
1474
1520
 
1475
- // src/components/club-dashboard/TeamDnaBlock.tsx
1521
+ // src/components/dashboard/TransfersCard.tsx
1476
1522
  var import_jsx_runtime23 = require("react/jsx-runtime");
1477
- function TeamDnaBlock({
1478
- block,
1479
- ui,
1480
- onAction
1481
- }) {
1482
- if (block.facts.length === 0) return null;
1483
- const heading = ui.clubTeamDnaHeading;
1484
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1485
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1486
- block.facts.map(
1487
- (f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1488
- "button",
1489
- {
1490
- type: "button",
1491
- className: "ss-w-cdash-fact",
1492
- onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
1493
- children: [
1494
- f.sentence,
1495
- f.label ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1496
- " ",
1497
- f.label
1498
- ] }) : null
1499
- ]
1500
- },
1501
- i
1502
- ) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { children: f.sentence }, i)
1503
- )
1523
+ function TransferList({ rows }) {
1524
+ if (rows.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfers-empty", children: "None" });
1525
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "ss-w-fandash-transfer-list", children: rows.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("li", { className: "ss-w-fandash-transfer-row", children: [
1526
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfer-name", children: r.playerName }),
1527
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfer-club", children: r.otherClub }),
1528
+ r.type ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfer-type", children: r.type }) : null
1529
+ ] }, `${r.playerName}-${i}`)) });
1530
+ }
1531
+ function TransfersCard({ card }) {
1532
+ const { data } = card;
1533
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-transfers", children: [
1534
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1535
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-fandash-transfers-cols", children: [
1536
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-fandash-transfers-col", children: [
1537
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfers-col-head", children: "In" }),
1538
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TransferList, { rows: data.in })
1539
+ ] }),
1540
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-fandash-transfers-col", children: [
1541
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "ss-w-fandash-transfers-col-head", children: "Out" }),
1542
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TransferList, { rows: data.out })
1543
+ ] })
1544
+ ] })
1504
1545
  ] });
1505
1546
  }
1506
1547
 
1507
- // src/components/club-dashboard/CountdownBlock.tsx
1508
- var import_react9 = require("react");
1548
+ // src/components/dashboard/LinksCard.tsx
1509
1549
  var import_jsx_runtime24 = require("react/jsx-runtime");
1510
- var DAY_MS = 24 * 3600 * 1e3;
1511
- function pad2(n) {
1512
- return String(n).padStart(2, "0");
1513
- }
1514
- function splitRemaining(remainingMs) {
1515
- const totalSeconds = Math.max(0, Math.floor(remainingMs / 1e3));
1516
- const h = Math.floor(totalSeconds / 3600);
1517
- const m = Math.floor(totalSeconds % 3600 / 60);
1518
- const s = totalSeconds % 60;
1519
- return { h: pad2(h), m: pad2(m), s: pad2(s) };
1520
- }
1521
- function CountdownBlock({ block, ui }) {
1522
- const [remainingMs, setRemainingMs] = (0, import_react9.useState)(() => block.kickoffUnix * 1e3 - Date.now());
1523
- (0, import_react9.useEffect)(() => {
1524
- setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1525
- if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
1526
- const id = setInterval(() => {
1527
- setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1528
- }, 1e3);
1529
- return () => clearInterval(id);
1530
- }, [block.kickoffUnix]);
1531
- if (remainingMs <= 0) return null;
1532
- if (remainingMs > DAY_MS) return null;
1533
- const { h, m, s } = splitRemaining(remainingMs);
1534
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
1535
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
1537
- "h",
1538
- " ",
1539
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
1540
- "m",
1541
- " ",
1542
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
1543
- "s"
1544
- ] }),
1545
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1550
+ function LinksCard({ card }) {
1551
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-fandash-card ss-w-fandash-links", children: [
1552
+ card.title ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-fandash-eyebrow", children: card.title }) : null,
1553
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-fandash-link-grid", children: card.data.links.map((link, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("a", { className: "ss-w-fandash-link-tile", href: link.url, target: "_blank", rel: "noopener noreferrer", children: [
1554
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-fandash-link-label", children: link.label }),
1555
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "ss-w-fandash-link-chevron", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChevronIcon, {}) })
1556
+ ] }, `${link.url}-${i}`)) })
1546
1557
  ] });
1547
1558
  }
1548
1559
 
1549
- // src/components/club-dashboard/ClubDashboard.tsx
1560
+ // src/components/dashboard/ClubFanDashboard.tsx
1550
1561
  var import_jsx_runtime25 = require("react/jsx-runtime");
1551
- var CLUB_BLOCK_REGISTRY = {
1552
- greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(GreetingHeaderBlock, { block }) : null,
1553
- fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
1554
- formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FormGuideBlock, { block, ui }) : null,
1555
- matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
1556
- matchPreviewCard: ({ block, ui }) => block.type === "matchPreviewCard" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MatchPreviewCardBlock, { block, ui }) : null,
1557
- teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
1558
- countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CountdownBlock, { block, ui }) : null
1559
- };
1560
- function ClubDashboard({
1561
- dashboard,
1562
- ui,
1563
- onAction
1564
- }) {
1565
- if (!dashboard.blocks.length) return null;
1566
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1567
- const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
1568
- if (!Comp) {
1569
- console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
1562
+ function ClubFanDashboard({ dashboard, onTap, ui }) {
1563
+ const orderedCards = [
1564
+ ...dashboard.cards.filter((c) => c.cardType === "countdown"),
1565
+ ...dashboard.cards.filter((c) => c.cardType !== "countdown")
1566
+ ];
1567
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-fandash", children: [
1568
+ dashboard.greeting ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "ss-w-fandash-greeting", children: dashboard.greeting }) : null,
1569
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-fandash-cards", children: orderedCards.map((card, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FanDashboardCard, { card, onTap, ui }, `${card.cardType}-${i}`)) })
1570
+ ] });
1571
+ }
1572
+ function FanDashboardCard({ card, onTap, ui }) {
1573
+ switch (card.cardType) {
1574
+ case "fixture":
1575
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FixtureCard, { card, onTap });
1576
+ case "countdown":
1577
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CountdownCard, { card });
1578
+ case "injuries":
1579
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(InjuriesCard, { card });
1580
+ case "reasonToBet":
1581
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReasonToBetCard, { card });
1582
+ case "whereToWatch":
1583
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(WhereToWatchCard, { card });
1584
+ case "congestedWeek":
1585
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CongestedWeekCard, { card, onTap });
1586
+ case "transfers":
1587
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TransfersCard, { card });
1588
+ case "links":
1589
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LinksCard, { card });
1590
+ default:
1570
1591
  return null;
1571
- }
1572
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Comp, { block, ui, onAction }) }, i);
1573
- }) });
1592
+ }
1574
1593
  }
1575
1594
 
1576
1595
  // src/components/ChatMessage.tsx
1577
1596
  var import_jsx_runtime26 = require("react/jsx-runtime");
1578
- function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
1597
+ function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
1579
1598
  if (message.role === "user") {
1580
1599
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1581
1600
  }
1601
+ const onFanDashboardTap = (card) => {
1602
+ onAct({ message: card.actionValue, label: card.actionLabel || card.title || "" });
1603
+ };
1582
1604
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1583
- message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Markdown, { text: message.text }) : null,
1584
- message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1585
- message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1605
+ message.text && !message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Markdown, { text: message.text }) : null,
1606
+ message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1607
+ message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ClubFanDashboard, { dashboard: message.clubFanDashboard, onTap: onFanDashboardTap, ui }) : null,
1586
1608
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1587
1609
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1588
1610
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
@@ -1608,14 +1630,14 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1608
1630
  var import_jsx_runtime28 = require("react/jsx-runtime");
1609
1631
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1610
1632
  const { state, send } = controller;
1611
- const listRef = (0, import_react10.useRef)(null);
1612
- const endRef = (0, import_react10.useRef)(null);
1613
- const pinnedRef = (0, import_react10.useRef)(true);
1614
- (0, import_react10.useEffect)(() => {
1633
+ const listRef = (0, import_react9.useRef)(null);
1634
+ const endRef = (0, import_react9.useRef)(null);
1635
+ const pinnedRef = (0, import_react9.useRef)(true);
1636
+ (0, import_react9.useEffect)(() => {
1615
1637
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
1616
1638
  }, [state.messages, state.status]);
1617
1639
  const hasUserMessage = state.messages.some((m) => m.role === "user");
1618
- const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
1640
+ const hasDashboard = state.messages.some((m) => m.role === "assistant" && (m.greetingDashboard || m.clubFanDashboard));
1619
1641
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1620
1642
  "div",
1621
1643
  {
@@ -1636,7 +1658,6 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1636
1658
  send(tile.actionValue, { displayText: tile.title });
1637
1659
  if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
1638
1660
  },
1639
- onClubAction: (label, opts) => send(label, { actionRef: opts.actionRef }),
1640
1661
  ui,
1641
1662
  slip
1642
1663
  },
@@ -1657,10 +1678,10 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1657
1678
  }
1658
1679
 
1659
1680
  // src/components/ChatInput.tsx
1660
- var import_react11 = require("react");
1681
+ var import_react10 = require("react");
1661
1682
  var import_jsx_runtime29 = require("react/jsx-runtime");
1662
1683
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
1663
- const [value, setValue] = (0, import_react11.useState)("");
1684
+ const [value, setValue] = (0, import_react10.useState)("");
1664
1685
  const submit = () => {
1665
1686
  const t = value.trim();
1666
1687
  if (!t) return;
@@ -1683,8 +1704,8 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
1683
1704
  var import_jsx_runtime30 = require("react/jsx-runtime");
1684
1705
  var FULLSCREEN_QUERY = "(max-width: 639px)";
1685
1706
  function useIsModal() {
1686
- const [modal, setModal] = (0, import_react12.useState)(false);
1687
- (0, import_react12.useEffect)(() => {
1707
+ const [modal, setModal] = (0, import_react11.useState)(false);
1708
+ (0, import_react11.useEffect)(() => {
1688
1709
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1689
1710
  const mql = window.matchMedia(FULLSCREEN_QUERY);
1690
1711
  const sync = () => setModal(mql.matches);
@@ -1697,7 +1718,7 @@ function useIsModal() {
1697
1718
  function ChatPanel({ controller, ui, slip, onDashboardTap }) {
1698
1719
  const { state, close, stop, send } = controller;
1699
1720
  const isModal = useIsModal();
1700
- (0, import_react12.useEffect)(() => {
1721
+ (0, import_react11.useEffect)(() => {
1701
1722
  const onKey = (e) => {
1702
1723
  if (e.key === "Escape") close();
1703
1724
  };
@@ -2061,61 +2082,117 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
2061
2082
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
2062
2083
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
2063
2084
 
2064
- /* club match-day dashboard */
2065
- .ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
2066
- .ss-w-cdash-block { display: flex; flex-direction: column; }
2067
-
2068
- .ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }
2069
- .ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }
2070
- .ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }
2071
-
2072
- .ss-w-cdash-fixture { display: flex; flex-direction: column; align-items: center; gap: 8px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 12px; text-align: center; }
2073
- .ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
2074
- .ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
2075
- .ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }
2076
- .ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }
2077
- .ss-w-cdash-crest--fallback { display: grid; place-items: center; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
2078
- .ss-w-cdash-fixture-meta { display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--ss-w-faint); }
2079
- .ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }
2080
- .ss-w-cdash-cta { font: inherit; font-weight: 700; font-size: 12px; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: none; border-radius: 999px; padding: 8px 18px; cursor: pointer; }
2081
-
2082
- .ss-w-cdash-form { display: flex; flex-direction: column; gap: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; }
2083
- .ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
2084
- .ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
2085
- .ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }
2086
- .ss-w-cdash-pill { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; font-size: 9.5px; font-weight: 700; color: #fff; }
2087
- .ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }
2088
- .ss-w-cdash-pill--d { background: var(--ss-w-faint); }
2089
- .ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
2090
-
2091
- .ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; }
2092
- .ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
2093
- .ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); margin: 0; }
2094
- .ss-w-cdash-fact { display: block; width: 100%; text-align: left; font: inherit; font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); background: none; border: none; padding: 0; cursor: pointer; }
2095
- .ss-w-cdash-fact:hover, .ss-w-cdash-fact:focus-visible { color: var(--ss-w-accent); text-decoration: underline; }
2096
- .ss-w-cdash-fact-label { font-size: 11px; font-weight: 700; color: var(--ss-w-accent); }
2097
-
2098
- .ss-w-cdash-cd { display: flex; flex-direction: column; align-items: center; gap: 4px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; text-align: center; }
2099
- .ss-w-cdash-cd-clock { display: flex; align-items: baseline; justify-content: center; gap: 2px; font-variant-numeric: tabular-nums; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-weight: 700; font-size: 18px; color: var(--ss-w-ink); }
2100
- .ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }
2101
- .ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
2102
-
2103
- .ss-w-cdash-preview { display: flex; flex-direction: column; gap: 8px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; }
2104
- .ss-w-cdash-preview-header { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 6px; }
2105
- .ss-w-cdash-preview-header .ss-w-cdash-team:first-child { justify-self: start; text-align: left; }
2106
- .ss-w-cdash-preview-header .ss-w-cdash-team:last-child { justify-self: end; text-align: right; }
2107
- .ss-w-cdash-preview-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px; }
2108
- .ss-w-cdash-preview-label { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); text-align: center; text-transform: uppercase; letter-spacing: 0.03em; }
2109
- .ss-w-cdash-preview-value { font-size: 12px; font-weight: 700; color: var(--ss-w-ink); text-align: center; }
2110
- .ss-w-cdash-preview-pills { display: flex; align-items: center; justify-content: center; gap: 3px; }
2111
- .ss-w-cdash-preview-row:first-of-type .ss-w-cdash-preview-value { justify-self: start; }
2112
- .ss-w-cdash-preview-row:first-of-type .ss-w-cdash-preview-value:last-child { justify-self: end; }
2113
- .ss-w-cdash-preview-row:last-of-type .ss-w-cdash-preview-pills:first-child { justify-self: start; }
2114
- .ss-w-cdash-preview-row:last-of-type .ss-w-cdash-preview-pills:last-child { justify-self: end; }
2115
- .ss-w-cdash-preview-edge { display: flex; align-items: baseline; gap: 4px; font-size: 12px; line-height: 1.4; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 8px; padding: 6px 8px; }
2116
- .ss-w-cdash-preview-edge strong { color: var(--ss-w-ink); }
2117
- .ss-w-cdash-preview-h2h { display: flex; flex-direction: column; gap: 2px; }
2118
- .ss-w-cdash-preview-h2h p { font-size: 11.5px; line-height: 1.4; color: var(--ss-w-faint); margin: 0; }
2085
+ /* club fan pre-match dashboard */
2086
+ .ss-w-fandash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
2087
+ .ss-w-fandash-greeting { font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ss-w-ink); }
2088
+ .ss-w-fandash-cards { display: flex; flex-direction: column; gap: 8px; }
2089
+
2090
+ /* Shared card chrome -- a plain <div> for [data] cards, a <button> for [prefill] cards. Both
2091
+ share the same box so the two families read as one system, not two ad hoc layouts. */
2092
+ .ss-w-fandash-card {
2093
+ display: flex; flex-direction: column; gap: 8px;
2094
+ padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);
2095
+ background: var(--ss-w-panel); text-align: left;
2096
+ color: inherit; font: inherit; width: 100%; min-width: 0;
2097
+ }
2098
+ .ss-w-fandash-card--tap { cursor: pointer; border-left: 3px solid var(--ss-w-accent); }
2099
+ .ss-w-fandash-card--tap:hover { background: var(--ss-w-bubble); }
2100
+ .ss-w-fandash-card-cta { align-self: flex-start; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); }
2101
+
2102
+ /* Shared alignment primitives: a small letterspaced section eyebrow, and a 3-column value/label
2103
+ split reused by the fixture head-to-head (and any future stat-row card). */
2104
+ .ss-w-fandash-eyebrow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
2105
+ .ss-w-fandash-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
2106
+ .ss-w-fandash-split-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; min-width: 0; }
2107
+ .ss-w-fandash-split-value { font-size: 20px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); line-height: 1; }
2108
+ .ss-w-fandash-split-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); overflow-wrap: anywhere; }
2109
+
2110
+ /* fixture card */
2111
+ .ss-w-fandash-fixture-teams { display: flex; align-items: center; gap: 10px; }
2112
+ .ss-w-fandash-fixture-team { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }
2113
+ .ss-w-fandash-fixture-team--away { justify-content: flex-end; }
2114
+ .ss-w-fandash-fixture-team .ss-w-bi-crest { width: 30px; height: 30px; }
2115
+ .ss-w-fandash-fixture-team .ss-w-bi-crest-mono { font-size: 12px; }
2116
+ .ss-w-fandash-fixture-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }
2117
+ .ss-w-fandash-fixture-team--away .ss-w-fandash-fixture-name { text-align: right; }
2118
+ .ss-w-fandash-fixture-vs { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }
2119
+ /* date + venue as labelled rows, so a long stadium name gets its own line to ellipsis in */
2120
+ .ss-w-fandash-fixture-meta { display: flex; flex-direction: column; gap: 1px; border-top: 1px solid var(--ss-w-line); padding-top: 8px; }
2121
+ .ss-w-fandash-fixture-metarow { display: flex; align-items: baseline; gap: 9px; }
2122
+ .ss-w-fandash-fixture-metakey { flex: none; width: 44px; font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
2123
+ .ss-w-fandash-fixture-metaval { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
2124
+ .ss-w-fandash-fact { font-size: 12px; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 8px; }
2125
+ /* each head-to-head figure sits on its own shaded tile, so the grid gap separates wins/draws/losses */
2126
+ .ss-w-fandash-h2h .ss-w-fandash-split-cell { background: var(--ss-w-bubble); border-radius: 10px; padding: 12px 6px; }
2127
+ /* extra breathing room between the tally row and the fact beyond the card's own gap */
2128
+ .ss-w-fandash-h2h .ss-w-fandash-fact { margin-top: 4px; }
2129
+
2130
+ /* last-five: one row per side, team name left, form pills right */
2131
+ .ss-w-fandash-fixture-form { display: flex; flex-direction: column; gap: 5px; }
2132
+ .ss-w-fandash-formrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
2133
+ .ss-w-fandash-formrow-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 600; }
2134
+ .ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }
2135
+ .ss-w-fandash-form-pill {
2136
+ display: inline-grid; place-items: center; width: 16px; height: 16px;
2137
+ border-radius: 4px; font-size: 9.5px; font-weight: 700; color: #fff;
2138
+ }
2139
+ .ss-w-fandash-form-pill--win { background: var(--ss-w-pos); }
2140
+ .ss-w-fandash-form-pill--loss { background: var(--ss-w-neg); }
2141
+ .ss-w-fandash-form-pill--draw { background: var(--ss-w-faint); }
2142
+
2143
+ /* countdown card: a compact top card -- section eyebrow left, colon-separated clock right. Each
2144
+ segment stacks its figure over a small unit label (d/h/m/s). The exact kickoff date is not
2145
+ repeated here; the fixture card below carries it. */
2146
+ .ss-w-fandash-countdown-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
2147
+ .ss-w-fandash-countdown-clock { display: inline-flex; align-items: flex-start; gap: 6px; color: var(--ss-w-accent); }
2148
+ .ss-w-fandash-countdown-seg { display: inline-flex; flex-direction: column; align-items: center; }
2149
+ .ss-w-fandash-countdown-value { font-size: 26px; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.01em; }
2150
+ .ss-w-fandash-countdown-unit { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); margin-top: 3px; }
2151
+ .ss-w-fandash-countdown-colon { font-size: 22px; font-weight: 750; line-height: 1; color: var(--ss-w-faint); }
2152
+
2153
+ /* injuries + transfers: two-column ours/theirs, in/out */
2154
+ .ss-w-fandash-transfers-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
2155
+ /* injuries: a 1px divider column sits between the two team sections, each headed by crest + name */
2156
+ .ss-w-fandash-injuries-cols { display: grid; grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1fr); gap: 12px; }
2157
+ .ss-w-fandash-injuries-divider { background: var(--ss-w-line); }
2158
+ .ss-w-fandash-injuries-col, .ss-w-fandash-transfers-col { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
2159
+ .ss-w-fandash-transfers-col-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }
2160
+ .ss-w-fandash-injuries-col-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--ss-w-ink); }
2161
+ .ss-w-fandash-injuries-col-head .ss-w-bi-crest { width: 18px; height: 18px; }
2162
+ .ss-w-fandash-injuries-col-head .ss-w-bi-crest-mono { font-size: 9px; }
2163
+ .ss-w-fandash-injuries-col-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2164
+ .ss-w-fandash-injuries-empty, .ss-w-fandash-transfers-empty { font-size: 11.5px; color: var(--ss-w-faint); }
2165
+ .ss-w-fandash-injury-list, .ss-w-fandash-transfer-list { list-style: none; display: flex; flex-direction: column; gap: 5px; }
2166
+ .ss-w-fandash-injury-row, .ss-w-fandash-transfer-row { display: flex; flex-direction: column; gap: 1px; }
2167
+ .ss-w-fandash-injury-name, .ss-w-fandash-transfer-name { font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }
2168
+ .ss-w-fandash-injury-meta { display: flex; flex-wrap: wrap; gap: 4px; font-size: 10.5px; color: var(--ss-w-faint); }
2169
+ .ss-w-fandash-injury-status { font-weight: 700; color: var(--ss-w-neg); }
2170
+ .ss-w-fandash-transfer-club { font-size: 11px; color: var(--ss-w-faint); }
2171
+ .ss-w-fandash-transfer-type { align-self: flex-start; font-size: 9.5px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 1px 7px; margin-top: 2px; }
2172
+
2173
+ /* reason-to-bet */
2174
+ .ss-w-fandash-reason-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }
2175
+ .ss-w-fandash-reason-item { font-size: 12.5px; padding-left: 14px; position: relative; }
2176
+ .ss-w-fandash-reason-item::before { content: "\u2022"; position: absolute; left: 0; color: var(--ss-w-accent); font-weight: 700; }
2177
+
2178
+ /* where-to-watch */
2179
+ .ss-w-fandash-stations { display: flex; flex-wrap: wrap; gap: 6px; }
2180
+ .ss-w-fandash-station-chip { font-size: 11.5px; font-weight: 600; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 999px; padding: 4px 10px; }
2181
+
2182
+ /* congested week: a fixed 3-column grid of upcoming fixtures (day / opponent / comp / time) */
2183
+ .ss-w-fandash-congested-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
2184
+ .ss-w-fandash-congested-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 8px; border-radius: 10px; background: var(--ss-w-bubble); }
2185
+ .ss-w-fandash-congested-day { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }
2186
+ .ss-w-fandash-congested-opponent { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }
2187
+ .ss-w-fandash-congested-comp { font-size: 10px; color: var(--ss-w-faint); overflow-wrap: anywhere; }
2188
+ .ss-w-fandash-congested-time { font-size: 10.5px; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }
2189
+
2190
+ /* links: 2-column grid of tappable tiles */
2191
+ .ss-w-fandash-link-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
2192
+ .ss-w-fandash-link-tile { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 13px; border-radius: 10px; border: 1px solid transparent; text-decoration: none; color: inherit; background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); }
2193
+ .ss-w-fandash-link-tile:hover { background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
2194
+ .ss-w-fandash-link-label { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }
2195
+ .ss-w-fandash-link-chevron { flex: none; width: 12px; height: 12px; color: var(--ss-w-accent); }
2119
2196
  `;
2120
2197
 
2121
2198
  // src/StatsWidget.tsx
@@ -2144,11 +2221,11 @@ function injectStyles(root) {
2144
2221
  function StatsWidget(props) {
2145
2222
  const injectedClient = "client" in props ? props.client : void 0;
2146
2223
  const cfg = props.config;
2147
- const built = (0, import_react13.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
2148
- const ui = (0, import_react13.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
2149
- const rootRef = (0, import_react13.useRef)(null);
2224
+ const built = (0, import_react12.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
2225
+ const ui = (0, import_react12.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
2226
+ const rootRef = (0, import_react12.useRef)(null);
2150
2227
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
2151
- const slip = (0, import_react13.useMemo)(
2228
+ const slip = (0, import_react12.useMemo)(
2152
2229
  () => ({
2153
2230
  onAddToSlip: props.config?.onAddToSlip,
2154
2231
  conversationId: controller.state.conversationId ?? void 0,
@@ -2161,11 +2238,11 @@ function StatsWidget(props) {
2161
2238
  }),
2162
2239
  [props.config?.onAddToSlip, controller.state.conversationId, built]
2163
2240
  );
2164
- const onDashboardTap = (0, import_react13.useMemo)(
2241
+ const onDashboardTap = (0, import_react12.useMemo)(
2165
2242
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
2166
2243
  [built]
2167
2244
  );
2168
- (0, import_react13.useEffect)(() => {
2245
+ (0, import_react12.useEffect)(() => {
2169
2246
  if (!built || !ui.injectStyles) return;
2170
2247
  const node = rootRef.current?.getRootNode();
2171
2248
  if (node) injectStyles(node);