@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.js CHANGED
@@ -83,7 +83,10 @@ var STRINGS = {
83
83
  fullTimeLabel: "Full time",
84
84
  inSlipLabel: "In slip",
85
85
  oddsUnavailable: "Odds unavailable right now",
86
- momentumLabel: "Momentum"
86
+ momentumLabel: "Momentum",
87
+ accordionValueLabel: "Value",
88
+ accordionRetry: "Couldn't load odds \u2014 tap to retry",
89
+ accordionSuspended: "Suspended"
87
90
  },
88
91
  tr: {
89
92
  launcherLabel: "SensibleStats ile sohbet et",
@@ -152,7 +155,10 @@ var STRINGS = {
152
155
  fullTimeLabel: "Ma\xE7 sonu",
153
156
  inSlipLabel: "Kuponda",
154
157
  oddsUnavailable: "Oranlar \u015Fu anda kullan\u0131lam\u0131yor",
155
- momentumLabel: "Momentum"
158
+ momentumLabel: "Momentum",
159
+ accordionValueLabel: "De\u011Fer",
160
+ accordionRetry: "Oranlar y\xFCklenemedi \u2014 yeniden dene",
161
+ accordionSuspended: "Ask\u0131da"
156
162
  }
157
163
  };
158
164
  function resolveLocaleStrings(locale) {
@@ -240,7 +246,10 @@ function normalizeUi(cfg) {
240
246
  fullTimeLabel: strings.fullTimeLabel,
241
247
  inSlipLabel: strings.inSlipLabel,
242
248
  oddsUnavailable: strings.oddsUnavailable,
243
- momentumLabel: strings.momentumLabel
249
+ momentumLabel: strings.momentumLabel,
250
+ accordionValueLabel: strings.accordionValueLabel,
251
+ accordionRetry: strings.accordionRetry,
252
+ accordionSuspended: strings.accordionSuspended
244
253
  };
245
254
  }
246
255
  function toClientOptions(cfg) {
@@ -994,6 +1003,8 @@ function useLiveMonitor(opts) {
994
1003
  const [oddsDot, setOddsDot] = useState(false);
995
1004
  const [lastViewedPrices, setLastViewedPrices] = useState({});
996
1005
  const [inSlip, setInSlip] = useState({});
1006
+ const [openMarket, setOpenMarket] = useState({});
1007
+ const [marketOdds, setMarketOdds] = useState({});
997
1008
  const pinsRef = useRef3(pins);
998
1009
  pinsRef.current = pins;
999
1010
  const activeTabRef = useRef3(activeTab);
@@ -1002,6 +1013,46 @@ function useLiveMonitor(opts) {
1002
1013
  snapshotRef.current = snapshot;
1003
1014
  const lastViewedPricesRef = useRef3(lastViewedPrices);
1004
1015
  lastViewedPricesRef.current = lastViewedPrices;
1016
+ const openMarketRef = useRef3(openMarket);
1017
+ openMarketRef.current = openMarket;
1018
+ const marketOddsRef = useRef3(marketOdds);
1019
+ marketOddsRef.current = marketOdds;
1020
+ const marketKey = (matchId, dev) => `${matchId}:${dev}`;
1021
+ const getMarketOddsRef = useRef3(opts.getMarketOdds);
1022
+ getMarketOddsRef.current = opts.getMarketOdds;
1023
+ const fetchMarket = useCallback2((matchId, dev) => {
1024
+ const key = marketKey(matchId, dev);
1025
+ const existing = marketOddsRef.current[key];
1026
+ if (existing?.loading) return;
1027
+ const loadingEntry = { ...existing, loading: true, error: false };
1028
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: loadingEntry };
1029
+ setMarketOdds((prev) => ({ ...prev, [key]: loadingEntry }));
1030
+ const fn = getMarketOddsRef.current;
1031
+ if (!fn) return;
1032
+ void fn(matchId, dev).then((block) => {
1033
+ const entry = { block: block ?? void 0, loading: false, error: false };
1034
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: entry };
1035
+ setMarketOdds((prev) => ({ ...prev, [key]: entry }));
1036
+ }).catch(() => {
1037
+ const entry = { ...marketOddsRef.current[key], loading: false, error: true };
1038
+ marketOddsRef.current = { ...marketOddsRef.current, [key]: entry };
1039
+ setMarketOdds((prev) => ({ ...prev, [key]: entry }));
1040
+ });
1041
+ }, []);
1042
+ const toggleMarket = useCallback2((matchId, dev) => {
1043
+ const key = marketKey(matchId, dev);
1044
+ const wasOpen = openMarketRef.current[matchId] === dev;
1045
+ const nextValue = wasOpen ? null : dev;
1046
+ openMarketRef.current = { ...openMarketRef.current, [matchId]: nextValue };
1047
+ setOpenMarket((prev) => ({ ...prev, [matchId]: nextValue }));
1048
+ const existing = marketOddsRef.current[key];
1049
+ if (!wasOpen && !(existing?.loading || existing?.block)) {
1050
+ fetchMarket(matchId, dev);
1051
+ }
1052
+ }, [fetchMarket]);
1053
+ const retryMarket = useCallback2((matchId, dev) => {
1054
+ fetchMarket(matchId, dev);
1055
+ }, [fetchMarket]);
1005
1056
  const applySnapshot = useCallback2((next) => {
1006
1057
  if (next === null) {
1007
1058
  setEnabled(false);
@@ -1021,6 +1072,16 @@ function useLiveMonitor(opts) {
1021
1072
  }
1022
1073
  }
1023
1074
  if (sawNewGoalOrRed && activeTabRef.current !== "matches") setMatchesDot(true);
1075
+ for (const m of next.matches) {
1076
+ if (!pinnedMatchIds.has(m.matchId)) continue;
1077
+ const first = m.availableMarkets?.[0];
1078
+ if (!first) continue;
1079
+ if (m.matchId in openMarketRef.current) continue;
1080
+ const dev = first.marketDeveloperName;
1081
+ openMarketRef.current = { ...openMarketRef.current, [m.matchId]: dev };
1082
+ setOpenMarket((prevOpen) => ({ ...prevOpen, [m.matchId]: dev }));
1083
+ fetchMarket(m.matchId, dev);
1084
+ }
1024
1085
  const marketPins = currentPins.filter((p) => p.kind !== "match");
1025
1086
  if (activeTabRef.current === "odds") {
1026
1087
  setLastViewedPrices((prevMap) => {
@@ -1071,12 +1132,17 @@ function useLiveMonitor(opts) {
1071
1132
  return;
1072
1133
  }
1073
1134
  applySnapshot(snap);
1135
+ for (const m of snap.matches) {
1136
+ if (m.phase !== "live") continue;
1137
+ const dev = openMarketRef.current[m.matchId];
1138
+ if (dev) fetchMarket(m.matchId, dev);
1139
+ }
1074
1140
  } catch {
1075
1141
  } finally {
1076
1142
  inFlightRef.current = false;
1077
1143
  scheduleRef.current();
1078
1144
  }
1079
- }, [applySnapshot]);
1145
+ }, [applySnapshot, fetchMarket]);
1080
1146
  const scheduleRef = useRef3(() => {
1081
1147
  });
1082
1148
  scheduleRef.current = () => {
@@ -1154,6 +1220,10 @@ function useLiveMonitor(opts) {
1154
1220
  lastViewedPrices,
1155
1221
  inSlip,
1156
1222
  markInSlip,
1223
+ openMarket,
1224
+ marketOdds,
1225
+ toggleMarket,
1226
+ retryMarket,
1157
1227
  _setSnapshot: applySnapshot
1158
1228
  };
1159
1229
  }
@@ -1694,48 +1764,50 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
1694
1764
  /* @__PURE__ */ jsx14(SlipButton, { selection, shownOdds: row.odds, marketName: vm.market, slip, ui })
1695
1765
  ] });
