@sensiblestats/widget-react 0.18.0 → 0.20.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_react12 = require("react");
39
+ var import_react13 = require("react");
40
40
  var import_widget_sdk5 = require("@sensiblestats/widget-sdk");
41
41
 
42
42
  // src/kickoff.ts
@@ -472,7 +472,13 @@ function toMarketOddsVM(card) {
472
472
  id: `${typeof card.matchId === "number" ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ""}`,
473
473
  market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? "",
474
474
  fixture: home && away ? `${home} vs ${away}` : void 0,
475
+ homeTeamName: home,
476
+ awayTeamName: away,
477
+ homeCrest: str(card.homeTeamImagePath),
478
+ awayCrest: str(card.awayTeamImagePath),
479
+ competitionCrest: str(card.competitionImagePath),
475
480
  competition: str(card.competitionName),
481
+ kickoffUtc: str(card.kickoffUtc),
476
482
  bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),
477
483
  updatedAt: updated.length > 0 ? updated[updated.length - 1] : void 0,
478
484
  isLive: rows.some((r) => r.isLive === true),
@@ -619,21 +625,42 @@ function reducer(state, action) {
619
625
  }
620
626
 
621
627
  // src/useChatStream.ts
628
+ var STREAM_FALLBACK_TIMEOUT_MS = 3e4;
622
629
  function useChatStream(conversation, starterTexts, greetingMessage) {
623
630
  const seed = (0, import_react.useMemo)(() => initialState(starterTexts.map(chipFromText)), []);
624
631
  const [state, dispatch] = (0, import_react.useReducer)(reducer, seed);
625
632
  const idRef = (0, import_react.useRef)(0);
626
633
  const handleRef = (0, import_react.useRef)(null);
634
+ const fallbackTimerRef = (0, import_react.useRef)(null);
627
635
  const stateRef = (0, import_react.useRef)(state);
628
636
  stateRef.current = state;
629
637
  const greetedRef = (0, import_react.useRef)(false);
630
638
  const nextId = () => `m${idRef.current++}`;
639
+ const clearFallbackTimer = (0, import_react.useCallback)(() => {
640
+ if (fallbackTimerRef.current != null) {
641
+ clearTimeout(fallbackTimerRef.current);
642
+ fallbackTimerRef.current = null;
643
+ }
644
+ }, []);
645
+ const armFallbackTimer = (0, import_react.useCallback)((onFire) => {
646
+ clearFallbackTimer();
647
+ fallbackTimerRef.current = setTimeout(() => {
648
+ fallbackTimerRef.current = null;
649
+ handleRef.current?.cancel();
650
+ handleRef.current = null;
651
+ onFire();
652
+ }, STREAM_FALLBACK_TIMEOUT_MS);
653
+ }, [clearFallbackTimer]);
631
654
  const consume = (0, import_react.useCallback)((handle, onError) => {
632
655
  ;
633
656
  (async () => {
634
657
  try {
635
- for await (const event of handle) dispatch({ kind: "EVENT", event });
658
+ for await (const event of handle) {
659
+ dispatch({ kind: "EVENT", event });
660
+ if (event.type === "turn_complete" || event.type === "error") clearFallbackTimer();
661
+ }
636
662
  } catch (err) {
663
+ if (handleRef.current === handle) clearFallbackTimer();
637
664
  if (err instanceof import_widget_sdk3.WidgetSdkError) onError(err);
638
665
  else if (err?.name === "AbortError") {
639
666
  } else throw err;
@@ -641,18 +668,23 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
641
668
  if (handleRef.current === handle) handleRef.current = null;
642
669
  }
643
670
  })();
644
- }, []);
671
+ }, [clearFallbackTimer]);
645
672
  const run = (0, import_react.useCallback)((input, displayText) => {
646
673
  handleRef.current?.cancel();
674
+ clearFallbackTimer();
647
675
  dispatch({ kind: "USER_SENT", input, userId: nextId(), assistantId: nextId(), displayText });
648
676
  const handle = conversation.send(input);
649
677
  handleRef.current = handle;
678
+ armFallbackTimer(() => {
679
+ dispatch({ kind: "STOP" });
680
+ dispatch({ kind: "STREAM_ERROR", error: new import_widget_sdk3.WidgetSdkError("No response received in time", "timeout") });
681
+ });
650
682
  consume(handle, (err) => dispatch({ kind: "STREAM_ERROR", error: err }));
651
- }, [conversation, consume]);
683
+ }, [conversation, consume, clearFallbackTimer, armFallbackTimer]);
652
684
  const send = (0, import_react.useCallback)((text, opts) => {
653
685
  const trimmed = text.trim();
654
686
  if (!trimmed) return;
655
- run({ message: trimmed, actionId: opts?.actionId, grounding: opts?.grounding }, opts?.displayText);
687
+ run({ message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef }, opts?.displayText);
656
688
  }, [run]);
657
689
  const retry = (0, import_react.useCallback)(() => {
658
690
  const last = stateRef.current.lastUserInput;
@@ -664,25 +696,29 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
664
696
  greetedRef.current = true;
665
697
  try {
666
698
  handleRef.current?.cancel();
699
+ clearFallbackTimer();
667
700
  dispatch({ kind: "GREETING_SENT", assistantId: nextId() });
668
701
  const handle = conversation.send({ message });
669
702
  handleRef.current = handle;
703
+ armFallbackTimer(() => dispatch({ kind: "STOP" }));
670
704
  consume(handle, () => dispatch({ kind: "STOP" }));
671
705
  } catch {
672
706
  dispatch({ kind: "STOP" });
673
707
  }
674
- }, [greetingMessage, conversation, consume]);
708
+ }, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer]);
675
709
  const open = (0, import_react.useCallback)(() => dispatch({ kind: "OPEN" }), []);
