@sensiblestats/widget-react 0.36.0 → 0.37.1

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
- 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,
1810
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: hideHeader ? "ss-w-mocard ss-w-mocard--bare" : "ss-w-mocard", children: [
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
 
@@ -3385,6 +3513,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3385
3513
  /* market odds card */
3386
3514
  .ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
3387
3515
  .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; }
3516
+ /* Embedded inside the market accordion, which already provides the card frame + accent rail --
3517
+ drop the inner frame so odds rows aren't double-bordered. */
3518
+ .ss-w-mocard--bare { border: none; border-radius: 0; padding: 0; background: none; }
3388
3519
  .ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
3389
3520
  .ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3390
3521
  .ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
@@ -3395,7 +3526,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3395
3526
  .ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
3396
3527
  .ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
3397
3528
  .ss-w-mo-row:last-child { border-bottom: none; }
3398
- .ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
3529
+ .ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); flex: 1; min-width: 0; }
3399
3530
  .ss-w-mo-price { margin-left: auto; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--ss-w-accent); }
3400
3531
  /* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a
3401
3532
  shortening price as a discount, which inverts what it actually means for the bettor. */
@@ -3406,7 +3537,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3406
3537
  a flex row, and must NOT follow the badge into the insight card's odds column. */
3407
3538
  .ss-w-mo-row .ss-w-move { margin-left: auto; }
3408
3539
  .ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }
3409
- .ss-w-mo-row .ss-w-slip { margin: 0; }
3540
+ .ss-w-mo-row .ss-w-slip { margin: 0; flex: none; }
3410
3541
  .ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }
3411
3542
 
3412
3543
  /* odds movement card */
@@ -3458,7 +3589,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3458
3589
 
3459
3590
  /* add to slip */
3460
3591
  .ss-w-slip { position: relative; display: flex; }
3461
- .ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; }
3592
+ .ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; white-space: nowrap; }
3462
3593
  .ss-w-slip-btn:disabled { opacity: .6; cursor: default; background: var(--ss-w-bubble); color: var(--ss-w-faint); border-color: var(--ss-w-line); }
3463
3594
  /* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward
3464
3595
  into the card -- inheriting the wrapper's width squeezes the text to one character per line.
@@ -3920,10 +4051,25 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3920
4051
  .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
4052
  .ss-w-mon-oddspin[data-settled] .ss-w-mo-price,
3922
4053
  .ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }
4054
+
4055
+ /* market accordion (Task 9): one collapsed row per available market, expanding into a reused
4056
+ MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */
4057
+ /* Pinned-match tile: the match card + its odds accordion, spaced apart. */
4058
+ .ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }
4059
+ .ss-w-acc { display: flex; flex-direction: column; gap: 6px; }
4060
+ .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; }
4061
+ .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); }
4062
+ .ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; }
4063
+ .ss-w-acc-label { font-size: 12.5px; font-weight: 600; }
4064
+ .ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); }
4065
+ .ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); }
4066
+ .ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
4067
+ .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; }
4068
+ .ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }
3923
4069
  `;
3924
4070
 
3925
4071
  // src/StatsWidget.tsx
3926
- var import_jsx_runtime49 = require("react/jsx-runtime");
4072
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3927
4073
  function buildClient(props) {
3928
4074
  try {
3929
4075
  if ("client" in props && props.client) {
@@ -3958,6 +4104,7 @@ function StatsWidget(props) {
3958
4104
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
3959
4105
  const monitor = useLiveMonitor({
3960
4106
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
4107
+ getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
3961
4108
  storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
3962
4109
  isOpen: controller.state.isOpen
3963
4110
  });
@@ -3995,7 +4142,7 @@ function StatsWidget(props) {
3995
4142
  }, [built, ui.injectStyles]);
3996
4143
  if (!built) return null;
3997
4144
  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)(
4145
+ 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
4146
  ChatFab,
4000
4147
  {
4001
4148
  label: ui.launcherLabel,