@sensiblestats/widget-react 0.36.0 → 0.37.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
@@ -120,7 +120,10 @@ var STRINGS = {
120
120
  fullTimeLabel: "Full time",
121
121
  inSlipLabel: "In slip",
122
122
  oddsUnavailable: "Odds unavailable right now",
123
- momentumLabel: "Momentum"
123
+ momentumLabel: "Momentum",
124
+ accordionValueLabel: "Value",
125
+ accordionRetry: "Couldn't load odds \u2014 tap to retry",
126
+ accordionSuspended: "Suspended"
124
127
  },
125
128
  tr: {
126
129
  launcherLabel: "SensibleStats ile sohbet et",
@@ -189,7 +192,10 @@ var STRINGS = {
189
192
  fullTimeLabel: "Ma\xE7 sonu",
190
193
  inSlipLabel: "Kuponda",
191
194
  oddsUnavailable: "Oranlar \u015Fu anda kullan\u0131lam\u0131yor",
192
- momentumLabel: "Momentum"
195
+ momentumLabel: "Momentum",
196
+ accordionValueLabel: "De\u011Fer",
197
+ accordionRetry: "Oranlar y\xFCklenemedi \u2014 yeniden dene",
198
+ accordionSuspended: "Ask\u0131da"
193
199
  }
194
200
  };
195
201
  function resolveLocaleStrings(locale) {
@@ -277,7 +283,10 @@ function normalizeUi(cfg) {
277
283
  fullTimeLabel: strings.fullTimeLabel,
278
284
  inSlipLabel: strings.inSlipLabel,
279
285
  oddsUnavailable: strings.oddsUnavailable,
280
- momentumLabel: strings.momentumLabel
286
+ momentumLabel: strings.momentumLabel,
287
+ accordionValueLabel: strings.accordionValueLabel,
288
+ accordionRetry: strings.accordionRetry,
289
+ accordionSuspended: strings.accordionSuspended
281
290
  };
282
291
  }