676
710
  const close = (0, import_react.useCallback)(() => {
677
711
  handleRef.current?.cancel();
678
712
  handleRef.current = null;
713
+ clearFallbackTimer();
679
714
  dispatch({ kind: "CLOSE" });
680
- }, []);
715
+ }, [clearFallbackTimer]);
681
716
  const stop = (0, import_react.useCallback)(() => {
682
717
  handleRef.current?.cancel();
683
718
  handleRef.current = null;
719
+ clearFallbackTimer();
684
720
  dispatch({ kind: "STOP" });
685
- }, []);
721
+ }, [clearFallbackTimer]);
686
722
  const toggle = (0, import_react.useCallback)(() => {
687
723
  if (stateRef.current.isOpen) close();
688
724
  else open();
@@ -748,7 +784,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
748
784
  }
749
785
 
750
786
  // src/components/ChatPanel.tsx
751
- var import_react11 = require("react");
787
+ var import_react12 = require("react");
752
788
 
753
789
  // src/components/ChatHeader.tsx
754
790
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -761,7 +797,7 @@ function ChatHeader({ onClose, closeLabel = "Close chat" }) {
761
797
  }
762
798
 
763
799
  // src/components/MessageList.tsx
764
- var import_react9 = require("react");
800
+ var import_react10 = require("react");
765
801
 
766
802
  // src/components/Markdown.tsx
767
803
  var import_react_markdown = __toESM(require("react-markdown"), 1);
@@ -881,7 +917,7 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
881
917
  }
882
918
 
883
919
  // src/components/BettingInsightList.tsx
884
- var import_react5 = require("react");
920
+ var import_react6 = require("react");
885
921
 
886
922
  // src/components/AddToSlipButton.tsx
887
923
  var import_react4 = require("react");
@@ -1004,53 +1040,64 @@ function OddsMovementBadge({
1004
1040
  ] });
1005
1041
  }
1006
1042
 
1007
- // src/components/BettingInsightList.tsx
1043
+ // src/components/Crest.tsx
1044
+ var import_react5 = require("react");
1008
1045
  var import_jsx_runtime10 = require("react/jsx-runtime");
1046
+ function initials2(name) {
1047
+ return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
1048
+ }
1049
+ function Crest2({ url, name, kind }) {
1050
+ const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
1051
+ const [failed, setFailed] = (0, import_react5.useState)(false);
1052
+ if (url && !failed) {
1053
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
1054
+ }
1055
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
1056
+ }
1057
+
1058
+ // src/components/BettingInsightList.tsx
1059
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1009
1060
  function StatRows2({ stats }) {
1010
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-row", children: [
1011
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
1012
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
1061
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-row", children: [
1062
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-lbl", children: s.label }),
1063
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-row-num", children: s.value })
1013
1064
  ] }, `${s.label}:${s.value}`)) });
1014
1065
  }
1015
1066
  function ScopedStats({ scopes }) {
1016
- const [active, setActive] = (0, import_react5.useState)(0);
1067
+ const [active, setActive] = (0, import_react6.useState)(0);
1017
1068
  const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
1018
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-scoped", children: [
1019
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
1020
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StatRows2, { stats: current.stats }, current.key)
1069
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-scoped", children: [
1070
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
1071
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: current.stats }, current.key)
1021
1072
  ] });
1022
1073
  }
1023
1074
  function hasStatsContent(it) {
1024
1075
  return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
1025
1076
  }
1026
- function initials2(name) {
1027
- return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
1028
- }
1029
- function Crest2({ url, name, kind }) {
1030
- const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
1031
- if (url) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cls, style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" });
1032
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
1033
- }
1034
- function StatsDisclosure({ it, ui }) {
1035
- const [open, setOpen] = (0, import_react5.useState)(false);
1077
+ function ReasonStrip({ it, ui }) {
1078
+ const [open, setOpen] = (0, import_react6.useState)(false);
1036
1079
  const hasScopes = !!it.scopes && it.scopes.length >= 2;
1037
1080
  const hasStats = hasStatsContent(it);
1038
- if (!hasStats) return null;
1039
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-stats", children: [
1040
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1081
+ const hasText = !!it.text;
1082
+ if (!hasText && !hasStats) return null;
1083
+ const expandable = hasStats || (it.text?.length ?? 0) > 90;
1084
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason", children: [
1085
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
1087
+ hasText ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
1088
+ open && hasStats ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StatRows2, { stats: it.stats }) : null
1089
+ ] }),
1090
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1041
1091
  "button",
1042
1092
  {
1043
1093
  type: "button",
1044
- className: "ss-w-bi-toggle",
1094
+ className: "ss-w-bi-expand",
1045
1095
  "aria-expanded": open,
1096
+ "aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
1046
1097
  onClick: () => setOpen((v) => !v),
1047
- children: [
1048
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats" }),
1049
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
1050
- ]
1098
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
1051
1099
  }
1052
- ),
1053
- open ? hasScopes ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StatRows2, { stats: it.stats }) : null
1100
+ ) : null
1054
1101
  ] });
1055
1102
  }
1056
1103
  function InsightCard({ it, ui, slip }) {
@@ -1058,105 +1105,119 @@ function InsightCard({ it, ui, slip }) {
1058
1105
  const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
1059
1106
  const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
1060
1107
  const showHeader = !!it.competition || live || !!kickoff;
1061
- const showReason = !!it.text || hasStatsContent(it);
1062
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-binsight", children: [
1063
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-header", children: [
1064
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1065
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
1066
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-comp", children: it.competition })
1108
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-binsight", children: [
1109
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-header", children: [
1110
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1111
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-comp", children: it.competition })
1067
1113
  ] }) : null }),
1068
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-header-right", children: [
1069
- live ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-live", children: [
1070
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1114
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-header-right", children: [
1115
+ live ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-live", children: [
1116
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1071
1117
  ui?.liveLabel ?? "Live"
