@sensiblestats/widget-react 0.17.0 → 0.19.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.js CHANGED
@@ -435,7 +435,13 @@ function toMarketOddsVM(card) {
435
435
  id: `${typeof card.matchId === "number" ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ""}`,
436
436
  market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? "",
437
437
  fixture: home && away ? `${home} vs ${away}` : void 0,
438
+ homeTeamName: home,
439
+ awayTeamName: away,
440
+ homeCrest: str(card.homeTeamImagePath),
441
+ awayCrest: str(card.awayTeamImagePath),
442
+ competitionCrest: str(card.competitionImagePath),
438
443
  competition: str(card.competitionName),
444
+ kickoffUtc: str(card.kickoffUtc),
439
445
  bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),
440
446
  updatedAt: updated.length > 0 ? updated[updated.length - 1] : void 0,
441
447
  isLive: rows.some((r) => r.isLive === true),
@@ -615,7 +621,7 @@ function useChatStream(conversation, starterTexts, greetingMessage) {
615
621
  const send = useCallback((text, opts) => {
616
622
  const trimmed = text.trim();
617
623
  if (!trimmed) return;
618
- run({ message: trimmed, actionId: opts?.actionId }, opts?.displayText);
624
+ run({ message: trimmed, actionId: opts?.actionId, grounding: opts?.grounding }, opts?.displayText);
619
625
  }, [run]);
620
626
  const retry = useCallback(() => {
621
627
  const last = stateRef.current.lastUserInput;
@@ -711,7 +717,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
711
717
  }
712
718
 
713
719
  // src/components/ChatPanel.tsx
714
- import { useEffect as useEffect5, useState as useState8 } from "react";
720
+ import { useEffect as useEffect5, useState as useState9 } from "react";
715
721
 
716
722
  // src/components/ChatHeader.tsx
717
723
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -844,7 +850,7 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
844
850
  }
845
851
 
846
852
  // src/components/BettingInsightList.tsx
847
- import { useState as useState3 } from "react";
853
+ import { useState as useState4 } from "react";
848
854
 
849
855
  // src/components/AddToSlipButton.tsx
850
856
  import { useCallback as useCallback2, useState as useState2 } from "react";
@@ -967,53 +973,64 @@ function OddsMovementBadge({
967
973
  );
968
974
  }
969
975
 
976
+ // src/components/Crest.tsx
977
+ import { useState as useState3 } from "react";
978
+ import { jsx as jsx10 } from "react/jsx-runtime";
979
+ function initials2(name) {
980
+ return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
981
+ }
982
+ function Crest2({ url, name, kind }) {
983
+ const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
984
+ const [failed, setFailed] = useState3(false);
985
+ if (url && !failed) {
986
+ return /* @__PURE__ */ jsx10("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
987
+ }
988
+ return /* @__PURE__ */ jsx10("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
989
+ }
990
+
970
991
  // src/components/BettingInsightList.tsx
971
- import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
992
+ import { Fragment, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
972
993
  function StatRows2({ stats }) {
973
- return /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-row", children: [
974
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-row-lbl", children: s.label }),
975
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-row-num", children: s.value })
994
+ return /* @__PURE__ */ jsx11("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-row", children: [
995
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-row-lbl", children: s.label }),
996
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-row-num", children: s.value })
976
997
  ] }, `${s.label}:${s.value}`)) });
977
998
  }
978
999
  function ScopedStats({ scopes }) {
979
- const [active, setActive] = useState3(0);
1000
+ const [active, setActive] = useState4(0);
980
1001
  const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
981
1002
  return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-scoped", children: [
982
- /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx10("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
983
- /* @__PURE__ */ jsx10(StatRows2, { stats: current.stats }, current.key)
1003
+ /* @__PURE__ */ jsx11("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx11("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
1004
+ /* @__PURE__ */ jsx11(StatRows2, { stats: current.stats }, current.key)
984
1005
  ] });
985
1006
  }
986
1007
  function hasStatsContent(it) {
987
1008
  return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
988
1009
  }
989
- function initials2(name) {
990
- return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
991
- }
992
- function Crest2({ url, name, kind }) {
993
- const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
994
- if (url) return /* @__PURE__ */ jsx10("span", { className: cls, style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" });
995
- return /* @__PURE__ */ jsx10("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
996
- }
997
- function StatsDisclosure({ it, ui }) {
998
- const [open, setOpen] = useState3(false);
1010
+ function ReasonStrip({ it, ui }) {
1011
+ const [open, setOpen] = useState4(false);
999
1012
  const hasScopes = !!it.scopes && it.scopes.length >= 2;
1000
1013
  const hasStats = hasStatsContent(it);
1001
- if (!hasStats) return null;
1002
- return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-stats", children: [
1003
- /* @__PURE__ */ jsxs7(
1014
+ const hasText = !!it.text;
1015
+ if (!hasText && !hasStats) return null;
1016
+ const expandable = hasStats || (it.text?.length ?? 0) > 90;
1017
+ return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason", children: [
1018
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
1019
+ /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason-body", children: [
1020
+ hasText ? /* @__PURE__ */ jsx11("p", { className: `ss-w-bi-text${open ? "" : " ss-w-bi-text-clamp"}`, children: it.text }) : null,
1021
+ open && hasStats ? hasScopes ? /* @__PURE__ */ jsx11(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx11(StatRows2, { stats: it.stats }) : null
1022
+ ] }),
1023
+ expandable ? /* @__PURE__ */ jsx11(
1004
1024
  "button",
1005
1025
  {
1006
1026
  type: "button",
1007
- className: "ss-w-bi-toggle",
1027
+ className: "ss-w-bi-expand",
1008
1028
  "aria-expanded": open,
1029
+ "aria-label": open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats",
1009
1030
  onClick: () => setOpen((v) => !v),
1010
- children: [
1011
- /* @__PURE__ */ jsx10("span", { children: open ? ui?.hideStats ?? "Hide stats" : ui?.showStats ?? "Show stats" }),
1012
- /* @__PURE__ */ jsx10("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
1013
- ]
1031
+ children: /* @__PURE__ */ jsx11("span", { className: `ss-w-bi-arrow${open ? " ss-w-bi-arrow-open" : ""}`, "aria-hidden": "true" })
1014
1032
  }
1015
- ),
1016
- open ? hasScopes ? /* @__PURE__ */ jsx10(ScopedStats, { scopes: it.scopes }) : /* @__PURE__ */ jsx10(StatRows2, { stats: it.stats }) : null
1033
+ ) : null
1017
1034
  ] });
1018
1035
  }