283
292
  function toClientOptions(cfg) {
@@ -1031,6 +1040,8 @@ function useLiveMonitor(opts) {
1031
1040
  const [oddsDot, setOddsDot] = (0, import_react3.useState)(false);
1032
1041
  const [lastViewedPrices, setLastViewedPrices] = (0, import_react3.useState)({});
1033
1042
  const [inSlip, setInSlip] = (0, import_react3.useState)({});
1043
+ const [openMarket, setOpenMarket] = (0, import_react3.useState)({});
1044
+ const [marketOdds, setMarketOdds] = (0, import_react3.useState)({});
1034
1045
  const pinsRef = (0, import_react3.useRef)(pins);
1035
1046
  pinsRef.current = pins;
1036
1047
  const activeTabRef = (0, import_react3.useRef)(activeTab);
@@ -1039,6 +1050,46 @@ function useLiveMonitor(opts) {
1039
1050
  snapshotRef.current = snapshot;
1040
1051
  const lastViewedPricesRef = (0, import_react3.useRef)(lastViewedPrices);
1041
1052
  lastViewedPricesRef.current = lastViewedPrices;
1053
+ const openMarketRef = (0, import_react3.useRef)(openMarket);
1054
+ openMarketRef.current = openMarket;
1055
+ const marketOddsRef = (0, import_react3.useRef)(marketOdds);
1056
+ marketOddsRef.current = marketOdds;
1057
+ const marketKey = (matchId, dev) => `${matchId}:${dev}`;
1058
+ const getMarketOddsRef = (0, import_react3.useRef)(opts.getMarketOdds);
1059
+ getMarketOddsRef.current = opts.getMarketOdds;
1060
+ const fetchMarket = (0, import_react3.useCallback)((matchId, dev) => {
1061
+ const key = marketKey(matchId, dev);
1062
+ const existing = marketOddsRef.current[key];
1063
+ if (existing?.loading) return;
1064
+ const loadingEntry = { ...existing, loading: true, error: false };
1065
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: loadingEntry };
1066
+ setMarketOdds((prev) => ({ ...prev, [key]: loadingEntry }));
1067
+ const fn = getMarketOddsRef.current;
1068
+ if (!fn) return;
1069
+ void fn(matchId, dev).then((block) => {
1070
+ const entry = { block: block ?? void 0, loading: false, error: false };
1071
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: entry };
1072
+ setMarketOdds((prev) => ({ ...prev, [key]: entry }));
1073
+ }).catch(() => {
1074
+ const entry = { ...marketOddsRef.current[key], loading: false, error: true };
1075
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: entry };
1076
+ setMarketOdds((prev) => ({ ...prev, [key]: entry }));
1077
+ });
1078
+ }, []);
1079
+ const toggleMarket = (0, import_react3.useCallback)((matchId, dev) => {
1080
+ const key = marketKey(matchId, dev);
1081
+ const wasOpen = openMarketRef.current[matchId] === dev;
1082
+ const nextValue = wasOpen ? null : dev;
1083
+ openMarketRef.current = { ...openMarketRef.current, [matchId]: nextValue };
1084
+ setOpenMarket((prev) => ({ ...prev, [matchId]: nextValue }));
1085
+ const existing = marketOddsRef.current[key];
1086
+ if (!wasOpen && !(existing?.loading || existing?.block)) {
1087
+ fetchMarket(matchId, dev);
1088
+ }
1089
+ }, [fetchMarket]);
1090
+ const retryMarket = (0, import_react3.useCallback)((matchId, dev) => {
1091
+ fetchMarket(matchId, dev);
1092
+ }, [fetchMarket]);
1042
1093
  const applySnapshot = (0, import_react3.useCallback)((next) => {
1043
1094
  if (next === null) {
1044
1095
  setEnabled(false);
@@ -1058,6 +1109,16 @@ function useLiveMonitor(opts) {
1058
1109
  }
1059
1110
  }
1060
1111
  if (sawNewGoalOrRed && activeTabRef.current !== "matches") setMatchesDot(true);
1112
+ for (const m of next.matches) {
1113
+ if (!pinnedMatchIds.has(m.matchId)) continue;
1114
+ const first = m.availableMarkets?.[0];
1115
+ if (!first) continue;
1116
+ if (m.matchId in openMarketRef.current) continue;
1117
+ const dev = first.marketDeveloperName;
1118
+ openMarketRef.current = { ...openMarketRef.current, [m.matchId]: dev };
1119
+ setOpenMarket((prevOpen) => ({ ...prevOpen, [m.matchId]: dev }));
1120
+ fetchMarket(m.matchId, dev);
1121
+ }
1061
1122
  const marketPins = currentPins.filter((p) => p.kind !== "match");
1062
1123
  if (activeTabRef.current === "odds") {
1063
1124
  setLastViewedPrices((prevMap) => {
@@ -1108,12 +1169,17 @@ function useLiveMonitor(opts) {
1108
1169
  return;
1109
1170
  }
1110
1171
  applySnapshot(snap);
1172
+ for (const m of snap.matches) {
1173
+ if (m.phase !== "live") continue;
1174
+ const dev = openMarketRef.current[m.matchId];
1175
+ if (dev) fetchMarket(m.matchId, dev);
1176
+ }
1111
1177
  } catch {
1112
1178
  } finally {
1113
1179
  inFlightRef.current = false;
1114
1180
  scheduleRef.current();
1115
1181
  }
1116
- }, [applySnapshot]);
1182
+ }, [applySnapshot, fetchMarket]);
1117
1183
  const scheduleRef = (0, import_react3.useRef)(() => {
1118
1184
  });
1119
1185
  scheduleRef.current = () => {
@@ -1191,6 +1257,10 @@ function useLiveMonitor(opts) {
1191
1257
  lastViewedPrices,
1192
1258
  inSlip,
1193
1259
  markInSlip,
1260
+ openMarket,
1261
+ marketOdds,
1262
+ toggleMarket,
1263
+ retryMarket,
1194
1264
  _setSnapshot: applySnapshot
1195
1265
  };
1196
1266
  }
@@ -1731,48 +1801,50 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
1731
1801
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1732
1802
  ] });
1733
1803
  }
