@sensiblestats/widget-react 0.14.0 → 0.15.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_react10 = require("react");
39
+ var import_react12 = require("react");
40
40
  var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
41
41
 
42
42
  // src/i18n.ts
@@ -79,6 +79,12 @@ var STRINGS = {
79
79
  const drift = direction ? `, ${direction}` : "";
80
80
  return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`;
81
81
  },
82
+ clubMatchPreviewHeading: "Match preview",
83
+ clubTeamDnaHeading: "How they play",
84
+ clubFormHeading: "Recent form",
85
+ clubCountdownLabel: "Countdown to kick-off",
86
+ clubKickoff: (ms) => new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
87
+ 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))}`,
82
88
  inSlip: "In slip",
83
89
  slipAdded: (n) => n === void 0 ? "Added to slip" : `Added to slip (${n} selection${n === 1 ? "" : "s"})`,
84
90
  slipDuplicate: "Already in your slip",
@@ -126,6 +132,12 @@ var STRINGS = {
126
132
  const drift = direction ? `, ${direction}` : "";
127
133
  return `Son ${span} i\xE7indeki oran hareketi: ${opening} ile a\xE7\u0131ld\u0131, \u015Fu anda ${current}${drift}.`;
128
134
  },
135
+ clubMatchPreviewHeading: "Ma\xE7 \xF6nizlemesi",
136
+ clubTeamDnaHeading: "Nas\u0131l oynuyorlar",
137
+ clubFormHeading: "Son form",
138
+ clubCountdownLabel: "Ba\u015Flama vuru\u015Funa kalan",
139
+ clubKickoff: (ms) => new Intl.DateTimeFormat("tr-TR", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" }).format(new Date(ms)),
140
+ 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))}`,
129
141
  inSlip: "Kuponda",
130
142
  slipAdded: (n) => n === void 0 ? "Kupona eklendi" : `Kupona eklendi (${n} se\xE7im)`,
131
143
  slipDuplicate: "Bu se\xE7im kuponunuzda zaten var",
@@ -185,6 +197,12 @@ function normalizeUi(cfg) {
185
197
  excludedSuspended: strings.excludedSuspended,
186
198
  chartTimeLabel: strings.chartTimeLabel,
187
199
  chartAria: strings.chartAria,
200
+ clubMatchPreviewHeading: strings.clubMatchPreviewHeading,
201
+ clubTeamDnaHeading: strings.clubTeamDnaHeading,
202
+ clubFormHeading: strings.clubFormHeading,
203
+ clubCountdownLabel: strings.clubCountdownLabel,
204
+ clubKickoff: strings.clubKickoff,
205
+ clubKickoffAria: strings.clubKickoffAria,
188
206
  addToSlip: strings.addToSlip,
189
207
  inSlip: strings.inSlip,
190
208
  slipAdded: strings.slipAdded,
@@ -531,7 +549,8 @@ function applyEvent(state, event) {
531
549
  messages: mapActive(state, (t) => ({
532
550
  ...t,
533
551
  done: true,
534
- greetingDashboard: event.data.dashboard ?? void 0
552
+ greetingDashboard: event.data.dashboard ?? void 0,
553
+ clubDashboard: event.data.clubDashboard ?? void 0
535
554
  }))
536
555
  };
537
556
  }
@@ -655,88 +674,27 @@ function SendIcon() {
655
674
  function CloseIcon() {
656
675
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2" }) });
657
676
  }
658
- function FootballIcon() {
659
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
660
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
661
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 7l3.5 2.5-1.3 4.1H9.8L8.5 9.5z" })
662
- ] });
663
- }
664
- function GoalNetIcon() {
665
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
666
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "5", width: "18", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
667
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1", d: "M3 9h18M3 13h18M8 5v12M16 5v12" })
668
- ] });
669
- }
670
- function BttsIcon() {
671
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
672
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
673
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "16", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
674
- ] });
675
- }
676
- function CardIcon() {
677
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "6", y: "3", width: "12", height: "18", rx: "1.5", fill: "currentColor" }) });
678
- }
679
- function CornerFlagIcon() {
680
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
681
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.6", d: "M6 21V4" }),
682
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M6 4l11 3.5L6 11z" })
683
- ] });
684
- }
685
- function PlayerIcon() {
686
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
687
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "7", r: "3.2", fill: "currentColor" }),
688
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M5 20c0-4 3-6.5 7-6.5s7 2.5 7 6.5z" })
689
- ] });
690
- }
691
- function TargetIcon() {
692
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
693
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
694
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
695
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "1.4", fill: "currentColor" })
696
- ] });
697
- }
698
- function TrophyIcon() {
699
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: [
700
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M7 3h10v4a5 5 0 0 1-5 5 5 5 0 0 1-5-5zM9 15h6v3H9zM7 19h10v2H7z" }),
701
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.4", d: "M7 5H4v2a3 3 0 0 0 3 3M17 5h3v2a3 3 0 0 1-3 3" })
702
- ] });
703
- }
704
- function ChartLineIcon() {
705
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", d: "M4 17l5-6 4 3 7-9" }) });
706
- }
707
- function ChartBarIcon() {
708
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M5 12h3v8H5zM10.5 7h3v13h-3zM16 15h3v5h-3z" }) });
709
- }
710
- function ChatIcon() {
711
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "1.6", d: "M4 5h16v11H9l-4 4z" }) });
712
- }
713
- function FireIcon() {
714
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 2c1 3-2 4-2 7a3 3 0 0 0 6 0c1 1 2 2.5 2 4.5A6 6 0 0 1 6 14c0-4 3-5 3-9 1 1 1.5 2 1.5 3C11.5 6 11 4 12 2z" }) });
715
- }
716
- function SparkleIcon() {
717
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M12 2l1.6 6.4L20 10l-6.4 1.6L12 18l-1.6-6.4L4 10l6.4-1.6z" }) });
718
- }
719
677
  function ChevronIcon() {
720
678
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
721
679
  }
722
- var DASHBOARD_ICONS = {
723
- football: FootballIcon,
724
- "goal-net": GoalNetIcon,
725
- btts: BttsIcon,
726
- card: CardIcon,
727
- "corner-flag": CornerFlagIcon,
728
- player: PlayerIcon,
729
- target: TargetIcon,
730
- trophy: TrophyIcon,
731
- "chart-line": ChartLineIcon,
732
- "chart-bar": ChartBarIcon,
733
- chat: ChatIcon,
734
- fire: FireIcon,
735
- sparkle: SparkleIcon
680
+ var DASHBOARD_EMOJI = {
681
+ football: "\u26BD",
682
+ "goal-net": "\u{1F945}",
683
+ btts: "\u{1F91D}",
684
+ card: "\u{1F7E8}",
685
+ "corner-flag": "\u{1F6A9}",
686
+ player: "\u{1F464}",
687
+ target: "\u{1F3AF}",
688
+ trophy: "\u{1F3C6}",
689
+ "chart-line": "\u{1F4C8}",
690
+ "chart-bar": "\u{1F4CA}",
691
+ chat: "\u{1F4AC}",
692
+ fire: "\u{1F525}",
693
+ sparkle: "\u2728"
736
694
  };
737
695
  function DashboardIcon({ name }) {
738
- const Glyph = DASHBOARD_ICONS[name] ?? TargetIcon;
739
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Glyph, {});
696
+ const glyph = Object.prototype.hasOwnProperty.call(DASHBOARD_EMOJI, name) ? DASHBOARD_EMOJI[name] : DASHBOARD_EMOJI.target;
697
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ss-w-dash-emoji", "aria-hidden": "true", children: glyph });
740
698
  }
741
699
 
742
700
  // src/components/GreetingBubble.tsx
@@ -759,7 +717,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
759
717
  }
760
718
 
761
719
  // src/components/ChatPanel.tsx
762
- var import_react9 = require("react");
720
+ var import_react11 = require("react");
763
721
 
764
722
  // src/components/ChatHeader.tsx
765
723
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -772,7 +730,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
772
730
  }
773
731
 
774
732
  // src/components/MessageList.tsx
775
- var import_react7 = require("react");
733
+ var import_react9 = require("react");
776
734
 
777
735
  // src/components/Markdown.tsx
778
736
  var import_react_markdown = __toESM(require("react-markdown"), 1);
@@ -1256,28 +1214,184 @@ function GreetingDashboard({ dashboard, onTap }) {
1256
1214
  ] });
1257
1215
  }
1258
1216
 
1259
- // src/components/ChatMessage.tsx
1217
+ // src/components/club-dashboard/GreetingHeaderBlock.tsx
1260
1218
  var import_jsx_runtime16 = require("react/jsx-runtime");
1261
- function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
1219
+ function GreetingHeaderBlock({ block }) {
1220
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
1221
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1222
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1223
+ ] });
1224
+ }
1225
+
1226
+ // src/components/club-dashboard/FixtureHeroBlock.tsx
1227
+ var import_react7 = require("react");
1228
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1229
+ function initials2(name) {
1230
+ return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
1231
+ }
1232
+ function Crest2({ url, name }) {
1233
+ const [broken, setBroken] = (0, import_react7.useState)(false);
1234
+ if (!url || broken) {
1235
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials2(name) });
1236
+ }
1237
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1238
+ }
1239
+ function FixtureHeroBlock({
1240
+ block,
1241
+ ui,
1242
+ onAction
1243
+ }) {
1244
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
1245
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-tie", children: [
1246
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.homeCrestUrl, name: block.homeName }),
1247
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
1248
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
1249
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
1250
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest2, { url: block.awayCrestUrl, name: block.awayName })
1251
+ ] }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
1253
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1254
+ block.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1255
+ block.competition ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1256
+ ] }),
1257
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, block.ctaLabel), children: block.ctaLabel })
1258
+ ] });
1259
+ }
1260
+
1261
+ // src/components/club-dashboard/FormGuideBlock.tsx
1262
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1263
+ function FormGuideBlock({ block }) {
1264
+ if (block.rows.length === 0) return null;
1265
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
1266
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
1267
+ row.name,
1268
+ row.position != null ? ` #${row.position}` : ""
1269
+ ] }),
1270
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
1271
+ ] }, row.name)) });
1272
+ }
1273
+
1274
+ // src/components/club-dashboard/MatchPreviewBlock.tsx
1275
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1276
+ function MatchPreviewBlock({
1277
+ block,
1278
+ ui,
1279
+ onAction
1280
+ }) {
1281
+ if (block.lines.length === 0) return null;
1282
+ const heading = ui.clubMatchPreviewHeading;
1283
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1285
+ block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: line }, i))
1286
+ ] });
1287
+ }
1288
+
1289
+ // src/components/club-dashboard/TeamDnaBlock.tsx
1290
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1291
+ function TeamDnaBlock({
1292
+ block,
1293
+ ui,
1294
+ onAction
1295
+ }) {
1296
+ if (block.lines.length === 0) return null;
1297
+ const heading = ui.clubTeamDnaHeading;
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
1299
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1300
+ block.lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: line }, i))
1301
+ ] });
1302
+ }
1303
+
1304
+ // src/components/club-dashboard/CountdownBlock.tsx
1305
+ var import_react8 = require("react");
1306
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1307
+ var DAY_MS = 24 * 3600 * 1e3;
1308
+ function pad2(n) {
1309
+ return String(n).padStart(2, "0");
1310
+ }
1311
+ function splitRemaining(remainingMs) {
1312
+ const totalSeconds = Math.max(0, Math.floor(remainingMs / 1e3));
1313
+ const h = Math.floor(totalSeconds / 3600);
1314
+ const m = Math.floor(totalSeconds % 3600 / 60);
1315
+ const s = totalSeconds % 60;
1316
+ return { h: pad2(h), m: pad2(m), s: pad2(s) };
1317
+ }
1318
+ function CountdownBlock({ block, ui }) {
1319
+ const [remainingMs, setRemainingMs] = (0, import_react8.useState)(() => block.kickoffUnix * 1e3 - Date.now());
1320
+ (0, import_react8.useEffect)(() => {
1321
+ setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1322
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
1323
+ const id = setInterval(() => {
1324
+ setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1325
+ }, 1e3);
1326
+ return () => clearInterval(id);
1327
+ }, [block.kickoffUnix]);
1328
+ if (remainingMs <= 0) return null;
1329
+ if (remainingMs > DAY_MS) return null;
1330
+ const { h, m, s } = splitRemaining(remainingMs);
1331
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
1332
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
1333
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
1334
+ "h",
1335
+ " ",
1336
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
1337
+ "m",
1338
+ " ",
1339
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
1340
+ "s"
1341
+ ] }),
1342
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1343
+ ] });
1344
+ }
1345
+
1346
+ // src/components/club-dashboard/ClubDashboard.tsx
1347
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1348
+ var CLUB_BLOCK_REGISTRY = {
1349
+ greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GreetingHeaderBlock, { block }) : null,
1350
+ fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
1351
+ formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FormGuideBlock, { block, ui }) : null,
1352
+ matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
1353
+ teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
1354
+ countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CountdownBlock, { block, ui }) : null
1355
+ };
1356
+ function ClubDashboard({
1357
+ dashboard,
1358
+ ui,
1359
+ onAction
1360
+ }) {
1361
+ if (!dashboard.blocks.length) return null;
1362
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1363
+ const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
1364
+ if (!Comp) {
1365
+ console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
1366
+ return null;
1367
+ }
1368
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp, { block, ui, onAction }) }, i);
1369
+ }) });
1370
+ }
1371
+
1372
+ // src/components/ChatMessage.tsx
1373
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1374
+ function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
1262
1375
  if (message.role === "user") {
1263
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1376
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1264
1377
  }