1019
1036
  function InsightCard({ it, ui, slip }) {
@@ -1021,16 +1038,15 @@ function InsightCard({ it, ui, slip }) {
1021
1038
  const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
1022
1039
  const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
1023
1040
  const showHeader = !!it.competition || live || !!kickoff;
1024
- const showReason = !!it.text || hasStatsContent(it);
1025
1041
  return /* @__PURE__ */ jsxs7("div", { className: "ss-w-binsight", children: [
1026
1042
  showHeader ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-header", children: [
1027
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ jsxs7(Fragment, { children: [
1028
- /* @__PURE__ */ jsx10(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
1029
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-comp", children: it.competition })
1043
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ jsxs7(Fragment, { children: [
1044
+ /* @__PURE__ */ jsx11(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
1045
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-comp", children: it.competition })
1030
1046
  ] }) : null }),
1031
1047
  /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-header-right", children: [
1032
1048
  live ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-live", children: [
1033
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1049
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1034
1050
  ui?.liveLabel ?? "Live"
1035
1051
  ] }) : null,
1036
1052
  kickoff ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-kick", children: [
@@ -1041,85 +1057,100 @@ function InsightCard({ it, ui, slip }) {
1041
1057
  ] })
1042
1058
  ] }) : null,
1043
1059
  /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-body", children: [
1044
- /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ jsxs7(Fragment, { children: [
1045
- /* @__PURE__ */ jsx10(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
1046
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
1047
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1048
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
1049
- /* @__PURE__ */ jsx10(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
1050
- ] }) : it.fixture ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
1060
+ /* @__PURE__ */ jsx11("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ jsxs7(Fragment, { children: [
1061
+ /* @__PURE__ */ jsx11(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
1062
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
1063
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1064
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
1065
+ /* @__PURE__ */ jsx11(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
1066
+ ] }) : it.fixture ? /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
1051
1067
  /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-action", children: [
1052
1068
  /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-mkt", children: [
1053
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-market", children: it.market }),
1054
- it.selection ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-sel", children: it.selection }) : null
1069
+ /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-market", children: it.market }),
1070
+ it.selection ? /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-sel", children: it.selection }) : null
1055
1071
  ] }),
1056
- it.isMarketFloor ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
1072
+ it.isMarketFloor ? /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
1057
1073
  it.odds ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-odds", children: [
1058
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
1059
- /* @__PURE__ */ jsx10("b", { children: it.odds }),
1060
- /* @__PURE__ */ jsx10(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
1061
- it.bookmaker ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
1074
+ /* @__PURE__ */ jsx11("b", { children: it.odds }),
1075
+ /* @__PURE__ */ jsx11(OddsMovementBadge, { previous: it.previousOdds, current: it.odds, direction: it.movementDirection, ui }),
1076
+ it.bookmaker ? /* @__PURE__ */ jsx11("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
1062
1077
  ] }) : null,
1063
- /* @__PURE__ */ jsx10(AddToSlipButton, { it, slip, ui })
1078
+ /* @__PURE__ */ jsx11(AddToSlipButton, { it, slip, ui })
1064
1079
  ] })
1065
1080
  ] }),
1066
- showReason ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason", children: [
1067
- /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
1068
- /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason-body", children: [
1069
- it.text ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-text", children: it.text }) : null,
1070
- /* @__PURE__ */ jsx10(StatsDisclosure, { it, ui })
1071
- ] })
1072
- ] }) : null,
1073
- it.disclaimer ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
1081
+ /* @__PURE__ */ jsx11(ReasonStrip, { it, ui }),
1082
+ it.disclaimer ? /* @__PURE__ */ jsx11("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
1074
1083
  ] });
1075
1084
  }
1076
1085
  function BettingInsightList({ insights, ui, slip }) {
1077
1086
  if (!insights || insights.length === 0) return null;
1078
- return /* @__PURE__ */ jsx10("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ jsx10(InsightCard, { it, ui, slip }, it.id)) });
1087
+ return /* @__PURE__ */ jsx11("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ jsx11(InsightCard, { it, ui, slip }, it.id)) });
1079
1088
  }
1080
1089
 
1081
1090
  // src/components/MarketOddsCardList.tsx
1082
- import { useState as useState4 } from "react";
1083
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1091
+ import { useState as useState5 } from "react";
1092
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1084
1093
  function OddsRow({ vm, row, ui, slip }) {
1085
1094
  const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
1086
1095
  return /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-row", children: [
1087
- /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-sel", children: row.selection }),
1088
- /* @__PURE__ */ jsx11(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
1089
- /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-price", children: row.odds }),
1090
- /* @__PURE__ */ jsx11(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1096
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-mo-sel", children: row.selection }),
1097
+ /* @__PURE__ */ jsx12(OddsMovementBadge, { previous: row.previousOdds, current: row.odds, direction: row.movementDirection, ui }),
1098
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-mo-price", children: row.odds }),
1099
+ /* @__PURE__ */ jsx12(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1091
1100
  ] });
1092
1101
  }
1093
1102
  function MarketOddsCard({ vm, ui, slip }) {
1094
- const [open, setOpen] = useState4(false);
1103
+ const [open, setOpen] = useState5(false);
1104
+ const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1105
+ const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
1106
+ const showHeader = !!vm.competition || vm.isLive || !!kickoff;
1095
1107
  return /* @__PURE__ */ jsxs8("div", { className: "ss-w-mocard", children: [
1096
- /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-head", children: [
1097
- /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-market", children: vm.market }),
1098
- /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-tag", children: ui?.marketPrices ?? "Market prices" })
1099
- ] }),
1100
- vm.fixture || vm.competition ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-fixture", children: [
1101
- vm.fixture ? /* @__PURE__ */ jsx11("span", { children: vm.fixture }) : null,
1102
- vm.competition ? /* @__PURE__ */ jsx11("span", { className: "ss-w-mo-comp", children: vm.competition }) : null
1108
+ showHeader ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-header", children: [
1109
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
1110
+ /* @__PURE__ */ jsx12(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1111
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-comp", children: vm.competition })
1112
+ ] }) : null }),
1113
+ /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-header-right", children: [
1114
+ vm.isLive ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-live", children: [
1115
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1116
+ ui?.liveLabel ?? "Live"
1117
+ ] }) : null,
1118
+ kickoff ? /* @__PURE__ */ jsxs8("span", { className: "ss-w-bi-kick", children: [
1119
+ kickoff.dayLabel,
1120
+ " ",
1121
+ kickoff.time
1122
+ ] }) : null
1123
+ ] })
1124
+ ] }) : null,
1125
+ hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-sub", children: [
1126
+ hasNamedTeams ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-bi-fixture", children: [
1127
+ /* @__PURE__ */ jsx12(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1128
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1129
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1130
+ /* @__PURE__ */ jsx12("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1131
+ /* @__PURE__ */ jsx12(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1132
+ ] }) : vm.fixture ? /* @__PURE__ */ jsx12("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1133
+ vm.market ? /* @__PURE__ */ jsx12("span", { className: "ss-w-mo-market", children: vm.market }) : null
1103
1134
  ] }) : null,