1072
1118
  ] }) : null,
1073
- kickoff ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-kick", children: [
1119
+ kickoff ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-kick", children: [
1074
1120
  kickoff.dayLabel,
1075
1121
  " ",
1076
1122
  kickoff.time
1077
1123
  ] }) : null
1078
1124
  ] })
1079
1125
  ] }) : null,
1080
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-body", children: [
1081
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1082
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
1083
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
1084
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1085
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
1086
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
1087
- ] }) : it.fixture ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
1088
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-action", children: [
1089
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-mkt", children: [
1090
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
1091
- it.selection ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-sel", children: it.selection }) : null
1126
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-body", children: [
1127
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1128
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
1129
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
1130
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1131
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
1132
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
1133
+ ] }) : it.fixture ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
1134
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-bi-action", children: [
1135
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-mkt", children: [
1136
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-market", children: it.market }),
1137
+ it.selection ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-sel", children: it.selection }) : null
1092
1138
  ] }),
1093
- it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
1094
- it.odds ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ss-w-bi-odds", children: [
1095
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
1096
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("b", { children: it.odds }),
1097
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
1098
- it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
1139
+ it.isMarketFloor ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
1140
+ it.odds ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "ss-w-bi-odds", children: [
1141
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("b", { children: it.odds }),
1142
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
1143
+ it.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
1099
1144
  ] }) : null,
1100
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AddToSlipButton, { it, slip, ui })
1145
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AddToSlipButton, { it, slip, ui })
1101
1146
  ] })
1102
1147
  ] }),
1103
- showReason ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-reason", children: [
1104
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
1105
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "ss-w-bi-reason-body", children: [
1106
- it.text ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "ss-w-bi-text", children: it.text }) : null,
1107
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StatsDisclosure, { it, ui })
1108
- ] })
1109
- ] }) : null,
1110
- it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
1148
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ReasonStrip, { it, ui }),
1149
+ it.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
1111
1150
  ] });
1112
1151
  }
1113
1152
  function BettingInsightList({ insights, ui, slip }) {
1114
1153
  if (!insights || insights.length === 0) return null;
1115
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(InsightCard, { it, ui, slip }, it.id)) });
1154
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(InsightCard, { it, ui, slip }, it.id)) });
1116
1155
  }
1117
1156
 
1118
1157
  // src/components/MarketOddsCardList.tsx
1119
- var import_react6 = require("react");
1120
- var import_jsx_runtime11 = require("react/jsx-runtime");
1158
+ var import_react7 = require("react");
1159
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1121
1160
  function OddsRow({ vm, row, ui, slip }) {
1122
1161
  const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
1123
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-mo-row", children: [
1124
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-mo-sel", children: row.selection }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
1126
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-mo-price", children: row.odds }),
1127
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1162
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-row", children: [
1163
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-sel", children: row.selection }),
1164
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
1165
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-price", children: row.odds }),
1166
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1128
1167
  ] });
1129
1168
  }
1130
1169
  function MarketOddsCard({ vm, ui, slip }) {
1131
- const [open, setOpen] = (0, import_react6.useState)(false);
1132
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-mocard", children: [
1133
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-mo-head", children: [
1134
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-mo-market", children: vm.market }),
1135
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-mo-tag", children: ui?.marketPrices ?? "Market prices" })
1136
- ] }),
1137
- vm.fixture || vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-mo-fixture", children: [
1138
- vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: vm.fixture }) : null,
1139
- vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ss-w-mo-comp", children: vm.competition }) : null
1170
+ const [open, setOpen] = (0, import_react7.useState)(false);
1171
+ const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1172
+ const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
1173
+ const showHeader = !!vm.competition || vm.isLive || !!kickoff;
1174
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mocard", children: [
1175
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-header", children: [
1176
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1177
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1178
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-comp", children: vm.competition })
1179
+ ] }) : null }),
1180
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-header-right", children: [
1181
+ vm.isLive ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-live", children: [
1182
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1183
+ ui?.liveLabel ?? "Live"
1184
+ ] }) : null,
1185
+ kickoff ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "ss-w-bi-kick", children: [
1186
+ kickoff.dayLabel,
1187
+ " ",
1188
+ kickoff.time
1189
+ ] }) : null
1190
+ ] })
1140
1191
  ] }) : null,
1141
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ss-w-mo-rows", children: [
1142
- vm.mainRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsRow, { vm, row, ui, slip }, row.key)),
1143
- open ? vm.moreRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(OddsRow, { vm, row, ui, slip }, row.key)) : null
1192
+ hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-sub", children: [
1193
+ hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-bi-fixture", children: [
1194
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1195
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1196
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1197
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1198
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1199
+ ] }) : vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1200
+ vm.market ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-mo-market", children: vm.market }) : null
1201
+ ] }) : null,
1202
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-mo-rows", children: [
1203
+ vm.mainRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)),
1204
+ open ? vm.moreRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsRow, { vm, row, ui, slip }, row.key)) : null
1144
1205
  ] }),
1145
- vm.moreRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { type: "button", className: "ss-w-bi-toggle", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
1146
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
1147
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
1206
+ vm.moreRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "ss-w-mo-more", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
1208
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `ss-w-mo-more-chev${open ? " ss-w-mo-more-chev-up" : ""}`, "aria-hidden": "true" })
1148
1209
  ] }) : null,
1149
- vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: vm.bookmaker }) }) : null,
1150
- vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1210
+ vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: vm.bookmaker }) }) : null,
1211
+ vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1151
1212
  ] });
1152
1213
  }
1153
1214
  function MarketOddsCardList({ cards, ui, slip }) {
1154
1215
  if (!cards || cards.length === 0) return null;
1155
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MarketOddsCard, { vm, ui, slip }, vm.id)) });
1216
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarketOddsCard, { vm, ui, slip }, vm.id)) });
1156
1217
  }