1696
1766
  }
1697
- function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds }) {
1767
+ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader }) {
1698
1768
  const [open, setOpen] = useState9(false);
1699
1769
  const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
1700
1770
  const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
1701
1771
  const showPin = !!monitor && vm.pinEnabled;
1702
1772
  const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin;
1703
- return /* @__PURE__ */ jsxs9("div", { className: "ss-w-mocard", children: [
1704
- showHeader ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-header", children: [
1705
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
1706
- /* @__PURE__ */ jsx14(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1707
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-comp", children: vm.competition })
1708
- ] }) : null }),
1709
- /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-header-right", children: [
1710
- vm.isLive ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-live", children: [
1711
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1712
- ui?.liveLabel ?? "Live"
1713
- ] }) : null,
1714
- kickoff ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-kick", children: [
1715
- kickoff.dayLabel,
1716
- " ",
1717
- kickoff.time
1718
- ] }) : null,
1719
- showPin && ui ? /* @__PURE__ */ jsx14(
1720
- PinToggle,
1721
- {
1722
- ui,
1723
- monitor,
1724
- pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1725
- }
1726
- ) : null
1727
- ] })
1728
- ] }) : null,
1729
- hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-sub", children: [
1730
- hasNamedTeams ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-fixture", children: [
1731
- /* @__PURE__ */ jsx14(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1732
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1733
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1734
- /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1735
- /* @__PURE__ */ jsx14(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1736
- ] }) : vm.fixture ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1737
- vm.market ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-market", children: vm.market }) : null
1738
- ] }) : null,
1773
+ return /* @__PURE__ */ jsxs9("div", { className: hideHeader ? "ss-w-mocard ss-w-mocard--bare" : "ss-w-mocard", children: [
1774
+ !hideHeader && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1775
+ showHeader ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-header", children: [
1776
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-header-left", children: vm.competition ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
1777
+ /* @__PURE__ */ jsx14(Crest2, { kind: "comp", url: vm.competitionCrest, name: vm.competition }),
1778
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-comp", children: vm.competition })
1779
+ ] }) : null }),
1780
+ /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-header-right", children: [
1781
+ vm.isLive ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-live", children: [
1782
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
1783
+ ui?.liveLabel ?? "Live"
1784
+ ] }) : null,
1785
+ kickoff ? /* @__PURE__ */ jsxs9("span", { className: "ss-w-bi-kick", children: [
1786
+ kickoff.dayLabel,
1787
+ " ",
1788
+ kickoff.time
1789
+ ] }) : null,
1790
+ showPin && ui ? /* @__PURE__ */ jsx14(
1791
+ PinToggle,
1792
+ {
1793
+ ui,
1794
+ monitor,
1795
+ pin: { kind: "market", matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, line: vm.mainLine }
1796
+ }
1797
+ ) : null
1798
+ ] })
1799
+ ] }) : null,
1800
+ hasNamedTeams || vm.fixture || vm.market ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-sub", children: [
1801
+ hasNamedTeams ? /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-fixture", children: [
1802
+ /* @__PURE__ */ jsx14(Crest2, { kind: "team", url: vm.homeCrest, name: vm.homeTeamName }),
1803
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-team", children: vm.homeTeamName }),
1804
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
1805
+ /* @__PURE__ */ jsx14("span", { className: "ss-w-bi-team", children: vm.awayTeamName }),
1806
+ /* @__PURE__ */ jsx14(Crest2, { kind: "team", url: vm.awayCrest, name: vm.awayTeamName })
1807
+ ] }) : vm.fixture ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-teams", children: vm.fixture }) : null,
1808
+ vm.market ? /* @__PURE__ */ jsx14("span", { className: "ss-w-mo-market", children: vm.market }) : null
1809
+ ] }) : null
1810
+ ] }),
1739
1811
  /* @__PURE__ */ jsxs9("div", { className: "ss-w-mo-rows", children: [
1740
1812
  vm.mainRows.map((row) => /* @__PURE__ */ jsx14(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)),
1741
1813
  open ? vm.moreRows.map((row) => /* @__PURE__ */ jsx14(OddsRow, { vm, row, ui, slip, inSlipIds }, row.key)) : null
@@ -1748,9 +1820,9 @@ function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds }) {
1748
1820
  vm.disclaimer ? /* @__PURE__ */ jsx14("p", { className: "ss-w-bi-disc", children: vm.disclaimer }) : null
1749
1821
  ] });