1734
- function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds }) {
1804
+ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader }) {
1735
1805
  const [open, setOpen] = (0, import_react12.useState)(false);
1736
1806
  const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1737
1807
  const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
1738
1808
  const showPin = !!monitor && vm.pinEnabled;
1739
1809
  const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin;
1740
1810
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-mocard", children: [
1741
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-bi-header", children: [
1742
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1743
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1744
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-comp", children: vm.competition })
1745
- ] }) : null }),
1746
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-header-right", children: [
1747
- vm.isLive ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-live", children: [
1748
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1749
- ui?.liveLabel ?? "Live"
1750
- ] }) : null,
1751
- kickoff ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-kick", children: [
1752
- kickoff.dayLabel,
1753
- " ",
1754
- kickoff.time
1755
- ] }) : null,
1756
- showPin && ui ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1757
- PinToggle,
1758
- {
1759
- ui,
1760
- monitor,
1761
- pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1762
- }
1763
- ) : null
1764
- ] })
1765
- ] }) : null,
1766
- hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-mo-sub", children: [
1767
- hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-bi-fixture", children: [
1768
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1769
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1770
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1771
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1772
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1773
- ] }) : vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1774
- vm.market ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-mo-market", children: vm.market }) : null
1775
- ] }) : null,
1811
+ !hideHeader && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1812
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-bi-header", children: [
1813
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1814
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1815
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-comp", children: vm.competition })
1816
+ ] }) : null }),
1817
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-header-right", children: [
1818
+ vm.isLive ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-live", children: [
1819
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1820
+ ui?.liveLabel ?? "Live"
1821
+ ] }) : null,
1822
+ kickoff ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "ss-w-bi-kick", children: [
1823
+ kickoff.dayLabel,
1824
+ " ",
1825
+ kickoff.time
1826
+ ] }) : null,
1827
+ showPin && ui ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1828
+ PinToggle,
1829
+ {
1830
+ ui,
1831
+ monitor,
1832
+ pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1833
+ }
1834
+ ) : null
1835
+ ] })
1836
+ ] }) : null,
1837
+ hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-mo-sub", children: [
1838
+ hasNamedTeams ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-bi-fixture", children: [
1839
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1840
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1843
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1844
+ ] }) : vm.fixture ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1845
+ vm.market ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ss-w-mo-market", children: vm.market }) : null
1846
+ ] }) : null
1847
+ ] }),
1776
1848
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ss-w-mo-rows", children: [
1777
1849
  vm.mainRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)),
1778
1850
  open ? vm.moreRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)) : null
@@ -1785,9 +1857,9 @@ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds }) {
1785
1857
  vm.disclaimer ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1786
1858
  ] });
1787
1859
  }
1788
- function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds }) {
1860
+ function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds, hideHeader }) {
1789
1861
  if (!cards || cards.length === 0) return null;
1790
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds }, vm.id)) });
1862
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds, hideHeader }, vm.id)) });
1791
1863
  }
1792
1864
 
1793
1865
  // src/components/OddsMovementCard.tsx
@@ -2897,8 +2969,63 @@ function TabBar({ monitor, ui, matchCount, oddsCount }) {
2897
2969
  }) });
2898
2970
  }
2899
2971
 
2900
- // src/components/MonitorMatchCard.tsx
2972
+ // src/components/MarketAccordion.tsx
2901
2973
  var import_jsx_runtime46 = require("react/jsx-runtime");