1157
1218
 
1158
1219
  // src/components/OddsMovementCard.tsx
1159
- var import_jsx_runtime12 = require("react/jsx-runtime");
1220
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1160
1221
  function directionWord(vm, ui) {
1161
1222
  if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
1162
1223
  if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
@@ -1166,18 +1227,18 @@ function OddsMovementCard({ vm, ui }) {
1166
1227
  const word = directionWord(vm, ui);
1167
1228
  const drift = word ? `, ${word}` : "";
1168
1229
  const aria = ui?.chartAria ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours) : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`;
1169
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-omcard", children: [
1170
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-om-head", children: [
1171
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-om-market", children: vm.market }),
1172
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
1230
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-omcard", children: [
1231
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-head", children: [
1232
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-market", children: vm.market }),
1233
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
1173
1234
  ] }),
1174
- vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-om-fixture", children: [
1175
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: vm.fixture }),
1176
- vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ss-w-om-comp", children: vm.competition }) : null
1235
+ vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-fixture", children: [
1236
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: vm.fixture }),
1237
+ vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-om-comp", children: vm.competition }) : null
1177
1238
  ] }) : null,
1178
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-sel", children: vm.selection }),
1179
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
1180
- vm.geometry === null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-empty", children: vm.observationCount === 1 ? ui?.singlePricePoint ?? "Only one price recorded so far for this selection." : ui?.notEnoughHistory ?? "No price history recorded yet for this selection." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1239
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-sel", children: vm.selection }),
1240
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
1241
+ vm.geometry === null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-empty", children: vm.observationCount === 1 ? ui?.singlePricePoint ?? "Only one price recorded so far for this selection." : ui?.notEnoughHistory ?? "No price history recorded yet for this selection." }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1181
1242
  "svg",
1182
1243
  {
1183
1244
  className: "ss-w-om-chart",
@@ -1186,83 +1247,83 @@ function OddsMovementCard({ vm, ui }) {
1186
1247
  role: "img",
1187
1248
  "aria-label": aria,
1188
1249
  children: [
1189
- vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("g", { children: [
1190
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
1191
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
1250
+ vm.geometry.gridlines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("g", { children: [
1251
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
1192
1253
  ] }, g.price)),
1193
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
1194
- vm.geometry.markers.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
1195
- ui?.chartTimeLabel ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1196
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
1197
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
1198
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
1254
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
1255
+ vm.geometry.markers.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
1256
+ ui?.chartTimeLabel ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1257
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
1258
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
1259
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
1199
1260
  ]
1200
1261
  }
1201
1262
  ),
1202
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ss-w-om-foot", children: [
1203
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1263
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-om-foot", children: [
1264
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1204
1265
  ui?.openingLabel ?? "Opening",
1205
1266
  " ",
1206
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("b", { children: vm.opening })
1267
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.opening })
1207
1268
  ] }),
1208
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1269
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1209
1270
  ui?.currentLabel ?? "Current",
1210
1271
  " ",
1211
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("b", { children: vm.current })
1272
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: vm.current })
1212
1273
  ] })
1213
1274
  ] }),
1214
- vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: vm.bookmaker }) }) : null,
1215
- vm.excludedCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
1216
- vm.isSuspended ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
1217
- vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
1275
+ vm.bookmaker ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: vm.bookmaker }) }) : null,
1276
+ vm.excludedCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
1277
+ vm.isSuspended ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
1278
+ vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
1218
1279
  ] });
1219
1280
  }
1220
1281
  function OddsMovementCardList({ cards, ui }) {
1221
1282
  if (!cards || cards.length === 0) return null;
1222
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OddsMovementCard, { vm, ui }, vm.id)) });
1283
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(OddsMovementCard, { vm, ui }, vm.id)) });
1223
1284
  }
1224
1285
 
1225
1286
  // src/components/ActionButtons.tsx
1226
- var import_jsx_runtime13 = require("react/jsx-runtime");
1287
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1227
1288
  function ActionButtons({ actions, loading, disabled, onAct }) {
1228
1289
  if (actions.length === 0 && !loading) return null;
1229
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ss-w-actions", children: [
1230
- actions.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
1231
- actions.length === 0 && loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1232
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-abtn-shimmer" }),
1233
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ss-w-abtn-shimmer" })
1290
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-actions", children: [
1291
+ actions.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
1292
+ actions.length === 0 && loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1293
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" }),
1294
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-abtn-shimmer" })
1234
1295
  ] }) : null
1235
1296
  ] });
1236
1297
  }
1237
1298
 
1238
1299
  // src/components/dashboard/DashboardTile.tsx
1239
- var import_jsx_runtime14 = require("react/jsx-runtime");
1300
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1240
1301
  var MAX_CRESTS = 3;
1241
1302
  function DashboardTile({ tile, onTap }) {
1242
1303
  const spanClass = tile.span === "full" ? "ss-w-dash-tile--full" : "ss-w-dash-tile--half";
1243
1304
  const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS);
1244
1305
  const hasMeta = Boolean(tile.badgeText) || crests.length > 0;
1245
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
1246
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DashboardIcon, { name: tile.icon }) }),
1247
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-dash-tile-body", children: [
1248
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-title", children: tile.title }),
1249
- tile.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
1306
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
1307
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DashboardIcon, { name: tile.icon }) }),
1308
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-body", children: [
1309
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-title", children: tile.title }),
1310
+ tile.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
1250
1311
  hasMeta ? (
1251
1312
  // Badge + crests sit on their own row, below the title, instead of sharing the
1252
1313
  // icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone
1253
1314
  // (~70px) left the title column at ~22px and forced character-by-character wrapping.
1254
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-dash-tile-meta", children: [
1255
- tile.badgeText ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
1256
- crests.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
1315
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "ss-w-dash-tile-meta", children: [
1316
+ tile.badgeText ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
1317
+ crests.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
1257
1318
  ] })
1258
1319
  ) : null
1259
1320
  ] }),
1260
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChevronIcon, {}) })
1321
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronIcon, {}) })
1261
1322
  ] });
1262
1323
  }
1263
1324
 
1264
1325
  // src/components/dashboard/GreetingDashboard.tsx
1265
- var import_jsx_runtime15 = require("react/jsx-runtime");
1326
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1266
1327
  var LAYOUT_CLASSES = {
1267
1328
  market: "ss-w-dash--market",
1268
1329
  goal: "ss-w-dash--goal",
@@ -1272,75 +1333,75 @@ function layoutClass(layout) {
1272
1333
  return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout) ? LAYOUT_CLASSES[layout] : LAYOUT_CLASSES.goal;
1273
1334
  }
1274
1335
  function GreetingDashboard({ dashboard, onTap }) {
1275
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
1276
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ss-w-dash-head", children: [
1277
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-title", children: dashboard.title }),
1278
- dashboard.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
1336
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
1337
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-dash-head", children: [
1338
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-title", children: dashboard.title }),
1339
+ dashboard.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
1279
1340
  ] }),
1280
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
1281
- dashboard.footerTip ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
1341
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
1342
+ dashboard.footerTip ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
1282
1343
  ] });
1283
1344
  }
1284
1345
 
1285
1346
  // src/components/club-dashboard/GreetingHeaderBlock.tsx
1286
- var import_jsx_runtime16 = require("react/jsx-runtime");
1347
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1287
1348
  function GreetingHeaderBlock({ block }) {
1288
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
1289
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1290
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1349
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-greeting", children: [
1350
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1351
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1291
1352
  ] });
1292
1353
  }
1293
1354
 
1294
1355
  // src/components/club-dashboard/FixtureHeroBlock.tsx
1295
- var import_react7 = require("react");
1296
- var import_jsx_runtime17 = require("react/jsx-runtime");
1356
+ var import_react8 = require("react");
1357
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1297
1358
  function initials3(name) {
1298
1359
  return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
1299
1360
  }
1300
1361
  function Crest3({ url, name }) {
1301
- const [broken, setBroken] = (0, import_react7.useState)(false);
1362
+ const [broken, setBroken] = (0, import_react8.useState)(false);
1302
1363
  if (!url || broken) {
1303
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
1364
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
1304
1365
  }
1305
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1366
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1306
1367
  }
1307
1368
  function FixtureHeroBlock({
1308
1369
  block,
1309
1370
  ui,
1310
1371
  onAction
1311
1372
  }) {
1312
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
1313
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-tie", children: [
1314
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
1315
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
1316
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
1317
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
1318
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
1373
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture", children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-tie", children: [
1375
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.homeName }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-vs", children: "v" }),
1378
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-team", children: block.awayName }),
1379
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Crest3, { url: block.awayCrestUrl, name: block.awayName })
1319
1380
  ] }),
1320
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
1321
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1322
- block.venue ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1323
- block.competition ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1381
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ss-w-cdash-fixture-meta", children: [
1382
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1383
+ block.venue ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1384
+ block.competition ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1324
1385
  ] }),
1325
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, void 0, block.ctaLabel), children: block.ctaLabel })
1386
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaLabel, { actionRef: block.ctaActionRef }), children: block.ctaLabel })
1326
1387
  ] });
1327
1388
  }
1328
1389
 
1329
1390
  // src/components/club-dashboard/FormGuideBlock.tsx
1330
- var import_jsx_runtime18 = require("react/jsx-runtime");
1391
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1331
1392
  function FormGuideBlock({ block }) {
1332
1393
  if (block.rows.length === 0) return null;
1333
- 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: [
1334
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
1394
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-cdash-form-row", children: [
1395
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-cdash-form-name", children: [
1335
1396
  row.name,
1336
1397
  row.position != null ? ` #${row.position}` : ""
1337
1398
  ] }),