1750
1822
  }
1751
- function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds }) {
1823
+ function MarketOddsCardList({ cards, ui, slip, monitor, inSlipIds, hideHeader }) {
1752
1824
  if (!cards || cards.length === 0) return null;
1753
- return /* @__PURE__ */ jsx14("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx14(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds }, vm.id)) });
1825
+ return /* @__PURE__ */ jsx14("div", { className: "ss-w-mocards", children: cards.map((vm) => /* @__PURE__ */ jsx14(MarketOddsCard, { vm, ui, slip, monitor, inSlipIds, hideHeader }, vm.id)) });
1754
1826
  }
1755
1827
 
1756
1828
  // src/components/OddsMovementCard.tsx
@@ -2860,8 +2932,63 @@ function TabBar({ monitor, ui, matchCount, oddsCount }) {
2860
2932
  }) });
2861
2933
  }
2862
2934
 
2863
- // src/components/MonitorMatchCard.tsx
2935
+ // src/components/MarketAccordion.tsx
2864
2936
  import { jsx as jsx46, jsxs as jsxs40 } from "react/jsx-runtime";
2937
+ function MarketAccordion({ match, monitor, ui, slip }) {
2938
+ const markets = match.availableMarkets ?? [];
2939
+ if (markets.length === 0) return null;
2940
+ const open = monitor.openMarket[match.matchId] ?? null;
2941
+ return /* @__PURE__ */ jsx46("div", { className: "ss-w-acc", children: markets.map((m) => {
2942
+ const isOpen = open === m.marketDeveloperName;
2943
+ const key = `${match.matchId}:${m.marketDeveloperName}`;
2944
+ const entry = monitor.marketOdds[key];
2945
+ return /* @__PURE__ */ jsxs40("div", { className: isOpen ? "ss-w-acc-row ss-w-acc-row-open" : "ss-w-acc-row", children: [
2946
+ /* @__PURE__ */ jsxs40(
2947
+ "button",
2948
+ {
2949
+ type: "button",
2950
+ className: "ss-w-acc-head",
2951
+ onClick: () => monitor.toggleMarket(match.matchId, m.marketDeveloperName),
2952
+ children: [
2953
+ /* @__PURE__ */ jsx46("span", { className: "ss-w-acc-chevron", children: isOpen ? "\u25BE" : "\u25B8" }),
2954
+ /* @__PURE__ */ jsx46("span", { className: "ss-w-acc-label", children: m.marketLabel }),
2955
+ m.hasInsight && /* @__PURE__ */ jsx46("span", { className: "ss-w-acc-badge", children: "\u2605" }),
2956
+ m.suspended && /* @__PURE__ */ jsx46("span", { className: "ss-w-acc-susp", children: ui.accordionSuspended })
2957
+ ]
2958
+ }
2959
+ ),
2960
+ isOpen && /* @__PURE__ */ jsxs40("div", { className: "ss-w-acc-panel", children: [
2961
+ entry?.error && /* @__PURE__ */ jsx46(
2962
+ "div",
2963
+ {
2964
+ className: "ss-w-acc-retry",
2965
+ onClick: () => monitor.retryMarket(match.matchId, m.marketDeveloperName),
2966
+ children: ui.accordionRetry
2967
+ }
2968
+ ),
2969
+ entry?.block?.insight?.text && /* @__PURE__ */ jsxs40("div", { className: "ss-w-acc-insight", children: [
2970
+ /* @__PURE__ */ jsx46("span", { className: "ss-w-acc-badge", children: ui.accordionValueLabel }),
2971
+ " ",
2972
+ entry.block.insight.text
2973
+ ] }),
2974
+ entry?.block?.card && /* @__PURE__ */ jsx46(
2975
+ MarketOddsCardList,
2976
+ {
2977
+ cards: [toMarketOddsVM(entry.block.card)],
2978
+ ui,
2979
+ slip,
2980
+ monitor,
2981
+ inSlipIds: monitor.inSlip,
2982
+ hideHeader: true
2983
+ }
2984
+ )
2985
+ ] })
2986
+ ] }, m.marketDeveloperName);
2987
+ }) });
2988
+ }
2989
+
2990
+ // src/components/MonitorMatchCard.tsx
2991
+ import { jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
2865
2992
  function chipSelection(row, matchId, conversationId) {
2866
2993
  const chip = row.market;
2867
2994
  if (!chip || !chip.addToSlipEnabled || typeof chip.matchOddsId !== "number" || typeof chip.price !== "number") return null;
@@ -2884,63 +3011,63 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
2884
3011
  const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins));