1265
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1266
- message.text ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Markdown, { text: message.text }) : null,
1267
- message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1268
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1269
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1270
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1271
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1272
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1378
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1379
+ message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Markdown, { text: message.text }) : null,
1380
+ message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1381
+ message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1382
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1383
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1384
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1385
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1386
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1273
1387
  ] });
1274
1388
  }
1275
1389
 
1276
1390
  // src/components/IntentChips.tsx
1277
- var import_jsx_runtime17 = require("react/jsx-runtime");
1391
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1278
1392
  function IntentChips({ chips, onPick }) {
1279
1393
  if (chips.length === 0) return null;
1280
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1394
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1281
1395
  }
1282
1396
 
1283
1397
  // src/scroll.ts
@@ -1287,18 +1401,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1287
1401
  }
1288
1402
 
1289
1403
  // src/components/MessageList.tsx
1290
- var import_jsx_runtime18 = require("react/jsx-runtime");
1404
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1291
1405
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1292
1406
  const { state, send } = controller;
1293
- const listRef = (0, import_react7.useRef)(null);
1294
- const endRef = (0, import_react7.useRef)(null);
1295
- const pinnedRef = (0, import_react7.useRef)(true);
1296
- (0, import_react7.useEffect)(() => {
1407
+ const listRef = (0, import_react9.useRef)(null);
1408
+ const endRef = (0, import_react9.useRef)(null);
1409
+ const pinnedRef = (0, import_react9.useRef)(true);
1410
+ (0, import_react9.useEffect)(() => {
1297
1411
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
1298
1412
  }, [state.messages, state.status]);
1299
1413
  const hasUserMessage = state.messages.some((m) => m.role === "user");
1300
1414
  const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
1301
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1415
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1302
1416
  "div",
1303
1417
  {
1304
1418
  className: "ss-w-list",
@@ -1308,7 +1422,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1308
1422
  if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
1309
1423
  },
1310
1424
  children: [
1311
- state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1425
+ state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1312
1426
  ChatMessage,
1313
1427
  {
1314
1428
  message: m,
@@ -1318,30 +1432,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1318
1432
  send(tile.actionValue, { displayText: tile.title });
1319
1433
  if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
1320
1434
  },
1435
+ onClubAction: (actionValue, displayText) => send(actionValue, { displayText }),
1321
1436
  ui,
1322
1437
  slip
1323
1438
  },
1324
1439
  m.id
1325
1440
  )),