2974
+ function MarketAccordion({ match, monitor, ui, slip }) {
2975
+ const markets = match.availableMarkets ?? [];
2976
+ if (markets.length === 0) return null;
2977
+ const open = monitor.openMarket[match.matchId] ?? null;
2978
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "ss-w-acc", children: markets.map((m) => {
2979
+ const isOpen = open === m.marketDeveloperName;
2980
+ const key = `${match.matchId}:${m.marketDeveloperName}`;
2981
+ const entry = monitor.marketOdds[key];
2982
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: isOpen ? "ss-w-acc-row ss-w-acc-row-open" : "ss-w-acc-row", children: [
2983
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
2984
+ "button",
2985
+ {
2986
+ type: "button",
2987
+ className: "ss-w-acc-head",
2988
+ onClick: () => monitor.toggleMarket(match.matchId, m.marketDeveloperName),
2989
+ children: [
2990
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-chevron", children: isOpen ? "\u25BE" : "\u25B8" }),
2991
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-label", children: m.marketLabel }),
2992
+ m.hasInsight && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-badge", children: "\u2605" }),
2993
+ m.suspended && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-susp", children: ui.accordionSuspended })
2994
+ ]
2995
+ }
2996
+ ),
2997
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-acc-panel", children: [
2998
+ entry?.error && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2999
+ "div",
3000
+ {
3001
+ className: "ss-w-acc-retry",
3002
+ onClick: () => monitor.retryMarket(match.matchId, m.marketDeveloperName),
3003
+ children: ui.accordionRetry
3004
+ }
3005
+ ),
3006
+ entry?.block?.insight?.text && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-acc-insight", children: [
3007
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-acc-badge", children: ui.accordionValueLabel }),
3008
+ " ",
3009
+ entry.block.insight.text
3010
+ ] }),
3011
+ entry?.block?.card && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3012
+ MarketOddsCardList,
3013
+ {
3014
+ cards: [toMarketOddsVM(entry.block.card)],
3015
+ ui,
3016
+ slip,
3017
+ monitor,
3018
+ inSlipIds: monitor.inSlip,
3019
+ hideHeader: true
3020
+ }
3021
+ )
3022
+ ] })
3023
+ ] }, m.marketDeveloperName);
3024
+ }) });
3025
+ }
3026
+
3027
+ // src/components/MonitorMatchCard.tsx
3028
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2902
3029
  function chipSelection(row, matchId, conversationId) {
2903
3030
  const chip = row.market;
2904
3031
  if (!chip || !chip.addToSlipEnabled || typeof chip.matchOddsId !== "number" || typeof chip.price !== "number") return null;
@@ -2921,63 +3048,63 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
2921
3048
  const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins));
2922
3049
  const orderedRows = [...promotedRows, ...otherRows];
2923
3050
  const kickoff = match.phase === "preMatch" && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : void 0;
2924
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon", children: [
2925
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-top", children: [
2926
- live && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-fandash-live-pill", children: [
2927
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
3051
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon", children: [
3052
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-top", children: [
3053
+ live && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-fandash-live-pill", children: [
3054
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
2928
3055
  ui.liveLabel
2929
3056
  ] }),
2930
- match.phase === "fullTime" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
2931
- kickoff && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-pill", children: [
3057
+ match.phase === "fullTime" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3058
+ kickoff && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-pill", children: [
2932
3059
  kickoff.dayLabel,
2933
3060
  " \xB7 ",
2934
3061
  kickoff.time
2935
3062
  ] }),
2936
- live && match.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-min", children: match.minuteLabel }),
2937
- match.competitionName && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-comp", children: match.competitionName }),
2938
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
3063
+ live && match.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-min", children: match.minuteLabel }),
3064
+ match.competitionName && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-comp", children: match.competitionName }),
3065
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
2939
3066
  ] }),
2940
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-main", children: [
2941
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-side", children: [
2942
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", url: match.homeCrestUrl ?? void 0, name: match.homeTeamName ?? void 0 }),
2943
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-name", children: match.homeTeamName })
3067
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-main", children: [
3068
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-side", children: [
3069
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Crest2, { kind: "team", url: match.homeCrestUrl ?? void 0, name: match.homeTeamName ?? void 0 }),
3070
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-name", children: match.homeTeamName })
2944
3071
  ] }),
2945
- match.phase === "preMatch" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-vs", children: "vs" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-score", children: [
3072
+ match.phase === "preMatch" ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-vs", children: "vs" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-score", children: [
2946
3073
  match.homeScore,
2947
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { children: "\u2013" }),
3074
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { children: "\u2013" }),
2948
3075
  match.awayScore
2949
3076
  ] }),
2950
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-side ss-w-mon-side--away", children: [
2951
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Crest2, { kind: "team", url: match.awayCrestUrl ?? void 0, name: match.awayTeamName ?? void 0 }),
2952
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-name", children: match.awayTeamName })
3077
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-side ss-w-mon-side--away", children: [
3078
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Crest2, { kind: "team", url: match.awayCrestUrl ?? void 0, name: match.awayTeamName ?? void 0 }),
3079
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-name", children: match.awayTeamName })
2953
3080
  ] })
2954
3081
  ] }),
