@sensiblestats/widget-react 0.16.0 → 0.17.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 +11 -0
- package/dist/index.cjs +124 -38
- 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 +129 -43
- package/dist/index.js.map +1 -1
- package/dist/styles.css +36 -11
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
import { useEffect as useEffect6, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
3
3
|
import { StatsWidgetClient } from "@sensiblestats/widget-sdk";
|
|
4
4
|
|
|
5
|
+
// src/kickoff.ts
|
|
6
|
+
function formatBettingKickoff(kickoffUtc, ui, locale, now = /* @__PURE__ */ new Date()) {
|
|
7
|
+
const at = new Date(kickoffUtc);
|
|
8
|
+
const intlLocale = locale === "tr" ? "tr-TR" : "en-GB";
|
|
9
|
+
const time = new Intl.DateTimeFormat(intlLocale, { hour: "2-digit", minute: "2-digit" }).format(at);
|
|
10
|
+
const atLocalDate = new Date(at.getFullYear(), at.getMonth(), at.getDate());
|
|
11
|
+
const nowLocalDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
12
|
+
const dayDiff = Math.round((atLocalDate.getTime() - nowLocalDate.getTime()) / 864e5);
|
|
13
|
+
const dayLabel = dayDiff === 0 ? ui.today : dayDiff === 1 ? ui.tomorrow : new Intl.DateTimeFormat(intlLocale, { weekday: "short", day: "numeric", month: "short" }).format(at);
|
|
14
|
+
return { dayLabel, time };
|
|
15
|
+
}
|
|
16
|
+
|
|
5
17
|
// src/i18n.ts
|
|
6
18
|
var STRINGS = {
|
|
7
19
|
en: {
|
|
@@ -56,7 +68,10 @@ var STRINGS = {
|
|
|
56
68
|
slipPriceNotAccepted: (from, to) => `Price moved to ${to} (was ${from}). Tap to add.`,
|
|
57
69
|
slipLoginRequired: "Sign in to add to your slip",
|
|
58
70
|
slipSuspended: "Market suspended",
|
|
59
|
-
slipFailed: "Couldn't add to slip. Try again."
|
|
71
|
+
slipFailed: "Couldn't add to slip. Try again.",
|
|
72
|
+
today: "Today",
|
|
73
|
+
tomorrow: "Tomorrow",
|
|
74
|
+
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, "en", now)
|
|
60
75
|
},
|
|
61
76
|
tr: {
|
|
62
77
|
launcherLabel: "SensibleStats ile sohbet et",
|
|
@@ -110,7 +125,10 @@ var STRINGS = {
|
|
|
110
125
|
slipPriceNotAccepted: (from, to) => `Oran ${to} oldu (\xF6nceki ${from}). Eklemek i\xE7in dokunun.`,
|
|
111
126
|
slipLoginRequired: "Kupona eklemek i\xE7in giri\u015F yap\u0131n",
|
|
112
127
|
slipSuspended: "Bu market ask\u0131ya al\u0131nd\u0131",
|
|
113
|
-
slipFailed: "Kupona eklenemedi. Tekrar deneyin."
|
|
128
|
+
slipFailed: "Kupona eklenemedi. Tekrar deneyin.",
|
|
129
|
+
today: "Bug\xFCn",
|
|
130
|
+
tomorrow: "Yar\u0131n",
|
|
131
|
+
bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, "tr", now)
|
|
114
132
|
}
|
|
115
133
|
};
|
|
116
134
|
function resolveLocaleStrings(locale) {
|
|
@@ -177,7 +195,10 @@ function normalizeUi(cfg) {
|
|
|
177
195
|
slipPriceNotAccepted: strings.slipPriceNotAccepted,
|
|
178
196
|
slipLoginRequired: strings.slipLoginRequired,
|
|
179
197
|
slipSuspended: strings.slipSuspended,
|
|
180
|
-
slipFailed: strings.slipFailed
|
|
198
|
+
slipFailed: strings.slipFailed,
|
|
199
|
+
today: strings.today,
|
|
200
|
+
tomorrow: strings.tomorrow,
|
|
201
|
+
bettingKickoff: strings.bettingKickoff
|
|
181
202
|
};
|
|
182
203
|
}
|
|
183
204
|
function toClientOptions(cfg) {
|
|
@@ -366,7 +387,13 @@ function toInsightVM(insight) {
|
|
|
366
387
|
oddsDecimal: typeof oddsValue === "number" && Number.isFinite(oddsValue) ? oddsValue : void 0,
|
|
367
388
|
quotedAtUtc: str(insight.odds?.quotedAtUtc),
|
|
368
389
|
previousOdds: previous !== void 0 && direction !== void 0 ? previous.toFixed(2) : void 0,
|
|
369
|
-
movementDirection: previous !== void 0 && direction !== void 0 ? direction : void 0
|
|
390
|
+
movementDirection: previous !== void 0 && direction !== void 0 ? direction : void 0,
|
|
391
|
+
homeTeamName: home,
|
|
392
|
+
awayTeamName: away,
|
|
393
|
+
homeCrest: str(insight.homeTeamImagePath),
|
|
394
|
+
awayCrest: str(insight.awayTeamImagePath),
|
|
395
|
+
competitionCrest: str(insight.competitionImagePath),
|
|
396
|
+
kickoffUtc: str(insight.kickoffUtc)
|
|
370
397
|
};
|
|
371
398
|
}
|
|
372
399
|
function toSlipSelection(vm, conversationId) {
|
|
@@ -941,7 +968,7 @@ function OddsMovementBadge({
|
|
|
941
968
|
}
|
|
942
969
|
|
|
943
970
|
// src/components/BettingInsightList.tsx
|
|
944
|
-
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
971
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
945
972
|
function StatRows2({ stats }) {
|
|
946
973
|
return /* @__PURE__ */ jsx10("div", { className: "ss-w-bi-rows", children: stats.map((s) => /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-row", children: [
|
|
947
974
|
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-row-lbl", children: s.label }),
|
|
@@ -956,10 +983,21 @@ function ScopedStats({ scopes }) {
|
|
|
956
983
|
/* @__PURE__ */ jsx10(StatRows2, { stats: current.stats }, current.key)
|
|
957
984
|
] });
|
|
958
985
|
}
|
|
986
|
+
function hasStatsContent(it) {
|
|
987
|
+
return !!it.scopes && it.scopes.length >= 2 || it.stats.length > 0;
|
|
988
|
+
}
|
|
989
|
+
function initials2(name) {
|
|
990
|
+
return (name ?? "").trim().slice(0, 1).toUpperCase() || "?";
|
|
991
|
+
}
|
|
992
|
+
function Crest2({ url, name, kind }) {
|
|
993
|
+
const cls = kind === "comp" ? "ss-w-bi-comp-logo" : "ss-w-bi-crest";
|
|
994
|
+
if (url) return /* @__PURE__ */ jsx10("span", { className: cls, style: { backgroundImage: `url(${url})` }, "aria-hidden": "true" });
|
|
995
|
+
return /* @__PURE__ */ jsx10("span", { className: `${cls} ss-w-bi-crest-mono`, "aria-hidden": "true", children: initials2(name) });
|
|
996
|
+
}
|
|
959
997
|
function StatsDisclosure({ it, ui }) {
|
|
960
998
|
const [open, setOpen] = useState3(false);
|
|
961
999
|
const hasScopes = !!it.scopes && it.scopes.length >= 2;
|
|
962
|
-
const hasStats =
|
|
1000
|
+
const hasStats = hasStatsContent(it);
|
|
963
1001
|
if (!hasStats) return null;
|
|
964
1002
|
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-stats", children: [
|
|
965
1003
|
/* @__PURE__ */ jsxs7(
|
|
@@ -980,24 +1018,42 @@ function StatsDisclosure({ it, ui }) {
|
|
|
980
1018
|
}
|
|
981
1019
|
function InsightCard({ it, ui, slip }) {
|
|
982
1020
|
const live = it.isLive || it.phase === "live";
|
|
1021
|
+
const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : void 0;
|
|
1022
|
+
const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName;
|
|
1023
|
+
const showHeader = !!it.competition || live || !!kickoff;
|
|
1024
|
+
const showReason = !!it.text || hasStatsContent(it);
|
|
983
1025
|
return /* @__PURE__ */ jsxs7("div", { className: "ss-w-binsight", children: [
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
/* @__PURE__ */ jsx10(
|
|
987
|
-
|
|
988
|
-
] }) : null,
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1026
|
+
showHeader ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-header", children: [
|
|
1027
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-header-left", children: it.competition ? /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1028
|
+
/* @__PURE__ */ jsx10(Crest2, { kind: "comp", url: it.competitionCrest, name: it.competition }),
|
|
1029
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-comp", children: it.competition })
|
|
1030
|
+
] }) : null }),
|
|
1031
|
+
/* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-header-right", children: [
|
|
1032
|
+
live ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-live", children: [
|
|
1033
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
|
|
1034
|
+
ui?.liveLabel ?? "Live"
|
|
1035
|
+
] }) : null,
|
|
1036
|
+
kickoff ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-kick", children: [
|
|
1037
|
+
kickoff.dayLabel,
|
|
1038
|
+
" ",
|
|
1039
|
+
kickoff.time
|
|
998
1040
|
] }) : null
|
|
999
|
-
] })
|
|
1041
|
+
] })
|
|
1042
|
+
] }) : null,
|
|
1043
|
+
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-body", children: [
|
|
1044
|
+
/* @__PURE__ */ jsx10("div", { className: "ss-w-bi-fixture", children: hasNamedTeams ? /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1045
|
+
/* @__PURE__ */ jsx10(Crest2, { kind: "team", url: it.homeCrest, name: it.homeTeamName }),
|
|
1046
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-team", children: it.homeTeamName }),
|
|
1047
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-vs", "aria-hidden": "true", children: "vs" }),
|
|
1048
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-team", children: it.awayTeamName }),
|
|
1049
|
+
/* @__PURE__ */ jsx10(Crest2, { kind: "team", url: it.awayCrest, name: it.awayTeamName })
|
|
1050
|
+
] }) : it.fixture ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-fixture-txt", children: it.fixture }) : null }),
|
|
1000
1051
|
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-action", children: [
|
|
1052
|
+
/* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-mkt", children: [
|
|
1053
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-market", children: it.market }),
|
|
1054
|
+
it.selection ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-sel", children: it.selection }) : null
|
|
1055
|
+
] }),
|
|
1056
|
+
it.isMarketFloor ? /* @__PURE__ */ jsx10("span", { className: "ss-w-bi-floor", children: ui?.marketFloorLabel ?? "Market price \xB7 not a value pick" }) : null,
|
|
1001
1057
|
it.odds ? /* @__PURE__ */ jsxs7("span", { className: "ss-w-bi-odds", children: [
|
|
1002
1058
|
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
|
|
1003
1059
|
/* @__PURE__ */ jsx10("b", { children: it.odds }),
|
|
@@ -1007,8 +1063,13 @@ function InsightCard({ it, ui, slip }) {
|
|
|
1007
1063
|
/* @__PURE__ */ jsx10(AddToSlipButton, { it, slip, ui })
|
|
1008
1064
|
] })
|
|
1009
1065
|
] }),
|
|
1010
|
-
|
|
1011
|
-
|
|
1066
|
+
showReason ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason", children: [
|
|
1067
|
+
/* @__PURE__ */ jsx10("span", { className: "ss-w-bi-chart", "aria-hidden": "true" }),
|
|
1068
|
+
/* @__PURE__ */ jsxs7("div", { className: "ss-w-bi-reason-body", children: [
|
|
1069
|
+
it.text ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-text", children: it.text }) : null,
|
|
1070
|
+
/* @__PURE__ */ jsx10(StatsDisclosure, { it, ui })
|
|
1071
|
+
] })
|
|
1072
|
+
] }) : null,
|
|
1012
1073
|
it.disclaimer ? /* @__PURE__ */ jsx10("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
|
|
1013
1074
|
] });
|
|
1014
1075
|
}
|
|
@@ -1058,7 +1119,7 @@ function MarketOddsCardList({ cards, ui, slip }) {
|
|
|
1058
1119
|
}
|
|
1059
1120
|
|
|
1060
1121
|
// src/components/OddsMovementCard.tsx
|
|
1061
|
-
import { Fragment, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1122
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1062
1123
|
function directionWord(vm, ui) {
|
|
1063
1124
|
if (vm.direction === "shortened") return ui?.oddsShortened ?? "shortened";
|
|
1064
1125
|
if (vm.direction === "drifted") return ui?.oddsDrifted ?? "drifted";
|
|
@@ -1094,7 +1155,7 @@ function OddsMovementCard({ vm, ui }) {
|
|
|
1094
1155
|
] }, g.price)),
|
|
1095
1156
|
/* @__PURE__ */ jsx12("path", { className: "ss-w-om-line", d: vm.geometry.path, fill: "none" }),
|
|
1096
1157
|
vm.geometry.markers.map((m, i) => /* @__PURE__ */ jsx12("circle", { className: "ss-w-om-dot", cx: m.x, cy: m.y, r: 2.5 }, i)),
|
|
1097
|
-
ui?.chartTimeLabel ? /* @__PURE__ */ jsxs9(
|
|
1158
|
+
ui?.chartTimeLabel ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1098
1159
|
/* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, textAnchor: "start", children: ui.chartTimeLabel(vm.geometry.startMs) }),
|
|
1099
1160
|
/* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: CHART_VIEW_W - 8, y: CHART_VIEW_H - 8, textAnchor: "end", children: ui.chartTimeLabel(vm.geometry.endMs) })
|
|
1100
1161
|
] }) : /* @__PURE__ */ jsx12("text", { className: "ss-w-om-xlab", x: 40, y: CHART_VIEW_H - 8, children: ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h` })
|
|
@@ -1125,12 +1186,12 @@ function OddsMovementCardList({ cards, ui }) {
|
|
|
1125
1186
|
}
|
|
1126
1187
|
|
|
1127
1188
|
// src/components/ActionButtons.tsx
|
|
1128
|
-
import { Fragment as
|
|
1189
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1129
1190
|
function ActionButtons({ actions, loading, disabled, onAct }) {
|
|
1130
1191
|
if (actions.length === 0 && !loading) return null;
|
|
1131
1192
|
return /* @__PURE__ */ jsxs10("div", { className: "ss-w-actions", children: [
|
|
1132
1193
|
actions.map((a, i) => /* @__PURE__ */ jsx13("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
|
|
1133
|
-
actions.length === 0 && loading ? /* @__PURE__ */ jsxs10(
|
|
1194
|
+
actions.length === 0 && loading ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
1134
1195
|
/* @__PURE__ */ jsx13("span", { className: "ss-w-abtn-shimmer" }),
|
|
1135
1196
|
/* @__PURE__ */ jsx13("span", { className: "ss-w-abtn-shimmer" })
|
|
1136
1197
|
] }) : null
|
|
@@ -1196,13 +1257,13 @@ function GreetingHeaderBlock({ block }) {
|
|
|
1196
1257
|
// src/components/club-dashboard/FixtureHeroBlock.tsx
|
|
1197
1258
|
import { useState as useState5 } from "react";
|
|
1198
1259
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1199
|
-
function
|
|
1260
|
+
function initials3(name) {
|
|
1200
1261
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
1201
1262
|
}
|
|
1202
|
-
function
|
|
1263
|
+
function Crest3({ url, name }) {
|
|
1203
1264
|
const [broken, setBroken] = useState5(false);
|
|
1204
1265
|
if (!url || broken) {
|
|
1205
|
-
return /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children:
|
|
1266
|
+
return /* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-crest ss-w-cdash-crest--fallback", "aria-hidden": "true", children: initials3(name) });
|
|
1206
1267
|
}
|
|
1207
1268
|
return /* @__PURE__ */ jsx17("img", { className: "ss-w-cdash-crest", src: url, alt: "", "aria-hidden": "true", onError: () => setBroken(true) });
|
|
1208
1269
|
}
|
|
@@ -1213,11 +1274,11 @@ function FixtureHeroBlock({
|
|
|
1213
1274
|
}) {
|
|
1214
1275
|
return /* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-fixture", children: [
|
|
1215
1276
|
/* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-tie", children: [
|
|
1216
|
-
/* @__PURE__ */ jsx17(
|
|
1277
|
+
/* @__PURE__ */ jsx17(Crest3, { url: block.homeCrestUrl, name: block.homeName }),
|
|
1217
1278
|
/* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-team", children: block.homeName }),
|
|
1218
1279
|
/* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-vs", children: "v" }),
|
|
1219
1280
|
/* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-team", children: block.awayName }),
|
|
1220
|
-
/* @__PURE__ */ jsx17(
|
|
1281
|
+
/* @__PURE__ */ jsx17(Crest3, { url: block.awayCrestUrl, name: block.awayName })
|
|
1221
1282
|
] }),
|
|
1222
1283
|
/* @__PURE__ */ jsxs14("div", { className: "ss-w-cdash-fixture-meta", children: [
|
|
1223
1284
|
/* @__PURE__ */ jsx17("span", { className: "ss-w-cdash-kickoff", children: ui.clubKickoff(block.kickoffUnix * 1e3) }),
|
|
@@ -1611,26 +1672,51 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
|
|
|
1611
1672
|
|
|
1612
1673
|
/* betting insights */
|
|
1613
1674
|
.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }
|
|
1614
|
-
.ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap:
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
.ss-w-bi-
|
|
1675
|
+
.ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 8px; }
|
|
1676
|
+
|
|
1677
|
+
/* row 1: competition logo + name on the left, live badge + kickoff on the right */
|
|
1678
|
+
.ss-w-bi-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); }
|
|
1679
|
+
.ss-w-bi-header-left { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
|
|
1680
|
+
.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }
|
|
1681
|
+
.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1682
|
+
.ss-w-bi-kick { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); white-space: nowrap; flex: none; }
|
|
1618
1683
|
.ss-w-bi-live { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: #c0392b; border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; gap: 4px; flex: none; }
|
|
1619
1684
|
.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }
|
|
1620
|
-
.ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; flex: none; }
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
.ss-w-bi-
|
|
1624
|
-
.ss-w-bi-
|
|
1625
|
-
.ss-w-bi-
|
|
1626
|
-
|
|
1685
|
+
.ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; align-self: flex-start; flex: none; }
|
|
1686
|
+
|
|
1687
|
+
/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */
|
|
1688
|
+
.ss-w-bi-comp-logo { width: 15px; height: 15px; flex: none; display: block; border-radius: 50%; background-size: contain; background-repeat: no-repeat; background-position: center; }
|
|
1689
|
+
.ss-w-bi-crest { width: 22px; height: 22px; flex: none; display: block; border-radius: 50%; background-size: contain; background-repeat: no-repeat; background-position: center; background-color: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); }
|
|
1690
|
+
.ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 9px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }
|
|
1691
|
+
|
|
1692
|
+
/* row 2: crest-flanked fixture on the left, boxed action panel on the right */
|
|
1693
|
+
.ss-w-bi-body { display: flex; align-items: center; gap: 10px; }
|
|
1694
|
+
.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12px; font-weight: 650; color: var(--ss-w-ink); }
|
|
1695
|
+
.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1696
|
+
.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }
|
|
1697
|
+
.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1698
|
+
.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: stretch; gap: 6px; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; }
|
|
1627
1699
|
.ss-w-bi-action .ss-w-slip > button { flex: 1; text-align: center; }
|
|
1628
1700
|
/* The action column is narrow; let its toast size to its own text and anchor to the card's right edge instead of being clipped to the button width. */
|
|
1629
1701
|
.ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }
|
|
1702
|
+
.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
1703
|
+
.ss-w-bi-market { font-size: 13.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }
|
|
1704
|
+
.ss-w-bi-sel { font-size: 11.5px; line-height: 1.3; color: var(--ss-w-faint); }
|
|
1630
1705
|
.ss-w-bi-odds { flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 1px; background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 10px; padding: 4px 11px; min-width: 62px; }
|
|
1631
1706
|
.ss-w-bi-odds-cap { font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }
|
|
1632
1707
|
.ss-w-bi-odds b { font-size: 19px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.1; }
|
|
1633
1708
|
.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
|
|
1709
|
+
|
|
1710
|
+
/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, in a subtle strip */
|
|
1711
|
+
.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }
|
|
1712
|
+
.ss-w-bi-chart { flex: none; width: 13px; height: 12px; margin-top: 2px; opacity: .55;
|
|
1713
|
+
background:
|
|
1714
|
+
linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) left / 3px 55% no-repeat,
|
|
1715
|
+
linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) center / 3px 100% no-repeat,
|
|
1716
|
+
linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) right / 3px 75% no-repeat;
|
|
1717
|
+
background-position: left bottom, center bottom, right bottom;
|
|
1718
|
+
}
|
|
1719
|
+
.ss-w-bi-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
|
|
1634
1720
|
.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }
|
|
1635
1721
|
.ss-w-bi-stats { display: flex; flex-direction: column; gap: 8px; }
|
|
1636
1722
|
.ss-w-bi-toggle { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }
|