2885
3012
  const orderedRows = [...promotedRows, ...otherRows];
2886
3013
  const kickoff = match.phase === "preMatch" && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : void 0;
2887
- return /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon", children: [
2888
- /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-top", children: [
2889
- live && /* @__PURE__ */ jsxs40("span", { className: "ss-w-fandash-live-pill", children: [
2890
- /* @__PURE__ */ jsx46("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
3014
+ return /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon", children: [
3015
+ /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-top", children: [
3016
+ live && /* @__PURE__ */ jsxs41("span", { className: "ss-w-fandash-live-pill", children: [
3017
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-fandash-live-dot", "aria-hidden": "true" }),
2891
3018
  ui.liveLabel
2892
3019
  ] }),
2893
- match.phase === "fullTime" && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
2894
- kickoff && /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-pill", children: [
3020
+ match.phase === "fullTime" && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3021
+ kickoff && /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-pill", children: [
2895
3022
  kickoff.dayLabel,
2896
3023
  " \xB7 ",
2897
3024
  kickoff.time
2898
3025
  ] }),
2899
- live && match.minuteLabel && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-min", children: match.minuteLabel }),
2900
- match.competitionName && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-comp", children: match.competitionName }),
2901
- /* @__PURE__ */ jsx46(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
3026
+ live && match.minuteLabel && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-min", children: match.minuteLabel }),
3027
+ match.competitionName && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-comp", children: match.competitionName }),
3028
+ /* @__PURE__ */ jsx47(PinToggle, { ui, monitor, pin: { kind: "match", matchId: match.matchId } })
2902
3029
  ] }),
2903
- /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-main", children: [
2904
- /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-side", children: [
2905
- /* @__PURE__ */ jsx46(Crest2, { kind: "team", url: match.homeCrestUrl ?? void 0, name: match.homeTeamName ?? void 0 }),
2906
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-name", children: match.homeTeamName })
3030
+ /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-main", children: [
3031
+ /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-side", children: [
3032
+ /* @__PURE__ */ jsx47(Crest2, { kind: "team", url: match.homeCrestUrl ?? void 0, name: match.homeTeamName ?? void 0 }),
3033
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-name", children: match.homeTeamName })
2907
3034
  ] }),
2908
- match.phase === "preMatch" ? /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-vs", children: "vs" }) : /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-score", children: [
3035
+ match.phase === "preMatch" ? /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-vs", children: "vs" }) : /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-score", children: [
2909
3036
  match.homeScore,
2910
- /* @__PURE__ */ jsx46("i", { children: "\u2013" }),
3037
+ /* @__PURE__ */ jsx47("i", { children: "\u2013" }),
2911
3038
  match.awayScore
2912
3039
  ] }),