2955
- scorers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "ss-w-mon-scorers", children: scorers.map((e) => `${e.player ?? ""} ${e.minuteLabel}`).join(", ") }),
2956
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
3082
+ scorers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-scorers", children: scorers.map((e) => `${e.player ?? ""} ${e.minuteLabel}`).join(", ") }),
3083
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
2957
3084
  const total = row.homeNum + row.awayNum;
2958
3085
  const homePct = total > 0 ? row.homeNum / total * 75 : 0;
2959
3086
  const awayPct = total > 0 ? row.awayNum / total * 75 : 0;
2960
3087
  const promoted = isPromoted(row, promotedPins);
2961
3088
  const selection = chipSelection(row, match.matchId, slip.conversationId);
2962
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: promoted ? "ss-w-mon-stat ss-w-mon-pstrip" : "ss-w-mon-stat", children: [
2963
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-stat-row", children: [
2964
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: row.homeValue }),
2965
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-l", children: row.label }),
2966
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: row.awayValue })
3089
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: promoted ? "ss-w-mon-stat ss-w-mon-pstrip" : "ss-w-mon-stat", children: [
3090
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-stat-row", children: [
3091
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: row.homeValue }),
3092
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-l", children: row.label }),
3093
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: row.awayValue })
2967
3094
  ] }),
2968
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-bar", children: [
2969
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("b", { className: "ss-w-mon-bar-home", style: { width: `${homePct}%` } }),
2970
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ss-w-mon-bar-away", style: { width: `${awayPct}%` } })
3095
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-bar", children: [
3096
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("b", { className: "ss-w-mon-bar-home", style: { width: `${homePct}%` } }),
3097
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ss-w-mon-bar-away", style: { width: `${awayPct}%` } })
2971
3098
  ] }),
2972
- row.market && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: promoted ? "ss-w-mon-stat-mkt ss-w-mon-mkt" : "ss-w-mon-stat-mkt", children: [
2973
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { children: [
3099
+ row.market && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: promoted ? "ss-w-mon-stat-mkt ss-w-mon-mkt" : "ss-w-mon-stat-mkt", children: [
3100
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { children: [
2974
3101
  row.market.marketLabel,
2975
3102
  " \xB7 ",
2976
3103
  row.market.selectionLabel
2977
3104
  ] }),
2978
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ss-w-mon-stat-mkt-right", children: [
2979
- row.market.isSuspended ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }) : typeof row.market.price === "number" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-price", children: row.market.price.toFixed(2) }),
2980
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3105
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-stat-mkt-right", children: [
3106
+ row.market.isSuspended ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }) : typeof row.market.price === "number" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-price", children: row.market.price.toFixed(2) }),
3107
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2981
3108
  SlipButton,
2982
3109
  {
2983
3110
  selection,
@@ -2991,68 +3118,69 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
2991
3118
  ] })
2992
3119
  ] }, row.label);
2993
3120
  }) }),
2994
- match.status === "stale" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(formatTime(match.asOfUtc)) }),
2995
- match.momentum.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-mom", children: [
2996
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "ss-w-mon-stat-row", children: [
2997
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: typeof match.momentumHomePct === "number" ? `${match.momentumHomePct}%` : "" }),
2998
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-l", children: ui.momentumLabel }),
2999
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: typeof match.momentumHomePct === "number" ? `${100 - match.momentumHomePct}%` : "" })
3121
+ match.status === "stale" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(formatTime(match.asOfUtc)) }),
3122
+ match.momentum.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-mom", children: [
3123
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-stat-row", children: [
3124
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: typeof match.momentumHomePct === "number" ? `${match.momentumHomePct}%` : "" }),
3125
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-l", children: ui.momentumLabel }),
3126
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: typeof match.momentumHomePct === "number" ? `${100 - match.momentumHomePct}%` : "" })
3000
3127
  ] }),
3001
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MomentumWave, { points: match.momentum, clubIsHome: true })
3128
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(MomentumWave, { points: match.momentum, clubIsHome: true })
3002
3129
  ] }),
3003
- match.mainMarket && match.phase !== "fullTime" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MarketOddsCardList, { cards: [toMarketOddsVM(match.mainMarket)], ui, slip }),
3004
- match.phase === "fullTime" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "ss-w-mon-grace", children: ui.graceNote })
3130
+ match.phase === "fullTime" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-grace", children: ui.graceNote })
3005
3131
  ] });