1338
- /* @__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)) })
1399
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
1339
1400
  ] }, row.name)) });
1340
1401
  }
1341
1402
 
1342
1403
  // src/components/club-dashboard/MatchPreviewBlock.tsx
1343
- var import_jsx_runtime19 = require("react/jsx-runtime");
1404
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1344
1405
  function MatchPreviewBlock({
1345
1406
  block,
1346
1407
  ui,
@@ -1348,31 +1409,31 @@ function MatchPreviewBlock({
1348
1409
  }) {
1349
1410
  if (block.facts.length === 0) return null;
1350
1411
  const heading = ui.clubMatchPreviewHeading;
1351
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1352
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1412
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1413
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1353
1414
  block.facts.map(
1354
- (f, i) => f.entityRef ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1415
+ (f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1355
1416
  "button",
1356
1417
  {
1357
1418
  type: "button",
1358
1419
  className: "ss-w-cdash-fact",
1359
- onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
1420
+ onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
1360
1421
  children: [
1361
1422
  f.sentence,
1362
- f.label ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1423
+ f.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1363
1424
  " ",
1364
1425
  f.label
1365
1426
  ] }) : null
1366
1427
  ]
1367
1428
  },
1368
1429
  i
1369
- ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: f.sentence }, i)
1430
+ ) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: f.sentence }, i)
1370
1431
  )
1371
1432
  ] });
1372
1433
  }
1373
1434
 
1374
1435
  // src/components/club-dashboard/TeamDnaBlock.tsx
1375
- var import_jsx_runtime20 = require("react/jsx-runtime");
1436
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1376
1437
  function TeamDnaBlock({
1377
1438
  block,
1378
1439
  ui,
@@ -1380,32 +1441,32 @@ function TeamDnaBlock({
1380
1441
  }) {
1381
1442
  if (block.facts.length === 0) return null;
1382
1443
  const heading = ui.clubTeamDnaHeading;
1383
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1384
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1444
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-lines", children: [
1445
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1385
1446
  block.facts.map(
1386
- (f, i) => f.entityRef ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1447
+ (f, i) => f.actionRef ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1387
1448
  "button",
1388
1449
  {
1389
1450
  type: "button",
1390
1451
  className: "ss-w-cdash-fact",
1391
- onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
1452
+ onClick: () => onAction(f.label ?? f.sentence, { actionRef: f.actionRef }),
1392
1453
  children: [
1393
1454
  f.sentence,
1394
- f.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1455
+ f.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "ss-w-cdash-fact-label", children: [
1395
1456
  " ",
1396
1457
  f.label
1397
1458
  ] }) : null
1398
1459
  ]
1399
1460
  },
1400
1461
  i
1401
- ) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { children: f.sentence }, i)
1462
+ ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: f.sentence }, i)
1402
1463
  )
1403
1464
  ] });
1404
1465
  }
1405
1466
 
1406
1467
  // src/components/club-dashboard/CountdownBlock.tsx
1407
- var import_react8 = require("react");
1408
- var import_jsx_runtime21 = require("react/jsx-runtime");
1468
+ var import_react9 = require("react");
1469
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1409
1470
  var DAY_MS = 24 * 3600 * 1e3;
1410
1471
  function pad2(n) {
1411
1472
  return String(n).padStart(2, "0");
@@ -1418,8 +1479,8 @@ function splitRemaining(remainingMs) {
1418
1479
  return { h: pad2(h), m: pad2(m), s: pad2(s) };
1419
1480
  }
1420
1481
  function CountdownBlock({ block, ui }) {
1421
- const [remainingMs, setRemainingMs] = (0, import_react8.useState)(() => block.kickoffUnix * 1e3 - Date.now());
1422
- (0, import_react8.useEffect)(() => {
1482
+ const [remainingMs, setRemainingMs] = (0, import_react9.useState)(() => block.kickoffUnix * 1e3 - Date.now());
1483
+ (0, import_react9.useEffect)(() => {
1423
1484
  setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1424
1485
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
1425
1486
  const id = setInterval(() => {
@@ -1430,30 +1491,30 @@ function CountdownBlock({ block, ui }) {
1430
1491
  if (remainingMs <= 0) return null;
1431
1492
  if (remainingMs > DAY_MS) return null;
1432
1493
  const { h, m, s } = splitRemaining(remainingMs);
1433
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
1434
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
1435
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
1494
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
1495
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
1496
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-h", children: h }),
1436
1497
  "h",
1437
1498
  " ",
1438
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
1499
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-m", children: m }),
1439
1500
  "m",
1440
1501
  " ",
1441
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "ss-w-cdash-cd-s", children: s }),
1442
1503
  "s"
1443
1504
  ] }),
1444
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1505
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1445
1506
  ] });
1446
1507
  }
1447
1508
 
1448
1509
  // src/components/club-dashboard/ClubDashboard.tsx
1449
- var import_jsx_runtime22 = require("react/jsx-runtime");
1510
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1450
1511
  var CLUB_BLOCK_REGISTRY = {
1451
- greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GreetingHeaderBlock, { block }) : null,
1452
- fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
1453
- formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FormGuideBlock, { block, ui }) : null,
1454
- matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
1455
- teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
1456
- countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CountdownBlock, { block, ui }) : null
1512
+ greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingHeaderBlock, { block }) : null,
1513
+ fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FixtureHeroBlock, { block, ui, onAction }) : null,
1514
+ formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FormGuideBlock, { block, ui }) : null,
1515
+ matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MatchPreviewBlock, { block, ui, onAction }) : null,
1516
+ teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TeamDnaBlock, { block, ui, onAction }) : null,
1517
+ countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CountdownBlock, { block, ui }) : null
1457
1518
  };
1458
1519
  function ClubDashboard({
1459
1520
  dashboard,
@@ -1461,39 +1522,39 @@ function ClubDashboard({
1461
1522
  onAction
1462
1523
  }) {
1463
1524
  if (!dashboard.blocks.length) return null;
1464
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1525
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1465
1526
  const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
1466
1527
  if (!Comp) {
1467
1528
  console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
1468
1529
  return null;
1469
1530
  }
1470
- 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);
1531
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Comp, { block, ui, onAction }) }, i);
1471
1532
  }) });
1472
1533
  }
1473
1534
 
1474
1535
  // src/components/ChatMessage.tsx
1475
- var import_jsx_runtime23 = require("react/jsx-runtime");
1536
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1476
1537
  function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
1477
1538
  if (message.role === "user") {
1478
- 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 }) });
1539
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1479
1540
  }
1480
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1481
- message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Markdown, { text: message.text }) : null,
1482
- message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1483
- message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1484
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1485
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1486
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1487
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1488
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1541
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1542
+ message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Markdown, { text: message.text }) : null,
1543
+ message.greetingDashboard ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1544
+ message.clubDashboard && ui ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1545
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1546
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(BettingInsightList, { insights: message.insights, ui, slip }),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1548
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1549
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1489
1550
  ] });
1490
1551
  }
1491
1552
 
1492
1553
  // src/components/IntentChips.tsx
1493
- var import_jsx_runtime24 = require("react/jsx-runtime");
1554
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1494
1555
  function IntentChips({ chips, onPick }) {
1495
1556
  if (chips.length === 0) return null;
1496
- 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}`)) });
1557
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1497
1558
  }
1498
1559
 
1499
1560
  // src/scroll.ts
@@ -1503,18 +1564,18 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1503
1564
  }
1504
1565
 
1505
1566
  // src/components/MessageList.tsx
1506
- var import_jsx_runtime25 = require("react/jsx-runtime");
1567
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1507
1568
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1508
1569
  const { state, send } = controller;
1509
- const listRef = (0, import_react9.useRef)(null);
1510
- const endRef = (0, import_react9.useRef)(null);
1511
- const pinnedRef = (0, import_react9.useRef)(true);
1512
- (0, import_react9.useEffect)(() => {
1570
+ const listRef = (0, import_react10.useRef)(null);
1571
+ const endRef = (0, import_react10.useRef)(null);
1572
+ const pinnedRef = (0, import_react10.useRef)(true);
1573
+ (0, import_react10.useEffect)(() => {
1513
1574
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
1514
1575
  }, [state.messages, state.status]);
1515
1576
  const hasUserMessage = state.messages.some((m) => m.role === "user");
1516
1577
  const hasDashboard = state.messages.some((m) => m.role === "assistant" && m.greetingDashboard);
1517
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1578
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1518
1579
  "div",
1519
1580
  {
1520
1581
  className: "ss-w-list",
@@ -1524,7 +1585,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1524
1585
  if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
1525
1586
  },
1526
1587
  children: [
1527
- state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1588
+ state.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1528
1589
  ChatMessage,
1529
1590
  {
1530
1591
  message: m,
@@ -1534,31 +1595,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1534
1595
  send(tile.actionValue, { displayText: tile.title });
1535
1596
  if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
1536
1597
  },
1537
- onClubAction: (message, grounding, displayText) => send(message, { grounding, displayText: displayText ?? message }),
1598
+ onClubAction: (label, opts) => send(label, { actionRef: opts.actionRef }),
1538
1599
  ui,
1539
1600
  slip
1540
1601
  },
1541
1602
  m.id
1542
1603
  )),
1543
- state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1604
+ state.isStreaming && state.actionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ActionButtons, { actions: [], loading: true, onAct: () => {
1544
1605
  } }) : null,
1545
- state.status ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1546
- state.error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1547
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1548
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1606
+ state.status ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "ss-w-status", children: state.status }) : null,
1607
+ state.error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-error", role: "alert", children: [
1608
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1549
1610
  ] }) : null,
1550
- !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1551
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: endRef })
1611
+ !hasUserMessage && !hasDashboard ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1612
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: endRef })
1552
1613
  ]
1553
1614
  }
1554
1615
  );
1555
1616
  }
1556
1617
 
1557
1618
  // src/components/ChatInput.tsx
1558
- var import_react10 = require("react");
1559
- var import_jsx_runtime26 = require("react/jsx-runtime");
1619
+ var import_react11 = require("react");
1620
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1560
1621
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
1561
- const [value, setValue] = (0, import_react10.useState)("");
1622
+ const [value, setValue] = (0, import_react11.useState)("");
1562
1623
  const submit = () => {
1563
1624
  const t = value.trim();
1564
1625
  if (!t) return;
@@ -1571,18 +1632,18 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
1571
1632
  submit();
1572
1633
  }
1573
1634
  };
1574
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "ss-w-input", children: [
1575
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1576
- 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, {}) })
1635
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-input", children: [
1636
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1637
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SendIcon, {}) })
1577
1638
  ] });
1578
1639
  }
1579
1640
 
1580
1641
  // src/components/ChatPanel.tsx
1581
- var import_jsx_runtime27 = require("react/jsx-runtime");
1642
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1582
1643
  var FULLSCREEN_QUERY = "(max-width: 639px)";
1583
1644
  function useIsModal() {
1584
- const [modal, setModal] = (0, import_react11.useState)(false);
1585
- (0, import_react11.useEffect)(() => {
1645
+ const [modal, setModal] = (0, import_react12.useState)(false);
1646
+ (0, import_react12.useEffect)(() => {
1586
1647
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1587
1648
  const mql = window.matchMedia(FULLSCREEN_QUERY);
1588
1649
  const sync = () => setModal(mql.matches);
@@ -1595,17 +1656,17 @@ function useIsModal() {
1595
1656
  function ChatPanel({ controller, ui, slip, onDashboardTap }) {
1596
1657
  const { state, close, stop, send } = controller;
1597
1658
  const isModal = useIsModal();
1598
- (0, import_react11.useEffect)(() => {
1659
+ (0, import_react12.useEffect)(() => {
1599
1660
  const onKey = (e) => {
1600
1661
  if (e.key === "Escape") close();
1601
1662
  };
1602
1663
  window.addEventListener("keydown", onKey);
1603
1664
  return () => window.removeEventListener("keydown", onKey);
1604
1665
  }, [close]);
1605
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1606
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1607
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1608
- /* @__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 })
1666
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1667
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1668
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageList, { controller, ui, slip, onDashboardTap }),
1669
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1609
1670
  ] });
1610
1671
  }
1611
1672
 
@@ -1653,7 +1714,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1653
1714
  .ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }
1654
1715
 
1655
1716
  /* panel */