1104
1135
  /* @__PURE__ */ jsxs8("div", { className: "ss-w-mo-rows", children: [
1105
- vm.mainRows.map((row) => /* @__PURE__ */ jsx11(OddsRow, { vm, row, ui, slip }, row.key)),
1106
- open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx11(OddsRow, { vm, row, ui, slip }, row.key)) : null
1136
+ vm.mainRows.map((row) => /* @__PURE__ */ jsx12(OddsRow, { vm, row, ui, slip }, row.key)),
1137
+ open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx12(OddsRow, { vm, row, ui, slip }, row.key)) : null
1107
1138
  ] }),
1108
- vm.moreRows.length > 0 ? /* @__PURE__ */ jsxs8("button", { type: "button", className: "ss-w-bi-toggle", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
1109
- /* @__PURE__ */ jsx11("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
1110
- /* @__PURE__ */ jsx11("span", { className: `ss-w-bi-chev${open ? " ss-w-bi-chev-up" : ""}`, "aria-hidden": "true" })
1139
+ vm.moreRows.length > 0 ? /* @__PURE__ */ jsxs8("button", { type: "button", className: "ss-w-mo-more", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: [
1140
+ /* @__PURE__ */ jsx12("span", { children: open ? ui?.hideLines ?? "Hide lines" : `${ui?.moreLines ?? "More lines"} (${vm.moreRows.length})` }),
1141
+ /* @__PURE__ */ jsx12("span", { className: `ss-w-mo-more-chev${open ? " ss-w-mo-more-chev-up" : ""}`, "aria-hidden": "true" })
1111
1142
  ] }) : null,
1112
- vm.bookmaker ? /* @__PURE__ */ jsx11("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ jsx11("span", { children: vm.bookmaker }) }) : null,
1113
- vm.disclaimer ? /* @__PURE__ */ jsx11("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1143
+ vm.bookmaker ? /* @__PURE__ */ jsx12("div", { className: "ss-w-mo-foot", children: /* @__PURE__ */ jsx12("span", { children: vm.bookmaker }) }) : null,
1144
+ vm.disclaimer ? /* @__PURE__ */ jsx12("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1114
1145
  ] });
1115
1146
  }
1116
1147
  function MarketOddsCardList({ cards, ui, slip }) {
1117
1148
  if (!cards || cards.length === 0) return null;
1118
- return /* @__PURE__ */ jsx11("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx11(MarketOddsCard, { vm, ui, slip }, vm.id)) });
1149
+ return /* @__PURE__ */ jsx12("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx12(MarketOddsCard, { vm, ui, slip }, vm.id)) });
1119
1150
  }
1120
1151
 
1121
1152
  // src/components/OddsMovementCard.tsx
1122
- import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1153
+ import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1123
1154
  function directionWord(vm, ui) {
1124
1155
  if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
1125
1156
  if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
@@ -1131,16 +1162,16 @@ function OddsMovementCard({ vm, ui }) {
1131
1162
  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}.`;
1132
1163
  return /* @__PURE__ */ jsxs9("div", { className: "ss-w-omcard", children: [
1133
1164
  /* @__PURE__ */ jsxs9("div", { className: "ss-w-om-head", children: [
1134
- /* @__PURE__ */ jsx12("span", { className: "ss-w-om-market", children: vm.market }),
1135
- /* @__PURE__ */ jsx12("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
1165
+ /* @__PURE__ */ jsx13("span", { className: "ss-w-om-market", children: vm.market }),
1166
+ /* @__PURE__ */ jsx13("span", { className: "ss-w-om-tag", children: ui?.priceMovement ?? "Price movement" })
1136
1167
  ] }),
1137
1168
  vm.fixture ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-om-fixture", children: [
1138
- /* @__PURE__ */ jsx12("span", { children: vm.fixture }),
1139
- vm.competition ? /* @__PURE__ */ jsx12("span", { className: "ss-w-om-comp", children: vm.competition }) : null
1169
+ /* @__PURE__ */ jsx13("span", { children: vm.fixture }),
1170
+ vm.competition ? /* @__PURE__ */ jsx13("span", { className: "ss-w-om-comp", children: vm.competition }) : null
1140
1171
  ] }) : null,
1141
- /* @__PURE__ */ jsx12("div", { className: "ss-w-om-sel", children: vm.selection }),
1142
- /* @__PURE__ */ jsx12(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
1143
- vm.geometry === null ? /* @__PURE__ */ jsx12("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__ */ jsxs9(
1172
+ /* @__PURE__ */ jsx13("div", { className: "ss-w-om-sel", children: vm.selection }),
1173
+ /* @__PURE__ */ jsx13(OddsMovementBadge, { previous: vm.opening, current: vm.current, direction: vm.direction, ui }),
1174
+ vm.geometry === null ? /* @__PURE__ */ jsx13("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__ */ jsxs9(
1144
1175
  "svg",
1145
1176
  {
1146
1177
  className: "ss-w-om-chart",
@@ -1150,15 +1181,15 @@ function OddsMovementCard({ vm, ui }) {
1150
1181
  "aria-label": aria,
1151
1182
  children: [
1152
1183
  vm.geometry.gridlines.map((g) => /* @__PURE__ */ jsxs9("g", { children: [
1153
- /* @__PURE__ */ jsx12("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
1154
- /* @__PURE__ */ jsx12("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
1184
+ /* @__PURE__ */ jsx13("line", { className: "ss-w-om-grid", x1: 40, y1: g.y, x2: CHART_VIEW_W - 8, y2: g.y }),
1185
+ /* @__PURE__ */ jsx13("text", { className: "ss-w-om-ylab", x: 34, y: g.y + 3, textAnchor: "end", children: g.price.toFixed(2) })
1155
1186
  ] }, g.price)),
1156
- /* @__PURE__ */ jsx12("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
1157
- vm.geometry.markers.map((m, i) => /* @__PURE__ */ jsx12("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
1158
- ui?.chartTimeLabel ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
1159
- /* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
1160
- /* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
1161
- ] }) : /* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
1187
+ /* @__PURE__ */ jsx13("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
1188
+ vm.geometry.markers.map((m, i) => /* @__PURE__ */ jsx13("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
1189
+ ui?.chartTimeLabel ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
1190
+ /* @__PURE__ */ jsx13("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
1191
+ /* @__PURE__ */ jsx13("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
1192
+ ] }) : /* @__PURE__ */ jsx13("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
1162
1193
  ]
1163
1194
  }
1164
1195
  ),
@@ -1166,66 +1197,66 @@ function OddsMovementCard({ vm, ui }) {
1166
1197
  /* @__PURE__ */ jsxs9("span", { children: [
1167
1198
  ui?.openingLabel ?? "Opening",
1168
1199
  " ",
1169
- /* @__PURE__ */ jsx12("b", { children: vm.opening })
1200
+ /* @__PURE__ */ jsx13("b", { children: vm.opening })
1170
1201
  ] }),
1171
1202
  /* @__PURE__ */ jsxs9("span", { children: [
1172
1203
  ui?.currentLabel ?? "Current",
1173
1204
  " ",
1174
- /* @__PURE__ */ jsx12("b", { children: vm.current })
1205
+ /* @__PURE__ */ jsx13("b", { children: vm.current })
1175
1206
  ] })
1176
1207
  ] }),
1177
- vm.bookmaker ? /* @__PURE__ */ jsx12("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ jsx12("span", { children: vm.bookmaker }) }) : null,
1178
- vm.excludedCount > 0 ? /* @__PURE__ */ jsx12("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
1179
- vm.isSuspended ? /* @__PURE__ */ jsx12("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
1180
- vm.disclaimer ? /* @__PURE__ */ jsx12("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
1208
+ vm.bookmaker ? /* @__PURE__ */ jsx13("div", { className: "ss-w-om-foot", children: /* @__PURE__ */ jsx13("span", { children: vm.bookmaker }) }) : null,
1209
+ vm.excludedCount > 0 ? /* @__PURE__ */ jsx13("div", { className: "ss-w-om-excl", children: ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.` }) : null,
1210
+ vm.isSuspended ? /* @__PURE__ */ jsx13("div", { className: "ss-w-om-susp", children: ui?.selectionSuspended ?? "This selection is not currently available to bet." }) : null,
1211
+ vm.disclaimer ? /* @__PURE__ */ jsx13("div", { className: "ss-w-om-disc", children: vm.disclaimer }) : null
1181
1212
  ] });