3006
3132
  }
3007
3133
 
3008
3134
  // src/components/MonitorTabs.tsx
3009
- var import_jsx_runtime47 = require("react/jsx-runtime");
3135
+ var import_jsx_runtime48 = require("react/jsx-runtime");
3010
3136
  function ContextLine({ m, monitor, ui }) {
3011
3137
  const kick = m.kickoffUtc ? ui.bettingKickoff(m.kickoffUtc) : void 0;
3012
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mk-ctx", children: [
3013
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3014
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
3015
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-name", children: m.homeTeamName })
3138
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mk-ctx", children: [
3139
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3140
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
3141
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-name", children: m.homeTeamName })
3016
3142
  ] }),
3017
- m.phase === "preMatch" ? kick && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mon-pill", children: [
3143
+ m.phase === "preMatch" ? kick && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mon-pill", children: [
3018
3144
  kick.dayLabel,
3019
3145
  " ",
3020
3146
  kick.time
3021
- ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("b", { children: [
3147
+ ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("b", { children: [
3022
3148
  m.homeScore,
3023
3149
  "\u2013",
3024
3150
  m.awayScore
3025
3151
  ] }),
3026
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3027
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
3028
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
3152
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-side", children: [
3153
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
3154
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
3029
3155
  ] }),
3030
- m.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
3031
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ss-w-mk-ctx-right", children: [
3032
- m.isSuspended && !m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
3033
- m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3034
- m.status === "stale" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
3156
+ m.minuteLabel && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
3157
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "ss-w-mk-ctx-right", children: [
3158
+ m.isSuspended && !m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
3159
+ m.isSettled && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3160
+ m.status === "stale" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
3035
3161
  (() => {
3036
3162
  const pin = monitor.pins.find((p) => p.key === m.key);
3037
- return pin ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PinToggle, { ui, monitor, pin }) : null;
3163
+ return pin ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PinToggle, { ui, monitor, pin }) : null;
3038
3164
  })()
3039
3165
  ] })
3040
3166
  ] });
3041
3167
  }
3042
3168
  function MatchesPanel({ monitor, ui, slip }) {
3043
3169
  const matches = (monitor.snapshot?.matches ?? []).filter((m) => monitor.pins.some((p) => p.kind === "match" && p.matchId === m.matchId));
3044
- if (matches.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-empty", children: ui.emptyMatchesTab });
3045
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-list", children: matches.map((m) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3046
- MonitorMatchCard,
3047
- {
3048
- match: m,
3049
- promotedPins: monitor.pins.filter((p) => p.kind !== "match" && p.matchId === m.matchId),
3050
- monitor,
3051
- ui,
3052
- slip
3053
- },
3054
- m.matchId
3055
- )) });
3170
+ if (matches.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty", children: ui.emptyMatchesTab });
3171
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-list", children: matches.map((m) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mon-item", children: [
3172
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3173
+ MonitorMatchCard,
3174
+ {
3175
+ match: m,
3176
+ promotedPins: monitor.pins.filter((p) => p.kind !== "match" && p.matchId === m.matchId),
3177
+ monitor,
3178
+ ui,
3179
+ slip
3180
+ }
3181
+ ),
3182
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(MarketAccordion, { match: m, monitor, ui, slip })
3183
+ ] }, m.matchId)) });
3056
3184
  }
3057
3185
  function withSinceViewMovement(vm, prev) {
3058
3186
  const primary = vm.mainRows[0];
@@ -3066,10 +3194,10 @@ function withSinceViewMovement(vm, prev) {
3066
3194
  }
3067
3195
  function OddsPanel({ monitor, ui, slip }) {
3068
3196
  const markets = (monitor.snapshot?.markets ?? []).filter((m) => monitor.pins.some((p) => p.key === m.key));
3069
- if (markets.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
3070
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3071
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ContextLine, { m, monitor, ui }),
3072
- m.card && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3197
+ if (markets.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
3198
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3199
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ContextLine, { m, monitor, ui }),
3200
+ m.card && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3073
3201
  MarketOddsCardList,
3074
3202
  {
3075
3203
  cards: [withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])],
@@ -3078,13 +3206,13 @@ function OddsPanel({ monitor, ui, slip }) {
3078
3206
  inSlipIds: monitor.inSlip
3079
3207
  }
3080
3208
  ),