1326
- state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1441
+ state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1327
1442
  } }) : null,
1328
- state.status ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1329
- state.error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1330
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1331
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1443
+ state.status ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1444
+ state.error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1445
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1446
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1332
1447
  ] }) : null,
1333
- !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1334
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { ref: endRef })
1448
+ !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1449
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: endRef })
1335
1450
  ]
1336
1451
  }
1337
1452
  );
1338
1453
  }
1339
1454
 
1340
1455
  // src/components/ChatInput.tsx
1341
- var import_react8 = require("react");
1342
- var import_jsx_runtime19 = require("react/jsx-runtime");
1456
+ var import_react10 = require("react");
1457
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1343
1458
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
1344
- const [value, setValue] = (0, import_react8.useState)("");
1459
+ const [value, setValue] = (0, import_react10.useState)("");
1345
1460
  const submit = () => {
1346
1461
  const t = value.trim();
1347
1462
  if (!t) return;
@@ -1354,18 +1469,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
1354
1469
  submit();
1355
1470
  }
1356
1471
  };
1357
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-input", children: [
1358
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1359
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SendIcon, {}) })
1472
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-input", children: [
1473
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1474
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendIcon, {}) })
1360
1475
  ] });
1361
1476
  }
1362
1477
 
1363
1478
  // src/components/ChatPanel.tsx