1656
- .ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(400px, calc(100vw - 40px)); height: min(620px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }
1717
+ .ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(460px, calc(100vw - 40px)); height: min(640px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }
1657
1718
  .ss-w-root[data-ss-w-pos="right"] .ss-w-panel { right: var(--ss-w-offset-x); }
1658
1719
  .ss-w-root[data-ss-w-pos="left"] .ss-w-panel { left: var(--ss-w-offset-x); }
1659
1720
  @media (max-width: 639px) {
@@ -1756,9 +1817,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1756
1817
  .ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; align-self: flex-start; flex: none; }
1757
1818
 
1758
1819
  /* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */
1759
- .ss-w-bi-comp-logo { width: 15px; height: 15px; flex: none; display: block; border-radius: 50%; background-size: contain; background-repeat: no-repeat; background-position: center; }
1760
- .ss-w-bi-crest { width: 22px; height: 22px; flex: none; display: block; border-radius: 50%; background-size: contain; background-repeat: no-repeat; background-position: center; background-color: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); }
1761
- .ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 9px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
1820
+ .ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
1821
+ .ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
1822
+ .ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 10px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
1762
1823
 
1763
1824
  /* row 2: crest-flanked fixture on the left, boxed action panel on the right */
1764
1825
  .ss-w-bi-body { display: flex; align-items: center; gap: 10px; }