3081
- m.history && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3082
- !m.card && !m.history && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3209
+ m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3210
+ !m.card && !m.history && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3083
3211
  ] }, m.key)) });
3084
3212
  }
3085
3213
 
3086
3214
  // src/components/ChatPanel.tsx
3087
- var import_jsx_runtime48 = require("react/jsx-runtime");
3215
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3088
3216
  var FULLSCREEN_QUERY = "(max-width: 639px)";
3089
3217
  function useIsModal() {
3090
3218
  const [modal, setModal] = (0, import_react22.useState)(false);
@@ -3115,9 +3243,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3115
3243
  (0, import_react22.useEffect)(() => {
3116
3244
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
3117
3245
  }, [monitor, state.isStreaming, state.messages.length]);
3118
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat, logoUrl: ui.logoUrl, headerTitle: ui.headerTitle }),
3120
- monitor && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3246
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3247
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChatHeader, { onClose: close, closeLabel: ui.closeChat, logoUrl: ui.logoUrl, headerTitle: ui.headerTitle }),
3248
+ monitor && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3121
3249
  TabBar,
3122
3250
  {
3123
3251
  monitor,
@@ -3126,16 +3254,16 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3126
3254
  oddsCount: monitor.pins.filter((p) => p.kind !== "match").length
3127
3255
  }
3128
3256
  ),
3129
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3257
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3130
3258
  "div",
3131
3259
  {
3132
3260
  style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
3133
- children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3261
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3134
3262
  }
3135
3263
  ),
3136
- monitor && monitor.activeTab === "matches" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(MatchesPanel, { monitor, ui, slip }),
3137
- monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(OddsPanel, { monitor, ui, slip }),
3138
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3264
+ monitor && monitor.activeTab === "matches" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(MatchesPanel, { monitor, ui, slip }),
3265
+ monitor && monitor.activeTab === "odds" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(OddsPanel, { monitor, ui, slip }),
3266
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3139
3267
  ] });
3140
3268
  }
3141
3269
 
@@ -3920,10 +4048,23 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3920
4048
  .ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }
3921
4049
  .ss-w-mon-oddspin[data-settled] .ss-w-mo-price,
3922
4050
  .ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }
4051
+
4052
+ /* market accordion (Task 9): one collapsed row per available market, expanding into a reused
4053
+ MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */
4054
+ .ss-w-acc { display: flex; flex-direction: column; gap: 6px; }
4055
+ .ss-w-acc-row { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); overflow: hidden; }
4056
+ .ss-w-acc-head { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 11px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); }
4057
+ .ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; }
4058
+ .ss-w-acc-label { font-size: 12.5px; font-weight: 600; }
4059
+ .ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); }
4060
+ .ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); }
4061
+ .ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
4062
+ .ss-w-acc-insight { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }
4063
+ .ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }
3923
4064
  `;
3924
4065
 
3925
4066
  // src/StatsWidget.tsx
3926
- var import_jsx_runtime49 = require("react/jsx-runtime");
4067
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3927
4068
  function buildClient(props) {
3928
4069
  try {
3929
4070
  if ("client" in props && props.client) {
@@ -3958,6 +4099,7 @@ function StatsWidget(props) {
3958
4099
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
3959
4100
  const monitor = useLiveMonitor({
3960
4101
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
4102
+ getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
3961
4103
  storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
3962
4104
  isOpen: controller.state.isOpen
3963
4105
  });
@@ -3995,7 +4137,7 @@ function StatsWidget(props) {
3995
4137
  }, [built, ui.injectStyles]);
3996
4138
  if (!built) return null;
3997
4139
  const attrs = themeAttrs(ui);
3998
- return /* @__PURE__ */ (0, import_jsx_runtime49.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_runtime49.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4140
+ return /* @__PURE__ */ (0, import_jsx_runtime50.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_runtime50.jsx)(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3999
4141
  ChatFab,
4000
4142
  {
4001
4143
  label: ui.launcherLabel,