1364
- var import_jsx_runtime20 = require("react/jsx-runtime");
1479
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1365
1480
  var FULLSCREEN_QUERY = "(max-width: 639px)";
1366
1481
  function useIsModal() {
1367
- const [modal, setModal] = (0, import_react9.useState)(false);
1368
- (0, import_react9.useEffect)(() => {
1482
+ const [modal, setModal] = (0, import_react11.useState)(false);
1483
+ (0, import_react11.useEffect)(() => {
1369
1484
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1370
1485
  const mql = window.matchMedia(FULLSCREEN_QUERY);
1371
1486
  const sync = () => setModal(mql.matches);
@@ -1378,17 +1493,17 @@ function useIsModal() {
1378
1493
  function ChatPanel({ controller, ui, slip, onDashboardTap }) {
1379
1494
  const { state, close, stop, send } = controller;
1380
1495
  const isModal = useIsModal();
1381
- (0, import_react9.useEffect)(() => {
1496
+ (0, import_react11.useEffect)(() => {
1382
1497
  const onKey = (e) => {
1383
1498
  if (e.key === "Escape") close();
1384
1499
  };
1385
1500
  window.addEventListener("keydown", onKey);
1386
1501
  return () => window.removeEventListener("keydown", onKey);
1387
1502
  }, [close]);
1388
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1389
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1390
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1391
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1503
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1504
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1505
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1506
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1392
1507
  ] });
1393
1508
  }
1394
1509
 
@@ -1665,7 +1780,8 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1665
1780
  min-width: 0; /* the panel is min(400px, 100vw - 40px): without this,
1666
1781
  a long Turkish title blows the column out */
1667
1782
  }
1668
- .ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 20px; height: 20px; color: var(--ss-w-accent); font-size: 18px; }
1783
+ .ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 28px; height: 28px; font-size: 22px; }
1784
+ .ss-w-dash-emoji { line-height: 1; }
1669
1785
  .ss-w-dash-tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }
1670
1786
  .ss-w-dash-tile-title { min-width: 0; font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }
1671
1787
  .ss-w-dash-tile-subtitle { min-width: 0; font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }
@@ -1695,15 +1811,63 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1695
1811
  .ss-w-dash--goal .ss-w-dash-grid { grid-template-columns: 1fr; }
1696
1812
  .ss-w-dash--goal .ss-w-dash-tile { border-radius: 999px; padding: 10px 14px; }
1697
1813
 
1698
- /* Discovery: tinted bento cards. */
1814
+ /* Discovery: tinted bento cards. Stacked (icon over text) so a two- or three-word title gets
1815
+ the tile's full width instead of the ~100px left of a horizontal icon+chevron -- that narrow
1816
+ column was wrapping "Most interesting angles" onto three lines. The chevron is dropped (the
1817
+ whole card is the tap target) and the badge + crest row is forced onto one line. */
1818
+ .ss-w-dash--discovery .ss-w-dash-tile { flex-direction: column; align-items: stretch; gap: 8px; }
1819
+ .ss-w-dash--discovery .ss-w-dash-tile-icon { align-self: flex-start; width: 32px; height: 32px; font-size: 26px; }
1820
+ .ss-w-dash--discovery .ss-w-dash-tile-chevron { display: none; }
1821
+ /* The full-span trends tile has the whole panel width, so its icon and title sit on one row
1822
+ (horizontal, centre-aligned) rather than stacking like the narrow half tiles. */
1823
+ .ss-w-dash--discovery .ss-w-dash-tile--full { flex-direction: row; align-items: center; }
1824
+ .ss-w-dash--discovery .ss-w-dash-tile--full .ss-w-dash-tile-icon { align-self: center; }
1825
+ .ss-w-dash--discovery .ss-w-dash-tile-meta { flex-wrap: nowrap; }
1826
+ .ss-w-dash--discovery .ss-w-dash-tile-crest { width: 22px; height: 22px; }
1699
1827
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: #eef8f1; }
1700
1828
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }
1701
1829
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }
1702
1830
  .ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }
1831
+
1832
+ /* club match-day dashboard */
1833
+ .ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
1834
+ .ss-w-cdash-block { display: flex; flex-direction: column; }
1835
+
1836
+ .ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }
1837
+ .ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }
1838
+ .ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }
1839
+
1840
+ .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; }
1841
+ .ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
1842
+ .ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
1843
+ .ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }
1844
+ .ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }
1845
+ .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)); }
1846
+ .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); }
1847
+ .ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }
1848
+ .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; }
1849
+
1850
+ .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; }
1851
+ .ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
1852
+ .ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }
1853
+ .ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }
1854
+ .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; }
1855
+ .ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }
1856
+ .ss-w-cdash-pill--d { background: var(--ss-w-faint); }
1857
+ .ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
1858
+
1859
+ .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; font: inherit; cursor: pointer; }
1860
+ .ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
1861
+ .ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); }
1862
+
1863
+ .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; }
1864
+ .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); }
1865
+ .ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }
1866
+ .ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }
1703
1867
  `;
1704
1868
 
1705
1869
  // src/StatsWidget.tsx
1706
- var import_jsx_runtime21 = require("react/jsx-runtime");
1870
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1707
1871
  function buildClient(props) {
1708
1872
  try {
1709
1873
  if ("client" in props && props.client) {
@@ -1728,11 +1892,11 @@ function injectStyles(root) {
1728
1892
  function StatsWidget(props) {
1729
1893
  const injectedClient = "client" in props ? props.client : void 0;
1730
1894
  const cfg = props.config;
1731
- const built = (0, import_react10.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
1732
- const ui = (0, import_react10.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
1733
- const rootRef = (0, import_react10.useRef)(null);
1895
+ const built = (0, import_react12.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
1896
+ const ui = (0, import_react12.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
1897
+ const rootRef = (0, import_react12.useRef)(null);
1734
1898
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
1735
- const slip = (0, import_react10.useMemo)(
1899
+ const slip = (0, import_react12.useMemo)(
1736
1900
  () => ({
1737
1901
  onAddToSlip: props.config?.onAddToSlip,
1738
1902
  conversationId: controller.state.conversationId ?? void 0,
@@ -1745,18 +1909,18 @@ function StatsWidget(props) {
1745
1909
  }),
1746
1910
  [props.config?.onAddToSlip, controller.state.conversationId, built]
1747
1911
  );
1748
- const onDashboardTap = (0, import_react10.useMemo)(
1912
+ const onDashboardTap = (0, import_react12.useMemo)(
1749
1913
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
1750
1914
  [built]
1751
1915
  );
1752
- (0, import_react10.useEffect)(() => {
1916
+ (0, import_react12.useEffect)(() => {
1753
1917
  if (!built || !ui.injectStyles) return;
1754
1918
  const node = rootRef.current?.getRootNode();
1755
1919
  if (node) injectStyles(node);
1756
1920
  }, [built, ui.injectStyles]);
1757
1921
  if (!built) return null;
1758
1922
  const attrs = themeAttrs(ui);
1759
- return /* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1923
+ return /* @__PURE__ */ (0, import_jsx_runtime28.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_runtime28.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1760
1924
  ChatFab,
1761
1925
  {
1762
1926
  label: ui.launcherLabel,