@@ -1766,16 +1827,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1766
1827
  .ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1767
1828
  .ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }
1768
1829
  .ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1769
- .ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: stretch; gap: 6px; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; }
1770
- .ss-w-bi-action .ss-w-slip > button { flex: 1; text-align: center; }
1830
+ .ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }
1831
+ .ss-w-bi-action .ss-w-slip { width: 100%; }
1832
+ .ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }
1771
1833
  /* The action column is narrow; let its toast size to its own text and anchor to the card's right edge instead of being clipped to the button width. */
1772
1834
  .ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
1773
- .ss-w-bi-mkt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
1774
- .ss-w-bi-market { font-size: 13.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }
1775
- .ss-w-bi-sel { font-size: 11.5px; line-height: 1.3; color: var(--ss-w-faint); }
1776
- .ss-w-bi-odds { flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 1px; background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 10px; padding: 4px 11px; min-width: 62px; }
1777
- .ss-w-bi-odds-cap { font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }
1778
- .ss-w-bi-odds b { font-size: 19px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.1; }
1835
+ .ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }
1836
+ .ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }
1837
+ .ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }
1838
+ .ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }
1839
+ .ss-w-bi-odds b { font-size: 23px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }
1779
1840
  .ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
1780
1841
 
1781
1842
  /* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
@@ -1789,11 +1850,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1789
1850
  }
1790
1851
  .ss-w-bi-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
1791
1852
  .ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
1792
- .ss-w-bi-stats { display: flex; flex-direction: column; gap: 8px; }
1793
- .ss-w-bi-toggle { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }
1794
- .ss-w-bi-toggle:hover { text-decoration: underline; }
1795
- .ss-w-bi-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }
1796
- .ss-w-bi-chev-up { transform: translateY(1px) rotate(-135deg); }
1853
+ .ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
1854
+ .ss-w-bi-expand { flex: none; align-self: center; display: grid; place-items: center; width: 22px; height: 22px; margin: -2px -4px -2px 0; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; }
1855
+ .ss-w-bi-expand:hover { color: var(--ss-w-ink); }
1856
+ .ss-w-bi-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); transition: transform .15s ease; }
1857
+ .ss-w-bi-arrow-open { transform: rotate(135deg); }
1797
1858
  .ss-w-bi-rows { display: flex; flex-direction: column; }
1798
1859
  .ss-w-bi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--ss-w-line); }
1799
1860
  .ss-w-bi-row:first-child { border-top: none; }
@@ -1808,11 +1869,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1808
1869
  /* market odds card */
