@sensiblestats/widget-react 0.22.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_react11 = 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
@@ -556,8 +556,8 @@ function applyEvent(state, event) {
556
556
  return { ...state, actionsLoading: true, status: event.data.message };
557
557
  case "turn_complete": {
558
558
  const active = activeTurn(state);
559
- const text = active?.text.trim() ?? "";
560
- 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;
561
561
  return {
562
562
  ...state,
563
563
  isStreaming: false,
@@ -568,7 +568,8 @@ function applyEvent(state, event) {
568
568
  messages: mapActive(state, (t) => ({
569
569
  ...t,
570
570
  done: true,
571
- greetingDashboard: event.data.dashboard ?? void 0
571
+ greetingDashboard: event.data.dashboard ?? void 0,
572
+ clubFanDashboard: event.data.clubFanDashboard ?? void 0
572
573
  }))
573
574
  };
574
575
  }
@@ -765,7 +766,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
765
766
  }
766
767
 
767
768
  // src/components/ChatPanel.tsx
768
- var import_react10 = require("react");
769
+ var import_react11 = require("react");
769
770
 
770
771
  // src/components/ChatHeader.tsx
771
772
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -778,7 +779,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
778
779
  }
779
780
 
780
781
  // src/components/MessageList.tsx
781
- var import_react8 = require("react");
782
+ var import_react9 = require("react");
782
783
 
783
784
  // src/components/Markdown.tsx
784
785
  var import_react_markdown = __toESM(require("react-markdown"), 1);
@@ -1324,28 +1325,299 @@ function GreetingDashboard({ dashboard, onTap }) {
1324
1325
  ] });
1325
1326
  }
1326
1327
 
1327
- // src/components/ChatMessage.tsx
1328
+ // src/components/dashboard/FixtureCard.tsx
1328
1329
  var import_jsx_runtime17 = require("react/jsx-runtime");
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 })
1343
+ ] });
1344
+ }
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 })
1377
+ ] }),
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
+ ] })
1384
+ ] }),
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
1405
+ ] });
1406
+ }
1407
+
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
1452
+ var import_jsx_runtime19 = require("react/jsx-runtime");
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
+ ] });
1486
+ }
1487
+
1488
+ // src/components/dashboard/ReasonToBetCard.tsx
1489
+ var import_jsx_runtime20 = require("react/jsx-runtime");
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
+ ] });
1495
+ }
1496
+
1497
+ // src/components/dashboard/WhereToWatchCard.tsx
1498
+ var import_jsx_runtime21 = require("react/jsx-runtime");
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}`)) })
1503
+ ] });
1504
+ }
1505
+
1506
+ // src/components/dashboard/CongestedWeekCard.tsx
1507
+ var import_jsx_runtime22 = require("react/jsx-runtime");
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 })
1518
+ ] });
1519
+ }
1520
+
1521
+ // src/components/dashboard/TransfersCard.tsx
1522
+ var import_jsx_runtime23 = require("react/jsx-runtime");
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
+ ] })
1545
+ ] });
1546
+ }
1547
+
1548
+ // src/components/dashboard/LinksCard.tsx
1549
+ var import_jsx_runtime24 = require("react/jsx-runtime");
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}`)) })
1557
+ ] });
1558
+ }
1559
+
1560
+ // src/components/dashboard/ClubFanDashboard.tsx
1561
+ var import_jsx_runtime25 = require("react/jsx-runtime");
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:
1591
+ return null;
1592
+ }
1593
+ }
1594
+
1595
+ // src/components/ChatMessage.tsx
1596
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1329
1597
  function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
1330
1598
  if (message.role === "user") {
1331
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
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 }) });
1332
1600
  }
1333
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1334
- message.text && !message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Markdown, { text: message.text }) : null,
1335
- message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1336
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1337
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1338
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1339
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1340
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1601
+ const onFanDashboardTap = (card) => {
1602
+ onAct({ message: card.actionValue, label: card.actionLabel || card.title || "" });
1603
+ };
1604
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
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,
1608
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1610
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1611
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1612
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1341
1613
  ] });
1342
1614
  }
1343
1615
 
1344
1616
  // src/components/IntentChips.tsx
1345
- var import_jsx_runtime18 = require("react/jsx-runtime");
1617
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1346
1618
  function IntentChips({ chips, onPick }) {
1347
1619
  if (chips.length === 0) return null;
1348
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1620
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1349
1621
  }
1350
1622
 
1351
1623
  // src/scroll.ts
@@ -1355,18 +1627,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1355
1627
  }
1356
1628
 
1357
1629
  // src/components/MessageList.tsx
1358
- var import_jsx_runtime19 = require("react/jsx-runtime");
1630
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1359
1631
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1360
1632
  const { state, send } = controller;
1361
- const listRef = (0, import_react8.useRef)(null);
1362
- const endRef = (0, import_react8.useRef)(null);
1363
- const pinnedRef = (0, import_react8.useRef)(true);
1364
- (0, import_react8.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)(() => {
1365
1637
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
1366
1638
  }, [state.messages, state.status]);
1367
1639
  const hasUserMessage = state.messages.some((m) => m.role === "user");
1368
- const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
1369
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1640
+ const hasDashboard = state.messages.some((m) => m.role === "assistant" && (m.greetingDashboard || m.clubFanDashboard));
1641
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1370
1642
  "div",