1182
1213
  }
1183
1214
  function OddsMovementCardList({ cards, ui }) {
1184
1215
  if (!cards || cards.length === 0) return null;
1185
- return /* @__PURE__ */ jsx12("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ jsx12(OddsMovementCard, { vm, ui }, vm.id)) });
1216
+ return /* @__PURE__ */ jsx13("div", { className: "ss-w-omcards", children: cards.map((vm) => /* @__PURE__ */ jsx13(OddsMovementCard, { vm, ui }, vm.id)) });
1186
1217
  }
1187
1218
 
1188
1219
  // src/components/ActionButtons.tsx
1189
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1220
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1190
1221
  function ActionButtons({ actions, loading, disabled, onAct }) {
1191
1222
  if (actions.length === 0 && !loading) return null;
1192
1223
  return /* @__PURE__ */ jsxs10("div", { className: "ss-w-actions", children: [
1193
- actions.map((a, i) => /* @__PURE__ */ jsx13("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
1194
- actions.length === 0 && loading ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
1195
- /* @__PURE__ */ jsx13("span", { className: "ss-w-abtn-shimmer" }),
1196
- /* @__PURE__ */ jsx13("span", { className: "ss-w-abtn-shimmer" })
1224
+ actions.map((a, i) => /* @__PURE__ */ jsx14("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
1225
+ actions.length === 0 && loading ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1226
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-abtn-shimmer" }),
1227
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-abtn-shimmer" })
1197
1228
  ] }) : null
1198
1229
  ] });
1199
1230
  }
1200
1231
 
1201
1232
  // src/components/dashboard/DashboardTile.tsx
1202
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1233
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1203
1234
  var MAX_CRESTS = 3;
1204
1235
  function DashboardTile({ tile, onTap }) {
1205
1236
  const spanClass = tile.span === "full" ? "ss-w-dash-tile--full" : "ss-w-dash-tile--half";
1206
1237
  const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS);
1207
1238
  const hasMeta = Boolean(tile.badgeText) || crests.length > 0;
1208
1239
  return /* @__PURE__ */ jsxs11("button", { type: "button", className: `ss-w-dash-tile ${spanClass}`, onClick: onTap, children: [
1209
- /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ jsx14(DashboardIcon, { name: tile.icon }) }),
1240
+ /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-icon", children: /* @__PURE__ */ jsx15(DashboardIcon, { name: tile.icon }) }),
1210
1241
  /* @__PURE__ */ jsxs11("span", { className: "ss-w-dash-tile-body", children: [
1211
- /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-title", children: tile.title }),
1212
- tile.subtitle ? /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
1242
+ /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-title", children: tile.title }),
1243
+ tile.subtitle ? /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-subtitle", children: tile.subtitle }) : null,
1213
1244
  hasMeta ? (
1214
1245
  // Badge + crests sit on their own row, below the title, instead of sharing the
1215
1246
  // icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone
1216
1247
  // (~70px) left the title column at ~22px and forced character-by-character wrapping.
1217
1248
  /* @__PURE__ */ jsxs11("span", { className: "ss-w-dash-tile-meta", children: [
1218
- tile.badgeText ? /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
1219
- crests.length > 0 ? /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
1249
+ tile.badgeText ? /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-badge", children: tile.badgeText }) : null,
1250
+ crests.length > 0 ? /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-crests", children: crests.map((url, i) => /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-crest", style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" }, `${url}-${i}`)) }) : null
1220
1251
  ] })
1221
1252
  ) : null
1222
1253
  ] }),
1223
- /* @__PURE__ */ jsx14("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ jsx14(ChevronIcon, {}) })
1254
+ /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-tile-chevron", children: /* @__PURE__ */ jsx15(ChevronIcon, {}) })
1224
1255
  ] });
1225
1256
  }
1226
1257
 
1227
1258
  // src/components/dashboard/GreetingDashboard.tsx