2913
- /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-side ss-w-mon-side--away", children: [
2914
- /* @__PURE__ */ jsx46(Crest2, { kind: "team", url: match.awayCrestUrl ?? void 0, name: match.awayTeamName ?? void 0 }),
2915
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-name", children: match.awayTeamName })
3040
+ /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-side ss-w-mon-side--away", children: [
3041
+ /* @__PURE__ */ jsx47(Crest2, { kind: "team", url: match.awayCrestUrl ?? void 0, name: match.awayTeamName ?? void 0 }),
3042
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-name", children: match.awayTeamName })
2916
3043
  ] })
2917
3044
  ] }),
2918
- scorers.length > 0 && /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-scorers", children: scorers.map((e) => `${e.player ?? ""} ${e.minuteLabel}`).join(", ") }),
2919
- /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
3045
+ scorers.length > 0 && /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-scorers", children: scorers.map((e) => `${e.player ?? ""} ${e.minuteLabel}`).join(", ") }),
3046
+ /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
2920
3047
  const total = row.homeNum + row.awayNum;
2921
3048
  const homePct = total > 0 ? row.homeNum / total * 75 : 0;
2922
3049
  const awayPct = total > 0 ? row.awayNum / total * 75 : 0;
2923
3050
  const promoted = isPromoted(row, promotedPins);
2924
3051
  const selection = chipSelection(row, match.matchId, slip.conversationId);
2925
- return /* @__PURE__ */ jsxs40("div", { className: promoted ? "ss-w-mon-stat ss-w-mon-pstrip" : "ss-w-mon-stat", children: [
2926
- /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-stat-row", children: [
2927
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: row.homeValue }),
2928
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-l", children: row.label }),
2929
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: row.awayValue })
3052
+ return /* @__PURE__ */ jsxs41("div", { className: promoted ? "ss-w-mon-stat ss-w-mon-pstrip" : "ss-w-mon-stat", children: [
3053
+ /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-stat-row", children: [
3054
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: row.homeValue }),
3055
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-l", children: row.label }),
3056
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: row.awayValue })
2930
3057
  ] }),
2931
- /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-bar", children: [
2932
- /* @__PURE__ */ jsx46("b", { className: "ss-w-mon-bar-home", style: { width: `${homePct}%` } }),
2933
- /* @__PURE__ */ jsx46("i", { className: "ss-w-mon-bar-away", style: { width: `${awayPct}%` } })
3058
+ /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-bar", children: [
3059
+ /* @__PURE__ */ jsx47("b", { className: "ss-w-mon-bar-home", style: { width: `${homePct}%` } }),
3060
+ /* @__PURE__ */ jsx47("i", { className: "ss-w-mon-bar-away", style: { width: `${awayPct}%` } })
2934
3061
  ] }),
2935
- row.market && /* @__PURE__ */ jsxs40("div", { className: promoted ? "ss-w-mon-stat-mkt ss-w-mon-mkt" : "ss-w-mon-stat-mkt", children: [
2936
- /* @__PURE__ */ jsxs40("span", { children: [
3062
+ row.market && /* @__PURE__ */ jsxs41("div", { className: promoted ? "ss-w-mon-stat-mkt ss-w-mon-mkt" : "ss-w-mon-stat-mkt", children: [
3063
+ /* @__PURE__ */ jsxs41("span", { children: [
2937
3064
  row.market.marketLabel,
2938
3065
  " \xB7 ",
2939
3066
  row.market.selectionLabel
2940
3067
  ] }),
2941
- /* @__PURE__ */ jsxs40("span", { className: "ss-w-mon-stat-mkt-right", children: [
2942
- row.market.isSuspended ? /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }) : typeof row.market.price === "number" && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-price", children: row.market.price.toFixed(2) }),
2943
- /* @__PURE__ */ jsx46(
3068
+ /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-stat-mkt-right", children: [
3069
+ row.market.isSuspended ? /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }) : typeof row.market.price === "number" && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-price", children: row.market.price.toFixed(2) }),
3070
+ /* @__PURE__ */ jsx47(
2944
3071
  SlipButton,
2945
3072
  {
2946
3073
  selection,
@@ -2954,68 +3081,69 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
2954
3081
  ] })
2955
3082
  ] }, row.label);
2956
3083
  }) }),
2957
- match.status === "stale" && /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-asof", children: ui.asOf(formatTime(match.asOfUtc)) }),
2958
- match.momentum.length > 0 && /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-mom", children: [
2959
- /* @__PURE__ */ jsxs40("div", { className: "ss-w-mon-stat-row", children: [
2960
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: typeof match.momentumHomePct === "number" ? `${match.momentumHomePct}%` : "" }),
2961
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-l", children: ui.momentumLabel }),
2962
- /* @__PURE__ */ jsx46("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: typeof match.momentumHomePct === "number" ? `${100 - match.momentumHomePct}%` : "" })
3084
+ match.status === "stale" && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-asof", children: ui.asOf(formatTime(match.asOfUtc)) }),
3085
+ match.momentum.length > 0 && /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-mom", children: [
3086
+ /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-stat-row", children: [
3087
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--home", children: typeof match.momentumHomePct === "number" ? `${match.momentumHomePct}%` : "" }),
3088
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-l", children: ui.momentumLabel }),
3089
+ /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-stat-v ss-w-mon-stat-v--away", children: typeof match.momentumHomePct === "number" ? `${100 - match.momentumHomePct}%` : "" })
2963
3090
  ] }),