1371
1643
  {
1372
1644
  className: "ss-w-list",
@@ -1376,7 +1648,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1376
1648
  if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
1377
1649
  },
1378
1650
  children: [
1379
- state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1651
+ state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1380
1652
  ChatMessage,
1381
1653
  {
1382
1654
  message: m,
@@ -1391,25 +1663,25 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1391
1663
  },
1392
1664
  m.id
1393
1665
  )),
1394
- state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1666
+ state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1395
1667
  } }) : null,
1396
- state.status ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1397
- state.error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1398
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1399
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1668
+ state.status ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1669
+ state.error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1670
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1671
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1400
1672
  ] }) : null,
1401
- !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1402
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref: endRef })
1673
+ !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1674
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { ref: endRef })
1403
1675
  ]
1404
1676
  }
1405
1677
  );
1406
1678
  }
1407
1679
 
1408
1680
  // src/components/ChatInput.tsx
1409
- var import_react9 = require("react");
1410
- var import_jsx_runtime20 = require("react/jsx-runtime");
1681
+ var import_react10 = require("react");
1682
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1411
1683
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
1412
- const [value, setValue] = (0, import_react9.useState)("");
1684
+ const [value, setValue] = (0, import_react10.useState)("");
1413
1685
  const submit = () => {
1414
1686
  const t = value.trim();
1415
1687
  if (!t) return;
@@ -1422,18 +1694,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
1422
1694
  submit();
1423
1695
  }
1424
1696
  };
1425
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-input", children: [
1426
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1427
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SendIcon, {}) })
1697
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "ss-w-input", children: [
1698
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1699
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SendIcon, {}) })
1428
1700
  ] });
1429
1701
  }
1430
1702
 
1431
1703
  // src/components/ChatPanel.tsx
1432
- var import_jsx_runtime21 = require("react/jsx-runtime");
1704
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1433
1705
  var FULLSCREEN_QUERY = "(max-width: 639px)";
1434
1706
  function useIsModal() {
1435
- const [modal, setModal] = (0, import_react10.useState)(false);
1436
- (0, import_react10.useEffect)(() => {
1707
+ const [modal, setModal] = (0, import_react11.useState)(false);
1708
+ (0, import_react11.useEffect)(() => {
1437
1709
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1438
1710
  const mql = window.matchMedia(FULLSCREEN_QUERY);
1439
1711
  const sync = () => setModal(mql.matches);
@@ -1446,17 +1718,17 @@ function useIsModal() {
1446
1718
  function ChatPanel({ controller, ui, slip, onDashboardTap }) {
1447
1719
  const { state, close, stop, send } = controller;
1448
1720
  const isModal = useIsModal();
1449
- (0, import_react10.useEffect)(() => {
1721
+ (0, import_react11.useEffect)(() => {
1450
1722
  const onKey = (e) => {
1451
1723
  if (e.key === "Escape") close();
1452
1724
  };
1453
1725
  window.addEventListener("keydown", onKey);
1454
1726
  return () => window.removeEventListener("keydown", onKey);
1455
1727
  }, [close]);
1456
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1457
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1458
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1459
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1728
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1729
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1730
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1731
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1460
1732
  ] });
1461
1733
  }
1462
1734
 
@@ -1809,10 +2081,122 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1809
2081
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }
1810
2082
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
1811
2083
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
2084
+
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); }
1812
2196
  `;
1813
2197
 
1814
2198
  // src/StatsWidget.tsx
1815
- var import_jsx_runtime22 = require("react/jsx-runtime");
2199
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1816
2200
  function buildClient(props) {
1817
2201
  try {
1818
2202
  if ("client" in props && props.client) {
@@ -1837,11 +2221,11 @@ function injectStyles(root) {
1837
2221
  function StatsWidget(props) {
1838
2222
  const injectedClient = "client" in props ? props.client : void 0;
1839
2223
  const cfg = props.config;
1840
- const built = (0, import_react11.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
1841
- const ui = (0, import_react11.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
1842
- const rootRef = (0, import_react11.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);
1843
2227
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
1844
- const slip = (0, import_react11.useMemo)(
2228
+ const slip = (0, import_react12.useMemo)(
1845
2229
  () => ({
1846
2230
  onAddToSlip: props.config?.onAddToSlip,
1847
2231
  conversationId: controller.state.conversationId ?? void 0,
@@ -1854,18 +2238,18 @@ function StatsWidget(props) {
1854
2238
  }),
1855
2239
  [props.config?.onAddToSlip, controller.state.conversationId, built]
1856
2240
  );
1857
- const onDashboardTap = (0, import_react11.useMemo)(
2241
+ const onDashboardTap = (0, import_react12.useMemo)(
1858
2242
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
1859
2243
  [built]
1860
2244
  );
1861
- (0, import_react11.useEffect)(() => {
2245
+ (0, import_react12.useEffect)(() => {
1862
2246
  if (!built || !ui.injectStyles) return;
1863
2247
  const node = rootRef.current?.getRootNode();
1864
2248
  if (node) injectStyles(node);
1865
2249
  }, [built, ui.injectStyles]);
1866
2250
  if (!built) return null;
1867
2251
  const attrs = themeAttrs(ui);
1868
- return /* @__PURE__ */ (0, import_jsx_runtime22.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_runtime22.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2252
+ return /* @__PURE__ */ (0, import_jsx_runtime31.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_runtime31.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1869
2253
  ChatFab,
1870
2254
  {
1871
2255
  label: ui.launcherLabel,