@sensiblestats/widget-react 0.48.10 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/index.cjs +2414 -250
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2282 -118
- package/dist/index.js.map +1 -1
- package/dist/styles.css +384 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/StatsWidget.tsx
|
|
2
|
-
import { useCallback as
|
|
2
|
+
import { useCallback as useCallback9, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef13, useState as useState33 } from "react";
|
|
3
3
|
import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
|
|
4
4
|
|
|
5
5
|
// src/kickoff.ts
|
|
@@ -83,6 +83,7 @@ var STRINGS = {
|
|
|
83
83
|
graceNote: "Unpins on next open \xB7 or in 4 h",
|
|
84
84
|
suspendedLabel: "Suspended",
|
|
85
85
|
fullTimeLabel: "Full time",
|
|
86
|
+
ownGoalLabel: "OG",
|
|
86
87
|
inSlipLabel: "In slip",
|
|
87
88
|
oddsUnavailable: "Odds unavailable right now",
|
|
88
89
|
momentumLabel: "Momentum",
|
|
@@ -92,7 +93,18 @@ var STRINGS = {
|
|
|
92
93
|
tabToday: "Today",
|
|
93
94
|
sectionLive: "Live",
|
|
94
95
|
halfTime: "HT",
|
|
95
|
-
staleStates: "Live scores can't be updated \u2014 showing the last known state."
|
|
96
|
+
staleStates: "Live scores can't be updated \u2014 showing the last known state.",
|
|
97
|
+
tabGames: "Games",
|
|
98
|
+
tabLeaderboard: "Leaderboard",
|
|
99
|
+
gamesLoginRequired: "Sign in to play and climb the leaderboard",
|
|
100
|
+
back: "Back",
|
|
101
|
+
leaderboardOffBoard: "Outside top 50",
|
|
102
|
+
leaderboardThisWeek: "This week",
|
|
103
|
+
leaderboardAllTime: "All time",
|
|
104
|
+
gamePlay: "Play",
|
|
105
|
+
gameResume: "Resume",
|
|
106
|
+
gameLocked: "Locked",
|
|
107
|
+
gameVoided: "Voided"
|
|
96
108
|
},
|
|
97
109
|
tr: {
|
|
98
110
|
launcherLabel: "SensibleStats ile sohbet et",
|
|
@@ -161,6 +173,7 @@ var STRINGS = {
|
|
|
161
173
|
graceNote: "Bir sonraki a\xE7\u0131l\u0131\u015Fta kald\u0131r\u0131l\u0131r \xB7 en ge\xE7 4 saat",
|
|
162
174
|
suspendedLabel: "Ask\u0131da",
|
|
163
175
|
fullTimeLabel: "Ma\xE7 sonu",
|
|
176
|
+
ownGoalLabel: "KK",
|
|
164
177
|
inSlipLabel: "Kuponda",
|
|
165
178
|
oddsUnavailable: "Oranlar \u015Fu anda kullan\u0131lam\u0131yor",
|
|
166
179
|
momentumLabel: "Momentum",
|
|
@@ -170,7 +183,18 @@ var STRINGS = {
|
|
|
170
183
|
tabToday: "Bug\xFCn",
|
|
171
184
|
sectionLive: "Canl\u0131",
|
|
172
185
|
halfTime: "\u0130Y",
|
|
173
|
-
staleStates: "Canl\u0131 skorlar g\xFCncellenemiyor \u2014 son bilinen durum g\xF6steriliyor."
|
|
186
|
+
staleStates: "Canl\u0131 skorlar g\xFCncellenemiyor \u2014 son bilinen durum g\xF6steriliyor.",
|
|
187
|
+
tabGames: "Oyunlar",
|
|
188
|
+
tabLeaderboard: "Lider Tablosu",
|
|
189
|
+
gamesLoginRequired: "Oynamak ve lider tablosuna girmek i\xE7in giri\u015F yap\u0131n",
|
|
190
|
+
back: "Geri",
|
|
191
|
+
leaderboardOffBoard: "\u0130lk 50 d\u0131\u015F\u0131nda",
|
|
192
|
+
leaderboardThisWeek: "Bu hafta",
|
|
193
|
+
leaderboardAllTime: "T\xFCm zamanlar",
|
|
194
|
+
gamePlay: "Oyna",
|
|
195
|
+
gameResume: "Devam et",
|
|
196
|
+
gameLocked: "Kilitli",
|
|
197
|
+
gameVoided: "\u0130ptal edildi"
|
|
174
198
|
}
|
|
175
199
|
};
|
|
176
200
|
function resolveLocaleStrings(locale) {
|
|
@@ -262,12 +286,24 @@ function normalizeUi(cfg) {
|
|
|
262
286
|
graceNote: strings.graceNote,
|
|
263
287
|
suspendedLabel: strings.suspendedLabel,
|
|
264
288
|
fullTimeLabel: strings.fullTimeLabel,
|
|
289
|
+
ownGoalLabel: strings.ownGoalLabel,
|
|
265
290
|
inSlipLabel: strings.inSlipLabel,
|
|
266
291
|
oddsUnavailable: strings.oddsUnavailable,
|
|
267
292
|
momentumLabel: strings.momentumLabel,
|
|
268
293
|
accordionValueLabel: strings.accordionValueLabel,
|
|
269
294
|
accordionRetry: strings.accordionRetry,
|
|
270
|
-
accordionSuspended: strings.accordionSuspended
|
|
295
|
+
accordionSuspended: strings.accordionSuspended,
|
|
296
|
+
tabGames: strings.tabGames,
|
|
297
|
+
tabLeaderboard: strings.tabLeaderboard,
|
|
298
|
+
gamesLoginRequired: strings.gamesLoginRequired,
|
|
299
|
+
back: strings.back,
|
|
300
|
+
leaderboardOffBoard: strings.leaderboardOffBoard,
|
|
301
|
+
leaderboardThisWeek: strings.leaderboardThisWeek,
|
|
302
|
+
leaderboardAllTime: strings.leaderboardAllTime,
|
|
303
|
+
gamePlay: strings.gamePlay,
|
|
304
|
+
gameResume: strings.gameResume,
|
|
305
|
+
gameLocked: strings.gameLocked,
|
|
306
|
+
gameVoided: strings.gameVoided
|
|
271
307
|
};
|
|
272
308
|
}
|
|
273
309
|
function toClientOptions(cfg) {
|
|
@@ -1102,7 +1138,7 @@ function useChatStream(conversation, starterTexts, greetingMessage, storageKey)
|
|
|
1102
1138
|
}
|
|
1103
1139
|
|
|
1104
1140
|
// src/useLiveMonitor.ts
|
|
1105
|
-
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState } from "react";
|
|
1141
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
1106
1142
|
|
|
1107
1143
|
// src/pinStore.ts
|
|
1108
1144
|
var MAX_MATCH_PINS = 5;
|
|
@@ -1164,6 +1200,13 @@ function createPinStore(storageKey, sessionId, onChange) {
|
|
|
1164
1200
|
};
|
|
1165
1201
|
}
|
|
1166
1202
|
|
|
1203
|
+
// src/useTabs.ts
|
|
1204
|
+
import { useState } from "react";
|
|
1205
|
+
function useTabs(initial = "chat") {
|
|
1206
|
+
const [activeTab, setActiveTab] = useState(initial);
|
|
1207
|
+
return { activeTab, setActiveTab };
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1167
1210
|
// src/useLiveMonitor.ts
|
|
1168
1211
|
var GOAL_OR_RED = /* @__PURE__ */ new Set(["goal", "red"]);
|
|
1169
1212
|
var MIN_POLL_MS = 5e3;
|
|
@@ -1185,19 +1228,19 @@ function phaseForPin(snapshot, pin) {
|
|
|
1185
1228
|
}
|
|
1186
1229
|
function useLiveMonitor(opts) {
|
|
1187
1230
|
const sessionIdRef = useRef3(crypto.randomUUID());
|
|
1188
|
-
const [pins, setPins] =
|
|
1189
|
-
const [store] =
|
|
1190
|
-
const [enabled, setEnabled] =
|
|
1191
|
-
const [snapshot, setSnapshotState] =
|
|
1192
|
-
const
|
|
1193
|
-
const [chatDot, setChatDot] =
|
|
1194
|
-
const [matchesDot, setMatchesDot] =
|
|
1195
|
-
const [oddsDot, setOddsDot] =
|
|
1196
|
-
const [todayDot, setTodayDot] =
|
|
1197
|
-
const [lastViewedPrices, setLastViewedPrices] =
|
|
1198
|
-
const [inSlip, setInSlip] =
|
|
1199
|
-
const [openMarket, setOpenMarket] =
|
|
1200
|
-
const [marketOdds, setMarketOdds] =
|
|
1231
|
+
const [pins, setPins] = useState2([]);
|
|
1232
|
+
const [store] = useState2(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins));
|
|
1233
|
+
const [enabled, setEnabled] = useState2(true);
|
|
1234
|
+
const [snapshot, setSnapshotState] = useState2(null);
|
|
1235
|
+
const { activeTab, setActiveTab: setActiveTabState } = useTabs("chat");
|
|
1236
|
+
const [chatDot, setChatDot] = useState2(false);
|
|
1237
|
+
const [matchesDot, setMatchesDot] = useState2(false);
|
|
1238
|
+
const [oddsDot, setOddsDot] = useState2(false);
|
|
1239
|
+
const [todayDot, setTodayDot] = useState2(false);
|
|
1240
|
+
const [lastViewedPrices, setLastViewedPrices] = useState2({});
|
|
1241
|
+
const [inSlip, setInSlip] = useState2({});
|
|
1242
|
+
const [openMarket, setOpenMarket] = useState2({});
|
|
1243
|
+
const [marketOdds, setMarketOdds] = useState2({});
|
|
1201
1244
|
const pinsRef = useRef3(pins);
|
|
1202
1245
|
pinsRef.current = pins;
|
|
1203
1246
|
const activeTabRef = useRef3(activeTab);
|
|
@@ -1435,7 +1478,7 @@ function useLiveMonitor(opts) {
|
|
|
1435
1478
|
}
|
|
1436
1479
|
|
|
1437
1480
|
// src/useMatchDiscovery.ts
|
|
1438
|
-
import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as
|
|
1481
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState3 } from "react";
|
|
1439
1482
|
|
|
1440
1483
|
// src/scheduleCache.ts
|
|
1441
1484
|
var PREFIX = "ss-w-schedule:";
|
|
@@ -1523,11 +1566,11 @@ function localDateOf(now) {
|
|
|
1523
1566
|
return `${y}-${m}-${d}`;
|
|
1524
1567
|
}
|
|
1525
1568
|
function useMatchDiscovery(opts) {
|
|
1526
|
-
const [groups, setGroups] =
|
|
1527
|
-
const [states, setStates] =
|
|
1528
|
-
const [failures, setFailures] =
|
|
1529
|
-
const [expanded, setExpanded] =
|
|
1530
|
-
const [touched, setTouched] =
|
|
1569
|
+
const [groups, setGroups] = useState3([]);
|
|
1570
|
+
const [states, setStates] = useState3({});
|
|
1571
|
+
const [failures, setFailures] = useState3(0);
|
|
1572
|
+
const [expanded, setExpanded] = useState3({});
|
|
1573
|
+
const [touched, setTouched] = useState3({});
|
|
1531
1574
|
const groupsRef = useRef4(groups);
|
|
1532
1575
|
groupsRef.current = groups;
|
|
1533
1576
|
const statesRef = useRef4(states);
|
|
@@ -1535,7 +1578,7 @@ function useMatchDiscovery(opts) {
|
|
|
1535
1578
|
const getStatesRef = useRef4(opts.getStates);
|
|
1536
1579
|
getStatesRef.current = opts.getStates;
|
|
1537
1580
|
const pinnedKey = opts.pinnedMatchIds.join(",");
|
|
1538
|
-
const [localDate, setLocalDate] =
|
|
1581
|
+
const [localDate, setLocalDate] = useState3(() => localDateOf(/* @__PURE__ */ new Date()));
|
|
1539
1582
|
useEffect4(() => {
|
|
1540
1583
|
const id = setInterval(() => {
|
|
1541
1584
|
const next = localDateOf(/* @__PURE__ */ new Date());
|
|
@@ -1615,6 +1658,107 @@ function useMatchDiscovery(opts) {
|
|
|
1615
1658
|
return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick };
|
|
1616
1659
|
}
|
|
1617
1660
|
|
|
1661
|
+
// src/useGames.ts
|
|
1662
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
|
|
1663
|
+
var GAMES_POLL_MS = 6e4;
|
|
1664
|
+
var DEFAULT_TZ = "Europe/London";
|
|
1665
|
+
function computeGameDay(timezone) {
|
|
1666
|
+
return new Intl.DateTimeFormat("en-CA", { timeZone: timezone }).format(/* @__PURE__ */ new Date());
|
|
1667
|
+
}
|
|
1668
|
+
function useGames(conversation, { activeTab, operatorTimezone }) {
|
|
1669
|
+
const [enabled, setEnabled] = useState4(true);
|
|
1670
|
+
const [games, setGames] = useState4([]);
|
|
1671
|
+
const [loading, setLoading] = useState4(false);
|
|
1672
|
+
const [refreshCount, setRefreshCount] = useState4(0);
|
|
1673
|
+
const inFlightRef = useRef5(false);
|
|
1674
|
+
const enabledRef = useRef5(true);
|
|
1675
|
+
const conversationRef = useRef5(conversation);
|
|
1676
|
+
conversationRef.current = conversation;
|
|
1677
|
+
const tzRef = useRef5(operatorTimezone ?? DEFAULT_TZ);
|
|
1678
|
+
tzRef.current = operatorTimezone ?? DEFAULT_TZ;
|
|
1679
|
+
useEffect5(() => {
|
|
1680
|
+
if (!enabledRef.current) return;
|
|
1681
|
+
let active = true;
|
|
1682
|
+
const doFetch = async () => {
|
|
1683
|
+
const conv = conversationRef.current;
|
|
1684
|
+
if (!conv || inFlightRef.current || !active) return;
|
|
1685
|
+
inFlightRef.current = true;
|
|
1686
|
+
setLoading(true);
|
|
1687
|
+
try {
|
|
1688
|
+
const gameDay = computeGameDay(tzRef.current);
|
|
1689
|
+
const result = await conv.getGames(gameDay);
|
|
1690
|
+
if (!active) return;
|
|
1691
|
+
if (result === null) {
|
|
1692
|
+
enabledRef.current = false;
|
|
1693
|
+
setEnabled(false);
|
|
1694
|
+
} else {
|
|
1695
|
+
setGames(result.games);
|
|
1696
|
+
}
|
|
1697
|
+
} catch {
|
|
1698
|
+
} finally {
|
|
1699
|
+
inFlightRef.current = false;
|
|
1700
|
+
if (active) setLoading(false);
|
|
1701
|
+
}
|
|
1702
|
+
};
|
|
1703
|
+
void doFetch();
|
|
1704
|
+
let intervalId;
|
|
1705
|
+
if (activeTab === "games") {
|
|
1706
|
+
intervalId = window.setInterval(() => {
|
|
1707
|
+
if (!enabledRef.current) {
|
|
1708
|
+
window.clearInterval(intervalId);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
void doFetch();
|
|
1712
|
+
}, GAMES_POLL_MS);
|
|
1713
|
+
}
|
|
1714
|
+
return () => {
|
|
1715
|
+
active = false;
|
|
1716
|
+
if (intervalId !== void 0) window.clearInterval(intervalId);
|
|
1717
|
+
};
|
|
1718
|
+
}, [activeTab, refreshCount]);
|
|
1719
|
+
const refresh = useCallback4(() => {
|
|
1720
|
+
setRefreshCount((c) => c + 1);
|
|
1721
|
+
}, []);
|
|
1722
|
+
return { enabled, games, loading, refresh };
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
// src/useLeaderboard.ts
|
|
1726
|
+
import { useCallback as useCallback5, useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
|
|
1727
|
+
function useLeaderboard(conversation, { activeTab }) {
|
|
1728
|
+
const [data, setData] = useState5(null);
|
|
1729
|
+
const [loading, setLoading] = useState5(false);
|
|
1730
|
+
const [refreshCount, setRefreshCount] = useState5(0);
|
|
1731
|
+
const inFlightRef = useRef6(false);
|
|
1732
|
+
const conversationRef = useRef6(conversation);
|
|
1733
|
+
conversationRef.current = conversation;
|
|
1734
|
+
useEffect6(() => {
|
|
1735
|
+
if (activeTab !== "leaderboard") return;
|
|
1736
|
+
let active = true;
|
|
1737
|
+
const doFetch = async () => {
|
|
1738
|
+
const conv = conversationRef.current;
|
|
1739
|
+
if (!conv || inFlightRef.current) return;
|
|
1740
|
+
inFlightRef.current = true;
|
|
1741
|
+
setLoading(true);
|
|
1742
|
+
try {
|
|
1743
|
+
const result = await conv.getLeaderboard();
|
|
1744
|
+
if (active) setData(result);
|
|
1745
|
+
} catch {
|
|
1746
|
+
} finally {
|
|
1747
|
+
inFlightRef.current = false;
|
|
1748
|
+
if (active) setLoading(false);
|
|
1749
|
+
}
|
|
1750
|
+
};
|
|
1751
|
+
void doFetch();
|
|
1752
|
+
return () => {
|
|
1753
|
+
active = false;
|
|
1754
|
+
};
|
|
1755
|
+
}, [activeTab, refreshCount]);
|
|
1756
|
+
const refresh = useCallback5(() => {
|
|
1757
|
+
setRefreshCount((c) => c + 1);
|
|
1758
|
+
}, []);
|
|
1759
|
+
return { data, loading, refresh };
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1618
1762
|
// src/liveClock.ts
|
|
1619
1763
|
function isTreatedLive(state, pollStale) {
|
|
1620
1764
|
return state?.phase === "live" && !pollStale;
|
|
@@ -1634,10 +1778,10 @@ function useEventLog() {
|
|
|
1634
1778
|
}
|
|
1635
1779
|
|
|
1636
1780
|
// src/components/ChatFab.tsx
|
|
1637
|
-
import { useEffect as
|
|
1781
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState7 } from "react";
|
|
1638
1782
|
|
|
1639
1783
|
// src/components/BrandMark.tsx
|
|
1640
|
-
import { useState as
|
|
1784
|
+
import { useState as useState6 } from "react";
|
|
1641
1785
|
|
|
1642
1786
|
// src/assets/logo.ts
|
|
1643
1787
|
var SS_LOGO_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjA5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjE5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+QWRvYmUgUGhvdG9zaG9wIDI2LjEwICgyMDI1MDczMC5tLjMxNjYgMDdiMTIzNCkgIChNYWNpbnRvc2gpPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrJu30+AABAAElEQVR4Ae2dB5wlRbX/T8/sLuyEXbIgCBhRERBQwfAABRURE6JPMSFiBtN7f0XF8Hzqw5xFfUYEfYqKiBhAgkoSAwoYEFSSAkvemdldlt3p/6/u3YXZZcINHU5Vf/vz6bn3dledOudbPff+urqCGRsEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEKiKQFZVQZQDAQhEQGCpbWaZbWG5bWrz9D5v7ZvK8030fiOdG9H70TX74tbn3Obr80LtG+jzoNKFNHNty5TgzjWJbleeVco7ps9LtU/o/YSOhc+36P0tNqnd7ObWe7Ob9P56G7Yl+jyp92wQgAAEZiSA0JkRDScgkBiBIGLm2f1stW0vgRD2bRXhlpIKW+v9Vnof9gURRR1EzhLt/2y95naNDdhVEkhXKaarFOuVkl/XKbbVEcWEqxCAQMEEEDoFA8UcBGolEMSM2YPVrvIg/eDvoP1B+qF/oI5tr31Ye9O20FJ0pThcpsAv1+vl+nyZ+FwuEXR102AQLwSaSACh08RaJ+b4Cdxsi/TA6GH6wd5JweykH/CH6XVn7RvHH1xlEYyJ26Uq7Y/aL9F+qT5fLLLh0RgbBCCQCAGETiIVSRgJE7hd/WMGbXdFuLtaI3bXj3F4f9+EI647tGvE+Dd6DPZbOfJ7vf+teh1dX7dTlA8BCPRGAKHTGzdyQaAcArkkzTLbRX1MHi1R81j9yO6h1/uVUxhWuyBwjdKeq/o4XzV0gR57XaR6WduZugszJIUABKomgNCpmjjlQWAqgdyGNL7oMfoB3bslbMwepdNN7EszlUoM71eovn4jQfpzvZ6tGjtPr2EkGRsEIOCMAELHWYXgTuIEctvQxtVaY7avHo3sI4EThE0Yns0WN4E7JXQulPA5W2GcqUdd5+rzHXGHhPcQSIMAQieNeiQKzwTGbEf96D1ZLoZ9L+0benYX3wohEFp3zpaQ/an209TB+S+FWMUIBCDQNQGETtfIyACBOQgs0f38QnuSxM1TlfJJ2reZIwen0ydwta6HH0r0nKLHXGfR2pN+hROhHwIIHT91gScxE1imSfdye5r2pyuMJ2jfIOZw8L1UAmHm59DSc4oedf2Q4eylssY4BPTvxgYBCPRG4Da7v2bffY4yH6w9DPlmg0C3BMLszmfrm/hEiZ7vaXGNMNMzGwQgUCABhE6BMDHVAAJLNdPwgB2kSIPA2a0BERNidQSC6Pm5WnpO0uu3ED3VgaektAkgdNKuX6IrgsCE3Vs/PofI1Au171KESWxAYA4CYX2u07Ufr0HrJ2uZ1fE50nMaAhCYgQBCZwYwHG44gbDEwgatlpsXiMS+2vlfafglUWP4Eyr7ZO1fV0fm03QlhpYfNghAoEMCfHl3CIpkDSCQ6ydkXHPbZPYyRfts7QwDb0C1RxbitWpd/KpmXvqKrs6/R+Y77kKgFgIInVqwU6grAu0RU4fqPvkwiRyWW3BVOTgzC4GzdO7LauX5jq7bFbOk4xQEGk0AodPo6m9w8Lm6FC+z/XV3/GpROED7QINpEHrcBG6W+1/RCMBjaeWJuyLxvhwCCJ1yuGLVK4GltqkkzWFyLwic+3p1E78g0AOBXHl+qtadz2oFtVP1Sl+eHiCSJT0CCJ306pSIpiMwoaHgub1ep/5dO5P5TceIYykRuFLBfMKW25dscxtLKTBigUC3BBA63RIjfTwE2o+nDpTAeZOc3jsex/EUAoURWCpLX7RB+5SWJbmyMKsYgkBEBBA6EVUWrnZIIFfD/bi9VE33oQXngR3mIhkEUiawWv8PYSLCY9R5+bcpB0psEFifAEJnfSJ8jpfArbaRLbAj1ILzBgWxabyB4DkESiVwmv5HjtHMy2HUFhsEkieA0Em+ihsQ4IRt1RI3mb1GryMNiJgQIVAEgV+plecYtX+erNfQkZkNAkkSQOgkWa0NCWq5bWur7G36kn6JImZyv4ZUO2EWTuD3+h/6LwRP4Vwx6IQAQsdJReBGFwRCC47Z0boHfble53eRk6QQgMDMBBA8M7PhTMQEEDoRV17jXG8/onqL4n6ldlpwGncBEHBFBILgeac6LZ9SUXkUA4FSCSB0SsWL8UIIhE7G8+2tsvU67QicQqBiBAJzEMjsXFttR2l523PmSMlpCLgmgNBxXT0Ndy7XzB8TdqQoBJGzUcNpED4E6iLwQxX8dnXzv7guBygXAv0QQOj0Q4+85RDINb3ZMs2Dk9u7VcDW5RSCVQhAoAsCYVTW8Vo+5W3qtHxtF/lICoHaCSB0aq8CHFiHwLjtq88f077TOsf5AAEIeCCwXDcgH1LrzgfVj2fCg0P4AIG5CCB05iLE+WoILLUH6W7xwyrsadUUSCkQgEAfBP6lvG9Xh+XjJHhYPLQPkGQtnwBCp3zGlDAbgVtssWYzfreSvFY7Q8VnY8U5CPgjcJFuUF6rx1nn+3MNjyDQJoDQ4Uqoh0Deavh+kQr/kPYt6nGCUiEAgYIIfEWPtI7SshJLCrKHGQgURgChUxhKDHVMYNx2kcz5jL4YH9txHhJCAALeCdym/+l3qv/Osfr/XuXdWfxrDgGETnPquv5Ib9T93kJ7rxwJj6kG63cIDyAAgRIIXKzHWS/X46wLS7CNSQh0TQCh0zUyMvREYMKerru9TyvvfXrKTyYIQCAmAuHh9KdthZZq2dSWxuQ4vqZHAKGTXp36imjcttQX3qckcg725Rje9EEgPJYIP15hv/2u9/maxxXtYcd36vjU7XZdAwt1LSzQwQ3WvJ+n92G1+fA9tLh13GwTvYY9nGOLn8C1qt0jNDrr5PhDIYJYCSB0Yq05736H+7ll9jL9oIUh4+FHjM03gZvk3g3a/7nmNQwfvk71d7328P4GPY64XT9YS1Wzy/W53G2JBNCoBM+kbabyN2ntA63XbVVwaBXcRn5so+Ph/QblOoP1vgnkdpLq6zWq1ev7toUBCHRJAKHTJTCSd0BguW2rNXK+qJRP7CA1SaohEGa2vVb73yQOrtCPTni9vPW6XO83t7Fq3CihlDGN2htoCZ77KKYHqYQHK64d9P4her9xCSVisjcCtyjb6yR2TugtO7kg0BsBhE5v3Mg1HYF2K87h+oH5iE6PTpeEY5UQuFGlXKz9D3e9Dtuf9eN/RyWleypkqVqETIJnUAIotx31Psy4vbt2BJAg1LLleoyV2ato3amFfiMLReg0stpLCHqZ7qgn7UuyTCtOCXhnMXm1zp2n/SLtf9APyMV6vHTdLOk5FQissPvZnRI8WUv0BOHzcO1BFLFVQyC07hwpsfONaoqjlCYTQOg0ufaLin3MnqcfjGNljhXGi2I6vZ2VapX4nVifr9fz9LjmPIma0H+GrQgCy207PXJ9rNjuJcZ7yWR49MVWLoFvqQv7q/XNcWu5xWC9yQQQOk2u/X5jv9kWqRvoZ2Tmhf2aIv+0BFbo6DnaT1dr2Tl6GBhETjjGVgWBMfVcGrTHif3eKu5x2nfVPlBF0Q0rI3SAf4lad85oWNyEWxEBhE5FoJMrZqm++AfseMW1XXKx1RdQ6DD8e+0/036aWmvOQdjUVxn3KDmsyzbf9lWdHKBz+2vf+h5pONArgXDtf0zX/NvEt3l9yXqlRr6OCCB0OsJEorsI5LrHHbd36MvoHTrG3e1dYHp+E4Z0/0iPS07T6xlqtQkdidliIDBuO8vNp6zZw3ImzP3Tf739QS1o/6624sv6N4UFCLQJIHS4EjonMGH31g9y6DwYmvLZeifwJ2U9WTLxFE2h9yuJxsneTZHTBYHwGHeB7ae6fJb8ebr2RS78itOJCbkd5tw5Lk738dobAYSOtxrx6s+4PUmuhUdVm3t10blfv5N/35GkOUk/gX9x7ivu9UMgV8+1Zfp/ye25MoPo6Z3lceL4Ws2SNN67CXJCoD31OhwgMDOB8KhqorUQ51EzJ+LMDARCy83xGlXybY0q+dsMaTicMgFET7+1Gx5hPUetO5f0a4j8zSVAi05z637uyMOok8y+pYSPnzsxKdYQCMO9w+O9E/TlHDoWs0GgTSCInnF7hv6nDtWBJ2unj1ubzFx/lynBK/X/FFqU2SDQNQGETtfIGpJhme2hxyzfUbTbNCTifsJcqcwnaf+yRo38jD43/aBsSN5lGrE1aS9StC/V/qCGRN1fmJmmshiyN+n/K/y/sUGgYwIInY5RNSjhhKZnz+0TinhBg6LuJdQJcTpKk8ydwIRnveAjT4vAUnuMfrxfqvad5+l6Cqu5s81M4FfidLAEz7UzJ+EMBNYlgNBZl0ezP+USNhP2WUF4WbNBdBz9VfpZ2r7j1CSEwGwExu2rOv2S2ZJwrkVgiVrDDlan/l/CAwKdEOAZcSeUmpBm3O6lEQ5nKlREThPqmxghEC+BsFr9Gbope3m8IeB5lQQQOlXS9lrWeGtBwwvVbB4mPWODAAQg4J3AfH1ffUFi59N6ZaJG77VVs38InZoroPbix+zZ8uFc7dvW7gsOQAACEOiGQK55diY0q/hS27SbbKRtFgGETrPqe91ox+0t6gQZRlYNrXuCTxCAAASiIfB4Pco63263B0bjMY5WSgChUyluJ4WFpt4x+7y8OcaJR7gBAQhAoB8CD9TUpuerZSesMs8GgXUIIHTWwdGAD2FNngn7oVpyXtGAaAkRAhBoDoFNW52Ux+2Q5oRMpJ0QQOh0QimVNMs0+d8G9guFE2ZlZYMABCCQGoEw99cJupk7OrXAiKd3Agid3tnFlXOp7aC5J0Kn413ichxvIQABCHRJILf/ltj5rEZkDXaZk+QJEkDoJFip9whpmT1KTbrn6Dgjq+4BhwMQgECSBHJ7teYG+5bEzgZJxkdQHRNA6HSMKtKE43pMNWlnyfvNIo0AtyEAAQj0RiDX9Blh+Pkttrg3A+RKgQBCJ4VanCmGcXu+Tp2ineHjMzHiOAQgkDqBvbS4zS800nSL1AMlvukJIHSm5xL/0fb06McrkPnxB0MEEIAABPoisLMe35+nR1nb9GWFzFESQOhEWW1zOD1mR7amRzf9a7NBAAIQgIDpO/H+eox/niYWfAA4mkWAH8LU6nvcjtIcOZ9MLSzigQAEIFAAgftoHNYvbdx2KsAWJiIhgNCJpKI6cnPc/kfpws4GAQhAAALTE9hSh8/UY6xHTX+ao6kRQOikUqPjreUcjkolHOKAAAQgUCKBzfQY63SJnT1KLAPTTgggdJxURF9utEXOW/qyQWYIQAACzSKwSGLnNMRO+pWO0Im9jhE5sdcg/kMAAvURQOzUx76ykhE6laEuoaAxTXNu1oSWnEsU5x9KIIhJCEBgdgKTOr169iTRn22LnQl7RPSREMC0BBA602KJ4OC4BE6W/MJ14Uv2gzZsj9TQ0CsjqBVchEBqBMb0PfNoBXVZaoGtF88ifcf8mNFY61FJ5CNCJ8aKHNMaLtbqfByj9535nNvf9fx8bxtpCbo7OstEKghAoHACw/Zr3WzsKrupT1sRlsk5jXl2Cr+CajeI0Km9Crp0YNxeoDusz3aZK67kuX3RlmuV9UWthUjj8h1vIZAigUz/kSP2eoW2n/brUgxxTUxbap6ds9VB+T4Jx9i40BA6MVX5hD1T7h4Xk8td+nq7mo+fa6P2cq1KM95lXpJDAAJlExixM9TSurP+T39QdlE12t9a8Z2lxUC3qtEHii6QAEKnQJilmhrTY5zcvqUy0qyz3C7QndSuEjknlsoR4xCAQH8EFtlN+j99hr6PXitDK/oz5jR3WC4it5+w6rnT+unSrTR/NLuE4D75uB7jZK07qAXufe3ewVxZPqBm8b1sof2j++zkgAAEaiEw2nqE/mh9N11RS/nlF7qzVj3/gQTPhuUXRQllEkDolEm3CNvLbXuZ+bH2RUWYc2bjVvlzgEROWJ/rTme+4Q4EIDAXgRH7vfqz7KZkobU5xW0vPUT/hsTOYIrBNSUmhI7nmh6zzTWDxWlyMcVnxRfpq2N3iZyfeK4CfIMABOYgsLmN6f/4eWseZaV3w5LZsyR2PjcHBU47JoDQ8Vo5uR7kWOtx1QO9utiHX1/RcNXH8KiqD4JkhYA3AuFR1oAeQZv9y5trffuT2eHqnHx033YwUAsBhE4t2OcoNNeDnGX2Nf3dc46UsZ2+UzG9Und/h+k1zU6MsdUI/kKgSAJDGlRgaqk1+0WRZl3YyjUTfZjegy06Aggdj1U2ockAc3uOR9f68GmJhqU+Xi05X+jDBlkhAAHvBEbsev2f76ubmRTn+/qKLbV/814F+LcuAYTOujzq/zShOWTM3ly/I4V6cLH64zxK3anPLdQqxiAAAZ8EMlslsfNaiZ0wi3tK/Xbm6/HcyRI7O/gEj1fTEUDoTEelrmPjugvKE7sLChOLLbPHqj/OVXVhpVwIQKAmAsPqxJvbk1T6zTV5UEaxG0vA/UhiZ9MyjGOzeAIIneKZ9mbxNk1QZa3J8ub1ZsBlrjA/zrOY5dhl3eAUBKohMKolFVa3+hv+tZoCKygls/upZedEibj5FZRGEX0SQOj0CbCQ7DdqntF5rRFWGxdir34jk7rjeZVETpgfJ6xAzgYBCDSZwGJNKrhaq6BnSa1f93i1Vn+iydUaS+wInbprKtd9wUI7QW48tG5XCip/ub7Mnqnn858vyB5mIACBFAgs1oIKQ3o8b5qAL5UtVx+kCd3UsbkmgNCpu3rGNWTR7Gl1u1FQ+TdJtu0jkXNKQfYwAwEIpEQgs5X6fnihQvpIMmHl9klNmbhPMvEkGAhCp85KHbOD1PrxtjpdKKzszP6mcRZ76o7twsJsYggCEEiPQKaeLSP2nwrsjYkEN1/f49/SY6xtEoknuTAQOnVV6VJ7kP45vlpX8QWXe6ns7WUbSeywQQACEOiEwIh9XJLn+UqawvDzLdQb8TuKZ0EnoZOmWgIInWp5t0vL1Xg7YN/Th9E6ii+4zAv1Dx4eV/2rYLuYgwAEUicwav+nG75nKczlCYS6h1p1Pp5AHMmFgNCpo0on7H9V7I51FF1wmWfp62k/TQSY0hwZBSPCHAQgMCuBYTtVLSEHKM3SWdPFcDJ0Th63l8TgapN8ROhUXdtjdoSKDM21sW+nqBXnAK2vPhZ7IPgPAQjUTCDMtZPppsnsppo9KaL4z0ns7FSEIWwUQwChUwzHzqxM2G76Z05htEEQOQcrFhbm7KzmSQUBCMxFYNh+rSRP0B672NlQMZxoS9Tlms0FAYROVdUQJgU09cy36DurrRU5K6tCRzkQgEBDCIzYJYo0BbGzg0agfqYhteY+TIROVVW0sLXmywOqKq6kchA5JYHFLAQgsIZAOmLnxXqEdSj1Wj8BhE4VdTBhh6mYQ6ooqsQyEDklwsU0BCAwhUA6Yucz6mL94CmR8bYGAgidsqEvtR00ouBTZRdTsv2frOmTw+OqkkFjHgIQWEPgbrFzS8RMhjSVyP/pN2CDiGOI3nWETplVGFa2HWitYzVUZjEl2/6FRM6z1fEYkVMyaMxDAALrEQhiZyD6oee7aD2s964XGR8rJIDQKRP2uL1b5ncvs4iSbV8oefN0iZxlJZeDeQhAAALTExiyX2lS0gN1MuZJBf9DE3E8YfoAOVo2AYROWYSX2mMlEI4qy3wFdi9Vc+uBtondXkFZFAEBCEBgZgKL7Jf6Pj1YCWJdLiKT/8fZbbbxzEFypiwCCJ0yyIah5AP2dZmOle/V+qd8sqK4sQw82IQABCDQNYFh+5Fuvl6sfJNd5/WRYWubp9G3bJUTmFd5iU0ocEP7qMK8b6Sh3qovk/011RVrV81dgUN69v7MuZORAgIdEMht2w5SNTtJWBtr3O4lCLGuKfVcPcL6jm4iT2x2RVYbfVZtcQ0obdyepCh/GmmkK3Sv9EStXXWOO//H7PtqZXqGO79wCAJpE7hdNz0buQtx3D4gn97szq/OHLpJN5MPpcW8M1hFpIr10UoRsRdv42ZJBLMvFm+4EouT+ud7gUuRU0n4FAIBCERDYLjV/zF0D4hx20ydGj4bo+Ox+ozQKbLmFrTWsbpPkSYrs5Xb63WH8b3KyqMgCEAAAr0SyHRbNmyHK/vZvZqoNV+ujtXjSSzuXCvGTgtH6HRKaq504ZFV1vrHmyulv/OZ1mQZtU/7cwyPIAABCMxAIMzttcoO0tnLZkjh/fCn1V9nC+9OpuAfQqeIWsy1fJvZF4owVYON0+X962solyIhAAEI9EdgI7tVI5kOkJEYVzzfRDfHH+sPALk7IYDQ6YTSXGkm7D1Kst1cyRyev0yzUjxX/2yrHfqGSxCAAATmJrCh/V2DKELLToxz7ByiR1j7zx0kKfohgNDph17IO2G76e8b+jVTQ/5b1Oz7VE1fdVsNZVMkBCAAgeIItCcUfG1xBiu19Dn1OIp5maBKYfVSGEKnF2pr8+Q2qAv08/o4uPZQJK9hhNXBGjT6t0j8xU0IQAACsxMYtv9V6/RnZk/k8ux2umH+b5eeJeIUQqefipywI5X9Ef2YqCnvW9T5+KyayqZYCEAAAuUQGGq1rsf43fZ6iZ1dy4GCVYROr9fAhN1bdw/xqfBMs3IOt4bB9xo5+SAAAQj4JJDpgXxu/y7nrvXp4IxeDaqf0WflO5P4zoio9xMInV7Z5fYhXZQjvWavKd+fdNfwUv0r5TWVT7EQgAAEyiUQ1ugbaC0AurLcggq2ntmetkzfz2yFE0Do9IJ0zPZWtkN6yVpjnjHdMTxLszaM1+gDRUMAAhAon8CQ/Uo3dPFNm5HbMaxwXvzlgdDplmmuWRti7PCWazLDRfbXbsMlPQQgAIEoCQy3Vgo/ITLfN7f59t7IfHbvLkKn2ypqd0DesdtstaYPI8NG7du1+kDhEIAABKomsMxepSLjmjk5l8/jtnPVqFIuD6HTTe2O2eZK/q5usjhIe6l6EsU4z48DdLgAAQhETaD9qP45imFFRHGE3+WPR+Sve1cROt1U0YD9l5Iv7iZLzWmXqV/Oc/SoLaZ/8pqRUTwEIJAUgRG7RN+Bb4wspsdr4MjTI/PZrbsInU6rZsweqrFKr+g0uZN0R6hfzl+c+IIbEIAABOohEPrr5PaDegrvsdTcPiyfF/SYm2xTCCB0psCY9W3WmnsmnhmQM/uuHll9ZdaYOAkBCECgKQRye5lC/VdE4T5QrTqxLmvhCjNCp5PqGLcnK1lMC69dp2U6X9lJaKSBAAQg0AgCi1ornL84sljfyXDz/msMoTMXw1xTT5maEGPaMt25LLKbY3IZXyEAAQiUTmDEzlAZnyi9nOIK2EgTmry1OHPNtITQmaveJ+yFSvKwuZK5OZ/rWfSw/diNPzgCAQhAwBOB4ZZwiGnI+ZGaMXkbTwhj8wWhM1uNtTuCvWe2JK7OZXaF+uX8pyufcAYCEICAJwKZLVc7/Uvk0mpPbs3iy4YaPfvuWc5zag4CCJ3ZAE3Yq3V6u9mSuDq32g7TMMoJVz7hDAQgAAFvBMISEbl9wJtbs/hzqI3ZQ2Y5z6lZCCB0ZoKzpLVg59EznXZ3PNPKt4vsl+78wiEIQAACHgmMWGitj+URVhjx+z6PGGPwCaEzUy0N23/o1GYznXZ2/BpNCUiHNWeVgjsQgIBjApndoUdCh8nD3LGXd7uWaVHmCdv17gO865QAQmc6UrfaRrr0Y5pJ8xW2qS2dLhSOQQACEIDADAQW2Xk686kZzvo7PBndEkQuGCJ0pquGea21oWJZ6uE4PWT7yXRhcAwCEIAABOYgsMzerhTXzJHKx+nMnkGrTvdVgdBZn1lozcmiWQTzVrU8Mcpq/TrkMwQgAIFOCYSFPzN7XafJa09Hq07XVYDQWR9ZTK05mfrljNqN64fAZwhAAAIQ6ILAsH1fN41xrIVFq04XFdtOitCZiiyu1pwLbcj+d6r7vIcABCAAgR4JzLMjlXNZj7mrzhbPiOCqyUxTHkJnKpQFdoQ+xtA3Z1JNra/WPjnVfd5DAAIQgECPBBba1cr53h5zV5st1wgs5tXpmDlCZy2q3Baq6fINaz+6fs3sWC3z8DvXPuIcBCAAgdgIDNtHdQN5RQRuZ/LzLRH46cJFhM7aahi3w/V207UfHb/eYnfaOxz7h2sQgAAE4iQQ5taxSG54zQ7RYhbbxgm6Wq8ROoF3bvOljv9fteh7LC23d2pc2K095iYbBCAAAQjMRmDYTtXpGBZGnq/OC4y6na0u15xD6AQQE1LGZvdZw8Tzy581Z87nPTuIbxCAAASiJ5C3Zsb3v+hnbi+z222T6HmXHABCJ1dbjkWiijP982W2quRrAvMQgAAEmk1g1P6s79oYbiqHbNBe2ezKmjt6hM6E7SdMD5sbVe0pfqIOyDE0p9YOCgcgAAEI9E1g0t4tGzEsrXOEul8s6DvehA2E1oxmb+Mt8bC/cwiTupB31uSAf3TuZ3nujbXEaCyLrJbHAcsQqJJArhbkRXZOlUW6Kmu8tVjy+135NL0zL1K3huOnP8XRZgudMA9BZn+K4DL4mi7iQyPwExchAAEIpEMgTDsyYX9XQFs6D+oi/Ubs5tzH2txr+qOrGObNWalnsO+s7QqhYAhAAAJNJZBpAHfWeoTlncCumkBwL+9O1uVfc4VO6Kme2YvrAt9FucfqnuLqLtKTFAIQgAAEiiIwZF/Sb4X/SQQze01RIadmp7lCZ9AOU2Vu6LpCM62qOxnJlOSuQeIcBCAAgR4JhJGuk1FM0nqQfjHu1WOUSWdrptDJbUAK/VXua3bSPqKOgDe59xMHIQABCKRMYMS+rfD+7DzEMPHty537WIt7zRQ6E/ZEjWK6fy3EOy90qe4jPt55clJCAAIQgEApBMICyrm9pxTbRRrNNadObvOKNJmCrWYKnTyKZ5nH2sZ2WwoXGTFAAAIQiJ5AHK0629gyOzB61gUH0DyhExZBy9xfCBO6f/hwwXWNOQhAAAIQ6JVAPK06h/caYqr5mid0Ju2lqkzvcX+avjmp/ssRFwQgEC2BETtRN8p/c+7/U9Sqs7VzHyt1z/sPfrEwQifkvCV0irVbrLUVtOYUCxRrEIAABAohkFlY6POYQmyVZyT8zh1anvn4LDdL6EzYE1RF27mupkxzNjDSynUV4RwEINBgAkN2nKK/1jmBl0rsNHvlgykV1CyhY1rS3ve2Wm1OH/HtIt5BAAIQaDCBzFYq+k+4JhBGFY/bPq59rNC55gidMBOy2UEVsu2lqG9rFuR/9JKRPBCAAAQgUBGBlfa/KmmsotJ6Kybj8dVacM0ROgP2PAXtfSn7D66tGF4hAAEIQMApgU3sdnn2Bafetd3KdGMfFiVlcz/6qMgqemGRxkqwdaZWn/19CXYxCQEIQAACRRMYaD2+Cp2TfW65flHG7Rk+navWq2a06Kyw+6lb1qOrRdtlaZl9ssscJIcABCAAgboIDNk1+l35Xl3Fd1RuZi/qKF3iiZohdFbbIc7r8UobslOc+4h7EIAABCAwlcBq+9TUjw7fP0k9iTZ36FelLjVD6OTm/bHVJ3VnMFlpzVMYBCAAAQj0R2CR/VIGLu7PSKm5w7pXzy21hAiMpy90Jmx31cMOjutiQoMVv+zYP1yDAAQgAIGZCHjvdtAeiDOT9404nr7Qye05rmsyt29o4Hvowc8GAQhAAAKxERiyb8plv9/huT3WJuzesWEt0l+ETpE0e7E1YJ/vJRt5IAABCEDAAYFMK0tl9nUHnszkQugY8eyZTjbheNpCJzy2yjTiyu/2Oxu23/p1D88gAAEIQGBOArnzOXUGmt1PJ22h4/2xVUZrzpxfICSAAAQg4J3AiF2iyfkucOtmbo/R6Kst3PpXsmMInZIBz2g+01ROy1rPdmdMwgkIQAACEIiEwIDrQSUDmh7Y+xJIpVV0ukJn3HZx/dgqtxM1u8FYaTWLYQhAAAIQqI7ACvuWClteXYFdlpTb07vMkUzydIVOZge6rqXcjnPtH85BAAIQgEDnBDa1pUrseabkfW2JloVo4Jau0Mldr/FxpS63nzfweiNkCEAAAikT+Krj4BZoic8nOfavNNfSFDrjtqWIPaI0av0azjUUMVPXNTYIQAACEEiHwLCdqWCucxtQ1szHV2kKnfZjq8ztxTbpes4Ft9hwDAIQgIBrAu2lfP7PsY8H6hZ70LF/pbiWptCZtKeVQqsYo7+yxXZ5MaawAgEIQAACrghkrkfTbqru0o9yxasCZ9ITOrkt0GOh/Spg12sRJ/aakXwQgAAEIOCcwLD9Wh76vZldbU92TrBw99ITOuNa18NsqHBSRRkc1LByNghAAAIQSJdA3hpq7jU+hI7XmunYr8yxWs3sXPV6v7rjWEgIAQhAAALxEcjsO26dzvTo6jbb2K1/JTiWXouOOR4+N+la5ZdweWESAhCAQAMJjNgf1On3704jH1B3ZM/dOwrHlpbQaa/lsWvhlIoyOGgnFWUKOxCAAAQg4JhA5ribgucnHyVUaVpCJ7MnlsCoKJO/Vc+ha4syhh0IQAACEHBMYMD5LMmO0RXtWlpCx+zxRQMqzF5mJxdmC0MQgAAEIOCbwMLW6KvrnTq5vYaZb+/Ut8LdSkvoZLZP4YSKMpgjdIpCiR0IQAAC7gmE2e9z+6FbP1c7/r0sGFo6QmeZbaOL6v4F8ynK3D+0ttXFRRnDDgQgAAEIREBgwH7g2Mt9HPtWqGvpCJ1Jx+o0c6zqC72cMAYBCEAAAncRGLKf6f2Kuz77erOPL3fK8yYdoWOOhY7ZT8urQixDAAIQgIBLApl6wpj9wqVvZtvJu+2c+laoWykJnTAjssftDo22OsujY/gEAQhAAAKlE/B7o7u6tZJA6QDqLiANodOe5fHBdcOcofxfau2tZTOc4zAEIAABCKRMIHfcop/ZY1JGvza2NITOfNtzbUAOX3/s0CdcggAEIACBKgiM2h9VjM851HKEThWXQDFlTLpufju9mCCxAgEIQAACkRLw+juwsy3RmODEtzRadDK3LTo32bBdmvg1RHgQgAAEIDA7gTNnP13b2UEtNP2o2kqvqOD4hU6u5cky26MiXt0Vk9nP5VveXSZSQwACEIBAUgQG7Gy38YTVzBPf4hc6Y/ZASQmfTW+Tji/uxC9swoMABCDghkBY5zCzv7nxZ6ojme0+9WOK7+MXOgOuK+nsFC8aYoIABCAAgS4J5E5vfHN7ZJeRRJc8fqFjboXOzWpnCr3t2SAAAQhAAAI/d4pgOxuzzZ36VohbKQidRxRCongjF9A/p3ioWIQABCAQJYHVdr5bvxN/fBW30MltQGJiV5cXT2bnufQLpyAAAQhAoHoCi+0KFXpj9QV3UCJCpwNIdSVZqtXK/XZERujUdV1QLgQgAAGfBC7w6Zbt4tSvQtyKu0VnwHYqhELxRlarf86vizeLRQhAAAIQiJZAZj6FTm4Pi5ZpB47HLnS8Vs4leqQ20QF/kkAAAhCAQFMITDoVOmYP0tORDVKthriFjjlt0cntN6leMMQFAQhAAAI9Eljp9rdhULfmD+kxKvfZ4hY6ue3olPDvnfqFWxCAAAQgUBeBTW2pWvtDp2SP284enSrCp3iFTm4LBOBBRUAo3Mag/bZwmxiEAAQgAIEUCFzkNAivXUH6xhWv0BlviZzBvgkUb2C1Fkn7Q/FmsQgBCEAAAtETyO13LmPIbQeXfhXgVLxCZ1BrXPncLlPT5HKfruEVBCAAAQjUTMBni06G0Kn5upim+Em3QueSabzlEAQgAAEIQCAQ8NriH+alm5diFcXbomNO1Wdmf0rxQiEmCEAAAhAogMCIXS8rtxZgqWgT89RVevuijXqwF7PQeYAHgPfwITNadO4BhQMQgAAEIDCFwKVT3vt5O88e7MeZ4jyJWej4HHF1p/m8gIu7ZrAEAQhAAAL9EMidtvznbruE9ENbi2LGuOW2odze0qHrd9gi+7tDv3AJAhCAAAT8EPDZxSGz+/pBVJwncQqdMbfPES/XiKvVxVUPliAAAQhAIDkCmf3ZZUy529/WvnDFKXQGbLu+oi4rc05rTllosQsBCEAgGQKDbmdH3j4ZxlMCiVPoZE6Fjt+pvadUOW8hAAEIQKBWAhva1Sr/zlp9mL7w7ac/HPfROIWO1+a1zC6P+3LAewhAAAIQKJ1Au4vDlaWX030Bo3a7bdJ9Nt854hQ6Ztu6xJojdFzWC05BAAIQ8EfA543xoNPf1z7qL1ah43HEldkqu7KPuiArBCAAAQg0hUDmtE9nZlulVgWxCp2tXVbEYrvWpV84BQEIQAACvgjkrX46vnxqe+Pz97UPUrEKHY8tOjdoaPkdfdQFWSEAAQhAoCkEcrvGaagef1/7QhWf0GlPFrhRX1GXk9nrRVtOtFiFAAQgAIHeCXht0Zk0WnR6r9WCcq5w+vzQrzovCDxmIAABCECgMALz3Lbo0EensEru1VBu9+o1a6n5BuyfpdrHOAQgAAEIpENgoV2nYHKHAfn8je0DVIyPrryO8b++j3ogKwQgAAEINIlApnG6Zje6CzmzTd351KdDCJ0+AU7J7u+CneIcbyEAAQhAwB2BJe48MoRO/XWSu5218Yb64eABBCAAAQhERMDjk4BN9EAtvkaQWSo9xmA2nyWe+k5l5lGZ18eDkiEAAQhAYC4CPp8EjKfVqjNvrlpwd35ALToeu2+ttl1twmlHaXeViEMQgAAEIKDfskUuKeQtoeNThPUALD6hk9toD3GWnyWzz7gUYOVHTgkQgAAEIJASgXm2OKVw4nt05VUBp3RVEAsEIAABCDSXwKSNpBR8fEInc9qik9JVQSwQgAAEINBcAon9zsYndMyGm3v1ETkEIAABCECgZAI5j65KJjyneYTOnIhIAAEIQAACEOiRgNe+sD2GE2OLjs/OyD1WANkgAAEIQAACrghk9NGpuz42qNsByocABCAAAQgkSyC3DVOKLcYWnYUpVQCxQAACEIAABJwRGHTmT1/uxCh0+gqYzBCAAAQgAAEIzEKAUVezwKnmFJ2Rq+FMKRCAAAQgAIHoCcTYohPfbM7RXyYEAAEIQAACDSKQ1KCfGIVOg641QoUABCAAAQhUToA+OpUjp0AIQAACEIAABCDQAwFadHqARhYIQAACEIAABOIggNCJo57wEgIQgAAEIACBHgggdHqARhYIQAACEIAABOIggNCJo57wEgIQgAAEIACBHgggdHqARhYIQAACEIAABOIgEKPQyeNAi5cQgAAEIAABCNRNIEahs7RuaJQPAQhAAAIQSJjAbSnFFqPQSYk/sUAAAhCAAAQgUCKBGIXOeIk8MA0BCEAAAhBoOoFVKQGIUegkVQEpXUzEAgEIQAACCRDILakGhRiFzrIELiNCgAAEIAABCPgkMGB3+nSsN69iFDpJKc3eqo1cEIAABCAAgZII5DZRkuVazMYodMZqIUWhEIAABCAAgWYQYNRVrfWcG0Kn1gqgcAhAAAIQSJoALTo1V29mt9fsAcVDAAIQgAAE0iUwwKOreis3S6s3eL0wKR0CEIAABCCwHoHJtH5n4+ujM2lJPTtc7/LiIwQgAAEIQKBuArfU7UCR5ccndDK7uUgA2IIABCAAAQhAYAqBAUPoTMFRx9sb6yiUMiEAAQhAAAKNIDCE0Km3nmnRqZc/pUMAAhCAQMoElllmK1IKkEdXKdUmsUAAAhCAAAT6I5DUY6uAIj6hcyd9dPq7hskNAQhAAAIQmJFAct1D4hM6i+xfM1YPJyAAAQhAAAIQ6IfADf1k9pg3PqGTWVjUk9mRPV5N+AQBCEAAArETuC72ANb3f976ByL5HFp1dnDo65MsT2vVV4eMcQkCEIBA/AQG7DH6vXifw0Cud+hTXy4hdPrCt17mVfZ328j+tt5RPkIAAhCAAATWJTBmO2p0k78tT697SHyPrtqXhU/FOc8e4O+qxSMIQAACEHBHILP7uvOp7RB9dJxUzDVO/FjXjRyhsy4QPkEAAhCAwLQEMtt+2uN1Hxy0a+t2oejy42zRye2qokEUYi+z+xViByMQgAAEIJA2gdyp0PH6+9rH1RCn0BmwK/uIubystOiUxxbLEIAABNIi8ECH4ay0IUtu1FWcQmfSqdChRcfh/y0uQQACEHBGYNy2lEeLnHll6hx9jfbcnV99OhSn0BlxKnSMPjp9Xo9khwAEIJA+gdzl9CgmiXNlivDjFDrtSQM9TlO9oaYz3CbFC4WYIAABCECgIAIDToWOOe3/2if2OIVOO+i/9xl7Odlz26kcw1iFAAQgAIEkCOT2YJdxZJoLLsEtZqHzV5f1gdBxWS04BQEIQMARgR0d+XK3K5N22d0f0nkXr9DJ7HKn1bCzU79wCwIQgAAEfBDw2fLv93e1r1qLV+hM2l/6iry8zD4v4PLixTIEIAABCHRKYKltqqRbdZq80nTDdkWl5VVUWLxCJzOfj67MHqqe6/Mrqj+KgQAEIACBmAhkbvtxXquh5RMxoezU13iFzrDbR1fzdKk8pNMKIB0EIAABCDSIQGa7OI02ydacwDpeodMeYu5zKQgz+uk4/U/GLQhAAAI1E9i95vKnLz6zS6Y/Ef/ReIVOm/3FTquAfjpOKwa3IAABCNRM4JE1lz9T8X+c6UTsx+MWOrlbBbpH7BcG/kMAAhCAQMEEbrRRWdyhYKvFmFttlxZjyJ+VuIWOuRU6j1SH5Hn+qhuPIAABCECgNgIb2q4qO6ut/NkKXoXQmQ1Pnee8KtAhLQVBP506rwzKhgAEIOCNQGZeW/uvsU3sdm+4ivIn7hadkdYsjncWBaNQO5O2Z6H2MAYBCEAAAnETyO3RTgNItiNy4B230MksiByfrTqZPcbpBY1bEIAABCBQB4HMHltHsXOWmdtv50wTcYK4hU4A77WCMlp0Iv6/wHUIQAACxRK4ze4vg1sUa7Qga4N2UUGWXJqJX+gMOFWiuS7qMacXtctLEacgAAEIJExgnuNW/szp72hBl0P8QsfswoJYFG9mgFad4qFiEQIQgECUBPZ26vVNttCudupbIW7FL3SGWkPMVxZCo2gjue1VtEnsQQACEIBAhAQy28ep10n3zwnM4xc67Q7JXmdI9nphO/1/wy0IQAACCRJYZtuoP2noo+Nvyx0/FSmIVvxCJ4DI7IKCeBRtZlfNTLBJ0UaxBwEIQAACERGYtP3cejtg57v1rSDH0hA6uZ1XEI+izQxofmQeXxVNFXsQgAAE4iLweLfu3um2oaAwZGkInUG3QidUlF8lX9hlhCEIQAACEJiWQN5a8uGJ056r/+BfbCO7tX43yvUgDaGz0K4SpuvKRdWz9f17zklGCEAAAhCIm8CE7aQAtnIaRPKPrQL3NIROiCSzc8KLuy10QFth93PnFw5BAAIQgEAVBPze7GZ2bhUA6i4jHaHjt5+OaaGKp9Rd0ZQPAQhAAAK1EPArdFbZz2shUnGh6Qgds7MrZtd5cRlCp3NYpIQABCCQCIGbbZEieZzTaP5pi+0Kp74V6lY6QmfYwlw6XjtV7as5FIYKrTmMQQACEICAbwILLLTmzHfq5NlO/SrcrXSETmaTEhO/KJxQMQY3tGXmtdd9MRFiBQIQgAAE1iWQ2dPXPeDoU+b4KUjBmNIROm0wZxTMpzhzueMLvrgosQQBCEAAAoFArlnUzA5wC2MVQsdt3czh2FlznK/z9IG68FMTlnXypGwIQAACfgmMt/rmbOzUwWub0j8n8E/rh3fE/qiYlji9sLawMXusU99wCwIQgAAEiiQwYM8u0lzBtk4v2J5rc2kJnUxtJmY/dUt80J7r1jccgwAEIACBYgiE1vvcsdDJHf9OFlMD61hJS+i0QzttnQg9fQgXfns6cE9e4QsEIAABCBRJoN1673U25Fy/Qz8rMlzvttITOrkFoRNadjxuW9ly28OjY/gEAQhAAAIFEfDdev8bze5zc0GRRmEmPaEz2uqj83u39HN7gVvfcAwCEIAABPojkNugbrUP7s9Iibkb9tgqkExP6ISocvtReHG55eqnE/4R2CAAAQhAID0CE7avgtrSbWCDdqpb30pyDKFTEthZzG5hE7bfLOc5BQEIQAAC8RLw3Gq/xBbahfGi7c3zNIXOqF0gHF6HmYeaen5v1UUuCEAAAhBwS6C91I/nYeWnWlhFoGFbmkKnXZF+m+ey1uir4YZda4QLAQhAIG0CE/YMBej3uz2zH6RdAdNHl6bQCbF6rtDcRvT4yrPqn/5q4SgEIAABCMxG4LDZTtZ87g4tLd2oiQLX8k5X6Ay1hpmvWBuow9dDHfqESxCAAAQg0AuB5badsoWOyF6309UAMOHVuTL9SlfoZFov3FxPirSP5tS5b5mVi20IQAACEKiIwCoLrTlZRaV1X0xmJ3WfKY0c6Qqddv1823E1Zdb+x3DsIq5BAAIQgMCcBMKSD5kdOme6+hKs0u/N9+srvt6S0xY6K1sdr1bWi3iW0jN7mebUmTdLCk5BAAIQgIB3AhP2JLm4rWM3z9Bq5bc49q9U19IWOpvY7aLnd+0rs630gO3AUmsY4xCAAAQgUC6B3F5dbgF9Ws/sxD4tRJ09baHTrhrfFZzbK6K+gnAeAhCAQJMJhE7Imesb1vDYqrH9c8Klmb7QWW0/VJyrHP8f7m+32f0d+4drEIAABCAwE4HV9kqd8vxb+rMmP7YK1ea5cma6rLo73n4u+ZPuMlWaOlMvnSMqLZHCIAABCECgfwK5LZCRw/s3VKqF40u1HoHx9IVOqITcvFf0ofLR72yaEVzIuAgBCECgcgITdojK3LzycjsvcEL9QE/uPHmaKZshdEZao6/GHFfhRroYX+TYP1yDAAQgAIF7EnjjPQ+5OnKybWHjrjyqwZlmCJ1MU/OZfa8Gvp0Xmdsb1Krjd7KpziMhJQQgAIH0CYzZExTkzq4Dzdw/zagEXzOEThul98dXO6hV56mV1DqFQAACEIBAfwQye1N/BkrPfUNT17Zan2xzhM6wnang/7U+AFefc/tPV/7gDAQgAAEI3JPAmD1UBw+45wlXR76uZwSeRxxXBqs5QiezST0a+mplZHsraG8tufaI3rKSCwIQgAAEKiGQ2ZtVju+uBpP2pUpYRFBIc4ROqIxJ+0oEdfKWCHzERQhAAALNJLC8tdRDGG3ld8vsPFtkf/HrYLWeNUvoLLYrhPfsahF3WVpuz7Yxe0iXuUgOAQhAAAJVEJhsdTGYX0VRfZTx5T7yJpe1WUKnXX3eL4BMDaK06iT3r0ZAEIBA9ASW2mbqAvFy53GEuXO+7dzHSt1rntAZtu+IcFjs0/P2Qg2I97wSrmd2+AYBCECgHAIDrdacDcsxXpDV3L6hKQw9zxtXUKCdm2me0Alz6mT29c4R1ZJyUH3l31ZLyRQKAQhAAAL3JBBacyyC5Xoy++w9nW/2keYJnVDfk3as+2rP7DBaddzXEg5CAAJNIdBuzfG9VE9u59uI/b4pVdJpnM0UOqP2JwE6u1NINaWbb6vtPTWVTbEQgAAEILCWwIRtpbf+F1+mNWdtja3z2kyhExDk9pl1SPj88EL1JnqAT9fwCgIQgEBDCOStASK+W3PMbtLS0Cc2pEa6CrO5QmektaLrdV3Rqj7xoA3af1VfLCVCAAIQgECLwHLbTq+viYDGF9X/9I4I/KzcxeYKnczu1EXx+cqJd1/g87X27MO7z0YOCEAAAhDom0C7C4H3eXPutAH7dN+xJmrA9xTWZUMf0wL2mV2tYjYou6g+7f9YHcy8r6vSZ4hzZB+zfeZIwWkIQKBoArld3+gZdsfsYfqNuFhYvf9WfkO/ES8ouvpTsee98srnPG5fVCEvK7+gPkvI7fE26r4DdZ9BzpJ9XL2q2CAAgaoJfE0/oIdWXaib8sbtFPlyoBt/ZnIks0eqf85vZjrd9OPNfXS1tuZz+/jat65fM/uwfuqpL9eVhHMQgEAyBMbtiYrFv8gx+yUiZ/arjh/OUbtUiE6bHZOLs7trZfMXuvAEJyAAAQikTCDXMBCzj0QRYmYfjcLPGp1E6LThx3KhvF+tOkM1Xi8UDQEIQCB9AsvscAW5UwSB/kW/CD+IwM9aXUToBPzDrRadGGaT3FqLtf2/Wq8YCocABCCQMoFbbLFuKP87khA/qG7Sk5H4WpubCJ2APtNlndsHaquFbgrO7SgtDRHmdWCDAAQgAIGiCSxorTO4edFmS7B3jW7STyjBbnImETprq3REy9pn9re1Hx2/bij9HsujNscYcQ0CEIDAegTG7KE68sb1jnr9+BH9Zq306pwnvxA6a2uj3fwXS6vOQZpEMIwIYIMABCAAgSII5JINWWvSPe+TA4Zob1ZrTpgaha0DAgidqZCG7Gv6+K+phxy//6Qet3mf6NAxPlyDAAQgMIXAhB2iT4+fcsTz2w9LlE14dtCTbwidqbXRbgb80NRDjt8/WB2T3+LYP1yDAAQgEAeB0AE5luHkoTVnGcs9dHNhIXTWpzXcWv/q+vUPu/ycq9Mcq5u7rBqcggAEIiKwgb1X3t4rEo8/rMWLxiPx1YWbCJ31qyHTmCaLZARWWKNr0D63fgh8hgAEIACBDgkssz3VDSCG1clDQLTmdFitU5MhdKbSWPu+3apzzdqPzl/3lbY/1LmPuAcBCEDAH4HQz3Gy1ak3lt9CWnN6uIpiqdweQusjS2jVyez9fVioOuvHJHa2rLpQyoMABCAQNYHx1pw5O0YSwxL65vRWUwidmbgN2Zd16uqZTjs7vpGaXo915hPuQAACEPBLYFxLPGQtoePXx6me5epHRN+cqUQ6fo/QmQlVewTWO2c67e54Zs+0MXuOO79wCAIQgIA3Au1FO78it+Z5c20Gf/5hI62BMjOc5vBsBBA6s9EZtq/rdFjdPI4tU8dkHmHFUVd4CQEI1Edgmb1Vhe9enwNdl/xOtT4xC3LX2NoZEDqzgQuzJcfUtGm2icJhtszZ6pRzEIBAswlM2G561P+uiCBcrFmQvxGRv+5cRejMVSXDdorEzrlzJXN0/qmaL/NljvzBFQhAAAI+COS2oUTO8XImlkdWYdHpt2pnhfI+riCETifwVtubO0nmKM3H7Ta7vyN/cAUCEIBA/QQmWnOkPaR+Rzr24DS15vyo49QknJYAQmdaLOsdXGTn6ci31zvq92Oubmvz7ATducRz1+KXJp5BAAIpEBi3fRXG6yIKZbW+w98Ukb9uXUXodFo1g611pVZ0mtxBuj3UMfm/HPiBCxCAAATqJTCmgdnWGlxSrx/dlJ5plNWo/bGbLKSdngBCZ3ou9zy60K7UwY/d84TjI5kdpSHn+zj2ENcgAAEIlEsgVw+XzL6mQrYqt6BCrd9qqy2e6U0KDb14Ywidbpgut/9R8hu6yVJz2gH9g39DYifczbBBAAIQaB6BCftPBb1/VIHn9m5bpHWt2AohgNDpBuPmkgzWmn+hm1x1p91KYud4PeulruuuCcqHAASqJRAW7LSolvMJfP6iXpafrRZU2qXx49dt/Q7bVyUaLug2W83pn6g1Ut5Wsw8UDwEIQKA6ArfZxhqU/U0VGNegjEwdkDNbVR2o9EtC6HRbx1mrbeQ1yhbXvAa5OiaP237dhkt6CEAAAtERCC3Y81rz5Wwfme+naDj5jyPz2b27CJ1eqmjYLpLi/lwvWWvME+r6/7Qu+7Y1+kDREIAABMonMN6a+fiA8gsqtIRlNmhHFmoRYy0CCJ1eL4Q77WhlvbHX7DXl21Q9+b+rNqkNaiqfYiEAAQiUS2DCDtSNaIwjlt5lC+2qcuE00zpCp9d638huVdY395q9xnyP0BIRx9ZYPkVDAAIQKIfA7fYA3ciFxZhj2y7RI6uPx+Z0LP4idPqpqeHW3Axn9WOiprwvVX+d19dUNsVCAAIQKJ7AjZpeb9BOkuGNijdewCwmgwAAIQhJREFUqsXQo+gVdEAujzFCpx+2oWPyanulTNzRj5ma8n6Uzsk1kadYCECgWAK5JM7C1grfDyvWcAXWcvuCDUU3krcCMMUVgdDpl+Viu1xK/D39mqkhf6j7E22pPaiGsikSAhCAQHEEJlqTuR5YnMHKLN2ggeRHVVZaQwtC6BRR8UP2IZm5tAhTFdvYSE2mP5TY2bTicikOAhCAQDEExu1QGfp/xRir3MobNdvPbZWX2rACETpFVHhmd0owHC5Tcc2t0479gWr0/b4ewi0oAgU2IAABCFRGYKn9m8r6QmXlFVlQbidrBuQwoSFbyQQQOkUBHrJfydQHizJXqZ3cHqeRWF+W2MkqLZfCIAABCPRKYKk9WDeY31f2+b2aqDHfbfq2fVWN5TeqaIROkdU9rIXYzP5YpMkKbb1AnZPfW2F5FAUBCECgNwITWol8wH6izJv0ZqD2XG9Ua871tXvREAfmNSTOasLMNPpqQs+L22thDVZTaIGlZFoPa8yu0yDNTxdoNWVTP9Rd2ZdSDpDYKiSQ2wkqbajCEuMs6mat653bj+T8dnEGYKdK5Hw1Ut+jdBuhU3S1DdtvJBY+oB/AOBfRzOwTa8TOd4tGk6C9v2mSr9B0zgaB/gmMq68f2+wEQl/CCfuOEj189oRuz94szw53612ijvHoqoyKHWkNN/9DGaYrsDkgkXaCxM4TKiiLIiAAAQh0RiD0IZxotYQ8sbMMDlPl9moeWVVfLwidMpiHR1i5HSLTMU4kGIhsoOffJ9sy26MMPNiEAAQg0BWBIHLG7bPK8/yu8vlKfIK6BZzoy6VmeIPQKaueR+1PEjuxzu1g8n1Eg+VP1ZfLTmUhwi4EIACBjgiECQHjHqV0la2013YUK4kKJ4DQKRzpFIMjrU69YWRArFuYSPAnFhbKY4MABCBQB4GJVn/Ht9RRdEFlTuqm8UUaH3Z7QfYw0yUBhE6XwLpKHtbCyuww5bmpq3y+Et9bEwqejdjxVSl4A4FGEBhTK0hu74s61lytUYvsl1HHELnzCJ2yK3BYw7Uze3HZxZRsf+uW2Flm9ym5HMxDAAIQaBMYU8fdLPKpLnI7X50A3k2V1ksAoVMF/2H7sYqJc9bku/lsrTurs9RBeZu7D/EOAhCAQAkE2iIndD6OebvV5tnzJNZWxRxECr4jdKqqxWE7WkLhgqqKK6Wc3O6vZ83n8RirFLoYhQAEAoE0RI5p5OrLbKFdTaXWTwChU1UdhIU/59m/q7hbqyqypHLuQ5+dkshiFgJNJ5CKyDFNvDpkJzW9Or3Ej9CpsiaCus+0RET8W7vPzpjtGH8oRAABCLggMG5H6fsx9sdVAeWvNGP6m10wxYkWAYRO1RfCsP1Aj7DeX3WxJZS3tb6UztZMpY8swTYmIQCBphBoTwZ4jML9nwRCvlmPrJ6j78aVCcSSTAgInTqqcsTeqWJ/VkfRBZe5mUTbz/RMfZ+C7WIOAhBoAoFcsqA943HM8+Ssralcbw7RI6tr1h7g1QcBhE4d9ZDZanXqfZ6KvrqO4gsuc5HuXn6klp2nF2wXcxCAQMoEcpuv742v6/vjVUmEmdm7NJT8tCRiSSwIhE5dFbrIbtY/+MEqPtb1sKaSW6iWnZP0pcWqvFOp8B4CEJiewBJJggk7RSfDmoDxb7l9Xy05740/kDQjQOjUWa/D9msV/8o6XSiw7AGJnf/VY6x3F2gTUxCAQGoExm1LiYJfKKwnJxLan22FJoUNM+GzuSSA0Km7Wkbsa3LhI3W7UVj5ofl23L6of/n5hdnEEAQgkAaBpfZgBRLmE9s1jYA0q9ikPdM21y0em1sCCB0PVTNsoSNemD05le1lapb+kd1ii1MJiDggAIE+CSy1x6nr8bmysl2flrxkn5Qjz9U6Vn/14hB+TE8AoTM9l2qPhs7JK+35KvSyagsutbT9bIHWeVlu25daCsYhAAH/BMa1eveAnSFHN/HvbIce5vZGOh93yKrmZAidmivgruI3URPoanuaPt9y17H43zxEMf3Kwp0cGwQg0DwC7eHjYY6c47QvSAZA6I84ap9MJp7EA0HoeKrgxXZ563mvJTXZ1Ba6kzuTEVmeLjR8gUAFBG6UFBhvLYOQwhw5U4H9TC05r516gPe+CSB0vNXPIvulXDrUm1t9+jO/NSJrQndAuVb8YoMABNImsNzuqwUtz9NIpNTm1/qzbkMPVlx3pl2BaUWH0PFYnyP2Tf0jHe3Rtb58yu1Itez8THd59+rLDpkhAAG/BCbsKXpk/Vs5+DC/Tvbk2Q1a0Pgp6mV0e0+5yVQbAYRObejnKHjY3qcUX54jVYyn95bTv7NltmeMzuMzBCAwA4GwZtWEppfI7VSl2HiGVLEenlB0T1Ur1VWxBtBkvxE6nmt/2F4h98KXRmrbvdUX6ReaeeKI1AIjHgg0ksBtEjYT9kOJnHcr/iwxBuEx1cFakTy0UrFFSACh47nSwrDzYc3TkOlZd3rbfMX1KX05fof5dtKrXCJqEIEJe6Qe6fxGER+QaNSvUOfjnyQaWyPCQuh4r+ZMD3nutAPl5h+9u9qTf7k9W3Mo/06CZ/ee8pMJAhCoh0B4VDVu/6FWnHP17n71OFF6qUdJ5Hy19FIooFQCCJ1S8RZkfCO7VUO095e1awqy6MtM+JLM1Wo1bq/Xa2rN3r5Y4w0EiiCw1DbTzUl4rP5h7aku9/JhiZwPFIELG/USQOjUy7/z0ofsWj3IeoIy3NR5pqhShsnEPq4vzx8xKiuqesPZphEYs8frxutihf2UhEP/sroNvDnh+BoVGkInpupebFfI3SB2bo7J7S59DS1Xl0jwpPq8v0scJIeAEwK5baibkI+ozTUs5bCVE6+KdyNTv8EwEITVyItnW5NFhE5N4HsudkQiYEDDHE0LK6S7ba5HWKdqVNYXbIkaj9kgAIF6CUxotfGJVofjN8mRlB8vn2JD9gJFuLpe4JReJAGETpE0q7I1pPWjJlsdlJdXVWQt5WT2cn3pXCJJ92+1lE+hEIDAoATO23XjcaFQ7Jg4jrPUkvMciZyVicfZuPCYjj/WKg9LRYxJ7GSau8I0jVW62/Zqwfp5uuERGQRcEzhEIqcJN8RB5ITv0ztc1wbO9USgCRdwT2CiyDSqxTLzBrTspN1UHsWlhpONJdCE34i1ImdZY2s58cCbcBGnXYXNETtp1yPRQQACdRBA5NRBveIyEToVAy+lOMROKVgxCgEIJE3g53pc9TQ9rqIlJ+lqtkY8e028CteEt1bshLlK2SAAAQhAYDYCoSXnAImcidkScS4NArTopFGP7SiC2MlsP324PaWwiAUCEIBAgQROXdPxmJacAqF6NoXQ8Vw7vfgWhp5bazh2qjMo90KFPBCAAARMgze+L5FzEI+rmnUxIHRSrO8wqeCkPVah/TPF8IgJAhCAQA8EvqbpRw+WyGGenB7gxZwFoRNz7c3m+yL7qw3a45Tk8tmScQ4CEIBAAwh8Qi05L5XIYcbjBlT2+iEidNYnktLnhXalmmpDy86vUwqLWCAAAQh0TCCzd6kl5w0SOXnHeUiYFAGETlLVOU0wo3aj7mT20ZmfTnOWQxCAAARSJTApcXO4vv/ek2qAxNUZAYROZ5ziThXmiRi2pyuI4+IOBO8hAAEIdERguUTOM/W996WOUpMoaQIInaSrd0pwoQPesB2qI8dMOcpbCEAAAqkRuEmDMfbT990pqQVGPL0RQOj0xi3OXOEZ9Yi9tdWca3ZnnEHgNQQgAIEZCfzVVtmetsjOmzEFJxpHAKHTuCpXwO3m3KfoHRMLNrH+iRkCKRLI7By15DzGNrK/pRgeMfVOAKHTO7u4c47YGWrfebSCuCruQPAeAhCAgB1vQ3pctchuhgUE1ieA0FmfSJM+j9qfJXYeqZB/0aSwiRUCEEiGQBgy/lY9kn+RHsnfkUxUBFIoAYROoTgjNNYefv5ECZ7PR+g9LkMAAs0lMCFx8yyJHAZYNPca6ChyhE5HmBJPFEZkjdqrJHZeo0hXJR4t4UEAArETyNQPJ1en42E7OfZQ8L98Agid8hnHU8KoHasvjyfK4RvjcbpGT3PboMbSKRoCTSVwum7HHqWbs0ubCoC4uyOA0OmOV/qpR+1sG7DdFGhYBZ1tNgKZWsHG7Tc2Zq+2WzXWgw0CECibwAfVivMUW2y3lF0Q9tMhkKUTCpEUSiC3BZpP+aNq4XltoXbTNbZCoX1P+1f0RXym+g5MphsqkZVCYNxuk93FpdiO3+hS/U+9RP9b348/FCKomgBCp2risZU3bi+Uy6Gj8lBsrtfo73Uq+5v6Yv6Gvph/W6MfFB0TAYTOTLV1qdYcP0gS8PKZEnAcArMRQOjMRodzbQLjtpPefEv7Q0DSNYG/tgTPpJ2oPgV/6jo3GZpDAKEzXV1/STcLr9P/0LLpTnIMAp0QQOh0Qok0pkdYwzZhnxKKl4KjZwKXieN31Qfqe7T09Mww3YwInal1O6EPr9LQ8eOnHuQ9BHohgNDphVqT84RHWVlrdNZIkzEUEPtV4vgDCZ9TJXrO1nsmOysAatQmEDprq+9i9XD7d81y/Je1B3iFQD8EEDr90Gtq3tvtgTbYepS1a1MRFBz3Mgme09XS8yPtP7GFdnXB9jEXAwGETqilT0r4vxnhH8MFG4+PCJ146sqXp7nN16Os98ipN2tnmoIiayezK2TudN3VnqH9LIbSFgnXsa1mC50lEjeHSuT82HEN4VqkBBA6kVacG7fHbC99QR0nf7Zz41NajoS1fC7Sfo5afc4R61+q38L1aYVINC0CzRU6p+jaPlyd9ZdwJUCgDAIInTKoNs3mzXqavoF9WmG/qGmh1xJve/r7c/XjcKEeIf5aj7r+QFN/LTVRbKFNEzqZpts0e4Nacb5ULEisQWBdAgiddXnwqR8CE/ZM/fh+Tibu1Y8Z8nZN4E7l+IPY/0YPEX8v0XOxfkIusS1aPyRdGyNDTQSaJXR+LpH+Uon0f9REm2IbRACh06DKriTUpbapfmw/qbIOqaQ8CpmZQG5/18lLtF8q8fNX1ctlGtt1mW3cmoF35nycqYdAM4TOmAT5W/T49XO6JsNjWTYIlE4AoVM64oYWQOuO54q/sSV8crtSPzVXSgCF16vV8fkq9ZO4RueYnK2O2ktf6PxYrTivYlRhHRdXs8tE6DS7/suNvt2681EV8uJyC8J6oQRC34nc/iWbN2i/TsJniUTQrXq9VZ9vbr2uVqvQgJYznZQomq92ohV2u5Y1XaFzYc2vzrawEOoC/ewN2Iaa4n+xbA3p/bDKXiQ7i2RksV4X63NY/2ntsSW20o5OslUqXaETFuB8g1pxvt7ZhUEqCBRLAKFTLE+sTUdg3PbVD9bn9IP1gOlOcyxZAqFlKPQfWruN6k0RUxFcq2vpJWp9OnOt4SReUxQ6mX1HdXWERE4QzWwQqIVAEV86tThOoRERGNF8MENaLyu398vrVRF5jqv9EQgLwYbWmLV7Ud8320g4n6F2p4/pmtqwPxfJXRKBq1VHz1L73HMQOSURxmzHBGjR6RgVCQshMGYP0z39sfqBelwh9jDSdAJ/1g/qC/SDelH0INJo0Vmp/+0PS9y8T/VCX6/oL8o0AijqDisNGkRRPoFRjQAa0iSDpjWzjInvygeefAkP0Q/rhZql+216HUw+Wt8B/lR9rR6mR4pvR+T4rqimeYfQaVqNe4g3DCsdsRPUhXUHufMx7as9uIUP0RKYpyvqfWo/+IW6SN8/2ijidfxq8X+2/qf310PKy+MNA89TJYDQSbVmY4hrU1uqL8c36Uvy4XL3jBhcxkfHBHJ7jM3TxIkT9grHXqbk2gr9775fjw0folac76UUGLGkRYA+OmnVZ9zRTNiB+uL8iIJ4UNyB4L0DAj+UD4dLSMcz2ieePjphor8T9KDwaE0OcJWDusYFCMxKgBadWfFwslICw/ZD3R3uKLHzepUb5t5gg0CvBA5UxkvVuvPMXg2Qb1oCZ6n/zSMlIF+EyJmWDwcdEkDoOKyURruUafj5qJaQWNWacye07nQ+AV2jwRH8NAQ2k2g+ScPQv6xpDsMEhGy9Ewij254mgfME3Yz8tncz5IRA9QR4dFU9c0rshsAy21pdld+lL9nDlI1RNd2wI+1UAldq5uUXS+78cupBV+99Prq6Sf97b9dIyS/rlTmwXF0wONMpAVp0OiVFunoIDNk/1cLzComdB8uBb9XjBKUmQGB7zd90tlp3PqBWng0SiKeqEE5VC84XEDlV4aacMgggdMqgis3iCSy2K9Rs/jx94e4m4z8uvgAsNoBA+L57s/rtXCjBs1MD4iVECEBABBA6XAZxEQgz4I7YAbpyHy3HfxqX83jrhMDO8uM3Ejv/qdYdvgOdVApuQKAsAvyTl0UWu+USGLILJHj2b7Xw5HZyuYVhPUECCxTTh9S6c6Ytt+0SjI+QIACBNQQQOlwKcRMILTyjGkKca+r5dh+eMMcHGwQ6JbC3+n9dotadF3eagXQQgEBcBBA6cdUX3s5EYNT+2OrDM6lZWs2+pP2OmZJyHALrERjV56+pdee7mqt7s/XO8RECEIicAEIn8grE/fUILLLLJHgOVwvPttr/W2dvWi8FHyEwPYHcDlKPnTDJ4AHTJ+AoBCAQIwGEToy1hs9zExi1JXqk9U4Njd1W/XheqQyXzZ2JFBCwe0kgn2pj9jldQSPwgAAE4ieA0Im/DolgNgKZupqGeUDCwoOZ1tIyO2225JyDQItAEMeh/9cy2xMiEIBA3AQQOnHXH953SiDTffqw7tRH7MnqfPpAZfuw9ps7zU66BhLItQzJpJ2j1p3/1tUzv4EECBkCSRBA6CRRjQTRFYH25IP/T8Jna+V7sVp6zusqP4mbRGBQ18fR6rdzvjoqh9m52SAAgcgIIHQiqzDcLZBAppFZI/Z1CZ7HyurO+kH7jF5ZNb1AxAmZ2l0dlS9S687r1LrDGoEJVSyhpE8AoZN+HRNhJwRGNJfKsB2hfSv9kD1b+w+UjUUMO2HXnDQbSuJ8Qq07p6nvTmgNZIMABCIggNCJoJJwsUICma3UaK3vaX+GxM69VfIbtF9UoQcU5Z/Afuq7c6lad57n31U8hAAEEDpcAxCYicCo3ahHW5/QvptEz8O0v1dJGaY+E69mHd9IrTvf1IzK37TbbONmhU60EIiLAEInrvrC27oIhJmXR+0dEj2hQ+rOiJ66KsJduc+zea0lJPZz5xkOQQACLQIIHS4ECHRLIPTnuafo+VO3ZkifDIHQX+d09d35pATwwmSiIhAIJEIAoZNIRRJGTQTuFj072qDdVz90r5Mnp2tfWZNHFFsXgdyOlNj5nfbd63KBciEAgXsSQOjckwlHINAbgYV2pVp6PqXHW0/SqJxNNRz5IBn6qvbrezNIrggJPFhi9wKJnXfodTBC/3EZAskRYD6I5KqUgNwRCPOujNuO+hv6ceyrfW/tYcVstpQJBMEzqQkpF9vlHYU5rm7NptS+tq9JuB/qyyW8gUB3BBA63fEiNQT6J5Cr++qYPUr3+/vqrj8Inz20b9i/YSw4JDAhgfsfNqT11sIyJLNtCJ3Z6HAOAj0TQOj0jI6MECiIQG4LtPTobrr7f4x+DB+jn8PHyvKWBVnHjA8CP5IbL1PryMyPMRE6PmoKL5IjgNBJrkoJKAkCK+x+mpf50S3hM2m76nUXxTWURGzNDeJmidhX6KHl96ZFgNCZFgsHIdAvAYROvwTJD4EqCISOreO2gwTPrioujOp5+JrXRVUUTxmFEjhOq6wdqe7qS9exitBZBwcfIFAUAYROUSSxA4E6CCy3bW21BJCps3OuyQwze4jeP1T7ZnW4Q5kdE7hK9fUSte78/K4cCJ27UPAGAkUSQOgUSRNbEPBC4HbbRKLnoRrivr1e76cf1e3lWtjvq/0+2hn6LAg1b6Fz8ke0kOzRqqM71GLHqKuaK4Ti0ySQpRkWUUEAAjMSCKO+Vtg2dqcET6bV2s3udderrfncft1E5zaY0Q4niiJwiQy9SPvPtTO8vCiq2IHAGgLzIAEBCDSMQKZuzqbJDdv77MHnEjoTtpFGhC2WPGq/5nrNNH5o7Y9ypgcwk2ohylrLH2yg1/lqQRq+y3CuWaIzTaE4dcvsqUrzgKmHGvx+J8V+oXa+jxt8ERB6eQT4xyqPLZYhED+B8EjF7IY1e3Hx3KiZgxfasTL4guKMRm1pQdTe4zwEHBNgCQjHlYNrEEiWwOaaMnHEXqj4DtO+bmtPskETGAQgUAcBhE4d1CkTAhBoExixr+ixVxguH/qpsEEAAhAonABCp3CkGIQABLoisMj+oh49j1Kfnc91lY/EEIAABDoggNDpABJJIACBkglkGgc2aq+W2HmOSgrDrNkgAAEIFEIAoVMIRoxAAAKFEBi172j81m4SPBcUYg8jEIBA4wkgdBp/CQAAAs4ILLR/qKPyXvLqg848wx0IQCBCAgidCCsNlyGQPIFM0xmO2FsU5/7ab0w+XgKEAARKI4DQKQ0thiEAgb4JjNhPNdlgWLn9zL5tYQACEGgkAYROI6udoCEQEYFhu06jsp4owfMOeb06Is9xFQIQcEAAoeOgEnABAhCYg0Cm2XaG7b36u49SXjtHak5DAAIQuIsAQucuFLyBAATcE1hk56hNZxeNyjrZva84CAEIuCCA0HFRDTgBAQh0TGCx3aKOys+S2Hmd8qzsOB8JIQCBRhJA6DSy2gkaApETyCRzRu1T6rezp/YrIo8G9yEAgRIJIHRKhItpCECgZALDdpFN2K4q5YSSS8I8BCAQKQGETqQVh9sQgMAaAlvY+JqV0F+qIxNwgQAEIDCVAEJnKg3eQwAC8RIYsa9qVNYjFMDF8QaB5xCAQNEEEDpFE8UeBCBQH4H2Suh7qN/OsfU5QckQgIAnAggdT7WBLxCAQP8Ewkrow/YadVc+WMZYCb1/oliAQNQEEDpRVx/OQwACMxIYte9qJfRdJXhYCX1GSJyAQPoEEDrp1zERQqC5BBbalWtWQv9AcyEQOQSaTQCh0+z6J3oIpE+gvRL6UQr0ydpZCT39GidCCKxDAKGzDg4+QAACyRIYsdMU287az0g2RgKDAATuQQChcw8kHIAABJIlMGLXq6PykzQq62jFyEroyVY0gUHgbgIInbtZ8A4CEGgCgfZK6O9bsxL6NU0ImRgh0GQCCJ0m1z6xQ6DJBNoroT9co7JYCb3J1wGxJ08AoZN8FRMgBCAwIwFWQp8RDScgkAoBhE4qNUkcEIBAbwTWroRutocMXN6bEXJBAAJeCSB0vNYMfkEAAtUSGLHf2zLbTYUeX23BlAYBCJRJAKFTJl1sQwACcRFor4T+Ijl9qHZWQo+r9vAWAtMSQOhMi4WDEIBAowmM2NfWrIT+h0ZzIHgIJEAAoZNAJRICBCBQAoH2Suh7as6dz5ZgHZMQgEBFBBA6FYGmGAhAIEIC7ZXQX6sh6M+W96yEHmEV4jIEEDpcAxCAAATmIjBq39NK6GHOHVZCn4sV5yHgjABCx1mF4A4EIOCUwEK7Siuh/5u8Cyuh5069xC0IQGA9Agid9YDwEQIQgMCMBDJbJbETVkLfX/uSGdNxAgIQcEMAoeOmKnAEAhCIhkB7JfRd5O/PovEZRyHQUAIInYZWPGFDAAJ9EmivhP5kjcp6uyyxEnqfOMkOgbIIIHTKIotdCEAgfQLtldDfrzl39lawrISefo0TYYQEEDoRVhouQwACzggssnPVphNGZX3fmWe4A4HGE0DoNP4SAAAEIFAIgfZK6AdJ7BwpeysLsYkRCECgbwIInb4RYgACEIDAGgLtldA/rU+shM5FAQEnBBA6TioCNyAAgYQI3L0S+tcTiopQIBAlAYROlNWG0xCAgHsC7ZXQXyw/X6KdldDdVxgOpkoAoZNqzRIXBCDgg8CIHadRWbvLGVZC91EjeNEwAgidhlU44UIAAjUQWGSX2bCFldA/U0PpFAmBRhNA6DS6+gkeAhCojEB7JfQjbMAOUpmshF4ZeApqOgGETtOvAOKHAASqJTBkJ2kl9F00DP38agumNAg0kwBCp5n1TtQQgECdBBba1VocdC+5cIx2VkKvsy4oO3kCCJ3kq5gAIQABlwTaK6G/Vb6FldBvcOkjTkEgAQIInQQqkRAgAIGICbRXQn+4Ijg94ihwHQJuCSB03FYNjkEAAo0h0F4JPbTsvE07K6E3puIJtAoCCJ0qKFMGBCAAgbkIhJXQR+x/9Df03WEl9Ll4cR4CHRJA6HQIimQQgAAEKiGwyM6zVa1RWayEXglwCkmdAEIn9RomPghAID4CG9mtNmrPWrMS+h3xBYDHEPBDAKHjpy7wBAIQgMC6BEYtrIS+p/a/rnuCTxCAQKcEEDqdkiIdBCAAgToItFdCD2tlsRJ6HfwpM3oCCJ3oq5AAIACB5AmwEnryVUyA5RFA6JTHFssQgAAEiiXQXgl9NxllJfRiyWItYQIInYQrl9AgAIEECSxSf51h24OV0BOsW0IqhQBCpxSsGIUABCBQIoHM7pDYWbsS+q0lloRpCERPAKETfRUSAAQg0FgC7ZXQH67WnfMay4DAITAHAYTOHIA4DQEIQMA1gbAS+pDtLR//RzsrobuuLJyrgwBCpw7qlAkBCECgSALtldDDOllP1s5K6EWyxVb0BBA60VchAUAAAhBYQ2CktQL6LvrESuhcFBBYQwChw6UAAQhAICUCI2rRGbawEvpbtbMSekp1Syw9EUDo9ISNTBCAAAQcE2ivhH6MDdi/ycurHXuKaxAonQBCp3TEFAABCECgJgJDdr5WQn+4uiifVJMHFAuB2gkgdGqvAhyAAAQgUCKB9kroB0nsHKFSWAm9RNSY9kkAoeOzXvAKAhCAQLEERu0zMhhWQr+sWMNYg4BvAggd3/WDdxCAAASKI9BeCf0RMnhccUaxBAHfBBA6vusH7yAAAQgUS6C9EvpLZPTF2ieKNY41CPgjgNDxVyd4BAEIQKB8AiP2dZs0VkIvnzQl1EwAoVNzBVA8BCAAgdoI3L0S+qdr84GCIVAyAYROyYAxDwEIQMA1gfZK6EdqYdBnyU9WQnddWTjXCwGETi/UyAMBCEAgNQLD9n0b1Jw7mZ2bWmjE02wCCJ1m1z/RQwACELibQHsl9H005877dZCV0O8mwzsIQAACEIAABJIiMG772bgdk1RMBAMBCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIBAqgT+PwQUc6J1VOHQAAAAAElFTkSuQmCC";
|
|
@@ -1686,7 +1830,7 @@ function DashboardIcon({ name }) {
|
|
|
1686
1830
|
// src/components/BrandMark.tsx
|
|
1687
1831
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1688
1832
|
function BrandMark({ logoUrl, className }) {
|
|
1689
|
-
const [failed, setFailed] =
|
|
1833
|
+
const [failed, setFailed] = useState6(false);
|
|
1690
1834
|
if (!logoUrl || failed) return /* @__PURE__ */ jsx2(SsMark, { className });
|
|
1691
1835
|
return /* @__PURE__ */ jsx2("img", { className, src: logoUrl, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
1692
1836
|
}
|
|
@@ -1711,9 +1855,9 @@ function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = "Dismiss" }) {
|
|
|
1711
1855
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1712
1856
|
function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = "Dismiss", introAllowed = false, onIntroStart }) {
|
|
1713
1857
|
const bubble = popupText ?? greeting;
|
|
1714
|
-
const [intro, setIntro] =
|
|
1715
|
-
const armedRef =
|
|
1716
|
-
|
|
1858
|
+
const [intro, setIntro] = useState7(false);
|
|
1859
|
+
const armedRef = useRef7(introAllowed);
|
|
1860
|
+
useEffect7(() => {
|
|
1717
1861
|
if (armedRef.current && bubble) {
|
|
1718
1862
|
armedRef.current = false;
|
|
1719
1863
|
setIntro(true);
|
|
@@ -1727,10 +1871,10 @@ function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup,
|
|
|
1727
1871
|
}
|
|
1728
1872
|
|
|
1729
1873
|
// src/components/ChatPanel.tsx
|
|
1730
|
-
import { useEffect as
|
|
1874
|
+
import { useEffect as useEffect14, useState as useState32 } from "react";
|
|
1731
1875
|
|
|
1732
1876
|
// src/components/ChatHeader.tsx
|
|
1733
|
-
import { useEffect as
|
|
1877
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState8 } from "react";
|
|
1734
1878
|
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1735
1879
|
function ChatHeader({
|
|
1736
1880
|
onClose,
|
|
@@ -1742,15 +1886,15 @@ function ChatHeader({
|
|
|
1742
1886
|
newConversationLabel = "New conversation",
|
|
1743
1887
|
moreOptionsLabel = "More options"
|
|
1744
1888
|
}) {
|
|
1745
|
-
const [menuOpen, setMenuOpen] =
|
|
1746
|
-
const wrapRef =
|
|
1747
|
-
const kebabRef =
|
|
1748
|
-
const firstItemRef =
|
|
1889
|
+
const [menuOpen, setMenuOpen] = useState8(false);
|
|
1890
|
+
const wrapRef = useRef8(null);
|
|
1891
|
+
const kebabRef = useRef8(null);
|
|
1892
|
+
const firstItemRef = useRef8(null);
|
|
1749
1893
|
const hasMenu = !!(canReset && onNewConversation);
|
|
1750
|
-
|
|
1894
|
+
useEffect8(() => {
|
|
1751
1895
|
if (menuOpen) firstItemRef.current?.focus();
|
|
1752
1896
|
}, [menuOpen]);
|
|
1753
|
-
|
|
1897
|
+
useEffect8(() => {
|
|
1754
1898
|
if (!menuOpen) return;
|
|
1755
1899
|
const onPointer = (e) => {
|
|
1756
1900
|
if (!wrapRef.current?.contains(e.target)) setMenuOpen(false);
|
|
@@ -1806,7 +1950,7 @@ function ChatHeader({
|
|
|
1806
1950
|
}
|
|
1807
1951
|
|
|
1808
1952
|
// src/components/MessageList.tsx
|
|
1809
|
-
import { useEffect as
|
|
1953
|
+
import { useEffect as useEffect12, useRef as useRef10 } from "react";
|
|
1810
1954
|
|
|
1811
1955
|
// src/components/Markdown.tsx
|
|
1812
1956
|
import ReactMarkdown from "react-markdown";
|
|
@@ -1824,7 +1968,7 @@ function Markdown({ text }) {
|
|
|
1824
1968
|
}
|
|
1825
1969
|
|
|
1826
1970
|
// src/components/EntityCardList.tsx
|
|
1827
|
-
import { useState as
|
|
1971
|
+
import { useState as useState9 } from "react";
|
|
1828
1972
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1829
1973
|
var MAX_VISIBLE = 3;
|
|
1830
1974
|
var RECORD_RE = /^(\d+)-(\d+)-(\d+)$/;
|
|
@@ -1908,7 +2052,7 @@ function ScopeTabs({ scopes, active, onSelect }) {
|
|
|
1908
2052
|
)) });
|
|
1909
2053
|
}
|
|
1910
2054
|
function EntityCardItem({ c }) {
|
|
1911
|
-
const [active, setActive] =
|
|
2055
|
+
const [active, setActive] = useState9(0);
|
|
1912
2056
|
const hasBody = c.scopes.length > 0;
|
|
1913
2057
|
if (!hasBody) {
|
|
1914
2058
|
return /* @__PURE__ */ jsx7("div", { className: "ss-w-ecard ss-w-ecard-bare", "data-kind": c.kind, children: /* @__PURE__ */ jsx7(CardHeader, { c, showScopeCrest: false }) });
|
|
@@ -1922,7 +2066,7 @@ function EntityCardItem({ c }) {
|
|
|
1922
2066
|
] });
|
|
1923
2067
|
}
|
|
1924
2068
|
function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMoreLabel = (n) => `Show ${n} more` }) {
|
|
1925
|
-
const [expanded, setExpanded] =
|
|
2069
|
+
const [expanded, setExpanded] = useState9(false);
|
|
1926
2070
|
if (cards.length === 0) return null;
|
|
1927
2071
|
const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE);
|
|
1928
2072
|
const overflow = cards.length - MAX_VISIBLE;
|
|
@@ -1933,18 +2077,18 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
|
|
|
1933
2077
|
}
|
|
1934
2078
|
|
|
1935
2079
|
// src/components/BettingInsightList.tsx
|
|
1936
|
-
import { useState as
|
|
2080
|
+
import { useState as useState13 } from "react";
|
|
1937
2081
|
|
|
1938
2082
|
// src/components/AddToSlipButton.tsx
|
|
1939
|
-
import { useCallback as
|
|
2083
|
+
import { useCallback as useCallback6, useState as useState10 } from "react";
|
|
1940
2084
|
import { isAddToSlipResult } from "@sensiblestats/widget-sdk";
|
|
1941
2085
|
|
|
1942
2086
|
// src/components/Toast.tsx
|
|
1943
|
-
import { useEffect as
|
|
2087
|
+
import { useEffect as useEffect9 } from "react";
|
|
1944
2088
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1945
2089
|
var DISMISS_MS = 4e3;
|
|
1946
2090
|
function Toast({ toast, onDismiss }) {
|
|
1947
|
-
|
|
2091
|
+
useEffect9(() => {
|
|
1948
2092
|
if (!toast) return;
|
|
1949
2093
|
const timer = setTimeout(onDismiss, DISMISS_MS);
|
|
1950
2094
|
return () => clearTimeout(timer);
|
|
@@ -1962,10 +2106,10 @@ function withTimeout(value) {
|
|
|
1962
2106
|
]);
|
|
1963
2107
|
}
|
|
1964
2108
|
function SlipButton({ selection, shownOdds, marketName, marketDeveloperName, slip, ui }) {
|
|
1965
|
-
const [pending, setPending] =
|
|
1966
|
-
const [settled, setSettled] =
|
|
1967
|
-
const [toast, setToast] =
|
|
1968
|
-
const dismiss =
|
|
2109
|
+
const [pending, setPending] = useState10(false);
|
|
2110
|
+
const [settled, setSettled] = useState10(false);
|
|
2111
|
+
const [toast, setToast] = useState10(null);
|
|
2112
|
+
const dismiss = useCallback6(() => setToast(null), []);
|
|
1969
2113
|
const log = useEventLog();
|
|
1970
2114
|
const handler = slip.onAddToSlip;
|
|
1971
2115
|
if (!ui || !handler || !selection) return null;
|
|
@@ -2055,14 +2199,14 @@ function OddsMovementBadge({
|
|
|
2055
2199
|
}
|
|
2056
2200
|
|
|
2057
2201
|
// src/components/Crest.tsx
|
|
2058
|
-
import { useState as
|
|
2202
|
+
import { useState as useState11 } from "react";
|
|
2059
2203
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2060
2204
|
function initials2(name) {
|
|
2061
2205
|
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
2062
2206
|
}
|
|
2063
2207
|
function Crest2({ url, name, kind }) {
|
|
2064
2208
|
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
2065
|
-
const [failed, setFailed] =
|
|
2209
|
+
const [failed, setFailed] = useState11(false);
|
|
2066
2210
|
if (url && !failed) {
|
|
2067
2211
|
return /* @__PURE__ */ jsx11("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
2068
2212
|
}
|
|
@@ -2070,7 +2214,7 @@ function Crest2({ url, name, kind }) {
|
|
|
2070
2214
|
}
|
|
2071
2215
|
|
|
2072
2216
|
// src/components/PinToggle.tsx
|
|
2073
|
-
import { useCallback as
|
|
2217
|
+
import { useCallback as useCallback7, useState as useState12 } from "react";
|
|
2074
2218
|
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2075
2219
|
var PIN_GLYPHS = {
|
|
2076
2220
|
pin: { viewBox: "0 0 24 24", strokeWidth: 1.4, transform: "scale(1.5)", d: "M9.5 1.5 14.5 6.5 13 8l-.5-.5-3 3 .3 2.2-1.4 1.4L5.6 11.3l-3.3 3.3-1-1 3.3-3.3L1.9 7.5l1.4-1.4 2.2.3 3-3L8 2.9z" },
|
|
@@ -2078,8 +2222,8 @@ var PIN_GLYPHS = {
|
|
|
2078
2222
|
bookmark: { viewBox: "0 0 24 24", strokeWidth: 2, d: "M7 3h10a1.5 1.5 0 0 1 1.5 1.5V21l-6.5-3.6L5.5 21V4.5A1.5 1.5 0 0 1 7 3z" }
|
|
2079
2223
|
};
|
|
2080
2224
|
function PinToggle({ pin, monitor, ui }) {
|
|
2081
|
-
const [toast, setToast] =
|
|
2082
|
-
const dismiss =
|
|
2225
|
+
const [toast, setToast] = useState12(null);
|
|
2226
|
+
const dismiss = useCallback7(() => setToast(null), []);
|
|
2083
2227
|
const log = useEventLog();
|
|
2084
2228
|
if (!monitor || !monitor.enabled) return null;
|
|
2085
2229
|
const key = pinKey(pin);
|
|
@@ -2139,7 +2283,7 @@ function StatRows({ stats }) {
|
|
|
2139
2283
|
] }, `${s.label}:${s.value}`)) });
|
|
2140
2284
|
}
|
|
2141
2285
|
function ScopedStats({ scopes }) {
|
|
2142
|
-
const [active, setActive] =
|
|
2286
|
+
const [active, setActive] = useState13(0);
|
|
2143
2287
|
const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
|
|
2144
2288
|
return /* @__PURE__ */ jsxs9("div", { className: "ss-w-bi-scoped", children: [
|
|
2145
2289
|
/* @__PURE__ */ jsx13("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx13("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
|
|
@@ -2150,7 +2294,7 @@ function hasStatsContent(it) {
|
|
|
2150
2294
|
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
2151
2295
|
}
|
|
2152
2296
|
function ReasonStrip({ it, ui }) {
|
|
2153
|
-
const [open, setOpen] =
|
|
2297
|
+
const [open, setOpen] = useState13(false);
|
|
2154
2298
|
const log = useEventLog();
|
|
2155
2299
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
2156
2300
|
const hasStats = hasStatsContent(it);
|
|
@@ -2270,7 +2414,7 @@ function BettingInsightList({ insights, ui, slip, monitor }) {
|
|
|
2270
2414
|
}
|
|
2271
2415
|
|
|
2272
2416
|
// src/components/MarketOddsCardList.tsx
|
|
2273
|
-
import { useState as
|
|
2417
|
+
import { useState as useState14 } from "react";
|
|
2274
2418
|
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2275
2419
|
function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
2276
2420
|
const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null;
|
|
@@ -2287,7 +2431,7 @@ function OddsRow({ vm, row, ui, slip, inSlipIds }) {
|
|
|
2287
2431
|
] });
|
|
2288
2432
|
}
|
|
2289
2433
|
function MarketOddsCard({ vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }) {
|
|
2290
|
-
const [open, setOpen] =
|
|
2434
|
+
const [open, setOpen] = useState14(false);
|
|
2291
2435
|
const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : void 0;
|
|
2292
2436
|
const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : void 0);
|
|
2293
2437
|
const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName;
|
|
@@ -2590,7 +2734,7 @@ function FixtureCard({ card }) {
|
|
|
2590
2734
|
}
|
|
2591
2735
|
|
|
2592
2736
|
// src/components/dashboard/CountdownCard.tsx
|
|
2593
|
-
import { Fragment as Fragment6, useEffect as
|
|
2737
|
+
import { Fragment as Fragment6, useEffect as useEffect10, useState as useState15 } from "react";
|
|
2594
2738
|
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2595
2739
|
var DAY_MS = 864e5;
|
|
2596
2740
|
function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
@@ -2609,12 +2753,12 @@ function remainingSegments(kickoffUnix, nowMs, withSeconds) {
|
|
|
2609
2753
|
function CountdownCard({ card }) {
|
|
2610
2754
|
const { data } = card;
|
|
2611
2755
|
const unitLabel = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit };
|
|
2612
|
-
const [nowMs, setNowMs] =
|
|
2613
|
-
const [reduced] =
|
|
2756
|
+
const [nowMs, setNowMs] = useState15(() => Date.now());
|
|
2757
|
+
const [reduced] = useState15(
|
|
2614
2758
|
() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
2615
2759
|
);
|
|
2616
2760
|
const withinDay = data.kickoffUnix * 1e3 - nowMs < DAY_MS;
|
|
2617
|
-
|
|
2761
|
+
useEffect10(() => {
|
|
2618
2762
|
if (reduced) return;
|
|
2619
2763
|
const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1e3 : 6e4);
|
|
2620
2764
|
return () => window.clearInterval(id);
|
|
@@ -2633,7 +2777,7 @@ function CountdownCard({ card }) {
|
|
|
2633
2777
|
}
|
|
2634
2778
|
|
|
2635
2779
|
// src/components/dashboard/InjuriesCard.tsx
|
|
2636
|
-
import { useState as
|
|
2780
|
+
import { useState as useState16 } from "react";
|
|
2637
2781
|
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2638
2782
|
var SHOWN = 3;
|
|
2639
2783
|
function ColHead({ name, crestUrl }) {
|
|
@@ -2656,7 +2800,7 @@ function InjuryList({ rows, emptyLabel, limit }) {
|
|
|
2656
2800
|
}
|
|
2657
2801
|
function InjuriesCard({ card, ui }) {
|
|
2658
2802
|
const { data } = card;
|
|
2659
|
-
const [expanded, setExpanded] =
|
|
2803
|
+
const [expanded, setExpanded] = useState16(false);
|
|
2660
2804
|
const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN);
|
|
2661
2805
|
const limit = expanded ? void 0 : SHOWN;
|
|
2662
2806
|
const showMore = ui?.showMore ?? ((n) => `Show ${n} more`);
|
|
@@ -2762,7 +2906,7 @@ function LinksCard({ card }) {
|
|
|
2762
2906
|
}
|
|
2763
2907
|
|
|
2764
2908
|
// src/components/dashboard/PostMatchResultCard.tsx
|
|
2765
|
-
import { useState as
|
|
2909
|
+
import { useState as useState17 } from "react";
|
|
2766
2910
|
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2767
2911
|
function initials3(name) {
|
|
2768
2912
|
return name.trim().slice(0, 3).toUpperCase();
|
|
@@ -2772,7 +2916,7 @@ function PostMatchCrest({
|
|
|
2772
2916
|
name,
|
|
2773
2917
|
side
|
|
2774
2918
|
}) {
|
|
2775
|
-
const [failed, setFailed] =
|
|
2919
|
+
const [failed, setFailed] = useState17(false);
|
|
2776
2920
|
const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`;
|
|
2777
2921
|
if (url && !failed) {
|
|
2778
2922
|
return /* @__PURE__ */ jsx27("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -2971,10 +3115,10 @@ function RestingFormCard({ card }) {
|
|
|
2971
3115
|
}
|
|
2972
3116
|
|
|
2973
3117
|
// src/components/dashboard/LiveScoreCard.tsx
|
|
2974
|
-
import { useRef as
|
|
3118
|
+
import { useRef as useRef9, useState as useState19 } from "react";
|
|
2975
3119
|
|
|
2976
3120
|
// src/useLiveClock.ts
|
|
2977
|
-
import { useEffect as
|
|
3121
|
+
import { useEffect as useEffect11, useState as useState18 } from "react";
|
|
2978
3122
|
var TICK_MS = 6e4;
|
|
2979
3123
|
var MAX_LIVE_TICK_MINUTES = 15;
|
|
2980
3124
|
function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
@@ -2983,10 +3127,10 @@ function computeDisplayMinute(minute, clockRunning, receivedAtMs) {
|
|
|
2983
3127
|
return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES);
|
|
2984
3128
|
}
|
|
2985
3129
|
function useLiveClock(minute, clockRunning, receivedAtMs) {
|
|
2986
|
-
const [displayMinute, setDisplayMinute] =
|
|
3130
|
+
const [displayMinute, setDisplayMinute] = useState18(
|
|
2987
3131
|
() => computeDisplayMinute(minute, clockRunning, receivedAtMs)
|
|
2988
3132
|
);
|
|
2989
|
-
|
|
3133
|
+
useEffect11(() => {
|
|
2990
3134
|
setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs));
|
|
2991
3135
|
if (!clockRunning) return;
|
|
2992
3136
|
const id = window.setInterval(() => {
|
|
@@ -3003,7 +3147,7 @@ function initials5(name) {
|
|
|
3003
3147
|
return name.trim().slice(0, 3).toUpperCase();
|
|
3004
3148
|
}
|
|
3005
3149
|
function LiveCrest({ url, name, side }) {
|
|
3006
|
-
const [failed, setFailed] =
|
|
3150
|
+
const [failed, setFailed] = useState19(false);
|
|
3007
3151
|
const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`;
|
|
3008
3152
|
if (url && !failed) {
|
|
3009
3153
|
return /* @__PURE__ */ jsx36("img", { className: cls, src: url, alt: "", "aria-hidden": "true", onError: () => setFailed(true) });
|
|
@@ -3022,7 +3166,7 @@ function LiveScoreCard({
|
|
|
3022
3166
|
}) {
|
|
3023
3167
|
const { data } = card;
|
|
3024
3168
|
const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`;
|
|
3025
|
-
const seedRef =
|
|
3169
|
+
const seedRef = useRef9(null);
|
|
3026
3170
|
if (!seedRef.current || seedRef.current.key !== seedKey) {
|
|
3027
3171
|
seedRef.current = { key: seedKey, receivedAtMs: Date.now() };
|
|
3028
3172
|
}
|
|
@@ -3062,7 +3206,7 @@ function LiveScoreCard({
|
|
|
3062
3206
|
}
|
|
3063
3207
|
|
|
3064
3208
|
// src/components/dashboard/LiveTimelineCard.tsx
|
|
3065
|
-
import { useState as
|
|
3209
|
+
import { useState as useState20 } from "react";
|
|
3066
3210
|
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3067
3211
|
var SHOWN2 = 3;
|
|
3068
3212
|
function EventIcon({ type }) {
|
|
@@ -3104,7 +3248,7 @@ function EventRow({ e }) {
|
|
|
3104
3248
|
] });
|
|
3105
3249
|
}
|
|
3106
3250
|
function LiveTimelineCard({ card, ui }) {
|
|
3107
|
-
const [expanded, setExpanded] =
|
|
3251
|
+
const [expanded, setExpanded] = useState20(false);
|
|
3108
3252
|
const events = card.data.events;
|
|
3109
3253
|
if (!events || events.length === 0) return null;
|
|
3110
3254
|
const sorted = [...events].sort((a, b) => b.minute - a.minute);
|
|
@@ -3344,11 +3488,11 @@ function turnAnchor(messages) {
|
|
|
3344
3488
|
}
|
|
3345
3489
|
function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
3346
3490
|
const { state, send } = controller;
|
|
3347
|
-
const listRef =
|
|
3348
|
-
const endRef =
|
|
3349
|
-
const pinnedRef =
|
|
3350
|
-
const anchoredTurnRef =
|
|
3351
|
-
|
|
3491
|
+
const listRef = useRef10(null);
|
|
3492
|
+
const endRef = useRef10(null);
|
|
3493
|
+
const pinnedRef = useRef10(true);
|
|
3494
|
+
const anchoredTurnRef = useRef10(null);
|
|
3495
|
+
useEffect12(() => {
|
|
3352
3496
|
const anchor = turnAnchor(state.messages);
|
|
3353
3497
|
const list = listRef.current;
|
|
3354
3498
|
if (anchor && anchor.turnId !== anchoredTurnRef.current) {
|
|
@@ -3404,10 +3548,10 @@ function MessageList({ controller, ui, slip, onDashboardTap, monitor }) {
|
|
|
3404
3548
|
}
|
|
3405
3549
|
|
|
3406
3550
|
// src/components/ChatInput.tsx
|
|
3407
|
-
import { useState as
|
|
3551
|
+
import { useState as useState21 } from "react";
|
|
3408
3552
|
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3409
3553
|
function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
|
|
3410
|
-
const [value, setValue] =
|
|
3554
|
+
const [value, setValue] = useState21("");
|
|
3411
3555
|
const submit = () => {
|
|
3412
3556
|
const t = value.trim();
|
|
3413
3557
|
if (!t) return;
|
|
@@ -3428,12 +3572,16 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
|
|
|
3428
3572
|
|
|
3429
3573
|
// src/components/TabBar.tsx
|
|
3430
3574
|
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3431
|
-
function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday }) {
|
|
3575
|
+
function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday, gamesEnabled }) {
|
|
3432
3576
|
const tabs = [
|
|
3433
3577
|
{ tab: "chat", label: ui.tabChat, count: 0, dot: monitor.chatDot },
|
|
3434
3578
|
...hasToday ? [{ tab: "today", label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : [],
|
|
3435
3579
|
...matchCount > 0 ? [{ tab: "following", label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : [],
|
|
3436
|
-
...oddsCount > 0 ? [{ tab: "odds", label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []
|
|
3580
|
+
...oddsCount > 0 ? [{ tab: "odds", label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : [],
|
|
3581
|
+
...gamesEnabled ? [
|
|
3582
|
+
{ tab: "games", label: ui.tabGames, count: 0, dot: false },
|
|
3583
|
+
{ tab: "leaderboard", label: ui.tabLeaderboard, count: 0, dot: false }
|
|
3584
|
+
] : []
|
|
3437
3585
|
];
|
|
3438
3586
|
if (tabs.length < 2) return null;
|
|
3439
3587
|
return /* @__PURE__ */ jsx45("div", { className: "ss-w-tabs", role: "tablist", children: tabs.map(({ tab, label, count, dot }) => {
|
|
@@ -3542,9 +3690,28 @@ function isPromoted(row, promotedPins) {
|
|
|
3542
3690
|
function formatTime(iso) {
|
|
3543
3691
|
return new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
3544
3692
|
}
|
|
3693
|
+
function groupScorers(goals, ownGoalLabel) {
|
|
3694
|
+
const order = [];
|
|
3695
|
+
const minutesByPlayer = /* @__PURE__ */ new Map();
|
|
3696
|
+
for (const g of goals) {
|
|
3697
|
+
const name = g.player ?? "";
|
|
3698
|
+
const minute = g.ownGoal ? `${g.minuteLabel} (${ownGoalLabel})` : g.minuteLabel;
|
|
3699
|
+
if (!minutesByPlayer.has(name)) {
|
|
3700
|
+
minutesByPlayer.set(name, []);
|
|
3701
|
+
order.push(name);
|
|
3702
|
+
}
|
|
3703
|
+
minutesByPlayer.get(name).push(minute);
|
|
3704
|
+
}
|
|
3705
|
+
return order.map((name) => {
|
|
3706
|
+
const minutes = minutesByPlayer.get(name).join(", ");
|
|
3707
|
+
return { player: name, label: name ? `${name} ${minutes}` : minutes };
|
|
3708
|
+
});
|
|
3709
|
+
}
|
|
3545
3710
|
function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
|
|
3546
3711
|
const live = match.phase === "live";
|
|
3547
|
-
const
|
|
3712
|
+
const goals = match.events.filter((e) => e.type === "goal");
|
|
3713
|
+
const homeScorers = groupScorers(goals.filter((e) => e.side === "home"), ui.ownGoalLabel);
|
|
3714
|
+
const awayScorers = groupScorers(goals.filter((e) => e.side === "away"), ui.ownGoalLabel);
|
|
3548
3715
|
const promotedRows = match.statRows.filter((row) => isPromoted(row, promotedPins));
|
|
3549
3716
|
const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins));
|
|
3550
3717
|
const orderedRows = [...promotedRows, ...otherRows];
|
|
@@ -3580,7 +3747,11 @@ function MonitorMatchCard({ match, promotedPins, monitor, ui, slip }) {
|
|
|
3580
3747
|
/* @__PURE__ */ jsx47("span", { className: "ss-w-mon-name", children: match.awayTeamName })
|
|
3581
3748
|
] })
|
|
3582
3749
|
] }),
|
|
3583
|
-
|
|
3750
|
+
(homeScorers.length > 0 || awayScorers.length > 0) && /* @__PURE__ */ jsxs42("div", { className: "ss-w-mon-scorers", children: [
|
|
3751
|
+
/* @__PURE__ */ jsx47("ul", { className: "ss-w-mon-scorers-col ss-w-mon-scorers-home", children: homeScorers.map((s, i) => /* @__PURE__ */ jsx47("li", { children: s.label }, `${s.player}-${i}`)) }),
|
|
3752
|
+
/* @__PURE__ */ jsx47("span", { className: "ss-w-mon-scorers-ball", "aria-hidden": "true", children: "\u26BD" }),
|
|
3753
|
+
/* @__PURE__ */ jsx47("ul", { className: "ss-w-mon-scorers-col ss-w-mon-scorers-away", children: awayScorers.map((s, i) => /* @__PURE__ */ jsx47("li", { children: s.label }, `${s.player}-${i}`)) })
|
|
3754
|
+
] }),
|
|
3584
3755
|
/* @__PURE__ */ jsx47("div", { className: "ss-w-mon-stats", children: orderedRows.map((row) => {
|
|
3585
3756
|
const total = row.homeNum + row.awayNum;
|
|
3586
3757
|
const homePct = total > 0 ? row.homeNum / total * 75 : 0;
|
|
@@ -3802,12 +3973,1604 @@ function TodayPanel({ discovery, ui, monitor }) {
|
|
|
3802
3973
|
] });
|
|
3803
3974
|
}
|
|
3804
3975
|
|
|
3976
|
+
// src/components/GamesPanel.tsx
|
|
3977
|
+
import { useState as useState30 } from "react";
|
|
3978
|
+
|
|
3979
|
+
// src/components/GamesLoginWall.tsx
|
|
3980
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
3981
|
+
function GamesLoginWall({ ui }) {
|
|
3982
|
+
return /* @__PURE__ */ jsx52("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ jsx52("div", { className: "ss-w-games-wall", children: /* @__PURE__ */ jsx52("p", { children: ui.gamesLoginRequired }) }) });
|
|
3983
|
+
}
|
|
3984
|
+
|
|
3985
|
+
// src/components/GameTile.tsx
|
|
3986
|
+
import { Fragment as Fragment8, jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
3987
|
+
var GAME_ICONS = {
|
|
3988
|
+
"mystery-tiger": "\u{1F42F}",
|
|
3989
|
+
"daily-quiz": "\u{1F9E0}",
|
|
3990
|
+
"career-path": "\u26BD",
|
|
3991
|
+
"beat-the-grid": "\u{1F3AF}",
|
|
3992
|
+
"guess-xi": "\u{1F4CB}",
|
|
3993
|
+
"head-of-league": "\u{1F3C6}"
|
|
3994
|
+
};
|
|
3995
|
+
function gameIcon(game) {
|
|
3996
|
+
return GAME_ICONS[game.gameId] ?? (game.kind === "fixture" ? "\u{1F4C5}" : "\u{1F3AE}");
|
|
3997
|
+
}
|
|
3998
|
+
function formatCountdown(lockAtUtc) {
|
|
3999
|
+
const diff = new Date(lockAtUtc).getTime() - Date.now();
|
|
4000
|
+
if (diff <= 0) return null;
|
|
4001
|
+
const totalMins = Math.floor(diff / 6e4);
|
|
4002
|
+
const hours = Math.floor(totalMins / 60);
|
|
4003
|
+
const mins = totalMins % 60;
|
|
4004
|
+
if (hours > 0) return `${hours}h ${mins}m`;
|
|
4005
|
+
return `${mins}m`;
|
|
4006
|
+
}
|
|
4007
|
+
function tileStatusLabel(game, ui) {
|
|
4008
|
+
switch (game.status) {
|
|
4009
|
+
case "available":
|
|
4010
|
+
return ui.gamePlay;
|
|
4011
|
+
case "in_progress":
|
|
4012
|
+
return ui.gameResume;
|
|
4013
|
+
case "played":
|
|
4014
|
+
case "graded": {
|
|
4015
|
+
const pts = game.score ?? 0;
|
|
4016
|
+
return `+${pts.toLocaleString("en")}`;
|
|
4017
|
+
}
|
|
4018
|
+
case "locked":
|
|
4019
|
+
return ui.gameLocked;
|
|
4020
|
+
case "voided":
|
|
4021
|
+
return ui.gameVoided;
|
|
4022
|
+
default:
|
|
4023
|
+
return "";
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
var DISABLED_STATUSES = /* @__PURE__ */ new Set(["locked", "voided"]);
|
|
4027
|
+
function GameTile({
|
|
4028
|
+
game,
|
|
4029
|
+
onOpen,
|
|
4030
|
+
ui
|
|
4031
|
+
}) {
|
|
4032
|
+
const disabled = DISABLED_STATUSES.has(game.status);
|
|
4033
|
+
const statusLabel = tileStatusLabel(game, ui);
|
|
4034
|
+
const countdown = game.kind === "fixture" && game.lockAtUtc ? formatCountdown(game.lockAtUtc) : null;
|
|
4035
|
+
const statusClass = `ss-w-tile-status ss-w-tile-status--${game.status}`;
|
|
4036
|
+
const inner = /* @__PURE__ */ jsxs47(Fragment8, { children: [
|
|
4037
|
+
/* @__PURE__ */ jsx53("span", { className: "ss-w-tile-icon", children: gameIcon(game) }),
|
|
4038
|
+
/* @__PURE__ */ jsx53("span", { className: "ss-w-tile-title", children: game.title ?? game.gameId }),
|
|
4039
|
+
countdown !== null ? /* @__PURE__ */ jsx53("span", { className: statusClass, "data-testid": "tile-countdown", children: countdown }) : /* @__PURE__ */ jsx53("span", { className: statusClass, children: statusLabel }),
|
|
4040
|
+
/* @__PURE__ */ jsx53("span", { className: `ss-w-tile-chip ss-w-tile-chip--${game.ranked ? "skill" : "fun"}`, children: game.ranked ? "Skill" : "For fun" })
|
|
4041
|
+
] });
|
|
4042
|
+
if (disabled) {
|
|
4043
|
+
return /* @__PURE__ */ jsx53("div", { className: "ss-w-tile", "data-disabled": true, children: inner });
|
|
4044
|
+
}
|
|
4045
|
+
return /* @__PURE__ */ jsx53(
|
|
4046
|
+
"button",
|
|
4047
|
+
{
|
|
4048
|
+
type: "button",
|
|
4049
|
+
className: "ss-w-tile",
|
|
4050
|
+
onClick: () => onOpen(game),
|
|
4051
|
+
children: inner
|
|
4052
|
+
}
|
|
4053
|
+
);
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
// src/components/GamesHub.tsx
|
|
4057
|
+
import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4058
|
+
function GamesHub({
|
|
4059
|
+
games,
|
|
4060
|
+
weeklyPrize,
|
|
4061
|
+
streak,
|
|
4062
|
+
weeklyRank,
|
|
4063
|
+
onOpen,
|
|
4064
|
+
ui
|
|
4065
|
+
}) {
|
|
4066
|
+
const showPrize = weeklyPrize || streak !== void 0 || weeklyRank !== void 0;
|
|
4067
|
+
return /* @__PURE__ */ jsxs48("div", { className: "ss-w-games-hub", children: [
|
|
4068
|
+
showPrize && /* @__PURE__ */ jsxs48("div", { className: "ss-w-prize", children: [
|
|
4069
|
+
/* @__PURE__ */ jsx54("span", { className: "ss-w-prize-icon", children: "\u{1F3C6}" }),
|
|
4070
|
+
/* @__PURE__ */ jsxs48("div", { className: "ss-w-prize-body", children: [
|
|
4071
|
+
weeklyPrize && /* @__PURE__ */ jsx54("span", { className: "ss-w-prize-text", children: weeklyPrize }),
|
|
4072
|
+
(streak !== void 0 || weeklyRank !== void 0) && /* @__PURE__ */ jsxs48("div", { className: "ss-w-g-chips", children: [
|
|
4073
|
+
streak !== void 0 && /* @__PURE__ */ jsxs48("span", { className: "ss-w-g-chip ss-w-g-chip--streak", children: [
|
|
4074
|
+
"\u{1F525} ",
|
|
4075
|
+
streak
|
|
4076
|
+
] }),
|
|
4077
|
+
weeklyRank !== void 0 && /* @__PURE__ */ jsxs48("span", { className: "ss-w-g-chip ss-w-g-chip--rank", children: [
|
|
4078
|
+
"#",
|
|
4079
|
+
weeklyRank
|
|
4080
|
+
] })
|
|
4081
|
+
] })
|
|
4082
|
+
] })
|
|
4083
|
+
] }),
|
|
4084
|
+
/* @__PURE__ */ jsx54("div", { className: "ss-w-gmatrix", children: games.map((g) => /* @__PURE__ */ jsx54(GameTile, { game: g, onOpen, ui }, `${g.gameId}-${g.gameDay}`)) })
|
|
4085
|
+
] });
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
// src/components/GameScreenHost.tsx
|
|
4089
|
+
import { useEffect as useEffect13, useRef as useRef12, useState as useState29 } from "react";
|
|
4090
|
+
|
|
4091
|
+
// src/useGamePlay.ts
|
|
4092
|
+
import { useCallback as useCallback8, useRef as useRef11, useState as useState22 } from "react";
|
|
4093
|
+
function toSubmitResult(payload) {
|
|
4094
|
+
return {
|
|
4095
|
+
// 'pending' means the play is recorded but awaiting resolution (fixture games)
|
|
4096
|
+
alreadyPlayed: payload.status === "played" || payload.status === "graded" || payload.status === "pending",
|
|
4097
|
+
score: payload.score,
|
|
4098
|
+
isCorrect: payload.isCorrect,
|
|
4099
|
+
clientStateJson: payload.clientStateJson,
|
|
4100
|
+
attemptsUsed: payload.attemptsUsed
|
|
4101
|
+
};
|
|
4102
|
+
}
|
|
4103
|
+
function useGamePlay(conversation, { gameId, gameDay, fixtureId, refresh }) {
|
|
4104
|
+
const [result, setResult] = useState22(null);
|
|
4105
|
+
const [submitting, setSubmitting] = useState22(false);
|
|
4106
|
+
const [rawStatus, setRawStatus] = useState22(null);
|
|
4107
|
+
const inFlightRef = useRef11(false);
|
|
4108
|
+
const convRef = useRef11(conversation);
|
|
4109
|
+
convRef.current = conversation;
|
|
4110
|
+
const optsRef = useRef11({ gameId, gameDay, fixtureId, refresh });
|
|
4111
|
+
optsRef.current = { gameId, gameDay, fixtureId, refresh };
|
|
4112
|
+
const submit = useCallback8(async (answerJson) => {
|
|
4113
|
+
const conv = convRef.current;
|
|
4114
|
+
if (!conv || inFlightRef.current) return;
|
|
4115
|
+
inFlightRef.current = true;
|
|
4116
|
+
setSubmitting(true);
|
|
4117
|
+
try {
|
|
4118
|
+
const opts = optsRef.current;
|
|
4119
|
+
const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId);
|
|
4120
|
+
if (playResult !== null) {
|
|
4121
|
+
setResult(playResult);
|
|
4122
|
+
if (playResult.pointsDelta != null) {
|
|
4123
|
+
opts.refresh?.();
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
} catch {
|
|
4127
|
+
} finally {
|
|
4128
|
+
inFlightRef.current = false;
|
|
4129
|
+
setSubmitting(false);
|
|
4130
|
+
}
|
|
4131
|
+
}, []);
|
|
4132
|
+
const hydrate = useCallback8(() => {
|
|
4133
|
+
const conv = convRef.current;
|
|
4134
|
+
if (!conv) return;
|
|
4135
|
+
const opts = optsRef.current;
|
|
4136
|
+
void (async () => {
|
|
4137
|
+
try {
|
|
4138
|
+
const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay);
|
|
4139
|
+
if (payload !== null) {
|
|
4140
|
+
setResult(toSubmitResult(payload));
|
|
4141
|
+
setRawStatus(payload.status);
|
|
4142
|
+
}
|
|
4143
|
+
} catch {
|
|
4144
|
+
}
|
|
4145
|
+
})();
|
|
4146
|
+
}, []);
|
|
4147
|
+
return { result, submitting, submit, hydrate, rawStatus };
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4150
|
+
// src/components/games/MysteryTigerGame.tsx
|
|
4151
|
+
import { useState as useState23, useId as useId2 } from "react";
|
|
4152
|
+
import { Fragment as Fragment9, jsx as jsx55, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4153
|
+
function parseClientState(json) {
|
|
4154
|
+
if (!json) return null;
|
|
4155
|
+
try {
|
|
4156
|
+
return JSON.parse(json);
|
|
4157
|
+
} catch {
|
|
4158
|
+
return null;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
var ATTR_LABELS = {
|
|
4162
|
+
position: "Pos",
|
|
4163
|
+
nationality: "Nat",
|
|
4164
|
+
age: "Age",
|
|
4165
|
+
shirtNumber: "Kit",
|
|
4166
|
+
apps: "Apps"
|
|
4167
|
+
};
|
|
4168
|
+
var ATTR_KEYS = [
|
|
4169
|
+
"position",
|
|
4170
|
+
"nationality",
|
|
4171
|
+
"age",
|
|
4172
|
+
"shirtNumber",
|
|
4173
|
+
"apps"
|
|
4174
|
+
];
|
|
4175
|
+
function MysteryTigerGame({
|
|
4176
|
+
config,
|
|
4177
|
+
result,
|
|
4178
|
+
submitting,
|
|
4179
|
+
onSubmit
|
|
4180
|
+
}) {
|
|
4181
|
+
const [query, setQuery] = useState23("");
|
|
4182
|
+
const inputId = useId2();
|
|
4183
|
+
const clientState = parseClientState(result?.clientStateJson);
|
|
4184
|
+
const alreadyGuessedIds = new Set(
|
|
4185
|
+
clientState?.guessResults.map((g) => g.playerId) ?? []
|
|
4186
|
+
);
|
|
4187
|
+
const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
|
|
4188
|
+
const filtered = config && !isOver ? config.squadPlayers.filter(
|
|
4189
|
+
(p) => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4190
|
+
) : [];
|
|
4191
|
+
function handleSelect(playerId) {
|
|
4192
|
+
if (!config || isOver || submitting) return;
|
|
4193
|
+
const prevGuesses = clientState?.guessResults.map((g) => g.playerId) ?? [];
|
|
4194
|
+
const newGuesses = [...prevGuesses, playerId];
|
|
4195
|
+
setQuery("");
|
|
4196
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4197
|
+
}
|
|
4198
|
+
return /* @__PURE__ */ jsxs49("div", { className: "ss-w-gt", "data-testid": "game-screen-mystery-tiger", children: [
|
|
4199
|
+
!config && /* @__PURE__ */ jsx55("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4200
|
+
config && /* @__PURE__ */ jsxs49(Fragment9, { children: [
|
|
4201
|
+
isOver && clientState && /* @__PURE__ */ jsxs49("div", { className: `ss-w-gt-banner ss-w-gt-banner--${clientState.solved ? "solved" : "failed"}`, children: [
|
|
4202
|
+
/* @__PURE__ */ jsx55("div", { className: "ss-w-gt-banner-label", children: clientState.solved ? "\u{1F42F} You found them!" : "\u{1F614} Better luck tomorrow" }),
|
|
4203
|
+
clientState.revealedPlayerName && /* @__PURE__ */ jsx55("div", { className: "ss-w-gt-banner-name", children: clientState.revealedPlayerName })
|
|
4204
|
+
] }),
|
|
4205
|
+
!isOver && /* @__PURE__ */ jsxs49("div", { className: "ss-w-gtta", children: [
|
|
4206
|
+
/* @__PURE__ */ jsx55(
|
|
4207
|
+
"input",
|
|
4208
|
+
{
|
|
4209
|
+
id: inputId,
|
|
4210
|
+
type: "text",
|
|
4211
|
+
role: "textbox",
|
|
4212
|
+
className: "ss-w-gtta-i",
|
|
4213
|
+
placeholder: "Search squad players\u2026",
|
|
4214
|
+
value: query,
|
|
4215
|
+
disabled: submitting || isOver,
|
|
4216
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4217
|
+
autoComplete: "off",
|
|
4218
|
+
"aria-label": "Search for a player",
|
|
4219
|
+
"aria-autocomplete": "list"
|
|
4220
|
+
}
|
|
4221
|
+
),
|
|
4222
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ jsx55("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ jsx55(
|
|
4223
|
+
"div",
|
|
4224
|
+
{
|
|
4225
|
+
className: "ss-w-gtta-opt",
|
|
4226
|
+
role: "option",
|
|
4227
|
+
"aria-selected": false,
|
|
4228
|
+
onClick: () => handleSelect(p.id),
|
|
4229
|
+
onKeyDown: (e) => {
|
|
4230
|
+
if (e.key === "Enter") handleSelect(p.id);
|
|
4231
|
+
},
|
|
4232
|
+
tabIndex: 0,
|
|
4233
|
+
children: p.name
|
|
4234
|
+
},
|
|
4235
|
+
p.id
|
|
4236
|
+
)) })
|
|
4237
|
+
] }),
|
|
4238
|
+
clientState && clientState.guessResults.length > 0 && /* @__PURE__ */ jsxs49("div", { children: [
|
|
4239
|
+
/* @__PURE__ */ jsxs49("div", { className: "ss-w-gthdr", children: [
|
|
4240
|
+
/* @__PURE__ */ jsx55("div", { className: "ss-w-gthdr-c ss-w-gthdr-c--name", children: "Player" }),
|
|
4241
|
+
ATTR_KEYS.map((key) => /* @__PURE__ */ jsx55("div", { className: "ss-w-gthdr-c", children: ATTR_LABELS[key] }, key))
|
|
4242
|
+
] }),
|
|
4243
|
+
/* @__PURE__ */ jsx55("div", { className: "ss-w-gtrows", children: clientState.guessResults.map((gr, i) => {
|
|
4244
|
+
const player = config.squadPlayers.find((p) => p.id === gr.playerId);
|
|
4245
|
+
return /* @__PURE__ */ jsxs49("div", { className: "ss-w-gtrow", children: [
|
|
4246
|
+
/* @__PURE__ */ jsx55("div", { className: "ss-w-gtrow-nm", children: player?.name ?? `#${gr.playerId}` }),
|
|
4247
|
+
ATTR_KEYS.map((key) => {
|
|
4248
|
+
const v = gr[key];
|
|
4249
|
+
return /* @__PURE__ */ jsx55(
|
|
4250
|
+
"div",
|
|
4251
|
+
{
|
|
4252
|
+
className: `ss-w-gtile ss-w-gtile--${v.verdict}`,
|
|
4253
|
+
"data-testid": `verdict-${key}-${i}`,
|
|
4254
|
+
"data-verdict": v.verdict,
|
|
4255
|
+
"aria-label": `${ATTR_LABELS[key]}: ${v.verdict}${v.direction ? ` ${v.direction}` : ""}`,
|
|
4256
|
+
children: v.direction && /* @__PURE__ */ jsx55("span", { className: "ss-w-gtile-dir", "aria-hidden": "true", children: v.direction === "up" ? "\u2191" : "\u2193" })
|
|
4257
|
+
},
|
|
4258
|
+
key
|
|
4259
|
+
);
|
|
4260
|
+
})
|
|
4261
|
+
] }, gr.playerId);
|
|
4262
|
+
}) })
|
|
4263
|
+
] }),
|
|
4264
|
+
clientState?.hintLine && !isOver && /* @__PURE__ */ jsx55("div", { className: "ss-w-gt-hint", children: clientState.hintLine }),
|
|
4265
|
+
!isOver && clientState && /* @__PURE__ */ jsxs49("div", { className: "ss-w-gt-hint", children: [
|
|
4266
|
+
clientState.guessesRemaining,
|
|
4267
|
+
" guess",
|
|
4268
|
+
clientState.guessesRemaining !== 1 ? "es" : "",
|
|
4269
|
+
" remaining"
|
|
4270
|
+
] })
|
|
4271
|
+
] })
|
|
4272
|
+
] });
|
|
4273
|
+
}
|
|
4274
|
+
|
|
4275
|
+
// src/components/games/HigherOrLowerGame.tsx
|
|
4276
|
+
import { Fragment as Fragment10, jsx as jsx56, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
4277
|
+
function parseClientState2(json) {
|
|
4278
|
+
if (!json) return null;
|
|
4279
|
+
try {
|
|
4280
|
+
return JSON.parse(json);
|
|
4281
|
+
} catch {
|
|
4282
|
+
return null;
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
function AnsweredRow({
|
|
4286
|
+
answered,
|
|
4287
|
+
pair
|
|
4288
|
+
}) {
|
|
4289
|
+
const cls = `ss-w-hlrrow ss-w-hlrrow--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4290
|
+
const icon = answered.wasCorrect ? "\u2713" : "\u2717";
|
|
4291
|
+
return /* @__PURE__ */ jsxs50("div", { className: cls, children: [
|
|
4292
|
+
/* @__PURE__ */ jsxs50("span", { className: "ss-w-hlrrow-names", children: [
|
|
4293
|
+
pair?.playerAName ?? "?",
|
|
4294
|
+
" vs ",
|
|
4295
|
+
pair?.playerBName ?? "?"
|
|
4296
|
+
] }),
|
|
4297
|
+
/* @__PURE__ */ jsx56("span", { className: "ss-w-hlrrow-pick", children: answered.pick }),
|
|
4298
|
+
/* @__PURE__ */ jsx56("span", { className: "ss-w-hlrrow-icon", children: icon })
|
|
4299
|
+
] });
|
|
4300
|
+
}
|
|
4301
|
+
function HigherOrLowerGame({
|
|
4302
|
+
config,
|
|
4303
|
+
result,
|
|
4304
|
+
submitting,
|
|
4305
|
+
onSubmit
|
|
4306
|
+
}) {
|
|
4307
|
+
const clientState = parseClientState2(result?.clientStateJson);
|
|
4308
|
+
const answeredCount = clientState?.answeredPairs.length ?? 0;
|
|
4309
|
+
const runEndedWrong = clientState?.answeredPairs.some((p) => !p.wasCorrect) ?? false;
|
|
4310
|
+
const allPairsAnswered = config != null && answeredCount >= config.pairs.length;
|
|
4311
|
+
const isOver = result?.alreadyPlayed === true || runEndedWrong || allPairsAnswered;
|
|
4312
|
+
const currentPair = config && !isOver ? config.pairs[answeredCount] ?? null : null;
|
|
4313
|
+
function handlePick(pick) {
|
|
4314
|
+
if (!config || isOver || submitting || !currentPair) return;
|
|
4315
|
+
const prevAnswers = clientState?.answeredPairs.map((p) => ({ pairIndex: p.pairIndex, pick: p.pick })) ?? [];
|
|
4316
|
+
const newAnswers = [...prevAnswers, { pairIndex: currentPair.pairIndex, pick }];
|
|
4317
|
+
onSubmit(JSON.stringify({ answers: newAnswers }));
|
|
4318
|
+
}
|
|
4319
|
+
return /* @__PURE__ */ jsxs50("div", { className: "ss-w-hl", "data-testid": "game-screen-higher-or-lower", children: [
|
|
4320
|
+
!config && /* @__PURE__ */ jsx56("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4321
|
+
config && /* @__PURE__ */ jsxs50(Fragment10, { children: [
|
|
4322
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlctx", children: [
|
|
4323
|
+
/* @__PURE__ */ jsx56("span", { className: "ss-w-hlctx-fam", children: config.statLabel }),
|
|
4324
|
+
/* @__PURE__ */ jsx56("span", { className: "ss-w-hlctx-szn", children: config.seasonLabel })
|
|
4325
|
+
] }),
|
|
4326
|
+
currentPair && /* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpair", children: [
|
|
4327
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpc", children: [
|
|
4328
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-name", children: currentPair.playerAName }),
|
|
4329
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-val", children: currentPair.playerAValue })
|
|
4330
|
+
] }),
|
|
4331
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpc ss-w-hlpc--b", children: [
|
|
4332
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-name", children: currentPair.playerBName }),
|
|
4333
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-val ss-w-hlpc-val--hidden", children: "?" })
|
|
4334
|
+
] })
|
|
4335
|
+
] }),
|
|
4336
|
+
!isOver && currentPair && /* @__PURE__ */ jsxs50("div", { className: "ss-w-hlbtns", children: [
|
|
4337
|
+
/* @__PURE__ */ jsx56(
|
|
4338
|
+
"button",
|
|
4339
|
+
{
|
|
4340
|
+
type: "button",
|
|
4341
|
+
className: "ss-w-hlbtn",
|
|
4342
|
+
disabled: submitting,
|
|
4343
|
+
onClick: () => handlePick("higher"),
|
|
4344
|
+
children: "Higher"
|
|
4345
|
+
}
|
|
4346
|
+
),
|
|
4347
|
+
/* @__PURE__ */ jsx56(
|
|
4348
|
+
"button",
|
|
4349
|
+
{
|
|
4350
|
+
type: "button",
|
|
4351
|
+
className: "ss-w-hlbtn",
|
|
4352
|
+
disabled: submitting,
|
|
4353
|
+
onClick: () => handlePick("lower"),
|
|
4354
|
+
children: "Lower"
|
|
4355
|
+
}
|
|
4356
|
+
)
|
|
4357
|
+
] }),
|
|
4358
|
+
clientState && clientState.answeredPairs.length > 0 && /* @__PURE__ */ jsx56("div", { className: "ss-w-hlresults", children: clientState.answeredPairs.map((answered) => {
|
|
4359
|
+
const pair = config.pairs.find((p) => p.pairIndex === answered.pairIndex);
|
|
4360
|
+
const vCls = `ss-w-hlpc-val ss-w-hlpc-val--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4361
|
+
const badgeCls = `ss-w-hlpc-badge ss-w-hlpc-badge--${answered.wasCorrect ? "correct" : "wrong"}`;
|
|
4362
|
+
return /* @__PURE__ */ jsxs50("div", { className: "ss-w-hlrrow", children: [
|
|
4363
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpair", children: [
|
|
4364
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpc", children: [
|
|
4365
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-name", children: pair?.playerAName ?? "?" }),
|
|
4366
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-val", children: pair?.playerAValue })
|
|
4367
|
+
] }),
|
|
4368
|
+
/* @__PURE__ */ jsxs50("div", { className: "ss-w-hlpc ss-w-hlpc--b", children: [
|
|
4369
|
+
/* @__PURE__ */ jsx56("div", { className: "ss-w-hlpc-name", children: pair?.playerBName ?? "?" }),
|
|
4370
|
+
/* @__PURE__ */ jsx56("div", { className: vCls, children: answered.playerBValue }),
|
|
4371
|
+
/* @__PURE__ */ jsx56("div", { className: badgeCls, children: answered.wasCorrect ? "\u2713" : "\u2717" })
|
|
4372
|
+
] })
|
|
4373
|
+
] }),
|
|
4374
|
+
/* @__PURE__ */ jsx56(AnsweredRow, { answered, pair })
|
|
4375
|
+
] }, answered.pairIndex);
|
|
4376
|
+
}) })
|
|
4377
|
+
] })
|
|
4378
|
+
] });
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
// src/components/games/CareerPathGame.tsx
|
|
4382
|
+
import { useState as useState24, useId as useId3 } from "react";
|
|
4383
|
+
import { Fragment as Fragment11, jsx as jsx57, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
4384
|
+
function parseClientState3(json) {
|
|
4385
|
+
if (!json) return null;
|
|
4386
|
+
try {
|
|
4387
|
+
return JSON.parse(json);
|
|
4388
|
+
} catch {
|
|
4389
|
+
return null;
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
function SpellYear({ spell }) {
|
|
4393
|
+
const parts = [];
|
|
4394
|
+
if (spell.startYear) parts.push(String(spell.startYear));
|
|
4395
|
+
if (spell.endYear) parts.push(String(spell.endYear));
|
|
4396
|
+
if (parts.length === 0) return null;
|
|
4397
|
+
return /* @__PURE__ */ jsx57("span", { className: "ss-w-cpath-spell-yr", children: parts.join(" \u2013 ") });
|
|
4398
|
+
}
|
|
4399
|
+
function ClubSpellCard({ spell }) {
|
|
4400
|
+
return /* @__PURE__ */ jsxs51("div", { className: `ss-w-cpath-club${spell.isLoan ? " ss-w-cpath-club--loan" : ""}`, children: [
|
|
4401
|
+
spell.crestUrl ? /* @__PURE__ */ jsx57(
|
|
4402
|
+
"img",
|
|
4403
|
+
{
|
|
4404
|
+
src: spell.crestUrl,
|
|
4405
|
+
alt: spell.clubName,
|
|
4406
|
+
className: "ss-w-cpath-crest",
|
|
4407
|
+
loading: "lazy"
|
|
4408
|
+
}
|
|
4409
|
+
) : /* @__PURE__ */ jsx57("div", { className: "ss-w-cpath-crest ss-w-cpath-crest--fallback", "aria-hidden": "true" }),
|
|
4410
|
+
/* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath-club-info", children: [
|
|
4411
|
+
/* @__PURE__ */ jsx57("span", { className: "ss-w-cpath-club-name", children: spell.clubName }),
|
|
4412
|
+
/* @__PURE__ */ jsx57(SpellYear, { spell }),
|
|
4413
|
+
spell.isLoan && /* @__PURE__ */ jsx57("span", { className: "ss-w-cpath-loan-badge", children: "Loan" })
|
|
4414
|
+
] })
|
|
4415
|
+
] });
|
|
4416
|
+
}
|
|
4417
|
+
function CareerPathGame({
|
|
4418
|
+
config,
|
|
4419
|
+
result,
|
|
4420
|
+
submitting,
|
|
4421
|
+
onSubmit
|
|
4422
|
+
}) {
|
|
4423
|
+
const [query, setQuery] = useState24("");
|
|
4424
|
+
const inputId = useId3();
|
|
4425
|
+
const clientState = parseClientState3(result?.clientStateJson);
|
|
4426
|
+
const alreadyGuessedIds = new Set(
|
|
4427
|
+
clientState?.guessResults.map((g) => g.playerId) ?? []
|
|
4428
|
+
);
|
|
4429
|
+
const isOver = result?.alreadyPlayed === true || clientState?.solved === true || clientState?.failed === true;
|
|
4430
|
+
const visiblePath = clientState?.visiblePath ?? config?.initialPath ?? [];
|
|
4431
|
+
const filtered = config && !isOver ? config.typeaheadPool.filter(
|
|
4432
|
+
(p) => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4433
|
+
) : [];
|
|
4434
|
+
function handleSelect(playerId) {
|
|
4435
|
+
if (!config || isOver || submitting) return;
|
|
4436
|
+
const prevGuesses = clientState?.guessResults.map((g) => g.playerId) ?? [];
|
|
4437
|
+
const newGuesses = [...prevGuesses, playerId];
|
|
4438
|
+
setQuery("");
|
|
4439
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4440
|
+
}
|
|
4441
|
+
return /* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath", "data-testid": "game-screen-career-path", children: [
|
|
4442
|
+
!config && /* @__PURE__ */ jsx57("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4443
|
+
config && /* @__PURE__ */ jsxs51(Fragment11, { children: [
|
|
4444
|
+
/* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath-ctx", children: [
|
|
4445
|
+
/* @__PURE__ */ jsx57("span", { className: "ss-w-cpath-ctx-label", children: "Career clubs" }),
|
|
4446
|
+
/* @__PURE__ */ jsxs51("span", { className: "ss-w-cpath-ctx-count", children: [
|
|
4447
|
+
config.totalClubs,
|
|
4448
|
+
" clubs total"
|
|
4449
|
+
] })
|
|
4450
|
+
] }),
|
|
4451
|
+
/* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath-path", children: [
|
|
4452
|
+
visiblePath.map((spell, i) => /* @__PURE__ */ jsx57(ClubSpellCard, { spell }, `${spell.clubName}-${i}`)),
|
|
4453
|
+
(clientState?.totalClubs ?? config.totalClubs) > visiblePath.length && /* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath-hidden", children: [
|
|
4454
|
+
"+",
|
|
4455
|
+
(clientState?.totalClubs ?? config.totalClubs) - visiblePath.length,
|
|
4456
|
+
" more clubs hidden"
|
|
4457
|
+
] })
|
|
4458
|
+
] }),
|
|
4459
|
+
isOver && clientState && /* @__PURE__ */ jsxs51("div", { className: `ss-w-cpath-banner ss-w-cpath-banner--${clientState.solved ? "solved" : "failed"}`, children: [
|
|
4460
|
+
/* @__PURE__ */ jsx57("div", { className: "ss-w-cpath-banner-label", children: clientState.solved ? "Career traced!" : "Better luck tomorrow" }),
|
|
4461
|
+
clientState.revealedPlayerName && /* @__PURE__ */ jsx57("div", { className: "ss-w-cpath-banner-name", children: clientState.revealedPlayerName })
|
|
4462
|
+
] }),
|
|
4463
|
+
!isOver && /* @__PURE__ */ jsxs51("div", { className: "ss-w-gtta", children: [
|
|
4464
|
+
/* @__PURE__ */ jsx57(
|
|
4465
|
+
"input",
|
|
4466
|
+
{
|
|
4467
|
+
id: inputId,
|
|
4468
|
+
type: "text",
|
|
4469
|
+
role: "textbox",
|
|
4470
|
+
className: "ss-w-gtta-i",
|
|
4471
|
+
placeholder: "Search players\u2026",
|
|
4472
|
+
value: query,
|
|
4473
|
+
disabled: submitting || isOver,
|
|
4474
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4475
|
+
autoComplete: "off",
|
|
4476
|
+
"aria-label": "Search for a player",
|
|
4477
|
+
"aria-autocomplete": "list"
|
|
4478
|
+
}
|
|
4479
|
+
),
|
|
4480
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ jsx57("div", { className: "ss-w-gtta-drop", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ jsx57(
|
|
4481
|
+
"div",
|
|
4482
|
+
{
|
|
4483
|
+
className: "ss-w-gtta-opt",
|
|
4484
|
+
role: "option",
|
|
4485
|
+
"aria-selected": false,
|
|
4486
|
+
onClick: () => handleSelect(p.id),
|
|
4487
|
+
onKeyDown: (e) => {
|
|
4488
|
+
if (e.key === "Enter") handleSelect(p.id);
|
|
4489
|
+
},
|
|
4490
|
+
tabIndex: 0,
|
|
4491
|
+
children: p.name
|
|
4492
|
+
},
|
|
4493
|
+
p.id
|
|
4494
|
+
)) })
|
|
4495
|
+
] }),
|
|
4496
|
+
clientState?.hintLine && !isOver && /* @__PURE__ */ jsx57("div", { className: "ss-w-cpath-hint", children: clientState.hintLine }),
|
|
4497
|
+
!isOver && clientState && /* @__PURE__ */ jsxs51("div", { className: "ss-w-cpath-hint", children: [
|
|
4498
|
+
clientState.guessesRemaining,
|
|
4499
|
+
" guess",
|
|
4500
|
+
clientState.guessesRemaining !== 1 ? "es" : "",
|
|
4501
|
+
" remaining"
|
|
4502
|
+
] })
|
|
4503
|
+
] })
|
|
4504
|
+
] });
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
// src/components/games/BeatTheGridGame.tsx
|
|
4508
|
+
import React, { useState as useState25, useId as useId4 } from "react";
|
|
4509
|
+
import { Fragment as Fragment12, jsx as jsx58, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
4510
|
+
function parseClientState4(json) {
|
|
4511
|
+
if (!json) return null;
|
|
4512
|
+
try {
|
|
4513
|
+
return JSON.parse(json);
|
|
4514
|
+
} catch {
|
|
4515
|
+
return null;
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4518
|
+
function findCellResult(cells, row, col) {
|
|
4519
|
+
return cells.find((c) => c.row === row && c.col === col);
|
|
4520
|
+
}
|
|
4521
|
+
function SearchSheet({
|
|
4522
|
+
row,
|
|
4523
|
+
col,
|
|
4524
|
+
rowLabel,
|
|
4525
|
+
colLabel,
|
|
4526
|
+
playerPool,
|
|
4527
|
+
alreadyFilledIds,
|
|
4528
|
+
onPick,
|
|
4529
|
+
onDismiss
|
|
4530
|
+
}) {
|
|
4531
|
+
const [query, setQuery] = useState25("");
|
|
4532
|
+
const inputId = useId4();
|
|
4533
|
+
const filtered = playerPool.filter(
|
|
4534
|
+
(p) => !alreadyFilledIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase())
|
|
4535
|
+
);
|
|
4536
|
+
return /* @__PURE__ */ jsxs52("div", { className: "ss-w-btg-sheet", "data-testid": "btg-search-sheet", children: [
|
|
4537
|
+
/* @__PURE__ */ jsxs52("div", { className: "ss-w-btg-sheet-hdr", children: [
|
|
4538
|
+
/* @__PURE__ */ jsxs52("div", { className: "ss-w-btg-sheet-ctx", children: [
|
|
4539
|
+
/* @__PURE__ */ jsx58("span", { className: "ss-w-btg-sheet-row", children: rowLabel }),
|
|
4540
|
+
/* @__PURE__ */ jsx58("span", { className: "ss-w-btg-sheet-sep", children: "\xD7" }),
|
|
4541
|
+
/* @__PURE__ */ jsx58("span", { className: "ss-w-btg-sheet-col", children: colLabel })
|
|
4542
|
+
] }),
|
|
4543
|
+
/* @__PURE__ */ jsx58(
|
|
4544
|
+
"button",
|
|
4545
|
+
{
|
|
4546
|
+
type: "button",
|
|
4547
|
+
className: "ss-w-btg-sheet-close",
|
|
4548
|
+
"data-testid": "btg-sheet-dismiss",
|
|
4549
|
+
"aria-label": "Dismiss",
|
|
4550
|
+
onClick: onDismiss,
|
|
4551
|
+
children: "\u2715"
|
|
4552
|
+
}
|
|
4553
|
+
)
|
|
4554
|
+
] }),
|
|
4555
|
+
/* @__PURE__ */ jsxs52("div", { className: "ss-w-gtta", children: [
|
|
4556
|
+
/* @__PURE__ */ jsx58(
|
|
4557
|
+
"input",
|
|
4558
|
+
{
|
|
4559
|
+
id: inputId,
|
|
4560
|
+
type: "text",
|
|
4561
|
+
role: "textbox",
|
|
4562
|
+
className: "ss-w-gtta-i",
|
|
4563
|
+
placeholder: "Search players\u2026",
|
|
4564
|
+
value: query,
|
|
4565
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4566
|
+
autoComplete: "off",
|
|
4567
|
+
"aria-label": `Search player for ${rowLabel} \xD7 ${colLabel}`,
|
|
4568
|
+
"aria-autocomplete": "list",
|
|
4569
|
+
autoFocus: true
|
|
4570
|
+
}
|
|
4571
|
+
),
|
|
4572
|
+
query.length > 0 && filtered.length > 0 && /* @__PURE__ */ jsx58("div", { className: "ss-w-gtta-drop ss-w-btg-ta-list", role: "listbox", children: filtered.map((p) => /* @__PURE__ */ jsx58(
|
|
4573
|
+
"div",
|
|
4574
|
+
{
|
|
4575
|
+
className: "ss-w-gtta-opt",
|
|
4576
|
+
role: "option",
|
|
4577
|
+
"aria-selected": false,
|
|
4578
|
+
onClick: () => onPick(row, col, p.id),
|
|
4579
|
+
onKeyDown: (e) => {
|
|
4580
|
+
if (e.key === "Enter") onPick(row, col, p.id);
|
|
4581
|
+
},
|
|
4582
|
+
tabIndex: 0,
|
|
4583
|
+
children: p.name
|
|
4584
|
+
},
|
|
4585
|
+
p.id
|
|
4586
|
+
)) })
|
|
4587
|
+
] })
|
|
4588
|
+
] });
|
|
4589
|
+
}
|
|
4590
|
+
function BeatTheGridGame({
|
|
4591
|
+
config,
|
|
4592
|
+
result,
|
|
4593
|
+
submitting,
|
|
4594
|
+
onSubmit,
|
|
4595
|
+
playerPool
|
|
4596
|
+
}) {
|
|
4597
|
+
const [activeCell, setActiveCell] = useState25(null);
|
|
4598
|
+
const clientState = parseClientState4(result?.clientStateJson);
|
|
4599
|
+
const filledCells = clientState?.cells ?? [];
|
|
4600
|
+
const isLocked2 = result?.alreadyPlayed === true || clientState?.isComplete === true;
|
|
4601
|
+
const alreadyFilledIds = new Set(filledCells.map((c) => c.playerId));
|
|
4602
|
+
function handleCellClick(row, col) {
|
|
4603
|
+
if (isLocked2 || submitting) return;
|
|
4604
|
+
const alreadyFilled = findCellResult(filledCells, row, col);
|
|
4605
|
+
if (alreadyFilled) return;
|
|
4606
|
+
setActiveCell({ row, col });
|
|
4607
|
+
}
|
|
4608
|
+
function handlePick(row, col, playerId) {
|
|
4609
|
+
setActiveCell(null);
|
|
4610
|
+
const prevCells = filledCells.map((c) => ({ row: c.row, col: c.col, playerId: c.playerId }));
|
|
4611
|
+
const newCells = [...prevCells, { row, col, playerId }];
|
|
4612
|
+
onSubmit(JSON.stringify({ cells: newCells }));
|
|
4613
|
+
}
|
|
4614
|
+
if (!config) {
|
|
4615
|
+
return /* @__PURE__ */ jsx58("div", { className: "ss-w-btg", "data-testid": "game-screen-beat-the-grid", children: /* @__PURE__ */ jsx58("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
4616
|
+
}
|
|
4617
|
+
const rows = config.rows;
|
|
4618
|
+
const cols = config.cols;
|
|
4619
|
+
return /* @__PURE__ */ jsxs52("div", { className: "ss-w-btg", "data-testid": "game-screen-beat-the-grid", children: [
|
|
4620
|
+
/* @__PURE__ */ jsxs52("div", { className: "ss-w-btg-ctx", children: [
|
|
4621
|
+
/* @__PURE__ */ jsxs52("span", { className: "ss-w-btg-ctx-score", children: [
|
|
4622
|
+
"Score: ",
|
|
4623
|
+
clientState?.totalScore ?? 0
|
|
4624
|
+
] }),
|
|
4625
|
+
!isLocked2 && /* @__PURE__ */ jsxs52("span", { className: "ss-w-btg-ctx-left", children: [
|
|
4626
|
+
config.maxGuesses - filledCells.length,
|
|
4627
|
+
" cell",
|
|
4628
|
+
config.maxGuesses - filledCells.length !== 1 ? "s" : "",
|
|
4629
|
+
" left"
|
|
4630
|
+
] }),
|
|
4631
|
+
isLocked2 && /* @__PURE__ */ jsx58("span", { className: "ss-w-btg-ctx-done", children: "Complete" })
|
|
4632
|
+
] }),
|
|
4633
|
+
/* @__PURE__ */ jsxs52(
|
|
4634
|
+
"div",
|
|
4635
|
+
{
|
|
4636
|
+
className: "ss-w-btg-grid",
|
|
4637
|
+
style: { gridTemplateColumns: `auto repeat(${cols.length}, 1fr)` },
|
|
4638
|
+
role: "grid",
|
|
4639
|
+
children: [
|
|
4640
|
+
/* @__PURE__ */ jsx58("div", { className: "ss-w-btg-gc ss-w-btg-gc--corner" }),
|
|
4641
|
+
cols.map((col) => /* @__PURE__ */ jsx58("div", { className: "ss-w-btg-gc ss-w-btg-gc--colhdr", children: col }, col)),
|
|
4642
|
+
rows.map((rowLabel, rowIdx) => /* @__PURE__ */ jsxs52(React.Fragment, { children: [
|
|
4643
|
+
/* @__PURE__ */ jsx58("div", { className: "ss-w-btg-gc ss-w-btg-gc--rowhdr", children: rowLabel }),
|
|
4644
|
+
cols.map((colLabel, colIdx) => {
|
|
4645
|
+
const filled = findCellResult(filledCells, rowIdx, colIdx);
|
|
4646
|
+
const isActive = activeCell?.row === rowIdx && activeCell?.col === colIdx;
|
|
4647
|
+
return /* @__PURE__ */ jsx58(
|
|
4648
|
+
"button",
|
|
4649
|
+
{
|
|
4650
|
+
type: "button",
|
|
4651
|
+
"data-testid": `btg-cell-${rowIdx}-${colIdx}`,
|
|
4652
|
+
"aria-label": `${rowLabel} ${colLabel}`,
|
|
4653
|
+
className: [
|
|
4654
|
+
"ss-w-btg-gc ss-w-btg-cell",
|
|
4655
|
+
filled ? filled.isCorrect ? "ss-w-btg-cell--correct" : "ss-w-btg-cell--wrong" : "",
|
|
4656
|
+
isActive ? "ss-w-btg-cell--active" : ""
|
|
4657
|
+
].filter(Boolean).join(" "),
|
|
4658
|
+
disabled: isLocked2 || submitting,
|
|
4659
|
+
onClick: () => handleCellClick(rowIdx, colIdx),
|
|
4660
|
+
children: filled ? /* @__PURE__ */ jsxs52(Fragment12, { children: [
|
|
4661
|
+
/* @__PURE__ */ jsx58("span", { className: "ss-w-btg-cell-score", children: filled.rarityScore }),
|
|
4662
|
+
filled.isCorrect && /* @__PURE__ */ jsx58("span", { className: "ss-w-btg-cell-check", "aria-hidden": "true", children: "\u2713" })
|
|
4663
|
+
] }) : /* @__PURE__ */ jsx58("span", { className: "ss-w-btg-cell-empty", "aria-hidden": "true", children: "+" })
|
|
4664
|
+
},
|
|
4665
|
+
`cell-${rowIdx}-${colIdx}`
|
|
4666
|
+
);
|
|
4667
|
+
})
|
|
4668
|
+
] }, rowIdx))
|
|
4669
|
+
]
|
|
4670
|
+
}
|
|
4671
|
+
),
|
|
4672
|
+
activeCell !== null && /* @__PURE__ */ jsx58(
|
|
4673
|
+
SearchSheet,
|
|
4674
|
+
{
|
|
4675
|
+
row: activeCell.row,
|
|
4676
|
+
col: activeCell.col,
|
|
4677
|
+
rowLabel: rows[activeCell.row] ?? "",
|
|
4678
|
+
colLabel: cols[activeCell.col] ?? "",
|
|
4679
|
+
playerPool,
|
|
4680
|
+
alreadyFilledIds,
|
|
4681
|
+
onPick: handlePick,
|
|
4682
|
+
onDismiss: () => setActiveCell(null)
|
|
4683
|
+
}
|
|
4684
|
+
)
|
|
4685
|
+
] });
|
|
4686
|
+
}
|
|
4687
|
+
|
|
4688
|
+
// src/components/games/GuessTheXiGame.tsx
|
|
4689
|
+
import { Fragment as Fragment13, jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
4690
|
+
function parseClientState5(json) {
|
|
4691
|
+
if (!json) return null;
|
|
4692
|
+
try {
|
|
4693
|
+
return JSON.parse(json);
|
|
4694
|
+
} catch {
|
|
4695
|
+
return null;
|
|
4696
|
+
}
|
|
4697
|
+
}
|
|
4698
|
+
function RevealCard({ reveal }) {
|
|
4699
|
+
return /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-reveal", "data-reveal-type": reveal.type ?? "", children: [
|
|
4700
|
+
reveal.slot && /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-reveal-slot", children: reveal.slot }),
|
|
4701
|
+
/* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-reveal-val", children: reveal.value })
|
|
4702
|
+
] });
|
|
4703
|
+
}
|
|
4704
|
+
function GuessTheXiGame({
|
|
4705
|
+
config,
|
|
4706
|
+
result,
|
|
4707
|
+
submitting,
|
|
4708
|
+
onSubmit
|
|
4709
|
+
}) {
|
|
4710
|
+
const clientState = parseClientState5(result?.clientStateJson);
|
|
4711
|
+
const isOver = result?.alreadyPlayed === true || clientState?.status === "solved" || clientState?.status === "failed";
|
|
4712
|
+
function handlePick(teamId) {
|
|
4713
|
+
if (!config || isOver || submitting) return;
|
|
4714
|
+
const prevGuesses = clientState?.guessHistory.map((g) => ({ teamId: g.teamId })) ?? [];
|
|
4715
|
+
const newGuesses = [...prevGuesses, { teamId }];
|
|
4716
|
+
onSubmit(JSON.stringify({ guesses: newGuesses }));
|
|
4717
|
+
}
|
|
4718
|
+
return /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi", "data-testid": "game-screen-guess-the-xi", children: [
|
|
4719
|
+
!config && /* @__PURE__ */ jsx59("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4720
|
+
config && /* @__PURE__ */ jsxs53(Fragment13, { children: [
|
|
4721
|
+
/* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-ctx", children: /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-ctx-label", children: config.poolLabel }) }),
|
|
4722
|
+
config.positions.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-pitch", children: config.positions.map((pos) => /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-pslot", children: [
|
|
4723
|
+
/* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-pslot-pos", children: pos.slot }),
|
|
4724
|
+
/* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-pslot-nat", children: pos.nationality })
|
|
4725
|
+
] }, pos.slot)) }),
|
|
4726
|
+
clientState && clientState.earnedReveals.length > 0 && /* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-reveals", children: clientState.earnedReveals.map((r, i) => /* @__PURE__ */ jsx59(RevealCard, { reveal: r }, i)) }),
|
|
4727
|
+
isOver && clientState && /* @__PURE__ */ jsx59("div", { className: `ss-w-gxi-banner ss-w-gxi-banner--${clientState.status}`, children: /* @__PURE__ */ jsx59("span", { className: "ss-w-gxi-banner-label", children: clientState.status === "solved" ? `Solved! ${clientState.score} pts` : "Better luck tomorrow" }) }),
|
|
4728
|
+
/* @__PURE__ */ jsx59("div", { className: "ss-w-gxi-pool", children: config.teamPool.map((team) => {
|
|
4729
|
+
const guessRecord = clientState?.guessHistory.find((g) => g.teamId === team.teamId);
|
|
4730
|
+
return /* @__PURE__ */ jsx59(
|
|
4731
|
+
"button",
|
|
4732
|
+
{
|
|
4733
|
+
type: "button",
|
|
4734
|
+
className: [
|
|
4735
|
+
"ss-w-gxi-team-btn",
|
|
4736
|
+
guessRecord ? guessRecord.wasCorrect ? "ss-w-gxi-team-btn--correct" : "ss-w-gxi-team-btn--wrong" : ""
|
|
4737
|
+
].filter(Boolean).join(" "),
|
|
4738
|
+
disabled: isOver || submitting,
|
|
4739
|
+
onClick: () => handlePick(team.teamId),
|
|
4740
|
+
children: team.teamName
|
|
4741
|
+
},
|
|
4742
|
+
team.teamId
|
|
4743
|
+
);
|
|
4744
|
+
}) }),
|
|
4745
|
+
!isOver && clientState && /* @__PURE__ */ jsxs53("div", { className: "ss-w-gxi-hint", children: [
|
|
4746
|
+
"Guess ",
|
|
4747
|
+
clientState.guessesUsed + 1,
|
|
4748
|
+
" of 6"
|
|
4749
|
+
] })
|
|
4750
|
+
] })
|
|
4751
|
+
] });
|
|
4752
|
+
}
|
|
4753
|
+
|
|
4754
|
+
// src/components/games/DailyQuizGame.tsx
|
|
4755
|
+
import { useState as useState26 } from "react";
|
|
4756
|
+
import { Fragment as Fragment14, jsx as jsx60, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
4757
|
+
function parseClientState6(json) {
|
|
4758
|
+
if (!json) return null;
|
|
4759
|
+
try {
|
|
4760
|
+
return JSON.parse(json);
|
|
4761
|
+
} catch {
|
|
4762
|
+
return null;
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
function findResult(results, index) {
|
|
4766
|
+
return results.find((r) => r.index === index);
|
|
4767
|
+
}
|
|
4768
|
+
function DailyQuizGame({
|
|
4769
|
+
config,
|
|
4770
|
+
result,
|
|
4771
|
+
submitting,
|
|
4772
|
+
onSubmit
|
|
4773
|
+
}) {
|
|
4774
|
+
const [selections, setSelections] = useState26(/* @__PURE__ */ new Map());
|
|
4775
|
+
const clientState = parseClientState6(result?.clientStateJson);
|
|
4776
|
+
const isRevealed = (clientState?.results.length ?? 0) > 0 || result?.alreadyPlayed === true;
|
|
4777
|
+
const allAnswered = config != null && selections.size === config.questions.length;
|
|
4778
|
+
function handleSelect(questionIndex, optionIndex) {
|
|
4779
|
+
if (isRevealed || submitting) return;
|
|
4780
|
+
setSelections((prev) => new Map(prev).set(questionIndex, optionIndex));
|
|
4781
|
+
}
|
|
4782
|
+
function handleSubmit() {
|
|
4783
|
+
if (!config || !allAnswered || isRevealed || submitting) return;
|
|
4784
|
+
const answers = config.questions.map((q) => ({
|
|
4785
|
+
index: q.index,
|
|
4786
|
+
selectedOptionIndex: selections.get(q.index) ?? 0
|
|
4787
|
+
}));
|
|
4788
|
+
onSubmit(JSON.stringify({ answers }));
|
|
4789
|
+
}
|
|
4790
|
+
return /* @__PURE__ */ jsxs54("div", { className: "ss-w-dq", "data-testid": "game-screen-daily-quiz", children: [
|
|
4791
|
+
!config && /* @__PURE__ */ jsx60("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }),
|
|
4792
|
+
config && /* @__PURE__ */ jsxs54(Fragment14, { children: [
|
|
4793
|
+
isRevealed && result?.score != null && /* @__PURE__ */ jsxs54("div", { className: "ss-w-dq-score", children: [
|
|
4794
|
+
/* @__PURE__ */ jsx60("span", { className: "ss-w-dq-score-val", children: result.score }),
|
|
4795
|
+
/* @__PURE__ */ jsx60("span", { className: "ss-w-dq-score-label", children: "pts" })
|
|
4796
|
+
] }),
|
|
4797
|
+
!isRevealed && /* @__PURE__ */ jsx60("div", { className: "ss-w-dq-prog", children: /* @__PURE__ */ jsx60(
|
|
4798
|
+
"div",
|
|
4799
|
+
{
|
|
4800
|
+
className: "ss-w-dq-prog-fill",
|
|
4801
|
+
style: { width: `${Math.round(selections.size / config.questions.length * 100)}%` }
|
|
4802
|
+
}
|
|
4803
|
+
) }),
|
|
4804
|
+
/* @__PURE__ */ jsx60("div", { className: "ss-w-dq-questions", children: config.questions.map((q) => {
|
|
4805
|
+
const qResult = clientState ? findResult(clientState.results, q.index) : void 0;
|
|
4806
|
+
const selectedIdx = selections.get(q.index);
|
|
4807
|
+
return /* @__PURE__ */ jsxs54("div", { className: "ss-w-dq-q", children: [
|
|
4808
|
+
/* @__PURE__ */ jsx60("div", { className: "ss-w-dq-qstem", children: q.stem }),
|
|
4809
|
+
/* @__PURE__ */ jsx60("div", { className: "ss-w-dq-opts", children: q.options.map((opt, optIdx) => {
|
|
4810
|
+
let optCls = "ss-w-dq-qopt";
|
|
4811
|
+
if (qResult) {
|
|
4812
|
+
if (optIdx === qResult.correctOptionIndex) {
|
|
4813
|
+
optCls += " ss-w-dq-qopt--correct";
|
|
4814
|
+
} else if (optIdx === selectedIdx && !qResult.isCorrect) {
|
|
4815
|
+
optCls += " ss-w-dq-qopt--wrong";
|
|
4816
|
+
}
|
|
4817
|
+
} else if (optIdx === selectedIdx) {
|
|
4818
|
+
optCls += " ss-w-dq-qopt--selected";
|
|
4819
|
+
}
|
|
4820
|
+
return /* @__PURE__ */ jsxs54(
|
|
4821
|
+
"button",
|
|
4822
|
+
{
|
|
4823
|
+
type: "button",
|
|
4824
|
+
className: optCls,
|
|
4825
|
+
disabled: isRevealed || submitting,
|
|
4826
|
+
onClick: () => handleSelect(q.index, optIdx),
|
|
4827
|
+
children: [
|
|
4828
|
+
/* @__PURE__ */ jsx60("span", { className: "ss-w-dq-qopt-letter", children: String.fromCharCode(65 + optIdx) }),
|
|
4829
|
+
/* @__PURE__ */ jsx60("span", { className: "ss-w-dq-qopt-text", children: opt })
|
|
4830
|
+
]
|
|
4831
|
+
},
|
|
4832
|
+
optIdx
|
|
4833
|
+
);
|
|
4834
|
+
}) }),
|
|
4835
|
+
qResult?.revealText && /* @__PURE__ */ jsx60("div", { className: `ss-w-dq-qwhy ss-w-dq-qwhy--${qResult.isCorrect ? "correct" : "wrong"}`, children: qResult.revealText })
|
|
4836
|
+
] }, q.index);
|
|
4837
|
+
}) }),
|
|
4838
|
+
!isRevealed && /* @__PURE__ */ jsx60(
|
|
4839
|
+
"button",
|
|
4840
|
+
{
|
|
4841
|
+
type: "button",
|
|
4842
|
+
className: "ss-w-dq-submit",
|
|
4843
|
+
disabled: !allAnswered || submitting,
|
|
4844
|
+
onClick: handleSubmit,
|
|
4845
|
+
"aria-label": "Submit answers",
|
|
4846
|
+
children: submitting ? "Submitting\u2026" : "Submit"
|
|
4847
|
+
}
|
|
4848
|
+
)
|
|
4849
|
+
] })
|
|
4850
|
+
] });
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4853
|
+
// src/components/games/MatchdayPredictorGame.tsx
|
|
4854
|
+
import { useState as useState27 } from "react";
|
|
4855
|
+
import { jsx as jsx61, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
4856
|
+
function parseClientState7(json) {
|
|
4857
|
+
if (!json) return null;
|
|
4858
|
+
try {
|
|
4859
|
+
return JSON.parse(json);
|
|
4860
|
+
} catch {
|
|
4861
|
+
return null;
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
function isLocked(kickoffUtc) {
|
|
4865
|
+
try {
|
|
4866
|
+
return new Date(kickoffUtc).getTime() <= Date.now();
|
|
4867
|
+
} catch {
|
|
4868
|
+
return true;
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
function MatchdayPredictorGame({
|
|
4872
|
+
config,
|
|
4873
|
+
result,
|
|
4874
|
+
submitting,
|
|
4875
|
+
onSubmit
|
|
4876
|
+
}) {
|
|
4877
|
+
const [homeScore, setHomeScore] = useState27(0);
|
|
4878
|
+
const [awayScore, setAwayScore] = useState27(0);
|
|
4879
|
+
const [firstScorerPlayerId, setFirstScorerPlayerId] = useState27(null);
|
|
4880
|
+
const clientState = parseClientState7(result?.clientStateJson);
|
|
4881
|
+
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
4882
|
+
if (alreadyPlayed && clientState) {
|
|
4883
|
+
if (!clientState.graded) {
|
|
4884
|
+
return /* @__PURE__ */ jsxs55("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4885
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-live", children: [
|
|
4886
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-live-score", children: [
|
|
4887
|
+
clientState.predictedHomeScore,
|
|
4888
|
+
" \u2013 ",
|
|
4889
|
+
clientState.predictedAwayScore
|
|
4890
|
+
] }),
|
|
4891
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-live-label", children: "Locked in \u2014 awaiting result" })
|
|
4892
|
+
] }),
|
|
4893
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
4894
|
+
] });
|
|
4895
|
+
}
|
|
4896
|
+
const r = clientState.result;
|
|
4897
|
+
const actualScore = `${r.homeScore} \u2013 ${r.awayScore}`;
|
|
4898
|
+
return /* @__PURE__ */ jsxs55("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4899
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-live", children: [
|
|
4900
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-live-score", children: actualScore }),
|
|
4901
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-live-label", children: "Full-time result" }),
|
|
4902
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-live-outcome", children: [
|
|
4903
|
+
/* @__PURE__ */ jsxs55("div", { className: `ss-w-mp-live-row${clientState.exactScoreCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4904
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-live-row-key", children: "Exact score" }),
|
|
4905
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-live-row-val", children: clientState.exactScoreCorrect ? "\u2713" : "\u2717" })
|
|
4906
|
+
] }),
|
|
4907
|
+
/* @__PURE__ */ jsxs55("div", { className: `ss-w-mp-live-row${clientState.outcomeCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4908
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-live-row-key", children: "Result (W/D/L)" }),
|
|
4909
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-live-row-val", children: clientState.outcomeCorrect ? "\u2713" : "\u2717" })
|
|
4910
|
+
] }),
|
|
4911
|
+
!clientState.firstScorerVoid && /* @__PURE__ */ jsxs55("div", { className: `ss-w-mp-live-row${clientState.firstScorerCorrect ? " ss-w-mp-live-row--correct" : ""}`, children: [
|
|
4912
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-live-row-key", children: "First scorer" }),
|
|
4913
|
+
/* @__PURE__ */ jsxs55("span", { className: "ss-w-mp-live-row-val", children: [
|
|
4914
|
+
clientState.firstScorerCorrect ? "\u2713" : "\u2717",
|
|
4915
|
+
r.firstScorerName ? ` ${r.firstScorerName}` : ""
|
|
4916
|
+
] })
|
|
4917
|
+
] })
|
|
4918
|
+
] })
|
|
4919
|
+
] }),
|
|
4920
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
4921
|
+
] });
|
|
4922
|
+
}
|
|
4923
|
+
if (!config) {
|
|
4924
|
+
return /* @__PURE__ */ jsx61("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: /* @__PURE__ */ jsx61("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
4925
|
+
}
|
|
4926
|
+
const locked = isLocked(config.kickoffUtc);
|
|
4927
|
+
const disabled = locked || submitting;
|
|
4928
|
+
function handleSubmit() {
|
|
4929
|
+
if (disabled || !config) return;
|
|
4930
|
+
onSubmit(
|
|
4931
|
+
JSON.stringify({
|
|
4932
|
+
homeScore,
|
|
4933
|
+
awayScore,
|
|
4934
|
+
...firstScorerPlayerId !== null ? { firstScorerPlayerId } : {}
|
|
4935
|
+
})
|
|
4936
|
+
);
|
|
4937
|
+
}
|
|
4938
|
+
return /* @__PURE__ */ jsxs55("div", { className: "ss-w-mp", "data-testid": "game-screen-matchday-predictor", children: [
|
|
4939
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-pred-score", children: [
|
|
4940
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-team", children: [
|
|
4941
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-team-name", children: config.homeTeam.name }),
|
|
4942
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-stepper", children: [
|
|
4943
|
+
/* @__PURE__ */ jsx61(
|
|
4944
|
+
"button",
|
|
4945
|
+
{
|
|
4946
|
+
type: "button",
|
|
4947
|
+
className: "ss-w-mp-stepper-btn",
|
|
4948
|
+
"aria-label": "-",
|
|
4949
|
+
disabled: disabled || homeScore <= 0,
|
|
4950
|
+
onClick: () => setHomeScore((s) => Math.max(0, s - 1)),
|
|
4951
|
+
children: "\u2212"
|
|
4952
|
+
}
|
|
4953
|
+
),
|
|
4954
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-stepper-val", children: homeScore }),
|
|
4955
|
+
/* @__PURE__ */ jsx61(
|
|
4956
|
+
"button",
|
|
4957
|
+
{
|
|
4958
|
+
type: "button",
|
|
4959
|
+
className: "ss-w-mp-stepper-btn",
|
|
4960
|
+
"aria-label": "+",
|
|
4961
|
+
disabled,
|
|
4962
|
+
onClick: () => setHomeScore((s) => s + 1),
|
|
4963
|
+
children: "+"
|
|
4964
|
+
}
|
|
4965
|
+
)
|
|
4966
|
+
] })
|
|
4967
|
+
] }),
|
|
4968
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-sep", children: "\u2013" }),
|
|
4969
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-team", children: [
|
|
4970
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-team-name", children: config.awayTeam.name }),
|
|
4971
|
+
/* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-stepper", children: [
|
|
4972
|
+
/* @__PURE__ */ jsx61(
|
|
4973
|
+
"button",
|
|
4974
|
+
{
|
|
4975
|
+
type: "button",
|
|
4976
|
+
className: "ss-w-mp-stepper-btn",
|
|
4977
|
+
"aria-label": "-",
|
|
4978
|
+
disabled: disabled || awayScore <= 0,
|
|
4979
|
+
onClick: () => setAwayScore((s) => Math.max(0, s - 1)),
|
|
4980
|
+
children: "\u2212"
|
|
4981
|
+
}
|
|
4982
|
+
),
|
|
4983
|
+
/* @__PURE__ */ jsx61("span", { className: "ss-w-mp-stepper-val", children: awayScore }),
|
|
4984
|
+
/* @__PURE__ */ jsx61(
|
|
4985
|
+
"button",
|
|
4986
|
+
{
|
|
4987
|
+
type: "button",
|
|
4988
|
+
className: "ss-w-mp-stepper-btn",
|
|
4989
|
+
"aria-label": "+",
|
|
4990
|
+
disabled,
|
|
4991
|
+
onClick: () => setAwayScore((s) => s + 1),
|
|
4992
|
+
children: "+"
|
|
4993
|
+
}
|
|
4994
|
+
)
|
|
4995
|
+
] })
|
|
4996
|
+
] })
|
|
4997
|
+
] }),
|
|
4998
|
+
config.scorerPool.length > 0 && /* @__PURE__ */ jsxs55("div", { className: "ss-w-mp-scorer", children: [
|
|
4999
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-scorer-label", children: "First scorer (optional)" }),
|
|
5000
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-scorer-list", children: config.scorerPool.map((p) => /* @__PURE__ */ jsx61(
|
|
5001
|
+
"button",
|
|
5002
|
+
{
|
|
5003
|
+
type: "button",
|
|
5004
|
+
className: `ss-w-mp-scorer-opt${firstScorerPlayerId === p.playerId ? " ss-w-mp-scorer-opt--selected" : ""}`,
|
|
5005
|
+
disabled,
|
|
5006
|
+
onClick: () => setFirstScorerPlayerId((id) => id === p.playerId ? null : p.playerId),
|
|
5007
|
+
children: p.playerName
|
|
5008
|
+
},
|
|
5009
|
+
p.playerId
|
|
5010
|
+
)) })
|
|
5011
|
+
] }),
|
|
5012
|
+
locked && /* @__PURE__ */ jsx61("div", { className: "ss-w-mp-live-label", children: "Submissions are now closed" }),
|
|
5013
|
+
/* @__PURE__ */ jsx61(
|
|
5014
|
+
"button",
|
|
5015
|
+
{
|
|
5016
|
+
type: "button",
|
|
5017
|
+
className: "ss-w-mp-savebtn",
|
|
5018
|
+
disabled,
|
|
5019
|
+
onClick: handleSubmit,
|
|
5020
|
+
"aria-label": "Save prediction",
|
|
5021
|
+
children: submitting ? "Saving\u2026" : "Save prediction"
|
|
5022
|
+
}
|
|
5023
|
+
),
|
|
5024
|
+
/* @__PURE__ */ jsx61("div", { className: "ss-w-mp-fun", children: "For fun \u2014 not in the leaderboard" })
|
|
5025
|
+
] });
|
|
5026
|
+
}
|
|
5027
|
+
|
|
5028
|
+
// src/components/games/StartingXiGame.tsx
|
|
5029
|
+
import { useState as useState28 } from "react";
|
|
5030
|
+
import { jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
5031
|
+
function parseClientState8(json) {
|
|
5032
|
+
if (!json) return null;
|
|
5033
|
+
try {
|
|
5034
|
+
return JSON.parse(json);
|
|
5035
|
+
} catch {
|
|
5036
|
+
return null;
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
function parseFormationRows(formation) {
|
|
5040
|
+
const parts = formation.split("-").map(Number).filter((n) => n > 0);
|
|
5041
|
+
if (parts.length === 0) return [1, 4, 3, 3];
|
|
5042
|
+
return [1, ...parts];
|
|
5043
|
+
}
|
|
5044
|
+
function StartingXiGame({
|
|
5045
|
+
config,
|
|
5046
|
+
result,
|
|
5047
|
+
submitting,
|
|
5048
|
+
onSubmit
|
|
5049
|
+
}) {
|
|
5050
|
+
const [picked, setPicked] = useState28([]);
|
|
5051
|
+
const clientState = parseClientState8(result?.clientStateJson);
|
|
5052
|
+
const alreadyPlayed = result?.alreadyPlayed === true;
|
|
5053
|
+
if (alreadyPlayed) {
|
|
5054
|
+
if (!clientState) {
|
|
5055
|
+
return /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-status", children: /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-status-label", children: "This game has been voided" }) }) });
|
|
5056
|
+
}
|
|
5057
|
+
if (clientState.status === "pending") {
|
|
5058
|
+
return /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-status", children: /* @__PURE__ */ jsxs56("div", { className: "ss-w-sxi-status-label", children: [
|
|
5059
|
+
"Prediction locked in (",
|
|
5060
|
+
clientState.predictedCount,
|
|
5061
|
+
" players) \u2014 awaiting result"
|
|
5062
|
+
] }) }) });
|
|
5063
|
+
}
|
|
5064
|
+
if (clientState.status === "graded") {
|
|
5065
|
+
return /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ jsxs56("div", { className: "ss-w-sxi-status ss-w-sxi-status--graded", children: [
|
|
5066
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-status-score", children: clientState.score }),
|
|
5067
|
+
/* @__PURE__ */ jsxs56("div", { className: "ss-w-sxi-status-label", children: [
|
|
5068
|
+
clientState.correctCount,
|
|
5069
|
+
" correct starters"
|
|
5070
|
+
] })
|
|
5071
|
+
] }) });
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
if (!config) {
|
|
5075
|
+
return /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: /* @__PURE__ */ jsx62("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5076
|
+
}
|
|
5077
|
+
const formationRows = parseFormationRows(config.formation);
|
|
5078
|
+
const pickedSet = new Set(picked);
|
|
5079
|
+
const canSubmit = picked.length === 11 && !submitting;
|
|
5080
|
+
function togglePlayer(playerId) {
|
|
5081
|
+
if (submitting) return;
|
|
5082
|
+
setPicked((prev) => {
|
|
5083
|
+
if (prev.includes(playerId)) {
|
|
5084
|
+
return prev.filter((id) => id !== playerId);
|
|
5085
|
+
}
|
|
5086
|
+
if (prev.length >= 11) return prev;
|
|
5087
|
+
return [...prev, playerId];
|
|
5088
|
+
});
|
|
5089
|
+
}
|
|
5090
|
+
function handleSubmit() {
|
|
5091
|
+
if (!canSubmit) return;
|
|
5092
|
+
onSubmit(JSON.stringify({ predictedPlayerIds: picked }));
|
|
5093
|
+
}
|
|
5094
|
+
let slotIndex = 0;
|
|
5095
|
+
const pitchRows = formationRows.map((count, rowIdx) => {
|
|
5096
|
+
const rowSlots = picked.slice(slotIndex, slotIndex + count);
|
|
5097
|
+
slotIndex += count;
|
|
5098
|
+
return { rowIdx, count, rowSlots };
|
|
5099
|
+
});
|
|
5100
|
+
return /* @__PURE__ */ jsxs56("div", { className: "ss-w-sxi", "data-testid": "game-screen-starting-xi", children: [
|
|
5101
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-formation", children: config.formation }),
|
|
5102
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-pitch", children: pitchRows.map(({ rowIdx, count, rowSlots }) => /* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-pitch-row", children: Array.from({ length: count }).map((_, i) => {
|
|
5103
|
+
const playerId = rowSlots[i];
|
|
5104
|
+
const player = playerId != null ? config.squadSheet.find((p) => p.playerId === playerId) : void 0;
|
|
5105
|
+
return /* @__PURE__ */ jsxs56(
|
|
5106
|
+
"div",
|
|
5107
|
+
{
|
|
5108
|
+
className: `ss-w-sxi-pslot${player ? " ss-w-sxi-pslot--filled" : ""}`,
|
|
5109
|
+
onClick: () => {
|
|
5110
|
+
if (player) togglePlayer(player.playerId);
|
|
5111
|
+
},
|
|
5112
|
+
onKeyDown: (e) => {
|
|
5113
|
+
if (e.key === "Enter" && player) togglePlayer(player.playerId);
|
|
5114
|
+
},
|
|
5115
|
+
tabIndex: player ? 0 : -1,
|
|
5116
|
+
role: player ? "button" : void 0,
|
|
5117
|
+
"aria-label": player ? `Remove ${player.playerName ?? ""}` : void 0,
|
|
5118
|
+
children: [
|
|
5119
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-pslot-num", children: player?.jerseyNumber ?? (rowIdx === 0 ? "GK" : "?") }),
|
|
5120
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-pslot-name", children: player?.playerName ?? "" })
|
|
5121
|
+
]
|
|
5122
|
+
},
|
|
5123
|
+
i
|
|
5124
|
+
);
|
|
5125
|
+
}) }, rowIdx)) }),
|
|
5126
|
+
/* @__PURE__ */ jsx62("div", { className: "ss-w-sxi-squad", children: config.squadSheet.map((p) => {
|
|
5127
|
+
const isPicked = pickedSet.has(p.playerId);
|
|
5128
|
+
return /* @__PURE__ */ jsxs56(
|
|
5129
|
+
"div",
|
|
5130
|
+
{
|
|
5131
|
+
className: `ss-w-sxi-squad-row${isPicked ? " ss-w-sxi-squad-row--picked" : ""}`,
|
|
5132
|
+
onClick: () => togglePlayer(p.playerId),
|
|
5133
|
+
onKeyDown: (e) => {
|
|
5134
|
+
if (e.key === "Enter") togglePlayer(p.playerId);
|
|
5135
|
+
},
|
|
5136
|
+
tabIndex: 0,
|
|
5137
|
+
role: "button",
|
|
5138
|
+
"aria-pressed": isPicked,
|
|
5139
|
+
children: [
|
|
5140
|
+
/* @__PURE__ */ jsx62("span", { className: "ss-w-sxi-squad-name", children: p.playerName }),
|
|
5141
|
+
/* @__PURE__ */ jsx62("span", { className: "ss-w-sxi-squad-pos", children: p.positionName })
|
|
5142
|
+
]
|
|
5143
|
+
},
|
|
5144
|
+
p.playerId
|
|
5145
|
+
);
|
|
5146
|
+
}) }),
|
|
5147
|
+
/* @__PURE__ */ jsx62(
|
|
5148
|
+
"button",
|
|
5149
|
+
{
|
|
5150
|
+
type: "button",
|
|
5151
|
+
className: "ss-w-sxi-savebtn",
|
|
5152
|
+
disabled: !canSubmit,
|
|
5153
|
+
onClick: handleSubmit,
|
|
5154
|
+
"aria-label": "Predict XI",
|
|
5155
|
+
children: submitting ? "Submitting\u2026" : `Predict XI (${picked.length}/11)`
|
|
5156
|
+
}
|
|
5157
|
+
)
|
|
5158
|
+
] });
|
|
5159
|
+
}
|
|
5160
|
+
|
|
5161
|
+
// src/components/games/StatLadderGame.tsx
|
|
5162
|
+
import { jsx as jsx63, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
5163
|
+
function parseClientState9(json) {
|
|
5164
|
+
if (!json) return null;
|
|
5165
|
+
try {
|
|
5166
|
+
return JSON.parse(json);
|
|
5167
|
+
} catch {
|
|
5168
|
+
return null;
|
|
5169
|
+
}
|
|
5170
|
+
}
|
|
5171
|
+
function StatLadderGame({
|
|
5172
|
+
config,
|
|
5173
|
+
result,
|
|
5174
|
+
submitting,
|
|
5175
|
+
onSubmit
|
|
5176
|
+
}) {
|
|
5177
|
+
const clientState = parseClientState9(result?.clientStateJson);
|
|
5178
|
+
const revealed = clientState != null;
|
|
5179
|
+
if (!config) {
|
|
5180
|
+
return /* @__PURE__ */ jsx63("div", { className: "ss-w-sl", "data-testid": "game-screen-stat-ladder", children: /* @__PURE__ */ jsx63("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5181
|
+
}
|
|
5182
|
+
const mysteryName = revealed ? clientState.revealedRank2.playerName : null;
|
|
5183
|
+
return /* @__PURE__ */ jsxs57("div", { className: "ss-w-sl", "data-testid": "game-screen-stat-ladder", children: [
|
|
5184
|
+
/* @__PURE__ */ jsx63("div", { className: "ss-w-sl-title", children: config.statLabel }),
|
|
5185
|
+
/* @__PURE__ */ jsx63("div", { className: "ss-w-sl-ladder", children: config.ladder.map((rung) => {
|
|
5186
|
+
const isMystery = rung.rank === 2;
|
|
5187
|
+
let rowCls = "ss-w-sl-lrow";
|
|
5188
|
+
if (isMystery) rowCls += " ss-w-sl-mystery";
|
|
5189
|
+
if (isMystery && revealed) {
|
|
5190
|
+
rowCls = rowCls.replace(" ss-w-sl-mystery", "");
|
|
5191
|
+
rowCls += clientState.isCorrect ? " ss-w-sl-lrow--correct" : " ss-w-sl-lrow--wrong";
|
|
5192
|
+
}
|
|
5193
|
+
const displayName = isMystery ? revealed ? mysteryName : "?" : rung.playerName ?? "?";
|
|
5194
|
+
return /* @__PURE__ */ jsxs57("div", { className: rowCls, children: [
|
|
5195
|
+
/* @__PURE__ */ jsxs57("div", { className: "ss-w-sl-lrow-rank", children: [
|
|
5196
|
+
"#",
|
|
5197
|
+
rung.rank
|
|
5198
|
+
] }),
|
|
5199
|
+
/* @__PURE__ */ jsx63("div", { className: "ss-w-sl-lrow-name", children: displayName }),
|
|
5200
|
+
/* @__PURE__ */ jsx63("div", { className: "ss-w-sl-lrow-stat", children: rung.statValue })
|
|
5201
|
+
] }, rung.rank);
|
|
5202
|
+
}) }),
|
|
5203
|
+
revealed && /* @__PURE__ */ jsx63("div", { className: `ss-w-sl-reveal ss-w-sl-reveal--${clientState.isCorrect ? "correct" : "wrong"}`, children: clientState.isCorrect ? "Correct!" : `Wrong \u2014 it was ${clientState.revealedRank2.playerName}` }),
|
|
5204
|
+
!revealed && /* @__PURE__ */ jsx63("div", { className: "ss-w-sl-picker", children: config.playerPool.map((p) => /* @__PURE__ */ jsx63(
|
|
5205
|
+
"button",
|
|
5206
|
+
{
|
|
5207
|
+
type: "button",
|
|
5208
|
+
className: "ss-w-sl-picker-opt",
|
|
5209
|
+
disabled: submitting,
|
|
5210
|
+
"aria-label": p.playerName,
|
|
5211
|
+
onClick: () => onSubmit(JSON.stringify({ guessedPlayerId: p.playerId })),
|
|
5212
|
+
children: p.playerName
|
|
5213
|
+
},
|
|
5214
|
+
p.playerId
|
|
5215
|
+
)) })
|
|
5216
|
+
] });
|
|
5217
|
+
}
|
|
5218
|
+
|
|
5219
|
+
// src/components/games/FanMotmGame.tsx
|
|
5220
|
+
import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
5221
|
+
function parseClientState10(json) {
|
|
5222
|
+
if (!json) return null;
|
|
5223
|
+
try {
|
|
5224
|
+
return JSON.parse(json);
|
|
5225
|
+
} catch {
|
|
5226
|
+
return null;
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
function FanMotmGame({
|
|
5230
|
+
config,
|
|
5231
|
+
result,
|
|
5232
|
+
submitting,
|
|
5233
|
+
onSubmit
|
|
5234
|
+
}) {
|
|
5235
|
+
const clientState = parseClientState10(result?.clientStateJson);
|
|
5236
|
+
const alreadyVoted = result?.alreadyPlayed === true;
|
|
5237
|
+
if (!config) {
|
|
5238
|
+
return /* @__PURE__ */ jsx64("div", { className: "ss-w-motm", "data-testid": "game-screen-fan-motm", children: /* @__PURE__ */ jsx64("div", { className: "ss-w-gscreen-body", children: "Loading\u2026" }) });
|
|
5239
|
+
}
|
|
5240
|
+
const pickedId = clientState?.pickedPlayerId ?? null;
|
|
5241
|
+
function handleVote(candidateId) {
|
|
5242
|
+
if (alreadyVoted || submitting) return;
|
|
5243
|
+
onSubmit(JSON.stringify({ pickedPlayerId: candidateId }));
|
|
5244
|
+
}
|
|
5245
|
+
return /* @__PURE__ */ jsxs58("div", { className: "ss-w-motm", "data-testid": "game-screen-fan-motm", children: [
|
|
5246
|
+
/* @__PURE__ */ jsx64("div", { className: "ss-w-motm-title", children: "Man of the Match \u2014 your vote" }),
|
|
5247
|
+
/* @__PURE__ */ jsx64("div", { className: "ss-w-motm-votes", children: config.candidates.map((c) => {
|
|
5248
|
+
const isVoted = alreadyVoted && pickedId === c.playerId;
|
|
5249
|
+
const rowCls = `ss-w-motm-vrow${isVoted ? " ss-w-motm-vrow--voted" : ""}${alreadyVoted ? " ss-w-motm-vrow--result" : ""}`;
|
|
5250
|
+
return /* @__PURE__ */ jsxs58(
|
|
5251
|
+
"button",
|
|
5252
|
+
{
|
|
5253
|
+
type: "button",
|
|
5254
|
+
className: rowCls,
|
|
5255
|
+
"data-testid": `motm-candidate-${c.playerId}`,
|
|
5256
|
+
disabled: alreadyVoted || submitting,
|
|
5257
|
+
onClick: () => handleVote(c.playerId),
|
|
5258
|
+
children: [
|
|
5259
|
+
/* @__PURE__ */ jsx64("div", { className: "ss-w-motm-vfill", style: { width: isVoted ? "100%" : "0%" } }),
|
|
5260
|
+
/* @__PURE__ */ jsx64("span", { className: "ss-w-motm-vrow-name", children: c.playerName })
|
|
5261
|
+
]
|
|
5262
|
+
},
|
|
5263
|
+
c.playerId
|
|
5264
|
+
);
|
|
5265
|
+
}) }),
|
|
5266
|
+
/* @__PURE__ */ jsx64("div", { className: "ss-w-motm-fun", children: "For fun \u2014 unranked community vote" })
|
|
5267
|
+
] });
|
|
5268
|
+
}
|
|
5269
|
+
|
|
5270
|
+
// src/components/GameScreenHost.tsx
|
|
5271
|
+
import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
5272
|
+
var FIXTURE_GAME_IDS = /* @__PURE__ */ new Set([
|
|
5273
|
+
"matchday-predictor",
|
|
5274
|
+
"starting-xi",
|
|
5275
|
+
"stat-ladder",
|
|
5276
|
+
"fan-motm"
|
|
5277
|
+
]);
|
|
5278
|
+
var PENDING_POLL_INTERVAL_MS = 3e4;
|
|
5279
|
+
function safeParseConfig(json) {
|
|
5280
|
+
if (!json) return null;
|
|
5281
|
+
try {
|
|
5282
|
+
return JSON.parse(json);
|
|
5283
|
+
} catch {
|
|
5284
|
+
return null;
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
function GameScreenHost({
|
|
5288
|
+
selected,
|
|
5289
|
+
onBack,
|
|
5290
|
+
conversation,
|
|
5291
|
+
ui
|
|
5292
|
+
}) {
|
|
5293
|
+
const { gameId, fixtureId, gameDay = "" } = selected;
|
|
5294
|
+
const [configJson, setConfigJson] = useState29(null);
|
|
5295
|
+
useEffect13(() => {
|
|
5296
|
+
setConfigJson(null);
|
|
5297
|
+
if (!conversation) return;
|
|
5298
|
+
let cancelled = false;
|
|
5299
|
+
void (async () => {
|
|
5300
|
+
try {
|
|
5301
|
+
const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || void 0);
|
|
5302
|
+
if (!cancelled && payload?.configJson) {
|
|
5303
|
+
setConfigJson(payload.configJson);
|
|
5304
|
+
}
|
|
5305
|
+
} catch {
|
|
5306
|
+
}
|
|
5307
|
+
})();
|
|
5308
|
+
return () => {
|
|
5309
|
+
cancelled = true;
|
|
5310
|
+
};
|
|
5311
|
+
}, [conversation, gameId, fixtureId, gameDay]);
|
|
5312
|
+
const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {
|
|
5313
|
+
gameId,
|
|
5314
|
+
gameDay,
|
|
5315
|
+
fixtureId: fixtureId || void 0
|
|
5316
|
+
});
|
|
5317
|
+
useEffect13(() => {
|
|
5318
|
+
if (conversation) hydrate();
|
|
5319
|
+
}, [conversation, gameId]);
|
|
5320
|
+
const hydrateRef = useRef12(hydrate);
|
|
5321
|
+
hydrateRef.current = hydrate;
|
|
5322
|
+
useEffect13(() => {
|
|
5323
|
+
if (!FIXTURE_GAME_IDS.has(gameId)) return;
|
|
5324
|
+
if (rawStatus !== "pending") return;
|
|
5325
|
+
const timerId = setInterval(() => {
|
|
5326
|
+
hydrateRef.current();
|
|
5327
|
+
}, PENDING_POLL_INTERVAL_MS);
|
|
5328
|
+
return () => clearInterval(timerId);
|
|
5329
|
+
}, [gameId, rawStatus]);
|
|
5330
|
+
const sharedProps = {
|
|
5331
|
+
result,
|
|
5332
|
+
submitting,
|
|
5333
|
+
onSubmit: submit,
|
|
5334
|
+
ui
|
|
5335
|
+
};
|
|
5336
|
+
function renderScreen() {
|
|
5337
|
+
switch (gameId) {
|
|
5338
|
+
case "mystery-tiger":
|
|
5339
|
+
return /* @__PURE__ */ jsx65(
|
|
5340
|
+
MysteryTigerGame,
|
|
5341
|
+
{
|
|
5342
|
+
...sharedProps,
|
|
5343
|
+
config: safeParseConfig(configJson)
|
|
5344
|
+
}
|
|
5345
|
+
);
|
|
5346
|
+
case "higher-or-lower":
|
|
5347
|
+
return /* @__PURE__ */ jsx65(
|
|
5348
|
+
HigherOrLowerGame,
|
|
5349
|
+
{
|
|
5350
|
+
...sharedProps,
|
|
5351
|
+
config: safeParseConfig(configJson)
|
|
5352
|
+
}
|
|
5353
|
+
);
|
|
5354
|
+
case "career-path":
|
|
5355
|
+
return /* @__PURE__ */ jsx65(
|
|
5356
|
+
CareerPathGame,
|
|
5357
|
+
{
|
|
5358
|
+
...sharedProps,
|
|
5359
|
+
config: safeParseConfig(configJson)
|
|
5360
|
+
}
|
|
5361
|
+
);
|
|
5362
|
+
case "beat-the-grid":
|
|
5363
|
+
return /* @__PURE__ */ jsx65(
|
|
5364
|
+
BeatTheGridGame,
|
|
5365
|
+
{
|
|
5366
|
+
...sharedProps,
|
|
5367
|
+
config: safeParseConfig(configJson),
|
|
5368
|
+
playerPool: []
|
|
5369
|
+
}
|
|
5370
|
+
);
|
|
5371
|
+
case "guess-the-xi":
|
|
5372
|
+
return /* @__PURE__ */ jsx65(
|
|
5373
|
+
GuessTheXiGame,
|
|
5374
|
+
{
|
|
5375
|
+
...sharedProps,
|
|
5376
|
+
config: safeParseConfig(configJson)
|
|
5377
|
+
}
|
|
5378
|
+
);
|
|
5379
|
+
case "daily-quiz":
|
|
5380
|
+
return /* @__PURE__ */ jsx65(
|
|
5381
|
+
DailyQuizGame,
|
|
5382
|
+
{
|
|
5383
|
+
...sharedProps,
|
|
5384
|
+
config: safeParseConfig(configJson)
|
|
5385
|
+
}
|
|
5386
|
+
);
|
|
5387
|
+
case "matchday-predictor":
|
|
5388
|
+
return /* @__PURE__ */ jsx65(
|
|
5389
|
+
MatchdayPredictorGame,
|
|
5390
|
+
{
|
|
5391
|
+
...sharedProps,
|
|
5392
|
+
config: safeParseConfig(configJson)
|
|
5393
|
+
}
|
|
5394
|
+
);
|
|
5395
|
+
case "starting-xi":
|
|
5396
|
+
return /* @__PURE__ */ jsx65(
|
|
5397
|
+
StartingXiGame,
|
|
5398
|
+
{
|
|
5399
|
+
...sharedProps,
|
|
5400
|
+
config: safeParseConfig(configJson)
|
|
5401
|
+
}
|
|
5402
|
+
);
|
|
5403
|
+
case "stat-ladder":
|
|
5404
|
+
return /* @__PURE__ */ jsx65(
|
|
5405
|
+
StatLadderGame,
|
|
5406
|
+
{
|
|
5407
|
+
...sharedProps,
|
|
5408
|
+
config: safeParseConfig(configJson)
|
|
5409
|
+
}
|
|
5410
|
+
);
|
|
5411
|
+
case "fan-motm":
|
|
5412
|
+
return /* @__PURE__ */ jsx65(
|
|
5413
|
+
FanMotmGame,
|
|
5414
|
+
{
|
|
5415
|
+
...sharedProps,
|
|
5416
|
+
config: safeParseConfig(configJson)
|
|
5417
|
+
}
|
|
5418
|
+
);
|
|
5419
|
+
default:
|
|
5420
|
+
return /* @__PURE__ */ jsx65("div", { className: "ss-w-gscreen-body", "data-testid": `game-screen-${gameId}`, children: gameId });
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
return /* @__PURE__ */ jsxs59("div", { className: "ss-w-gscreen", children: [
|
|
5424
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "ss-w-gscreen-back", onClick: onBack, children: [
|
|
5425
|
+
/* @__PURE__ */ jsx65("span", { className: "ss-w-gscreen-back-arrow", "aria-hidden": "true", children: "\u2039" }),
|
|
5426
|
+
ui.back
|
|
5427
|
+
] }),
|
|
5428
|
+
renderScreen()
|
|
5429
|
+
] });
|
|
5430
|
+
}
|
|
5431
|
+
|
|
5432
|
+
// src/components/GamesPanel.tsx
|
|
5433
|
+
import { jsx as jsx66 } from "react/jsx-runtime";
|
|
5434
|
+
function GamesPanel({
|
|
5435
|
+
loggedIn,
|
|
5436
|
+
games,
|
|
5437
|
+
ui,
|
|
5438
|
+
conversation
|
|
5439
|
+
}) {
|
|
5440
|
+
const [selected, setSelected] = useState30(null);
|
|
5441
|
+
if (!loggedIn) return /* @__PURE__ */ jsx66(GamesLoginWall, { ui });
|
|
5442
|
+
if (selected !== null) {
|
|
5443
|
+
return /* @__PURE__ */ jsx66("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ jsx66(
|
|
5444
|
+
GameScreenHost,
|
|
5445
|
+
{
|
|
5446
|
+
selected,
|
|
5447
|
+
onBack: () => setSelected(null),
|
|
5448
|
+
conversation: conversation ?? null,
|
|
5449
|
+
ui
|
|
5450
|
+
}
|
|
5451
|
+
) });
|
|
5452
|
+
}
|
|
5453
|
+
return /* @__PURE__ */ jsx66("div", { className: "ss-w-mon-list", "data-testid": "games-hub", children: /* @__PURE__ */ jsx66(
|
|
5454
|
+
GamesHub,
|
|
5455
|
+
{
|
|
5456
|
+
games,
|
|
5457
|
+
onOpen: (g) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId, gameDay: g.gameDay }),
|
|
5458
|
+
ui
|
|
5459
|
+
}
|
|
5460
|
+
) });
|
|
5461
|
+
}
|
|
5462
|
+
|
|
5463
|
+
// src/components/Leaderboard.tsx
|
|
5464
|
+
import { useState as useState31 } from "react";
|
|
5465
|
+
|
|
5466
|
+
// src/components/LeaderboardRow.tsx
|
|
5467
|
+
import { jsx as jsx67, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
5468
|
+
function formatPoints(n) {
|
|
5469
|
+
return n.toLocaleString("en");
|
|
5470
|
+
}
|
|
5471
|
+
function LeaderboardWeeklyRow({
|
|
5472
|
+
row,
|
|
5473
|
+
isMe
|
|
5474
|
+
}) {
|
|
5475
|
+
const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? " ss-w-lb2-rank--top3" : ""}`;
|
|
5476
|
+
return /* @__PURE__ */ jsxs60("div", { className: `ss-w-lb2-row${isMe ? " ss-w-lb2-row--you" : ""}`, children: [
|
|
5477
|
+
/* @__PURE__ */ jsxs60("span", { className: rankClass, children: [
|
|
5478
|
+
"#",
|
|
5479
|
+
row.rank
|
|
5480
|
+
] }),
|
|
5481
|
+
/* @__PURE__ */ jsx67("span", { className: "ss-w-lb2-handle", children: row.handle }),
|
|
5482
|
+
/* @__PURE__ */ jsx67("span", { className: "ss-w-lb2-points", children: formatPoints(row.points) }),
|
|
5483
|
+
row.currentStreak > 0 && /* @__PURE__ */ jsxs60("span", { className: "ss-w-lb2-streak", children: [
|
|
5484
|
+
"\u{1F525} ",
|
|
5485
|
+
row.currentStreak
|
|
5486
|
+
] })
|
|
5487
|
+
] });
|
|
5488
|
+
}
|
|
5489
|
+
function LeaderboardAllTimeRow({
|
|
5490
|
+
row,
|
|
5491
|
+
isMe
|
|
5492
|
+
}) {
|
|
5493
|
+
const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? " ss-w-lb2-rank--top3" : ""}`;
|
|
5494
|
+
return /* @__PURE__ */ jsxs60("div", { className: `ss-w-lb2-row${isMe ? " ss-w-lb2-row--you" : ""}`, children: [
|
|
5495
|
+
/* @__PURE__ */ jsxs60("span", { className: rankClass, children: [
|
|
5496
|
+
"#",
|
|
5497
|
+
row.rank
|
|
5498
|
+
] }),
|
|
5499
|
+
/* @__PURE__ */ jsx67("span", { className: "ss-w-lb2-handle", children: row.handle }),
|
|
5500
|
+
/* @__PURE__ */ jsx67("span", { className: "ss-w-lb2-points", children: formatPoints(row.allTimePoints) })
|
|
5501
|
+
] });
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
// src/components/Leaderboard.tsx
|
|
5505
|
+
import { jsx as jsx68, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
5506
|
+
function Leaderboard({
|
|
5507
|
+
data,
|
|
5508
|
+
ui
|
|
5509
|
+
}) {
|
|
5510
|
+
const [segment, setSegment] = useState31("weekly");
|
|
5511
|
+
const myRow = segment === "weekly" ? data.myWeeklyRow : data.myAllTimeRow;
|
|
5512
|
+
const offBoard = myRow !== null && myRow !== void 0 && myRow.rank === -1;
|
|
5513
|
+
return /* @__PURE__ */ jsxs61("div", { className: "ss-w-lb2", children: [
|
|
5514
|
+
/* @__PURE__ */ jsxs61("div", { className: "ss-w-seg", children: [
|
|
5515
|
+
/* @__PURE__ */ jsx68(
|
|
5516
|
+
"button",
|
|
5517
|
+
{
|
|
5518
|
+
type: "button",
|
|
5519
|
+
className: "ss-w-seg-btn",
|
|
5520
|
+
...segment === "weekly" ? { "data-on": "" } : {},
|
|
5521
|
+
onClick: () => setSegment("weekly"),
|
|
5522
|
+
children: ui.leaderboardThisWeek
|
|
5523
|
+
}
|
|
5524
|
+
),
|
|
5525
|
+
/* @__PURE__ */ jsx68(
|
|
5526
|
+
"button",
|
|
5527
|
+
{
|
|
5528
|
+
type: "button",
|
|
5529
|
+
className: "ss-w-seg-btn",
|
|
5530
|
+
...segment === "alltime" ? { "data-on": "" } : {},
|
|
5531
|
+
onClick: () => setSegment("alltime"),
|
|
5532
|
+
children: ui.leaderboardAllTime
|
|
5533
|
+
}
|
|
5534
|
+
)
|
|
5535
|
+
] }),
|
|
5536
|
+
/* @__PURE__ */ jsx68("div", { className: "ss-w-lb2-rows", children: segment === "weekly" ? data.weeklyTop.map((row) => /* @__PURE__ */ jsx68(
|
|
5537
|
+
LeaderboardWeeklyRow,
|
|
5538
|
+
{
|
|
5539
|
+
row,
|
|
5540
|
+
isMe: row.operatorUserId === data.myWeeklyRow?.operatorUserId
|
|
5541
|
+
},
|
|
5542
|
+
row.operatorUserId
|
|
5543
|
+
)) : data.allTimeTop.map((row) => /* @__PURE__ */ jsx68(
|
|
5544
|
+
LeaderboardAllTimeRow,
|
|
5545
|
+
{
|
|
5546
|
+
row,
|
|
5547
|
+
isMe: row.operatorUserId === data.myAllTimeRow?.operatorUserId
|
|
5548
|
+
},
|
|
5549
|
+
row.operatorUserId
|
|
5550
|
+
)) }),
|
|
5551
|
+
/* @__PURE__ */ jsx68("div", { className: "ss-w-kitline", children: "\u{1F3BD}" }),
|
|
5552
|
+
myRow != null && (offBoard ? /* @__PURE__ */ jsx68("div", { className: "ss-w-lbgap", children: ui.leaderboardOffBoard }) : /* @__PURE__ */ jsxs61("div", { className: "ss-w-lb2-rows", children: [
|
|
5553
|
+
segment === "weekly" && data.myWeeklyRow && /* @__PURE__ */ jsx68(LeaderboardWeeklyRow, { row: data.myWeeklyRow, isMe: true }),
|
|
5554
|
+
segment === "alltime" && data.myAllTimeRow && /* @__PURE__ */ jsx68(LeaderboardAllTimeRow, { row: data.myAllTimeRow, isMe: true })
|
|
5555
|
+
] })),
|
|
5556
|
+
segment === "alltime" && data.myAllTimeRow && !offBoard && /* @__PURE__ */ jsx68("div", { className: "ss-w-lb2-rows", children: /* @__PURE__ */ jsx68("div", { className: "ss-w-lb2-row", children: /* @__PURE__ */ jsx68("span", { className: "ss-w-lb2-handle", children: formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0)) }) }) })
|
|
5557
|
+
] });
|
|
5558
|
+
}
|
|
5559
|
+
|
|
5560
|
+
// src/components/LeaderboardPanel.tsx
|
|
5561
|
+
import { jsx as jsx69 } from "react/jsx-runtime";
|
|
5562
|
+
function LeaderboardPanel({ loggedIn, data, ui }) {
|
|
5563
|
+
if (!loggedIn) return /* @__PURE__ */ jsx69(GamesLoginWall, { ui });
|
|
5564
|
+
if (data === null) return /* @__PURE__ */ jsx69("div", { className: "ss-w-mon-list" });
|
|
5565
|
+
return /* @__PURE__ */ jsx69("div", { className: "ss-w-mon-list", children: /* @__PURE__ */ jsx69(Leaderboard, { data, ui }) });
|
|
5566
|
+
}
|
|
5567
|
+
|
|
3805
5568
|
// src/components/ChatPanel.tsx
|
|
3806
|
-
import { jsx as
|
|
5569
|
+
import { jsx as jsx70, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
3807
5570
|
var FULLSCREEN_QUERY = "(max-width: 639px)";
|
|
3808
5571
|
function useIsModal() {
|
|
3809
|
-
const [modal, setModal] =
|
|
3810
|
-
|
|
5572
|
+
const [modal, setModal] = useState32(false);
|
|
5573
|
+
useEffect14(() => {
|
|
3811
5574
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
3812
5575
|
const mql = window.matchMedia(FULLSCREEN_QUERY);
|
|
3813
5576
|
const sync = () => setModal(mql.matches);
|
|
@@ -3817,10 +5580,10 @@ function useIsModal() {
|
|
|
3817
5580
|
}, []);
|
|
3818
5581
|
return modal;
|
|
3819
5582
|
}
|
|
3820
|
-
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery }) {
|
|
5583
|
+
function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }) {
|
|
3821
5584
|
const { state, close, stop, send, reset } = controller;
|
|
3822
5585
|
const isModal = useIsModal();
|
|
3823
|
-
|
|
5586
|
+
useEffect14(() => {
|
|
3824
5587
|
const onKey = (e) => {
|
|
3825
5588
|
if (e.key === "Escape") close();
|
|
3826
5589
|
};
|
|
@@ -3831,11 +5594,11 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery })
|
|
|
3831
5594
|
monitor?.setActiveTab("chat");
|
|
3832
5595
|
send(text);
|
|
3833
5596
|
};
|
|
3834
|
-
|
|
5597
|
+
useEffect14(() => {
|
|
3835
5598
|
if (monitor && monitor.activeTab !== "chat" && state.isStreaming) monitor.markChatActivity();
|
|
3836
5599
|
}, [monitor, state.isStreaming, state.messages.length]);
|
|
3837
|
-
return /* @__PURE__ */
|
|
3838
|
-
/* @__PURE__ */
|
|
5600
|
+
return /* @__PURE__ */ jsxs62("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
|
|
5601
|
+
/* @__PURE__ */ jsx70(
|
|
3839
5602
|
ChatHeader,
|
|
3840
5603
|
{
|
|
3841
5604
|
onClose: close,
|
|
@@ -3848,7 +5611,7 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery })
|
|
|
3848
5611
|
moreOptionsLabel: ui.moreOptions
|
|
3849
5612
|
}
|
|
3850
5613
|
),
|
|
3851
|
-
monitor && /* @__PURE__ */
|
|
5614
|
+
monitor && /* @__PURE__ */ jsx70(
|
|
3852
5615
|
TabBar,
|
|
3853
5616
|
{
|
|
3854
5617
|
monitor,
|
|
@@ -3856,20 +5619,23 @@ function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery })
|
|
|
3856
5619
|
matchCount: monitor.pins.filter((p) => p.kind === "match").length,
|
|
3857
5620
|
oddsCount: monitor.pins.filter((p) => p.kind !== "match").length,
|
|
3858
5621
|
todayCount: discovery?.liveCount ?? 0,
|
|
3859
|
-
hasToday: discovery ? visibleGroupsOf(discovery.groups, discovery.states).length > 0 : false
|
|
5622
|
+
hasToday: discovery ? visibleGroupsOf(discovery.groups, discovery.states).length > 0 : false,
|
|
5623
|
+
gamesEnabled: gamesResult?.enabled ?? false
|
|
3860
5624
|
}
|
|
3861
5625
|
),
|
|
3862
|
-
/* @__PURE__ */
|
|
5626
|
+
/* @__PURE__ */ jsx70(
|
|
3863
5627
|
"div",
|
|
3864
5628
|
{
|
|
3865
5629
|
style: !monitor || monitor.activeTab === "chat" ? { display: "contents" } : { position: "absolute", inset: 0, visibility: "hidden", display: "flex", flexDirection: "column" },
|
|
3866
|
-
children: /* @__PURE__ */
|
|
5630
|
+
children: /* @__PURE__ */ jsx70(MessageList, { controller, ui, slip, onDashboardTap, monitor })
|
|
3867
5631
|
}
|
|
3868
5632
|
),
|
|
3869
|
-
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */
|
|
3870
|
-
monitor && monitor.activeTab === "following" && /* @__PURE__ */
|
|
3871
|
-
monitor && monitor.activeTab === "odds" && /* @__PURE__ */
|
|
3872
|
-
/* @__PURE__ */
|
|
5633
|
+
monitor && discovery && monitor.activeTab === "today" && /* @__PURE__ */ jsx70(TodayPanel, { discovery, ui, monitor }),
|
|
5634
|
+
monitor && monitor.activeTab === "following" && /* @__PURE__ */ jsx70(MatchesPanel, { monitor, ui, slip }),
|
|
5635
|
+
monitor && monitor.activeTab === "odds" && /* @__PURE__ */ jsx70(OddsPanel, { monitor, ui, slip }),
|
|
5636
|
+
monitor && monitor.activeTab === "games" && gamesResult && /* @__PURE__ */ jsx70(GamesPanel, { loggedIn: !!loggedIn, games: gamesResult.games, ui, conversation }),
|
|
5637
|
+
monitor && monitor.activeTab === "leaderboard" && leaderboardResult && /* @__PURE__ */ jsx70(LeaderboardPanel, { loggedIn: !!loggedIn, data: leaderboardResult.data, ui }),
|
|
5638
|
+
/* @__PURE__ */ jsx70(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: handleSend, onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
|
|
3873
5639
|
] });
|
|
3874
5640
|
}
|
|
3875
5641
|
|
|
@@ -3883,6 +5649,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
3883
5649
|
--ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;
|
|
3884
5650
|
--ss-w-pos: #1aa563; --ss-w-neg: #e0524b;
|
|
3885
5651
|
--ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;
|
|
5652
|
+
--ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;
|
|
3886
5653
|
--ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;
|
|
3887
5654
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
3888
5655
|
font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);
|
|
@@ -3894,6 +5661,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
3894
5661
|
--ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;
|
|
3895
5662
|
--ss-w-pos: #37c891; --ss-w-neg: #f0655d;
|
|
3896
5663
|
--ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;
|
|
5664
|
+
--ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;
|
|
3897
5665
|
}
|
|
3898
5666
|
}
|
|
3899
5667
|
.ss-w-root[data-ss-w-theme="dark"] {
|
|
@@ -3902,12 +5670,14 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
3902
5670
|
--ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;
|
|
3903
5671
|
--ss-w-pos: #37c891; --ss-w-neg: #f0655d;
|
|
3904
5672
|
--ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;
|
|
5673
|
+
--ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;
|
|
3905
5674
|
}
|
|
3906
5675
|
.ss-w-root[data-ss-w-theme="light"] {
|
|
3907
5676
|
--ss-w-accent: #17936a; --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;
|
|
3908
5677
|
--ss-w-ink: #14181d; --ss-w-faint: #6b7580;
|
|
3909
5678
|
--ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;
|
|
3910
5679
|
--ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;
|
|
5680
|
+
--ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;
|
|
3911
5681
|
}
|
|
3912
5682
|
|
|
3913
5683
|
/* launcher */
|
|
@@ -4642,7 +6412,12 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
4642
6412
|
.ss-w-mon-vs { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; }
|
|
4643
6413
|
.ss-w-mon-score { display: flex; align-items: baseline; justify-content: center; font-size: 26px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }
|
|
4644
6414
|
.ss-w-mon-score i { font-style: normal; color: var(--ss-w-faint); font-weight: 500; margin: 0 4px; }
|
|
4645
|
-
.ss-w-mon-scorers { font-size: 11.5px; color: var(--ss-w-faint);
|
|
6415
|
+
.ss-w-mon-scorers { display: grid; grid-template-columns: 1fr auto 1fr; align-items: start; column-gap: 10px; font-size: 11.5px; color: var(--ss-w-faint); }
|
|
6416
|
+
.ss-w-mon-scorers-col { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
6417
|
+
.ss-w-mon-scorers-col li { overflow-wrap: anywhere; }
|
|
6418
|
+
.ss-w-mon-scorers-home { text-align: right; }
|
|
6419
|
+
.ss-w-mon-scorers-away { text-align: left; }
|
|
6420
|
+
.ss-w-mon-scorers-ball { flex: none; align-self: start; line-height: 1.35; }
|
|
4646
6421
|
.ss-w-mon-stats { display: flex; flex-direction: column; gap: 10px; }
|
|
4647
6422
|
.ss-w-mon-stat { display: flex; flex-direction: column; gap: 5px; }
|
|
4648
6423
|
.ss-w-mon-pstrip { padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--ss-w-accent) 8%, transparent); }
|
|
@@ -4744,10 +6519,384 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
4744
6519
|
.ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }
|
|
4745
6520
|
|
|
4746
6521
|
.ss-w-stale { font-size: 11px; font-weight: 600; color: var(--ss-w-cta); background: color-mix(in srgb, var(--ss-w-cta) 12%, var(--ss-w-panel)); border-radius: 8px; padding: 6px 9px; }
|
|
6522
|
+
|
|
6523
|
+
/* ---- Games hub (D2) ---- */
|
|
6524
|
+
/* Hub shell: prize banner \u2192 chips \u2192 game matrix, all in a single column */
|
|
6525
|
+
.ss-w-games-hub { display: flex; flex-direction: column; gap: 12px; }
|
|
6526
|
+
|
|
6527
|
+
/* Prize banner: CTA-tinted card with icon + body column (label + chips) */
|
|
6528
|
+
.ss-w-prize { display: flex; align-items: flex-start; gap: 10px; padding: 11px 13px; border-radius: 12px; background: color-mix(in srgb, var(--ss-w-cta) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 22%, var(--ss-w-line)); }
|
|
6529
|
+
.ss-w-prize-icon { flex: none; font-size: 20px; line-height: 1; padding-top: 1px; }
|
|
6530
|
+
.ss-w-prize-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
6531
|
+
.ss-w-prize-text { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.35; overflow-wrap: anywhere; }
|
|
6532
|
+
|
|
6533
|
+
/* Hub chips (streak / rank) \u2014 NOT .ss-w-chip which belongs to intent chips */
|
|
6534
|
+
.ss-w-g-chips { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
6535
|
+
.ss-w-g-chip { display: inline-flex; align-items: center; font-size: 11px; font-weight: 700; border-radius: 999px; padding: 3px 10px; border: 1px solid transparent; white-space: nowrap; }
|
|
6536
|
+
.ss-w-g-chip--streak { color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border-color: var(--ss-w-cta); }
|
|
6537
|
+
.ss-w-g-chip--rank { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-accent) 24%, var(--ss-w-line)); }
|
|
6538
|
+
|
|
6539
|
+
/* Game matrix: 2-column grid of tiles */
|
|
6540
|
+
.ss-w-gmatrix { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
|
6541
|
+
|
|
6542
|
+
/* Game tile: a tappable card with status-driven visual state */
|
|
6543
|
+
.ss-w-tile { display: flex; flex-direction: column; gap: 6px; padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); cursor: pointer; text-align: left; font: inherit; color: inherit; width: 100%; min-width: 0; transition: background .12s ease; }
|
|
6544
|
+
.ss-w-tile:not([data-disabled]):hover { background: var(--ss-w-bubble); }
|
|
6545
|
+
.ss-w-tile[data-disabled] { opacity: .6; cursor: default; pointer-events: none; }
|
|
6546
|
+
.ss-w-tile-icon { font-size: 22px; line-height: 1; }
|
|
6547
|
+
.ss-w-tile-title { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.25; overflow-wrap: anywhere; }
|
|
6548
|
+
.ss-w-tile-status { font-size: 11px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6549
|
+
.ss-w-tile-status--available { color: var(--ss-w-accent); font-weight: 600; }
|
|
6550
|
+
.ss-w-tile-status--in_progress { color: var(--ss-w-accent); font-weight: 600; }
|
|
6551
|
+
.ss-w-tile-status--played { color: var(--ss-w-correct); font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
6552
|
+
.ss-w-tile-status--graded { color: var(--ss-w-correct); font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
6553
|
+
/* Skill / For-fun kind chip */
|
|
6554
|
+
.ss-w-tile-chip { display: inline-flex; align-self: flex-start; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; border-radius: 999px; padding: 2px 7px; margin-top: 2px; }
|
|
6555
|
+
.ss-w-tile-chip--skill { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); }
|
|
6556
|
+
.ss-w-tile-chip--fun { color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); }
|
|
6557
|
+
|
|
6558
|
+
/* Game screen host: back-row + placeholder body */
|
|
6559
|
+
.ss-w-gscreen { display: flex; flex-direction: column; gap: 0; }
|
|
6560
|
+
.ss-w-gscreen-back { display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; padding: 6px 0 10px; align-self: flex-start; }
|
|
6561
|
+
.ss-w-gscreen-back-arrow { font-size: 11px; font-weight: 700; }
|
|
6562
|
+
.ss-w-gscreen-body { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 16px; color: var(--ss-w-faint); font-size: 13px; text-align: center; }
|
|
6563
|
+
|
|
6564
|
+
/* ---- Leaderboard (D2) ---- */
|
|
6565
|
+
/* Outer shell */
|
|
6566
|
+
.ss-w-lb2 { display: flex; flex-direction: column; gap: 12px; }
|
|
6567
|
+
|
|
6568
|
+
/* Segmented control: This week / All time */
|
|
6569
|
+
.ss-w-seg { display: inline-flex; gap: 2px; align-self: flex-start; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 2px; }
|
|
6570
|
+
.ss-w-seg-btn { font-size: 12px; font-weight: 600; border: none; border-radius: 7px; padding: 5px 12px; color: var(--ss-w-faint); background: none; cursor: pointer; font: inherit; white-space: nowrap; }
|
|
6571
|
+
.ss-w-seg-btn[data-on] { color: var(--ss-w-ink); background: var(--ss-w-panel); box-shadow: 0 1px 3px rgba(0,0,0,.09); }
|
|
6572
|
+
|
|
6573
|
+
/* Row list */
|
|
6574
|
+
.ss-w-lb2-rows { display: flex; flex-direction: column; border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; background: var(--ss-w-panel); }
|
|
6575
|
+
.ss-w-lb2-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }
|
|
6576
|
+
.ss-w-lb2-row:last-child { border-bottom: none; }
|
|
6577
|
+
/* Highlighted "you" row: full-width tint via negative margin trick, contained by border-radius above */
|
|
6578
|
+
.ss-w-lb2-row--you { background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); }
|
|
6579
|
+
.ss-w-lb2-rank { flex: none; min-width: 30px; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-faint); }
|
|
6580
|
+
.ss-w-lb2-rank--top3 { color: var(--ss-w-cta); }
|
|
6581
|
+
.ss-w-lb2-handle { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ss-w-ink); }
|
|
6582
|
+
.ss-w-lb2-points { flex: none; font-size: 13px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }
|
|
6583
|
+
.ss-w-lb2-streak { flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); padding-left: 4px; }
|
|
6584
|
+
|
|
6585
|
+
/* Kit-prize separator: a labelled hairline (eyebrow + two growing lines) */
|
|
6586
|
+
.ss-w-kitline { display: flex; align-items: center; gap: 8px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); }
|
|
6587
|
+
.ss-w-kitline::before, .ss-w-kitline::after { content: ""; flex: 1; height: 1px; background: var(--ss-w-line); }
|
|
6588
|
+
|
|
6589
|
+
/* Off-board treatment: dashed pill indicating rank is outside top N */
|
|
6590
|
+
.ss-w-lbgap { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 12px; font-size: 11.5px; color: var(--ss-w-faint); border: 1px dashed var(--ss-w-line); border-radius: 10px; }
|
|
6591
|
+
|
|
6592
|
+
/* ---- Mystery Tiger game screen (D3) ---- */
|
|
6593
|
+
.ss-w-gt { display: flex; flex-direction: column; gap: 10px; }
|
|
6594
|
+
/* Typeahead wrapper: relative so the dropdown can position under it */
|
|
6595
|
+
.ss-w-gtta { position: relative; }
|
|
6596
|
+
.ss-w-gtta-i { width: 100%; box-sizing: border-box; padding: 9px 12px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); font: inherit; font-size: 13px; outline: none; transition: border-color .12s; }
|
|
6597
|
+
.ss-w-gtta-i:focus { border-color: var(--ss-w-accent); }
|
|
6598
|
+
.ss-w-gtta-i:disabled { opacity: .5; cursor: not-allowed; }
|
|
6599
|
+
.ss-w-gtta-drop { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 10; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 10px; max-height: 180px; overflow-y: auto; box-shadow: 0 4px 16px rgba(0,0,0,.12); }
|
|
6600
|
+
.ss-w-gtta-opt { padding: 9px 12px; font-size: 13px; cursor: pointer; color: var(--ss-w-ink); border-bottom: 1px solid var(--ss-w-line); }
|
|
6601
|
+
.ss-w-gtta-opt:last-child { border-bottom: none; }
|
|
6602
|
+
.ss-w-gtta-opt:hover { background: var(--ss-w-bubble); }
|
|
6603
|
+
/* Column header labels: one cell per attribute */
|
|
6604
|
+
.ss-w-gthdr { display: grid; grid-template-columns: 1fr repeat(5, 36px); gap: 4px; padding: 0 2px; }
|
|
6605
|
+
.ss-w-gthdr-c { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6606
|
+
.ss-w-gthdr-c--name { text-align: left; }
|
|
6607
|
+
/* Guess rows */
|
|
6608
|
+
.ss-w-gtrows { display: flex; flex-direction: column; gap: 4px; }
|
|
6609
|
+
.ss-w-gtrow { display: grid; grid-template-columns: 1fr repeat(5, 36px); gap: 4px; align-items: center; }
|
|
6610
|
+
.ss-w-gtrow-nm { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 4px; }
|
|
6611
|
+
/* Verdict tiles */
|
|
6612
|
+
.ss-w-gtile { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 36px; border-radius: 8px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; gap: 1px; transition: transform .1s; }
|
|
6613
|
+
.ss-w-gtile--exact { background: var(--ss-w-correct); color: #fff; }
|
|
6614
|
+
.ss-w-gtile--near { background: var(--ss-w-cta); color: var(--ss-w-cta-ink, #fff); }
|
|
6615
|
+
.ss-w-gtile--miss { background: var(--ss-w-bubble); color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); }
|
|
6616
|
+
.ss-w-gtile-dir { font-size: 11px; line-height: 1; }
|
|
6617
|
+
/* Hint line */
|
|
6618
|
+
.ss-w-gt-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; padding: 2px 0; font-style: italic; }
|
|
6619
|
+
/* Outcome banner: shown when solved or failed */
|
|
6620
|
+
.ss-w-gt-banner { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 12px; border-radius: 12px; text-align: center; }
|
|
6621
|
+
.ss-w-gt-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6622
|
+
.ss-w-gt-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6623
|
+
.ss-w-gt-banner-name { font-size: 16px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6624
|
+
.ss-w-gt-banner-label { font-size: 12px; color: var(--ss-w-faint); }
|
|
6625
|
+
|
|
6626
|
+
/* ---- Higher or Lower game screen (D3) ---- */
|
|
6627
|
+
.ss-w-hl { display: flex; flex-direction: column; gap: 12px; }
|
|
6628
|
+
/* Stat context header: family name + season */
|
|
6629
|
+
.ss-w-hlctx { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
|
|
6630
|
+
.ss-w-hlctx-fam { font-size: 14px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6631
|
+
.ss-w-hlctx-szn { font-size: 11.5px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6632
|
+
/* Score chip */
|
|
6633
|
+
.ss-w-hl-score { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 11%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, var(--ss-w-line)); border-radius: 999px; padding: 3px 10px; }
|
|
6634
|
+
/* Pair card: two player cards + divider */
|
|
6635
|
+
.ss-w-hlpair { display: flex; align-items: stretch; gap: 0; border-radius: 14px; border: 1.5px solid var(--ss-w-line); overflow: hidden; background: var(--ss-w-panel); }
|
|
6636
|
+
/* Player card */
|
|
6637
|
+
.ss-w-hlpc { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 10px; text-align: center; }
|
|
6638
|
+
.ss-w-hlpc--b { border-left: 1px solid var(--ss-w-line); }
|
|
6639
|
+
.ss-w-hlpc-name { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.25; word-break: break-word; min-width: 0; }
|
|
6640
|
+
.ss-w-hlpc-val { font-size: 22px; font-weight: 800; color: var(--ss-w-accent); font-variant-numeric: tabular-nums; line-height: 1; }
|
|
6641
|
+
.ss-w-hlpc-val--hidden { color: var(--ss-w-faint); font-size: 26px; }
|
|
6642
|
+
.ss-w-hlpc-val--correct { color: var(--ss-w-correct); }
|
|
6643
|
+
.ss-w-hlpc-val--wrong { color: var(--ss-w-cta); }
|
|
6644
|
+
.ss-w-hlpc-badge { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; border-radius: 999px; padding: 2px 8px; }
|
|
6645
|
+
.ss-w-hlpc-badge--correct { color: #fff; background: var(--ss-w-correct); }
|
|
6646
|
+
.ss-w-hlpc-badge--wrong { color: var(--ss-w-cta-ink, #fff); background: var(--ss-w-cta); }
|
|
6647
|
+
/* Higher / Lower buttons */
|
|
6648
|
+
.ss-w-hlbtns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
6649
|
+
.ss-w-hlbtn { padding: 11px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; transition: background .1s, border-color .1s, color .1s; }
|
|
6650
|
+
.ss-w-hlbtn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); color: var(--ss-w-accent); }
|
|
6651
|
+
.ss-w-hlbtn:disabled { opacity: .5; cursor: not-allowed; }
|
|
6652
|
+
/* Answered pair result rows */
|
|
6653
|
+
.ss-w-hlresults { display: flex; flex-direction: column; gap: 4px; }
|
|
6654
|
+
.ss-w-hlrrow { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 8px; font-size: 12px; background: var(--ss-w-bubble); }
|
|
6655
|
+
.ss-w-hlrrow--correct { background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6656
|
+
.ss-w-hlrrow--wrong { background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); }
|
|
6657
|
+
.ss-w-hlrrow-names { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6658
|
+
.ss-w-hlrrow-pick { font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
6659
|
+
.ss-w-hlrrow-icon { font-size: 14px; flex: none; }
|
|
6660
|
+
|
|
6661
|
+
/* ---- Career Path game screen (D3) ---- */
|
|
6662
|
+
.ss-w-cpath { display: flex; flex-direction: column; gap: 12px; }
|
|
6663
|
+
/* Context header */
|
|
6664
|
+
.ss-w-cpath-ctx { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px; }
|
|
6665
|
+
.ss-w-cpath-ctx-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
|
|
6666
|
+
.ss-w-cpath-ctx-count { font-size: 12px; font-weight: 600; color: var(--ss-w-accent); }
|
|
6667
|
+
/* Career path: vertical timeline of club spells */
|
|
6668
|
+
.ss-w-cpath-path { display: flex; flex-direction: column; gap: 4px; }
|
|
6669
|
+
/* Single club card */
|
|
6670
|
+
.ss-w-cpath-club { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }
|
|
6671
|
+
.ss-w-cpath-club--loan { border-style: dashed; }
|
|
6672
|
+
/* Crest image / fallback */
|
|
6673
|
+
.ss-w-cpath-crest { width: 30px; height: 30px; object-fit: contain; flex: none; border-radius: 4px; }
|
|
6674
|
+
.ss-w-cpath-crest--fallback { background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; }
|
|
6675
|
+
/* Club info: name + years */
|
|
6676
|
+
.ss-w-cpath-club-info { display: flex; flex: 1; min-width: 0; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
6677
|
+
.ss-w-cpath-club-name { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6678
|
+
.ss-w-cpath-spell-yr { font-size: 11px; color: var(--ss-w-faint); font-weight: 500; white-space: nowrap; }
|
|
6679
|
+
.ss-w-cpath-loan-badge { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; padding: 1px 7px; border-radius: 999px; background: color-mix(in srgb, var(--ss-w-cta) 15%, var(--ss-w-panel)); color: var(--ss-w-cta-ink, #1b1300); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); flex: none; }
|
|
6680
|
+
/* Hidden clubs indicator */
|
|
6681
|
+
.ss-w-cpath-hidden { font-size: 11.5px; color: var(--ss-w-faint); font-style: italic; text-align: center; padding: 6px 0 2px; }
|
|
6682
|
+
/* Hint line */
|
|
6683
|
+
.ss-w-cpath-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; padding: 2px 0; font-style: italic; }
|
|
6684
|
+
/* Outcome banner */
|
|
6685
|
+
.ss-w-cpath-banner { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 12px; border-radius: 12px; text-align: center; }
|
|
6686
|
+
.ss-w-cpath-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6687
|
+
.ss-w-cpath-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6688
|
+
.ss-w-cpath-banner-name { font-size: 16px; font-weight: 750; color: var(--ss-w-ink); }
|
|
6689
|
+
.ss-w-cpath-banner-label { font-size: 12px; color: var(--ss-w-faint); }
|
|
6690
|
+
|
|
6691
|
+
/* ---- Beat the Grid game screen (D3) ---- */
|
|
6692
|
+
.ss-w-btg { display: flex; flex-direction: column; gap: 10px; }
|
|
6693
|
+
/* Score/context row */
|
|
6694
|
+
.ss-w-btg-ctx { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
|
|
6695
|
+
.ss-w-btg-ctx-score { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6696
|
+
.ss-w-btg-ctx-left { font-size: 12px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6697
|
+
.ss-w-btg-ctx-done { font-size: 12px; font-weight: 700; color: var(--ss-w-correct); }
|
|
6698
|
+
/* Grid layout \u2014 col count driven inline via style */
|
|
6699
|
+
.ss-w-btg-grid { display: grid; gap: 4px; width: 100%; }
|
|
6700
|
+
/* Generic grid cell */
|
|
6701
|
+
.ss-w-btg-gc { display: flex; align-items: center; justify-content: center; text-align: center; border-radius: 8px; min-height: 42px; padding: 4px; font-size: 11px; word-break: break-word; line-height: 1.2; }
|
|
6702
|
+
/* Corner placeholder */
|
|
6703
|
+
.ss-w-btg-gc--corner { background: none; }
|
|
6704
|
+
/* Column header */
|
|
6705
|
+
.ss-w-btg-gc--colhdr { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); }
|
|
6706
|
+
/* Row header */
|
|
6707
|
+
.ss-w-btg-gc--rowhdr { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); writing-mode: horizontal-tb; }
|
|
6708
|
+
/* Interactive cells */
|
|
6709
|
+
.ss-w-btg-cell { flex-direction: column; gap: 2px; cursor: pointer; background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-line); transition: border-color .12s, background .12s; }
|
|
6710
|
+
.ss-w-btg-cell:hover:not(:disabled) { border-color: var(--ss-w-accent); background: var(--ss-w-bubble); }
|
|
6711
|
+
.ss-w-btg-cell:disabled { cursor: not-allowed; opacity: .75; }
|
|
6712
|
+
.ss-w-btg-cell--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); }
|
|
6713
|
+
.ss-w-btg-cell--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 10%, var(--ss-w-panel)); }
|
|
6714
|
+
.ss-w-btg-cell--active { border-color: var(--ss-w-accent); }
|
|
6715
|
+
.ss-w-btg-cell-score { font-size: 14px; font-weight: 800; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6716
|
+
.ss-w-btg-cell-check { font-size: 12px; color: var(--ss-w-correct); line-height: 1; }
|
|
6717
|
+
.ss-w-btg-cell-empty { font-size: 16px; color: var(--ss-w-faint); }
|
|
6718
|
+
/* Scoped search sheet: slides up over the grid */
|
|
6719
|
+
.ss-w-btg-sheet { display: flex; flex-direction: column; gap: 10px; padding: 12px; background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-line); border-radius: 14px; box-shadow: 0 4px 20px rgba(0,0,0,.1); }
|
|
6720
|
+
.ss-w-btg-sheet-hdr { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
6721
|
+
.ss-w-btg-sheet-ctx { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
|
|
6722
|
+
.ss-w-btg-sheet-row { font-size: 12.5px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6723
|
+
.ss-w-btg-sheet-sep { font-size: 13px; color: var(--ss-w-faint); font-weight: 500; }
|
|
6724
|
+
.ss-w-btg-sheet-col { font-size: 12.5px; font-weight: 700; color: var(--ss-w-accent); }
|
|
6725
|
+
.ss-w-btg-sheet-close { background: none; border: none; cursor: pointer; font-size: 14px; color: var(--ss-w-faint); padding: 2px 6px; border-radius: 6px; line-height: 1; font: inherit; }
|
|
6726
|
+
.ss-w-btg-sheet-close:hover { color: var(--ss-w-ink); background: var(--ss-w-bubble); }
|
|
6727
|
+
|
|
6728
|
+
/* ---- Guess the XI game screen (D3) ---- */
|
|
6729
|
+
.ss-w-gxi { display: flex; flex-direction: column; gap: 12px; }
|
|
6730
|
+
/* Context label (pool label) */
|
|
6731
|
+
.ss-w-gxi-ctx { display: flex; align-items: center; }
|
|
6732
|
+
.ss-w-gxi-ctx-label { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .05em; }
|
|
6733
|
+
/* Positions pitch: compact slot grid */
|
|
6734
|
+
.ss-w-gxi-pitch { display: flex; flex-wrap: wrap; gap: 5px; }
|
|
6735
|
+
.ss-w-gxi-pslot { display: flex; flex-direction: column; align-items: center; gap: 2px; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 10px; min-width: 52px; }
|
|
6736
|
+
.ss-w-gxi-pslot-pos { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-accent); }
|
|
6737
|
+
.ss-w-gxi-pslot-nat { font-size: 10px; color: var(--ss-w-faint); font-weight: 500; text-align: center; line-height: 1.2; }
|
|
6738
|
+
/* Earned reveals */
|
|
6739
|
+
.ss-w-gxi-reveals { display: flex; flex-direction: column; gap: 4px; }
|
|
6740
|
+
.ss-w-gxi-reveal { display: flex; align-items: center; gap: 6px; padding: 7px 10px; background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 22%, var(--ss-w-line)); border-radius: 8px; }
|
|
6741
|
+
.ss-w-gxi-reveal-slot { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-cta-ink, #1b1300); background: var(--ss-w-cta); border-radius: 6px; padding: 1px 6px; flex: none; }
|
|
6742
|
+
.ss-w-gxi-reveal-val { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
|
|
6743
|
+
/* Team pool: responsive flex grid of buttons */
|
|
6744
|
+
.ss-w-gxi-pool { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6745
|
+
.ss-w-gxi-team-btn { font: inherit; font-size: 12.5px; font-weight: 650; border-radius: 10px; padding: 9px 14px; cursor: pointer; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); color: var(--ss-w-ink); transition: background .1s, border-color .1s; }
|
|
6746
|
+
.ss-w-gxi-team-btn:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6747
|
+
.ss-w-gxi-team-btn:disabled { opacity: .5; cursor: not-allowed; }
|
|
6748
|
+
.ss-w-gxi-team-btn--correct { background: color-mix(in srgb, var(--ss-w-correct) 14%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 35%, var(--ss-w-line)); color: var(--ss-w-correct); }
|
|
6749
|
+
.ss-w-gxi-team-btn--wrong { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); text-decoration: line-through; opacity: .65; }
|
|
6750
|
+
/* Outcome banner */
|
|
6751
|
+
.ss-w-gxi-banner { display: flex; align-items: center; justify-content: center; padding: 10px 12px; border-radius: 10px; }
|
|
6752
|
+
.ss-w-gxi-banner--solved { background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6753
|
+
.ss-w-gxi-banner--failed { background: color-mix(in srgb, var(--ss-w-wrong) 8%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); }
|
|
6754
|
+
.ss-w-gxi-banner-label { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }
|
|
6755
|
+
/* Hint line */
|
|
6756
|
+
.ss-w-gxi-hint { font-size: 11.5px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
6757
|
+
|
|
6758
|
+
/* ---- Daily Quiz game screen (D3) ---- */
|
|
6759
|
+
.ss-w-dq { display: flex; flex-direction: column; gap: 14px; }
|
|
6760
|
+
/* Score banner (post-reveal) */
|
|
6761
|
+
.ss-w-dq-score { display: flex; align-items: baseline; justify-content: center; gap: 4px; padding: 10px; background: color-mix(in srgb, var(--ss-w-correct) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); border-radius: 12px; }
|
|
6762
|
+
.ss-w-dq-score-val { font-size: 26px; font-weight: 800; color: var(--ss-w-correct); font-variant-numeric: tabular-nums; }
|
|
6763
|
+
.ss-w-dq-score-label { font-size: 13px; font-weight: 650; color: var(--ss-w-faint); }
|
|
6764
|
+
/* Progress bar */
|
|
6765
|
+
.ss-w-dq-prog { height: 4px; border-radius: 999px; background: var(--ss-w-bubble); overflow: hidden; }
|
|
6766
|
+
.ss-w-dq-prog-fill { height: 100%; border-radius: 999px; background: var(--ss-w-accent); transition: width .25s ease; }
|
|
6767
|
+
/* Questions list */
|
|
6768
|
+
.ss-w-dq-questions { display: flex; flex-direction: column; gap: 16px; }
|
|
6769
|
+
/* Single question */
|
|
6770
|
+
.ss-w-dq-q { display: flex; flex-direction: column; gap: 8px; }
|
|
6771
|
+
.ss-w-dq-qstem { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.4; }
|
|
6772
|
+
/* Options grid: 2 across */
|
|
6773
|
+
.ss-w-dq-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
|
|
6774
|
+
.ss-w-dq-qopt { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12.5px; cursor: pointer; text-align: left; color: var(--ss-w-ink); transition: background .1s, border-color .1s; }
|
|
6775
|
+
.ss-w-dq-qopt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6776
|
+
.ss-w-dq-qopt:disabled { cursor: not-allowed; }
|
|
6777
|
+
.ss-w-dq-qopt--selected { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); }
|
|
6778
|
+
.ss-w-dq-qopt--correct { border-color: var(--ss-w-correct); background: color-mix(in srgb, var(--ss-w-correct) 12%, var(--ss-w-panel)); color: var(--ss-w-correct); }
|
|
6779
|
+
.ss-w-dq-qopt--wrong { border-color: color-mix(in srgb, var(--ss-w-cta) 50%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-cta) 8%, var(--ss-w-panel)); opacity: .75; }
|
|
6780
|
+
/* Option letter badge */
|
|
6781
|
+
.ss-w-dq-qopt-letter { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); font-size: 10px; font-weight: 800; display: flex; align-items: center; justify-content: center; color: var(--ss-w-faint); }
|
|
6782
|
+
.ss-w-dq-qopt-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6783
|
+
/* Why/reveal text */
|
|
6784
|
+
.ss-w-dq-qwhy { font-size: 11.5px; padding: 6px 10px; border-radius: 8px; line-height: 1.4; }
|
|
6785
|
+
.ss-w-dq-qwhy--correct { background: color-mix(in srgb, var(--ss-w-correct) 9%, var(--ss-w-panel)); color: var(--ss-w-correct); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 22%, var(--ss-w-line)); }
|
|
6786
|
+
.ss-w-dq-qwhy--wrong { background: var(--ss-w-bubble); color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); }
|
|
6787
|
+
/* Submit button */
|
|
6788
|
+
.ss-w-dq-submit { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6789
|
+
.ss-w-dq-submit:disabled { opacity: .4; cursor: not-allowed; }
|
|
6790
|
+
.ss-w-dq-submit:hover:not(:disabled) { opacity: .88; }
|
|
6791
|
+
|
|
6792
|
+
/* \u2500\u2500 Matchday Predictor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6793
|
+
.ss-w-mp { display: flex; flex-direction: column; gap: 14px; }
|
|
6794
|
+
/* Score prediction row */
|
|
6795
|
+
.ss-w-mp-pred-score { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 12px 0; }
|
|
6796
|
+
.ss-w-mp-team { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; min-width: 0; }
|
|
6797
|
+
.ss-w-mp-team-name { font-size: 12px; font-weight: 650; color: var(--ss-w-ink); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
|
|
6798
|
+
.ss-w-mp-stepper { display: flex; align-items: center; gap: 8px; }
|
|
6799
|
+
.ss-w-mp-stepper-btn { width: 32px; height: 32px; border-radius: 50%; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 18px; font-weight: 700; color: var(--ss-w-ink); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background .1s; }
|
|
6800
|
+
.ss-w-mp-stepper-btn:hover:not(:disabled) { background: var(--ss-w-bubble); }
|
|
6801
|
+
.ss-w-mp-stepper-btn:disabled { opacity: .35; cursor: not-allowed; }
|
|
6802
|
+
.ss-w-mp-stepper-val { font-size: 26px; font-weight: 800; color: var(--ss-w-ink); min-width: 28px; text-align: center; font-variant-numeric: tabular-nums; }
|
|
6803
|
+
.ss-w-mp-sep { font-size: 22px; font-weight: 700; color: var(--ss-w-faint); padding: 0 4px; }
|
|
6804
|
+
/* First-scorer picker */
|
|
6805
|
+
.ss-w-mp-scorer { display: flex; flex-direction: column; gap: 6px; }
|
|
6806
|
+
.ss-w-mp-scorer-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }
|
|
6807
|
+
.ss-w-mp-scorer-list { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6808
|
+
.ss-w-mp-scorer-opt { padding: 6px 12px; border-radius: 999px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-ink); cursor: pointer; transition: background .1s, border-color .1s; }
|
|
6809
|
+
.ss-w-mp-scorer-opt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6810
|
+
.ss-w-mp-scorer-opt--selected { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); color: var(--ss-w-accent); }
|
|
6811
|
+
.ss-w-mp-scorer-opt:disabled { opacity: .35; cursor: not-allowed; }
|
|
6812
|
+
/* Save button */
|
|
6813
|
+
.ss-w-mp-savebtn { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6814
|
+
.ss-w-mp-savebtn:disabled { opacity: .4; cursor: not-allowed; }
|
|
6815
|
+
.ss-w-mp-savebtn:hover:not(:disabled) { opacity: .88; }
|
|
6816
|
+
/* Live / pending state */
|
|
6817
|
+
.ss-w-mp-live { display: flex; flex-direction: column; gap: 10px; align-items: center; text-align: center; padding: 14px 0; }
|
|
6818
|
+
.ss-w-mp-live-score { font-size: 30px; font-weight: 800; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6819
|
+
.ss-w-mp-live-label { font-size: 12px; color: var(--ss-w-faint); font-style: italic; }
|
|
6820
|
+
.ss-w-mp-live-outcome { display: flex; flex-direction: column; gap: 6px; width: 100%; }
|
|
6821
|
+
.ss-w-mp-live-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 12px; border-radius: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); font-size: 12.5px; }
|
|
6822
|
+
.ss-w-mp-live-row--correct { border-color: color-mix(in srgb, var(--ss-w-correct) 40%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6823
|
+
.ss-w-mp-live-row-key { color: var(--ss-w-faint); font-weight: 600; }
|
|
6824
|
+
.ss-w-mp-live-row-val { font-weight: 700; color: var(--ss-w-ink); }
|
|
6825
|
+
.ss-w-mp-live-row--correct .ss-w-mp-live-row-val { color: var(--ss-w-correct); }
|
|
6826
|
+
/* For-fun note */
|
|
6827
|
+
.ss-w-mp-fun { font-size: 11px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
6828
|
+
|
|
6829
|
+
/* \u2500\u2500 Starting XI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6830
|
+
.ss-w-sxi { display: flex; flex-direction: column; gap: 14px; }
|
|
6831
|
+
.ss-w-sxi-formation { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6832
|
+
/* Formation pitch area */
|
|
6833
|
+
.ss-w-sxi-pitch { display: flex; flex-direction: column; gap: 10px; padding: 12px 8px; border-radius: 12px; background: color-mix(in srgb, var(--ss-w-accent) 4%, var(--ss-w-panel)); border: 1px solid var(--ss-w-line); min-height: 260px; }
|
|
6834
|
+
.ss-w-sxi-pitch-row { display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; }
|
|
6835
|
+
/* Player slot */
|
|
6836
|
+
.ss-w-sxi-pslot { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 64px; cursor: pointer; }
|
|
6837
|
+
.ss-w-sxi-pslot-num { width: 36px; height: 36px; border-radius: 50%; border: 2px dashed var(--ss-w-line); background: var(--ss-w-bubble); display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: var(--ss-w-faint); transition: border-color .1s, background .1s; }
|
|
6838
|
+
.ss-w-sxi-pslot--filled .ss-w-sxi-pslot-num { border-style: solid; border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); color: var(--ss-w-accent); }
|
|
6839
|
+
.ss-w-sxi-pslot-name { font-size: 9.5px; font-weight: 600; color: var(--ss-w-ink); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
|
|
6840
|
+
/* Squad picker */
|
|
6841
|
+
.ss-w-sxi-squad { display: flex; flex-direction: column; gap: 4px; max-height: 200px; overflow-y: auto; }
|
|
6842
|
+
.ss-w-sxi-squad-row { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border-radius: 8px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); cursor: pointer; transition: background .1s; }
|
|
6843
|
+
.ss-w-sxi-squad-row:hover:not(.ss-w-sxi-squad-row--picked) { background: var(--ss-w-bubble); }
|
|
6844
|
+
.ss-w-sxi-squad-row--picked { background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); border-color: var(--ss-w-accent); }
|
|
6845
|
+
.ss-w-sxi-squad-name { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }
|
|
6846
|
+
.ss-w-sxi-squad-pos { font-size: 10.5px; color: var(--ss-w-faint); }
|
|
6847
|
+
.ss-w-sxi-savebtn { width: 100%; padding: 13px; border-radius: 12px; border: none; background: var(--ss-w-accent); color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: opacity .15s; }
|
|
6848
|
+
.ss-w-sxi-savebtn:disabled { opacity: .4; cursor: not-allowed; }
|
|
6849
|
+
.ss-w-sxi-savebtn:hover:not(:disabled) { opacity: .88; }
|
|
6850
|
+
/* Pending / graded states */
|
|
6851
|
+
.ss-w-sxi-status { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 14px 12px; border-radius: 12px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); text-align: center; }
|
|
6852
|
+
.ss-w-sxi-status--graded { background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); border-color: color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); }
|
|
6853
|
+
.ss-w-sxi-status-score { font-size: 28px; font-weight: 800; color: var(--ss-w-correct); font-variant-numeric: tabular-nums; }
|
|
6854
|
+
.ss-w-sxi-status-label { font-size: 12.5px; color: var(--ss-w-faint); }
|
|
6855
|
+
|
|
6856
|
+
/* \u2500\u2500 Stat Ladder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6857
|
+
.ss-w-sl { display: flex; flex-direction: column; gap: 14px; }
|
|
6858
|
+
.ss-w-sl-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6859
|
+
/* Ladder list */
|
|
6860
|
+
.ss-w-sl-ladder { display: flex; flex-direction: column; gap: 6px; }
|
|
6861
|
+
.ss-w-sl-lrow { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); }
|
|
6862
|
+
.ss-w-sl-lrow-rank { font-size: 11px; font-weight: 800; color: var(--ss-w-faint); width: 18px; flex: none; text-align: center; }
|
|
6863
|
+
.ss-w-sl-lrow-name { flex: 1; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); }
|
|
6864
|
+
.ss-w-sl-lrow-stat { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); font-variant-numeric: tabular-nums; }
|
|
6865
|
+
/* Mystery rung */
|
|
6866
|
+
.ss-w-sl-mystery { border: 1.5px dashed var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 5%, var(--ss-w-panel)); }
|
|
6867
|
+
.ss-w-sl-mystery .ss-w-sl-lrow-name { color: var(--ss-w-faint); font-style: italic; }
|
|
6868
|
+
/* Reveal overlay: correct / wrong */
|
|
6869
|
+
.ss-w-sl-lrow--correct { border-color: color-mix(in srgb, var(--ss-w-correct) 40%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-correct) 8%, var(--ss-w-panel)); }
|
|
6870
|
+
.ss-w-sl-lrow--wrong { border-color: color-mix(in srgb, var(--ss-w-wrong, #e05050) 30%, var(--ss-w-line)); background: color-mix(in srgb, var(--ss-w-wrong, #e05050) 6%, var(--ss-w-panel)); }
|
|
6871
|
+
/* Player picker */
|
|
6872
|
+
.ss-w-sl-picker { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
6873
|
+
.ss-w-sl-picker-opt { padding: 6px 12px; border-radius: 999px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-ink); cursor: pointer; transition: background .1s, border-color .1s; }
|
|
6874
|
+
.ss-w-sl-picker-opt:hover:not(:disabled) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6875
|
+
.ss-w-sl-picker-opt:disabled { opacity: .35; cursor: not-allowed; }
|
|
6876
|
+
.ss-w-sl-reveal { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 12px; border-radius: 12px; text-align: center; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); }
|
|
6877
|
+
.ss-w-sl-reveal--correct { background: color-mix(in srgb, var(--ss-w-correct) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-correct) 28%, var(--ss-w-line)); color: var(--ss-w-correct); }
|
|
6878
|
+
.ss-w-sl-reveal--wrong { background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); }
|
|
6879
|
+
|
|
6880
|
+
/* \u2500\u2500 Fan MOTM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
6881
|
+
.ss-w-motm { display: flex; flex-direction: column; gap: 14px; }
|
|
6882
|
+
.ss-w-motm-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); text-align: center; }
|
|
6883
|
+
/* Vote candidate list */
|
|
6884
|
+
.ss-w-motm-votes { display: flex; flex-direction: column; gap: 6px; }
|
|
6885
|
+
.ss-w-motm-vrow { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-radius: 10px; border: 1.5px solid var(--ss-w-line); background: var(--ss-w-panel); cursor: pointer; transition: background .1s, border-color .1s; position: relative; overflow: hidden; }
|
|
6886
|
+
.ss-w-motm-vrow:hover:not(.ss-w-motm-vrow--voted):not(.ss-w-motm-vrow--result) { background: var(--ss-w-bubble); border-color: var(--ss-w-accent); }
|
|
6887
|
+
.ss-w-motm-vrow--voted { border-color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); cursor: default; }
|
|
6888
|
+
.ss-w-motm-vrow--result { cursor: default; }
|
|
6889
|
+
.ss-w-motm-vrow-name { flex: 1; font-size: 13px; font-weight: 650; color: var(--ss-w-ink); position: relative; z-index: 1; }
|
|
6890
|
+
.ss-w-motm-vrow-pct { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
|
|
6891
|
+
/* Share fill bar (behind content) */
|
|
6892
|
+
.ss-w-motm-vfill { position: absolute; top: 0; left: 0; height: 100%; background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); transition: width .4s ease; pointer-events: none; }
|
|
6893
|
+
.ss-w-motm-vrow--voted .ss-w-motm-vfill { background: color-mix(in srgb, var(--ss-w-accent) 18%, var(--ss-w-panel)); }
|
|
6894
|
+
/* For-fun note */
|
|
6895
|
+
.ss-w-motm-fun { font-size: 11px; color: var(--ss-w-faint); text-align: center; font-style: italic; }
|
|
4747
6896
|
`;
|
|
4748
6897
|
|
|
4749
6898
|
// src/StatsWidget.tsx
|
|
4750
|
-
import { jsx as
|
|
6899
|
+
import { jsx as jsx71 } from "react/jsx-runtime";
|
|
4751
6900
|
function buildClient(props) {
|
|
4752
6901
|
try {
|
|
4753
6902
|
if ("client" in props && props.client) {
|
|
@@ -4781,14 +6930,14 @@ function StatsWidget(props) {
|
|
|
4781
6930
|
[built?.client]
|
|
4782
6931
|
);
|
|
4783
6932
|
const ui = useMemo3(() => normalizeUi(props.config ?? { operatorId: "", publicKey: "" }), [props.config]);
|
|
4784
|
-
const rootRef =
|
|
4785
|
-
const introDoneRef =
|
|
4786
|
-
const markIntroDone =
|
|
6933
|
+
const rootRef = useRef13(null);
|
|
6934
|
+
const introDoneRef = useRef13(false);
|
|
6935
|
+
const markIntroDone = useCallback9(() => {
|
|
4787
6936
|
introDoneRef.current = true;
|
|
4788
6937
|
}, []);
|
|
4789
6938
|
const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ""}:${cfg?.userContext?.operatorUserId ?? "anon"}`;
|
|
4790
6939
|
const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : void 0, convStorageKey);
|
|
4791
|
-
const [hasToday, setHasToday] =
|
|
6940
|
+
const [hasToday, setHasToday] = useState33(false);
|
|
4792
6941
|
const monitor = useLiveMonitor({
|
|
4793
6942
|
getLiveMonitor: (pins) => built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null),
|
|
4794
6943
|
getMarketOdds: (matchId, dev) => built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null),
|
|
@@ -4796,11 +6945,11 @@ function StatsWidget(props) {
|
|
|
4796
6945
|
isOpen: controller.state.isOpen,
|
|
4797
6946
|
hasToday
|
|
4798
6947
|
});
|
|
4799
|
-
const getSchedule =
|
|
6948
|
+
const getSchedule = useCallback9(
|
|
4800
6949
|
(localDate, utcOffsetMinutes) => built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),
|
|
4801
6950
|
[built]
|
|
4802
6951
|
);
|
|
4803
|
-
const getStates =
|
|
6952
|
+
const getStates = useCallback9(
|
|
4804
6953
|
(matchIds) => built ? built.conversation.getStates(matchIds) : Promise.resolve(null),
|
|
4805
6954
|
[built]
|
|
4806
6955
|
);
|
|
@@ -4816,12 +6965,14 @@ function StatsWidget(props) {
|
|
|
4816
6965
|
pinnedMatchIds
|
|
4817
6966
|
});
|
|
4818
6967
|
const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0;
|
|
4819
|
-
|
|
6968
|
+
useEffect15(() => {
|
|
4820
6969
|
setHasToday(todayHasContent);
|
|
4821
6970
|
}, [todayHasContent]);
|
|
6971
|
+
const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
6972
|
+
const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab });
|
|
4822
6973
|
const markTodayActivity = monitor.markTodayActivity;
|
|
4823
|
-
const prevLiveCountRef =
|
|
4824
|
-
|
|
6974
|
+
const prevLiveCountRef = useRef13(0);
|
|
6975
|
+
useEffect15(() => {
|
|
4825
6976
|
const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0;
|
|
4826
6977
|
prevLiveCountRef.current = discovery.liveCount;
|
|
4827
6978
|
if (rose) markTodayActivity();
|
|
@@ -4856,11 +7007,11 @@ function StatsWidget(props) {
|
|
|
4856
7007
|
const operatorUserId = cfg?.userContext?.operatorUserId;
|
|
4857
7008
|
const anonymousUserId = cfg?.userContext?.anonymousUserId;
|
|
4858
7009
|
const conversationId = controller.state.conversationId ?? void 0;
|
|
4859
|
-
|
|
7010
|
+
useEffect15(() => {
|
|
4860
7011
|
if (!logger) return;
|
|
4861
7012
|
logger.setIdentity({ operatorUserId, anonymousUserId, conversationId });
|
|
4862
7013
|
}, [logger, operatorUserId, anonymousUserId, conversationId]);
|
|
4863
|
-
|
|
7014
|
+
useEffect15(() => {
|
|
4864
7015
|
if (!logger) return;
|
|
4865
7016
|
const onHide = () => {
|
|
4866
7017
|
logger.flushOnHide();
|
|
@@ -4877,14 +7028,27 @@ function StatsWidget(props) {
|
|
|
4877
7028
|
logger.dispose();
|
|
4878
7029
|
};
|
|
4879
7030
|
}, [logger]);
|
|
4880
|
-
|
|
7031
|
+
useEffect15(() => {
|
|
4881
7032
|
if (!built || !ui.injectStyles) return;
|
|
4882
7033
|
const node = rootRef.current?.getRootNode();
|
|
4883
7034
|
if (node) injectStyles(node);
|
|
4884
7035
|
}, [built, ui.injectStyles]);
|
|
4885
7036
|
if (!built) return null;
|
|
4886
7037
|
const attrs = themeAttrs(ui);
|
|
4887
|
-
return /* @__PURE__ */
|
|
7038
|
+
return /* @__PURE__ */ jsx71(EventLogContext.Provider, { value: logger, children: /* @__PURE__ */ jsx71("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__ */ jsx71(
|
|
7039
|
+
ChatPanel,
|
|
7040
|
+
{
|
|
7041
|
+
controller,
|
|
7042
|
+
ui,
|
|
7043
|
+
slip,
|
|
7044
|
+
onDashboardTap,
|
|
7045
|
+
monitor: monitor.enabled ? monitor : void 0,
|
|
7046
|
+
discovery,
|
|
7047
|
+
gamesResult,
|
|
7048
|
+
leaderboardResult,
|
|
7049
|
+
loggedIn: !!operatorUserId
|
|
7050
|
+
}
|
|
7051
|
+
) : /* @__PURE__ */ jsx71(
|
|
4888
7052
|
ChatFab,
|
|
4889
7053
|
{
|
|
4890
7054
|
label: ui.launcherLabel,
|