1809
1870
  .ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
1810
1871
  .ss-w-mocard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }
1811
- .ss-w-mo-head { display: flex; align-items: center; gap: 8px; }
1812
- .ss-w-mo-market { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
1813
- .ss-w-mo-tag { margin-left: auto; flex: none; font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 2px 7px; }
1814
- .ss-w-mo-fixture { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }
1815
- .ss-w-mo-comp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1872
+ .ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
1873
+ .ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1874
+ .ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
1875
+ .ss-w-mo-more { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }
1876
+ .ss-w-mo-more:hover { text-decoration: underline; }
1877
+ .ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }
1878
+ .ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }
1816
1879
  .ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
1817
1880
  .ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
1818
1881
  .ss-w-mo-row:last-child { border-bottom: none; }
@@ -1998,7 +2061,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1998
2061
  `;
1999
2062
 
2000
2063
  // src/StatsWidget.tsx
2001
- var import_jsx_runtime28 = require("react/jsx-runtime");
2064
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2002
2065
  function buildClient(props) {
2003
2066
  try {
2004
2067
  if ("client" in props && props.client) {
@@ -2023,11 +2086,11 @@ function injectStyles(root) {
2023
2086
  function StatsWidget(props) {
2024
2087
  const injectedClient = "client" in props ? props.client : void 0;
2025
2088
  const cfg = props.config;
2026
- const built = (0, import_react12.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
2027
- const ui = (0, import_react12.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
2028
- const rootRef = (0, import_react12.useRef)(null);
2089
+ const built = (0, import_react13.useMemo)(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl]);
2090
+ const ui = (0, import_react13.useMemo)(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
2091
+ const rootRef = (0, import_react13.useRef)(null);
2029
2092
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
2030
- const slip = (0, import_react12.useMemo)(
2093
+ const slip = (0, import_react13.useMemo)(
2031
2094
  () => ({
2032
2095
  onAddToSlip: props.config?.onAddToSlip,
2033
2096
  conversationId: controller.state.conversationId ?? void 0,
@@ -2040,18 +2103,18 @@ function StatsWidget(props) {
2040
2103
  }),
2041
2104
  [props.config?.onAddToSlip, controller.state.conversationId, built]
2042
2105
  );
2043
- const onDashboardTap = (0, import_react12.useMemo)(
2106
+ const onDashboardTap = (0, import_react13.useMemo)(
2044
2107
  () => built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : void 0,
2045
2108
  [built]
2046
2109
  );
2047
- (0, import_react12.useEffect)(() => {
2110
+ (0, import_react13.useEffect)(() => {
2048
2111
  if (!built || !ui.injectStyles) return;
2049
2112
  const node = rootRef.current?.getRootNode();
2050
2113
  if (node) injectStyles(node);
2051
2114
  }, [built, ui.injectStyles]);
2052
2115
  if (!built) return null;
2053
2116
  const attrs = themeAttrs(ui);
2054
- 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)(
2117
+ return /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2055
2118
  ChatFab,
2056
2119
  {
2057
2120
  label: ui.launcherLabel,