1228
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1259
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1229
1260
  var LAYOUT_CLASSES = {
1230
1261
  market: "ss-w-dash--market",
1231
1262
  goal: "ss-w-dash--goal",
@@ -1237,35 +1268,35 @@ function layoutClass(layout) {
1237
1268
  function GreetingDashboard({ dashboard, onTap }) {
1238
1269
  return /* @__PURE__ */ jsxs12("div", { className: `ss-w-dash ${layoutClass(dashboard.layout)}`, children: [
1239
1270
  /* @__PURE__ */ jsxs12("div", { className: "ss-w-dash-head", children: [
1240
- /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-title", children: dashboard.title }),
1241
- dashboard.subtitle ? /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
1271
+ /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-title", children: dashboard.title }),
1272
+ dashboard.subtitle ? /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-subtitle", children: dashboard.subtitle }) : null
1242
1273
  ] }),
1243
- /* @__PURE__ */ jsx15("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ jsx15(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
1244
- dashboard.footerTip ? /* @__PURE__ */ jsx15("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
1274
+ /* @__PURE__ */ jsx16("div", { className: "ss-w-dash-grid", children: dashboard.tiles.map((t, i) => /* @__PURE__ */ jsx16(DashboardTile, { tile: t, onTap: () => onTap(t, i) }, `${t.title}-${i}`)) }),
1275
+ dashboard.footerTip ? /* @__PURE__ */ jsx16("span", { className: "ss-w-dash-foot", children: dashboard.footerTip }) : null
1245
1276
  ] });
1246
1277
  }
1247
1278
 
1248
1279
  // src/components/club-dashboard/GreetingHeaderBlock.tsx
1249
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1280
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1250
1281
  function GreetingHeaderBlock({ block }) {
1251
1282
  return /* @__PURE__ */ jsxs13("div", { className: "ss-w-cdash-greeting", children: [
1252
- /* @__PURE__ */ jsx16("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1253
- /* @__PURE__ */ jsx16("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1283
+ /* @__PURE__ */ jsx17("div", { className: "ss-w-cdash-greeting-title", children: block.title }),
1284
+ /* @__PURE__ */ jsx17("div", { className: "ss-w-cdash-greeting-subtitle", children: block.subtitle })
1254
1285
  ] });
1255
1286
  }
1256
1287
 
1257
1288
  // src/components/club-dashboard/FixtureHeroBlock.tsx
1258
- import { useState as useState5 } from "react";
1259
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1289
+ import { useState as useState6 } from "react";
1290
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1260
1291
  function initials3(name) {
1261
1292
  return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
1262
1293
  }
1263
1294
  function Crest3({ url, name }) {
1264
- const [broken, setBroken] = useState5(false);
1295
+ const [broken, setBroken] = useState6(false);
1265
1296
  if (!url || broken) {
1266
- return /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
1297
+ return /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
1267
1298
  }
1268
- return /* @__PURE__ */ jsx17("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1299
+ return /* @__PURE__ */ jsx18("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
1269
1300
  }
1270
1301
  function FixtureHeroBlock({
1271
1302
  block,
@@ -1274,67 +1305,101 @@ function FixtureHeroBlock({
1274
1305
  }) {
1275
1306
  return /* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-fixture", children: [
1276
1307
  /* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-tie", children: [
1277
- /* @__PURE__ */ jsx17(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
1278
- /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-team", children: block.homeName }),
1279
- /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-vs", children: "v" }),
1280
- /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-team", children: block.awayName }),
1281
- /* @__PURE__ */ jsx17(Crest3, { url: block.awayCrestUrl, name: block.awayName })
1308
+ /* @__PURE__ */ jsx18(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
1309
+ /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-team", children: block.homeName }),
1310
+ /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-vs", children: "v" }),
1311
+ /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-team", children: block.awayName }),
1312
+ /* @__PURE__ */ jsx18(Crest3, { url: block.awayCrestUrl, name: block.awayName })
1282
1313
  ] }),
1283
1314
  /* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-fixture-meta", children: [
1284
- /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1285
- block.venue ? /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1286
- block.competition ? /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1315
+ /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
1316
+ block.venue ? /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-venue", children: block.venue }) : null,
1317
+ block.competition ? /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-comp", children: block.competition }) : null
1287
1318
  ] }),
1288
- /* @__PURE__ */ jsx17("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, block.ctaLabel), children: block.ctaLabel })
1319
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "ss-w-cdash-cta", onClick: () => onAction(block.ctaActionValue, void 0, block.ctaLabel), children: block.ctaLabel })
1289
1320
  ] });
1290
1321
  }
1291
1322
 
1292
1323
  // src/components/club-dashboard/FormGuideBlock.tsx
1293
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1324
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
1294
1325
  function FormGuideBlock({ block }) {
1295
1326
  if (block.rows.length === 0) return null;
1296
- return /* @__PURE__ */ jsx18("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ jsxs15("div", { className: "ss-w-cdash-form-row", children: [
1327
+ return /* @__PURE__ */ jsx19("div", { className: "ss-w-cdash-form", children: block.rows.map((row) => /* @__PURE__ */ jsxs15("div", { className: "ss-w-cdash-form-row", children: [
1297
1328
  /* @__PURE__ */ jsxs15("span", { className: "ss-w-cdash-form-name", children: [
1298
1329
  row.name,
1299
1330
  row.position != null ? ` #${row.position}` : ""
1300
1331
  ] }),
1301
- /* @__PURE__ */ jsx18("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ jsx18("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
1332
+ /* @__PURE__ */ jsx19("span", { className: "ss-w-cdash-form-pills", children: row.last5.map((r, i) => /* @__PURE__ */ jsx19("span", { className: `ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`, children: r }, i)) })
1302
1333
  ] }, row.name)) });
1303
1334
  }
1304
1335
 
1305
1336
  // src/components/club-dashboard/MatchPreviewBlock.tsx
1306
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1337
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1307
1338
  function MatchPreviewBlock({
1308
1339
  block,
1309
1340
  ui,
1310
1341
  onAction
1311
1342
  }) {
1312
- if (block.lines.length === 0) return null;
1343
+ if (block.facts.length === 0) return null;
1313
1344
  const heading = ui.clubMatchPreviewHeading;
1314
- return /* @__PURE__ */ jsxs16("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
1315
- /* @__PURE__ */ jsx19("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1316
- block.lines.map((line, i) => /* @__PURE__ */ jsx19("p", { children: line }, i))
1345
+ return /* @__PURE__ */ jsxs16("div", { className: "ss-w-cdash-lines", children: [
1346
+ /* @__PURE__ */ jsx20("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1347
+ block.facts.map(
1348
+ (f, i) => f.entityRef ? /* @__PURE__ */ jsxs16(
1349
+ "button",
1350
+ {
1351
+ type: "button",
1352
+ className: "ss-w-cdash-fact",
1353
+ onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
1354
+ children: [
1355
+ f.sentence,
1356
+ f.label ? /* @__PURE__ */ jsxs16("span", { className: "ss-w-cdash-fact-label", children: [
1357
+ " ",
1358
+ f.label
1359
+ ] }) : null
1360
+ ]
1361
+ },
1362
+ i
1363
+ ) : /* @__PURE__ */ jsx20("p", { children: f.sentence }, i)
1364
+ )
1317
1365
  ] });
1318
1366
  }
1319
1367
 
1320
1368
  // src/components/club-dashboard/TeamDnaBlock.tsx
1321
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1369
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1322
1370
  function TeamDnaBlock({
1323
1371
  block,
1324
1372
  ui,
1325
1373
  onAction
1326
1374
  }) {
1327
- if (block.lines.length === 0) return null;
1375
+ if (block.facts.length === 0) return null;
1328
1376
  const heading = ui.clubTeamDnaHeading;
1329
- return /* @__PURE__ */ jsxs17("button", { type: "button", className: "ss-w-cdash-lines", onClick: () => onAction(block.actionValue, heading), children: [
1330
- /* @__PURE__ */ jsx20("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1331
- block.lines.map((line, i) => /* @__PURE__ */ jsx20("p", { children: line }, i))
1377
+ return /* @__PURE__ */ jsxs17("div", { className: "ss-w-cdash-lines", children: [
1378
+ /* @__PURE__ */ jsx21("span", { className: "ss-w-cdash-lines-heading", children: heading }),
1379
+ block.facts.map(
1380
+ (f, i) => f.entityRef ? /* @__PURE__ */ jsxs17(
1381
+ "button",
1382
+ {
1383
+ type: "button",
1384
+ className: "ss-w-cdash-fact",
1385
+ onClick: () => onAction(f.question ?? f.sentence, { ...f.entityRef, subject: f.sentence, personaHint: "club" }),
1386
+ children: [
1387
+ f.sentence,
1388
+ f.label ? /* @__PURE__ */ jsxs17("span", { className: "ss-w-cdash-fact-label", children: [
1389
+ " ",
1390
+ f.label
1391
+ ] }) : null
1392
+ ]
1393
+ },
1394
+ i
1395
+ ) : /* @__PURE__ */ jsx21("p", { children: f.sentence }, i)
1396
+ )
1332
1397
  ] });
1333
1398
  }
1334
1399
 
1335
1400
  // src/components/club-dashboard/CountdownBlock.tsx
1336
- import { useEffect as useEffect3, useState as useState6 } from "react";
1337
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1401
+ import { useEffect as useEffect3, useState as useState7 } from "react";
1402
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1338
1403
  var DAY_MS = 24 * 3600 * 1e3;
1339
1404
  function pad2(n) {
1340
1405
  return String(n).padStart(2, "0");
@@ -1347,7 +1412,7 @@ function splitRemaining(remainingMs) {
1347
1412
  return { h: pad2(h), m: pad2(m), s: pad2(s) };
1348
1413
  }
1349
1414
  function CountdownBlock({ block, ui }) {
1350
- const [remainingMs, setRemainingMs] = useState6(() => block.kickoffUnix * 1e3 - Date.now());
1415
+ const [remainingMs, setRemainingMs] = useState7(() => block.kickoffUnix * 1e3 - Date.now());
1351
1416
  useEffect3(() => {
1352
1417
  setRemainingMs(block.kickoffUnix * 1e3 - Date.now());
1353
1418
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
@@ -1361,28 +1426,28 @@ function CountdownBlock({ block, ui }) {
1361
1426
  const { h, m, s } = splitRemaining(remainingMs);
1362
1427
  return /* @__PURE__ */ jsxs18("div", { className: "ss-w-cdash-cd", "aria-label": ui.clubKickoffAria(block.kickoffUnix * 1e3), children: [
1363
1428
  /* @__PURE__ */ jsxs18("div", { className: "ss-w-cdash-cd-clock", "aria-hidden": "true", children: [
1364
- /* @__PURE__ */ jsx21("span", { className: "ss-w-cdash-cd-h", children: h }),
1429
+ /* @__PURE__ */ jsx22("span", { className: "ss-w-cdash-cd-h", children: h }),
1365
1430
  "h",
1366
1431
  " ",
1367
- /* @__PURE__ */ jsx21("span", { className: "ss-w-cdash-cd-m", children: m }),
1432
+ /* @__PURE__ */ jsx22("span", { className: "ss-w-cdash-cd-m", children: m }),
1368
1433
  "m",
1369
1434
  " ",
1370
- /* @__PURE__ */ jsx21("span", { className: "ss-w-cdash-cd-s", children: s }),
1435
+ /* @__PURE__ */ jsx22("span", { className: "ss-w-cdash-cd-s", children: s }),
1371
1436
  "s"
1372
1437
  ] }),
1373
- /* @__PURE__ */ jsx21("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1438
+ /* @__PURE__ */ jsx22("div", { className: "ss-w-cdash-cd-label", children: ui.clubCountdownLabel })
1374
1439
  ] });
1375
1440
  }
1376
1441
 
1377
1442
  // src/components/club-dashboard/ClubDashboard.tsx
1378
- import { jsx as jsx22 } from "react/jsx-runtime";
1443
+ import { jsx as jsx23 } from "react/jsx-runtime";
1379
1444
  var CLUB_BLOCK_REGISTRY = {
1380
- greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ jsx22(GreetingHeaderBlock, { block }) : null,
1381
- fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ jsx22(FixtureHeroBlock, { block, ui, onAction }) : null,
1382
- formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ jsx22(FormGuideBlock, { block, ui }) : null,
1383
- matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ jsx22(MatchPreviewBlock, { block, ui, onAction }) : null,
1384
- teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ jsx22(TeamDnaBlock, { block, ui, onAction }) : null,
1385
- countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ jsx22(CountdownBlock, { block, ui }) : null
1445
+ greetingHeader: ({ block }) => block.type === "greetingHeader" ? /* @__PURE__ */ jsx23(GreetingHeaderBlock, { block }) : null,
1446
+ fixtureHero: ({ block, ui, onAction }) => block.type === "fixtureHero" ? /* @__PURE__ */ jsx23(FixtureHeroBlock, { block, ui, onAction }) : null,
1447
+ formGuide: ({ block, ui }) => block.type === "formGuide" ? /* @__PURE__ */ jsx23(FormGuideBlock, { block, ui }) : null,
1448
+ matchPreview: ({ block, ui, onAction }) => block.type === "matchPreview" ? /* @__PURE__ */ jsx23(MatchPreviewBlock, { block, ui, onAction }) : null,
1449
+ teamDna: ({ block, ui, onAction }) => block.type === "teamDna" ? /* @__PURE__ */ jsx23(TeamDnaBlock, { block, ui, onAction }) : null,
1450
+ countdown: ({ block, ui }) => block.type === "countdown" ? /* @__PURE__ */ jsx23(CountdownBlock, { block, ui }) : null
1386
1451
  };
1387
1452
  function ClubDashboard({
1388
1453
  dashboard,
@@ -1390,39 +1455,39 @@ function ClubDashboard({
1390
1455
  onAction
1391
1456
  }) {
1392
1457
  if (!dashboard.blocks.length) return null;
1393
- return /* @__PURE__ */ jsx22("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1458
+ return /* @__PURE__ */ jsx23("div", { className: "ss-w-cdash", children: dashboard.blocks.map((block, i) => {
1394
1459
  const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type) ? CLUB_BLOCK_REGISTRY[block.type] : void 0;
1395
1460
  if (!Comp) {
1396
1461
  console.warn(`[club-dashboard] no renderer for block type "${block.type}"`);
1397
1462
  return null;
1398
1463
  }
1399
- return /* @__PURE__ */ jsx22("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ jsx22(Comp, { block, ui, onAction }) }, i);
1464
+ return /* @__PURE__ */ jsx23("div", { className: "ss-w-cdash-block", children: /* @__PURE__ */ jsx23(Comp, { block, ui, onAction }) }, i);
1400
1465
  }) });
1401
1466
  }
1402
1467
 
1403
1468
  // src/components/ChatMessage.tsx
1404
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
1469
+ import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
1405
1470
  function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }) {
1406
1471
  if (message.role === "user") {
1407
- return /* @__PURE__ */ jsx23("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx23("div", { className: "ss-w-bubble", children: message.text }) });
1472
+ return /* @__PURE__ */ jsx24("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx24("div", { className: "ss-w-bubble", children: message.text }) });
1408
1473
  }
1409
1474
  return /* @__PURE__ */ jsxs19("div", { className: "ss-w-msg ss-w-bot", children: [
1410
- message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ jsx23(Markdown, { text: message.text }) : null,
1411
- message.greetingDashboard ? /* @__PURE__ */ jsx23(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1412
- message.clubDashboard && ui ? /* @__PURE__ */ jsx23(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1413
- /* @__PURE__ */ jsx23(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1414
- /* @__PURE__ */ jsx23(BettingInsightList, { insights: message.insights, ui, slip }),
1415
- /* @__PURE__ */ jsx23(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1416
- /* @__PURE__ */ jsx23(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1417
- /* @__PURE__ */ jsx23(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1475
+ message.text && !message.greetingDashboard && !message.clubDashboard ? /* @__PURE__ */ jsx24(Markdown, { text: message.text }) : null,
1476
+ message.greetingDashboard ? /* @__PURE__ */ jsx24(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1477
+ message.clubDashboard && ui ? /* @__PURE__ */ jsx24(ClubDashboard, { dashboard: message.clubDashboard, ui, onAction: onClubAction }) : null,
1478
+ /* @__PURE__ */ jsx24(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
1479
+ /* @__PURE__ */ jsx24(BettingInsightList, { insights: message.insights, ui, slip }),
1480
+ /* @__PURE__ */ jsx24(MarketOddsCardList, { cards: message.marketOdds, ui, slip }),
1481
+ /* @__PURE__ */ jsx24(OddsMovementCardList, { cards: message.oddsMovement, ui }),
1482
+ /* @__PURE__ */ jsx24(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
1418
1483
  ] });
1419
1484
  }
1420
1485
 
1421
1486
  // src/components/IntentChips.tsx
1422
- import { jsx as jsx24 } from "react/jsx-runtime";
1487
+ import { jsx as jsx25 } from "react/jsx-runtime";
1423
1488
  function IntentChips({ chips, onPick }) {
1424
1489
  if (chips.length === 0) return null;
1425
- return /* @__PURE__ */ jsx24("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx24("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1490
+ return /* @__PURE__ */ jsx25("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx25("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
1426
1491
  }
1427
1492
 
1428
1493
  // src/scroll.ts
@@ -1432,7 +1497,7 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1432
1497
  }
1433
1498
 
1434
1499
  // src/components/MessageList.tsx
1435
- import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
1500
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1436
1501
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1437
1502
  const { state, send } = controller;
1438
1503
  const listRef = useRef2(null);
@@ -1453,7 +1518,7 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1453
1518
  if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
1454
1519
  },
1455
1520
  children: [
1456
- state.messages.map((m) => /* @__PURE__ */ jsx25(
1521
+ state.messages.map((m) => /* @__PURE__ */ jsx26(
1457
1522
  ChatMessage,
1458
1523
  {
1459
1524
  message: m,
@@ -1463,31 +1528,31 @@ function MessageList({ controller, ui, slip, onDashboardTap }) {
1463
1528
  send(tile.actionValue, { displayText: tile.title });
1464
1529
  if (m.role === "assistant" && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout);
1465
1530
  },
1466
- onClubAction: (actionValue, displayText) => send(actionValue, { displayText }),
1531
+ onClubAction: (message, grounding, displayText) => send(message, { grounding, displayText: displayText ?? message }),
1467
1532
  ui,
1468
1533
  slip
1469
1534
  },
1470
1535
  m.id
1471
1536
  )),
1472
- state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx25(ActionButtons, { actions: [], loading: true, onAct: () => {
1537
+ state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx26(ActionButtons, { actions: [], loading: true, onAct: () => {
1473
1538
  } }) : null,
1474
- state.status ? /* @__PURE__ */ jsx25("div", { className: "ss-w-status", children: state.status }) : null,
1539
+ state.status ? /* @__PURE__ */ jsx26("div", { className: "ss-w-status", children: state.status }) : null,
1475
1540
  state.error ? /* @__PURE__ */ jsxs20("div", { className: "ss-w-error", role: "alert", children: [
1476
- /* @__PURE__ */ jsx25("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1477
- /* @__PURE__ */ jsx25("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1541
+ /* @__PURE__ */ jsx26("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
1542
+ /* @__PURE__ */ jsx26("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
1478
1543
  ] }) : null,
1479
- !hasUserMessage && !hasDashboard ? /* @__PURE__ */ jsx25(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1480
- /* @__PURE__ */ jsx25("div", { ref: endRef })
1544
+ !hasUserMessage && !hasDashboard ? /* @__PURE__ */ jsx26(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
1545
+ /* @__PURE__ */ jsx26("div", { ref: endRef })
1481
1546
  ]
1482
1547
  }
1483
1548
  );
1484
1549
  }
1485
1550
 
1486
1551
  // src/components/ChatInput.tsx
1487
- import { useState as useState7 } from "react";
1488
- import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
1552
+ import { useState as useState8 } from "react";
1553
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
1489
1554
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
1490
- const [value, setValue] = useState7("");
1555
+ const [value, setValue] = useState8("");
1491
1556
  const submit = () => {
1492
1557
  const t = value.trim();
1493
1558
  if (!t) return;
@@ -1501,16 +1566,16 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
1501
1566
  }
1502
1567
  };
1503
1568
  return /* @__PURE__ */ jsxs21("div", { className: "ss-w-input", children: [
1504
- /* @__PURE__ */ jsx26("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1505
- streaming ? /* @__PURE__ */ jsx26("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx26("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx26("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx26(SendIcon, {}) })
1569
+ /* @__PURE__ */ jsx27("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
1570
+ streaming ? /* @__PURE__ */ jsx27("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx27("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx27("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx27(SendIcon, {}) })
1506
1571
  ] });
1507
1572
  }
1508
1573
 
1509
1574
  // src/components/ChatPanel.tsx
1510
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
1575
+ import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
1511
1576
  var FULLSCREEN_QUERY = "(max-width: 639px)";
1512
1577
  function useIsModal() {
1513
- const [modal, setModal] = useState8(false);
1578
+ const [modal, setModal] = useState9(false);
1514
1579
  useEffect5(() => {
1515
1580
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1516
1581
  const mql = window.matchMedia(FULLSCREEN_QUERY);
@@ -1532,9 +1597,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap }) {
1532
1597
  return () => window.removeEventListener("keydown", onKey);
1533
1598
  }, [close]);
1534
1599
  return /* @__PURE__ */ jsxs22("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
1535
- /* @__PURE__ */ jsx27(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1536
- /* @__PURE__ */ jsx27(MessageList, { controller, ui, slip, onDashboardTap }),
1537
- /* @__PURE__ */ jsx27(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1600
+ /* @__PURE__ */ jsx28(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
1601
+ /* @__PURE__ */ jsx28(MessageList, { controller, ui, slip, onDashboardTap }),
1602
+ /* @__PURE__ */ jsx28(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
1538
1603
  ] });
1539
1604
  }
1540
1605
 
@@ -1582,7 +1647,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1582
1647
  .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; }
1583
1648
 
1584
1649
  /* panel */
1585
- .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); }
1650
+ .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); }
1586
1651
  .ss-w-root[data-ss-w-pos="right"] .ss-w-panel { right: var(--ss-w-offset-x); }
1587
1652
  .ss-w-root[data-ss-w-pos="left"] .ss-w-panel { left: var(--ss-w-offset-x); }
1588
1653
  @media (max-width: 639px) {
@@ -1685,9 +1750,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1685
1750
  .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; }
1686
1751
 
1687
1752
  /* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */
1688
- .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; }
1689
- .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); }
1690
- .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)); }
1753
+ .ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
1754
+ .ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }
1755
+ .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)); }
1691
1756
 
1692
1757
  /* row 2: crest-flanked fixture on the left, boxed action panel on the right */
1693
1758
  .ss-w-bi-body { display: flex; align-items: center; gap: 10px; }
@@ -1695,16 +1760,16 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1695
1760
  .ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1696
1761
  .ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }
1697
1762
  .ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1698
- .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; }
1699
- .ss-w-bi-action .ss-w-slip > button { flex: 1; text-align: center; }
1763
+ .ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }
1764
+ .ss-w-bi-action .ss-w-slip { width: 100%; }
1765
+ .ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }
1700
1766
  /* 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. */
1701
1767
  .ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
1702
- .ss-w-bi-mkt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
1703
- .ss-w-bi-market { font-size: 13.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }
1704
- .ss-w-bi-sel { font-size: 11.5px; line-height: 1.3; color: var(--ss-w-faint); }
1705
- .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; }
1706
- .ss-w-bi-odds-cap { font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }
1707
- .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; }
1768
+ .ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }
1769
+ .ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }
1770
+ .ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }
1771
+ .ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }
1772
+ .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; }
1708
1773
  .ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
1709
1774
 
1710
1775
  /* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
@@ -1718,11 +1783,11 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1718
1783
  }
1719
1784
  .ss-w-bi-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
1720
1785
  .ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
1721
- .ss-w-bi-stats { display: flex; flex-direction: column; gap: 8px; }
1722
- .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; }
1723
- .ss-w-bi-toggle:hover { text-decoration: underline; }
1724
- .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; }
1725
- .ss-w-bi-chev-up { transform: translateY(1px) rotate(-135deg); }
1786
+ .ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
1787
+ .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; }
1788
+ .ss-w-bi-expand:hover { color: var(--ss-w-ink); }
1789
+ .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; }
1790
+ .ss-w-bi-arrow-open { transform: rotate(135deg); }
1726
1791
  .ss-w-bi-rows { display: flex; flex-direction: column; }
1727
1792
  .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); }
1728
1793
  .ss-w-bi-row:first-child { border-top: none; }
@@ -1737,11 +1802,13 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1737
1802
  /* market odds card */
1738
1803
  .ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
1739
1804
  .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; }
1740
- .ss-w-mo-head { display: flex; align-items: center; gap: 8px; }
1741
- .ss-w-mo-market { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
1742
- .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; }
1743
- .ss-w-mo-fixture { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }
1744
- .ss-w-mo-comp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1805
+ .ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
1806
+ .ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1807
+ .ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
1808
+ .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; }
1809
+ .ss-w-mo-more:hover { text-decoration: underline; }
1810
+ .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; }
1811
+ .ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }
1745
1812
  .ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
1746
1813
  .ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
1747
1814
  .ss-w-mo-row:last-child { border-bottom: none; }
@@ -1913,9 +1980,12 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1913
1980
  .ss-w-cdash-pill--d { background: var(--ss-w-faint); }
1914
1981
  .ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }
1915
1982
 
1916
- .ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; font: inherit; cursor: pointer; }
1983
+ .ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; }
1917
1984
  .ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }
1918
- .ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); }
1985
+ .ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); margin: 0; }
1986
+ .ss-w-cdash-fact { display: block; width: 100%; text-align: left; font: inherit; font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); background: none; border: none; padding: 0; cursor: pointer; }
1987
+ .ss-w-cdash-fact:hover, .ss-w-cdash-fact:focus-visible { color: var(--ss-w-accent); text-decoration: underline; }
1988
+ .ss-w-cdash-fact-label { font-size: 11px; font-weight: 700; color: var(--ss-w-accent); }
1919
1989
 
1920
1990
  .ss-w-cdash-cd { display: flex; flex-direction: column; align-items: center; gap: 4px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; text-align: center; }
1921
1991
  .ss-w-cdash-cd-clock { display: flex; align-items: baseline; justify-content: center; gap: 2px; font-variant-numeric: tabular-nums; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-weight: 700; font-size: 18px; color: var(--ss-w-ink); }
@@ -1924,7 +1994,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
1924
1994
  `;
1925
1995
 
1926
1996
  // src/StatsWidget.tsx
1927
- import { jsx as jsx28 } from "react/jsx-runtime";
1997
+ import { jsx as jsx29 } from "react/jsx-runtime";
1928
1998
  function buildClient(props) {
1929
1999
  try {
1930
2000
  if ("client" in props && props.client) {
@@ -1977,7 +2047,7 @@ function StatsWidget(props) {
1977
2047
  }, [built, ui.injectStyles]);
1978
2048
  if (!built) return null;
1979
2049
  const attrs = themeAttrs(ui);
1980
- return /* @__PURE__ */ jsx28("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__ */ jsx28(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ jsx28(
2050
+ return /* @__PURE__ */ jsx29("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__ */ jsx29(ChatPanel, { controller, ui, slip, onDashboardTap }) : /* @__PURE__ */ jsx29(
1981
2051
  ChatFab,
1982
2052
  {
1983
2053
  label: ui.launcherLabel,