2964
- /* @__PURE__ */ jsx46(MomentumWave, { points: match.momentum, clubIsHome: true })
3091
+ /* @__PURE__ */ jsx47(MomentumWave, { points: match.momentum, clubIsHome: true })
2965
3092
  ] }),
2966
- match.mainMarket && match.phase !== "fullTime" && /* @__PURE__ */ jsx46(MarketOddsCardList, { cards: [toMarketOddsVM(match.mainMarket)], ui, slip }),
2967
- match.phase === "fullTime" && /* @__PURE__ */ jsx46("div", { className: "ss-w-mon-grace", children: ui.graceNote })
3093
+ match.phase === "fullTime" && /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-grace", children: ui.graceNote })
2968
3094
  ] });
2969
3095
  }
2970
3096
 
2971
3097
  // src/components/MonitorTabs.tsx
2972
- import { jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
3098
+ import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
2973
3099
  function ContextLine({ m, monitor, ui }) {
2974
3100
  const kick = m.kickoffUtc ? ui.bettingKickoff(m.kickoffUtc) : void 0;
2975
- return /* @__PURE__ */ jsxs41("div", { className: "ss-w-mk-ctx", children: [
2976
- /* @__PURE__ */ jsxs41("span", { className: "ss-w-mk-ctx-side", children: [
2977
- /* @__PURE__ */ jsx47(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
2978
- /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-name", children: m.homeTeamName })
3101
+ return /* @__PURE__ */ jsxs42("div", { className: "ss-w-mk-ctx", children: [
3102
+ /* @__PURE__ */ jsxs42("span", { className: "ss-w-mk-ctx-side", children: [
3103
+ /* @__PURE__ */ jsx48(Crest2, { kind: "team", url: m.homeCrestUrl ?? void 0, name: m.homeTeamName ?? void 0 }),
3104
+ /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-name", children: m.homeTeamName })
2979
3105
  ] }),
2980
- m.phase === "preMatch" ? kick && /* @__PURE__ */ jsxs41("span", { className: "ss-w-mon-pill", children: [
3106
+ m.phase === "preMatch" ? kick && /* @__PURE__ */ jsxs42("span", { className: "ss-w-mon-pill", children: [
2981
3107
  kick.dayLabel,
2982
3108
  " ",
2983
3109
  kick.time
2984
- ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ jsxs41("b", { children: [
3110
+ ] }) : typeof m.homeScore === "number" && /* @__PURE__ */ jsxs42("b", { children: [
2985
3111
  m.homeScore,
2986
3112
  "\u2013",
2987
3113
  m.awayScore
2988
3114
  ] }),
2989
- /* @__PURE__ */ jsxs41("span", { className: "ss-w-mk-ctx-side", children: [
2990
- /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
2991
- /* @__PURE__ */ jsx47(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
3115
+ /* @__PURE__ */ jsxs42("span", { className: "ss-w-mk-ctx-side", children: [
3116
+ /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-name", children: m.awayTeamName }),
3117
+ /* @__PURE__ */ jsx48(Crest2, { kind: "team", url: m.awayCrestUrl ?? void 0, name: m.awayTeamName ?? void 0 })
2992
3118
  ] }),
2993
- m.minuteLabel && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
2994
- /* @__PURE__ */ jsxs41("span", { className: "ss-w-mk-ctx-right", children: [
2995
- m.isSuspended && !m.isSettled && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
2996
- m.isSettled && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
2997
- m.status === "stale" && /* @__PURE__ */ jsx47("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
3119
+ m.minuteLabel && /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-min", children: m.minuteLabel }),
3120
+ /* @__PURE__ */ jsxs42("span", { className: "ss-w-mk-ctx-right", children: [
3121
+ m.isSuspended && !m.isSettled && /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-susp", children: ui.suspendedLabel }),
3122
+ m.isSettled && /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-pill", children: ui.fullTimeLabel }),
3123
+ m.status === "stale" && /* @__PURE__ */ jsx48("span", { className: "ss-w-mon-asof", children: ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })) }),
2998
3124
  (() => {
2999
3125
  const pin = monitor.pins.find((p) => p.key === m.key);
3000
- return pin ? /* @__PURE__ */ jsx47(PinToggle, { ui, monitor, pin }) : null;
3126
+ return pin ? /* @__PURE__ */ jsx48(PinToggle, { ui, monitor, pin }) : null;
3001
3127
  })()
3002
3128
  ] })
3003
3129
  ] });
3004
3130
  }
3005
3131
  function MatchesPanel({ monitor, ui, slip }) {
3006
3132
  const matches = (monitor.snapshot?.matches ?? []).filter((m) => monitor.pins.some((p) => p.kind === "match" && p.matchId === m.matchId));
3007
- if (matches.length === 0) return /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-empty", children: ui.emptyMatchesTab });
3008
- return /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-list", children: matches.map((m) => /* @__PURE__ */ jsx47(
3009
- MonitorMatchCard,
3010
- {
3011
- match: m,
3012
- promotedPins: monitor.pins.filter((p) => p.kind !== "match" && p.matchId === m.matchId),
3013
- monitor,
3014
- ui,
3015
- slip
3016
- },
3017
- m.matchId
3018
- )) });
3133
+ if (matches.length === 0) return /* @__PURE__ */ jsx48("div", { className: "ss-w-mon-empty", children: ui.emptyMatchesTab });
3134
+ return /* @__PURE__ */ jsx48("div", { className: "ss-w-mon-list", children: matches.map((m) => /* @__PURE__ */ jsxs42("div", { className: "ss-w-mon-item", children: [
3135
+ /* @__PURE__ */ jsx48(
3136
+ MonitorMatchCard,
3137
+ {
3138
+ match: m,
3139
+ promotedPins: monitor.pins.filter((p) => p.kind !== "match" && p.matchId === m.matchId),
3140
+ monitor,
3141
+ ui,
3142
+ slip
3143
+ }
3144
+ ),
3145
+ /* @__PURE__ */ jsx48(MarketAccordion, { match: m, monitor, ui, slip })
3146
+ ] }, m.matchId)) });
3019
3147
  }
3020
3148
  function withSinceViewMovement(vm, prev) {
3021
3149
  const primary = vm.mainRows[0];
@@ -3029,10 +3157,10 @@ function withSinceViewMovement(vm, prev) {
3029
3157
  }
3030
3158
  function OddsPanel({ monitor, ui, slip }) {
3031
3159
  const markets = (monitor.snapshot?.markets ?? []).filter((m) => monitor.pins.some((p) => p.key === m.key));
3032
- if (markets.length === 0) return /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
3033
- return /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ jsxs41("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3034
- /* @__PURE__ */ jsx47(ContextLine, { m, monitor, ui }),
3035
- m.card && /* @__PURE__ */ jsx47(
3160
+ if (markets.length === 0) return /* @__PURE__ */ jsx48("div", { className: "ss-w-mon-empty", children: ui.emptyOddsTab });
3161
+ return /* @__PURE__ */ jsx48("div", { className: "ss-w-mon-list", children: markets.map((m) => /* @__PURE__ */ jsxs42("div", { className: "ss-w-mon-oddspin", "data-settled": m.isSettled || void 0, children: [
3162
+ /* @__PURE__ */ jsx48(ContextLine, { m, monitor, ui }),
3163
+ m.card && /* @__PURE__ */ jsx48(
3036
3164
  MarketOddsCardList,
3037
3165
  {
3038
3166
  cards: [withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])],
@@ -3041,13 +3169,13 @@ function OddsPanel({ monitor, ui, slip }) {
3041
3169
  inSlipIds: monitor.inSlip
3042
3170
  }
3043
3171
  ),
3044
- m.history && /* @__PURE__ */ jsx47(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3045
- !m.card && !m.history && /* @__PURE__ */ jsx47("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3172
+ m.history && /* @__PURE__ */ jsx48(OddsMovementCardList, { cards: [toOddsMovementVM(m.history)], ui }),
3173
+ !m.card && !m.history && /* @__PURE__ */ jsx48("div", { className: "ss-w-mon-empty-card", children: ui.oddsUnavailable })
3046
3174
  ] }, m.key)) });
3047
3175
  }
3048
3176
 
3049
3177
  // src/components/ChatPanel.tsx
3050
- import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
3178
+ import { jsx as jsx49, jsxs as jsxs43 } from "react/jsx-runtime";
3051
3179
  var FULLSCREEN_QUERY = "(max-width: 639px)";
3052
3180
  function useIsModal() {
3053
3181
  const [modal, setModal] = useState17(false);
@@ -3078,9 +3206,9 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3078
3206
  useEffect9(() => {
3079
3207
  if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
3080
3208
  }, [monitor, state.isStreaming, state.messages.length]);
3081
- return /* @__PURE__ */ jsxs42("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3082
- /* @__PURE__ */ jsx48(ChatHeader, { onClose: close, closeLabel: ui.closeChat, logoUrl: ui.logoUrl, headerTitle: ui.headerTitle }),
3083
- monitor && /* @__PURE__ */ jsx48(
3209
+ return /* @__PURE__ */ jsxs43("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
3210
+ /* @__PURE__ */ jsx49(ChatHeader, { onClose: close, closeLabel: ui.closeChat, logoUrl: ui.logoUrl, headerTitle: ui.headerTitle }),
3211
+ monitor && /* @__PURE__ */ jsx49(
3084
3212
  TabBar,
3085
3213
  {
3086
3214
  monitor,
@@ -3089,16 +3217,16 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor }) {
3089
3217
  oddsCount: monitor.pins.filter((p) => p.kind !== "match").length
3090
3218
  }
3091
3219
  ),
3092
- /* @__PURE__ */ jsx48(
3220
+ /* @__PURE__ */ jsx49(
3093
3221
  "div",
3094
3222
  {
3095
3223
  style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
3096
- children: /* @__PURE__ */ jsx48(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3224
+ children: /* @__PURE__ */ jsx49(MessageList, { controller, ui, slip, onDashboardTap, monitor })
3097
3225
  }
3098
3226
  ),
3099
- monitor && monitor.activeTab === "matches" && /* @__PURE__ */ jsx48(MatchesPanel, { monitor, ui, slip }),
3100
- monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx48(OddsPanel, { monitor, ui, slip }),
3101
- /* @__PURE__ */ jsx48(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3227
+ monitor && monitor.activeTab === "matches" && /* @__PURE__ */ jsx49(MatchesPanel, { monitor, ui, slip }),
3228
+ monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx49(OddsPanel, { monitor, ui, slip }),
3229
+ /* @__PURE__ */ jsx49(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
3102
3230
  ] });
3103
3231
  }
3104
3232
 
@@ -3348,6 +3476,9 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3348
3476
  /* market odds card */
3349
3477
  .ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }
3350
3478
  .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; }
3479
+ /* Embedded inside the market accordion, which already provides the card frame + accent rail --
3480
+ drop the inner frame so odds rows aren't double-bordered. */
3481
+ .ss-w-mocard--bare { border: none; border-radius: 0; padding: 0; background: none; }
3351
3482
  .ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
3352
3483
  .ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3353
3484
  .ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }
@@ -3358,7 +3489,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3358
3489
  .ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }
3359
3490
  .ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }
3360
3491
  .ss-w-mo-row:last-child { border-bottom: none; }
3361
- .ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
3492
+ .ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); flex: 1; min-width: 0; }
3362
3493
  .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); }
3363
3494
  /* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a
3364
3495
  shortening price as a discount, which inverts what it actually means for the bettor. */
@@ -3369,7 +3500,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3369
3500
  a flex row, and must NOT follow the badge into the insight card's odds column. */
3370
3501
  .ss-w-mo-row .ss-w-move { margin-left: auto; }
3371
3502
  .ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }
3372
- .ss-w-mo-row .ss-w-slip { margin: 0; }
3503
+ .ss-w-mo-row .ss-w-slip { margin: 0; flex: none; }
3373
3504
  .ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }
3374
3505
 
3375
3506
  /* odds movement card */
@@ -3421,7 +3552,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3421
3552
 
3422
3553
  /* add to slip */
3423
3554
  .ss-w-slip { position: relative; display: flex; }
3424
- .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; }
3555
+ .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; }
3425
3556
  .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); }
3426
3557
  /* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward
3427
3558
  into the card -- inheriting the wrapper's width squeezes the text to one character per line.
@@ -3883,10 +4014,25 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
3883
4014
  .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); }
3884
4015
  .ss-w-mon-oddspin[data-settled] .ss-w-mo-price,
3885
4016
  .ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }
4017
+
4018
+ /* market accordion (Task 9): one collapsed row per available market, expanding into a reused
4019
+ MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */
4020
+ /* Pinned-match tile: the match card + its odds accordion, spaced apart. */
4021
+ .ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }
4022
+ .ss-w-acc { display: flex; flex-direction: column; gap: 6px; }
4023
+ .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; }
4024
+ .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); }
4025
+ .ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; }
4026
+ .ss-w-acc-label { font-size: 12.5px; font-weight: 600; }
4027
+ .ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); }
4028
+ .ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); }
4029
+ .ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }
4030
+ .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; }
4031
+ .ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }
3886
4032
  `;
3887
4033
 
3888
4034
  // src/StatsWidget.tsx
3889
- import { jsx as jsx49 } from "react/jsx-runtime";
4035
+ import { jsx as jsx50 } from "react/jsx-runtime";
3890
4036
  function buildClient(props) {
3891
4037
  try {
3892
4038
  if ("client" in props && props.client) {
@@ -3921,6 +4067,7 @@ function StatsWidget(props) {
3921
4067
  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0);
3922
4068
  const monitor = useLiveMonitor({
3923
4069
  getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
4070
+ getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
3924
4071
  storageKey: `ss-w-pins:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`,
3925
4072
  isOpen: controller.state.isOpen
3926
4073
  });
@@ -3958,7 +4105,7 @@ function StatsWidget(props) {
3958
4105
  }, [built, ui.injectStyles]);
3959
4106
  if (!built) return null;
3960
4107
  const attrs = themeAttrs(ui);
3961
- return /* @__PURE__ */ jsx49("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__ */ jsx49(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ jsx49(
4108
+ return /* @__PURE__ */ jsx50("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__ */ jsx50(ChatPanel, { controller, ui, slip, onDashboardTap, monitor: monitor.enabled ? monitor : void 0 }) : /* @__PURE__ */ jsx50(
3962
4109
  ChatFab,
3963
4110
  {
3964
4111
  label: ui.launcherLabel,