@sensiblestats/widget-react 0.66.0 → 0.67.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 +39 -12
- 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 +152 -125
- package/dist/index.js.map +1 -1
- package/dist/styles.css +5 -0
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/StatsWidget.tsx","../src/kickoff.ts","../src/i18n.ts","../src/config.ts","../src/slip.ts","../src/useHostEvents.ts","../src/components/ChatPanel.tsx","../src/components/ChatHeader.tsx","../src/assets/logo.ts","../src/components/Icons.tsx","../src/components/BrandMark.tsx","../src/components/MessageList.tsx","../src/components/Markdown.tsx","../src/components/EntityCardList.tsx","../src/components/AddToSlipButton.tsx","../src/chart.ts","../src/model.ts","../src/eventLogContext.ts","../src/slipStateContext.ts","../src/components/Toast.tsx","../src/components/OddsMovementBadge.tsx","../src/components/Crest.tsx","../src/components/PinToggle.tsx","../src/pinStore.ts","../src/components/PriceHistoryButton.tsx","../src/host.ts","../src/matchLinkContext.ts","../src/components/MatchLink.tsx","../src/components/BettingInsightList.tsx","../src/components/MarketOddsCardList.tsx","../src/components/CompactOddsList.tsx","../src/compactList.ts","../src/components/OddsMovementCard.tsx","../src/components/ActionButtons.tsx","../src/components/dashboard/DashboardTile.tsx","../src/components/dashboard/GreetingDashboard.tsx","../src/components/dashboard/FixtureCard.tsx","../src/components/dashboard/CountdownCard.tsx","../src/components/dashboard/InjuriesCard.tsx","../src/components/dashboard/ReasonToBetCard.tsx","../src/components/dashboard/WhereToWatchCard.tsx","../src/components/dashboard/CongestedWeekCard.tsx","../src/components/dashboard/TransfersCard.tsx","../src/components/dashboard/LinksCard.tsx","../src/components/dashboard/PostMatchResultCard.tsx","../src/components/dashboard/PostMatchGoalsCard.tsx","../src/components/dashboard/PostMatchStatsCard.tsx","../src/components/dashboard/PostMatchTopPerformerCard.tsx","../src/components/dashboard/PostMatchNextCard.tsx","../src/components/dashboard/RestingNextCard.tsx","../src/components/dashboard/RestingStandingsCard.tsx","../src/components/dashboard/RestingSeasonCard.tsx","../src/components/dashboard/RestingFormCard.tsx","../src/components/dashboard/LiveScoreCard.tsx","../src/useLiveClock.ts","../src/components/dashboard/LiveTimelineCard.tsx","../src/components/dashboard/MomentumWave.tsx","../src/components/dashboard/LiveStatsCard.tsx","../src/components/dashboard/ClubFanDashboard.tsx","../src/components/ChatMessage.tsx","../src/components/IntentChips.tsx","../src/scroll.ts","../src/components/ChatInput.tsx","../src/components/TabBar.tsx","../src/components/MarketAccordion.tsx","../src/components/LiveFactBlock.tsx","../src/components/MonitorMatchCard.tsx","../src/components/MonitorTabs.tsx","../src/components/FixtureRow.tsx","../src/liveClock.ts","../src/components/CompetitionGroup.tsx","../src/components/TodayPanel.tsx","../src/components/GamesPanel.tsx","../src/components/GamesLoginWall.tsx","../src/components/GamesHub.tsx","../src/components/games/ui/gameMeta.ts","../src/components/GameTileArt.tsx","../src/components/games/ui/Chip.tsx","../src/components/games/ui/icons.tsx","../src/components/GameTile.tsx","../src/components/GameScreenHost.tsx","../src/useGamePlay.ts","../src/components/games/MysteryTigerGame.tsx","../src/components/games/nationFlags.ts","../src/components/games/PlayerAvatar.tsx","../src/components/games/ui/GameHeader.tsx","../src/components/games/ui/SegmentProgress.tsx","../src/components/games/ui/SearchField.tsx","../src/components/games/ui/FooterBar.tsx","../src/components/games/ui/Silhouette.tsx","../src/components/games/ui/GameButton.tsx","../src/components/games/ui/ResultCard.tsx","../src/components/games/ui/OptionList.tsx","../src/components/games/HigherOrLowerGame.tsx","../src/components/games/CareerPathGame.tsx","../src/components/games/ui/CrestShield.tsx","../src/components/games/BeatTheGridGame.tsx","../src/components/games/GuessTheXiGame.tsx","../src/components/games/ui/PitchSvg.tsx","../src/components/games/ui/formations.ts","../src/components/games/DailyQuizGame.tsx","../src/components/games/MatchdayPredictorGame.tsx","../src/components/games/StartingXiGame.tsx","../src/components/games/StatLadderGame.tsx","../src/components/games/FanMotmGame.tsx","../src/components/games/ui/fonts.ts","../src/components/Leaderboard.tsx","../src/components/LeaderboardRow.tsx","../src/components/LeaderboardEmpty.tsx","../src/components/LeaderboardPanel.tsx","../src/matchViews.ts","../src/slipLedger.ts","../src/dashboardTap.ts","../src/theme.ts","../src/useChatStream.ts","../src/reducer.ts","../src/useLiveDashboardPoll.ts","../src/conversationStore.ts","../src/useLiveMonitor.ts","../src/useTabs.ts","../src/useMatchDiscovery.ts","../src/scheduleCache.ts","../src/dueSet.ts","../src/useGames.ts","../src/useLeaderboard.ts","../src/popupTelemetry.ts","../src/components/ChatFab.tsx","../src/components/GreetingBubble.tsx","../src/components/HostEventsProvider.tsx","../src/styles/css.generated.ts"],"sourcesContent":["export { StatsWidget } from './StatsWidget'\nexport type { StatsWidgetProps } from './StatsWidget'\nexport type { StatsWidgetConfig } from './config'\nexport { createWidgetHost } from './host'\nexport type { WidgetHost } from './host'\nexport { WIDGET_CSS } from './styles/css.generated'\n","import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from 'react'\nimport { StatsWidgetClient, type Conversation } from '@sensiblestats/widget-sdk'\nimport { normalizeUi, toClientOptions, toUserContext, type StatsWidgetConfig } from './config'\nimport { wasAdded, type SlipHandlerProps } from './slip'\nimport type { WidgetHost } from './host'\nimport { useHostEvents } from './useHostEvents'\nimport { createDashboardTapSignal } from './dashboardTap'\nimport { themeAttrs } from './theme'\nimport { useChatStream } from './useChatStream'\nimport { useLiveMonitor } from './useLiveMonitor'\nimport { useMatchDiscovery } from './useMatchDiscovery'\nimport { useGames } from './useGames'\nimport { useLeaderboard } from './useLeaderboard'\nimport { visibleGroupsOf } from './liveClock'\nimport { EventLogContext } from './eventLogContext'\nimport { usePopupTelemetry } from './popupTelemetry'\nimport { ChatFab } from './components/ChatFab'\nimport { ChatPanel } from './components/ChatPanel'\nimport { HostEventsProvider } from './components/HostEventsProvider'\nimport { WIDGET_CSS } from './styles/css.generated'\n\nexport type StatsWidgetProps =\n | { config: StatsWidgetConfig; client?: never; host?: WidgetHost }\n | { client: StatsWidgetClient; config?: Omit<StatsWidgetConfig, 'operatorId' | 'publicKey' | 'baseUrl' | 'userContext'>; host?: WidgetHost }\n\nfunction buildClient(props: StatsWidgetProps): { client: StatsWidgetClient; conversation: Conversation } | null {\n try {\n if ('client' in props && props.client) {\n return { client: props.client, conversation: props.client.conversation() }\n }\n const cfg = props.config as StatsWidgetConfig\n const client = new StatsWidgetClient(toClientOptions(cfg))\n return { client, conversation: client.conversation(toUserContext(cfg)) }\n } catch (err) {\n console.error('[StatsWidget] failed to initialize:', err instanceof Error ? err.message : err)\n return null\n }\n}\n\nfunction injectStyles(root: Document | ShadowRoot): void {\n const host: ParentNode = root instanceof ShadowRoot ? root : root.head\n if (host.querySelector('#ss-w-styles')) return\n const el = document.createElement('style')\n el.id = 'ss-w-styles'\n el.textContent = WIDGET_CSS\n host.appendChild(el)\n}\n\nexport function StatsWidget(props: StatsWidgetProps): JSX.Element | null {\n const injectedClient = 'client' in props ? props.client : undefined\n const cfg = props.config as Partial<StatsWidgetConfig> | undefined\n const built = useMemo(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl])\n // One logger per mount, keyed on the client identity (not on operatorUserId/anonymousUserId/\n // conversationId -- those change over the widget's lifetime and are pushed in via setIdentity\n // below, not by tearing down and recreating the logger).\n const logger = useMemo(\n () => (built ? built.client.createEventLogger({\n operatorUserId: cfg?.userContext?.operatorUserId,\n anonymousUserId: cfg?.userContext?.anonymousUserId,\n }) : null),\n [built?.client],\n )\n const ui = useMemo(() => normalizeUi((props.config ?? { operatorId: '', publicKey: '' }) as StatsWidgetConfig), [props.config])\n const rootRef = useRef<HTMLDivElement>(null)\n // One-shot launcher attention animation: the FAB nudges then the greeting\n // types in, exactly once per page load. The ref lives here (not in ChatFab,\n // which remounts every time the panel closes) so it never replays; a page\n // refresh remounts the widget and re-arms it.\n const introDoneRef = useRef(false)\n const markIntroDone = useCallback(() => { introDoneRef.current = true }, [])\n const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`\n const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : undefined, convStorageKey)\n // The two hooks are mutually dependent -- useMatchDiscovery needs monitor.pins, useLiveMonitor\n // needs to know whether Today has content -- so the cycle is broken with state rather than a\n // read of discovery's own render. It settles one render later, and unlike a ref it actually\n // re-renders, which is what lets the fallback effect fire when Today empties under the user.\n const [hasToday, setHasToday] = useState(false)\n const monitor = useLiveMonitor({\n getLiveMonitor: (pins) => (built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null)),\n getMarketOdds: (matchId, dev) => (built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null)),\n storageKey: `ss-w-pins:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`,\n isOpen: controller.state.isOpen,\n hasToday,\n })\n // Stable across renders (deps = [built], itself memoized on the client identity) -- the real\n // call site useMatchDiscovery.test.tsx's interval-churn test protects: a freshly-constructed\n // arrow here would defeat that guarantee even with the hook's own getStatesRef defense.\n const getSchedule = useCallback(\n (localDate: string, utcOffsetMinutes: number) =>\n built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),\n [built],\n )\n const getStates = useCallback(\n (matchIds: number[]) => (built ? built.conversation.getStates(matchIds) : Promise.resolve(null)),\n [built],\n )\n const pinnedMatchIds = useMemo(\n () => monitor.pins.filter((p) => p.kind === 'match').map((p) => p.matchId),\n [monitor.pins],\n )\n const discovery = useMatchDiscovery({\n getSchedule,\n getStates,\n operatorId: cfg?.operatorId ?? '',\n isOpen: controller.state.isOpen,\n pinnedMatchIds,\n })\n const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0\n useEffect(() => { setHasToday(todayHasContent) }, [todayHasContent])\n\n const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab })\n const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab })\n\n // The Today dot: the live count rising from zero is the \"something changed you have not seen\"\n // event for this tab. The hook suppresses it while Today is the active tab, exactly as the\n // other three dots are suppressed.\n const markTodayActivity = monitor.markTodayActivity\n const prevLiveCountRef = useRef(0)\n useEffect(() => {\n const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0\n prevLiveCountRef.current = discovery.liveCount\n if (rose) markTodayActivity()\n }, [discovery.liveCount, markTodayActivity])\n const hostEvents = useHostEvents({\n host: props.host,\n operatorId: cfg?.operatorId ?? '',\n currentUser: cfg?.userContext?.operatorUserId || undefined,\n logger,\n isOpen: controller.state.isOpen,\n closePanel: controller.close,\n onOpenMatch: props.config?.onOpenMatch,\n openMatchLabel: ui.openMatch,\n })\n const markAdded = hostEvents.markAdded\n const slip = useMemo<SlipHandlerProps>(\n () => {\n const handler = props.config?.onAddToSlip\n return {\n // I3: the D5 persistent in-slip badge must arm from ANY add path -- a chat-message\n // insight/market card, not just the ones rendered inside the Odds tab itself -- so the\n // wasAdded->markAdded wrap lives here (once), not duplicated per consumer. It awaits the\n // operator's handler itself, so a result that lands after the button's own timeout still\n // arms the badge.\n onAddToSlip: handler && (async (sel) => {\n const result = await handler(sel)\n if (wasAdded(result)) markAdded(sel.matchOddsId)\n return result\n }),\n conversationId: controller.state.conversationId ?? undefined,\n }\n },\n [props.config?.onAddToSlip, controller.state.conversationId, markAdded],\n )\n const onDashboardTap = useMemo(\n () => (built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : undefined),\n [built, logger],\n )\n\n const dismissPopup = usePopupTelemetry(logger, controller.state.isOpen, controller.state.popupText, controller.dismissPopup)\n\n const operatorUserId = cfg?.userContext?.operatorUserId\n const anonymousUserId = cfg?.userContext?.anonymousUserId\n const conversationId = controller.state.conversationId ?? undefined\n useEffect(() => {\n if (!logger) return\n logger.setIdentity({ operatorUserId, anonymousUserId, conversationId })\n }, [logger, operatorUserId, anonymousUserId, conversationId])\n\n useEffect(() => {\n if (!logger) return\n // React StrictMode runs this cleanup and then this setup again on the same memoized logger.\n // Without the resume the second pass keeps a disposed logger and every later event is dropped.\n logger.resume()\n const onHide = (): void => { logger.flushOnHide() }\n const onVisibilityHide = (): void => {\n if (document.visibilityState === 'hidden') logger.flushOnHide()\n }\n window.addEventListener('pagehide', onHide)\n document.addEventListener('visibilitychange', onVisibilityHide)\n return () => {\n window.removeEventListener('pagehide', onHide)\n document.removeEventListener('visibilitychange', onVisibilityHide)\n // dispose() only clears the internal timer -- it does NOT flush queued events, so an\n // unflushed dispose on unmount silently drops whatever is still queued.\n logger.flushOnHide()\n logger.dispose()\n }\n }, [logger])\n\n useEffect(() => {\n if (!built || !ui.injectStyles) return\n const node = rootRef.current?.getRootNode()\n if (node) injectStyles(node as Document | ShadowRoot)\n }, [built, ui.injectStyles])\n\n if (!built) return null\n const attrs = themeAttrs(ui)\n return (\n <EventLogContext.Provider value={logger}>\n <HostEventsProvider value={hostEvents}>\n <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 as CSSProperties}>\n {controller.state.isOpen ? (\n <ChatPanel\n controller={controller}\n ui={ui}\n slip={slip}\n onDashboardTap={onDashboardTap}\n monitor={monitor.enabled ? monitor : undefined}\n discovery={discovery}\n gamesResult={gamesResult}\n leaderboardResult={leaderboardResult}\n loggedIn={!!operatorUserId}\n conversation={built?.conversation ?? null}\n />\n ) : (\n <ChatFab\n label={ui.launcherLabel}\n greeting={ui.greeting}\n popupText={controller.state.popupText}\n logoUrl={ui.logoUrl}\n onOpen={controller.open}\n onDismissPopup={dismissPopup}\n dismissLabel={ui.dismissGreeting}\n introAllowed={!introDoneRef.current}\n onIntroStart={markIntroDone}\n />\n )}\n </div>\n </HostEventsProvider>\n </EventLogContext.Provider>\n )\n}\n\n// Hooks must run unconditionally; when the client failed to build we still need a Conversation-shaped stub for the hook.\nfunction emptyConversation(): Conversation {\n return { send: () => { throw new Error('widget not initialized') } } as unknown as Conversation\n}\n","export function formatBettingKickoff(\n kickoffUtc: string,\n ui: { today: string; tomorrow: string },\n locale: string,\n now: Date = new Date(),\n): { dayLabel: string; time: string } {\n const at = new Date(kickoffUtc)\n const intlLocale = locale === 'tr' ? 'tr-TR' : 'en-GB'\n const time = new Intl.DateTimeFormat(intlLocale, { hour: '2-digit', minute: '2-digit' }).format(at)\n const atLocalDate = new Date(at.getFullYear(), at.getMonth(), at.getDate())\n const nowLocalDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const dayDiff = Math.round((atLocalDate.getTime() - nowLocalDate.getTime()) / 86_400_000)\n const dayLabel =\n dayDiff === 0\n ? ui.today\n : dayDiff === 1\n ? ui.tomorrow\n : new Intl.DateTimeFormat(intlLocale, { weekday: 'short', day: 'numeric', month: 'short' }).format(at)\n return { dayLabel, time }\n}\n","import { formatBettingKickoff } from './kickoff'\n\nexport type Locale = 'en' | 'tr'\n\n// Games-tab copy (u393). Each game task adds its own keys here, in en AND tr.\nexport interface GamesStrings {\n // BCP-47 tag set on the games roots so CSS text-transform uppercases Turkish i → İ.\n lang: 'en' | 'tr'\n dailyChallenge: string\n playNow: string\n dailyGames: string\n newSetAtMidnight: string\n matchdayGames: string\n kickoffAt: (dayTime: string) => string\n statStreak: string\n statToday: string\n statRank: string\n unitDays: string\n unitPts: string\n thisWeek: string\n newToday: string\n resume: string\n done: string\n doneWithScore: (score: number) => string\n locksAt: (dayTime: string) => string\n // Points with the locale's digit grouping (\"1,200\" en / \"1.200\" tr). Used by the hub TODAY stat and doneWithScore.\n formatPts: (n: number) => string\n // Shared by every game screen (loading branch, result card, primary guess button).\n loading: string\n backToGames: string\n alreadyPlayedTitle: string\n guess: string\n // Localised \"Sat 15:00\". A function so each locale owns its Intl locale.\n formatDayTime: (iso: string) => string\n // Display names keyed by gameId — locale-specific replacements for the GAME_TITLES map.\n titles: Record<string, string>\n taglines: Record<string, string>\n mysteryTiger: {\n eyebrow: string\n labels: Record<'position' | 'nationality' | 'age' | 'shirtNumber' | 'apps', string>\n yourGuesses: string\n legendMatch: string\n legendClose: string\n legendHigher: string\n searchLabel: string\n searchPlaceholder: string\n optionsLabel: string\n progress: (used: number, total: number) => string\n solved: string\n failed: string\n detail: (guesses: number) => string\n }\n higherOrLower: {\n eyebrow: (points: number) => string\n streak: string\n whoHadMore: string\n season: (label: string) => string\n higher: string\n lower: string\n vs: string\n lastAnswer: (name: string, value: number) => string\n answersSoFar: (answered: number, total: number) => string\n runOver: string\n perfectRun: string\n runDetail: (correct: number) => string\n }\n guessTheXi: {\n pitchLabel: string\n notThem: string\n whichClub: (left: number) => string\n searchPlaceholder: string\n optionsLabel: string\n solved: string\n failed: string\n detail: (guesses: number) => string\n theAnswer: string\n }\n dailyQuiz: {\n questionOf: (i: number, n: number) => string\n results: string\n next: string\n previous: string\n submit: string\n submitting: string\n correctOf: (correct: number, n: number) => string\n progressAria: (i: number, n: number) => string\n }\n careerPath: {\n eyebrow: string\n mysteryPlayer: string\n lockPosition: string\n lockNationality: string\n firstClub: string\n loan: string\n nextClubHidden: string\n moreClubs: (k: number) => string\n searchLabel: string\n searchPlaceholder: string\n solved: string\n failed: string\n guessesLine: (n: number) => string\n }\n beatTheGrid: {\n eyebrow: string\n filled: (n: number, total: number) => string\n toGo: (n: number) => string\n progressAria: (n: number, total: number) => string\n rowAbbrev: Record<string, string>\n pickCell: (row: string, col: string) => string\n cellFilled: (row: string, col: string, name: string, verdict: string) => string\n correct: string\n wrong: string\n closeSearch: string\n searchLabel: (row: string, col: string) => string\n searchPlaceholder: string\n emptyPool: string\n complete: string\n summary: (correct: number, filled: number) => string\n }\n predictor: {\n eyebrow: (home: string, away: string) => string\n home: string\n away: string\n goalsUp: (team: string) => string\n goalsDown: (team: string) => string\n firstScorer: string\n optional: string\n searchLabel: string\n searchPlaceholder: string\n noScorer: string\n save: string\n saving: string\n closed: string\n saved: string\n savedDetail: (p: { home: string; away: string; h: number; a: number; scorer: string | null }) => string\n fullTime: (h: number, a: number) => string\n exactScore: string\n outcome: string\n firstScorerRow: string\n correct: string\n incorrect: string\n forFun: string\n }\n startingXi: {\n eyebrow: string\n perStarter: (n: number) => string\n picked: (n: number) => string\n toGo: (n: number) => string\n pickSlot: (pos: string) => string\n clearSlot: (pos: string, name: string) => string\n pickFor: (pos: string) => string\n allPicked: string\n searchLabel: string\n submit: string\n submitting: string\n locksAt: (dayTime: string) => string\n locksSoon: string\n pending: (n: number) => string\n gradedLine: (correct: number) => string\n voided: string\n }\n motm: {\n title: string\n eyebrow: string\n voted: string\n yourVote: string\n youVoted: (name: string) => string\n thanks: string\n tapToVote: string\n forFun: string\n }\n statLadder: {\n eyebrow: string\n question: (stat: string) => { pre: string; emph: string; post: string }\n whoSecond: string\n clue: (\n c: { value: number; above: { name: string; diff: number } | null; below: { name: string; diff: number } | null },\n stat: string,\n ) => string\n searchLabel: string\n searchPlaceholder: string\n guess: string\n correct: string\n wrong: (name: string) => string\n }\n}\n\nconst formatPtsEn = (n: number): string => new Intl.NumberFormat('en-GB').format(n)\nconst formatPtsTr = (n: number): string => new Intl.NumberFormat('tr-TR').format(n)\n\nexport interface LocaleStrings {\n launcherLabel: string\n placeholder: string\n closeChat: string\n newConversation: string\n moreOptions: string\n chatDialogLabel: string\n stopResponse: string\n sendMessage: string\n dismissGreeting: string\n somethingWentWrong: string\n retry: string\n showLess: string\n showMore: (n: number) => string\n oddsLabel: string\n liveLabel: string\n marketFloorLabel: string\n addToSlip: string\n marketPrices: string\n moreLines: string\n hideLines: string\n oddsMoved: (was: string, now: string, direction: string) => string\n oddsShortened: string\n oddsDrifted: string\n updatedLabel: string\n priceMovement: string\n openingLabel: string\n currentLabel: string\n movementWindow: (hours: number) => string\n notEnoughHistory: string\n singlePricePoint: string\n selectionSuspended: string\n excludedSuspended: (n: number) => string\n chartTimeLabel: (ms: number) => string\n chartAria: (opening: string, current: string, direction: string, hours: number) => string\n inSlip: string\n slipAdded: string\n slipDuplicate: string\n slipPriceChanged: (from: string, to: string) => string\n slipPriceNotAccepted: (from: string, to: string) => string\n slipLoginRequired: string\n slipSuspended: string\n slipFailed: string\n today: string\n tomorrow: string\n bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n tabChat: string\n tabFollowing: string\n tabOdds: string\n tabToday: string\n sectionLive: string\n /** Short scoreboard badge for the fixture row's time column. The long-form phase name\n * for the monitor card is fullTimeLabel. */\n halfTime: string\n staleStates: string\n pinLabel: string\n unpinLabel: string\n matchPinLabel: string\n matchUnpinLabel: string\n matchLimitToast: string\n marketLimitToast: string\n priceHistoryLabel: string\n emptyMatchesTab: string\n emptyOddsTab: string\n asOf: (time: string) => string\n graceNote: string\n suspendedLabel: string\n fullTimeLabel: string\n ownGoalLabel: string\n inSlipLabel: string\n /** Accessible name of a match link. Both names when the card has them, else the short form. */\n openMatch: (home?: string, away?: string) => string\n oddsUnavailable: string\n momentumLabel: string\n liveFactLabel: string\n liveFactAsk: string\n liveFactEarlier: (n: number) => string\n liveFactHideEarlier: string\n accordionRetry: string\n accordionSuspended: string\n tabGames: string\n tabLeaderboard: string\n gamesLoginRequired: string\n back: string\n leaderboardOffBoard: string\n leaderboardThisWeek: string\n leaderboardAllTime: string\n leaderboardEmptyFreshTitle: string\n leaderboardEmptyFreshBody: string\n leaderboardEmptyColdTitle: string\n leaderboardEmptyColdBody: string\n leaderboardEmptyCta: string\n leaderboardLastWeekLabel: string\n leaderboardAllTimeEmpty: string\n gamePlay: string\n gameLocked: string\n gameVoided: string\n games: GamesStrings\n}\n\nconst STRINGS: Record<Locale, LocaleStrings> = {\n en: {\n launcherLabel: 'Chat with SensibleStats',\n placeholder: 'Ask about a team, player or match…',\n closeChat: 'Close chat',\n newConversation: 'New conversation',\n moreOptions: 'More options',\n chatDialogLabel: 'SensibleStats chat',\n stopResponse: 'Stop response',\n sendMessage: 'Send message',\n dismissGreeting: 'Dismiss',\n somethingWentWrong: 'Something went wrong.',\n retry: 'Retry',\n showLess: 'Show less',\n showMore: (n) => `Show ${n} more`,\n oddsLabel: 'Odds',\n liveLabel: 'Live',\n marketFloorLabel: 'Market price · not a value pick',\n addToSlip: 'Add to slip',\n marketPrices: 'Market prices',\n moreLines: 'More lines',\n hideLines: 'Hide lines',\n oddsMoved: (was, now, direction) => `was ${was}, now ${now}, ${direction}`,\n oddsShortened: 'shortened',\n oddsDrifted: 'drifted',\n updatedLabel: 'updated',\n priceMovement: 'Price movement',\n openingLabel: 'Opening',\n currentLabel: 'Current',\n movementWindow: (hours) => (hours % 24 === 0 ? `Last ${hours / 24}d` : `Last ${hours}h`),\n notEnoughHistory: 'No price history recorded yet for this selection.',\n singlePricePoint: 'Only one price recorded so far for this selection.',\n selectionSuspended: 'This selection is not currently available to bet.',\n excludedSuspended: (n) => `${n} suspended price${n === 1 ? '' : 's'} excluded from this chart.`,\n chartTimeLabel: (ms) =>\n new Intl.DateTimeFormat('en-GB', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n chartAria: (opening, current, direction, hours) => {\n const span = hours % 24 === 0 ? `${hours / 24} day${hours / 24 === 1 ? '' : 's'}` : `${hours} hour${hours === 1 ? '' : 's'}`\n // A flat price has no direction word; appending an empty one leaves \", .\" for a screen reader.\n const drift = direction ? `, ${direction}` : ''\n return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`\n },\n inSlip: 'In slip',\n slipAdded: 'Added to slip',\n slipDuplicate: 'Already in your slip',\n slipPriceChanged: (from, to) => `Added at ${to} (was ${from})`,\n slipPriceNotAccepted: (from, to) => `Price moved to ${to} (was ${from}). Tap to add.`,\n slipLoginRequired: 'Sign in to add to your slip',\n slipSuspended: 'Market suspended',\n slipFailed: \"Couldn't add to slip. Try again.\",\n today: 'Today',\n tomorrow: 'Tomorrow',\n bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, 'en', now),\n tabChat: 'Chat',\n tabFollowing: 'Following',\n tabOdds: 'Odds',\n pinLabel: 'Track odds',\n unpinLabel: 'Stop tracking odds',\n matchPinLabel: 'Track match',\n matchUnpinLabel: 'Stop tracking match',\n matchLimitToast: 'Match limit reached — unpin one first',\n marketLimitToast: 'Odds limit reached — unpin one first',\n priceHistoryLabel: 'Price history',\n emptyMatchesTab: 'No pinned matches yet. Pin a match from the conversation to track it live.',\n emptyOddsTab: 'No odds followed yet. Tap Price history on a price that moved to follow it here.',\n asOf: (time) => `Prices as of ${time}`,\n graceNote: 'Unpins on next open · or in 4 h',\n suspendedLabel: 'Suspended',\n fullTimeLabel: 'Full time',\n ownGoalLabel: 'OG',\n inSlipLabel: 'In slip',\n openMatch: (home, away) => (home && away ? `Open ${home} vs ${away}` : 'Open match'),\n oddsUnavailable: 'Odds unavailable right now',\n momentumLabel: 'Momentum',\n liveFactLabel: 'Live fact',\n liveFactAsk: 'Ask about this',\n liveFactEarlier: (n: number) => `Earlier facts (${n})`,\n liveFactHideEarlier: 'Hide earlier facts',\n accordionRetry: \"Couldn't load odds — tap to retry\",\n accordionSuspended: 'Suspended',\n tabToday: 'Today',\n sectionLive: 'Live',\n halfTime: 'HT',\n staleStates: \"Live scores can't be updated — showing the last known state.\",\n tabGames: 'Games',\n tabLeaderboard: 'Leaderboard',\n gamesLoginRequired: 'Sign in to play and climb the leaderboard',\n back: 'Back',\n leaderboardOffBoard: 'Outside top 50',\n leaderboardThisWeek: 'This week',\n leaderboardAllTime: 'All time',\n leaderboardEmptyFreshTitle: 'New week, blank slate',\n leaderboardEmptyFreshBody: 'No scores yet. The first fan to play a game takes #1.',\n leaderboardEmptyColdTitle: 'Be the first up',\n leaderboardEmptyColdBody: \"Nobody's on the board yet. Play a game and you're #1.\",\n leaderboardEmptyCta: \"Play today's games\",\n leaderboardLastWeekLabel: 'Last week',\n leaderboardAllTimeEmpty: 'The all-time board fills as fans play — nothing here yet.',\n gamePlay: 'Play',\n gameLocked: 'Locked',\n gameVoided: 'Voided',\n games: {\n lang: 'en',\n dailyChallenge: 'Daily challenge',\n playNow: 'Play now',\n dailyGames: 'Daily games',\n newSetAtMidnight: 'New set at midnight',\n matchdayGames: 'Matchday games',\n kickoffAt: (t) => `Kick-off ${t}`,\n statStreak: 'Streak',\n statToday: 'Today',\n statRank: 'Rank',\n unitDays: 'days',\n unitPts: 'pts',\n thisWeek: 'this week',\n newToday: 'New today',\n resume: 'Resume',\n done: 'Done',\n doneWithScore: (s) => `Done · +${formatPtsEn(s)}`,\n locksAt: (t) => `Locks ${t}`,\n formatPts: formatPtsEn,\n loading: 'Loading…',\n backToGames: 'Back to games',\n alreadyPlayedTitle: 'Played today',\n guess: 'Guess',\n formatDayTime: (iso) =>\n new Intl.DateTimeFormat('en-GB', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n titles: {\n 'mystery-tiger': 'Mystery Player',\n 'daily-quiz': 'Daily Quiz',\n 'career-path': 'Career Path',\n 'beat-the-grid': 'Beat the Grid',\n 'guess-the-xi': 'Guess the XI',\n 'higher-or-lower': 'Higher or Lower',\n 'matchday-predictor': 'Matchday Predictor',\n 'starting-xi': 'Starting XI',\n 'stat-ladder': 'Stat Ladder',\n 'fan-motm': 'Fan MOTM',\n },\n taglines: {\n 'mystery-tiger': 'One player. Six guesses.',\n 'higher-or-lower': 'Who had more?',\n 'guess-the-xi': 'Name the team',\n 'daily-quiz': 'Test your club knowledge',\n 'career-path': 'Follow the clubs',\n 'beat-the-grid': 'Fill all 9 cells',\n 'matchday-predictor': 'Call the score',\n 'starting-xi': 'Pick the lineup',\n 'stat-ladder': 'Find the missing rung',\n 'fan-motm': 'Vote at full time',\n },\n mysteryTiger: {\n eyebrow: 'Daily · resets 00:00',\n labels: { position: 'POS', nationality: 'NAT', age: 'AGE', shirtNumber: 'NO.', apps: 'APPS' },\n yourGuesses: 'Your guesses',\n legendMatch: 'Match',\n legendClose: 'Close',\n legendHigher: 'Mystery is higher',\n searchLabel: 'Guess a squad player',\n searchPlaceholder: 'Search by name',\n optionsLabel: 'Squad players',\n progress: (used, total) => `${used} of ${total} guesses used`,\n solved: 'You found them!',\n failed: 'Out of guesses',\n detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n },\n higherOrLower: {\n eyebrow: (p) => `+${p} per correct`,\n streak: 'Streak',\n whoHadMore: 'Who had more',\n season: (l) => `${l} season`,\n higher: 'Higher',\n lower: 'Lower',\n vs: 'VS',\n lastAnswer: (name, value) => `${name} had ${value}`,\n answersSoFar: (a, total) => `${a} of ${total} answered`,\n runOver: 'Run over',\n perfectRun: 'Perfect run!',\n runDetail: (c) => `${c} correct in a row · back tomorrow`,\n },\n guessTheXi: {\n pitchLabel: 'Starting line-up by nationality',\n notThem: 'Not them:',\n whichClub: (left) => `Which club is this? · ${left} left`,\n searchPlaceholder: 'Search clubs',\n optionsLabel: 'Clubs',\n solved: 'Solved!',\n failed: 'Out of guesses',\n detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n theAnswer: 'The answer',\n },\n dailyQuiz: {\n questionOf: (i, n) => `Question ${i} of ${n}`,\n results: 'Results',\n next: 'Next',\n previous: 'Previous',\n submit: 'Submit',\n submitting: 'Submitting…',\n correctOf: (c, n) => `${c} of ${n} correct`,\n progressAria: (i, n) => `Question ${i} of ${n}`,\n },\n careerPath: {\n eyebrow: 'Oldest club first',\n mysteryPlayer: 'Mystery player',\n lockPosition: 'Position',\n lockNationality: 'Nationality',\n firstClub: 'First club',\n loan: 'Loan',\n nextClubHidden: 'Next club — revealed after a wrong guess',\n moreClubs: (k) => `+ ${k} more club${k === 1 ? '' : 's'}`,\n searchLabel: 'Who is it?',\n searchPlaceholder: 'Search any player',\n solved: 'Career traced!',\n failed: 'Out of guesses',\n guessesLine: (n) => `${n} guess${n === 1 ? '' : 'es'} · come back tomorrow`,\n },\n beatTheGrid: {\n eyebrow: 'Fill each cell with a player who fits',\n filled: (n, t) => `${n} of ${t} filled`,\n toGo: (n) => `${n} to go`,\n progressAria: (n, t) => `${n} of ${t} cells filled`,\n rowAbbrev: { Goalkeeper: 'GK', Defender: 'DEF', Midfielder: 'MID', Forward: 'FWD' },\n pickCell: (r, c) => `Pick a ${r.toLowerCase()} with ${c}`,\n cellFilled: (r, c, name, verdict) => `${r} with ${c}: ${name}, ${verdict.toLowerCase()}`,\n correct: 'Correct',\n wrong: 'Wrong',\n closeSearch: 'Close player search',\n searchLabel: (r, c) => `Search player for ${r} × ${c}`,\n searchPlaceholder: 'Search players',\n emptyPool: 'No players available to search yet.',\n complete: 'Grid complete',\n summary: (c, f) => `${c}/${f} correct · come back tomorrow`,\n },\n predictor: {\n eyebrow: (home, away) => `${home} v ${away}`,\n home: 'Home',\n away: 'Away',\n goalsUp: (team) => `${team} goals up`,\n goalsDown: (team) => `${team} goals down`,\n firstScorer: 'First scorer',\n optional: 'Optional',\n searchLabel: 'Search first scorer',\n searchPlaceholder: 'Search squad',\n noScorer: 'No first scorer',\n save: 'Save prediction',\n saving: 'Saving…',\n closed: 'Submissions are now closed',\n saved: 'Prediction saved',\n savedDetail: (p) =>\n `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ${p.scorer} first` : ''} · awaiting result`,\n fullTime: (h, a) => `Full time ${h} – ${a}`,\n exactScore: 'Exact score',\n outcome: 'Result (W/D/L)',\n firstScorerRow: 'First scorer',\n correct: 'Correct',\n incorrect: 'Incorrect',\n forFun: 'For fun — not in the leaderboard',\n },\n startingXi: {\n eyebrow: 'Predict the lineup',\n perStarter: (n) => `+${n} per starter`,\n picked: (n) => `${n} of 11 picked`,\n toGo: (n) => `${n} to go`,\n pickSlot: (pos) => `Pick ${pos}`,\n clearSlot: (pos, name) => `Remove ${name} from ${pos}`,\n pickFor: (pos) => `Pick your ${pos}`,\n allPicked: 'All 11 picked — tap a player on the pitch to swap',\n searchLabel: 'Search squad',\n submit: 'Lock in my XI',\n submitting: 'Submitting…',\n locksAt: (t) => `Locks ${t}, about an hour before kick-off`,\n locksSoon: 'Locks about an hour before kick-off',\n pending: (n) => `Prediction locked in (${n} players) — awaiting result`,\n gradedLine: (c) => `${c} of 11 correct`,\n voided: 'This game has been voided',\n },\n motm: {\n title: 'Man of the Match',\n eyebrow: 'Fan vote',\n voted: 'Voted',\n yourVote: 'Your vote',\n youVoted: (name) => `You voted ${name}`,\n thanks: \"Thanks — results aren't shown for this vote\",\n tapToVote: 'Tap a player to vote',\n forFun: 'For fun — unranked community vote',\n },\n statLadder: {\n eyebrow: 'Last match',\n question: (stat) => ({ pre: 'Who made the ', emph: '2nd-most', post: ` ${stat.toLowerCase()}?` }),\n whoSecond: \"Who's 2nd?\",\n clue: (c, stat) => {\n const parts: string[] = []\n if (c.above) parts.push(c.above.diff === 0 ? `the same as ${c.above.name}` : `${c.above.diff} fewer than ${c.above.name}`)\n if (c.below) parts.push(c.below.diff === 0 ? `the same as ${c.below.name}` : `${c.below.diff} more than ${c.below.name}`)\n return `They made ${c.value} ${stat.toLowerCase()}${parts.length ? `, ${parts.join(' and ')}` : ''}.`\n },\n searchLabel: 'Guess the 2nd player',\n searchPlaceholder: 'Search squad',\n guess: 'Guess',\n correct: 'Correct!',\n wrong: (name) => `Wrong — it was ${name}`,\n },\n },\n },\n tr: {\n launcherLabel: 'SensibleStats ile sohbet et',\n placeholder: 'Bir takım, oyuncu veya maç hakkında sor…',\n closeChat: 'Sohbeti kapat',\n newConversation: 'Yeni sohbet',\n moreOptions: 'Diğer seçenekler',\n chatDialogLabel: 'SensibleStats sohbet',\n stopResponse: 'Yanıtı durdur',\n sendMessage: 'Mesaj gönder',\n dismissGreeting: 'Kapat',\n somethingWentWrong: 'Bir şeyler ters gitti.',\n retry: 'Tekrar dene',\n showLess: 'Daha az göster',\n showMore: (n) => `${n} tane daha göster`,\n oddsLabel: 'Oran',\n liveLabel: 'Canlı',\n marketFloorLabel: 'Piyasa oranı · değer bahsi değil',\n addToSlip: 'Kupona ekle',\n marketPrices: 'Piyasa fiyatları',\n moreLines: 'Diğer çizgiler',\n hideLines: 'Çizgileri gizle',\n oddsMoved: (was, now, direction) => `önce ${was}, şimdi ${now}, ${direction}`,\n oddsShortened: 'düştü',\n oddsDrifted: 'yükseldi',\n updatedLabel: 'güncellendi',\n priceMovement: 'Oran hareketi',\n openingLabel: 'Açılış',\n currentLabel: 'Güncel',\n movementWindow: (hours) => (hours % 24 === 0 ? `Son ${hours / 24} gün` : `Son ${hours} saat`),\n notEnoughHistory: 'Bu seçim için henüz oran geçmişi kaydedilmedi.',\n singlePricePoint: 'Bu seçim için şimdiye kadar yalnızca bir fiyat kaydedildi.',\n selectionSuspended: 'Bu seçim şu anda bahse kapalı.',\n excludedSuspended: (n) => `${n} askıya alınmış fiyat bu grafikten hariç tutuldu.`,\n chartTimeLabel: (ms) =>\n new Intl.DateTimeFormat('tr-TR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n chartAria: (opening, current, direction, hours) => {\n const span = hours % 24 === 0 ? `${hours / 24} gün` : `${hours} saat`\n const drift = direction ? `, ${direction}` : ''\n return `Son ${span} içindeki oran hareketi: ${opening} ile açıldı, şu anda ${current}${drift}.`\n },\n inSlip: 'Kuponda',\n slipAdded: 'Kupona eklendi',\n slipDuplicate: 'Bu seçim kuponunuzda zaten var',\n slipPriceChanged: (from, to) => `${to} oranıyla eklendi (önceki ${from})`,\n slipPriceNotAccepted: (from, to) => `Oran ${to} oldu (önceki ${from}). Eklemek için dokunun.`,\n slipLoginRequired: 'Kupona eklemek için giriş yapın',\n slipSuspended: 'Bu market askıya alındı',\n slipFailed: 'Kupona eklenemedi. Tekrar deneyin.',\n today: 'Bugün',\n tomorrow: 'Yarın',\n bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, 'tr', now),\n tabChat: 'Sohbet',\n tabFollowing: 'Takip',\n tabOdds: 'Oranlar',\n pinLabel: 'Oranı takip et',\n unpinLabel: 'Oran takibini bırak',\n matchPinLabel: 'Maçı takip et',\n matchUnpinLabel: 'Maç takibini bırak',\n matchLimitToast: 'Maç limiti dolu — önce bir maçı kaldır',\n marketLimitToast: 'Oran limiti dolu — önce birini kaldır',\n priceHistoryLabel: 'Oran geçmişi',\n emptyMatchesTab: 'Henüz sabitlenmiş maç yok. Canlı takip için sohbetteki bir maçı sabitle.',\n emptyOddsTab: 'Henüz takip edilen oran yok. Değişen bir oranda Oran geçmişi düğmesine dokunarak burada takip et.',\n asOf: (time) => `Fiyatlar ${time} itibarıyla`,\n graceNote: 'Bir sonraki açılışta kaldırılır · en geç 4 saat',\n suspendedLabel: 'Askıda',\n fullTimeLabel: 'Maç sonu',\n ownGoalLabel: 'KK',\n inSlipLabel: 'Kuponda',\n openMatch: (home, away) => (home && away ? `${home} - ${away} maçını aç` : 'Maçı aç'),\n oddsUnavailable: 'Oranlar şu anda kullanılamıyor',\n momentumLabel: 'Momentum',\n liveFactLabel: 'Canlı bilgi',\n liveFactAsk: 'Bunu sor',\n liveFactEarlier: (n: number) => `Önceki bilgiler (${n})`,\n liveFactHideEarlier: 'Önceki bilgileri gizle',\n accordionRetry: 'Oranlar yüklenemedi — yeniden dene',\n accordionSuspended: 'Askıda',\n tabToday: 'Bugün',\n sectionLive: 'Canlı',\n halfTime: 'İY',\n staleStates: 'Canlı skorlar güncellenemiyor — son bilinen durum gösteriliyor.',\n tabGames: 'Oyunlar',\n tabLeaderboard: 'Lider Tablosu',\n gamesLoginRequired: 'Oynamak ve lider tablosuna girmek için giriş yapın',\n back: 'Geri',\n leaderboardOffBoard: 'İlk 50 dışında',\n leaderboardThisWeek: 'Bu hafta',\n leaderboardAllTime: 'Tüm zamanlar',\n leaderboardEmptyFreshTitle: 'Yeni hafta, temiz sayfa',\n leaderboardEmptyFreshBody: 'Henüz skor yok. Oynayan ilk taraftar 1. sıraya geçer.',\n leaderboardEmptyColdTitle: 'İlk sen ol',\n leaderboardEmptyColdBody: 'Panoda henüz kimse yok. Bir oyun oyna, 1. sıra senin.',\n leaderboardEmptyCta: 'Bugünün oyunlarını oyna',\n leaderboardLastWeekLabel: 'Geçen hafta',\n leaderboardAllTimeEmpty: 'Tüm zamanlar panosu taraftarlar oynadıkça dolar — henüz bir şey yok.',\n gamePlay: 'Oyna',\n gameLocked: 'Kilitli',\n gameVoided: 'İptal edildi',\n games: {\n lang: 'tr',\n dailyChallenge: 'Günün meydan okuması',\n playNow: 'Hemen oyna',\n dailyGames: 'Günlük oyunlar',\n newSetAtMidnight: 'Yeni set gece yarısı',\n matchdayGames: 'Maç günü oyunları',\n kickoffAt: (t) => `Başlama ${t}`,\n statStreak: 'Seri',\n statToday: 'Bugün',\n statRank: 'Sıra',\n unitDays: 'gün',\n unitPts: 'puan',\n thisWeek: 'bu hafta',\n newToday: 'Bugün yeni',\n resume: 'Devam et',\n done: 'Tamamlandı',\n doneWithScore: (s) => `Tamamlandı · +${formatPtsTr(s)}`,\n locksAt: (t) => `Kilit ${t}`,\n formatPts: formatPtsTr,\n loading: 'Yükleniyor…',\n backToGames: 'Oyunlara dön',\n alreadyPlayedTitle: 'Bugün oynadın',\n guess: 'Tahmin',\n formatDayTime: (iso) =>\n new Intl.DateTimeFormat('tr-TR', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n titles: {\n 'mystery-tiger': 'Gizemli Oyuncu',\n 'daily-quiz': 'Günün Testi',\n 'career-path': 'Kariyer Yolu',\n 'beat-the-grid': 'Tabloyu Tamamla',\n 'guess-the-xi': 'Bu 11 Kimin?',\n 'higher-or-lower': 'Fazla mı, Az mı?',\n 'matchday-predictor': 'Skor Tahmini',\n 'starting-xi': 'İlk 11 Tahmini',\n 'stat-ladder': 'İstatistik Merdiveni',\n 'fan-motm': 'Maçın Oyuncusu',\n },\n taglines: {\n 'mystery-tiger': 'Bir oyuncu. Altı tahmin.',\n 'higher-or-lower': 'Kimin daha fazlası var?',\n 'guess-the-xi': 'Takımı bil',\n 'daily-quiz': 'Kulüp bilgini sına',\n 'career-path': 'Kulüpleri takip et',\n 'beat-the-grid': '9 hücreyi doldur',\n 'matchday-predictor': 'Skoru tahmin et',\n 'starting-xi': 'İlk 11’i seç',\n 'stat-ladder': 'Eksik basamağı bul',\n 'fan-motm': 'Maç sonunda oy ver',\n },\n mysteryTiger: {\n eyebrow: 'Günlük · 00:00’da yenilenir',\n labels: { position: 'POZ', nationality: 'UYR', age: 'YAŞ', shirtNumber: 'NO.', apps: 'MAÇ' },\n yourGuesses: 'Tahminlerin',\n legendMatch: 'Eşleşme',\n legendClose: 'Yakın',\n legendHigher: 'Gizli oyuncu daha yüksek',\n searchLabel: 'Kadrodan bir oyuncu tahmin et',\n searchPlaceholder: 'İsimle ara',\n optionsLabel: 'Kadro oyuncuları',\n progress: (used, total) => `${total} tahminden ${used} kullanıldı`,\n solved: 'Buldun!',\n failed: 'Tahmin hakkın bitti',\n detail: (n) => `${n} tahmin · yarın yine gel`,\n },\n higherOrLower: {\n eyebrow: (p) => `Doğru başına +${p}`,\n streak: 'Seri',\n whoHadMore: 'Kimin daha fazlası var',\n season: (l) => `${l} sezonu`,\n higher: 'Daha fazla',\n lower: 'Daha az',\n vs: 'VS',\n lastAnswer: (name, value) => `${name}: ${value}`,\n answersSoFar: (a, total) => `${total} eşleşmeden ${a} yanıtlandı`,\n runOver: 'Seri bitti',\n perfectRun: 'Kusursuz seri!',\n runDetail: (c) => `Üst üste ${c} doğru · yarın yine gel`,\n },\n guessTheXi: {\n pitchLabel: 'Uyruklara göre ilk 11',\n notThem: 'Bunlar değil:',\n whichClub: (left) => `Bu hangi kulüp? · ${left} hak kaldı`,\n searchPlaceholder: 'Kulüp ara',\n optionsLabel: 'Kulüpler',\n solved: 'Bildin!',\n failed: 'Tahmin hakkın bitti',\n detail: (n) => `${n} tahmin · yarın yine gel`,\n theAnswer: 'Doğru cevap',\n },\n dailyQuiz: {\n questionOf: (i, n) => `Soru ${i} / ${n}`,\n results: 'Sonuçlar',\n next: 'İleri',\n previous: 'Önceki',\n submit: 'Gönder',\n submitting: 'Gönderiliyor…',\n correctOf: (c, n) => `${n} soruda ${c} doğru`,\n progressAria: (i, n) => `Soru ${i} / ${n}`,\n },\n careerPath: {\n eyebrow: 'En eski kulüp önce',\n mysteryPlayer: 'Gizemli oyuncu',\n lockPosition: 'Mevki',\n lockNationality: 'Uyruk',\n firstClub: 'İlk kulüp',\n loan: 'Kiralık',\n nextClubHidden: 'Sıradaki kulüp — yanlış tahminden sonra açılır',\n moreClubs: (k) => `+ ${k} kulüp daha`,\n searchLabel: 'Bu kim?',\n searchPlaceholder: 'Herhangi bir oyuncu ara',\n solved: 'Kariyer çözüldü!',\n failed: 'Tahmin hakkın bitti',\n guessesLine: (n) => `${n} tahmin · yarın tekrar gel`,\n },\n beatTheGrid: {\n eyebrow: 'Her hücreye uyan bir oyuncu yerleştir',\n filled: (n, t) => `${t} hücreden ${n} dolu`,\n toGo: (n) => `${n} kaldı`,\n progressAria: (n, t) => `${t} hücreden ${n} dolu`,\n rowAbbrev: { Goalkeeper: 'KL', Defender: 'DEF', Midfielder: 'OS', Forward: 'FV' },\n pickCell: (r, c) => `${r} × ${c} için oyuncu seç`,\n cellFilled: (r, c, name, verdict) => `${r} × ${c}: ${name}, ${verdict.toLocaleLowerCase('tr')}`,\n correct: 'Doğru',\n wrong: 'Yanlış',\n closeSearch: 'Oyuncu aramayı kapat',\n searchLabel: (r, c) => `${r} × ${c} için oyuncu ara`,\n searchPlaceholder: 'Oyuncu ara',\n emptyPool: 'Henüz aranacak oyuncu yok.',\n complete: 'Tablo tamamlandı',\n summary: (c, f) => `${f} hücrede ${c} doğru · yarın tekrar gel`,\n },\n predictor: {\n eyebrow: (home, away) => `${home} - ${away}`,\n home: 'Ev sahibi',\n away: 'Deplasman',\n goalsUp: (team) => `${team} golünü artır`,\n goalsDown: (team) => `${team} golünü azalt`,\n firstScorer: 'İlk golü atan',\n optional: 'İsteğe bağlı',\n searchLabel: 'İlk golcüyü ara',\n searchPlaceholder: 'Kadroda ara',\n noScorer: 'İlk gol yok',\n save: 'Tahmini kaydet',\n saving: 'Kaydediliyor…',\n closed: 'Tahminler kapandı',\n saved: 'Tahmin kaydedildi',\n savedDetail: (p) =>\n `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ilk gol ${p.scorer}` : ''} · sonuç bekleniyor`,\n fullTime: (h, a) => `Maç sonu ${h} – ${a}`,\n exactScore: 'Tam skor',\n outcome: 'Sonuç (G/B/M)',\n firstScorerRow: 'İlk golü atan',\n correct: 'Doğru',\n incorrect: 'Yanlış',\n forFun: 'Eğlence için — sıralamaya girmez',\n },\n startingXi: {\n eyebrow: 'Kadroyu tahmin et',\n perStarter: (n) => `İlk 11 oyuncu başına +${n}`,\n picked: (n) => `11 oyuncudan ${n} seçildi`,\n toGo: (n) => `${n} kaldı`,\n pickSlot: (pos) => `${pos} seç`,\n clearSlot: (pos, name) => `${name} oyuncusunu ${pos} mevkiinden çıkar`,\n pickFor: (pos) => `${pos} için oyuncu seç`,\n allPicked: '11 oyuncu seçildi — değiştirmek için sahadaki oyuncuya dokun',\n searchLabel: 'Kadroda ara',\n submit: 'İlk 11’imi kilitle',\n submitting: 'Gönderiliyor…',\n locksAt: (t) => `${t} kilitlenir, başlamadan yaklaşık bir saat önce`,\n locksSoon: 'Başlamadan yaklaşık bir saat önce kilitlenir',\n pending: (n) => `Tahmin kilitlendi (${n} oyuncu) — sonuç bekleniyor`,\n gradedLine: (c) => `11 oyuncudan ${c} doğru`,\n voided: 'Bu oyun iptal edildi',\n },\n motm: {\n title: 'Maçın Oyuncusu',\n eyebrow: 'Taraftar oylaması',\n voted: 'Oy verildi',\n yourVote: 'Oy verdiğin',\n youVoted: (name) => `${name} için oy verdin`,\n thanks: 'Teşekkürler — bu oylamanın sonuçları gösterilmiyor',\n tapToVote: 'Oy vermek için bir oyuncuya dokun',\n forFun: 'Eğlence için — sıralamaya girmeyen taraftar oylaması',\n },\n statLadder: {\n eyebrow: 'Son maç',\n question: (stat) => ({ pre: `${stat.toLocaleLowerCase('tr')} sıralamasında `, emph: '2. sırada', post: ' kim var?' }),\n whoSecond: '2. kim?',\n clue: (c, stat) => {\n const parts: string[] = []\n if (c.above) parts.push(c.above.diff === 0 ? `${c.above.name} ile aynı` : `${c.above.name} oyuncusundan ${c.above.diff} eksik`)\n if (c.below) parts.push(c.below.diff === 0 ? `${c.below.name} ile aynı` : `${c.below.name} oyuncusundan ${c.below.diff} fazla`)\n return `${c.value} ${stat.toLocaleLowerCase('tr')}${parts.length ? `: ${parts.join(' ve ')}` : ''}.`\n },\n searchLabel: '2. oyuncuyu tahmin et',\n searchPlaceholder: 'Kadroda ara',\n guess: 'Tahmin et',\n correct: 'Doğru!',\n wrong: (name) => `Yanlış — doğru cevap ${name}`,\n },\n },\n },\n}\n\nexport function resolveLocaleStrings(locale?: string): LocaleStrings {\n return STRINGS[locale as Locale] ?? STRINGS.en\n}\n\n/** True unless the locale's language is one the widget supports other than English; a missing\n * or unsupported locale counts as English. Matches on the language subtag, so \"tr-TR\" is Turkish. */\nexport function isEnglishLocale(locale?: string): boolean {\n const lang = (locale ?? '').trim().toLowerCase().split(/[-_]/)[0] ?? ''\n return lang === 'en' || !Object.prototype.hasOwnProperty.call(STRINGS, lang)\n}\n","import type { AddToSlipHandler, StatsWidgetClientOptions, UserContext } from '@sensiblestats/widget-sdk'\nimport { isEnglishLocale, resolveLocaleStrings } from './i18n'\nimport type { GamesStrings } from './i18n'\n\nexport interface StatsWidgetConfig {\n operatorId: string\n publicKey: string\n baseUrl?: string\n userContext?: UserContext\n theme?: 'light' | 'dark' | 'auto'\n accent?: string\n position?: 'left' | 'right'\n offset?: { x?: number; y?: number }\n radius?: number\n /** BCP-47-ish locale code for the widget's own chrome text (e.g. \"en\", \"tr\"). Defaults to \"en\". */\n locale?: string\n launcherLabel?: string\n greeting?: string\n /** Message auto-sent once on load (e.g. \"hello\"); its response shows as the launcher popup. */\n greetingMessage?: string\n placeholder?: string\n starters?: string[]\n injectStyles?: boolean\n /** Called when the user adds an insight's selection to the operator's slip. */\n onAddToSlip?: AddToSlipHandler\n /** Called when the user taps a match in the widget; take them to your match page. Team names\n * become links only when this is set. A thrown error or a rejected promise is ignored. */\n onOpenMatch?: (match: { matchId: number }) => void | Promise<void>\n\n // — Branding —\n /** Operator logo; replaces the SS mark in the header and the FAB launcher. */\n logoUrl?: string\n /** Header title text. Default \"SensibleStats\". */\n headerTitle?: string\n /** CTA color → --ss-w-cta. */\n cta?: string\n /** Panel/surface color → --ss-w-panel. Pair with `ink`. */\n surface?: string\n /** Primary text color → --ss-w-ink. Pair with `surface`. */\n ink?: string\n /** Icon used for the pin/save toggle on matches and odds. Default \"pin\". */\n pinIcon?: 'pin' | 'star' | 'bookmark'\n}\n\ntype UiKeys =\n | 'theme' | 'accent' | 'position' | 'offset' | 'radius' | 'locale'\n | 'launcherLabel' | 'greeting' | 'greetingMessage' | 'placeholder' | 'starters' | 'injectStyles'\n | 'logoUrl' | 'headerTitle' | 'cta' | 'surface' | 'ink' | 'pinIcon'\n\nexport interface UiConfig {\n theme: 'light' | 'dark' | 'auto'\n accent?: string\n position: 'left' | 'right'\n offset: { x: number; y: number }\n radius: number\n launcherLabel: string\n greeting?: string\n greetingMessage?: string\n placeholder: string\n starters: string[]\n injectStyles: boolean\n logoUrl?: string\n headerTitle?: string\n /** The server localizes betting labels for non-English widgets (\"2.5 Üst\"), so only an English\n * widget can report the label it shows as the raw slip selection. */\n rawBettingLabels: boolean\n cta?: string\n surface?: string\n ink?: string\n pinIcon: 'pin' | 'star' | 'bookmark'\n closeChat: string\n newConversation: string\n moreOptions: string\n chatDialogLabel: string\n stopResponse: string\n sendMessage: string\n dismissGreeting: string\n somethingWentWrong: string\n retry: string\n showLess: string\n showMore: (n: number) => string\n oddsLabel: string\n liveLabel: string\n marketFloorLabel: string\n marketPrices: string\n moreLines: string\n hideLines: string\n oddsMoved: (was: string, now: string, direction: string) => string\n oddsShortened: string\n oddsDrifted: string\n updatedLabel: string\n priceMovement: string\n openingLabel: string\n currentLabel: string\n movementWindow: (hours: number) => string\n notEnoughHistory: string\n singlePricePoint: string\n selectionSuspended: string\n excludedSuspended: (n: number) => string\n chartTimeLabel: (ms: number) => string\n chartAria: (opening: string, current: string, direction: string, hours: number) => string\n addToSlip: string\n inSlip: string\n slipAdded: string\n slipDuplicate: string\n slipPriceChanged: (from: string, to: string) => string\n slipPriceNotAccepted: (from: string, to: string) => string\n slipLoginRequired: string\n slipSuspended: string\n slipFailed: string\n today: string\n tomorrow: string\n bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n tabChat: string\n tabFollowing: string\n tabOdds: string\n tabToday: string\n sectionLive: string\n halfTime: string\n staleStates: string\n pinLabel: string\n unpinLabel: string\n matchPinLabel: string\n matchUnpinLabel: string\n matchLimitToast: string\n marketLimitToast: string\n priceHistoryLabel: string\n emptyMatchesTab: string\n emptyOddsTab: string\n asOf: (time: string) => string\n graceNote: string\n suspendedLabel: string\n fullTimeLabel: string\n ownGoalLabel: string\n inSlipLabel: string\n openMatch: (home?: string, away?: string) => string\n oddsUnavailable: string\n momentumLabel: string\n liveFactLabel: string\n liveFactAsk: string\n liveFactEarlier: (n: number) => string\n liveFactHideEarlier: string\n accordionRetry: string\n accordionSuspended: string\n tabGames: string\n tabLeaderboard: string\n gamesLoginRequired: string\n back: string\n leaderboardOffBoard: string\n leaderboardThisWeek: string\n leaderboardAllTime: string\n leaderboardEmptyFreshTitle: string\n leaderboardEmptyFreshBody: string\n leaderboardEmptyColdTitle: string\n leaderboardEmptyColdBody: string\n leaderboardEmptyCta: string\n leaderboardLastWeekLabel: string\n leaderboardAllTimeEmpty: string\n gamePlay: string\n gameLocked: string\n gameVoided: string\n games: GamesStrings\n}\n\nexport function normalizeUi(cfg: Pick<StatsWidgetConfig, UiKeys>): UiConfig {\n const strings = resolveLocaleStrings(cfg.locale)\n return {\n theme: cfg.theme ?? 'auto',\n accent: cfg.accent,\n logoUrl: cfg.logoUrl,\n headerTitle: cfg.headerTitle,\n rawBettingLabels: isEnglishLocale(cfg.locale),\n cta: cfg.cta,\n surface: cfg.surface,\n ink: cfg.ink,\n pinIcon: cfg.pinIcon ?? 'pin',\n position: cfg.position ?? 'right',\n offset: { x: cfg.offset?.x ?? 20, y: cfg.offset?.y ?? 20 },\n radius: cfg.radius ?? 16,\n launcherLabel: cfg.launcherLabel ?? strings.launcherLabel,\n greeting: cfg.greeting,\n greetingMessage: cfg.greetingMessage,\n placeholder: cfg.placeholder ?? strings.placeholder,\n starters: cfg.starters ?? [],\n injectStyles: cfg.injectStyles ?? true,\n closeChat: strings.closeChat,\n newConversation: strings.newConversation,\n moreOptions: strings.moreOptions,\n chatDialogLabel: strings.chatDialogLabel,\n stopResponse: strings.stopResponse,\n sendMessage: strings.sendMessage,\n dismissGreeting: strings.dismissGreeting,\n somethingWentWrong: strings.somethingWentWrong,\n retry: strings.retry,\n showLess: strings.showLess,\n showMore: strings.showMore,\n oddsLabel: strings.oddsLabel,\n liveLabel: strings.liveLabel,\n marketFloorLabel: strings.marketFloorLabel,\n marketPrices: strings.marketPrices,\n moreLines: strings.moreLines,\n hideLines: strings.hideLines,\n oddsMoved: strings.oddsMoved,\n oddsShortened: strings.oddsShortened,\n oddsDrifted: strings.oddsDrifted,\n updatedLabel: strings.updatedLabel,\n priceMovement: strings.priceMovement,\n openingLabel: strings.openingLabel,\n currentLabel: strings.currentLabel,\n movementWindow: strings.movementWindow,\n notEnoughHistory: strings.notEnoughHistory,\n singlePricePoint: strings.singlePricePoint,\n selectionSuspended: strings.selectionSuspended,\n excludedSuspended: strings.excludedSuspended,\n chartTimeLabel: strings.chartTimeLabel,\n chartAria: strings.chartAria,\n addToSlip: strings.addToSlip,\n inSlip: strings.inSlip,\n slipAdded: strings.slipAdded,\n slipDuplicate: strings.slipDuplicate,\n slipPriceChanged: strings.slipPriceChanged,\n slipPriceNotAccepted: strings.slipPriceNotAccepted,\n slipLoginRequired: strings.slipLoginRequired,\n slipSuspended: strings.slipSuspended,\n slipFailed: strings.slipFailed,\n today: strings.today,\n tomorrow: strings.tomorrow,\n bettingKickoff: strings.bettingKickoff,\n tabChat: strings.tabChat,\n tabFollowing: strings.tabFollowing,\n tabOdds: strings.tabOdds,\n tabToday: strings.tabToday,\n sectionLive: strings.sectionLive,\n halfTime: strings.halfTime,\n staleStates: strings.staleStates,\n pinLabel: strings.pinLabel,\n unpinLabel: strings.unpinLabel,\n matchPinLabel: strings.matchPinLabel,\n matchUnpinLabel: strings.matchUnpinLabel,\n matchLimitToast: strings.matchLimitToast,\n marketLimitToast: strings.marketLimitToast,\n priceHistoryLabel: strings.priceHistoryLabel,\n emptyMatchesTab: strings.emptyMatchesTab,\n emptyOddsTab: strings.emptyOddsTab,\n asOf: strings.asOf,\n graceNote: strings.graceNote,\n suspendedLabel: strings.suspendedLabel,\n fullTimeLabel: strings.fullTimeLabel,\n ownGoalLabel: strings.ownGoalLabel,\n inSlipLabel: strings.inSlipLabel,\n openMatch: strings.openMatch,\n oddsUnavailable: strings.oddsUnavailable,\n momentumLabel: strings.momentumLabel,\n liveFactLabel: strings.liveFactLabel,\n liveFactAsk: strings.liveFactAsk,\n liveFactEarlier: strings.liveFactEarlier,\n liveFactHideEarlier: strings.liveFactHideEarlier,\n accordionRetry: strings.accordionRetry,\n accordionSuspended: strings.accordionSuspended,\n tabGames: strings.tabGames,\n tabLeaderboard: strings.tabLeaderboard,\n gamesLoginRequired: strings.gamesLoginRequired,\n back: strings.back,\n leaderboardOffBoard: strings.leaderboardOffBoard,\n leaderboardThisWeek: strings.leaderboardThisWeek,\n leaderboardAllTime: strings.leaderboardAllTime,\n leaderboardEmptyFreshTitle: strings.leaderboardEmptyFreshTitle,\n leaderboardEmptyFreshBody: strings.leaderboardEmptyFreshBody,\n leaderboardEmptyColdTitle: strings.leaderboardEmptyColdTitle,\n leaderboardEmptyColdBody: strings.leaderboardEmptyColdBody,\n leaderboardEmptyCta: strings.leaderboardEmptyCta,\n leaderboardLastWeekLabel: strings.leaderboardLastWeekLabel,\n leaderboardAllTimeEmpty: strings.leaderboardAllTimeEmpty,\n gamePlay: strings.gamePlay,\n gameLocked: strings.gameLocked,\n gameVoided: strings.gameVoided,\n games: strings.games,\n }\n}\n\nexport function toClientOptions(cfg: StatsWidgetConfig): StatsWidgetClientOptions {\n const opts: StatsWidgetClientOptions = { operatorId: cfg.operatorId, publicKey: cfg.publicKey }\n if (cfg.baseUrl !== undefined) opts.baseUrl = cfg.baseUrl\n return opts\n}\n\nexport function toUserContext(cfg: StatsWidgetConfig): UserContext | undefined {\n return cfg.userContext && Object.keys(cfg.userContext).length > 0 ? cfg.userContext : undefined\n}\n","import type { AddToSlipHandler, AddToSlipResult, LiveMonitorStatPrice, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from './config'\n\nexport const ADD_TO_SLIP_TIMEOUT_MS = 10_000\n\nexport interface SlipToast { kind: 'success' | 'error'; text: string }\n\nexport interface SlipHandlerProps {\n onAddToSlip?: AddToSlipHandler\n conversationId?: string\n}\n\nexport interface SlipPickFields { matchId?: number; selection?: string; line?: string; odds?: number }\n\nexport const MAX_SELECTION = 64\nexport const MAX_LINE = 32\nexport const MAX_ODDS = 10_000\n\n// The gateway rejects the whole batch when one event breaks a length or range rule, so a value\n// that would fail validation is dropped from the pick rather than risking every queued event.\nexport function slipPickFields(selection: SlipSelection, label?: string, line?: string): SlipPickFields {\n const fields: SlipPickFields = {}\n if (Number.isSafeInteger(selection.matchId) && selection.matchId > 0) fields.matchId = selection.matchId\n if (label && label.trim() && label.length <= MAX_SELECTION) fields.selection = label\n if (line && line.trim() && line.length <= MAX_LINE) fields.line = line\n const odds = selection.oddsDecimal\n if (Number.isFinite(odds) && odds > 1 && odds <= MAX_ODDS) fields.odds = odds\n return fields\n}\n\n// Shared by every market-chip renderer (stat rows, live facts): a chip only becomes a slip\n// selection when it carries a real, addable price -- otherwise there's nothing to submit.\nexport function chipSelection(market: LiveMonitorStatPrice | null | undefined, matchId: number, conversationId?: string): SlipSelection | null {\n if (!market || !market.addToSlipEnabled || typeof market.matchOddsId !== 'number' || typeof market.price !== 'number') return null\n const selection: SlipSelection = { matchOddsId: market.matchOddsId, matchId, oddsDecimal: market.price }\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n\nexport function wasAdded(result: AddToSlipResult | void): boolean {\n if (!result) return true\n if (result.status === 'price_changed') return result.accepted\n return result.status === 'added'\n}\n\nexport function isTerminal(result: AddToSlipResult | void): boolean {\n if (!result) return true\n if (result.status === 'price_changed') return result.accepted\n return result.status === 'added' || result.status === 'duplicate'\n}\n\n// slip_result's `outcome`: 'added' on success (including the assumed-success void/duplicate/\n// accepted-price-change cases), else the specific reject reason string -- so a downstream\n// consumer can tell \"the user added it\" from \"why it was refused\" without re-deriving toast text.\nexport function slipOutcome(result: AddToSlipResult | void): string {\n if (!result) return 'added'\n switch (result.status) {\n case 'added':\n case 'duplicate':\n return result.status\n case 'price_changed':\n return result.accepted ? 'added' : 'price_changed'\n case 'rejected':\n return result.reason\n }\n}\n\nexport function resultToToast(result: AddToSlipResult | void, shownOdds: string, ui: UiConfig): SlipToast {\n if (!result) return { kind: 'success', text: ui.slipAdded }\n switch (result.status) {\n case 'added':\n return { kind: 'success', text: ui.slipAdded }\n case 'duplicate':\n return { kind: 'success', text: ui.slipDuplicate }\n case 'price_changed':\n return result.accepted\n ? { kind: 'success', text: ui.slipPriceChanged(shownOdds, result.newOddsDecimal.toFixed(2)) }\n : { kind: 'error', text: ui.slipPriceNotAccepted(shownOdds, result.newOddsDecimal.toFixed(2)) }\n case 'rejected':\n if (result.reason === 'login_required') return { kind: 'error', text: ui.slipLoginRequired }\n if (result.reason === 'suspended') return { kind: 'error', text: ui.slipSuspended }\n return { kind: 'error', text: result.message ?? ui.slipFailed }\n }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\nimport { FULLSCREEN_QUERY } from './components/ChatPanel'\nimport type { StatsWidgetConfig, UiConfig } from './config'\nimport { attachHost, type HostSink, type WidgetHost } from './host'\nimport type { MatchLinkValue } from './matchLinkContext'\nimport { createMatchViews } from './matchViews'\nimport { BET_REPORT_MAX, createSlipLedger, toSlipEvent } from './slipLedger'\nimport type { SlipAdd, SlipState } from './slipStateContext'\n\nexport interface HostEventsOptions {\n host: WidgetHost | undefined\n operatorId: string\n /** operatorUserId of the visitor; undefined when anonymous. */\n currentUser: string | undefined\n logger: EventLogger | null\n isOpen: boolean\n closePanel: () => void\n onOpenMatch: StatsWidgetConfig['onOpenMatch']\n openMatchLabel: UiConfig['openMatch']\n}\n\nexport interface HostEvents {\n slipState: SlipState\n /** Arms the Odds tab badge for an odd the widget added to the slip. */\n markAdded(matchOddsId: number): void\n /** Null unless the operator passed onOpenMatch: without it nothing renders as a link. */\n matchLink: MatchLinkValue | null\n}\n\n/** The part of the widget the operator's side can change, and what the widget reports about it. */\nexport function useHostEvents(opts: HostEventsOptions): HostEvents {\n const { host, operatorId, currentUser, logger, isOpen, closePanel, onOpenMatch, openMatchLabel } = opts\n\n // The two marks live here, not in the button or the monitor hook, so a host call can clear\n // them. `added` arms the Odds tab badge; `settled` flips a button to \"In slip\".\n const [added, setAdded] = useState<Record<number, true>>({})\n const [settled, setSettled] = useState<Record<number, true>>({})\n const markAdded = useCallback((matchOddsId: number) => {\n setAdded((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n }, [])\n const settle = useCallback((matchOddsId: number) => {\n setSettled((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n }, [])\n const clearMarks = useCallback((ids: readonly number[]) => {\n const drop = (prev: Record<number, true>): Record<number, true> => {\n if (!ids.some((id) => prev[id])) return prev\n const next = { ...prev }\n for (const id of ids) delete next[id]\n return next\n }\n setAdded(drop)\n setSettled(drop)\n }, [])\n\n const hasHost = host !== undefined\n // Only an operator that passed a host can ever read the ledger, so only then is it written.\n const ledger = useMemo(\n () => (hasHost ? createSlipLedger(`ss-w-slip:${operatorId}`) : null),\n [hasHost, operatorId],\n )\n const currentUserRef = useRef(currentUser)\n currentUserRef.current = currentUser // latest-value pattern; recordAdd stays stable across logins\n const recordAdd = useCallback((add: SlipAdd) => {\n ledger?.record({ id: add.selection.matchOddsId, market: add.market, ...add.pick, user: currentUserRef.current })\n }, [ledger])\n const slipState = useMemo<SlipState>(\n () => ({ added, settled, settle, recordAdd }),\n [added, settled, settle, recordAdd],\n )\n\n const hasOpenMatch = typeof onOpenMatch === 'function'\n const tracksViews = hasHost || hasOpenMatch\n // What this tab has already reported about match views. Keyed on the user as well, so a login\n // or logout starts from the state stored for that visitor.\n const views = useMemo(\n () => (tracksViews ? createMatchViews(`ss-w-views:${operatorId}`, { user: currentUser }) : null),\n [tracksViews, operatorId, currentUser],\n )\n\n // What a host call does. It lives in a ref so the attach effect below depends only on the host,\n // while every call still sees the latest logger, ledger and user (the latest-fn pattern).\n const sinkRef = useRef<HostSink>(() => {})\n sinkRef.current = (command) => {\n if (command.kind === 'matchOpened') {\n if (views?.view(command.matchId) === 'log') {\n logger?.log({ name: 'match_view', entityType: 'match', entityId: String(command.matchId) })\n }\n return\n }\n const name = command.kind === 'slipRemoved' ? 'slip_remove' : 'bet_placed'\n const ids = command.kind === 'slipRemoved' ? [command.matchOddsId] : command.matchOddsIds\n // The marks clear for any odd the host names. Only an odd the widget itself added, a ledger\n // hit, is reported: the host passes every leg without filtering.\n clearMarks(ids)\n if (!ledger) return\n let reported = 0\n for (const id of ids) {\n const entry = ledger.take(id, currentUser)\n if (!entry || reported >= BET_REPORT_MAX) continue\n reported++\n logger?.log(toSlipEvent(name, entry))\n }\n }\n useEffect(() => {\n if (!host) return\n return attachHost(host, (command) => sinkRef.current(command))\n }, [host])\n\n // A view is reported only for a visitor who has opened the panel in this tab. The first open\n // logs what was held until then and sends it; a view is otherwise deferred and starts no\n // request of its own. `views` changes with the user, so a login while the panel is open\n // re-runs this for the new visitor.\n useEffect(() => {\n if (!isOpen || !views) return\n const held = views.markOpened()\n if (held.length === 0) return\n for (const matchId of held) {\n logger?.log({ name: 'match_view', entityType: 'match', entityId: String(matchId) })\n }\n void logger?.flushNow()\n }, [isOpen, views, logger])\n\n // What a tap on a match link does. In a ref for the same reason as the sink: the context value\n // below stays stable while the tap still sees the latest handler, logger and view state.\n const openMatchRef = useRef<(matchId: number) => void>(() => {})\n openMatchRef.current = (matchId) => {\n // The tap and the page view that follows it share one `seen` entry, so one visit to a match\n // writes one row.\n if (views?.view(matchId) === 'log') {\n logger?.log({ name: 'match_open', entityType: 'match', entityId: String(matchId) })\n }\n try {\n const done = onOpenMatch?.({ matchId })\n if (done && typeof done.then === 'function') done.then(undefined, () => {})\n } catch {\n // an operator handler that throws must not break the widget\n }\n // On a phone the panel covers the page, so the match page would open behind it.\n if (typeof window.matchMedia === 'function' && window.matchMedia(FULLSCREEN_QUERY).matches) closePanel()\n }\n const matchLink = useMemo<MatchLinkValue | null>(\n () => (hasOpenMatch ? { open: (matchId) => openMatchRef.current(matchId), label: openMatchLabel } : null),\n [hasOpenMatch, openMatchLabel],\n )\n\n return { slipState, markAdded, matchLink }\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { ChatHeader } from './ChatHeader'\nimport { MessageList } from './MessageList'\nimport { ChatInput } from './ChatInput'\nimport { TabBar } from './TabBar'\nimport { MatchesPanel, OddsPanel } from './MonitorTabs'\nimport type { AskHandler } from './LiveFactBlock'\nimport { TodayPanel } from './TodayPanel'\nimport { GamesPanel } from './GamesPanel'\nimport { LeaderboardPanel } from './LeaderboardPanel'\nimport { visibleGroupsOf } from '../liveClock'\n\n// Mirrors the panel's fullscreen breakpoint in widget.css (@media max-width: 639px).\n// The panel only traps the page — and is thus truly modal — when it fills the viewport.\nexport const FULLSCREEN_QUERY = '(max-width: 639px)'\n\nfunction useIsModal(): boolean {\n const [modal, setModal] = useState(false)\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return\n const mql = window.matchMedia(FULLSCREEN_QUERY)\n const sync = (): void => setModal(mql.matches)\n sync()\n mql.addEventListener('change', sync)\n return () => mql.removeEventListener('change', sync)\n }, [])\n return modal\n}\n\nexport function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }: {\n controller: ChatController\n ui: UiConfig\n slip: SlipHandlerProps\n onDashboardTap?: DashboardTapHandler\n /** Optional -- absent (feature off / not threaded) renders today's DOM byte-identically. */\n monitor?: LiveMonitorController\n /** Optional -- absent means the Today tab never qualifies (see hasToday below). */\n discovery?: MatchDiscoveryController\n /** Games hook result; absent for non-club operators. */\n gamesResult?: { enabled: boolean; games: GameSummary[]; loading: boolean; refresh: () => void }\n /** Leaderboard hook result; absent for non-club operators. */\n leaderboardResult?: { data: LeaderboardPayload | null; loading: boolean; refresh: () => void }\n /** True when the operator user is logged in (operatorUserId is set). */\n loggedIn?: boolean\n /** Conversation instance threaded down to GameScreenHost for game config fetching + play submits. */\n conversation?: GamePlayConversation | null\n}): JSX.Element {\n const { state, close, stop, send, reset } = controller\n const isModal = useIsModal()\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close() }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [close])\n\n // Composer always switches the visible tab to chat BEFORE the message is sent, so a reply\n // streaming in is never invisible behind the Matches/Odds tab.\n const handleSend = (text: string) => {\n monitor?.setActiveTab('chat')\n send(text)\n }\n\n // \"Ask about this\" on a live fact: same tab-first rule as the composer, plus the grounding the\n // server turns into [live_facts] context (spec §6).\n const handleAsk: AskHandler = (text, grounding) => {\n monitor?.setActiveTab('chat')\n send(text, { grounding })\n }\n\n // A reply landing while the user is on another tab must surface the chat dot -- markChatActivity\n // is idempotent (setChatDot(true) on an already-true dot is a no-op re-render), so re-running\n // this on every streaming/message-count change is safe.\n useEffect(() => {\n if (monitor && monitor.activeTab !== 'chat' && state.isStreaming) monitor.markChatActivity()\n }, [monitor, state.isStreaming, state.messages.length])\n\n return (\n <div className=\"ss-w-panel\" role=\"dialog\" aria-modal={isModal} aria-label={ui.chatDialogLabel}>\n <ChatHeader\n onClose={close}\n closeLabel={ui.closeChat}\n logoUrl={ui.logoUrl}\n headerTitle={ui.headerTitle}\n onNewConversation={reset}\n canReset={state.messages.length > 0}\n newConversationLabel={ui.newConversation}\n moreOptionsLabel={ui.moreOptions}\n />\n {monitor && (\n <TabBar\n monitor={monitor}\n ui={ui}\n matchCount={monitor.pins.filter((p) => p.kind === 'match').length}\n oddsCount={monitor.pins.filter((p) => p.kind !== 'match').length}\n todayCount={discovery?.liveCount ?? 0}\n hasToday={discovery ? visibleGroupsOf(discovery.groups, discovery.states).length > 0 : false}\n gamesEnabled={gamesResult?.enabled ?? false}\n />\n )}\n {/* MessageList stays MOUNTED across tab switches so its scroll-anchoring refs survive --\n `display: contents` makes the wrapper transparent to .ss-w-panel's flex layout when the\n chat tab is active. `display: none` would zero the list's clientHeight and reset its\n scrollTop, defeating MessageList's own scroll-anchoring math (and silently consuming its\n reserved-turn-space effect) the moment a tab switch happens mid-stream. Absolute-position\n + visibility:hidden instead: the list keeps its box (so its scroll position survives) but\n is pulled out of .ss-w-panel's flex flow (so it doesn't fight the active panel for space)\n and is neither painted nor interactive. `.ss-w-panel` is `position: fixed`, which already\n serves as the containing block for this. */}\n <div\n style={\n !monitor || monitor.activeTab === 'chat'\n ? { display: 'contents' }\n // display:flex (not the default block) is required here: MessageList's root carries\n // `.ss-w-list { flex: 1; ... }`, which only takes effect on a flex-item child. Without\n // it this wrapper lays out as a plain block, .ss-w-list collapses to its own\n // content height (no longer clipped by .ss-w-panel's fixed height), scrollHeight\n // drops to equal clientHeight, and the browser clamps its scrollTop to 0 --\n // silently destroying the exact scroll position this hidden-not-unmounted\n // wrapper exists to preserve.\n : { position: 'absolute', inset: 0, visibility: 'hidden', display: 'flex', flexDirection: 'column' }\n }\n >\n <MessageList controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} monitor={monitor} />\n </div>\n {monitor && discovery && monitor.activeTab === 'today' && <TodayPanel discovery={discovery} ui={ui} monitor={monitor} />}\n {monitor && monitor.activeTab === 'following' && <MatchesPanel monitor={monitor} ui={ui} slip={slip} onAsk={handleAsk} />}\n {monitor && monitor.activeTab === 'odds' && <OddsPanel monitor={monitor} ui={ui} slip={slip} />}\n {monitor && monitor.activeTab === 'games' && gamesResult && (\n <GamesPanel\n loggedIn={!!loggedIn}\n games={gamesResult.games}\n ui={ui}\n conversation={conversation}\n leaderboard={leaderboardResult?.data ?? null}\n refreshHub={() => { gamesResult.refresh(); leaderboardResult?.refresh() }}\n />\n )}\n {monitor && monitor.activeTab === 'leaderboard' && leaderboardResult && (\n <LeaderboardPanel\n loggedIn={!!loggedIn}\n data={leaderboardResult.data}\n loading={leaderboardResult.loading}\n onPlay={() => monitor.setActiveTab('games')}\n ui={ui}\n />\n )}\n {/* The composer is a chat affordance; hide it on the Games/Leaderboard tabs where it only confuses. */}\n {(!monitor || (monitor.activeTab !== 'games' && monitor.activeTab !== 'leaderboard')) && (\n <ChatInput placeholder={ui.placeholder} streaming={state.isStreaming} onSend={handleSend} onStop={stop} stopLabel={ui.stopResponse} sendLabel={ui.sendMessage} />\n )}\n </div>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { CloseIcon, KebabIcon } from './Icons'\nimport { BrandMark } from './BrandMark'\n\nexport function ChatHeader({\n onClose,\n closeLabel = 'Close chat',\n logoUrl,\n headerTitle,\n onNewConversation,\n canReset,\n newConversationLabel = 'New conversation',\n moreOptionsLabel = 'More options',\n}: {\n onClose: () => void\n closeLabel?: string\n logoUrl?: string\n headerTitle?: string\n onNewConversation?: () => void\n canReset?: boolean\n newConversationLabel?: string\n moreOptionsLabel?: string\n}): JSX.Element {\n const [menuOpen, setMenuOpen] = useState(false)\n const wrapRef = useRef<HTMLDivElement>(null)\n const kebabRef = useRef<HTMLButtonElement>(null)\n const firstItemRef = useRef<HTMLButtonElement>(null)\n\n // Secondary actions (currently just \"New conversation\") live behind the kebab; Close stays a\n // one-tap control since it is the most frequent action.\n const hasMenu = !!(canReset && onNewConversation)\n\n useEffect(() => {\n if (menuOpen) firstItemRef.current?.focus()\n }, [menuOpen])\n\n useEffect(() => {\n if (!menuOpen) return\n const onPointer = (e: MouseEvent) => {\n if (!wrapRef.current?.contains(e.target as Node)) setMenuOpen(false)\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setMenuOpen(false)\n kebabRef.current?.focus()\n }\n }\n document.addEventListener('mousedown', onPointer)\n document.addEventListener('keydown', onKey)\n return () => {\n document.removeEventListener('mousedown', onPointer)\n document.removeEventListener('keydown', onKey)\n }\n }, [menuOpen])\n\n const runNewConversation = (): void => {\n setMenuOpen(false)\n onNewConversation?.()\n }\n\n return (\n <header className=\"ss-w-header\">\n <BrandMark logoUrl={logoUrl} className=\"ss-w-header-mark\" />\n <span className=\"ss-w-header-title\">{headerTitle ?? 'SensibleStats'}</span>\n {hasMenu ? (\n <div className=\"ss-w-menu-wrap\" ref={wrapRef}>\n <button\n type=\"button\"\n className=\"ss-w-kebab\"\n ref={kebabRef}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n aria-label={moreOptionsLabel}\n onClick={() => setMenuOpen((open) => !open)}\n >\n <KebabIcon />\n </button>\n {menuOpen ? (\n <div className=\"ss-w-menu\" role=\"menu\" aria-label={moreOptionsLabel}>\n <button\n type=\"button\"\n className=\"ss-w-menu-item\"\n role=\"menuitem\"\n ref={firstItemRef}\n onClick={runNewConversation}\n >\n <span>{newConversationLabel}</span>\n </button>\n </div>\n ) : null}\n </div>\n ) : null}\n <button type=\"button\" className=\"ss-w-close\" aria-label={closeLabel} onClick={onClose}>\n <CloseIcon />\n </button>\n </header>\n )\n}\n","// SensibleStats brand mark, inlined as a data URI so the published widget\n// bundle stays self-contained (no external asset hosting / CORS concerns\n// for third-party embeds).\nexport const SS_LOGO_DATA_URI = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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\"\n","// SensibleStats brand mark, rendered from the official logo asset.\nimport { SS_LOGO_DATA_URI } from '../assets/logo'\n\nexport function SsMark({ className }: { className?: string }): JSX.Element {\n return <img className={className} src={SS_LOGO_DATA_URI} alt=\"\" aria-hidden=\"true\" />\n}\nexport function SendIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M3 20l18-8L3 4v6l12 2-12 2z\" /></svg>\n}\nexport function CloseIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M18 6L6 18M6 6l12 12\" stroke=\"currentColor\" strokeWidth=\"2\" /></svg>\n}\nexport function ChevronIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" /></svg>\n}\nexport function NewChatIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" /></svg>\n}\nexport function KebabIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><g fill=\"currentColor\"><circle cx=\"12\" cy=\"5\" r=\"1.6\" /><circle cx=\"12\" cy=\"12\" r=\"1.6\" /><circle cx=\"12\" cy=\"19\" r=\"1.6\" /></g></svg>\n}\n\n// Dashboard tile icons are emoji (matching the betting widget mockup), not the old monochrome\n// line glyphs: they carry their own colour and read at a larger size. Rendered as text.\nconst DASHBOARD_EMOJI: Record<string, string> = {\n football: '⚽', 'goal-net': '🥅', btts: '🤝',\n card: '🟨', 'corner-flag': '🚩', player: '👤',\n target: '🎯', trophy: '🏆', 'chart-line': '📈',\n 'chart-bar': '📊', chat: '💬', fire: '🔥', sparkle: '✨',\n}\n\nexport function DashboardIcon({ name }: { name: string }): JSX.Element {\n // hasOwnProperty (not `in`, not `?? fallback`) so a prototype member name like 'toString'\n // resolves to the fallback emoji rather than an inherited function or a stray property value.\n const glyph = Object.prototype.hasOwnProperty.call(DASHBOARD_EMOJI, name)\n ? DASHBOARD_EMOJI[name]\n : DASHBOARD_EMOJI.target\n return <span className=\"ss-w-dash-emoji\" aria-hidden=\"true\">{glyph}</span>\n}\n","import { useState } from 'react'\nimport { SsMark } from './Icons'\n\n// Operator logo with a hard fallback to the built-in SS mark: a missing or\n// broken logoUrl must never leave a blank in the header or launcher.\nexport function BrandMark({ logoUrl, className }: { logoUrl?: string; className?: string }): JSX.Element {\n const [failed, setFailed] = useState(false)\n if (!logoUrl || failed) return <SsMark className={className} />\n return <img className={className} src={logoUrl} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n}\n","import { useEffect, useRef } from 'react'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { ChatMessage } from './ChatMessage'\nimport { IntentChips } from './IntentChips'\nimport { ActionButtons } from './ActionButtons'\nimport { isPinnedToBottom } from '../scroll'\nimport type { Message } from '../reducer'\n\n// The element to pin to the top when a new turn begins: the user's question if\n// this turn has one (so the reply reads from just below it), otherwise the\n// assistant turn itself (an auto-greeting or greeting dashboard has no user\n// bubble, and we still want its top in view rather than its bottom).\nfunction turnAnchor(messages: Message[]): { turnId: string; anchorId: string } | null {\n const last = messages[messages.length - 1]\n if (!last || last.role !== 'assistant') return null\n const prev = messages[messages.length - 2]\n return { turnId: last.id, anchorId: prev && prev.role === 'user' ? prev.id : last.id }\n}\n\nexport function MessageList({ controller, ui, slip, onDashboardTap, monitor }: {\n controller: ChatController\n ui: UiConfig\n slip: SlipHandlerProps\n onDashboardTap?: DashboardTapHandler\n monitor?: LiveMonitorController\n}): JSX.Element {\n const { state, send } = controller\n const listRef = useRef<HTMLDivElement>(null)\n const endRef = useRef<HTMLDivElement>(null)\n // Follow the stream only while the user is at the bottom. pinnedRef is updated\n // on real scroll events (content growth fires none), so a user who scrolls up\n // stays put when late content — suggested actions, status — arrives.\n const pinnedRef = useRef(true)\n // The turn id we have already anchored to the top. On a new turn we pin its\n // start to the top so a long reply reads from its beginning instead of the\n // viewport jumping to the bottom of the answer.\n const anchoredTurnRef = useRef<string | null>(null)\n useEffect(() => {\n const anchor = turnAnchor(state.messages)\n const list = listRef.current\n if (anchor && anchor.turnId !== anchoredTurnRef.current) {\n anchoredTurnRef.current = anchor.turnId\n // Reserve a viewport of space below the new turn before scrolling, so the\n // anchor can actually reach the top even while the reply is still empty\n // (without it the scroll lands at the bottom, onScroll re-pins to bottom,\n // and the streaming reply then follows the bottom down). The spacer is the\n // endRef element; it collapses again once the turn stops streaming.\n //\n // Only reserve while the turn is actively streaming. A turn first anchored\n // when it is ALREADY complete -- panel opened after the greeting finished,\n // or a restored/cross-tab-synced conversation -- has its full height, so it\n // needs no spacer; reserving one here would never be collapsed (this branch\n // returns, and the collapse below only runs on a later !isStreaming pass\n // that never comes), leaving a viewport of dead scroll space below content.\n if (endRef.current && list) endRef.current.style.height = state.isStreaming ? `${list.clientHeight}px` : ''\n // Top-anchored, so the list is no longer pinned to the bottom; streaming\n // updates below won't yank it back down for the rest of this turn.\n pinnedRef.current = false\n list?.querySelector(`[data-msg-id=\"${anchor.anchorId}\"]`)?.scrollIntoView({ block: 'start' })\n return\n }\n // Turn finished: drop the reserved space (content above is unaffected, so the\n // anchored message keeps its position).\n if (!state.isStreaming && endRef.current) endRef.current.style.height = ''\n if (pinnedRef.current) endRef.current?.scrollIntoView({ block: 'end' })\n }, [state.messages, state.status, state.isStreaming])\n\n // Chips are always emitted by the server; the widget prefers the dashboard and\n // hides the chips client-side once a greeting dashboard, a club fan dashboard, or a\n // user message exists.\n const hasUserMessage = state.messages.some((m) => m.role === 'user')\n const hasDashboard = state.messages.some((m) => m.role === 'assistant' && (m.greetingDashboard || m.clubFanDashboard))\n return (\n <div\n className=\"ss-w-list\"\n aria-live=\"polite\"\n ref={listRef}\n onScroll={() => { if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current) }}\n >\n {state.messages.map((m) => (\n <ChatMessage\n key={m.id}\n message={m}\n disabled={state.isStreaming}\n onAct={(a) => send(a.message, { actionId: a.actionId, actionRef: a.actionRef, displayText: a.label })}\n onTap={(tile, index) => {\n send(tile.actionValue, tile.actionRef\n ? { actionRef: tile.actionRef, displayText: tile.title }\n : { displayText: tile.title })\n // Only fires from within the dashboard this message itself rendered (ChatMessage\n // renders GreetingDashboard only when message.greetingDashboard is set), so the\n // dashboard -- and its layout -- is guaranteed present here.\n if (m.role === 'assistant' && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout)\n }}\n ui={ui}\n slip={slip}\n monitor={monitor}\n />\n ))}\n {state.isStreaming && state.actionsLoading ? <ActionButtons actions={[]} loading onAct={() => {}} /> : null}\n {state.status ? <div className=\"ss-w-status\">{state.status}</div> : null}\n {state.error ? (\n <div className=\"ss-w-error\" role=\"alert\">\n <span>{'message' in state.error ? state.error.message : ui.somethingWentWrong}</span>\n <button type=\"button\" className=\"ss-w-retry\" onClick={() => controller.retry()}>{ui.retry}</button>\n </div>\n ) : null}\n {!hasUserMessage && !hasDashboard ? <IntentChips chips={state.starters} onPick={(t) => send(t)} /> : null}\n <div ref={endRef} className=\"ss-w-turn-spacer\" aria-hidden=\"true\" />\n </div>\n )\n}\n","import ReactMarkdown, { type Components } from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst components: Components = {\n a: ({ children, href }) => (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"ss-w-md-link\">{children}</a>\n ),\n table: ({ children }) => (\n <div className=\"ss-w-table-wrap\"><table className=\"ss-w-md-table\">{children}</table></div>\n ),\n ul: ({ children }) => <ul className=\"ss-w-md-ul\">{children}</ul>,\n ol: ({ children }) => <ol className=\"ss-w-md-ol\">{children}</ol>,\n code: ({ children }) => <code className=\"ss-w-md-code\">{children}</code>,\n}\n\nexport function Markdown({ text }: { text: string }): JSX.Element {\n return (\n <div className=\"ss-w-md\">\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>{text}</ReactMarkdown>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { CardVM, CardScope, StatCell } from '../model'\n\nconst MAX_VISIBLE = 3\nconst RECORD_RE = /^(\\d+)-(\\d+)-(\\d+)$/\n\nfunction initials(name: string): string {\n return name.split(/\\s+/).slice(0, 2).map((w) => w[0] ?? '').join('').toUpperCase()\n}\n\n// \"2026/2027\" -> \"26/27\", \"2026\" -> \"26\"; leaves any non-4-digit token untouched.\nfunction shortSeason(season: string): string {\n return season.replace(/\\d{4}/g, (year) => year.slice(2))\n}\n\nfunction Crest({ image, label }: { image: string; label?: string }): JSX.Element {\n return (\n <span\n className=\"ss-w-ecard-crest\"\n style={{ backgroundImage: `url(${image})` }}\n {...(label ? { role: 'img', title: label, 'aria-label': label } : { 'aria-hidden': 'true' as const })}\n />\n )\n}\n\n// Proportional win/draw/loss bar. Rendered for any stat value shaped \"w-d-l\".\nfunction FormBar({ w, d, l }: { w: number; d: number; l: number }): JSX.Element | null {\n if (w + d + l === 0) return null\n return (\n <span className=\"ss-w-form\" aria-hidden=\"true\">\n {w > 0 ? <span className=\"ss-w-form-w\" style={{ flexGrow: w }} /> : null}\n {d > 0 ? <span className=\"ss-w-form-d\" style={{ flexGrow: d }} /> : null}\n {l > 0 ? <span className=\"ss-w-form-l\" style={{ flexGrow: l }} /> : null}\n </span>\n )\n}\n\nfunction StatCellView({ s }: { s: StatCell }): JSX.Element {\n const m = RECORD_RE.exec(s.value)\n if (m) {\n return (\n <div className=\"ss-w-ecard-cell\">\n <span className=\"ss-w-ecard-cval\"><FormBar w={Number(m[1])} d={Number(m[2])} l={Number(m[3])} /></span>\n <span className=\"ss-w-ecard-clabel\">{s.value}</span>\n </div>\n )\n }\n return (\n <div className=\"ss-w-ecard-cell\">\n <span className=\"ss-w-ecard-cval\">{s.value}</span>\n <span className=\"ss-w-ecard-clabel\">{s.label}</span>\n </div>\n )\n}\n\nfunction StatStrip({ stats }: { stats: StatCell[] }): JSX.Element | null {\n if (stats.length === 0) return null\n const cols = Math.min(stats.length, 4)\n return (\n <div className=\"ss-w-ecard-strip\" style={{ gridTemplateColumns: `repeat(${cols}, 1fr)` }}>\n {stats.map((s) => <StatCellView key={s.label + s.value} s={s} />)}\n </div>\n )\n}\n\nfunction CardHeader({ c, showScopeCrest }: { c: CardVM; showScopeCrest: boolean }): JSX.Element {\n const onlyScope = c.scopes.length === 1 ? c.scopes[0]! : null\n return (\n <div className=\"ss-w-ecard-hd\">\n <span\n className={c.kind === 'team' ? 'ss-w-thumb ss-w-team' : 'ss-w-thumb'}\n style={c.image ? { backgroundImage: `url(${c.image})` } : undefined}\n >\n {c.image ? '' : initials(c.name)}\n </span>\n <span className=\"ss-w-ecard-idtext\">\n <span className=\"ss-w-nm\">{c.name}</span>\n {c.sub ? <span className=\"ss-w-sub\">{c.sub}</span> : null}\n </span>\n <span className=\"ss-w-ecard-meta\">\n {showScopeCrest && onlyScope?.image ? <Crest image={onlyScope.image} label={onlyScope.label} /> : null}\n {c.season ? <span className=\"ss-w-ecard-season\">{shortSeason(c.season)}</span> : null}\n </span>\n </div>\n )\n}\n\nfunction ScopeTabs({ scopes, active, onSelect }: { scopes: CardScope[]; active: number; onSelect: (i: number) => void }): JSX.Element {\n return (\n <div className=\"ss-w-ecard-scopes\" role=\"tablist\">\n {scopes.map((s, i) => (\n <button\n key={String(s.competitionId ?? 'all')}\n type=\"button\"\n role=\"tab\"\n className=\"ss-w-ecard-scope\"\n aria-selected={i === active}\n aria-label={s.label}\n title={s.label}\n onClick={() => onSelect(i)}\n >\n {s.image ? <Crest image={s.image} /> : s.label}\n </button>\n ))}\n </div>\n )\n}\n\nfunction EntityCardItem({ c }: { c: CardVM }): JSX.Element {\n const [active, setActive] = useState(0)\n const hasBody = c.scopes.length > 0\n if (!hasBody) {\n return (\n <div className=\"ss-w-ecard ss-w-ecard-bare\" data-kind={c.kind}>\n <CardHeader c={c} showScopeCrest={false} />\n </div>\n )\n }\n const multi = c.scopes.length > 1\n const scope = c.scopes[multi ? (c.scopes[active] ? active : 0) : 0]!\n return (\n <div className=\"ss-w-ecard\" data-kind={c.kind}>\n <CardHeader c={c} showScopeCrest={!multi} />\n {multi ? <ScopeTabs scopes={c.scopes} active={active} onSelect={setActive} /> : null}\n <StatStrip stats={scope.stats} />\n </div>\n )\n}\n\nexport function EntityCardList({ cards, disabled, showLessLabel = 'Show less', showMoreLabel = (n: number) => `Show ${n} more` }: { cards: CardVM[]; disabled?: boolean; showLessLabel?: string; showMoreLabel?: (n: number) => string }): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n if (cards.length === 0) return null\n const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE)\n const overflow = cards.length - MAX_VISIBLE\n return (\n <div className=\"ss-w-cards\">\n {visible.map((c) => <EntityCardItem key={c.id} c={c} />)}\n {overflow > 0 ? (\n <button type=\"button\" className=\"ss-w-cards-more\" disabled={disabled} onClick={() => setExpanded((v) => !v)}>\n {expanded ? showLessLabel : showMoreLabel(overflow)}\n </button>\n ) : null}\n </div>\n )\n}\n","import { useCallback, useState } from 'react'\nimport { isAddToSlipResult, type AddToSlipResult, type SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { toSlipSelection, type InsightVM } from '../model'\nimport { ADD_TO_SLIP_TIMEOUT_MS, isTerminal, resultToToast, slipOutcome, slipPickFields, wasAdded, type SlipHandlerProps, type SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { useSlipState } from '../slipStateContext'\nimport { Toast } from './Toast'\n\nfunction withTimeout(value: Promise<AddToSlipResult | void>): Promise<AddToSlipResult | void> {\n return Promise.race([\n value,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('add-to-slip timed out')), ADD_TO_SLIP_TIMEOUT_MS)),\n ])\n}\n\nexport function SlipButton(\n { selection, shownOdds, marketDeveloperName, selectionLabel, line, slip, ui, price }:\n {\n selection: SlipSelection | null; shownOdds: string; marketDeveloperName?: string\n /** The raw selection label and line, sent apart (never the joined display string). */\n selectionLabel?: string; line?: string\n slip: SlipHandlerProps; ui?: UiConfig\n /** Draws the price itself as the button, as a compact list row does. */\n price?: { label?: string; ariaLabel: string }\n },\n): JSX.Element | null {\n const [pending, setPending] = useState(false)\n const [settledLocal, setSettledLocal] = useState(false)\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n const slipState = useSlipState()\n\n const handler = slip.onAddToSlip\n if (!ui || !handler || !selection) return null\n // Inside a widget the mark belongs to the odd and lives at the root, where a host call can\n // clear it. Rendered on its own, with no provider, the button keeps its own state.\n const settled = slipState ? !!slipState.settled[selection.matchOddsId] : settledLocal\n\n const onClick = async (): Promise<void> => {\n setPending(true)\n const pick = slipPickFields(selection, ui.rawBettingLabels ? selectionLabel : undefined, line)\n // A market/selection with no marketDeveloperName has no entity to report under entityType\n // 'market' -- skip the emit rather than log entityId: undefined (mirrors the PinToggle guard).\n if (marketDeveloperName !== undefined) {\n log?.log({ name: 'slip_click', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, ...pick })\n }\n try {\n const raw = await withTimeout(Promise.resolve(handler(selection)))\n // Only a genuine void return means \"assume success\". A non-null value the\n // guard rejects is a broken contract (e.g. an operator forwarding their own\n // backend's reason string, which `any` lets past the compiler) — treating it\n // as void would report a refused bet to the user as added.\n if (raw != null && !isAddToSlipResult(raw)) throw new Error('malformed add-to-slip result')\n const result = raw ?? undefined\n if (marketDeveloperName !== undefined) {\n log?.log({\n name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName,\n outcome: slipOutcome(result), ...pick,\n })\n }\n setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui))\n if (slipState) {\n if (isTerminal(result)) slipState.settle(selection.matchOddsId)\n if (wasAdded(result) && marketDeveloperName !== undefined) {\n slipState.recordAdd({ selection, market: marketDeveloperName, pick })\n }\n } else {\n setSettledLocal(isTerminal(result))\n }\n } catch {\n if (marketDeveloperName !== undefined) {\n log?.log({ name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, outcome: 'timeout', ...pick })\n }\n setToast({ kind: 'error', text: ui.slipFailed })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"ss-w-slip\">\n {price ? (\n <button\n type=\"button\"\n className=\"ss-w-slip-btn ss-w-slip-btn--price\"\n data-settled={settled || undefined}\n aria-label={`${price.ariaLabel}, ${settled ? ui.inSlip : ui.addToSlip}`}\n disabled={pending || settled}\n onClick={onClick}\n >\n {price.label ? <span className=\"ss-w-mol-lab\">{price.label}</span> : null}\n {shownOdds}\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"ss-w-slip-btn\"\n disabled={pending || settled}\n onClick={onClick}\n >\n {settled ? ui.inSlip : ui.addToSlip}\n </button>\n )}\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n\nexport function AddToSlipButton(\n { it, slip, ui }: { it: InsightVM; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n const selection = it.addToSlipEnabled ? toSlipSelection(it, slip.conversationId) : null\n return (\n <SlipButton\n selection={selection}\n shownOdds={it.odds ?? ''}\n marketDeveloperName={it.marketDeveloperName}\n selectionLabel={it.selectionLabel}\n line={it.line}\n slip={slip}\n ui={ui}\n />\n )\n}\n","export interface ChartSample { atMs: number; price: number }\nexport interface ChartGeometry {\n path: string\n markers: { x: number; y: number }[]\n gridlines: { y: number; price: number }[]\n viewBox: string\n startMs: number\n endMs: number\n}\n\nexport const CHART_VIEW_W = 320\nexport const CHART_VIEW_H = 140\n\nconst PLOT_X0 = 40\nconst PLOT_X1 = 312\nconst PLOT_Y0 = 10\nconst PLOT_Y1 = 110\n\n// Point markers are drawn only on sparse series. Measured on sandbox1, the median chartable\n// series has TWO points: without markers a two-point chart is one bare diagonal that reads as a\n// rendering glitch rather than as data. Above this count the dots crowd the line and the shape\n// carries itself.\nconst MARKER_MAX_POINTS = 8\n\n// A flat series has no price range to scale against. Widening the domain by a fixed amount keeps\n// the line horizontal through the middle of the plot instead of dividing by zero.\nconst FLAT_DOMAIN_PAD = 0.05\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100\n\nexport function projectSeries(samples: ChartSample[]): ChartGeometry | null {\n if (samples.length < 2) return null\n\n // noUncheckedIndexedAccess can't see that the length check above guarantees these exist.\n const tMin = samples[0]!.atMs\n const tMax = samples[samples.length - 1]!.atMs\n if (tMax <= tMin) return null\n\n const prices = samples.map((s) => s.price)\n const pMin = Math.min(...prices)\n const pMax = Math.max(...prices)\n\n let yMin: number\n let yMax: number\n if (pMax === pMin) {\n yMin = pMin - FLAT_DOMAIN_PAD\n yMax = pMax + FLAT_DOMAIN_PAD\n } else {\n const pad = (pMax - pMin) * 0.1\n yMin = pMin - pad\n yMax = pMax + pad\n }\n\n const x = (atMs: number): number =>\n round2(PLOT_X0 + ((atMs - tMin) / (tMax - tMin)) * (PLOT_X1 - PLOT_X0))\n const y = (price: number): number =>\n round2(PLOT_Y1 - ((price - yMin) / (yMax - yMin)) * (PLOT_Y1 - PLOT_Y0))\n\n const projected = samples.map((s) => ({ x: x(s.atMs), y: y(s.price) }))\n const path = projected.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`).join(' ')\n\n return {\n path,\n markers: samples.length <= MARKER_MAX_POINTS ? projected : [],\n // The real extremes, never the padded bounds: a gridline label is a price, and the padded\n // bounds are prices nobody was ever offered. A flat series has one real extreme, not two —\n // two identical gridlines would collide on both React key and rendered text.\n gridlines: pMax === pMin\n ? [{ y: y(pMax), price: pMax }]\n : [\n { y: y(pMax), price: pMax },\n { y: y(pMin), price: pMin },\n ],\n viewBox: `0 0 ${CHART_VIEW_W} ${CHART_VIEW_H}`,\n startMs: tMin,\n endMs: tMax,\n }\n}\n","import type { BettingInsight, EntityCard, MarketOddsCard, MarketOddsRow, OddsMovementCard, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { ChartGeometry, ChartSample } from './chart'\nimport { projectSeries } from './chart'\n\nexport type CardKind = 'player' | 'team' | 'generic'\nexport interface StatCell { label: string; value: string }\nexport interface CardScope { competitionId: number | null; label: string; image?: string; stats: StatCell[] }\nexport interface CardVM { id: string; kind: CardKind; name: string; image?: string; sub?: string; season?: string; scopes: CardScope[] }\nexport interface ActionVM { label: string; actionId?: string; actionRef?: string; message: string }\nexport interface ChipVM { text: string }\nexport interface InsightVM {\n id: string\n market: string\n selection?: string\n odds?: string\n bookmaker?: string\n isLive: boolean\n phase?: string\n fixture?: string\n competition?: string\n text: string\n disclaimer?: string\n matchId: number\n matchOddsId?: number\n marketDeveloperName?: string\n selectionLabel?: string\n line?: string\n addToSlipEnabled: boolean\n pinEnabled: boolean\n isMarketFloor: boolean\n oddsDecimal?: number\n quotedAtUtc?: string\n previousOdds?: string\n movementDirection?: 'shortened' | 'drifted'\n homeTeamName?: string\n awayTeamName?: string\n homeCrest?: string\n awayCrest?: string\n competitionCrest?: string\n kickoffUtc?: string\n kickoffLabel?: string\n}\n\nexport interface MarketOddsRowVM {\n key: string\n selection: string\n selectionLabel?: string\n line?: string\n odds: string\n oddsDecimal?: number\n matchOddsId?: number\n quotedAtUtc?: string\n isMain: boolean\n isSuspended: boolean\n previousOdds?: string\n movementDirection?: 'shortened' | 'drifted'\n}\nexport interface MarketOddsVM {\n id: string\n market: string\n fixture?: string\n homeTeamName?: string\n awayTeamName?: string\n homeCrest?: string\n awayCrest?: string\n competitionCrest?: string\n competition?: string\n kickoffUtc?: string\n kickoffLabel?: string\n bookmaker?: string\n updatedAt?: string\n isLive: boolean\n matchId: number\n mainRows: MarketOddsRowVM[]\n moreRows: MarketOddsRowVM[]\n disclaimer?: string\n addToSlipEnabled: boolean\n marketDeveloperName?: string\n mainLine?: string\n pinEnabled: boolean\n /** The stat drawn inside the card, above the rows. */\n statText?: string\n}\n\nfunction str(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined\n}\nfunction num(v: unknown): string | undefined {\n return typeof v === 'number' && Number.isFinite(v) ? String(v) : undefined\n}\n\nfunction readStatCells(raw: unknown): StatCell[] {\n if (!Array.isArray(raw)) return []\n const cells: StatCell[] = []\n for (const entry of raw as Array<Record<string, unknown>>) {\n const label = str(entry.label)\n const value = num(entry.value) ?? str(entry.value)\n if (label !== undefined && value !== undefined) cells.push({ label, value })\n }\n return cells\n}\n\nexport function toCardVM(card: EntityCard): CardVM {\n const entityType = str(card.entityType)?.toLowerCase()\n const kind: CardKind = entityType === 'player' ? 'player' : entityType === 'team' ? 'team' : 'generic'\n const scopes = Array.isArray(card.scopes)\n ? (card.scopes as unknown as Array<Record<string, unknown>>)\n .map((s): CardScope | null => {\n const label = str(s.label)\n if (!label) return null\n return {\n competitionId: typeof s.competitionId === 'number' ? s.competitionId : null,\n label,\n image: str(s.imagePath),\n stats: readStatCells(s.stats),\n }\n })\n .filter((s): s is CardScope => s !== null)\n : []\n return {\n id: String(card.entityId),\n kind,\n name: card.canonicalName,\n image: str(card.imagePath) ?? str(card.imageUrl) ?? str(card.image_url) ?? str(card.logoUrl) ?? str(card.logo),\n sub: str(card.subtitle) ?? str(card.teamName) ?? str(card.leagueName) ?? str(card.position),\n season: str(card.seasonName),\n scopes,\n }\n}\n\nexport function toActionVM(action: Record<string, unknown>): ActionVM {\n const label = str(action.actionLabel) ?? str(action.label) ?? str(action.text) ?? str(action.title) ?? 'Continue'\n const actionId = str(action.actionId) ?? str(action.id)\n const actionRef = str(action.actionRef)\n const message = str(action.actionValue) ?? str(action.message) ?? str(action.query) ?? label\n return { label, actionId, actionRef, message }\n}\n\nexport function toChipVM(intent: Record<string, unknown>): ChipVM | null {\n const text = str(intent.text) ?? str(intent.label) ?? str(intent.title)\n return text ? { text } : null\n}\n\nexport function chipFromText(text: string): ChipVM {\n return { text }\n}\n\n// A localized label can already embed the line (TR \"2.5 Üst\") -- never append it twice.\n// Shared by every selection/line join site so they can't drift out of sync (u324).\nexport function joinSelection(label?: string, line?: string): string | undefined {\n if (label && line && label.includes(line)) return label\n return [label, line].filter(Boolean).join(' ') || undefined\n}\n\nexport function toInsightVM(insight: BettingInsight): InsightVM {\n const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? ''\n const selectionLabel = str(insight.selectionLabel)\n const selectionLine = str(insight.line)\n const selection = joinSelection(selectionLabel, selectionLine)\n const value = insight.odds?.value\n const odds = typeof value === 'number' && Number.isFinite(value) ? value.toFixed(2) : undefined\n const oddsValue = insight.odds?.value\n const matchOddsId = typeof insight.odds?.matchOddsId === 'number' ? insight.odds.matchOddsId : undefined\n const home = str(insight.homeTeamName)\n const away = str(insight.awayTeamName)\n const fixture = home && away ? `${home} vs ${away}` : undefined\n const competition = str(insight.competitionName)\n const previousValue = insight.odds?.previousValue\n const previous =\n typeof previousValue === 'number' && Number.isFinite(previousValue) ? previousValue : undefined\n const direction =\n insight.odds?.movementDirection === 'shortened' || insight.odds?.movementDirection === 'drifted'\n ? insight.odds.movementDirection\n : undefined\n return {\n id: str(insight.insightId) ?? `${str(insight.ruleId) ?? 'insight'}:${num(insight.matchId) ?? ''}`,\n market,\n selection,\n odds,\n // The wire payload carries bookmakerId (not a name); render a name only if one is present.\n bookmaker: str(insight.odds?.bookmakerName),\n isLive: insight.odds?.isLive === true,\n phase: str(insight.phase),\n fixture,\n competition,\n text: str(insight.text) ?? '',\n disclaimer: str(insight.disclaimer),\n matchId: typeof insight.matchId === 'number' ? insight.matchId : 0,\n matchOddsId,\n marketDeveloperName: str(insight.marketDeveloperName),\n selectionLabel: str(insight.selectionLabel),\n line: str(insight.line),\n addToSlipEnabled: insight.addToSlipEnabled === true,\n pinEnabled: insight.pinEnabled === true,\n isMarketFloor: insight.isMarketFloor === true,\n oddsDecimal: typeof oddsValue === 'number' && Number.isFinite(oddsValue) ? oddsValue : undefined,\n quotedAtUtc: str(insight.odds?.quotedAtUtc),\n previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n homeTeamName: home,\n awayTeamName: away,\n homeCrest: str(insight.homeTeamImagePath),\n awayCrest: str(insight.awayTeamImagePath),\n competitionCrest: str(insight.competitionImagePath),\n kickoffUtc: str(insight.kickoffUtc),\n kickoffLabel: str(insight.kickoffLabel),\n }\n}\n\nexport function toSlipSelection(vm: InsightVM, conversationId?: string): SlipSelection | null {\n if (vm.matchOddsId === undefined || vm.oddsDecimal === undefined) return null\n const selection: SlipSelection = {\n matchOddsId: vm.matchOddsId,\n matchId: vm.matchId,\n oddsDecimal: vm.oddsDecimal,\n }\n if (vm.quotedAtUtc !== undefined) selection.quotedAtUtc = vm.quotedAtUtc\n if (vm.id !== undefined) selection.insightId = vm.id\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n\nexport function toMarketOddsVM(card: MarketOddsCard): MarketOddsVM {\n const rows = Array.isArray(card.rows) ? card.rows : []\n const toRow = (r: MarketOddsRow, i: number): MarketOddsRowVM => {\n const selection = joinSelection(str(r.selectionLabel), str(r.line)) ?? ''\n const price = typeof r.price === 'number' && Number.isFinite(r.price) ? r.price : undefined\n const previous =\n typeof r.previousPrice === 'number' && Number.isFinite(r.previousPrice) ? r.previousPrice : undefined\n const direction =\n r.movementDirection === 'shortened' || r.movementDirection === 'drifted' ? r.movementDirection : undefined\n return {\n key: `${selection}:${str(r.line) ?? ''}:${i}`,\n selection,\n selectionLabel: str(r.selectionLabel),\n line: str(r.line),\n odds: price !== undefined ? price.toFixed(2) : '',\n oddsDecimal: price,\n matchOddsId: typeof r.matchOddsId === 'number' ? r.matchOddsId : undefined,\n quotedAtUtc: str(r.quotedAtUtc),\n isMain: r.isMainLine !== false,\n // === true, not !== false: a server that has not shipped the field yet leaves it undefined,\n // and undefined must read as open rather than hiding every price on the card.\n isSuspended: r.isSuspended === true,\n previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n }\n }\n // A suspended selection leaves the ladder entirely, same rule the live match card follows: we do\n // not show a price the bookmaker is not taking. If every line is suspended the card has no rows and\n // MarketOddsCardList renders nothing for it.\n const vms = rows.map(toRow).filter((r) => r.selection && r.odds && !r.isSuspended)\n const home = str(card.homeTeamName)\n const away = str(card.awayTeamName)\n const updated = rows.map((r) => str(r.quotedAtUtc)).filter((v): v is string => !!v).sort()\n return {\n id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}`,\n market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n fixture: home && away ? `${home} vs ${away}` : undefined,\n homeTeamName: home,\n awayTeamName: away,\n homeCrest: str(card.homeTeamImagePath),\n awayCrest: str(card.awayTeamImagePath),\n competitionCrest: str(card.competitionImagePath),\n competition: str(card.competitionName),\n kickoffUtc: str(card.kickoffUtc),\n kickoffLabel: str(card.kickoffLabel),\n bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),\n updatedAt: updated.length > 0 ? updated[updated.length - 1] : undefined,\n isLive: rows.some((r) => r.isLive === true),\n matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n mainRows: vms.filter((r) => r.isMain),\n moreRows: vms.filter((r) => !r.isMain),\n disclaimer: str(card.disclaimer),\n addToSlipEnabled: card.addToSlipEnabled === true,\n marketDeveloperName: str(card.marketDeveloperName),\n mainLine: str(card.mainLine),\n pinEnabled: card.pinEnabled === true,\n statText: card.insight && typeof card.insight === 'object' ? str(card.insight.text) : undefined,\n }\n}\n\nexport interface OddsMovementVM {\n id: string\n matchId: number\n market: string\n marketDeveloperName?: string\n selection: string\n selectionLabel?: string\n line?: string\n fixture?: string\n competition?: string\n bookmaker?: string\n opening: string\n current: string\n direction?: 'shortened' | 'drifted'\n windowHours: number\n excludedCount: number\n isSuspended: boolean\n disclaimer?: string\n geometry: ChartGeometry | null\n observationCount: number\n pinEnabled: boolean\n matchOddsId?: number\n}\n\nexport function toOddsMovementVM(card: OddsMovementCard): OddsMovementVM {\n const raw = Array.isArray(card.points) ? card.points : []\n const samples: ChartSample[] = []\n for (const p of raw) {\n const price = typeof p.price === 'number' && Number.isFinite(p.price) ? p.price : undefined\n const atMs = typeof p.atUtc === 'string' ? Date.parse(p.atUtc) : NaN\n if (price === undefined || Number.isNaN(atMs)) continue\n samples.push({ atMs, price })\n }\n // projectSeries trusts sample order as the time domain (samples[0]/samples[^1] become tMin/tMax)\n // without re-checking it; every other field above is already validated, so this is the one\n // property whose violation is otherwise invisible.\n samples.sort((a, b) => a.atMs - b.atMs)\n\n const asNumber = (v: unknown): number | undefined =>\n typeof v === 'number' && Number.isFinite(v) ? v : undefined\n const opening = asNumber(card.openingPrice)\n const current = asNumber(card.currentPrice)\n const home = str(card.homeTeamName)\n const away = str(card.awayTeamName)\n const selection = joinSelection(str(card.selectionLabel), str(card.line)) ?? ''\n const bookmakerId = typeof card.bookmakerId === 'number' ? card.bookmakerId : ''\n\n return {\n id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}:${selection}:${bookmakerId}`,\n matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n marketDeveloperName: str(card.marketDeveloperName),\n selection,\n selectionLabel: str(card.selectionLabel),\n line: str(card.line),\n fixture: home && away ? `${home} vs ${away}` : undefined,\n competition: str(card.competitionName),\n bookmaker: str(card.bookmakerName),\n opening: opening !== undefined ? opening.toFixed(2) : '',\n current: current !== undefined ? current.toFixed(2) : '',\n direction:\n card.movementDirection === 'shortened' || card.movementDirection === 'drifted'\n ? card.movementDirection\n : undefined,\n windowHours: asNumber(card.windowHours) ?? 0,\n excludedCount: asNumber(card.excludedSuspendedCount) ?? 0,\n isSuspended: card.isSuspended === true,\n disclaimer: str(card.disclaimer),\n geometry: projectSeries(samples),\n observationCount: samples.length,\n pinEnabled: card.pinEnabled === true,\n matchOddsId: typeof card.matchOddsId === 'number' ? card.matchOddsId : undefined,\n }\n}\n\nexport function marketOddsRowToSlipSelection(\n vm: MarketOddsVM, row: MarketOddsRowVM, conversationId?: string,\n): SlipSelection | null {\n if (row.matchOddsId === undefined || row.oddsDecimal === undefined) return null\n const selection: SlipSelection = { matchOddsId: row.matchOddsId, matchId: vm.matchId, oddsDecimal: row.oddsDecimal }\n if (row.quotedAtUtc !== undefined) selection.quotedAtUtc = row.quotedAtUtc\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n","import { createContext, useContext } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\nexport const EventLogContext = createContext<EventLogger | null>(null)\n\nexport function useEventLog(): EventLogger | null {\n return useContext(EventLogContext)\n}\n","import { createContext, useContext } from 'react'\nimport type { SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { SlipPickFields } from './slip'\n\nexport interface SlipAdd {\n selection: SlipSelection\n /** market developer name */\n market: string\n pick: SlipPickFields\n}\n\nexport interface SlipState {\n /** Odds the widget added in this mount. Drives the Odds tab's persistent in-slip badge. */\n added: Readonly<Record<number, true>>\n /** Odds whose button got a terminal answer in this mount. Drives the button's \"In slip\" label. */\n settled: Readonly<Record<number, true>>\n settle(matchOddsId: number): void\n /** Remembers an add the widget made, so a later host call for that odd can be reported. */\n recordAdd(add: SlipAdd): void\n}\n\nexport const SlipStateContext = createContext<SlipState | null>(null)\n\nexport function useSlipState(): SlipState | null {\n return useContext(SlipStateContext)\n}\n","import { useEffect } from 'react'\nimport type { SlipToast } from '../slip'\n\nconst DISMISS_MS = 4000\n\nexport function Toast({ toast, onDismiss }: { toast: SlipToast | null; onDismiss: () => void }): JSX.Element | null {\n useEffect(() => {\n if (!toast) return\n const timer = setTimeout(onDismiss, DISMISS_MS)\n return () => clearTimeout(timer)\n }, [toast, onDismiss])\n\n if (!toast) return null\n return (\n <div className={`ss-w-toast ss-w-toast-${toast.kind}`} role=\"status\" aria-live=\"polite\">\n {toast.text}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\n\n// One component for both card types. The market-odds row and the insight card must not drift into\n// two visual languages for the same signal, so there is exactly one place this markup exists.\nexport function OddsMovementBadge({\n previous,\n current,\n direction,\n ui,\n}: {\n previous?: string\n current: string\n direction?: 'shortened' | 'drifted'\n ui?: UiConfig\n}): JSX.Element | null {\n if (previous === undefined || direction === undefined) return null\n const directionWord =\n direction === 'shortened' ? (ui?.oddsShortened ?? 'shortened') : (ui?.oddsDrifted ?? 'drifted')\n const label =\n ui?.oddsMoved?.(previous, current, directionWord) ?? `was ${previous}, now ${current}, ${directionWord}`\n return (\n // Strikethrough is invisible to screen readers, so the whole was/now/direction sentence rides\n // on one aria-label and the visual glyphs are hidden from the accessibility tree.\n <span className=\"ss-w-move\" role=\"img\" aria-label={label}>\n <span className=\"ss-w-move-prev\" aria-hidden=\"true\">{previous}</span>\n <span className=\"ss-w-move-arrow\" aria-hidden=\"true\">{direction === 'shortened' ? '▼' : '▲'}</span>\n </span>\n )\n}\n","import { useState } from 'react'\n\nexport function initials(name?: string): string {\n return (name ?? '').trim().slice(0, 1).toUpperCase() || '?'\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a monogram (first initial) -- the design\n// wants the monogram whenever the crest is missing OR fails to load, which a background-image span\n// can't detect. onError flips to the monogram; the fixed sizing keeps the row height stable either way.\nexport function Crest({ url, name, kind }: { url?: string; name?: string; kind: 'team' | 'comp' }): JSX.Element {\n const cls = kind === 'comp' ? 'ss-w-bi-comp-logo' : 'ss-w-bi-crest'\n const [failed, setFailed] = useState(false)\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return <span className={`${cls} ss-w-bi-crest-mono`} aria-hidden=\"true\">{initials(name)}</span>\n}\n","import { useCallback, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\n// One glyph per pinIcon choice, drawn from a single silhouette path so the\n// pinned state can toggle outline (off) → filled (on) without a second asset.\n// The pin keeps its original thumbtack (scaled into a 24 box) so the default\n// look is unchanged in shape; star and bookmark are standard marks.\nconst PIN_GLYPHS: Record<'pin' | 'star' | 'bookmark', { viewBox: string; d: string; strokeWidth: number; transform?: string }> = {\n 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' },\n star: { viewBox: '0 0 24 24', strokeWidth: 2, d: 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z' },\n 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' },\n}\n\nexport function PinToggle({ pin, monitor, ui }: {\n pin: Omit<PinRef, 'key'>\n monitor: LiveMonitorController | undefined\n ui: UiConfig\n}): JSX.Element | null {\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n\n if (!monitor || !monitor.enabled) return null\n\n const key = pinKey(pin)\n const pinned = monitor.isPinned(key)\n // Match pins and odds pins are separate behaviors (2026-09-06 ruling): each toggle tracks\n // exactly its own pin, and the labels name which one this is.\n const labels = pin.kind === 'match'\n ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel }\n : { pin: ui.pinLabel, unpin: ui.unpinLabel }\n\n const onClick = (): void => {\n const result = monitor.togglePin({ ...pin, key })\n // A market/selection pin with no marketDeveloperName has no entity to report under\n // entityType 'market' -- skip the emit rather than fall back to the match id, which would\n // mislabel a match under a market entityType.\n if ((result === 'added' || result === 'removed') && (pin.kind === 'match' || pin.marketDeveloperName !== undefined)) {\n log?.log({\n name: result === 'added' ? 'pin_add' : 'pin_remove',\n entityType: pin.kind === 'match' ? 'match' : 'market',\n entityId: pin.kind === 'match' ? String(pin.matchId) : pin.marketDeveloperName,\n marketDeveloperName: pin.marketDeveloperName,\n })\n } else if (result === 'match_limit') {\n setToast({ kind: 'error', text: ui.matchLimitToast })\n } else if (result === 'market_limit') {\n setToast({ kind: 'error', text: ui.marketLimitToast })\n }\n }\n\n const glyph = PIN_GLYPHS[ui.pinIcon]\n return (\n <div className=\"ss-w-pin-wrap\">\n <button\n type=\"button\"\n className=\"ss-w-pin\"\n data-on={pinned || undefined}\n data-icon={ui.pinIcon}\n aria-pressed={pinned}\n aria-label={pinned ? labels.unpin : labels.pin}\n onClick={onClick}\n >\n <svg viewBox={glyph.viewBox} aria-hidden=\"true\">\n <path\n transform={glyph.transform}\n d={glyph.d}\n fill={pinned ? 'currentColor' : 'none'}\n stroke={pinned ? 'none' : 'currentColor'}\n strokeWidth={glyph.strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n","import type { PinRef } from '@sensiblestats/widget-sdk'\n\nexport const MAX_MATCH_PINS = 5\nexport const MAX_MARKET_PINS = 10\nexport type PinAddResult = 'added' | 'removed' | 'match_limit' | 'market_limit'\n\nexport type StoredPin = PinRef & { graceAt?: number; graceSession?: string }\n\nexport interface PinStore {\n pins: PinRef[]\n /** Toggle: same key present -> remove; else add if under the kind's cap. */\n toggle(pin: PinRef): PinAddResult\n remove(key: string): void\n has(key: string): boolean\n /** D7: stamps graceAt/graceSession on the given keys, only where not already stamped. */\n markGrace(keys: string[], sessionId: string, now: number): void\n}\n\nexport function pinKey(p: Omit<PinRef, 'key'>): string {\n return `${p.kind}:${p.matchId}:${p.marketDeveloperName ?? ''}:${p.selectionLabel ?? ''}:${p.line ?? ''}:${p.matchOddsId ?? ''}`\n}\n\nexport const GRACE_MS = 4 * 60 * 60 * 1000\n\n/** D7: drop pins whose grace started in a PREVIOUS session (next widget open) or > 4h ago. */\nexport function pruneExpired(pins: StoredPin[], sessionId: string, now: number): StoredPin[] {\n return pins.filter((p) => p.graceAt === undefined || (p.graceSession === sessionId && now - p.graceAt <= GRACE_MS))\n}\n\ninterface StoredPins {\n v: 1\n pins: StoredPin[]\n}\n\nfunction safeRead(storageKey: string): StoredPin[] {\n try {\n const raw = window.localStorage.getItem(storageKey)\n if (!raw) return []\n const parsed = JSON.parse(raw) as StoredPins\n return parsed.v === 1 && Array.isArray(parsed.pins) ? parsed.pins : []\n } catch {\n return []\n }\n}\n\nfunction safeWrite(storageKey: string, pins: StoredPin[]): void {\n try {\n window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, pins } satisfies StoredPins))\n } catch {\n // storage blocked -> in-memory only for the session (spec, degradation rules)\n }\n}\n\nexport function loadPins(storageKey: string): PinRef[] {\n return safeRead(storageKey)\n}\n\nexport function createPinStore(storageKey: string, sessionId: string, onChange: (pins: PinRef[]) => void): PinStore {\n // D7 grace: pins whose subject finished in a previous session (or >4h ago) are dropped on open.\n let pins = pruneExpired(safeRead(storageKey), sessionId, Date.now())\n\n const commit = (next: StoredPin[]) => {\n pins = next\n safeWrite(storageKey, pins)\n onChange(pins)\n }\n commit(pins)\n\n return {\n get pins() {\n return pins\n },\n has: (key) => pins.some((p) => p.key === key),\n remove: (key) => commit(pins.filter((p) => p.key !== key)),\n markGrace(keys, session, now) {\n commit(\n pins.map((p) => (keys.includes(p.key) && p.graceAt === undefined ? { ...p, graceAt: now, graceSession: session } : p)),\n )\n },\n toggle(pin) {\n if (pins.some((p) => p.key === pin.key)) {\n commit(pins.filter((p) => p.key !== pin.key))\n return 'removed'\n }\n const matchCount = pins.filter((p) => p.kind === 'match').length\n const marketCount = pins.length - matchCount\n if (pin.kind === 'match' && matchCount >= MAX_MATCH_PINS) return 'match_limit'\n if (pin.kind !== 'match' && marketCount >= MAX_MARKET_PINS) return 'market_limit'\n commit([...pins, pin])\n return 'added'\n },\n }\n}\n","import { useCallback, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { joinSelection } from '../model'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\ntype HistoryPin = Omit<PinRef, 'key' | 'kind' | 'withHistory'>\n\n// D27: in place of an odds pin, a price that moved opens its history in the Odds tab. The tap adds\n// the selection with its history, or finds it already there, and switches tab. It never removes\n// an entry: unpinning lives in the Odds tab.\nexport function PriceHistoryButton({ selection, monitor, ui }: {\n selection: HistoryPin\n monitor: LiveMonitorController | undefined\n ui: UiConfig\n}): JSX.Element | null {\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n\n if (!monitor || !monitor.enabled) return null\n // The name carries the selection: two moved rows on one card must not read as two identical buttons.\n const name = joinSelection(selection.selectionLabel ?? undefined, selection.line ?? undefined)\n const label = name ? `${ui.priceHistoryLabel}, ${name}` : ui.priceHistoryLabel\n\n const onClick = (): void => {\n const pin = { ...selection, kind: 'selection' as const, withHistory: true }\n const key = pinKey(pin)\n if (!monitor.isPinned(key)) {\n const result = monitor.togglePin({ ...pin, key })\n if (result === 'market_limit' || result === 'match_limit') {\n setToast({ kind: 'error', text: result === 'market_limit' ? ui.marketLimitToast : ui.matchLimitToast })\n return\n }\n // Logged as the market pin it is, so the market signal behind \"Your market\" keeps its input.\n if (result === 'added' && pin.marketDeveloperName !== undefined) {\n log?.log({ name: 'pin_add', entityType: 'market', entityId: pin.marketDeveloperName, marketDeveloperName: pin.marketDeveloperName })\n }\n }\n monitor.setActiveTab('odds')\n }\n\n return (\n <div className=\"ss-w-pin-wrap\">\n <button type=\"button\" className=\"ss-w-hist\" aria-label={label} title={label} onClick={onClick}>\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 13.5h12M3 10.5l3.2-3.4 2.6 2.2L13 4.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n","export interface WidgetHost {\n /** The user removed this selection from the operator's slip. */\n slipRemoved(selection: { matchOddsId: number }): void\n /** The user placed a bet. Pass every leg; the widget reports only the ones it added. */\n betPlaced(bet: { selections: ReadonlyArray<{ matchOddsId: number }> }): void\n /** The user opened this match's page on the operator's site. */\n matchOpened(match: { matchId: number }): void\n}\n\nexport type HostCommand =\n | { kind: 'slipRemoved'; matchOddsId: number }\n | { kind: 'betPlaced'; matchOddsIds: number[] }\n | { kind: 'matchOpened'; matchId: number }\n\nexport type HostSink = (command: HostCommand) => void\n\nexport const HOST_QUEUE_MAX = 20\n\ninterface HostState {\n queue: HostCommand[]\n sink: HostSink | null\n}\n\n// Keyed by the object createWidgetHost() returned. WidgetHost is an exported interface, so an\n// operator can pass an object it built by hand; that object has no entry here and stays inert.\nconst STATES = new WeakMap<WidgetHost, HostState>()\n\nexport function isValidId(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value > 0\n}\n\n/**\n * The operator's handle for telling the widget what happened on its side. Create it once at\n * module scope and pass it as the `host` prop. Calls made while no widget is mounted are queued\n * and replayed when one attaches. No method ever throws, and creating a host touches no browser\n * API, so a module-scope host is safe under server rendering.\n */\nexport function createWidgetHost(): WidgetHost {\n const state: HostState = { queue: [], sink: null }\n\n const dispatch = (command: HostCommand): void => {\n if (state.sink) {\n state.sink(command)\n return\n }\n state.queue.push(command)\n if (state.queue.length > HOST_QUEUE_MAX) state.queue.shift()\n }\n\n const host: WidgetHost = {\n // Every body sits in a try: a missing argument, a malformed one and a widget bug behind the\n // sink all end the same way, with the call ignored.\n slipRemoved(selection) {\n try {\n const id: unknown = selection.matchOddsId\n if (isValidId(id)) dispatch({ kind: 'slipRemoved', matchOddsId: id })\n } catch {\n // a host method never throws into operator code\n }\n },\n betPlaced(bet) {\n try {\n const legs: unknown = bet.selections\n if (!Array.isArray(legs)) return\n const ids: number[] = []\n for (const leg of legs as ReadonlyArray<{ matchOddsId?: unknown } | null | undefined>) {\n const id = leg?.matchOddsId\n if (isValidId(id) && !ids.includes(id)) ids.push(id)\n }\n if (ids.length > 0) dispatch({ kind: 'betPlaced', matchOddsIds: ids })\n } catch {\n // a host method never throws into operator code\n }\n },\n matchOpened(match) {\n try {\n const id: unknown = match.matchId\n if (isValidId(id)) dispatch({ kind: 'matchOpened', matchId: id })\n } catch {\n // a host method never throws into operator code\n }\n },\n }\n\n STATES.set(host, state)\n return host\n}\n\n/**\n * Internal: connects a mounted widget to a host, replays what was queued, and returns the detach.\n * Not exported from the package.\n */\nexport function attachHost(host: WidgetHost, sink: HostSink): () => void {\n const state = STATES.get(host)\n if (!state) return () => {}\n state.sink = sink\n const queued = state.queue\n state.queue = []\n for (const command of queued) {\n try {\n sink(command)\n } catch {\n // one failing command must not drop the ones queued behind it\n }\n }\n return () => {\n // A second widget may have attached since; only the current owner clears the slot.\n if (state.sink === sink) state.sink = null\n }\n}\n","import { createContext, useContext } from 'react'\n\nexport interface MatchLinkValue {\n /** Reports the tap, calls the operator's onOpenMatch, and closes the panel on a phone. */\n open(matchId: number): void\n /** Accessible name for the link, in the widget's language. */\n label(home?: string, away?: string): string\n}\n\n/** Present only when the operator passed `onOpenMatch`. Without it nothing renders as a link. */\nexport const MatchLinkContext = createContext<MatchLinkValue | null>(null)\n\nexport function useMatchLink(): MatchLinkValue | null {\n return useContext(MatchLinkContext)\n}\n","import type { ReactNode } from 'react'\nimport { isValidId } from '../host'\nimport { useMatchLink } from '../matchLinkContext'\n\n/**\n * Wraps a card's team names. With no `onOpenMatch` from the operator, or no usable match id, it\n * renders the element the card rendered before, class and children unchanged. Otherwise it is a\n * button that keeps that class for layout and opens the operator's match page.\n */\nexport function MatchLink({ matchId, home, away, detail, className, as: Tag = 'span', children }: {\n matchId: number\n home?: string | null\n away?: string | null\n /** What the link shows besides the names, such as the score. The label replaces the button's\n * content for a screen reader, so anything left out of it is never announced. */\n detail?: string\n className: string\n as?: 'span' | 'div'\n children: ReactNode\n}): JSX.Element {\n const link = useMatchLink()\n if (!link || !isValidId(matchId)) return <Tag className={className}>{children}</Tag>\n const label = link.label(home ?? undefined, away ?? undefined)\n return (\n <button\n type=\"button\"\n className={`${className} ss-w-matchlink`}\n aria-label={detail ? `${label}, ${detail}` : label}\n onClick={() => link.open(matchId)}\n >\n {children}\n </button>\n )\n}\n","import type { InsightVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { AddToSlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\nimport { MatchLink } from './MatchLink'\n\n// The reason-to-bet fact sentence, shown in full: the card carries no supporting stat rows and\n// nothing to expand.\nfunction ReasonStrip({ it }: { it: InsightVM }): JSX.Element | null {\n if (!it.text) return null\n return (\n <div className=\"ss-w-bi-reason\">\n <span className=\"ss-w-bi-chart\" aria-hidden=\"true\" />\n <p className=\"ss-w-bi-text\">{it.text}</p>\n </div>\n )\n}\n\n// Renders the fixture as the card's hero: the named team pair when present, else the prose\n// fixture, else the competition (the fallback that becomes the header hero when there is no\n// fixture at all). On a fixture card this fills its own line; the competition rides the meta line\n// above it (u350 two-tier).\nfunction CardFixture({ it }: { it: InsightVM }): JSX.Element | null {\n if (it.homeTeamName && it.awayTeamName) {\n return (\n <>\n <Crest kind=\"team\" url={it.homeCrest} name={it.homeTeamName} />\n <span className=\"ss-w-bi-team\">{it.homeTeamName}</span>\n <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n <span className=\"ss-w-bi-team\">{it.awayTeamName}</span>\n <Crest kind=\"team\" url={it.awayCrest} name={it.awayTeamName} />\n </>\n )\n }\n if (it.fixture) return <span className=\"ss-w-bi-fixture-txt\">{it.fixture}</span>\n if (it.competition) {\n return (\n <>\n <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n <span className=\"ss-w-bi-comp\">{it.competition}</span>\n </>\n )\n }\n return null\n}\n\nfunction InsightCard(\n { it, ui, slip, monitor }: { it: InsightVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element {\n const live = it.isLive || it.phase === 'live'\n // Prefer the server-rendered chip (operator timezone + language); fall back to browser-zone\n // formatting of the raw instant for older servers that don't send a label.\n const kickoffFallback = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : undefined\n const kickoff = it.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName\n // A fixture (team pair or prose string) is the card's hero and gets its own full-width line so\n // long club names stop truncating; the competition, kickoff and match pin sit on a quieter meta\n // line above it. Only when there is no fixture does the competition itself become the hero on a\n // single header line (u350 two-tier).\n const leftIsFixture = hasNamedTeams || !!it.fixture\n const showPin = !!monitor && it.pinEnabled\n const showHeader = leftIsFixture || !!it.competition || live || !!kickoff || showPin\n // live badge + kickoff + match pin: shared by the fixture card's meta line and the\n // competition-hero card's header-right, so the trio renders identically on both. The pin here\n // pins the MATCH; a moved price opens its history from the pick row below (D27).\n const headerControls = (\n <>\n {live ? (\n <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n ) : null}\n {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n {showPin && ui ? (\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: it.matchId }} />\n ) : null}\n </>\n )\n return (\n <div className=\"ss-w-binsight\">\n {showHeader ? (\n leftIsFixture ? (\n <div className=\"ss-w-bi-head\">\n {(it.competition || live || kickoff || showPin) ? (\n <div className=\"ss-w-bi-meta\">\n <span className=\"ss-w-bi-meta-left\">\n {it.competition ? (\n <>\n <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n <span className=\"ss-w-bi-comp\">{it.competition}</span>\n </>\n ) : null}\n </span>\n <span className=\"ss-w-bi-meta-right\">{headerControls}</span>\n </div>\n ) : null}\n <MatchLink as=\"div\" matchId={it.matchId} home={it.homeTeamName} away={it.awayTeamName} className=\"ss-w-bi-fixture-line\">\n <CardFixture it={it} />\n </MatchLink>\n </div>\n ) : (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-left\"><CardFixture it={it} /></span>\n <span className=\"ss-w-bi-header-right\">{headerControls}</span>\n </div>\n )\n ) : null}\n <div className=\"ss-w-bi-action\">\n {it.market ? <span className=\"ss-w-bi-market\">{it.market}</span> : null}\n <div className=\"ss-w-bi-pick-row\">\n {it.selection ? <span className=\"ss-w-bi-sel\">{it.selection}</span> : null}\n {it.odds ? (\n <span className=\"ss-w-bi-odds\">\n <b>{it.odds}</b>\n <OddsMovementBadge previous={it.previousOdds} current={it.odds} direction={it.movementDirection} ui={ui} />\n {it.bookmaker ? <span className=\"ss-w-bi-book\">{it.bookmaker}</span> : null}\n </span>\n ) : null}\n {it.odds && showPin && ui && it.previousOdds ? (\n <PriceHistoryButton\n ui={ui}\n monitor={monitor}\n selection={{ matchId: it.matchId, marketDeveloperName: it.marketDeveloperName, selectionLabel: it.selectionLabel, line: it.line, matchOddsId: it.matchOddsId }}\n />\n ) : null}\n <AddToSlipButton it={it} slip={slip} ui={ui} />\n </div>\n </div>\n {it.isMarketFloor ? (\n <span className=\"ss-w-bi-floor\">{ui?.marketFloorLabel ?? 'Market price · not a value pick'}</span>\n ) : null}\n <ReasonStrip it={it} />\n {it.disclaimer ? <p className=\"ss-w-bi-disc\">{it.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function BettingInsightList(\n { insights, ui, slip, monitor }:\n { insights: InsightVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element | null {\n if (!insights || insights.length === 0) return null\n return (\n <div className=\"ss-w-binsights\">\n {insights.map((it) => <InsightCard key={it.id} it={it} ui={ui} slip={slip} monitor={monitor} />)}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { MarketOddsVM, MarketOddsRowVM } from '../model'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { SlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\nimport { MatchLink } from './MatchLink'\n\nfunction OddsRow(\n { vm, row, ui, slip, inSlipIds, history }:\n { vm: MarketOddsVM; row: MarketOddsRowVM; ui?: UiConfig; slip: SlipHandlerProps; inSlipIds?: Record<number, true>; history?: LiveMonitorController },\n): JSX.Element {\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null\n // D5 persistent in-slip badge: keyed by matchOddsId in the widget's slip state (`added`, set by\n // StatsWidget's onAddToSlip wrap), NOT the button's own \"In slip\" mark -- the two follow\n // different rules (a duplicate answer marks the button and not the badge). Passed as a plain\n // id map (not the full LiveMonitorController) so callers can surface the badge without also\n // turning on this list's OWN pin-toggle header (OddsPanel already owns that pin via the\n // market snapshot's context line -- a second, independently-keyed toggle here could drift out\n // of sync with it).\n const inSlip = !!inSlipIds && row.matchOddsId != null && !!inSlipIds[row.matchOddsId]\n return (\n <div className=\"ss-w-mo-row\">\n <span className=\"ss-w-mo-sel\">{row.selection}</span>\n <OddsMovementBadge previous={row.previousOdds} current={row.odds} direction={row.movementDirection} ui={ui} />\n <span className=\"ss-w-mo-price\">{row.odds}</span>\n {history && ui && row.previousOdds ? (\n <PriceHistoryButton\n ui={ui}\n monitor={history}\n selection={{ matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, selectionLabel: row.selectionLabel, line: row.line, matchOddsId: row.matchOddsId }}\n />\n ) : null}\n {inSlip && ui ? <span className=\"ss-w-mon-inslip\">✓ {ui.inSlipLabel}</span> : null}\n <SlipButton selection={selection} shownOdds={row.odds} marketDeveloperName={vm.marketDeveloperName} selectionLabel={row.selectionLabel} line={row.line} slip={slip} ui={ui} />\n </div>\n )\n}\n\nfunction MarketOddsCard(\n { vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n { vm: MarketOddsVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element {\n const [open, setOpen] = useState(false)\n const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName\n const showPin = !!monitor && vm.pinEnabled\n // Chat path (no pinRef): the header pin is the MATCH pin, and a price that moved opens its\n // history (D27). The OddsPanel path passes pinRef and keeps its single market pin in the header;\n // the Live tab accordion (hideHeader) has neither.\n const history = showPin && !pinRef && !hideHeader ? monitor : undefined\n const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin\n return (\n <div className={hideHeader ? 'ss-w-mocard ss-w-mocard--bare' : 'ss-w-mocard'}>\n {!hideHeader && (\n <>\n {showHeader ? (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-left\">\n {vm.competition ? (\n <>\n <Crest kind=\"comp\" url={vm.competitionCrest} name={vm.competition} />\n <span className=\"ss-w-bi-comp\">{vm.competition}</span>\n </>\n ) : null}\n </span>\n <span className=\"ss-w-bi-header-right\">\n {vm.isLive ? (\n <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n ) : null}\n {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n {showPin && ui ? (\n <PinToggle\n ui={ui}\n monitor={monitor}\n pin={pinRef ?? { kind: 'match', matchId: vm.matchId }}\n />\n ) : null}\n </span>\n </div>\n ) : null}\n {(hasNamedTeams || vm.fixture || vm.market) ? (\n <div className=\"ss-w-mo-sub\">\n {hasNamedTeams ? (\n <MatchLink as=\"div\" matchId={vm.matchId} home={vm.homeTeamName} away={vm.awayTeamName} className=\"ss-w-bi-fixture\">\n <Crest kind=\"team\" url={vm.homeCrest} name={vm.homeTeamName} />\n <span className=\"ss-w-bi-team\">{vm.homeTeamName}</span>\n <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n <span className=\"ss-w-bi-team\">{vm.awayTeamName}</span>\n <Crest kind=\"team\" url={vm.awayCrest} name={vm.awayTeamName} />\n </MatchLink>\n ) : vm.fixture ? <span className=\"ss-w-mo-teams\">{vm.fixture}</span> : null}\n {vm.market ? (\n <div className=\"ss-w-mo-market-row\">\n <span className=\"ss-w-mo-market\">{vm.market}</span>\n </div>\n ) : null}\n </div>\n ) : null}\n </>\n )}\n {vm.statText && !hideHeader ? <div className=\"ss-w-mo-stat\">{vm.statText}</div> : null}\n <div className=\"ss-w-mo-rows\">\n {vm.mainRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} />)}\n {open ? vm.moreRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} />) : null}\n </div>\n {vm.moreRows.length > 0 ? (\n <button type=\"button\" className=\"ss-w-mo-more\" aria-expanded={open} onClick={() => setOpen((v) => !v)}>\n <span>{open ? ui?.hideLines ?? 'Hide lines' : `${ui?.moreLines ?? 'More lines'} (${vm.moreRows.length})`}</span>\n <span className={`ss-w-mo-more-chev${open ? ' ss-w-mo-more-chev-up' : ''}`} aria-hidden=\"true\" />\n </button>\n ) : null}\n {vm.bookmaker ? (\n <div className=\"ss-w-mo-foot\">\n <span>{vm.bookmaker}</span>\n </div>\n ) : null}\n {vm.disclaimer ? <p className=\"ss-w-bi-disc\">{vm.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function MarketOddsCardList(\n { cards, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n { cards: MarketOddsVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-mocards\">\n {cards.map((vm) => (\n <MarketOddsCard key={vm.id} vm={vm} ui={ui} slip={slip} monitor={monitor} inSlipIds={inSlipIds} hideHeader={hideHeader} pinRef={pinRef} />\n ))}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { CompactCellVM, CompactListVM, CompactRowVM } from '../compactList'\nimport { COMPACT_PAGE } from '../compactList'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { MatchLink } from './MatchLink'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PinToggle } from './PinToggle'\n\nfunction Cell({ row, cell, ui, slip }: { row: CompactRowVM; cell: CompactCellVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const vm = row.card\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, cell.row, slip.conversationId) : null\n const button = (\n <SlipButton\n selection={selection}\n shownOdds={cell.row.odds}\n marketDeveloperName={vm.marketDeveloperName}\n selectionLabel={cell.row.selectionLabel}\n line={cell.row.line}\n slip={slip}\n ui={ui}\n price={{ label: cell.label, ariaLabel: `${vm.homeTeamName ?? ''} ${vm.awayTeamName ?? ''}, ${cell.row.selection} ${cell.row.odds}` }}\n />\n )\n return (\n // A third of the price column fits four characters at the row's size: 13.00 steps down a size\n // and 101.00 two.\n <span className={['ss-w-mol-cell', cell.row.odds.length >= 5 && 'ss-w-mol-cell--wide', cell.row.odds.length >= 6 && 'ss-w-mol-cell--wider'].filter(Boolean).join(' ')}>\n {selection && slip.onAddToSlip && ui ? button : (\n <span className=\"ss-w-mol-price\">\n {cell.label ? <span className=\"ss-w-mol-lab\">{cell.label}</span> : null}\n {cell.row.odds}\n </span>\n )}\n <OddsMovementBadge previous={cell.row.previousOdds} current={cell.row.odds} direction={cell.row.movementDirection} ui={ui} />\n </span>\n )\n}\n\nfunction Row({ row, columns, ui, slip, monitor }: {\n row: CompactRowVM; columns: number; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n}): JSX.Element {\n const vm = row.card\n const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const when = vm.isLive\n ? ui?.liveLabel ?? 'Live'\n : vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n return (\n <div className=\"ss-w-mol-row\">\n <MatchLink as=\"div\" matchId={vm.matchId} home={vm.homeTeamName} away={vm.awayTeamName} className=\"ss-w-mol-fx\">\n <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.homeCrest} name={vm.homeTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.homeTeamName}</span></span>\n <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.awayCrest} name={vm.awayTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.awayTeamName}</span></span>\n {row.otherMarket ? <span className=\"ss-w-mol-mkt\">{row.otherMarket}</span> : null}\n </MatchLink>\n <span className=\"ss-w-mol-cells\" style={{ gridTemplateColumns: `repeat(${row.cells.length || columns}, minmax(0, 1fr))` }}>\n {row.cells.map((cell) => <Cell key={cell.row.key} row={row} cell={cell} ui={ui} slip={slip} />)}\n </span>\n <span className={vm.isLive ? 'ss-w-mol-side ss-w-mol-side--live' : 'ss-w-mol-side'}>\n {when ? <span className=\"ss-w-mol-when\">{when}</span> : null}\n {monitor && vm.pinEnabled && ui ? <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: vm.matchId }} /> : null}\n </span>\n </div>\n )\n}\n\nexport function CompactOddsList({ list, ui, slip, monitor }: {\n list: CompactListVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n}): JSX.Element {\n const [shown, setShown] = useState(COMPACT_PAGE)\n const hidden = list.rowCount - shown\n let left = shown\n return (\n <div className=\"ss-w-mol\">\n <div className=\"ss-w-mol-head\">\n <span className=\"ss-w-mol-market\">{list.market}</span>\n <span className=\"ss-w-mol-cols\" style={{ gridTemplateColumns: `repeat(${list.columns.length}, minmax(0, 1fr))` }}>\n {list.columns.map((c, i) => <span key={`${c}:${i}`} className=\"ss-w-mol-col\">{c}</span>)}\n </span>\n <span className=\"ss-w-mol-side\" aria-hidden=\"true\" />\n </div>\n {list.groups.map((group, gi) => {\n const rows = group.rows.slice(0, Math.max(0, left))\n left -= rows.length\n if (rows.length === 0) return null\n return (\n <div className=\"ss-w-mol-group\" key={`${group.competition ?? ''}:${gi}`}>\n {group.competition ? (\n <div className=\"ss-w-mol-comp\">\n <Crest kind=\"comp\" url={group.competitionCrest} name={group.competition} />\n <span>{group.competition}</span>\n </div>\n ) : null}\n {rows.map((row) => <Row key={row.card.id} row={row} columns={list.columns.length} ui={ui} slip={slip} monitor={monitor} />)}\n </div>\n )\n })}\n {hidden > 0 ? (\n <button type=\"button\" className=\"ss-w-mo-more\" onClick={() => setShown((n) => n + COMPACT_PAGE)}>\n <span>{ui?.showMore ? ui.showMore(Math.min(COMPACT_PAGE, hidden)) : `Show ${Math.min(COMPACT_PAGE, hidden)} more`}</span>\n <span className=\"ss-w-mo-more-chev\" aria-hidden=\"true\" />\n </button>\n ) : null}\n {list.bookmaker ? <div className=\"ss-w-mo-foot\"><span>{list.bookmaker}</span></div> : null}\n {list.disclaimer ? <p className=\"ss-w-bi-disc\">{list.disclaimer}</p> : null}\n </div>\n )\n}\n","import type { MarketOddsRowVM, MarketOddsVM } from './model'\n\n/** One price in a compact list row. `label` is set when the column head does not say what it is. */\nexport interface CompactCellVM {\n row: MarketOddsRowVM\n label?: string\n}\n\nexport interface CompactRowVM {\n card: MarketOddsVM\n /** The row's market name, set when it differs from the list's market. */\n otherMarket?: string\n cells: CompactCellVM[]\n}\n\nexport interface CompactGroupVM {\n competition?: string\n competitionCrest?: string\n rows: CompactRowVM[]\n}\n\nexport interface CompactListVM {\n market: string\n columns: string[]\n groups: CompactGroupVM[]\n rowCount: number\n bookmaker?: string\n disclaimer?: string\n}\n\nexport const COMPACT_MIN_CARDS = 3\n\n/** A row holds two or three prices in the price column. A market with more, such as correct score,\n * or a card with every price suspended, keeps the stack. */\nconst COMPACT_MAX_PRICES = 3\n\n/** Match Result heads are the betting convention, 1 X 2, in every language: \"Beraberlik\" and\n * \"Deplasman\" do not fit a price column. */\nconst RESULT_MARKET = 'FULLTIME_RESULT'\nconst RESULT_HEADS = ['1', 'X', '2']\nexport const COMPACT_PAGE = 5\n\n/** The list's market: the one most cards carry, the first card's on a tie. */\nfunction referenceMarket(cards: MarketOddsVM[]): string | undefined {\n const counts = new Map<string | undefined, number>()\n for (const c of cards) counts.set(c.marketDeveloperName, (counts.get(c.marketDeveloperName) ?? 0) + 1)\n let best = cards[0]!.marketDeveloperName\n for (const c of cards) {\n if ((counts.get(c.marketDeveloperName) ?? 0) > (counts.get(best) ?? 0)) best = c.marketDeveloperName\n }\n return best\n}\n\n/**\n * D16: three or more price cards on one turn, one per fixture, draw as one compact list. Returns\n * null for anything else, which keeps the stack: fewer cards, or two cards of the same fixture.\n * A row of another market than the list's names its market and labels its own prices (R19, Ertu\n * 2026-10-03).\n */\nexport function toCompactList(cards: MarketOddsVM[]): CompactListVM | null {\n if (cards.length < COMPACT_MIN_CARDS) return null\n if (new Set(cards.map((c) => c.matchId)).size !== cards.length) return null\n if (cards.some((c) => c.mainRows.length === 0 || c.mainRows.length > COMPACT_MAX_PRICES)) return null\n\n const market = referenceMarket(cards)\n // The heads come from the card of the list's market with the most open prices: a suspended price\n // on the first card must not drop a column for every row.\n const head = cards\n .filter((c) => c.marketDeveloperName === market)\n .reduce((best, c) => (c.mainRows.length > best.mainRows.length ? c : best))\n const labels = head.mainRows.map((r) => r.selectionLabel ?? r.selection)\n const columns = market === RESULT_MARKET && labels.length === RESULT_HEADS.length ? RESULT_HEADS : labels\n\n const toRow = (card: MarketOddsVM): CompactRowVM => {\n const sameMarket = card.marketDeveloperName === market\n const own = card.mainRows.map((r) => r.selectionLabel ?? r.selection)\n const aligned = sameMarket && own.length === labels.length && own.every((l, i) => l === labels[i])\n return {\n card,\n otherMarket: sameMarket ? undefined : card.market,\n cells: card.mainRows.map((row) => ({\n row,\n label: !aligned ? row.selection : row.line !== head.mainLine && row.line ? row.line : undefined,\n })),\n }\n }\n\n const groups: CompactGroupVM[] = []\n for (const card of cards) {\n let group = groups.find((g) => g.competition === card.competition)\n if (!group) {\n group = { competition: card.competition, competitionCrest: card.competitionCrest, rows: [] }\n groups.push(group)\n }\n group.rows.push(toRow(card))\n }\n\n return {\n market: head.market,\n columns,\n groups,\n rowCount: cards.length,\n bookmaker: cards.map((c) => c.bookmaker).find(Boolean),\n disclaimer: cards.map((c) => c.disclaimer).find(Boolean),\n }\n}\n","import type { UiConfig } from '../config'\nimport type { OddsMovementVM } from '../model'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { CHART_VIEW_H, CHART_VIEW_W } from '../chart'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PriceHistoryButton } from './PriceHistoryButton'\n\nfunction directionWord(vm: OddsMovementVM, ui?: UiConfig): string {\n if (vm.direction === 'shortened') return ui?.oddsShortened ?? 'shortened'\n if (vm.direction === 'drifted') return ui?.oddsDrifted ?? 'drifted'\n return ''\n}\n\nfunction OddsMovementCard(\n { vm, ui, monitor }: { vm: OddsMovementVM; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element {\n const word = directionWord(vm, ui)\n const drift = word ? `, ${word}` : ''\n const aria = ui?.chartAria\n ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours)\n : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`\n const showPin = !!monitor && vm.pinEnabled\n\n return (\n <div className=\"ss-w-omcard\">\n <div className=\"ss-w-om-head\">\n <span className=\"ss-w-om-market\">{vm.market}</span>\n <span className=\"ss-w-om-tag\">{ui?.priceMovement ?? 'Price movement'}</span>\n {showPin && ui ? (\n <PriceHistoryButton\n ui={ui}\n monitor={monitor}\n selection={{\n matchId: vm.matchId,\n marketDeveloperName: vm.marketDeveloperName,\n selectionLabel: vm.selectionLabel,\n line: vm.line,\n matchOddsId: vm.matchOddsId,\n }}\n />\n ) : null}\n </div>\n {vm.fixture ? (\n <div className=\"ss-w-om-fixture\">\n <span>{vm.fixture}</span>\n {vm.competition ? <span className=\"ss-w-om-comp\">{vm.competition}</span> : null}\n </div>\n ) : null}\n <div className=\"ss-w-om-sel\">{vm.selection}</div>\n <OddsMovementBadge previous={vm.opening} current={vm.current} direction={vm.direction} ui={ui} />\n\n {vm.geometry === null ? (\n <div className=\"ss-w-om-empty\">\n {vm.observationCount === 1\n ? ui?.singlePricePoint ?? 'Only one price recorded so far for this selection.'\n : ui?.notEnoughHistory ?? 'No price history recorded yet for this selection.'}\n </div>\n ) : (\n <svg\n className=\"ss-w-om-chart\"\n viewBox={vm.geometry.viewBox}\n width=\"100%\"\n role=\"img\"\n aria-label={aria}\n >\n {vm.geometry.gridlines.map((g) => (\n <g key={g.price}>\n <line className=\"ss-w-om-grid\" x1={40} y1={g.y} x2={CHART_VIEW_W - 8} y2={g.y} />\n <text className=\"ss-w-om-ylab\" x={34} y={g.y + 3} textAnchor=\"end\">{g.price.toFixed(2)}</text>\n </g>\n ))}\n <path className=\"ss-w-om-line\" d={vm.geometry.path} fill=\"none\" />\n {vm.geometry.markers.map((m, i) => (\n <circle key={i} className=\"ss-w-om-dot\" cx={m.x} cy={m.y} r={2.5} />\n ))}\n {ui?.chartTimeLabel ? (\n <>\n <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8} textAnchor=\"start\">\n {ui.chartTimeLabel(vm.geometry.startMs)}\n </text>\n <text className=\"ss-w-om-xlab\" x={CHART_VIEW_W - 8} y={CHART_VIEW_H - 8} textAnchor=\"end\">\n {ui.chartTimeLabel(vm.geometry.endMs)}\n </text>\n </>\n ) : (\n <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8}>\n {ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h`}\n </text>\n )}\n </svg>\n )}\n\n <div className=\"ss-w-om-foot\">\n <span>{ui?.openingLabel ?? 'Opening'} <b>{vm.opening}</b></span>\n <span>{ui?.currentLabel ?? 'Current'} <b>{vm.current}</b></span>\n </div>\n {vm.bookmaker ? (\n <div className=\"ss-w-om-foot\">\n <span>{vm.bookmaker}</span>\n </div>\n ) : null}\n {vm.excludedCount > 0 ? (\n <div className=\"ss-w-om-excl\">\n {ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.`}\n </div>\n ) : null}\n {vm.isSuspended ? (\n <div className=\"ss-w-om-susp\">{ui?.selectionSuspended ?? 'This selection is not currently available to bet.'}</div>\n ) : null}\n {vm.disclaimer ? <div className=\"ss-w-om-disc\">{vm.disclaimer}</div> : null}\n </div>\n )\n}\n\nexport function OddsMovementCardList(\n { cards, ui, monitor }: { cards: OddsMovementVM[]; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-omcards\">\n {cards.map((vm) => <OddsMovementCard key={vm.id} vm={vm} ui={ui} monitor={monitor} />)}\n </div>\n )\n}\n","import type { ActionVM } from '../model'\n\nexport function ActionButtons({ actions, loading, disabled, onAct }: { actions: ActionVM[]; loading: boolean; disabled?: boolean; onAct: (action: ActionVM) => void }): JSX.Element | null {\n if (actions.length === 0 && !loading) return null\n return (\n <div className=\"ss-w-actions\">\n {actions.map((a, i) => (\n <button key={`${a.label}-${i}`} type=\"button\" className=\"ss-w-abtn\" disabled={disabled} onClick={() => onAct(a)}>{a.label}</button>\n ))}\n {actions.length === 0 && loading ? (\n <>\n <span className=\"ss-w-abtn-shimmer\" />\n <span className=\"ss-w-abtn-shimmer\" />\n </>\n ) : null}\n </div>\n )\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport { DashboardIcon, ChevronIcon } from '../Icons'\n\n// The server payload caps crests at 3 (spec D2); slicing here is a defensive floor, not a\n// server-side promise, since a badge + crest row this wide already competes for the same\n// space the title needs.\nconst MAX_CRESTS = 3\n\n// The server appends the price as a last \" · @1.85\" segment; it is lifted out so the hero can show\n// it as a price rather than as the tail of a sentence.\nconst ODDS_TAIL = /\\s*·\\s*@(\\d+(?:\\.\\d+)?)\\s*$/\n\nfunction splitOdds(subtitle: string): { text: string; odds?: string } {\n const m = ODDS_TAIL.exec(subtitle)\n return m ? { text: subtitle.slice(0, m.index), odds: m[1] } : { text: subtitle }\n}\n\nfunction HeroTile({ tile, onTap, oddsLabel }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel: string }): JSX.Element {\n const crests = (tile.imageUrls ?? []).filter(Boolean).slice(0, 2)\n const sub = tile.subtitle ? splitOdds(tile.subtitle) : null\n return (\n <button type=\"button\" className=\"ss-w-dash-tile ss-w-dash-tile--full ss-w-dash-hero\" onClick={onTap}>\n <span className=\"ss-w-dash-hero-top\">\n {tile.badgeText ? <span className=\"ss-w-dash-hero-badge\">{tile.badgeText}</span> : null}\n {sub?.odds ? <span className=\"ss-w-dash-hero-price\"><span className=\"ss-g-sr\">{oddsLabel} </span>{sub.odds}</span> : null}\n <span className=\"ss-w-dash-hero-chevron\"><ChevronIcon /></span>\n </span>\n <span className=\"ss-w-dash-hero-main\">\n <span className=\"ss-w-dash-hero-visual\" aria-hidden=\"true\">\n {crests.length > 0\n ? crests.map((url, i) => (\n <span key={`${url}-${i}`} className=\"ss-w-dash-hero-crest\" style={{ backgroundImage: `url(${url})` }} />\n ))\n : <span className=\"ss-w-dash-hero-icon\"><DashboardIcon name={tile.icon} /></span>}\n </span>\n <span className=\"ss-w-dash-hero-body\">\n <span className=\"ss-w-dash-hero-title\">{tile.title}</span>\n {sub?.text ? <span className=\"ss-w-dash-hero-subtitle\">{sub.text}</span> : null}\n </span>\n </span>\n </button>\n )\n}\n\nexport function DashboardTile({ tile, onTap, oddsLabel = 'Odds' }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel?: string }): JSX.Element {\n if (tile.emphasis === 'hero') return <HeroTile tile={tile} onTap={onTap} oddsLabel={oddsLabel} />\n const spanClass = tile.span === 'full' ? 'ss-w-dash-tile--full' : 'ss-w-dash-tile--half'\n const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS)\n const hasMeta = Boolean(tile.badgeText) || crests.length > 0\n return (\n <button type=\"button\" className={`ss-w-dash-tile ${spanClass}`} onClick={onTap}>\n <span className=\"ss-w-dash-tile-icon\"><DashboardIcon name={tile.icon} /></span>\n <span className=\"ss-w-dash-tile-body\">\n <span className=\"ss-w-dash-tile-title\">{tile.title}</span>\n {tile.subtitle ? <span className=\"ss-w-dash-tile-subtitle\">{tile.subtitle}</span> : null}\n {hasMeta ? (\n // Badge + crests sit on their own row, below the title, instead of sharing the\n // icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone\n // (~70px) left the title column at ~22px and forced character-by-character wrapping.\n <span className=\"ss-w-dash-tile-meta\">\n {tile.badgeText ? <span className=\"ss-w-dash-tile-badge\">{tile.badgeText}</span> : null}\n {crests.length > 0 ? (\n <span className=\"ss-w-dash-tile-crests\">\n {crests.map((url, i) => (\n <span key={`${url}-${i}`} className=\"ss-w-dash-tile-crest\" style={{ backgroundImage: `url(${url})` }} aria-hidden=\"true\" />\n ))}\n </span>\n ) : null}\n </span>\n ) : null}\n </span>\n <span className=\"ss-w-dash-tile-chevron\"><ChevronIcon /></span>\n </button>\n )\n}\n","import type { GreetingDashboard as GreetingDashboardData, GreetingDashboardLayout, GreetingDashboardTile as GreetingDashboardTileData } from '@sensiblestats/widget-sdk'\nimport { DashboardTile } from './DashboardTile'\n\nconst LAYOUT_CLASSES: Record<GreetingDashboardLayout, string> = {\n market: 'ss-w-dash--market',\n goal: 'ss-w-dash--goal',\n discovery: 'ss-w-dash--discovery',\n}\n\n// The server's layout is a closed set, but a mismatched deploy or a future value\n// could still send something outside it. Falling back to goal (an allowlist check,\n// not a truthiness test) avoids emitting a class with no CSS rule behind it.\n// hasOwnProperty (not `in`) so a prototype member name like 'toString' can't slip\n// through as a layout and get interpolated into the className.\nfunction layoutClass(layout: string): string {\n return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout)\n ? LAYOUT_CLASSES[layout as GreetingDashboardLayout]\n : LAYOUT_CLASSES.goal\n}\n\nexport function GreetingDashboard({ dashboard, onTap, oddsLabel }: { dashboard: GreetingDashboardData; onTap: (tile: GreetingDashboardTileData, index: number) => void; oddsLabel?: string }): JSX.Element {\n return (\n <div className={`ss-w-dash ${layoutClass(dashboard.layout)}`}>\n <div className=\"ss-w-dash-head\">\n <span className=\"ss-w-dash-title\">{dashboard.title}</span>\n {dashboard.subtitle ? <span className=\"ss-w-dash-subtitle\">{dashboard.subtitle}</span> : null}\n </div>\n <div className=\"ss-w-dash-grid\">\n {dashboard.tiles.map((t, i) => (\n <DashboardTile key={`${t.title}-${i}`} tile={t} onTap={() => onTap(t, i)} oddsLabel={oddsLabel} />\n ))}\n </div>\n {dashboard.footerTip ? <span className=\"ss-w-dash-foot\">{dashboard.footerTip}</span> : null}\n </div>\n )\n}\n","import type { FixtureCard as FixtureCardData, FormMatch } from '@sensiblestats/widget-sdk'\nimport { Crest } from '../Crest'\n\nfunction teamFormResultClass(result: FormMatch['result']): string {\n if (result === 'W') return 'ss-w-fandash-teamform-cell--win'\n if (result === 'L') return 'ss-w-fandash-teamform-cell--loss'\n return 'ss-w-fandash-teamform-cell--draw'\n}\n\n// One historical-match cell: subject crest + score + opponent crest, ordered by which side the\n// subject team played on so the score always reads left-to-right as it happened on the pitch.\nfunction TeamFormCell({ m, subjectCrestUrl, subjectName }: {\n m: FormMatch\n subjectCrestUrl?: string | null\n subjectName: string\n}): JSX.Element {\n const subjectCrest = <Crest url={subjectCrestUrl ?? undefined} name={subjectName} kind=\"team\" />\n const opponentCrest = <Crest url={m.opponentCrestUrl ?? undefined} kind=\"team\" />\n const score = m.teamIsHome ? `${m.teamScore} - ${m.oppScore}` : `${m.oppScore} - ${m.teamScore}`\n return (\n <div className={`ss-w-fandash-teamform-cell ${teamFormResultClass(m.result)}`}>\n {m.teamIsHome ? subjectCrest : opponentCrest}\n <span className=\"ss-w-fandash-teamform-score\">{score}</span>\n {m.teamIsHome ? opponentCrest : subjectCrest}\n </div>\n )\n}\n\nconst TEAM_FORM_ROWS = 5\n\n// Two-column \"Team form\" card: left = home team's last 5, right = away team's last 5, most-recent\n// first. The rows grid is filled home-cell, away-cell per index (matching the approved two-column\n// mock) so a 2-col CSS grid lays them out in the right pairs without any extra layout wiring. A\n// shorter side just leaves later slots blank rather than shifting the other column's rows.\nfunction teamFormRows(data: FixtureCardData['data']): JSX.Element[] {\n return Array.from({ length: TEAM_FORM_ROWS }, (_, i) => i).flatMap((i) => [\n <span key={`h-${i}`} className=\"ss-w-fandash-teamform-slot\">\n {data.homeForm[i] ? (\n <TeamFormCell m={data.homeForm[i]} subjectCrestUrl={data.homeCrestUrl} subjectName={data.homeName} />\n ) : null}\n </span>,\n <span key={`a-${i}`} className=\"ss-w-fandash-teamform-slot\">\n {data.awayForm[i] ? (\n <TeamFormCell m={data.awayForm[i]} subjectCrestUrl={data.awayCrestUrl} subjectName={data.awayName} />\n ) : null}\n </span>,\n ])\n}\n\n// The fixture payload renders as three stacked [data] cards -- the fixture head (teams, kickoff,\n// venue), the last-five form, and the head-to-head record -- so each block reads as its own unit.\n// None is a tap target: the compare-form action lives in the greeting chips, so the card carries no\n// redundant CTA. (u319: the server now issues FixtureCard as a plain DataCard with no actionRef.)\nexport function FixtureCard({ card }: { card: FixtureCardData }): JSX.Element {\n const { data } = card\n const h2h = data.h2H\n return (\n <>\n <div className=\"ss-w-fandash-card ss-w-fandash-fixture\">\n <span className=\"ss-w-fandash-eyebrow\">{card.title} · {data.competition}</span>\n <div className=\"ss-w-fandash-fixture-teams\">\n <span className=\"ss-w-fandash-fixture-team\">\n <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n <span className=\"ss-w-fandash-fixture-name\">{data.homeName}</span>\n </span>\n <span className=\"ss-w-fandash-fixture-vs\">v</span>\n <span className=\"ss-w-fandash-fixture-team ss-w-fandash-fixture-team--away\">\n <span className=\"ss-w-fandash-fixture-name\">{data.awayName}</span>\n <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n </span>\n </div>\n <div className=\"ss-w-fandash-fixture-meta\">\n <span className=\"ss-w-fandash-fixture-kickoff\">{data.kickoffLabel}</span>\n {data.venue ? <span className=\"ss-w-fandash-fixture-venue\"> · {data.venue}</span> : null}\n </div>\n </div>\n\n <div className=\"ss-w-fandash-card ss-w-fandash-lastfive\">\n <span className=\"ss-w-fandash-eyebrow\">{data.formLabel}</span>\n <div className=\"ss-w-fandash-teamform-head\">\n <span className=\"ss-w-fandash-teamform-head-team\">\n <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n <span className=\"ss-w-fandash-teamform-head-name\">{data.homeName}</span>\n </span>\n <span className=\"ss-w-fandash-teamform-head-team\">\n <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n <span className=\"ss-w-fandash-teamform-head-name\">{data.awayName}</span>\n </span>\n </div>\n <div className=\"ss-w-fandash-teamform-rows\">\n {teamFormRows(data)}\n </div>\n </div>\n\n {h2h || data.fact ? (\n <div className=\"ss-w-fandash-card ss-w-fandash-h2h\">\n {h2h ? (\n <>\n <span className=\"ss-w-fandash-eyebrow\">{h2h.label}</span>\n <div className=\"ss-w-fandash-split\">\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.wins}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.homeWinsLabel}</span>\n </span>\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.draws}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.drawsLabel}</span>\n </span>\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.losses}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.awayWinsLabel}</span>\n </span>\n </div>\n </>\n ) : null}\n {data.fact ? <span className=\"ss-w-fandash-fact\">{data.fact}</span> : null}\n </div>\n ) : null}\n </>\n )\n}\n","import { Fragment, useEffect, useState } from 'react'\nimport type { CountdownCard as CountdownCardData } from '@sensiblestats/widget-sdk'\n\ntype UnitKind = 'd' | 'h' | 'm' | 's'\ntype Segment = { value: string; unit: UnitKind }\n\nconst DAY_MS = 86_400_000\n\n// The countdown reads day:hour while the match is more than a day out, and switches to a live\n// hour:minute:second clock on match day (under a day to kickoff). `withSeconds` is dropped under\n// reduced motion so the card never shows a seconds figure it will never refresh. Returns null once\n// kickoff has passed.\nfunction remainingSegments(kickoffUnix: number, nowMs: number, withSeconds: boolean): Segment[] | null {\n const totalSeconds = Math.floor((kickoffUnix * 1000 - nowMs) / 1000)\n if (totalSeconds <= 0) return null\n const days = Math.floor(totalSeconds / 86_400)\n const hours = Math.floor((totalSeconds % 86_400) / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n const pad = (n: number) => String(n).padStart(2, '0')\n if (days > 0) return [{ value: pad(days), unit: 'd' }, { value: pad(hours), unit: 'h' }]\n const segs: Segment[] = [{ value: pad(hours), unit: 'h' }, { value: pad(minutes), unit: 'm' }]\n if (withSeconds) segs.push({ value: pad(seconds), unit: 's' })\n return segs\n}\n\nexport function CountdownCard({ card }: { card: CountdownCardData }): JSX.Element {\n const { data } = card\n // Unit labels are server-localized; the numbers are computed client-side.\n const unitLabel: Record<UnitKind, string> = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit }\n const [nowMs, setNowMs] = useState(() => Date.now())\n // Reduced motion is read once at mount: it decides whether the card ticks at all and whether it\n // shows a (necessarily static, so potentially stale) seconds figure. Ticking is otherwise\n // additive -- the segments computed at mount keep showing even if no interval ever fires.\n const [reduced] = useState(\n () => typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches,\n )\n const withinDay = data.kickoffUnix * 1000 - nowMs < DAY_MS\n useEffect(() => {\n if (reduced) return\n const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1000 : 60_000)\n return () => window.clearInterval(id)\n }, [reduced, withinDay])\n const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced)\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-countdown\">\n <div className=\"ss-w-fandash-countdown-top\">\n <span className=\"ss-w-fandash-eyebrow\">{card.title ?? 'Kick-off in'}</span>\n {segments ? (\n <span className=\"ss-w-fandash-countdown-clock\">\n {segments.map((s, i) => (\n <Fragment key={s.unit}>\n {i > 0 ? <span className=\"ss-w-fandash-countdown-colon\">:</span> : null}\n <span className=\"ss-w-fandash-countdown-seg\">\n <span className=\"ss-w-fandash-countdown-value\">{s.value}</span>\n <span className=\"ss-w-fandash-countdown-unit\">{unitLabel[s.unit]}</span>\n </span>\n </Fragment>\n ))}\n </span>\n ) : null}\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { InjuriesCard as InjuriesCardData, InjuryRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { Crest } from '../Crest'\n\nconst SHOWN = 3\n\nfunction ColHead({ name, crestUrl }: { name: string; crestUrl?: string | null }): JSX.Element {\n return (\n <span className=\"ss-w-fandash-injuries-col-head\">\n <Crest url={crestUrl ?? undefined} name={name} kind=\"team\" />\n <span className=\"ss-w-fandash-injuries-col-head-name\">{name}</span>\n </span>\n )\n}\n\nfunction InjuryList({ rows, emptyLabel, limit }: { rows: InjuryRow[]; emptyLabel: string; limit?: number }): JSX.Element {\n if (rows.length === 0) return <span className=\"ss-w-fandash-injuries-empty\">{emptyLabel}</span>\n const shown = limit === undefined ? rows : rows.slice(0, limit)\n return (\n <ul className=\"ss-w-fandash-injury-list\">\n {shown.map((r, i) => (\n <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-injury-row\">\n <span className=\"ss-w-fandash-injury-name\">{r.playerName}</span>\n <span className=\"ss-w-fandash-injury-meta\">\n <span className=\"ss-w-fandash-injury-status\">{r.status}</span>\n {r.injuryType ? <span className=\"ss-w-fandash-injury-type\">{r.injuryType}</span> : null}\n {r.expectedReturnLabel ? <span className=\"ss-w-fandash-injury-return\">{r.expectedReturnLabel}</span> : null}\n </span>\n </li>\n ))}\n </ul>\n )\n}\n\nexport function InjuriesCard({ card, ui }: { card: InjuriesCardData; ui?: UiConfig }): JSX.Element {\n const { data } = card\n const [expanded, setExpanded] = useState(false)\n // Either side's list can be long; a shared toggle collapses both to SHOWN and reveals the rest,\n // so the card doesn't push the input off-screen. The count is how many are hidden across both sides.\n const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN)\n const limit = expanded ? undefined : SHOWN\n const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n const showLess = ui?.showLess ?? 'Show less'\n // \"Ours\" is club-vs-opponent, not home-vs-away — reorder into home/away columns so the card\n // reads left-to-right like the rest of the dashboard regardless of which side the club is on.\n const homeCol = data.oursIsHome\n ? { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n : { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n const awayCol = data.oursIsHome\n ? { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n : { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-injuries\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-injuries-cols\">\n <div className=\"ss-w-fandash-injuries-col\">\n <ColHead name={homeCol.name} crestUrl={homeCol.crest} />\n <InjuryList rows={homeCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n </div>\n <div className=\"ss-w-fandash-injuries-divider\" />\n <div className=\"ss-w-fandash-injuries-col\">\n <ColHead name={awayCol.name} crestUrl={awayCol.crest} />\n <InjuryList rows={awayCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n </div>\n </div>\n {hidden > 0 ? (\n <button\n type=\"button\"\n className=\"ss-w-fandash-injuries-more\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? showLess : showMore(hidden)}\n </button>\n ) : null}\n </div>\n )\n}\n","import type { ReasonToBetCard as ReasonToBetCardData } from '@sensiblestats/widget-sdk'\n\nexport function ReasonToBetCard({ card }: { card: ReasonToBetCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-reasons\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <ul className=\"ss-w-fandash-reason-list\">\n {card.data.angles.map((angle, i) => (\n <li key={`${angle}-${i}`} className=\"ss-w-fandash-reason-item\">{angle}</li>\n ))}\n </ul>\n </div>\n )\n}\n","import type { WhereToWatchCard as WhereToWatchCardData } from '@sensiblestats/widget-sdk'\n\nexport function WhereToWatchCard({ card }: { card: WhereToWatchCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-watch\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <span className=\"ss-w-fandash-stations\">\n {card.data.stations.map((station, i) => (\n <span key={`${station}-${i}`} className=\"ss-w-fandash-station-chip\">{station}</span>\n ))}\n </span>\n </div>\n )\n}\n","import type { CongestedWeekCard as CongestedWeekCardData } from '@sensiblestats/widget-sdk'\n\nexport function CongestedWeekCard({ card, onTap }: { card: CongestedWeekCardData; onTap: (card: CongestedWeekCardData) => void }): JSX.Element {\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-congested\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-congested-grid\">\n {card.data.entries.map((entry, i) => (\n <span key={`${entry.opponent}-${i}`} className=\"ss-w-fandash-congested-cell\">\n <span className=\"ss-w-fandash-congested-day\">{entry.dayLabel}</span>\n <span className=\"ss-w-fandash-congested-opponent\">{entry.opponent}</span>\n <span className=\"ss-w-fandash-congested-comp\">{entry.competition}</span>\n <span className=\"ss-w-fandash-congested-time\">{entry.timeLabel}</span>\n </span>\n ))}\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { TransfersCard as TransfersCardData, TransferRow } from '@sensiblestats/widget-sdk'\n\nfunction TransferList({ rows }: { rows: TransferRow[] }): JSX.Element {\n if (rows.length === 0) return <span className=\"ss-w-fandash-transfers-empty\">None</span>\n return (\n <ul className=\"ss-w-fandash-transfer-list\">\n {rows.map((r, i) => (\n <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-transfer-row\">\n <span className=\"ss-w-fandash-transfer-name\">{r.playerName}</span>\n <span className=\"ss-w-fandash-transfer-club\">{r.otherClub}</span>\n {r.type ? <span className=\"ss-w-fandash-transfer-type\">{r.type}</span> : null}\n </li>\n ))}\n </ul>\n )\n}\n\nexport function TransfersCard({ card }: { card: TransfersCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-transfers\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-transfers-cols\">\n <div className=\"ss-w-fandash-transfers-col\">\n <span className=\"ss-w-fandash-transfers-col-head\">In</span>\n <TransferList rows={data.in} />\n </div>\n <div className=\"ss-w-fandash-transfers-col\">\n <span className=\"ss-w-fandash-transfers-col-head\">Out</span>\n <TransferList rows={data.out} />\n </div>\n </div>\n </div>\n )\n}\n","import type { LinksCard as LinksCardData } from '@sensiblestats/widget-sdk'\nimport { ChevronIcon } from '../Icons'\n\nexport function LinksCard({ card }: { card: LinksCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-links\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-link-grid\">\n {card.data.links.map((link, i) => (\n <a key={`${link.url}-${i}`} className=\"ss-w-fandash-link-tile\" href={link.url} target=\"_blank\" rel=\"noopener noreferrer\">\n <span className=\"ss-w-fandash-link-label\">{link.label}</span>\n <span className=\"ss-w-fandash-link-chevron\"><ChevronIcon /></span>\n </a>\n ))}\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { PostMatchResultCard as PostMatchResultCardData } from '@sensiblestats/widget-sdk'\n\nfunction initials(name: string): string {\n return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Same img-with-fallback treatment as LiveScoreCard's LiveCrest -- a broken/absent URL falls back\n// to a coloured initials chip, which a background-image span can't detect on its own.\nfunction PostMatchCrest({\n url,\n name,\n side,\n}: {\n url?: string | null\n name: string\n side: 'home' | 'away'\n}): JSX.Element {\n const [failed, setFailed] = useState(false)\n const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return (\n <span className={`${cls} ss-w-fandash-postmatch-crest--fallback`} aria-hidden=\"true\">\n {initials(name)}\n </span>\n )\n}\n\n// [data] card -- the full-time scoreboard. No tap target: the score itself is the payload, and\n// the goals/stats/top-performer cards below carry the actionRef taps for this match.\nexport function PostMatchResultCard({ card }: { card: PostMatchResultCardData }): JSX.Element {\n const { data } = card\n const homeWon = data.homeScore >= data.awayScore\n const awayWon = data.awayScore >= data.homeScore\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-result\">\n <div className=\"ss-w-fandash-postmatch-top\">\n {/* card.title carries the server-localized \"Full time\" label -- reused as the pill text\n rather than a hardcoded English literal. */}\n {card.title ? <span className=\"ss-w-fandash-postmatch-pill\">{card.title}</span> : null}\n <span className={`ss-w-fandash-postmatch-tag ss-w-fandash-postmatch-tag--${data.outcome}`}>\n {data.resultLabel}\n </span>\n </div>\n <div className=\"ss-w-fandash-postmatch-main\">\n <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--home\">\n <PostMatchCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n <span className=\"ss-w-fandash-postmatch-team-name\">{data.homeName}</span>\n </div>\n <div className=\"ss-w-fandash-postmatch-score-main\">\n <span\n className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? 'win' : 'lose'}`}\n >\n {data.homeScore}\n </span>\n <span className=\"ss-w-fandash-postmatch-score-sep\">–</span>\n <span\n className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? 'win' : 'lose'}`}\n >\n {data.awayScore}\n </span>\n </div>\n <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--away\">\n <PostMatchCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n <span className=\"ss-w-fandash-postmatch-team-name\">{data.awayName}</span>\n </div>\n </div>\n <div className=\"ss-w-fandash-postmatch-meta\">\n {data.kickoffLabel}\n {data.competition ? ` · ${data.competition}` : ''}\n </div>\n </div>\n )\n}\n","import type { PostMatchGoalsCard as PostMatchGoalsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see FixtureCard/CongestedWeekCard).\nexport function PostMatchGoalsCard({ card, onTap }: {\n card: PostMatchGoalsCardData\n onTap: (card: PostMatchGoalsCardData) => void\n}): JSX.Element {\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-goals\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <ul className=\"ss-w-fandash-postmatch-goal-list\">\n {card.data.goals.map((g, i) => (\n <li key={`${g.text}-${i}`} className={g.scoredByClub ? 'ss-w-fandash-postmatch-goal ss-w-fandash-postmatch-goal--club' : 'ss-w-fandash-postmatch-goal'}>\n <span className=\"ss-w-fandash-postmatch-goal-ball\" />\n <span>{g.text}</span>\n </li>\n ))}\n </ul>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchStatsCard as PostMatchStatsCardData } from '@sensiblestats/widget-sdk'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width. Mirrors LiveStatsCard's splitWidths.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n const total = homeNum + awayNum\n if (total <= 0) return { home: '50%', away: '50%' }\n const homePct = Math.round((homeNum / total) * 1000) / 10\n return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function PostMatchStatsCard({ card, onTap }: {\n card: PostMatchStatsCardData\n onTap: (card: PostMatchStatsCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-stats\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-stat-rows\">\n {data.rows.map((r, i) => {\n // Row values are club-first, but the result card above renders home-left/away-right, so\n // orient by venue: the home team's value on the left, the away team's on the right. When\n // the club is the away side, that means the club's value is the RIGHT column.\n const leftValue = data.clubIsHome ? r.clubValue : r.oppValue\n const rightValue = data.clubIsHome ? r.oppValue : r.clubValue\n const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n const { home, away } = splitWidths(homeNum, awayNum)\n return (\n <div key={`${r.label}-${i}`} className=\"ss-w-fandash-postmatch-stat\">\n <div className=\"ss-w-fandash-postmatch-stat-row\">\n <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--home\">{leftValue}</span>\n <span className=\"ss-w-fandash-postmatch-stat-label\">{r.label}</span>\n <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--away\">{rightValue}</span>\n </div>\n <div className=\"ss-w-fandash-postmatch-stat-bar\">\n <span className=\"ss-w-fandash-postmatch-stat-bar-home\" style={{ width: home }} />\n <span className=\"ss-w-fandash-postmatch-stat-bar-away\" style={{ width: away }} />\n </div>\n </div>\n )\n })}\n </div>\n {data.rows.length > 0 ? (\n <div className=\"ss-w-fandash-postmatch-legend\">\n <span className=\"ss-w-fandash-postmatch-legend-item\">\n <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--home\" />\n {data.homeName}\n </span>\n <span className=\"ss-w-fandash-postmatch-legend-item\">\n <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--away\" />\n {data.awayName}\n </span>\n </div>\n ) : null}\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchTopPerformerCard as PostMatchTopPerformerCardData } from '@sensiblestats/widget-sdk'\n\n// First letter of the first and last word (a single-word name yields just that one letter, since\n// first === last); whitespace/empty falls back to \"?\" rather than rendering a blank avatar.\nfunction initials(playerName: string): string {\n const words = playerName.trim().split(/\\s+/).filter(Boolean)\n if (words.length === 0) return '?'\n const first = words[0]!.charAt(0)\n const last = words[words.length - 1]!.charAt(0)\n return (words.length > 1 ? `${first}${last}` : first).toUpperCase()\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard. Full mockup treatment:\n// gradient initials avatar + name + a prominent rating chip. No \"2 goals\" sub-line -- there's no\n// data for it.\nexport function PostMatchTopPerformerCard({ card, onTap }: {\n card: PostMatchTopPerformerCardData\n onTap: (card: PostMatchTopPerformerCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-performer\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-perf-row\">\n <span className=\"ss-w-fandash-postmatch-perf-avatar\" aria-hidden=\"true\">{initials(data.playerName)}</span>\n <span className=\"ss-w-fandash-postmatch-perf-name\">{data.playerName}</span>\n <span className=\"ss-w-fandash-postmatch-perf-rating\">{data.ratingLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchNextCard as PostMatchNextCardData } from '@sensiblestats/widget-sdk'\n\n// [data] card -- the upcoming fixture teaser that follows a post-match dashboard. No tap target.\n// v1 (modest): whenLabel is already a complete localized phrase composed server-side -- it\n// includes the opponent, venue and kickoff time (EN \"vs Bournemouth (H) · Sat 12 Sep · 15:00\",\n// TR \"İç sahada Bournemouth · ...\"). Rendering opponentName alongside it would duplicate the\n// opponent, so this card shows only whenLabel, dressed up with an accent rule rather than a second\n// line. The richer opponent-headline + venue chip + crest layout needs a server field split\n// (opponent vs venue vs time as separate fields) and is deferred.\nexport function PostMatchNextCard({ card }: { card: PostMatchNextCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-next\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-next-row\">\n <span className=\"ss-w-fandash-postmatch-next-when\">{data.whenLabel}</span>\n </div>\n </div>\n )\n}\n","import type { RestingNextCard as RestingNextCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see PostMatchGoalsCard/FixtureCard).\nexport function RestingNextCard({ card, onTap }: {\n card: RestingNextCardData\n onTap: (card: RestingNextCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-next\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-next-row\">\n <span className=\"ss-w-fandash-resting-next-when\">{data.whenLabel}</span>\n {data.competition ? <span className=\"ss-w-fandash-resting-next-competition\">{data.competition}</span> : null}\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingStandingsCard as RestingStandingsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingStandingsCard({ card, onTap }: {\n card: RestingStandingsCardData\n onTap: (card: RestingStandingsCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-standings\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-standings-row\">\n <span className=\"ss-w-fandash-resting-standings-position\">{data.positionLabel}</span>\n <span className=\"ss-w-fandash-resting-standings-record\">{data.recordLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingSeasonCard as RestingSeasonCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingSeasonCard({ card, onTap }: {\n card: RestingSeasonCardData\n onTap: (card: RestingSeasonCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-season\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-season-rows\">\n {data.scorerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.scorerLabel}</span> : null}\n {data.playerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.playerLabel}</span> : null}\n <span className=\"ss-w-fandash-resting-season-row\">{data.tallyLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingFormCard as RestingFormCardData } from '@sensiblestats/widget-sdk'\n\nfunction resultClass(result: string): string {\n const upper = result.toUpperCase()\n if (upper === 'W') return 'ss-w-fandash-form-pill--win'\n if (upper === 'L') return 'ss-w-fandash-form-pill--loss'\n return 'ss-w-fandash-form-pill--draw'\n}\n\n// [data] card -- recent form as one styled W/D/L pill per letter (same pill classes as the\n// fixture card's last-five strip). No tap target.\nexport function RestingFormCard({ card }: { card: RestingFormCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-resting-form\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <span className=\"ss-w-fandash-form\">\n {data.letters.map((r, i) => (\n <span key={`${r}-${i}`} className={`ss-w-fandash-form-pill ${resultClass(r)}`}>{r}</span>\n ))}\n </span>\n </div>\n )\n}\n","import { useRef, useState } from 'react'\nimport type { LiveScoreCard as LiveScoreCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport { useLiveClock } from '../../useLiveClock'\n\nfunction initials(name: string): string {\n return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a coloured initials chip -- the design\n// wants the chip whenever the crest is missing OR fails to load, which a background-image span\n// can't detect on its own.\nfunction LiveCrest({ url, name, side }: { url?: string | null; name: string; side: 'home' | 'away' }): JSX.Element {\n const [failed, setFailed] = useState(false)\n const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return (\n <span className={`${cls} ss-w-fandash-live-crest--fallback`} aria-hidden=\"true\">\n {initials(name)}\n </span>\n )\n}\n\n// Renders \"Salah 6', Núñez 9'\" from the goal events the parent filtered out of the live timeline,\n// oldest first. Events with no player name are dropped rather than rendered blank; if nothing is\n// left, the scorers line is omitted entirely.\nfunction scorersLine(goalEvents: LiveEventLine[] | undefined): string | null {\n if (!goalEvents || goalEvents.length === 0) return null\n // Defensive: only ever render actual goals, even if a caller passes an unfiltered event list.\n const named = goalEvents.filter((e) => e.type === 'goal' && e.player)\n if (named.length === 0) return null\n return named\n .slice()\n .sort((a, b) => a.minute - b.minute)\n .map((e) => `${e.player} ${e.minuteLabel}`)\n .join(', ')\n}\n\n// [data] card -- the in-play scoreboard. No tap target: the live score itself is the payload,\n// and the timeline/stats cards below carry the rest of the in-play picture.\nexport function LiveScoreCard({\n card,\n goalEvents,\n}: {\n card: LiveScoreCardData\n goalEvents?: LiveEventLine[]\n}): JSX.Element {\n const { data } = card\n\n // The reducer replaces the card object on every ~60s poll, so seeding the live-clock hook with\n // `Date.now()` on every render would restart its elapsed-time math each time and the minute\n // would never tick between polls. Reseed only when the server minute or score actually changes.\n const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`\n const seedRef = useRef<{ key: string; receivedAtMs: number } | null>(null)\n if (!seedRef.current || seedRef.current.key !== seedKey) {\n seedRef.current = { key: seedKey, receivedAtMs: Date.now() }\n }\n\n const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs)\n const minuteSuffix = data.minuteLabel.replace(/^\\d+/, '')\n const scorers = scorersLine(goalEvents)\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-score\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-top\">\n <span className=\"ss-w-fandash-live-pill\">\n <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n {data.statusLabel}\n </span>\n <span className=\"ss-w-fandash-live-minute\">{`${displayMinute}${minuteSuffix}`}</span>\n {data.competition ? <span className=\"ss-w-fandash-live-competition\">{data.competition}</span> : null}\n </div>\n <div className=\"ss-w-fandash-live-main\">\n <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--home\">\n <LiveCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n <span className=\"ss-w-fandash-live-team-name\">{data.homeName}</span>\n </div>\n <div className=\"ss-w-fandash-live-score-main\">\n <span className=\"ss-w-fandash-live-score-value\">{data.homeScore}</span>\n <span className=\"ss-w-fandash-live-score-sep\">–</span>\n <span className=\"ss-w-fandash-live-score-value\">{data.awayScore}</span>\n </div>\n <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--away\">\n <LiveCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n <span className=\"ss-w-fandash-live-team-name\">{data.awayName}</span>\n </div>\n </div>\n {scorers ? (\n <div className=\"ss-w-fandash-live-scorers\">\n <span className=\"ss-w-fandash-live-scorers-icon\" aria-hidden=\"true\">\n ⚽\n </span>\n {scorers}\n </div>\n ) : null}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst TICK_MS = 60_000\n// Generous stoppage-time headroom. The server clamps 2H to 105; if a live poll never\n// delivers a \"Finished\" transition (resolver drops the match before that lands), a stuck\n// clockRunning:true must hold here instead of climbing forever.\nconst MAX_LIVE_TICK_MINUTES = 15\n\nfunction computeDisplayMinute(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n if (!clockRunning) return minute\n const elapsedMinutes = Math.floor((Date.now() - receivedAtMs) / TICK_MS)\n return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES)\n}\n\n// Ticks a live match minute forward once per real minute between server polls, so the\n// clock doesn't look frozen during the 60s gap. Reseeds immediately whenever `minute` or\n// `receivedAtMs` changes (a fresh poll), rather than waiting for the next interval tick.\nexport function useLiveClock(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n const [displayMinute, setDisplayMinute] = useState(() =>\n computeDisplayMinute(minute, clockRunning, receivedAtMs),\n )\n\n useEffect(() => {\n setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n\n if (!clockRunning) return\n\n const id = window.setInterval(() => {\n setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n }, TICK_MS)\n\n return () => window.clearInterval(id)\n }, [minute, clockRunning, receivedAtMs])\n\n return displayMinute\n}\n","import { useState } from 'react'\nimport type { LiveTimelineCard as LiveTimelineCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nconst SHOWN = 3\n\n// Per-type icon: a ball mark for goals, a coloured card rectangle for yellow/red, up/down\n// arrows for a substitution. An unrecognised type (forward-compat with the server's union)\n// renders a neutral dot rather than nothing, so a new event type never looks broken.\nfunction EventIcon({ type }: { type: LiveEventLine['type'] }): JSX.Element {\n if (type === 'goal') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico ss-w-fandash-live-tl-ico--goal\" aria-hidden=\"true\">\n <span className=\"ss-w-fandash-live-tl-ball\" />\n </span>\n )\n }\n if (type === 'yellow' || type === 'red') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n <span className={`ss-w-fandash-live-tl-card ss-w-fandash-live-tl-card--${type}`} />\n </span>\n )\n }\n if (type === 'sub') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n <span className=\"ss-w-fandash-live-tl-subarrows\">⇅</span>\n </span>\n )\n }\n return <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\"><span className=\"ss-w-fandash-live-tl-dot\" /></span>\n}\n\n// Sub events name both players; the \"for {playerOff}\" half only renders when the server sent\n// it, and everything falls back to the server's plain text if a name field is missing.\nfunction EventLabel({ e }: { e: LiveEventLine }): JSX.Element {\n if (e.type === 'sub') {\n return (\n <span className=\"ss-w-fandash-live-tl-who\">\n {e.player ?? e.text}\n {e.playerOff ? <span className=\"ss-w-fandash-live-tl-off\"> for {e.playerOff}</span> : null}\n </span>\n )\n }\n return <span className=\"ss-w-fandash-live-tl-who\">{e.player ?? e.text}</span>\n}\n\nfunction EventRow({ e }: { e: LiveEventLine }): JSX.Element {\n const cls = [\n 'ss-w-fandash-live-tl-ev',\n e.side === 'home' ? 'ss-w-fandash-live-tl-ev--home' : 'ss-w-fandash-live-tl-ev--away',\n e.type === 'goal' ? 'ss-w-fandash-live-tl-ev--goal' : '',\n ]\n .filter(Boolean)\n .join(' ')\n return (\n <div className={cls}>\n <span className=\"ss-w-fandash-live-tl-txt\">\n <EventLabel e={e} />\n <EventIcon type={e.type} />\n </span>\n <span className=\"ss-w-fandash-live-tl-badge\">{e.minuteLabel}</span>\n </div>\n )\n}\n\n// [data] card -- the in-play event feed as a compact two-sided timeline down a centre spine:\n// each club's events sit on its own side, most-recent 3 shown with a \"See more\" toggle for the\n// rest. No tap target.\nexport function LiveTimelineCard({ card, ui }: { card: LiveTimelineCardData; ui?: UiConfig }): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n const events = card.data.events\n if (!events || events.length === 0) return null\n\n const sorted = [...events].sort((a, b) => b.minute - a.minute)\n const rest = sorted.length - SHOWN\n const shown = expanded ? sorted : sorted.slice(0, SHOWN)\n\n const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n const showLess = ui?.showLess ?? 'Show less'\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-timeline\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-tl\">\n {shown.map((e, i) => (\n <EventRow key={`${e.minute}-${e.side}-${e.type}-${i}`} e={e} />\n ))}\n </div>\n {rest > 0 ? (\n <button\n type=\"button\"\n className=\"ss-w-fandash-live-tl-more\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? showLess : showMore(rest)}\n </button>\n ) : null}\n </div>\n )\n}\n","import { useId } from 'react'\nimport type { LiveStatsData } from '@sensiblestats/widget-sdk'\n\n// widget-sdk's events.ts defines `MomentumPoint` but its barrel (index.ts) never re-exports it on\n// its own -- only as the element type of `LiveStatsData.momentum`. Indexing off that field avoids\n// widening this task's scope to a widget-sdk barrel edit for a type alias.\ntype MomentumPoint = LiveStatsData['momentum'][number]\n\nconst WIDTH = 270\nconst HEIGHT = 56\nconst BASELINE = HEIGHT / 2 // mid-height, matches the mockup's BASE=28 for H=56\nconst SCALE = 0.26 // value ±100 -> ±26px around the baseline, same as the mockup\n\nfunction buildPaths(\n points: MomentumPoint[],\n): { area: string; line: string; lastLeftPct: number; lastTopPx: number } {\n const lastIndex = points.length - 1\n const px = (i: number): number => (lastIndex === 0 ? 0 : (i / lastIndex) * WIDTH)\n const py = (v: number): number => BASELINE - v * SCALE\n const linePts = points.map((p, i) => `${px(i).toFixed(1)},${py(p.value).toFixed(1)}`)\n const area = `M0,${BASELINE} L${linePts.join(' L')} L${WIDTH},${BASELINE} Z`\n const line = `M${linePts.join(' L')}`\n // The caller (MomentumWave) already returns null for an empty series, so lastIndex is always a\n // valid index here -- the `?? 0` only satisfies noUncheckedIndexedAccess, it never triggers.\n const lastValue = points[lastIndex]?.value ?? 0\n // The marker is an HTML overlay positioned by PERCENT of width (so it survives the SVG's\n // preserveAspectRatio=\"none\" scaling undistorted) -- always 0 for a single point, always 100 for\n // the last of more than one, matching px()'s own 0..WIDTH mapping.\n const lastLeftPct = lastIndex === 0 ? 0 : 100\n return { area, line, lastLeftPct, lastTopPx: py(lastValue) }\n}\n\n// [data] momentum wave -- no tap target. `value` is club-positive (clubPressure - oppPressure),\n// but colour follows VENUE, not club, to stay consistent with the score/timeline cards: the club's\n// own colour is --ss-w-home when `clubIsHome`, --ss-w-away otherwise. So a club-positive swing (up,\n// above the baseline) is filled with the club's venue colour, and an opponent-positive swing (down)\n// with the opponent's venue colour -- top/bottom are NOT fixed to home/away, they flip with\n// `clubIsHome` so the same team is always the same colour across every live card.\nexport function MomentumWave({\n points,\n caption,\n clubIsHome,\n}: {\n points: MomentumPoint[]\n caption?: string | null\n clubIsHome: boolean\n}): JSX.Element | null {\n if (points.length === 0) return null\n\n const { area, line, lastLeftPct, lastTopPx } = buildPaths(points)\n const clipId = useId()\n const topClipId = `${clipId}-top`\n const bottomClipId = `${clipId}-bottom`\n const topClass = clubIsHome ? 'ss-w-fandash-live-mom-home' : 'ss-w-fandash-live-mom-away'\n const bottomClass = clubIsHome ? 'ss-w-fandash-live-mom-away' : 'ss-w-fandash-live-mom-home'\n\n return (\n <div className=\"ss-w-fandash-live-mom\">\n {caption ? <span className=\"ss-w-fandash-live-mom-caption\">{caption}</span> : null}\n <div className=\"ss-w-fandash-live-mom-plot\">\n <svg\n className=\"ss-w-fandash-live-mom-svg\"\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n preserveAspectRatio=\"none\"\n role=\"img\"\n aria-label={caption ?? 'Momentum'}\n >\n <defs>\n <clipPath id={topClipId}>\n <rect x={0} y={0} width={WIDTH} height={BASELINE} />\n </clipPath>\n <clipPath id={bottomClipId}>\n <rect x={0} y={BASELINE} width={WIDTH} height={HEIGHT - BASELINE} />\n </clipPath>\n </defs>\n <path d={area} className={topClass} clipPath={`url(#${topClipId})`} />\n <path d={area} className={bottomClass} clipPath={`url(#${bottomClipId})`} />\n <line x1={0} y1={BASELINE} x2={WIDTH} y2={BASELINE} className=\"ss-w-fandash-live-mom-base\" />\n <path d={line} className=\"ss-w-fandash-live-mom-line\" vectorEffect=\"non-scaling-stroke\" />\n </svg>\n {/* HTML overlay dot, not an SVG <circle> -- the SVG's preserveAspectRatio=\"none\" stretches\n non-uniform scaling into an oval, and at x=WIDTH half of a circle hangs off the edge.\n An HTML element can't be deformed by the SVG's viewBox scaling, and clamp() keeps it\n fully inside the plot at both ends. */}\n <span\n className=\"ss-w-fandash-live-mom-now\"\n style={{ left: `clamp(4px, ${lastLeftPct}%, calc(100% - 4px))`, top: `${lastTopPx}px` }}\n aria-hidden=\"true\"\n />\n </div>\n </div>\n )\n}\n","import type { LiveStatsCard as LiveStatsCardData } from '@sensiblestats/widget-sdk'\nimport { MomentumWave } from './MomentumWave'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width, since a stat can legitimately be 0-0 early in a match.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n const total = homeNum + awayNum\n if (total <= 0) return { home: '50%', away: '50%' }\n const homePct = Math.round((homeNum / total) * 1000) / 10\n return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [data] card -- in-play match stats, home value / stat label / away value per row, each backed\n// by a home/away split bar, plus an optional momentum wave (or its text fallback). No tap target.\n//\n// LiveStatRow itself only carries clubNum/oppNum (club vs opponent), but LiveStatsData now also\n// carries `clubIsHome`/`homeName`/`awayName` (mirroring the venue signal LiveScoreCard already\n// has and the ClubIsHome pattern on RestingNextData/PostMatchNextData) -- so this card orients by\n// VENUE, not by club, to stay colour-consistent with the score and timeline cards: home is always\n// --ss-w-home on the left, away is always --ss-w-away on the right, and clubNum/oppNum are placed\n// on whichever side `clubIsHome` says the club actually occupies this match.\nexport function LiveStatsCard({ card }: { card: LiveStatsCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-stats\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-stat-rows\">\n {data.rows.map((r, i) => {\n const homeValue = data.clubIsHome ? r.clubValue : r.oppValue\n const awayValue = data.clubIsHome ? r.oppValue : r.clubValue\n const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n const { home, away } = splitWidths(homeNum, awayNum)\n return (\n <div key={`${r.label}-${i}`} className=\"ss-w-fandash-live-stat\">\n <div className=\"ss-w-fandash-live-stat-row\">\n <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--home\">{homeValue}</span>\n <span className=\"ss-w-fandash-live-stat-label\">{r.label}</span>\n <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--away\">{awayValue}</span>\n </div>\n <div className=\"ss-w-fandash-live-bar\">\n <span className=\"ss-w-fandash-live-bar-home\" style={{ width: home }} />\n <span className=\"ss-w-fandash-live-bar-away\" style={{ width: away }} />\n </div>\n </div>\n )\n })}\n </div>\n {data.momentum.length > 0 ? (\n <MomentumWave points={data.momentum} caption={data.momentumLabel} clubIsHome={data.clubIsHome} />\n ) : data.momentumLabel ? (\n <span className=\"ss-w-fandash-live-momentum\">{data.momentumLabel}</span>\n ) : null}\n {data.rows.length > 0 ? (\n <div className=\"ss-w-fandash-live-legend\">\n <span className=\"ss-w-fandash-live-legend-item\">\n <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--home\" />\n {data.homeName}\n </span>\n <span className=\"ss-w-fandash-live-legend-item\">\n <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--away\" />\n {data.awayName}\n </span>\n </div>\n ) : null}\n </div>\n )\n}\n","import type {\n ClubFanDashboardCard,\n ClubFanDashboardPayload,\n CongestedWeekCard as CongestedWeekCardData,\n LiveEventLine,\n LiveTimelineCard as LiveTimelineCardData,\n PostMatchGoalsCard as PostMatchGoalsCardData,\n PostMatchStatsCard as PostMatchStatsCardData,\n PostMatchTopPerformerCard as PostMatchTopPerformerCardData,\n RestingNextCard as RestingNextCardData,\n RestingStandingsCard as RestingStandingsCardData,\n RestingSeasonCard as RestingSeasonCardData,\n} from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { FixtureCard } from './FixtureCard'\nimport { CountdownCard } from './CountdownCard'\nimport { InjuriesCard } from './InjuriesCard'\nimport { ReasonToBetCard } from './ReasonToBetCard'\nimport { WhereToWatchCard } from './WhereToWatchCard'\nimport { CongestedWeekCard } from './CongestedWeekCard'\nimport { TransfersCard } from './TransfersCard'\nimport { LinksCard } from './LinksCard'\nimport { PostMatchResultCard } from './PostMatchResultCard'\nimport { PostMatchGoalsCard } from './PostMatchGoalsCard'\nimport { PostMatchStatsCard } from './PostMatchStatsCard'\nimport { PostMatchTopPerformerCard } from './PostMatchTopPerformerCard'\nimport { PostMatchNextCard } from './PostMatchNextCard'\nimport { RestingNextCard } from './RestingNextCard'\nimport { RestingStandingsCard } from './RestingStandingsCard'\nimport { RestingSeasonCard } from './RestingSeasonCard'\nimport { RestingFormCard } from './RestingFormCard'\nimport { LiveScoreCard } from './LiveScoreCard'\nimport { LiveTimelineCard } from './LiveTimelineCard'\nimport { LiveStatsCard } from './LiveStatsCard'\n\n// The [prefill] card types (see ClubFanDashboardPayload.cs) -- tapping any of them sends its\n// actionLabel as a follow-up message, carrying the opaque actionRef so the server resolves the\n// pre-issued binding. Every other card type is a [data] card with no tap target. FixtureCard is a\n// DataCard now (u319): its tap moved to the greeting chips, so it's not in this union any more.\nexport type ClubFanDashboardTapCard =\n | CongestedWeekCardData\n | PostMatchGoalsCardData\n | PostMatchStatsCardData\n | PostMatchTopPerformerCardData\n | RestingNextCardData\n | RestingStandingsCardData\n | RestingSeasonCardData\n\nexport function ClubFanDashboard({ dashboard, onTap, ui }: {\n dashboard: ClubFanDashboardPayload\n onTap: (card: ClubFanDashboardTapCard) => void\n ui?: UiConfig\n}): JSX.Element {\n // The clock leads the dashboard, so any countdown card is floated to the top; the rest keep\n // their server order.\n const orderedCards = [\n ...dashboard.cards.filter((c) => c.cardType === 'countdown'),\n ...dashboard.cards.filter((c) => c.cardType !== 'countdown'),\n ]\n // The score card's scorers line is derived from the sibling timeline card's goal events, so it\n // needs pulling out here where the full card list is in scope. Null-safe: no timeline card (or\n // no goals in it) means no scorers line, not a crash.\n const timelineCard = dashboard.cards.find(\n (c): c is LiveTimelineCardData => c.cardType === 'liveTimeline',\n )\n const goalEvents = timelineCard?.data.events.filter((e) => e.type === 'goal')\n return (\n <div className=\"ss-w-fandash\">\n {dashboard.greeting ? <span className={dashboard.greetingIsLead ? 'ss-w-fandash-greeting ss-w-fandash-greeting--lead' : 'ss-w-fandash-greeting'}>{dashboard.greeting}</span> : null}\n <div className=\"ss-w-fandash-cards\">\n {orderedCards.map((card, i) => (\n <FanDashboardCard key={`${card.cardType}-${i}`} card={card} onTap={onTap} ui={ui} goalEvents={goalEvents} />\n ))}\n </div>\n </div>\n )\n}\n\nfunction FanDashboardCard({ card, onTap, ui, goalEvents }: {\n card: ClubFanDashboardCard\n onTap: (card: ClubFanDashboardTapCard) => void\n ui?: UiConfig\n goalEvents?: LiveEventLine[]\n}): JSX.Element | null {\n switch (card.cardType) {\n case 'fixture':\n return <FixtureCard card={card} />\n case 'countdown':\n return <CountdownCard card={card} />\n case 'injuries':\n return <InjuriesCard card={card} ui={ui} />\n case 'reasonToBet':\n return <ReasonToBetCard card={card} />\n case 'whereToWatch':\n return <WhereToWatchCard card={card} />\n case 'congestedWeek':\n return <CongestedWeekCard card={card} onTap={onTap} />\n case 'transfers':\n return <TransfersCard card={card} />\n case 'links':\n return <LinksCard card={card} />\n case 'postMatchResult':\n return <PostMatchResultCard card={card} />\n case 'postMatchGoals':\n return <PostMatchGoalsCard card={card} onTap={onTap} />\n case 'postMatchStats':\n return <PostMatchStatsCard card={card} onTap={onTap} />\n case 'postMatchTopPerformer':\n return <PostMatchTopPerformerCard card={card} onTap={onTap} />\n case 'postMatchNext':\n return <PostMatchNextCard card={card} />\n case 'restingNext':\n return <RestingNextCard card={card} onTap={onTap} />\n case 'restingStandings':\n return <RestingStandingsCard card={card} onTap={onTap} />\n case 'restingSeason':\n return <RestingSeasonCard card={card} onTap={onTap} />\n case 'restingForm':\n return <RestingFormCard card={card} />\n case 'liveScore':\n return <LiveScoreCard card={card} goalEvents={goalEvents} />\n case 'liveTimeline':\n return <LiveTimelineCard card={card} ui={ui} />\n case 'liveStats':\n return <LiveStatsCard card={card} />\n default:\n // The server's cardType is a closed set, but a mismatched deploy could still send an\n // unrecognised discriminator -- render nothing for it rather than crash the whole turn.\n return null\n }\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport type { Message } from '../reducer'\nimport type { ActionVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { Markdown } from './Markdown'\nimport { EntityCardList } from './EntityCardList'\nimport { BettingInsightList } from './BettingInsightList'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { CompactOddsList } from './CompactOddsList'\nimport { toCompactList } from '../compactList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { ActionButtons } from './ActionButtons'\nimport { GreetingDashboard } from './dashboard/GreetingDashboard'\nimport { ClubFanDashboard, type ClubFanDashboardTapCard } from './dashboard/ClubFanDashboard'\n\nexport function ChatMessage({ message, disabled, onAct, onTap, ui, slip, monitor }: {\n message: Message\n disabled: boolean\n onAct: (a: ActionVM) => void\n onTap: (tile: GreetingDashboardTile, index: number) => void\n ui?: UiConfig\n slip: SlipHandlerProps\n monitor?: LiveMonitorController\n}): JSX.Element {\n if (message.role === 'user') {\n return <div className=\"ss-w-msg ss-w-user\" data-msg-id={message.id}><div className=\"ss-w-bubble\">{message.text}</div></div>\n }\n // A [prefill] club-fan-dashboard card tap reuses the same send path as an action button --\n // actionLabel becomes both the message and the display text, and the opaque actionRef rides\n // along so the server resolves the card's pre-issued action binding rather than re-planning\n // a prose command -- rather than threading a second tap handler through MessageList.\n const onFanDashboardTap = (card: ClubFanDashboardTapCard): void => {\n onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || '' })\n }\n const compact = toCompactList(message.marketOdds)\n return (\n <div className=\"ss-w-msg ss-w-bot\" data-msg-id={message.id}>\n {message.text && !message.greetingDashboard && !message.clubFanDashboard ? <Markdown text={message.text} /> : null}\n {message.greetingDashboard && !message.clubFanDashboard ? <GreetingDashboard dashboard={message.greetingDashboard} onTap={onTap} oddsLabel={ui?.oddsLabel} /> : null}\n {message.clubFanDashboard ? <ClubFanDashboard dashboard={message.clubFanDashboard} onTap={onFanDashboardTap} ui={ui} /> : null}\n <EntityCardList cards={message.cards} disabled={disabled} showLessLabel={ui?.showLess} showMoreLabel={ui?.showMore} />\n <BettingInsightList insights={message.insights} ui={ui} slip={slip} monitor={monitor} />\n {compact\n ? <CompactOddsList list={compact} ui={ui} slip={slip} monitor={monitor} />\n : <MarketOddsCardList cards={message.marketOdds} ui={ui} slip={slip} monitor={monitor} />}\n <OddsMovementCardList cards={message.oddsMovement} ui={ui} monitor={monitor} />\n <ActionButtons actions={message.actions} loading={false} disabled={disabled} onAct={onAct} />\n </div>\n )\n}\n","import type { ChipVM } from '../model'\n\nexport function IntentChips({ chips, onPick }: { chips: ChipVM[]; onPick: (text: string) => void }): JSX.Element | null {\n if (chips.length === 0) return null\n return (\n <div className=\"ss-w-chips\">\n {chips.map((c, i) => (\n <button key={`${c.text}-${i}`} type=\"button\" className=\"ss-w-chip\" onClick={() => onPick(c.text)}>{c.text}</button>\n ))}\n </div>\n )\n}\n","// Distance (px) from the bottom within which the list is still considered\n// \"pinned\" — small enough that a user reading earlier content isn't counted\n// as pinned, large enough to absorb sub-pixel/rounding drift while streaming.\nexport const PIN_THRESHOLD = 48\n\n/**\n * True when the scroll container is at (or within PIN_THRESHOLD of) its bottom.\n * Used to decide whether new content should auto-scroll: we follow the stream\n * only while the user is already at the bottom, so late arrivals (e.g. suggested\n * actions) never yank a user who has scrolled up to read.\n */\nexport function isPinnedToBottom(el: Pick<HTMLElement, 'scrollHeight' | 'scrollTop' | 'clientHeight'>, threshold = PIN_THRESHOLD): boolean {\n return el.scrollHeight - el.scrollTop - el.clientHeight <= threshold\n}\n","import { useState, type KeyboardEvent } from 'react'\nimport { SendIcon } from './Icons'\n\nexport function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = 'Stop response', sendLabel = 'Send message' }: { placeholder: string; streaming: boolean; onSend: (t: string) => void; onStop: () => void; stopLabel?: string; sendLabel?: string }): JSX.Element {\n const [value, setValue] = useState('')\n const submit = () => { const t = value.trim(); if (!t) return; onSend(t); setValue('') }\n const onKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit() }\n }\n return (\n <div className=\"ss-w-input\">\n <textarea className=\"ss-w-textarea\" rows={1} placeholder={placeholder} value={value} disabled={streaming} onChange={(e) => setValue(e.target.value)} onKeyDown={onKeyDown} />\n {streaming ? (\n <button type=\"button\" className=\"ss-w-send ss-w-stop\" aria-label={stopLabel} onClick={onStop}><span className=\"ss-w-stop-glyph\" /></button>\n ) : (\n <button type=\"button\" className=\"ss-w-send\" aria-label={sendLabel} onClick={submit}><SendIcon /></button>\n )}\n </div>\n )\n}\n","import type { LiveMonitorController, MonitorTab } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\n\nexport function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday, gamesEnabled }: {\n monitor: LiveMonitorController\n ui: UiConfig\n matchCount: number\n oddsCount: number\n /** Live match count. NEVER the fixture count -- a Saturday would badge 41. */\n todayCount: number\n hasToday: boolean\n /** Enabled when getGames resolves non-null; false for betting operators (404 sentinel). */\n gamesEnabled?: boolean\n}): JSX.Element | null {\n const tabs: { tab: MonitorTab; label: string; count: number; dot: boolean }[] = [\n { tab: 'chat', label: ui.tabChat, count: 0, dot: monitor.chatDot },\n ...(hasToday ? [{ tab: 'today' as MonitorTab, label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : []),\n ...(matchCount > 0 ? [{ tab: 'following' as MonitorTab, label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : []),\n ...(oddsCount > 0 ? [{ tab: 'odds' as MonitorTab, label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []),\n ...(gamesEnabled ? [\n { tab: 'games' as MonitorTab, label: ui.tabGames, count: 0, dot: false },\n { tab: 'leaderboard' as MonitorTab, label: ui.tabLeaderboard, count: 0, dot: false },\n ] : []),\n ]\n\n // A lone Chat tab is chrome that selects nothing -- the strip stays hidden, as it does today\n // when nothing is pinned.\n if (tabs.length < 2) return null\n\n return (\n <div className=\"ss-w-tabs\" role=\"tablist\">\n {tabs.map(({ tab, label, count, dot }) => {\n const active = monitor.activeTab === tab\n return (\n <button\n key={tab}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n data-on={active ? '' : undefined}\n className=\"ss-w-tab\"\n onClick={() => monitor.setActiveTab(tab)}\n >\n {label}\n {count > 0 && <span className=\"ss-w-tab-count\">{count}</span>}\n {dot && !active && <span className=\"ss-w-tab-dot\" aria-hidden=\"true\" />}\n </button>\n )\n })}\n </div>\n )\n}\n","import type { LiveMonitorMatch } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { toMarketOddsVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\n\nexport function MarketAccordion({ match, monitor, ui, slip }: {\n match: LiveMonitorMatch\n monitor: LiveMonitorController\n ui: UiConfig\n slip: SlipHandlerProps\n}): JSX.Element | null {\n const slipState = useSlipState()\n const markets = match.availableMarkets ?? []\n if (markets.length === 0) return null\n const open = monitor.openMarket[match.matchId] ?? null\n\n return (\n <div className=\"ss-w-acc\">\n {markets.map((m) => {\n // A suspended market has no servable card: the odds lookup drops every suspended/stopped\n // row, so /live-monitor/market answers 404 MarketNotPriced and the panel lands on the\n // tap-to-retry affordance, which can never succeed. Don't offer the tap. `&& !m.suspended`\n // also collapses a market that suspends WHILE open, instead of leaving stale rows up.\n const isOpen = open === m.marketDeveloperName && !m.suspended\n const key = `${match.matchId}:${m.marketDeveloperName}`\n const entry = monitor.marketOdds[key]\n return (\n <div key={m.marketDeveloperName} className={isOpen ? 'ss-w-acc-row ss-w-acc-row-open' : 'ss-w-acc-row'}>\n <div className=\"ss-w-acc-head\">\n <button\n type=\"button\"\n className={m.suspended ? 'ss-w-acc-toggle ss-w-acc-toggle--susp' : 'ss-w-acc-toggle'}\n aria-expanded={isOpen}\n disabled={m.suspended}\n onClick={() => monitor.toggleMarket(match.matchId, m.marketDeveloperName)}\n >\n <span className=\"ss-w-acc-chevron\">{m.suspended ? '' : isOpen ? '▾' : '▸'}</span>\n <span className=\"ss-w-acc-label\">{m.marketLabel}</span>\n {m.hasInsight && <span className=\"ss-w-acc-badge\">★</span>}\n {m.suspended && <span className=\"ss-w-acc-susp\">{ui.accordionSuspended}</span>}\n </button>\n </div>\n {isOpen && (\n <div className=\"ss-w-acc-panel\">\n {entry?.error && (\n <div\n className=\"ss-w-acc-retry\"\n onClick={() => monitor.retryMarket(match.matchId, m.marketDeveloperName)}\n >\n {ui.accordionRetry}\n </div>\n )}\n {entry?.block?.insight?.text && (\n <div className=\"ss-w-acc-insight\">{entry.block.insight.text}</div>\n )}\n {entry?.block?.card && (\n <MarketOddsCardList\n cards={[toMarketOddsVM(entry.block.card)]}\n ui={ui}\n slip={slip}\n monitor={monitor}\n inSlipIds={slipState?.added}\n hideHeader\n />\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { ChatGrounding, LiveMonitorFact } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\n\nexport type AskHandler = (text: string, grounding: ChatGrounding) => void\n\n// Spec §6: the newest fact under the score, one at a time; earlier ones expand below it. A fact\n// with no market (unpriced, suspended, or a record) renders without the chip row at all.\nexport function LiveFactBlock({ facts, matchId, ui, slip, onAsk }: {\n facts: LiveMonitorFact[]\n matchId: number\n ui: UiConfig\n slip: SlipHandlerProps\n onAsk?: AskHandler\n}): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n const [current, ...earlier] = facts\n if (!current) return null\n const m = current.market\n return (\n <section className=\"ss-w-fact\" aria-label={ui.liveFactLabel}>\n <div className=\"ss-w-fact-k\">\n <span>{ui.liveFactLabel}</span>\n <span className=\"ss-w-fact-min\">· {current.minuteLabel}</span>\n <span className=\"ss-w-fact-subj\">{current.subjectLabel}</span>\n </div>\n <p className=\"ss-w-fact-text\">{current.text}</p>\n <div className=\"ss-w-fact-basis\">{current.basis}</div>\n {m && !m.isSuspended && (\n <div className=\"ss-w-fact-mkt\">\n <span>{m.marketLabel} · {m.selectionLabel}</span>\n <span className=\"ss-w-mon-stat-mkt-right\">\n {typeof m.price === 'number' && <span className=\"ss-w-mon-price\">{m.price.toFixed(2)}</span>}\n <SlipButton\n selection={chipSelection(m, matchId, slip.conversationId)}\n shownOdds={typeof m.price === 'number' ? m.price.toFixed(2) : ''}\n marketDeveloperName={m.marketDeveloperName}\n selectionLabel={m.selectionLabel}\n slip={slip}\n ui={ui}\n />\n </span>\n </div>\n )}\n {expanded && earlier.length > 0 && (\n <ul className=\"ss-w-fact-hist\">\n {earlier.map((f) => (\n <li key={f.id}>\n <span className=\"ss-w-fact-hmin\">{f.minuteLabel}</span>\n <div>\n <p className=\"ss-w-fact-htext\">{f.text}</p>\n <div className=\"ss-w-fact-basis\">{f.basis}</div>\n </div>\n </li>\n ))}\n </ul>\n )}\n <div className=\"ss-w-fact-foot\">\n {onAsk && (\n <button type=\"button\" className=\"ss-w-fact-link\"\n onClick={() => onAsk(current.text, { kind: 'liveFact', matchId, subject: current.text.slice(0, 400) })}>\n {ui.liveFactAsk}\n </button>\n )}\n {earlier.length > 0 && (\n <button type=\"button\" className=\"ss-w-fact-link ss-w-fact-link--muted\" aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}>\n {expanded ? ui.liveFactHideEarlier : ui.liveFactEarlier(earlier.length)}\n </button>\n )}\n </div>\n </section>\n )\n}\n","import type { LiveMonitorEvent, LiveMonitorMatch, LiveMonitorStatRow, PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { MomentumWave } from './dashboard/MomentumWave'\nimport { LiveFactBlock, type AskHandler } from './LiveFactBlock'\nimport { PinToggle } from './PinToggle'\nimport { MatchLink } from './MatchLink'\n\n// A stat row's market chip promotes to the top when the user has pinned that market -- matched by\n// FIELD, never by a reconstructed pin key. LiveMonitorStatPrice carries no `line`, and its\n// selectionLabel is server-localized (TR \"2.5 Üst\" vs the stored pin's raw \"Over\"), so any key\n// string built from the chip would never equal the stored pin's key. marketDeveloperName is the\n// one field both sides always share in its raw, unlocalized form; matchOddsId is an unambiguous\n// same-selection identifier when both sides carry it.\nfunction isPromoted(row: LiveMonitorStatRow, promotedPins: readonly PinRef[]): boolean {\n const chip = row.market\n if (!chip) return false\n return promotedPins.some((pin) =>\n pin.marketDeveloperName === chip.marketDeveloperName ||\n (chip.matchOddsId != null && pin.matchOddsId === chip.matchOddsId))\n}\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface ScorerLine { player: string; label: string }\n\n// One line per scorer for a single side, in the order goals were scored, with a brace collapsed\n// onto that scorer's line (\"Powell 87', 90+6'\"). An own goal carries an \"(OG)\" marker on its\n// minute. Goals arrive already ascending from the server; grouping by name preserves that order\n// via the first appearance of each scorer.\nfunction groupScorers(goals: LiveMonitorEvent[], ownGoalLabel: string): ScorerLine[] {\n const order: string[] = []\n const minutesByPlayer = new Map<string, string[]>()\n for (const g of goals) {\n const name = g.player ?? ''\n const minute = g.ownGoal ? `${g.minuteLabel} (${ownGoalLabel})` : g.minuteLabel\n if (!minutesByPlayer.has(name)) {\n minutesByPlayer.set(name, [])\n order.push(name)\n }\n minutesByPlayer.get(name)!.push(minute)\n }\n return order.map((name) => {\n const minutes = minutesByPlayer.get(name)!.join(', ')\n return { player: name, label: name ? `${name} ${minutes}` : minutes }\n })\n}\n\nexport function MonitorMatchCard({ match, promotedPins, monitor, ui, slip, onAsk }: {\n match: LiveMonitorMatch\n /** the user's non-match pins on this match — their stat rows promote to the top strip */\n promotedPins: PinRef[]\n monitor: LiveMonitorController\n ui: UiConfig\n slip: SlipHandlerProps\n onAsk?: AskHandler\n}): JSX.Element {\n const live = match.phase === 'live'\n const goals = match.events.filter((e) => e.type === 'goal')\n const homeScorers = groupScorers(goals.filter((e) => e.side === 'home'), ui.ownGoalLabel)\n const awayScorers = groupScorers(goals.filter((e) => e.side === 'away'), ui.ownGoalLabel)\n const promotedRows = match.statRows.filter((row) => isPromoted(row, promotedPins))\n const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins))\n const orderedRows = [...promotedRows, ...otherRows]\n const kickoff = match.phase === 'preMatch' && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : undefined\n\n return (\n <div className=\"ss-w-mon\">\n <div className=\"ss-w-mon-top\">\n {live && (\n <span className=\"ss-w-fandash-live-pill\">\n <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n {ui.liveLabel}\n </span>\n )}\n {match.phase === 'fullTime' && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n {kickoff && <span className=\"ss-w-mon-pill\">{kickoff.dayLabel} · {kickoff.time}</span>}\n {live && match.minuteLabel && <span className=\"ss-w-mon-min\">{match.minuteLabel}</span>}\n {match.competitionName && <span className=\"ss-w-mon-comp\">{match.competitionName}</span>}\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n </div>\n <MatchLink\n as=\"div\"\n matchId={match.matchId}\n home={match.homeTeamName}\n away={match.awayTeamName}\n detail={match.phase !== 'preMatch' ? `${match.homeScore}–${match.awayScore}` : undefined}\n className=\"ss-w-mon-main\"\n >\n <span className=\"ss-w-mon-side\">\n <Crest kind=\"team\" url={match.homeCrestUrl ?? undefined} name={match.homeTeamName ?? undefined} />\n <span className=\"ss-w-mon-name\">{match.homeTeamName}</span>\n </span>\n {match.phase === 'preMatch' ? (\n <span className=\"ss-w-mon-vs\">vs</span>\n ) : (\n <span className=\"ss-w-mon-score\">{match.homeScore}<i>–</i>{match.awayScore}</span>\n )}\n <span className=\"ss-w-mon-side ss-w-mon-side--away\">\n <Crest kind=\"team\" url={match.awayCrestUrl ?? undefined} name={match.awayTeamName ?? undefined} />\n <span className=\"ss-w-mon-name\">{match.awayTeamName}</span>\n </span>\n </MatchLink>\n {(homeScorers.length > 0 || awayScorers.length > 0) && (\n <div className=\"ss-w-mon-scorers\">\n <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-home\">\n {homeScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n </ul>\n <span className=\"ss-w-mon-scorers-ball\" aria-hidden=\"true\">⚽</span>\n <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-away\">\n {awayScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n </ul>\n </div>\n )}\n {live && match.facts && match.facts.length > 0 && (\n <LiveFactBlock facts={match.facts} matchId={match.matchId} ui={ui} slip={slip} onAsk={onAsk} />\n )}\n <div className=\"ss-w-mon-stats\">\n {orderedRows.map((row) => {\n const total = row.homeNum + row.awayNum\n const homePct = total > 0 ? (row.homeNum / total) * 75 : 0\n const awayPct = total > 0 ? (row.awayNum / total) * 75 : 0\n const promoted = isPromoted(row, promotedPins)\n const selection = chipSelection(row.market, match.matchId, slip.conversationId)\n return (\n <div className={promoted ? 'ss-w-mon-stat ss-w-mon-pstrip' : 'ss-w-mon-stat'} key={row.label}>\n <div className=\"ss-w-mon-stat-row\">\n <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--home\">{row.homeValue}</span>\n <span className=\"ss-w-mon-stat-l\">{row.label}</span>\n <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--away\">{row.awayValue}</span>\n </div>\n <div className=\"ss-w-mon-bar\">\n <b className=\"ss-w-mon-bar-home\" style={{ width: `${homePct}%` }} />\n <i className=\"ss-w-mon-bar-away\" style={{ width: `${awayPct}%` }} />\n </div>\n {/* A suspended market drops its whole betting line -- label, price and button -- and\n the stat row keeps its bar, exactly like a row with no market at all. Showing it\n offered a price the bookmaker was not taking next to a live Add to slip whose\n only possible outcome was the slipSuspended error toast. bet365 suspends\n derivative in-play markets constantly: measured across 20 live matches, 61% of\n Goals Over/Under rows and 69% of 1st Half Goals rows were suspended against 9%\n of Fulltime Result. */}\n {row.market && !row.market.isSuspended && (\n <div className={promoted ? 'ss-w-mon-stat-mkt ss-w-mon-mkt' : 'ss-w-mon-stat-mkt'}>\n <span>{row.market.marketLabel} · {row.market.selectionLabel}</span>\n <span className=\"ss-w-mon-stat-mkt-right\">\n {typeof row.market.price === 'number' && <span className=\"ss-w-mon-price\">{row.market.price.toFixed(2)}</span>}\n <SlipButton\n selection={selection}\n shownOdds={typeof row.market.price === 'number' ? row.market.price.toFixed(2) : ''}\n marketDeveloperName={row.market.marketDeveloperName}\n selectionLabel={row.market.selectionLabel}\n slip={slip}\n ui={ui}\n />\n </span>\n </div>\n )}\n </div>\n )\n })}\n </div>\n {match.status === 'stale' && <span className=\"ss-w-mon-asof\">{ui.asOf(formatTime(match.asOfUtc))}</span>}\n {match.momentum.length > 0 && (\n <div className=\"ss-w-mon-mom\">\n {/* Label only -- no percentage split. momentumHomePct is a share of the WHOLE match's\n accumulated pressure, so it reads as a verdict on the match (\"99% - 1%\") when the\n wave beneath it is showing minute-by-minute swing. The two disagree on sight, and\n the share is the one that misleads. */}\n <span className=\"ss-w-mon-stat-l\">{ui.momentumLabel}</span>\n <MomentumWave points={match.momentum} clubIsHome={true} />\n </div>\n )}\n {match.phase === 'fullTime' && <div className=\"ss-w-mon-grace\">{ui.graceNote}</div>}\n </div>\n )\n}\n","import type { LiveMonitorMarket } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { MarketOddsRowVM, MarketOddsVM } from '../model'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { MarketAccordion } from './MarketAccordion'\nimport { MonitorMatchCard } from './MonitorMatchCard'\nimport { toMarketOddsVM, toOddsMovementVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\nimport type { AskHandler } from './LiveFactBlock'\n\n// Slim live-only strip above an Odds-tab market card. The card itself already shows the\n// competition, fixture, market, kickoff and the unpin — so this renders ONLY the match-live\n// context the card lacks (score, minute, suspended/settled, stale as-of), and nothing at all for\n// a pre-match market (avoids duplicating the card's fixture/kickoff). (u342)\nfunction OddsLiveStrip({ m, ui }: { m: LiveMonitorMarket; ui: UiConfig }): JSX.Element | null {\n const showScore = m.phase !== 'preMatch' && typeof m.homeScore === 'number'\n const stale = m.status === 'stale'\n if (!showScore && !m.minuteLabel && !(m.isSuspended && !m.isSettled) && !m.isSettled && !stale) return null\n return (\n <div className=\"ss-w-mk-live\">\n {showScore && (\n <b className=\"ss-w-mk-live-score\">{m.homeTeamName} {m.homeScore}–{m.awayScore} {m.awayTeamName}</b>\n )}\n {m.minuteLabel && <span className=\"ss-w-mon-min\">{m.minuteLabel}</span>}\n {m.isSuspended && !m.isSettled && <span className=\"ss-w-mon-susp\">{ui.suspendedLabel}</span>}\n {m.isSettled && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n {stale && (\n <span className=\"ss-w-mon-asof\">{ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }))}</span>\n )}\n </div>\n )\n}\n\nexport function MatchesPanel({ monitor, ui, slip, onAsk }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps; onAsk?: AskHandler }): JSX.Element {\n // Only EXPLICIT match pins surface here (2026-09-06 ruling: an odds pin tracks odds, a match\n // pin tracks the match -- never combined). Filtering against current pins, not just the\n // snapshot, also makes an unpin drop the card immediately.\n const matches = (monitor.snapshot?.matches ?? []).filter((m) =>\n monitor.pins.some((p) => p.kind === 'match' && p.matchId === m.matchId))\n if (matches.length === 0) return <div className=\"ss-w-mon-empty\">{ui.emptyMatchesTab}</div>\n return (\n <div className=\"ss-w-mon-list\">\n {matches.map((m) => (\n <div key={m.matchId} className=\"ss-w-mon-item\">\n <MonitorMatchCard\n match={m}\n // promotion is PER MATCH: only odds pins on THIS match promote their stat row\n promotedPins={monitor.pins.filter((p) => p.kind !== 'match' && p.matchId === m.matchId)}\n monitor={monitor}\n ui={ui}\n slip={slip}\n onAsk={onAsk}\n />\n <MarketAccordion match={m} monitor={monitor} ui={ui} slip={slip} />\n </div>\n ))}\n </div>\n )\n}\n\n// I2 (since-view movement): the badge on a pin's PRIMARY row must reflect what THIS operator's\n// client last saw (monitor.lastViewedPrices, keyed by the market snapshot's own key), never the\n// server's own previousPrice/movementDirection window -- those two clocks are unrelated. Only the\n// first main row carries this override; other rows/lines keep whatever (if anything) the server\n// sent.\nfunction withSinceViewMovement(vm: MarketOddsVM, prev: number | undefined): MarketOddsVM {\n const primary = vm.mainRows[0]\n if (prev === undefined || !primary || primary.oddsDecimal === undefined || primary.oddsDecimal === prev) return vm\n const updatedPrimary: MarketOddsRowVM = {\n ...primary,\n previousOdds: prev.toFixed(2),\n movementDirection: primary.oddsDecimal < prev ? 'shortened' : 'drifted',\n }\n return { ...vm, mainRows: [updatedPrimary, ...vm.mainRows.slice(1)] }\n}\n\nexport function OddsPanel({ monitor, ui, slip }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const slipState = useSlipState()\n // Same current-pins filter as MatchesPanel: only markets a stored pin still claims render, so\n // every card carries its unpin affordance and vanishes the moment that pin is removed.\n const markets = (monitor.snapshot?.markets ?? []).filter((m) =>\n monitor.pins.some((p) => p.key === m.key))\n if (markets.length === 0) return <div className=\"ss-w-mon-empty\">{ui.emptyOddsTab}</div>\n return (\n <div className=\"ss-w-mon-list\">\n {markets.map((m) => {\n // The unpin lives in the card's own header now; pass the ORIGINAL stored pin ref (found by\n // key) so its pinKey matches exactly -- the card would otherwise reconstruct a market pin\n // with line=mainLine, which never matches an accordion pin stored without a line.\n const pin = monitor.pins.find((p) => p.key === m.key)\n return (\n <div className=\"ss-w-mon-oddspin\" key={m.key} data-settled={m.isSettled || undefined}>\n <OddsLiveStrip m={m} ui={ui} />\n {/* D5 persistent in-slip badge: the wasAdded->markAdded wrapping lives in StatsWidget's\n own slip memo (so a conversation-path add also arms the badge) -- this panel only\n reads the widget's slip state to render it. */}\n {m.card && (\n <MarketOddsCardList\n cards={[withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])]}\n ui={ui}\n slip={slip}\n monitor={monitor}\n pinRef={pin ?? undefined}\n inSlipIds={slipState?.added}\n />\n )}\n {m.history && <OddsMovementCardList cards={[toOddsMovementVM(m.history)]} ui={ui} />}\n {!m.card && !m.history && <div className=\"ss-w-mon-empty-card\">{ui.oddsUnavailable}</div>}\n </div>\n )\n })}\n </div>\n )\n}\n","import type { MatchState, ScheduleMatch } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { PinToggle } from './PinToggle'\nimport { MatchLink } from './MatchLink'\n\nfunction kickoffLabel(kickoffUnix: number): string {\n const d = new Date(kickoffUnix * 1000)\n return `${`${d.getHours()}`.padStart(2, '0')}:${`${d.getMinutes()}`.padStart(2, '0')}`\n}\n\n// The away side mirrors the home side around the score: crest on the far (right)\n// edge, name aligned inward toward the score. Reversing the flow in CSS keeps the\n// DOM order crest→name identical to home, matching the away pattern used by the\n// fandash fixture/live cards.\nfunction Side({ name, crest, away = false }: { name: string; crest?: string | null; away?: boolean }): JSX.Element {\n return (\n <span className={away ? 'ss-w-drow-side ss-w-drow-side--away' : 'ss-w-drow-side'}>\n {crest ? <img className=\"ss-w-drow-crest\" src={crest} alt=\"\" /> : null}\n <span className=\"ss-w-drow-nm\">{name}</span>\n </span>\n )\n}\n\nexport function FixtureRow({ match, state, stale, ui, monitor }: {\n match: ScheduleMatch\n state?: MatchState\n stale: boolean\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element {\n // Deliberately no per-match staleness test. u357 added one, reading Match.UpdatedAt through\n // stateAsOfUtc — but that column advances only when the DATA CHANGES, not when we poll. Measured\n // on sandbox1: every live match had a poll age of 31-48s while UpdatedAt ages ran 32-1451s, so\n // the guard suppressed the clock on 9 of 17 healthy matches, Levante v Barcelona among them. The\n // stalled window it was built for does not exist; `stale` (our own fetch failing) is the only\n // real signal we have, and it already covers the whole payload.\n const isLive = state?.phase === 'live' && !stale\n // Gated on phase, never on the presence of a number: /states counts goal rows, so it reports 0\n // for a fixture with none whatever its phase, and the due set polls anything whose kickoff clock\n // has passed. A \"NotStarted\" fixture between the clock passing and the live feed flipping would\n // otherwise read 0-0. The typeof pair only narrows the template below.\n const hasScore = (state?.phase === 'live' || state?.phase === 'fullTime')\n && typeof state.homeScore === 'number' && typeof state.awayScore === 'number'\n const score = hasScore ? `${state!.homeScore}–${state!.awayScore}` : undefined\n\n // Rendered verbatim. The minute runs ~2 min behind wall clock because the provider's own\n // `minutes` field is a snapshot we freeze until the next poll -- that is being corrected at the\n // source in the hub (deriving from the ticking period's start), NOT compensated for here. Two\n // layers each adding elapsed to the same number is how you get a 139th minute.\n const ticked = state?.phase === 'live' ? (state.minuteLabel ?? null) : null\n const when = state?.isHalfTime && !stale\n ? ui.halfTime\n : isLive\n ? (ticked ?? '\\u2014')\n : state?.phase === 'live'\n ? '\\u2014'\n : kickoffLabel(match.kickoffUnix)\n\n return (\n <div className={isLive || state?.isHalfTime ? 'ss-w-drow ss-w-drow--live' : 'ss-w-drow'}>\n <span className={isLive || state?.isHalfTime ? 'ss-w-drow-when ss-w-drow-when--live' : 'ss-w-drow-when'}>{when}</span>\n <MatchLink matchId={match.matchId} home={match.homeTeamName} away={match.awayTeamName} detail={score} className=\"ss-w-drow-fx\">\n <Side name={match.homeTeamName} crest={match.homeTeamImagePath} />\n {/* The score sits between the two sides, where a scoreboard puts it. With no score yet it\n is the separating dash, so the row keeps one shape before and after kickoff. */}\n <span className={hasScore ? 'ss-w-drow-sc' : 'ss-w-drow-sc ss-w-drow-sc--idle'}>\n {score ?? '–'}\n </span>\n <Side name={match.awayTeamName} crest={match.awayTeamImagePath} away />\n </MatchLink>\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n </div>\n )\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\n\n/**\n * The single question \"is this match being presented as live right now\". Both sides of the seam\n * must ask it the same way: TodayPanel uses it to pick the live band, CompetitionGroup uses its\n * negation to decide what stays in the group. If the two ever disagree a match falls through the\n * gap and renders nowhere — that is a defect this codebase has already shipped once.\n *\n * `pollStale` is OUR fetch failing, which is a real reason to stop trusting every state at once.\n * There is deliberately no per-match staleness test here; see the note in FixtureRow.\n */\nexport function isTreatedLive(state: MatchState | undefined, pollStale: boolean): boolean {\n return state?.phase === 'live' && !pollStale\n}\n\n/**\n * A match the Today tab has no reason to keep listing. The schedule endpoint already excludes\n * terminal matches server-side (LiveMonitorScheduleComposer filters Match.MatchState), but the\n * client caches a day's schedule in localStorage for six hours — so a match that finishes while\n * the panel is open would linger in a list a fresh load would not show it in. This closes that\n * gap so both paths agree.\n *\n * fullTime only, deliberately. `postponed` arises server-side when a fixture has no kickoff\n * timestamp, which the schedule query already excludes, and hiding a postponed fixture from the\n * day it was scheduled for would be a different decision than the one being made here.\n */\nexport function isFinished(state: MatchState | undefined): boolean {\n return state?.phase === 'fullTime'\n}\n\n/**\n * What the Today tab actually contains, after the finished matches leave. This is the ONE answer\n * both the panel and the tab strip read: TodayPanel renders it, and `hasToday` decides from its\n * length whether the tab exists at all. Deciding the tab from the raw schedule instead is what\n * shipped a Today tab opening onto a blank panel once every match of the day had ended.\n */\nexport function visibleGroupsOf(\n groups: readonly ScheduleGroup[],\n states: Record<number, MatchState>,\n): ScheduleGroup[] {\n return groups\n .map((group) => ({ ...group, matches: group.matches.filter((m) => !isFinished(states[m.matchId])) }))\n .filter((group) => group.matches.length > 0)\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { FixtureRow } from './FixtureRow'\nimport { isTreatedLive } from '../liveClock'\n\nexport function CompetitionGroup({ group, open, onToggle, states, stale, ui, monitor, disambiguate = false }: {\n group: ScheduleGroup\n open: boolean\n onToggle(): void\n /** True when another group on screen shares this competition's name, so the name alone\n * does not identify it. Only then is the country worth the horizontal space. */\n disambiguate?: boolean\n states: Record<number, MatchState>\n stale: boolean\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element | null {\n // A live fixture is rendered in the live band above, so it is absent here AND absent from the\n // count -- the badge has to agree with what is under the header. But once the poll goes stale\n // the live band hides itself (Task 13), so a cached phase:'live' match must fall back into its\n // group rather than vanish from the tab entirely -- mirrors FixtureRow's own isLive check.\n const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale))\n const hasLive = own.length !== group.matches.length\n\n // Every match hoisted into the live band leaves nothing under this header. Rendering anyway\n // produced a header reading \"Championship ... 0\" whose body was empty however you toggled it.\n // Hiding it is safe against the vanish bug the filter above guards: when the poll goes stale\n // isTreatedLive is false for everything, so own is the full list and the group comes back.\n if (own.length === 0) {\n return null\n }\n\n return (\n <div className=\"ss-w-grp\">\n <button type=\"button\" className=\"ss-w-grp-head\" aria-expanded={open} onClick={onToggle}>\n <span className=\"ss-w-grp-chev\">{open ? '▾' : '▸'}</span>\n {hasLive && <span className=\"ss-w-sec-dot\" aria-hidden=\"true\" />}\n <span className=\"ss-w-grp-name\">\n {group.competitionName}\n {disambiguate && group.competitionCountry\n ? <span className=\"ss-w-grp-country\"> ({group.competitionCountry})</span>\n : null}\n </span>\n <span className=\"ss-w-grp-count\">{own.length}</span>\n </button>\n {open && (\n <div className=\"ss-w-grp-body\">\n {own.map((m) => (\n <FixtureRow key={m.matchId} match={m} state={states[m.matchId]} stale={stale} ui={ui} monitor={monitor} />\n ))}\n </div>\n )}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport { CompetitionGroup } from './CompetitionGroup'\nimport { FixtureRow } from './FixtureRow'\nimport { isTreatedLive, visibleGroupsOf } from '../liveClock'\n\nexport function TodayPanel({ discovery, ui, monitor }: {\n discovery: MatchDiscoveryController\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element {\n const { groups, states, stale, expanded, toggleGroup } = discovery\n\n // Finished matches leave the day. Everything below reads visibleGroups, never groups: the live\n // band, the name-collision count, the group list and the tab strip that decides whether this\n // panel is reachable at all have to agree on what the day contains, and filtering in one place\n // is what guarantees that.\n const visibleGroups = visibleGroupsOf(groups, states)\n\n // Flat across competitions but ordered by the competition's rank, then by the fixture's position\n // inside its group -- no ranking field of the client's own. Array.sort is stable, so ties within\n // a rank keep the flatMap's group-then-match order.\n // The sort is NOT dead code: `rank` is the contract, the array order is not. That the composer\n // currently emits groups already in rank order is incidental -- nothing in the wire format\n // promises it, and a server-side reordering would silently scramble the live band without this.\n const liveRows = stale\n ? []\n : visibleGroups\n .flatMap((group) =>\n group.matches\n .filter((m) => isTreatedLive(states[m.matchId], stale))\n .map((match) => ({ match, rank: group.rank })))\n .sort((a, b) => a.rank - b.rank)\n\n // competitionName is not an identity: a real Saturday returns four groups named \"Premier\n // League\". Only collide-on-screen names pay the horizontal cost of a country suffix.\n const nameCounts = visibleGroups.reduce<Record<string, number>>((acc, g) => {\n acc[g.competitionName] = (acc[g.competitionName] ?? 0) + 1\n return acc\n }, {})\n\n return (\n <div className=\"ss-w-mon-list\">\n {stale && <div className=\"ss-w-stale\">{ui.staleStates}</div>}\n\n {liveRows.length > 0 && (\n <>\n <div className=\"ss-w-sec-head\">\n <span className=\"ss-w-sec-dot\" aria-hidden=\"true\" />\n {ui.sectionLive}\n </div>\n <div className=\"ss-w-today-live\">\n {liveRows.map(({ match }) => (\n <FixtureRow key={match.matchId} match={match} state={states[match.matchId]}\n stale={stale} ui={ui} monitor={monitor} />\n ))}\n </div>\n </>\n )}\n\n {visibleGroups.map((group) => (\n <CompetitionGroup\n key={group.competitionId}\n group={group}\n open={expanded[group.competitionId] ?? group.expandedByDefault}\n onToggle={() => toggleGroup(group.competitionId)}\n disambiguate={(nameCounts[group.competitionName] ?? 0) > 1}\n states={states}\n stale={stale}\n ui={ui}\n monitor={monitor}\n />\n ))}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { GamesHub } from './GamesHub'\nimport { GameScreenHost } from './GameScreenHost'\nimport { ensureGamesFonts } from './games/ui/fonts'\n\nexport function GamesPanel({\n loggedIn,\n games,\n ui,\n conversation,\n leaderboard,\n refreshHub,\n}: {\n loggedIn: boolean\n games: GameSummary[]\n ui: UiConfig\n conversation?: GamePlayConversation | null\n leaderboard?: LeaderboardPayload | null\n /** Called when a play is saved and when the fan leaves a game screen, so the hub's tiles and stat row reflect the play. */\n refreshHub?: () => void\n}): JSX.Element {\n const [selected, setSelected] = useState<{ gameId: string; fixtureId: number; gameDay: string; lockAtUtc: string | null } | null>(null)\n\n useEffect(() => { ensureGamesFonts() }, [])\n\n if (!loggedIn) return <GamesLoginWall ui={ui} />\n\n if (selected !== null) {\n return (\n <div className=\"ss-w-gscreen-wrap\" lang={ui.games.lang}>\n <GameScreenHost\n selected={selected}\n onBack={() => { setSelected(null); refreshHub?.() }}\n onPlayed={refreshHub}\n conversation={conversation ?? null}\n ui={ui}\n />\n </div>\n )\n }\n\n return (\n <div className=\"ss-g-hub-wrap\" data-testid=\"games-hub\" lang={ui.games.lang}>\n <GamesHub\n games={games}\n onOpen={(g: GameSummary) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId, gameDay: g.gameDay, lockAtUtc: g.lockAtUtc ?? null })}\n myWeeklyRow={leaderboard?.myWeeklyRow ?? null}\n ui={ui}\n />\n </div>\n )\n}\n","import type { UiConfig } from '../config'\n\nexport function GamesLoginWall({ ui }: { ui: UiConfig }): JSX.Element {\n return (\n <div className=\"ss-w-mon-list\">\n <div className=\"ss-w-games-wall\">\n <p>{ui.gamesLoginRequired}</p>\n </div>\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GameTile } from './GameTile'\nimport { Chip } from './games/ui/Chip'\nimport { IconFlame } from './games/ui/icons'\n\nconst PLAYABLE = new Set<GameSummary['status']>(['available', 'in_progress'])\nconst DONE = new Set<GameSummary['status']>(['played', 'graded'])\n\nexport function pickHeroGame(games: GameSummary[]): GameSummary | null {\n const daily = games.filter(g => g.kind === 'daily')\n const tiger = daily.find(g => g.gameId === 'mystery-tiger')\n if (tiger && PLAYABLE.has(tiger.status)) return tiger\n const firstPlayable = daily.find(g => PLAYABLE.has(g.status))\n if (firstPlayable) return firstPlayable\n return tiger ?? daily[0] ?? null\n}\n\n// Two fixtures of one game on one day must not share a key.\nexport const tileKey = (g: GameSummary): string => `${g.gameId}-${g.gameDay}-${g.fixtureId}`\n\nexport function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }: {\n games: GameSummary[]\n myWeeklyRow?: LeaderboardRow | null\n weeklyPrize?: string\n onOpen: (g: GameSummary) => void\n ui: UiConfig\n}): JSX.Element {\n const [, setTick] = useState(0)\n useEffect(() => {\n const id = setInterval(() => setTick(t => t + 1), 60_000)\n return () => clearInterval(id)\n }, [])\n\n const hero = pickHeroGame(games)\n const daily = games.filter(g => g.kind === 'daily' && g !== hero)\n const grid = daily.filter(g => g.gameId !== 'beat-the-grid')\n const wide = daily.find(g => g.gameId === 'beat-the-grid')\n const fixtures = games.filter(g => g.kind === 'fixture')\n const kickoffs = fixtures.map(g => g.kickoffUtc).filter((k): k is string => !!k).sort()\n const todayPts = games.filter(g => DONE.has(g.status)).reduce((s, g) => s + (g.score ?? 0), 0)\n const dash = '—'\n\n return (\n <div className=\"ss-g-hub\">\n <div className=\"ss-g-stats\">\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statStreak}</span>\n <span className=\"ss-g-stat-v\" data-testid=\"stat-streak\">\n {myWeeklyRow ? <><IconFlame />{myWeeklyRow.currentStreak}</> : dash}\n {myWeeklyRow && <small>{ui.games.unitDays}</small>}\n </span></div>\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statToday}</span>\n <span className=\"ss-g-stat-v ss-g-stat-v--accent\" data-testid=\"stat-today\">{ui.games.formatPts(todayPts)}<small>{ui.games.unitPts}</small></span></div>\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statRank}</span>\n <span className=\"ss-g-stat-v\" data-testid=\"stat-rank\">{myWeeklyRow ? `#${myWeeklyRow.rank}` : dash}\n {myWeeklyRow && <small>{ui.games.thisWeek}</small>}</span></div>\n </div>\n\n {weeklyPrize && <Chip variant=\"accent\" className=\"ss-g-prize\">{weeklyPrize}</Chip>}\n\n {hero && <GameTile game={hero} onOpen={onOpen} ui={ui} variant=\"hero\" />}\n\n {(grid.length > 0 || wide) && (\n <section className=\"ss-g-sec\">\n <div className=\"ss-g-sec-head\"><h3>{ui.games.dailyGames}</h3><span>{ui.games.newSetAtMidnight}</span></div>\n {grid.length > 0 && <div className=\"ss-g-grid\">{grid.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>}\n {wide && <GameTile game={wide} onOpen={onOpen} ui={ui} variant=\"wide\" />}\n </section>\n )}\n\n {fixtures.length > 0 && (\n <section className=\"ss-g-sec\">\n <div className=\"ss-g-sec-head\"><h3>{ui.games.matchdayGames}</h3>\n {kickoffs[0] && <span>{ui.games.kickoffAt(ui.games.formatDayTime(kickoffs[0]))}</span>}</div>\n <div className=\"ss-g-grid\">{fixtures.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>\n </section>\n )}\n </div>\n )\n}\n","function prettifyGameId(gameId: string): string {\n return gameId.split('-').map(w => (w ? w[0]!.toUpperCase() + w.slice(1) : w)).join(' ')\n}\n\n// `title` is nullable because GameSummary.title is `string | null` (widget-sdk events.ts).\n// `titles` is the locale-specific map from GamesStrings — caller passes `ui.games.titles`.\nexport function gameTitle(g: { gameId: string; title?: string | null }, titles: Record<string, string>): string {\n return g.title ?? titles[g.gameId] ?? prettifyGameId(g.gameId)\n}\n\n// Design renders \"first name\" small over \"SURNAME\" big. Surname = last token.\nexport function splitName(full: string): { first: string; last: string } {\n const parts = full.trim().split(/\\s+/).filter(Boolean)\n if (parts.length <= 1) return { first: '', last: parts[0] ?? '' }\n return { first: parts.slice(0, -1).join(' '), last: parts[parts.length - 1]! }\n}\n","export function GameTileArt({ gameId }: { gameId: string }): JSX.Element {\n return (\n <svg className=\"ss-g-art\" viewBox=\"0 0 120 74\" aria-hidden=\"true\">{ART[gameId] ?? ART.default}</svg>\n )\n}\n\nconst head = (cx: number, cy: number, r: number, cls = 'ss-g-art-fg') => (\n <g className={cls}><circle cx={cx} cy={cy - r * 0.3} r={r * 0.45} /><path d={`M${cx - r} ${cy + r}c0-${r * 0.8} ${r * 0.45}-${r * 1.1} ${r}-${r * 1.1}s${r} ${r * 0.3} ${r} ${r * 1.1}z`} /></g>\n)\n\nconst ART: Record<string, JSX.Element> = {\n 'mystery-tiger': <>{head(60, 38, 26, 'ss-g-art-fg')}<text x=\"60\" y=\"36\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n 'higher-or-lower': <>{head(32, 38, 20)}{head(88, 38, 20)}<circle cx=\"60\" cy=\"37\" r=\"11\" className=\"ss-g-art-accent\" /><path d=\"M57 33l3-3 3 3M57 41l3 3 3-3\" className=\"ss-g-art-ink\" /></>,\n 'guess-the-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60, 'a'], [24, 46], [48, 46], [72, 46], [96, 46], [36, 30], [60, 30], [84, 30], [40, 14], [60, 14], [80, 14]].map(([x, y, a], i) => <circle key={i} cx={x as number} cy={y as number} r=\"4\" className={a ? 'ss-g-art-accent' : 'ss-g-art-dot'} />)}</>,\n 'daily-quiz': <>{[[14, 8], [62, 8], [14, 40], [62, 40]].map(([x, y], i) => <rect key={i} x={x} y={y} width=\"44\" height=\"26\" rx=\"5\" className={i === 1 ? 'ss-g-art-correct' : 'ss-g-art-block'} />)}</>,\n 'career-path': <><path d=\"M18 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><path d=\"M48 37h8M84 37h8\" className=\"ss-g-art-line\" /><path d=\"M60 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><rect x=\"96\" y=\"22\" width=\"18\" height=\"26\" rx=\"4\" className=\"ss-g-art-dash\" /><text x=\"105\" y=\"40\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n 'beat-the-grid': <>{[0, 1, 2].flatMap(r => [0, 1, 2].map(c => <rect key={`${r}${c}`} x={33 + c * 19} y={10 + r * 19} width=\"16\" height=\"16\" rx=\"3\" className={(r + c) % 3 === 0 ? 'ss-g-art-accent' : 'ss-g-art-block'} />))}</>,\n 'matchday-predictor': <><path d=\"M10 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /><rect x=\"38\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-accent-stroke\" /><rect x=\"64\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-dash\" /><path d=\"M90 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /></>,\n 'starting-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60], [30, 46], [50, 46], [70, 46], [90, 46], [45, 30], [75, 30], [30, 16], [60, 16], [90, 16]].map(([x, y], i) => <circle key={i} cx={x} cy={y} r=\"5\" className={i < 7 ? 'ss-g-art-accent' : 'ss-g-art-dash'} />)}</>,\n 'stat-ladder': <>{[[20, 70], [34, 52], [48, 34]].map(([y, w], i) => <rect key={i} x=\"24\" y={y} width={w} height=\"12\" rx=\"3\" className={i === 1 ? 'ss-g-art-accent' : 'ss-g-art-block'} />)}</>,\n 'fan-motm': <><circle cx=\"60\" cy=\"37\" r=\"26\" className=\"ss-g-art-accent-stroke\" />{head(60, 40, 18)}<path d=\"M84 8l2.4 5 5.4.6-4 3.7 1.1 5.4-4.9-2.7-4.9 2.7 1.1-5.4-4-3.7 5.4-.6z\" className=\"ss-g-art-accent\" /></>,\n default: <circle cx=\"60\" cy=\"37\" r=\"22\" className=\"ss-g-art-fg\" />,\n}\n","import type { ReactNode } from 'react'\n\nexport type ChipVariant = 'neutral' | 'accent' | 'success' | 'badge' | 'lock'\n\nexport function Chip({ variant = 'neutral', icon, children, className }: {\n variant?: ChipVariant; icon?: ReactNode; children: ReactNode; className?: string\n}): JSX.Element {\n return (\n <span className={`ss-g-chip ss-g-chip--${variant}${className ? ` ${className}` : ''}`}>\n {icon}{children}\n </span>\n )\n}\n\nexport function StatStack({ value, label }: { value: ReactNode; label: string }): JSX.Element {\n return (\n <span className=\"ss-g-statstack\">\n <span className=\"ss-g-statstack-v\">{value}</span>\n <span className=\"ss-g-statstack-l\">{label}</span>\n </span>\n )\n}\n","type P = { size?: number }\nconst svg = (size: number, children: JSX.Element | JSX.Element[], fill = false): JSX.Element => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={fill ? 'currentColor' : 'none'} stroke={fill ? 'none' : 'currentColor'}\n strokeWidth={2.2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">{children}</svg>\n)\nexport const IconChevronLeft = ({ size = 20 }: P) => svg(size, <path d=\"M15 18l-6-6 6-6\" />)\nexport const IconLock = ({ size = 14 }: P) => svg(size, [<rect key=\"a\" x=\"5\" y=\"11\" width=\"14\" height=\"10\" rx=\"2\" />, <path key=\"b\" d=\"M8 11V7a4 4 0 0 1 8 0v4\" />])\nexport const IconCheck = ({ size = 14 }: P) => svg(size, <path d=\"M5 12l5 5 9-10\" />)\nexport const IconClose = ({ size = 16 }: P) => svg(size, <path d=\"M6 6l12 12M18 6L6 18\" />)\nexport const IconSearch = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"11\" cy=\"11\" r=\"7\" />, <path key=\"b\" d=\"M20 20l-3.5-3.5\" />])\nexport const IconPlus = ({ size = 20 }: P) => svg(size, <path d=\"M12 5v14M5 12h14\" />)\nexport const IconStar = ({ size = 14 }: P) => svg(size, <path d=\"M12 2.5l2.9 6 6.6.8-4.9 4.5 1.3 6.5L12 17l-5.9 3.3 1.3-6.5L2.5 9.3l6.6-.8z\" />, true)\nexport const IconBulb = ({ size = 16 }: P) => svg(size, [<path key=\"a\" d=\"M9 18h6M10 21h4\" />, <path key=\"b\" d=\"M12 3a6 6 0 0 0-3.5 10.9V16h7v-2.1A6 6 0 0 0 12 3z\" />])\nexport const IconArrowUp = ({ size = 12 }: P) => svg(size, <path d=\"M12 19V5M5 12l7-7 7 7\" />)\nexport const IconArrowDown = ({ size = 12 }: P) => svg(size, <path d=\"M12 5v14M19 12l-7 7-7-7\" />)\nexport const IconCalendar = ({ size = 18 }: P) => svg(size, [<rect key=\"a\" x=\"4\" y=\"5\" width=\"16\" height=\"15\" rx=\"2\" />, <path key=\"b\" d=\"M4 10h16M9 3v4M15 3v4\" />])\nexport const IconShield = ({ size = 18 }: P) => svg(size, <path d=\"M12 3l7 3v6c0 5-3 8-7 9-4-1-7-4-7-9V6z\" />)\nexport const IconFlag = ({ size = 18 }: P) => svg(size, <path d=\"M5 21V4M5 4h12l-2 4 2 4H5\" />)\nexport const IconBall = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"12\" cy=\"12\" r=\"9\" />, <path key=\"b\" d=\"M12 7l4 3-1.5 4.5h-5L8 10z\" />])\nexport const IconBoot = ({ size = 18 }: P) => svg(size, <path d=\"M4 6h6l1 6 8 3v3H4z\" />)\nexport const IconGloves = ({ size = 18 }: P) => svg(size, <path d=\"M7 21v-8l-2-3V6a1.5 1.5 0 0 1 3 0v3V4a1.5 1.5 0 0 1 3 0v5V3.5a1.5 1.5 0 0 1 3 0V9V5a1.5 1.5 0 0 1 3 0v9l-2 3v4z\" />)\nexport const IconFlame = ({ size = 16 }: P) => svg(size, <path d=\"M12 3c1 4 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-7 1.5 1 2 2 2 3 1-2 1-4 1-6z\" />, true)\n","import type { GameSummary } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { gameTitle } from './games/ui/gameMeta'\nimport { GameTileArt } from './GameTileArt'\nimport { Chip } from './games/ui/Chip'\nimport { IconChevronLeft } from './games/ui/icons'\n\nexport type TileTone = 'new' | 'accent' | 'success' | 'muted'\n\n/** Pure: the tile's status line and tone, from the existing GameSummary fields only. */\nexport function tileStatus(game: GameSummary, ui: UiConfig): { text: string; tone: TileTone } {\n switch (game.status) {\n case 'locked': return { text: ui.gameLocked, tone: 'muted' }\n case 'voided': return { text: ui.gameVoided, tone: 'muted' }\n case 'in_progress': return { text: ui.games.resume, tone: 'accent' }\n case 'played':\n case 'graded':\n return game.ranked\n ? { text: ui.games.doneWithScore(game.score ?? 0), tone: 'success' }\n : { text: ui.games.done, tone: 'success' }\n default:\n if (game.kind === 'fixture' && game.lockAtUtc && new Date(game.lockAtUtc).getTime() > Date.now()) {\n return { text: ui.games.locksAt(ui.games.formatDayTime(game.lockAtUtc)), tone: 'accent' }\n }\n return { text: ui.games.taglines[game.gameId] ?? ui.gamePlay, tone: 'new' }\n }\n}\n\nconst DISABLED = new Set<GameSummary['status']>(['locked', 'voided'])\n\nexport function GameTile({ game, onOpen, ui, variant = 'tile' }: {\n game: GameSummary; onOpen: (g: GameSummary) => void; ui: UiConfig; variant?: 'tile' | 'wide' | 'hero'\n}): JSX.Element {\n const status = tileStatus(game, ui)\n const disabled = DISABLED.has(game.status)\n const title = gameTitle(game, ui.games.titles)\n\n const body = variant === 'hero' ? (\n <>\n <span className=\"ss-g-hero-text\">\n <span className=\"ss-g-hero-eyebrow\">{ui.games.dailyChallenge}</span>\n {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n <span className=\"ss-g-hero-title\">{title}</span>\n <span className=\"ss-g-hero-sub\">{ui.games.taglines[game.gameId] ?? ''}</span>\n {status.tone === 'success'\n ? <span className=\"ss-g-tile-status\" data-tone=\"success\">{status.text}</span>\n : <span className=\"ss-g-hero-cta\">{status.tone === 'accent' ? ui.games.resume : ui.games.playNow} →</span>}\n </span>\n <span className=\"ss-g-hero-art\"><GameTileArt gameId={game.gameId} /></span>\n </>\n ) : variant === 'wide' ? (\n <>\n <span className=\"ss-g-wide-art\"><GameTileArt gameId={game.gameId} /></span>\n <span className=\"ss-g-wide-text\">\n <span className=\"ss-g-tile-title\">{title}</span>\n <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n </span>\n <span className=\"ss-g-wide-chev\"><IconChevronLeft size={18} /></span>\n </>\n ) : (\n <>\n <span className=\"ss-g-tile-art\"><GameTileArt gameId={game.gameId} /></span>\n <span className=\"ss-g-tile-title\">{title}</span>\n <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n </>\n )\n\n const cls = `ss-g-tile ss-g-tile--${variant}`\n if (disabled) return <div className={cls} data-disabled aria-disabled=\"true\">{body}</div>\n return <button type=\"button\" className={cls} aria-label={`${title} — ${status.text}`} onClick={() => onOpen(game)}>{body}</button>\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { useGamePlay } from '../useGamePlay'\nimport { MysteryTigerGame } from './games/MysteryTigerGame'\nimport { HigherOrLowerGame } from './games/HigherOrLowerGame'\nimport { CareerPathGame } from './games/CareerPathGame'\nimport { BeatTheGridGame } from './games/BeatTheGridGame'\nimport { GuessTheXiGame } from './games/GuessTheXiGame'\nimport { DailyQuizGame } from './games/DailyQuizGame'\nimport { MatchdayPredictorGame } from './games/MatchdayPredictorGame'\nimport { StartingXiGame } from './games/StartingXiGame'\nimport { StatLadderGame } from './games/StatLadderGame'\nimport { FanMotmGame } from './games/FanMotmGame'\nimport { GameHeader } from './games/ui/GameHeader'\nimport { gameTitle } from './games/ui/gameMeta'\nimport type {\n MysteryTigerConfig,\n HolConfig,\n CareerPathConfig,\n BeatTheGridConfig,\n GuessTheXiConfig,\n DailyQuizConfig,\n MatchdayPredictorConfig,\n StartingXiConfig,\n StatLadderConfig,\n FanMotmConfig,\n} from './games/types'\n\n// Fixture games need a pending-result poll: they submit once before kickoff,\n// then remain in \"pending\" until resolved at full time.\nconst FIXTURE_GAME_IDS = new Set([\n 'matchday-predictor',\n 'starting-xi',\n 'stat-ladder',\n 'fan-motm',\n])\n\n// Poll cadence while a fixture game result is pending (30 seconds).\nconst PENDING_POLL_INTERVAL_MS = 30_000\n\nfunction safeParseConfig<T>(json: string | null | undefined): T | null {\n if (!json) return null\n try {\n return JSON.parse(json) as T\n } catch {\n return null\n }\n}\n\nexport function GameScreenHost({\n selected,\n onBack,\n onPlayed,\n conversation,\n ui,\n}: {\n selected: { gameId: string; fixtureId: number; gameDay?: string; lockAtUtc?: string | null }\n onBack: () => void\n /** Called once a submitted play has been saved, so the hub can refetch points and status. */\n onPlayed?: () => void\n conversation: GamePlayConversation | null | undefined\n ui: UiConfig\n}): JSX.Element {\n const { gameId, fixtureId, gameDay = '', lockAtUtc = null } = selected\n\n // Fetch config on open\n const [configJson, setConfigJson] = useState<string | null>(null)\n\n useEffect(() => {\n setConfigJson(null)\n if (!conversation) return\n let cancelled = false\n void (async () => {\n try {\n const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || undefined, ui.games.lang)\n if (!cancelled && payload?.configJson) {\n setConfigJson(payload.configJson)\n }\n } catch {\n // best-effort\n }\n })()\n return () => { cancelled = true }\n }, [conversation, gameId, fixtureId, gameDay, ui.games.lang])\n\n // Shared submit lifecycle\n const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {\n gameId,\n gameDay: gameDay,\n fixtureId: fixtureId || undefined,\n locale: ui.games.lang,\n })\n\n // Hydrate on open for a returning fan\n useEffect(() => {\n if (conversation) hydrate()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversation, gameId])\n\n // Pending-result poll: while a fixture game result is pending (submitted but not yet\n // resolved at full time), poll getGameResult at a low cadence until graded or voided.\n const hydrateRef = useRef(hydrate)\n hydrateRef.current = hydrate\n\n useEffect(() => {\n if (!FIXTURE_GAME_IDS.has(gameId)) return\n if (rawStatus !== 'pending') return\n\n const timerId = setInterval(() => {\n hydrateRef.current()\n }, PENDING_POLL_INTERVAL_MS)\n\n return () => clearInterval(timerId)\n }, [gameId, rawStatus])\n\n const sharedProps = {\n result,\n submitting,\n // Refresh only after the play is saved: a fan can tap Back while a submit is still in flight,\n // and a refetch fired from Back alone would read the hub's pre-play state.\n onSubmit: (answerJson: string) => { void submit(answerJson).then(() => onPlayed?.()) },\n ui,\n onBack,\n lockAtUtc,\n }\n\n function renderScreen(): JSX.Element {\n switch (gameId) {\n case 'mystery-tiger':\n return (\n <MysteryTigerGame\n {...sharedProps}\n config={safeParseConfig<MysteryTigerConfig>(configJson)}\n />\n )\n case 'higher-or-lower':\n return (\n <HigherOrLowerGame\n {...sharedProps}\n config={safeParseConfig<HolConfig>(configJson)}\n />\n )\n case 'career-path':\n return (\n <CareerPathGame\n {...sharedProps}\n config={safeParseConfig<CareerPathConfig>(configJson)}\n />\n )\n case 'beat-the-grid': {\n const btgConfig = safeParseConfig<BeatTheGridConfig>(configJson)\n return (\n <BeatTheGridGame\n {...sharedProps}\n config={btgConfig}\n playerPool={btgConfig?.playerPool ?? []}\n />\n )\n }\n case 'guess-the-xi':\n return (\n <GuessTheXiGame\n {...sharedProps}\n config={safeParseConfig<GuessTheXiConfig>(configJson)}\n />\n )\n case 'daily-quiz':\n return (\n <DailyQuizGame\n {...sharedProps}\n config={safeParseConfig<DailyQuizConfig>(configJson)}\n />\n )\n case 'matchday-predictor':\n return (\n <MatchdayPredictorGame\n {...sharedProps}\n config={safeParseConfig<MatchdayPredictorConfig>(configJson)}\n />\n )\n case 'starting-xi':\n return (\n <StartingXiGame\n {...sharedProps}\n config={safeParseConfig<StartingXiConfig>(configJson)}\n />\n )\n case 'stat-ladder':\n return (\n <StatLadderGame\n {...sharedProps}\n config={safeParseConfig<StatLadderConfig>(configJson)}\n />\n )\n case 'fan-motm':\n return (\n <FanMotmGame\n {...sharedProps}\n config={safeParseConfig<FanMotmConfig>(configJson)}\n />\n )\n default:\n return (\n <div className=\"ss-g-screen\" data-testid={`game-screen-${gameId}`}>\n <GameHeader title={gameTitle({ gameId }, ui.games.titles)} onBack={onBack} backLabel={ui.back} />\n </div>\n )\n }\n }\n\n return (\n <div className=\"ss-w-gscreen\" data-testid=\"gscreen\" data-lock-at={lockAtUtc ?? undefined}>\n {renderScreen()}\n </div>\n )\n}\n","import { useCallback, useRef, useState } from 'react'\nimport type { GameResultPayload, GameStatePayload, SubmitPlayResult } from '@sensiblestats/widget-sdk'\n\nexport interface UseGamePlayOptions {\n gameId: string\n gameDay: string\n fixtureId?: number\n locale?: string\n /** Called after a ranked play completes (pointsDelta present). */\n refresh?: () => void\n}\n\nexport interface UseGamePlayResult {\n result: SubmitPlayResult | null\n submitting: boolean\n submit: (answerJson: string) => Promise<void>\n hydrate: () => void\n /** Raw status string from the last getGameResult call (null until hydrated). */\n rawStatus: string | null\n}\n\nexport type GamePlayConversation = {\n postPlay: (gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string) => Promise<SubmitPlayResult | null>\n getGameResult: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameResultPayload | null>\n getGameConfig: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameStatePayload | null>\n}\n\nfunction toSubmitResult(payload: GameResultPayload): SubmitPlayResult {\n return {\n // 'pending' means the play is recorded but awaiting resolution (fixture games)\n alreadyPlayed: payload.status === 'played' || payload.status === 'graded' || payload.status === 'pending',\n score: payload.score,\n isCorrect: payload.isCorrect,\n clientStateJson: payload.clientStateJson,\n attemptsUsed: payload.attemptsUsed,\n }\n}\n\nexport function useGamePlay(\n conversation: GamePlayConversation | null | undefined,\n { gameId, gameDay, fixtureId, locale, refresh }: UseGamePlayOptions,\n): UseGamePlayResult {\n const [result, setResult] = useState<SubmitPlayResult | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const [rawStatus, setRawStatus] = useState<string | null>(null)\n\n const inFlightRef = useRef(false)\n const convRef = useRef(conversation)\n convRef.current = conversation\n const optsRef = useRef({ gameId, gameDay, fixtureId, locale, refresh })\n optsRef.current = { gameId, gameDay, fixtureId, locale, refresh }\n // Mirror the latest result so submit() (a stable [] callback) can tell whether we\n // already hold in-progress state without wiping it.\n const resultRef = useRef<SubmitPlayResult | null>(null)\n resultRef.current = result\n\n const refetch = useCallback(async (): Promise<void> => {\n const conv = convRef.current\n if (!conv) return\n const opts = optsRef.current\n try {\n const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay, opts.locale)\n if (payload === null) return\n // Never let a null-clientState payload blank a board we already hold (e.g. a rescore that\n // couldn't reconstruct state). A first hydrate holds nothing, so a legitimately terminal\n // null-state play (voided / already-played) still renders; the status always updates.\n if (payload.clientStateJson == null && resultRef.current?.clientStateJson != null) {\n setRawStatus(payload.status)\n return\n }\n setResult(toSubmitResult(payload))\n setRawStatus(payload.status)\n } catch {\n // best-effort\n }\n }, [])\n\n const submit = useCallback(async (answerJson: string): Promise<void> => {\n const conv = convRef.current\n if (!conv || inFlightRef.current) return\n inFlightRef.current = true\n setSubmitting(true)\n try {\n const opts = optsRef.current\n const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId, opts.locale)\n if (playResult !== null) {\n // Guard against a state-losing response: a still-in-progress submit that carries no\n // ClientStateJson (e.g. a server-side concurrency retry) must NOT overwrite the board\n // we already hold. Reconcile from the server instead of rendering an empty state.\n const hasFreshState = playResult.clientStateJson != null\n const isTerminal = playResult.alreadyPlayed === true\n const holdsState = resultRef.current?.clientStateJson != null\n if (!hasFreshState && !isTerminal && holdsState) {\n await refetch()\n } else {\n setResult(playResult)\n }\n if (playResult.pointsDelta != null) {\n opts.refresh?.()\n }\n }\n } catch {\n // best-effort; leave result unchanged\n } finally {\n inFlightRef.current = false\n setSubmitting(false)\n }\n }, [refetch])\n\n const hydrate = useCallback((): void => {\n void refetch()\n }, [refetch])\n\n return { result, submitting, submit, hydrate, rawStatus }\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, MysteryTigerConfig, MysteryTigerClientState, MysteryTigerGuessResult, MysteryTigerAttributeVerdict } from './types'\nimport { nationalityFlag } from './nationFlags'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress, type SegmentState } from './ui/SegmentProgress'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { IconBulb } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\nfunction parseClientState(json: string | null | undefined): MysteryTigerClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as MysteryTigerClientState\n } catch {\n return null\n }\n}\n\nexport type MtAttrKey = keyof Omit<MysteryTigerGuessResult, 'playerId'>\nconst ATTR_KEYS: MtAttrKey[] = ['position', 'nationality', 'age', 'shirtNumber', 'apps']\nconst NUMERIC_KEYS: ReadonlySet<MtAttrKey> = new Set<MtAttrKey>(['age', 'shirtNumber', 'apps'])\n\nconst MAX_GUESSES = 6\n\nfunction verdictGlyph(v: MysteryTigerAttributeVerdict): string {\n if (v.verdict === 'exact') return '✓'\n if (v.verdict === 'miss') return '✗'\n if (v.direction === 'up') return '↑'\n if (v.direction === 'down') return '↓'\n return '≈'\n}\n\n// Direction arrow shown under a numeric value (\"22 ▲\" = mystery player is older/higher/more).\nfunction directionArrow(v: MysteryTigerAttributeVerdict): string {\n if (v.direction === 'up') return '▲'\n if (v.direction === 'down') return '▼'\n return ''\n}\n\n// Full position names (Sportmonks \"Centre Forward\", \"Goalkeeper\", …) overflow the small square\n// tile, so map them to a short code for display. Anything unmapped falls back to its initials.\nconst POSITION_SHORT: Record<string, string> = {\n goalkeeper: 'GK', keeper: 'GK',\n defender: 'DEF', 'centre back': 'CB', 'center back': 'CB', 'centre-back': 'CB', 'center-back': 'CB',\n 'left back': 'LB', 'right back': 'RB', 'left wing-back': 'LWB', 'right wing-back': 'RWB', sweeper: 'SW',\n midfielder: 'MID', 'defensive midfield': 'DM', 'central midfield': 'CM', 'centre midfield': 'CM',\n 'attacking midfield': 'AM', 'left midfield': 'LM', 'right midfield': 'RM',\n 'left wing': 'LW', 'right wing': 'RW', 'left winger': 'LW', 'right winger': 'RW',\n forward: 'FWD', attacker: 'FWD', striker: 'ST', 'second striker': 'SS',\n 'centre forward': 'CF', 'center forward': 'CF', 'centre-forward': 'CF',\n}\n\nfunction shortPosition(value: string): string {\n const mapped = POSITION_SHORT[value.trim().toLowerCase()]\n if (mapped) return mapped\n if (value.length <= 3) return value.toUpperCase() // already a code (GK, ST, CB, …)\n return value.split(/[\\s-]+/).filter(Boolean).map(w => (w[0] ?? '').toUpperCase()).join('').slice(0, 3)\n}\n\n// The display face of a tile: the guessed player's own value (a flag for nationality, a short\n// code for position), falling back to the verdict glyph when the backend sent no value.\nfunction tileFace(key: MtAttrKey, v: MysteryTigerAttributeVerdict): string {\n if (!v.value) return verdictGlyph(v)\n if (key === 'nationality') return nationalityFlag(v.value)\n if (key === 'position') return shortPosition(v.value)\n return v.value\n}\n\nexport interface KnownAttribute { key: MtAttrKey; state: 'known' | 'range' | 'unknown'; text: string }\n\n// What the fan has pinned down so far, per attribute. An exact verdict reveals the value. For the\n// numeric attributes each ▲ (\"mystery is higher than v\") raises the floor and each ▼ lowers the\n// ceiling, so 23▲ + 26▼ reads \"24–25\", only ▼9 reads \"< 9\", only ▲31 reads \"> 31\".\nexport function deriveKnownAttributes(guesses: MysteryTigerGuessResult[], keys: MtAttrKey[]): KnownAttribute[] {\n return keys.map((key): KnownAttribute => {\n const exact = guesses.find(g => g[key].verdict === 'exact')\n if (exact) return { key, state: 'known', text: tileFace(key, exact[key]) }\n if (!NUMERIC_KEYS.has(key)) return { key, state: 'unknown', text: '?' }\n let maxUp: number | null = null\n let minDown: number | null = null\n for (const g of guesses) {\n const v = g[key]\n if (!v.value || !v.direction) continue\n const n = Number(v.value)\n if (!Number.isFinite(n)) continue\n if (v.direction === 'up') maxUp = maxUp === null ? n : Math.max(maxUp, n)\n else minDown = minDown === null ? n : Math.min(minDown, n)\n }\n if (maxUp !== null && minDown !== null) {\n const lo = maxUp + 1\n const hi = minDown - 1\n return { key, state: 'range', text: lo >= hi ? String(lo) : `${lo}–${hi}` }\n }\n if (minDown !== null) return { key, state: 'range', text: `< ${minDown}` }\n if (maxUp !== null) return { key, state: 'range', text: `> ${maxUp}` }\n return { key, state: 'unknown', text: '?' }\n })\n}\n\nexport function MysteryTigerGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<MysteryTigerConfig>): JSX.Element {\n const t = ui.games.mysteryTiger\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const guessResults = clientState?.guessResults ?? []\n const alreadyGuessedIds = new Set<number>(guessResults.map(g => g.playerId))\n const shirtEnabled = config?.shirtTileEnabled ?? clientState?.shirtTileEnabled ?? false\n const keys = ATTR_KEYS.filter(k => k !== 'shirtNumber' || shirtEnabled)\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.solved === true ||\n clientState?.failed === true\n\n const guessesUsed = clientState?.guessesUsed ?? guessResults.length\n const totalGuesses = clientState ? clientState.guessesUsed + clientState.guessesRemaining : MAX_GUESSES\n const score = result?.score ?? 0\n const revealName = isOver ? clientState?.revealedPlayerName : undefined\n\n const filtered =\n config && !isOver\n ? config.squadPlayers.filter(\n p => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handleSelect(playerId: number) {\n if (!config || isOver || submitting) return\n const prevGuesses = guessResults.map(g => g.playerId)\n const newGuesses = [...prevGuesses, playerId]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const headerRight = !config ? undefined : isOver ? (\n <Chip variant=\"accent\">{score} {ui.games.unitPts}</Chip>\n ) : (\n <span data-testid=\"mt-chip\">\n <Chip>{ui.games.guess} <span className=\"ss-g-num\">{guessesUsed + 1}</span> / {totalGuesses}</Chip>\n </span>\n )\n\n const segments: SegmentState[] = Array.from({ length: totalGuesses }, (_, i) =>\n i < guessesUsed ? 'done' : i === guessesUsed ? 'current' : 'todo')\n const cols = { gridTemplateColumns: `minmax(0, 1fr) repeat(${keys.length}, 42px)` }\n const known = deriveKnownAttributes(guessResults, keys)\n\n return (\n <div className=\"ss-g-screen ss-g-mt\" data-testid=\"game-screen-mystery-tiger\">\n <GameHeader title={gameTitle({ gameId: 'mystery-tiger' }, ui.games.titles)} eyebrow={t.eyebrow} right={headerRight}\n onBack={onBack} backLabel={ui.back} />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n <div className={`ss-g-mt-card${isOver ? ' ss-g-mt-card--reveal' : ''}`}>\n <div className=\"ss-g-mt-portrait\">\n {revealName ? (\n <PlayerAvatar className=\"ss-g-mt-photo\" name={revealName} imagePath={clientState?.revealedPlayerImagePath} />\n ) : (\n <Silhouette size={150} variant=\"mystery\" />\n )}\n {revealName && <span className=\"ss-g-mt-reveal-name\">{revealName}</span>}\n </div>\n <div className=\"ss-g-mt-known\" style={{ gridTemplateColumns: `repeat(${keys.length}, minmax(0, 1fr))` }}>\n {known.map(k => (\n <div key={k.key} className=\"ss-g-mt-known-cell\">\n <span className=\"ss-g-mt-lab\">{t.labels[k.key]}</span>\n <span className=\"ss-g-mt-known-v\" data-state={k.state} data-testid={`known-${k.key}`}>{k.text}</span>\n </div>\n ))}\n </div>\n </div>\n\n {!isOver && <SegmentProgress segments={segments} ariaLabel={t.progress(guessesUsed, totalGuesses)} />}\n\n {guessResults.length > 0 && (\n <div className=\"ss-g-mt-table\">\n <div className=\"ss-g-mt-thead\" style={cols}>\n <span>{t.yourGuesses}</span>\n {keys.map(k => <span key={k}>{t.labels[k]}</span>)}\n </div>\n {guessResults.map((gr, i) => {\n const name = config.squadPlayers.find(p => p.id === gr.playerId)?.name ?? `#${gr.playerId}`\n const { first, last } = splitName(name)\n return (\n <div key={gr.playerId} className=\"ss-g-mt-row\" style={cols}>\n <div className=\"ss-g-mt-who\">\n <PlayerAvatar className=\"ss-g-mt-av\" name={name} />\n <span className=\"ss-g-mt-names\">\n {first && <span className=\"ss-g-mt-first\">{first}</span>}\n <span className=\"ss-g-mt-last\">{last}</span>\n </span>\n </div>\n {keys.map(key => {\n const v = gr[key]\n const arrow = directionArrow(v)\n return (\n <div\n key={key}\n className=\"ss-g-mt-cell\"\n data-testid={`verdict-${key}-${i}`}\n data-verdict={v.verdict}\n aria-label={`${t.labels[key]}: ${v.value ?? v.verdict}${v.direction ? ` ${v.direction}` : ''}`}\n >\n <span className=\"ss-g-mt-cell-v\" aria-hidden=\"true\">{tileFace(key, v)}</span>\n {arrow && <span className=\"ss-g-mt-cell-dir\" aria-hidden=\"true\">{arrow}</span>}\n </div>\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n\n {!isOver && (\n <div className=\"ss-g-mt-legend\">\n <span><i className=\"ss-g-mt-sw\" data-verdict=\"exact\" />{t.legendMatch}</span>\n <span><i className=\"ss-g-mt-sw\" data-verdict=\"near\" />{t.legendClose}</span>\n <span>▲ {t.legendHigher}</span>\n </div>\n )}\n\n {clientState?.hintLine && !isOver && (\n <div className=\"ss-g-mt-hint\"><IconBulb /><span>{clientState.hintLine}</span></div>\n )}\n\n {isOver && (\n <ResultCard\n tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n title={clientState?.solved ? t.solved : clientState?.failed ? t.failed : ui.games.alreadyPlayedTitle}\n score={score}\n detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={t.optionsLabel}\n options={filtered.map(p => ({\n key: p.id,\n content: <><PlayerAvatar className=\"ss-g-opt-av\" name={p.name} /><span>{p.name}</span></>,\n }))}\n onPick={k => handleSelect(Number(k))}\n />\n )}\n <SearchField id={inputId} label={t.searchLabel} placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={submitting} />\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","// Maps a nationality country-name string (as the games backend emits it) to a flag emoji.\n// UK home nations use subdivision flag emoji; everything else uses regional-indicator pairs.\n// Unmapped nationalities fall back to a short uppercased code so a slot is never blank.\n\nconst FLAGS: Record<string, string> = {\n // UK home nations (subdivision flags)\n england: '🏴\\u{E0067}\\u{E0062}\\u{E0065}\\u{E006E}\\u{E0067}\\u{E007F}',\n scotland: '🏴\\u{E0067}\\u{E0062}\\u{E0073}\\u{E0063}\\u{E0074}\\u{E007F}',\n wales: '🏴\\u{E0067}\\u{E0062}\\u{E0077}\\u{E006C}\\u{E0073}\\u{E007F}',\n 'northern ireland': '🇬🇧',\n 'republic of ireland': '🇮🇪',\n ireland: '🇮🇪',\n 'united kingdom': '🇬🇧',\n\n // Western & Southern Europe\n france: '🇫🇷', spain: '🇪🇸', portugal: '🇵🇹', germany: '🇩🇪', italy: '🇮🇹',\n netherlands: '🇳🇱', belgium: '🇧🇪', switzerland: '🇨🇭', austria: '🇦🇹',\n luxembourg: '🇱🇺', malta: '🇲🇹', cyprus: '🇨🇾',\n andorra: '🇦🇩', liechtenstein: '🇱🇮', 'san marino': '🇸🇲', monaco: '🇲🇨',\n\n // Northern Europe\n denmark: '🇩🇰', sweden: '🇸🇪', norway: '🇳🇴', finland: '🇫🇮', iceland: '🇮🇸',\n\n // Central & Eastern Europe\n poland: '🇵🇱', czechia: '🇨🇿', 'czech republic': '🇨🇿', croatia: '🇭🇷',\n serbia: '🇷🇸', 'bosnia and herzegovina': '🇧🇦', bosnia: '🇧🇦',\n greece: '🇬🇷', romania: '🇷🇴', ukraine: '🇺🇦', russia: '🇷🇺',\n hungary: '🇭🇺', slovakia: '🇸🇰', slovenia: '🇸🇮', bulgaria: '🇧🇬',\n lithuania: '🇱🇹', latvia: '🇱🇻', estonia: '🇪🇪', moldova: '🇲🇩', belarus: '🇧🇾',\n\n // South-East Europe / Balkans\n turkey: '🇹🇷', türkiye: '🇹🇷', albania: '🇦🇱', 'north macedonia': '🇲🇰',\n kosovo: '🇽🇰', montenegro: '🇲🇪',\n\n // Caucasus & Central Asia\n armenia: '🇦🇲', georgia: '🇬🇪', azerbaijan: '🇦🇿',\n kazakhstan: '🇰🇿', uzbekistan: '🇺🇿', kyrgyzstan: '🇰🇬',\n tajikistan: '🇹🇯', turkmenistan: '🇹🇲',\n\n // South America\n brazil: '🇧🇷', argentina: '🇦🇷', uruguay: '🇺🇾', colombia: '🇨🇴', chile: '🇨🇱',\n peru: '🇵🇪', ecuador: '🇪🇨', paraguay: '🇵🇾', venezuela: '🇻🇪', bolivia: '🇧🇴',\n guyana: '🇬🇾', suriname: '🇸🇷',\n\n // North & Central America\n mexico: '🇲🇽', 'united states': '🇺🇸', usa: '🇺🇸', canada: '🇨🇦',\n 'costa rica': '🇨🇷', panama: '🇵🇦', honduras: '🇭🇳', 'el salvador': '🇸🇻',\n guatemala: '🇬🇹', nicaragua: '🇳🇮',\n\n // Caribbean\n jamaica: '🇯🇲', cuba: '🇨🇺', haiti: '🇭🇹', 'dominican republic': '🇩🇴',\n 'trinidad and tobago': '🇹🇹', trinidad: '🇹🇹',\n 'curaçao': '🇨🇼', curacao: '🇨🇼',\n barbados: '🇧🇧',\n\n // West Africa\n nigeria: '🇳🇬', ghana: '🇬🇭', senegal: '🇸🇳',\n ivorycoast: '🇨🇮', \"cote d'ivoire\": '🇨🇮', \"côte d'ivoire\": '🇨🇮', 'ivory coast': '🇨🇮',\n cameroon: '🇨🇲', mali: '🇲🇱', guinea: '🇬🇳', 'guinea-bissau': '🇬🇼',\n 'sierra leone': '🇸🇱', liberia: '🇱🇷', 'cape verde': '🇨🇻', 'gambia': '🇬🇲',\n mauritania: '🇲🇷', togo: '🇹🇬', benin: '🇧🇯', 'burkina faso': '🇧🇫', niger: '🇳🇪',\n\n // Central & East Africa\n 'dr congo': '🇨🇩', 'democratic republic of the congo': '🇨🇩', 'congo dr': '🇨🇩',\n 'republic of the congo': '🇨🇬', congo: '🇨🇬', 'congo republic': '🇨🇬', 'congo-brazzaville': '🇨🇬',\n 'central african republic': '🇨🇫', gabon: '🇬🇦', 'equatorial guinea': '🇬🇶',\n 'south africa': '🇿🇦', angola: '🇦🇴', namibia: '🇳🇦', botswana: '🇧🇼',\n zimbabwe: '🇿🇼', zambia: '🇿🇲', malawi: '🇲🇼', mozambique: '🇲🇿',\n tanzania: '🇹🇿', kenya: '🇰🇪', uganda: '🇺🇬', rwanda: '🇷🇼',\n ethiopia: '🇪🇹', eritrea: '🇪🇷', djibouti: '🇩🇯', somalia: '🇸🇴',\n sudan: '🇸🇩', 'south sudan': '🇸🇸', chad: '🇹🇩',\n lesotho: '🇱🇸', eswatini: '🇸🇿', swaziland: '🇸🇿',\n madagascar: '🇲🇬', mauritius: '🇲🇺', comoros: '🇰🇲', seychelles: '🇸🇨',\n\n // North Africa\n egypt: '🇪🇬', morocco: '🇲🇦', algeria: '🇩🇿', tunisia: '🇹🇳',\n\n // Middle East\n 'saudi arabia': '🇸🇦', iran: '🇮🇷', iraq: '🇮🇶', lebanon: '🇱🇧',\n syria: '🇸🇾', jordan: '🇯🇴', qatar: '🇶🇦', 'united arab emirates': '🇦🇪', uae: '🇦🇪',\n kuwait: '🇰🇼', bahrain: '🇧🇭', oman: '🇴🇲', yemen: '🇾🇪',\n israel: '🇮🇱', palestine: '🇵🇸',\n\n // East & South-East Asia\n japan: '🇯🇵', 'south korea': '🇰🇷', korea: '🇰🇷', china: '🇨🇳',\n india: '🇮🇳', thailand: '🇹🇭', indonesia: '🇮🇩', malaysia: '🇲🇾',\n philippines: '🇵🇭', vietnam: '🇻🇳',\n\n // Oceania\n australia: '🇦🇺', 'new zealand': '🇳🇿', fiji: '🇫🇯',\n}\n\nexport function nationalityFlag(nationality: string | null | undefined): string {\n if (!nationality) return '🏳️'\n const key = nationality.trim().toLowerCase()\n return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase()\n}\n\n// A nationality without a flag falls back to its first three letters (\"BEN\"); callers size that\n// text down so it fits the disc a flag emoji would fill.\nexport function isNationCode(flag: string): boolean {\n return /^[A-Z]{1,3}$/.test(flag)\n}\n","import { useState } from 'react'\n\n// Two-letter initials from a display name: first + last token, or the first two letters\n// of a single-token name. Used as the photo fallback so an avatar circle is never a bare ball.\nexport function initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n const first = parts[0]\n if (!first) return '?'\n const last = parts[parts.length - 1]\n if (parts.length === 1 || !last) return first.slice(0, 2).toUpperCase()\n return ((first[0] ?? '') + (last[0] ?? '')).toUpperCase()\n}\n\n// The data provider (Sportmonks) serves a generic grey silhouette at .../placeholder.png for\n// people it has no photo of. Treat it as no photo so the fallback (initials, shield) shows.\nexport function isPlaceholderImage(url: string | null | undefined): boolean {\n return !!url && /\\/placeholder\\.(png|jpe?g|svg|webp)(\\?|$)/i.test(url)\n}\n\n// Circular player avatar. Shows the photo when an imagePath is present and loads; otherwise\n// (missing URL or a broken image) falls back to the player's initials on the same circle.\nexport function PlayerAvatar({\n name,\n imagePath,\n className,\n}: {\n name: string\n imagePath?: string\n className: string\n}): JSX.Element {\n const [failed, setFailed] = useState(false)\n const showImage = Boolean(imagePath) && !isPlaceholderImage(imagePath) && !failed\n\n return (\n <div className={className} aria-hidden=\"true\">\n {showImage ? (\n <img src={imagePath} alt=\"\" loading=\"lazy\" onError={() => setFailed(true)} />\n ) : (\n <span className=\"ss-w-av-initials\">{initialsOf(name)}</span>\n )}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { IconChevronLeft } from './icons'\n\nexport function GameHeader({ title, eyebrow, right, onBack, backLabel }: {\n title: string; eyebrow?: string; right?: ReactNode; onBack?: () => void; backLabel: string\n}): JSX.Element {\n return (\n <div className=\"ss-g-head\">\n {onBack && (\n <button type=\"button\" className=\"ss-g-back\" aria-label={backLabel} onClick={onBack}>\n <IconChevronLeft />\n </button>\n )}\n <div className=\"ss-g-head-text\">\n {eyebrow && <span className=\"ss-g-eyebrow\">{eyebrow}</span>}\n <h2 className=\"ss-g-title\">{title}</h2>\n </div>\n {right && <div className=\"ss-g-head-right\">{right}</div>}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\n\nexport type SegmentState = 'done' | 'current' | 'todo' | 'correct' | 'wrong'\n\nexport function SegmentProgress({ segments, ariaLabel, leftLabel, rightLabel, right }: {\n segments: SegmentState[]; ariaLabel: string; leftLabel?: string; rightLabel?: string; right?: ReactNode\n}): JSX.Element {\n return (\n <div className=\"ss-g-progress\">\n <div className=\"ss-g-progress-main\">\n {(leftLabel || rightLabel) && (\n <div className=\"ss-g-progress-labels\">\n <span>{leftLabel}</span><span className=\"ss-g-progress-rl\">{rightLabel}</span>\n </div>\n )}\n <div className=\"ss-g-segs\" role=\"img\" aria-label={ariaLabel}\n style={{ gridTemplateColumns: `repeat(${segments.length}, minmax(0, 1fr))` }}>\n {segments.map((s, i) => <span key={i} className=\"ss-g-seg\" data-state={s} />)}\n </div>\n </div>\n {right}\n </div>\n )\n}\n","import type { KeyboardEvent, Ref } from 'react'\nimport { IconSearch } from './icons'\n\nexport function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown }: {\n id: string; label: string; labelHidden?: boolean; placeholder: string; value: string\n onChange: (v: string) => void; disabled?: boolean; inputRef?: Ref<HTMLInputElement>\n onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void\n}): JSX.Element {\n return (\n <div className=\"ss-g-search\">\n <label htmlFor={id} className={labelHidden ? 'ss-g-sr' : 'ss-g-search-label'}>{label}</label>\n <div className=\"ss-g-search-box\">\n <IconSearch />\n <input id={id} ref={inputRef} type=\"text\" autoComplete=\"off\" placeholder={placeholder} value={value}\n disabled={disabled} onKeyDown={onKeyDown} onChange={e => onChange(e.target.value)} />\n </div>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nexport function FooterBar({ children }: { children: ReactNode }): JSX.Element {\n return <div className=\"ss-g-footer\">{children}</div>\n}\n","export function Silhouette({ size, variant = 'default' }: { size: number; variant?: 'default' | 'selected' | 'mystery' }): JSX.Element {\n return (\n <span className={`ss-g-sil ss-g-sil--${variant}`} style={{ width: size, height: size }} aria-hidden=\"true\">\n <svg width={size * 0.86} height={size * 0.86} viewBox=\"0 0 100 100\">\n <circle cx=\"50\" cy=\"40\" r=\"19\" fill=\"currentColor\" />\n <path d=\"M12 100c0-23 17-38 38-38s38 15 38 38z\" fill=\"currentColor\" />\n </svg>\n {variant === 'mystery' && <span className=\"ss-g-sil-q\">?</span>}\n </span>\n )\n}\n","import type { ButtonHTMLAttributes } from 'react'\n\nexport type GameButtonVariant = 'primary' | 'outline' | 'accent-outline' | 'surface'\n\nexport function GameButton({ variant = 'primary', block = false, className, type = 'button', ...rest }:\n ButtonHTMLAttributes<HTMLButtonElement> & { variant?: GameButtonVariant; block?: boolean }): JSX.Element {\n const cls = `ss-g-btn ss-g-btn--${variant}${block ? ' ss-g-btn--block' : ''}${className ? ` ${className}` : ''}`\n return <button type={type} className={cls} {...rest} />\n}\n","import type { UiConfig } from '../../../config'\nimport { GameButton } from './GameButton'\n\nexport type ResultTone = 'win' | 'lose' | 'neutral'\n\n// Spec §6: every game's solved / lost / already-played state uses this one card.\nexport function ResultCard({ tone, title, score, detail, onBack, ui }: {\n tone: ResultTone; title: string; score?: number; detail?: string; onBack?: () => void; ui: UiConfig\n}): JSX.Element {\n return (\n <div className=\"ss-g-result\" data-tone={tone} role=\"status\">\n <span className=\"ss-g-result-title\">{title}</span>\n {score !== undefined && (\n <span className=\"ss-g-result-score\"><span className=\"ss-g-result-num\">{score}</span>{ui.games.unitPts}</span>\n )}\n {detail && <span className=\"ss-g-result-detail\">{detail}</span>}\n {onBack && <GameButton variant=\"outline\" onClick={onBack}>{ui.games.backToGames}</GameButton>}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\n\nexport interface OptionItem { key: string | number; content: ReactNode }\n\n// Typeahead results. Real <button>s (keyboard reachable) carrying role=option inside a listbox.\nexport function OptionList({ label, options, onPick }: {\n label: string; options: OptionItem[]; onPick: (key: string | number) => void\n}): JSX.Element {\n return (\n <div className=\"ss-g-opts\" role=\"listbox\" aria-label={label}>\n {options.map(o => (\n <button key={o.key} type=\"button\" role=\"option\" aria-selected={false} className=\"ss-g-opt\" onClick={() => onPick(o.key)}>\n {o.content}\n </button>\n ))}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport type { GameScreenProps, HolConfig, HolClientState } from './types'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { StatStack } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconArrowUp, IconArrowDown, IconCheck, IconClose } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Points awarded per correct pick — mirrors HigherOrLowerContentGenerator.PointsPerCorrect.\nconst POINTS_PER_CORRECT = 10\n\nfunction parseClientState(json: string | null | undefined): HolClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as HolClientState\n } catch {\n return null\n }\n}\n\nfunction PlayerCard({ name, imagePath, highlight, children }: {\n name: string; imagePath?: string; highlight?: boolean; children: ReactNode\n}): JSX.Element {\n const { first, last } = splitName(name)\n return (\n <div className={`ss-g-hl-card${highlight ? ' ss-g-hl-card--b' : ''}`}>\n <div className=\"ss-g-hl-photo-wrap\">\n {imagePath\n ? <PlayerAvatar className=\"ss-g-hl-photo\" name={name} imagePath={imagePath} />\n : <Silhouette size={150} />}\n </div>\n <div className=\"ss-g-hl-info\">\n {first && <span className=\"ss-g-hl-first\">{first}</span>}\n <span className=\"ss-g-hl-surname\">{last}</span>\n {children}\n </div>\n </div>\n )\n}\n\nexport function HigherOrLowerGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<HolConfig>): JSX.Element {\n const t = ui.games.higherOrLower\n const clientState = parseClientState(result?.clientStateJson)\n\n const answeredPairs = clientState?.answeredPairs ?? []\n const answeredCount = answeredPairs.length\n const runEndedWrong = answeredPairs.some(p => !p.wasCorrect)\n const allPairsAnswered = config != null && answeredCount >= config.pairs.length\n const isOver = result?.alreadyPlayed === true || runEndedWrong || allPairsAnswered\n\n const currentPair = config && !isOver ? config.pairs[answeredCount] ?? null : null\n\n const correctCount = answeredPairs.filter(p => p.wasCorrect).length\n // A returning fan may come back with no client state: show the stored play score then.\n const score = clientState?.score ?? result?.score ?? 0\n const runLength = clientState?.runLength ?? 0\n\n const lastAnswer = answeredPairs[answeredPairs.length - 1]\n const lastAnswerPair = lastAnswer ? config?.pairs.find(p => p.pairIndex === lastAnswer.pairIndex) : undefined\n\n function handlePick(pick: 'higher' | 'lower') {\n if (!config || isOver || submitting || !currentPair) return\n const prevAnswers = answeredPairs.map(p => ({ pairIndex: p.pairIndex, pick: p.pick }))\n const newAnswers = [...prevAnswers, { pairIndex: currentPair.pairIndex, pick }]\n onSubmit(JSON.stringify({ answers: newAnswers }))\n }\n\n return (\n <div className=\"ss-g-screen ss-g-hl\" data-testid=\"game-screen-higher-or-lower\">\n <GameHeader\n title={gameTitle({ gameId: 'higher-or-lower' }, ui.games.titles)}\n eyebrow={t.eyebrow(POINTS_PER_CORRECT)}\n right={config ? <StatStack value={runLength} label={t.streak} /> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n <div className=\"ss-g-hl-prompt\" data-testid=\"hol-prompt\">\n <span className=\"ss-g-hl-prompt-q\">{t.whoHadMore}</span>\n <span className=\"ss-g-hl-prompt-stat\">{config.statLabel}</span>\n <span className=\"ss-g-hl-prompt-season\">{t.season(config.seasonLabel)}</span>\n </div>\n\n {currentPair && (\n <div className=\"ss-g-hl-pair\">\n <PlayerCard name={currentPair.playerAName} imagePath={currentPair.playerAImagePath}>\n <span className=\"ss-g-hl-value\">{currentPair.playerAValue}</span>\n <span className=\"ss-g-hl-stat\">{config.statLabel}</span>\n </PlayerCard>\n <span className=\"ss-g-hl-vs\" aria-hidden=\"true\">{t.vs}</span>\n <PlayerCard name={currentPair.playerBName} imagePath={currentPair.playerBImagePath} highlight>\n <div className=\"ss-g-hl-btns\">\n <GameButton variant=\"primary\" disabled={submitting} onClick={() => handlePick('higher')}>\n <IconArrowUp size={16} />{t.higher}\n </GameButton>\n <GameButton variant=\"outline\" disabled={submitting} onClick={() => handlePick('lower')}>\n <IconArrowDown size={16} />{t.lower}\n </GameButton>\n </div>\n </PlayerCard>\n </div>\n )}\n\n {lastAnswer && lastAnswerPair && (\n <p className=\"ss-g-hl-feedback\" data-testid=\"hol-last\" data-correct={lastAnswer.wasCorrect ? 'true' : 'false'}>\n {lastAnswer.wasCorrect ? <IconCheck /> : <IconClose />}\n {t.lastAnswer(splitName(lastAnswerPair.playerBName).last, lastAnswer.playerBValue)}\n </p>\n )}\n\n {isOver && (\n <ResultCard\n tone={runEndedWrong ? 'lose' : allPairsAnswered ? 'win' : 'neutral'}\n title={runEndedWrong ? t.runOver : allPairsAnswered ? t.perfectRun : ui.games.alreadyPlayedTitle}\n score={score}\n detail={clientState ? t.runDetail(correctCount) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n <div className=\"ss-g-hl-foot\">\n <div className=\"ss-g-hl-dots\" role=\"img\" aria-label={t.answersSoFar(answeredCount, config.pairs.length)}>\n {config.pairs.map((p, i) => {\n const a = answeredPairs[i]\n return <span key={p.pairIndex} className=\"ss-g-hl-dot\" data-state={a ? (a.wasCorrect ? 'correct' : 'wrong') : 'todo'} />\n })}\n </div>\n <span className=\"ss-g-hl-pts\">\n <span data-testid=\"hol-score\">{score}</span> <span className=\"ss-g-hl-pts-unit\">{ui.games.unitPts}</span>\n </span>\n </div>\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, CareerPathConfig, CareerPathClientState, CareerPathClubSpell } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { IconLock } from './ui/icons'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): CareerPathClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as CareerPathClientState\n } catch {\n return null\n }\n}\n\n// \"2012–2015\", \"2012\" when single-season or open-ended, '' when the generator had no start year.\nexport function spellYears(spell: CareerPathClubSpell): string {\n if (!spell.startYear) return ''\n if (spell.endYear && spell.endYear !== spell.startYear) return `${spell.startYear}–${spell.endYear}`\n return String(spell.startYear)\n}\n\nexport function CareerPathGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n}: GameScreenProps<CareerPathConfig>): JSX.Element {\n const s = ui.games.careerPath\n const title = gameTitle({ gameId: 'career-path' }, ui.games.titles)\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyGuessedIds = new Set<number>(clientState?.guessResults.map(g => g.playerId) ?? [])\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.solved === true ||\n clientState?.failed === true\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-career-path\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const visiblePath = clientState?.visiblePath ?? config.initialPath\n const totalClubs = clientState?.totalClubs ?? config.totalClubs\n const hidden = isOver ? 0 : Math.max(0, totalClubs - visiblePath.length)\n\n const filtered = !isOver\n ? config.typeaheadPool.filter(\n p => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handleSelect(playerId: number): void {\n if (!config || isOver || submitting) return\n const prevGuesses = clientState?.guessResults.map(g => g.playerId) ?? []\n const newGuesses = [...prevGuesses, playerId]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const right = !isOver && clientState\n ? (\n <span data-testid=\"cp-guess-chip\">\n <Chip variant=\"neutral\">\n {ui.games.guess} <span className=\"ss-g-num\">{clientState.guessesUsed + 1}</span> / {clientState.guessesUsed + clientState.guessesRemaining}\n </Chip>\n </span>\n )\n : undefined\n\n const outcome = clientState?.solved ? s.solved : clientState?.failed ? s.failed : ui.games.done\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-career-path\">\n <GameHeader title={title} eyebrow={s.eyebrow} right={right} onBack={onBack} backLabel={ui.back} />\n\n <div className=\"ss-g-body\">\n <div className=\"ss-g-cp-card\">\n {isOver && clientState?.revealedPlayerName ? (\n <PlayerAvatar className=\"ss-g-cp-photo\" name={clientState.revealedPlayerName} imagePath={clientState.revealedPlayerImagePath} />\n ) : (\n <Silhouette size={64} variant={isOver ? 'default' : 'mystery'} />\n )}\n <div className=\"ss-g-cp-card-text\">\n <span className=\"ss-g-cp-card-title\">\n {isOver && clientState?.revealedPlayerName ? clientState.revealedPlayerName : s.mysteryPlayer}\n </span>\n {clientState?.hintLine ? (\n <span className=\"ss-g-cp-hint\">{clientState.hintLine}</span>\n ) : !isOver ? (\n <span className=\"ss-g-cp-locks\">\n <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockPosition}</Chip>\n <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockNationality}</Chip>\n </span>\n ) : null}\n </div>\n </div>\n\n <ol className=\"ss-g-cp-line\">\n {visiblePath.map((spell, i) => {\n const years = i === 0 ? s.firstClub : spellYears(spell)\n return (\n <li key={`${spell.clubName}-${i}`} className=\"ss-g-cp-step\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile\"><CrestShield src={spell.crestUrl} name={spell.clubName} size={30} /></span>\n <span className=\"ss-g-cp-conn\" aria-hidden=\"true\" />\n </span>\n <span className=\"ss-g-cp-step-text\">\n <span className=\"ss-g-cp-club\">{spell.clubName}</span>\n <span className=\"ss-g-cp-sub\">\n <span className=\"ss-g-cp-years\">{years}</span>\n {spell.isLoan && (\n <>\n {years ? ' · ' : ''}\n <span className=\"ss-g-cp-loan\">{s.loan}</span>\n </>\n )}\n </span>\n </span>\n </li>\n )\n })}\n {hidden > 0 && (\n <li className=\"ss-g-cp-step ss-g-cp-step--hidden\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile ss-g-cp-tile--locked\"><IconLock size={18} /></span>\n {hidden > 1 && <span className=\"ss-g-cp-conn ss-g-cp-conn--faint\" aria-hidden=\"true\" />}\n </span>\n <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.nextClubHidden}</span></span>\n </li>\n )}\n {hidden > 1 && (\n <li className=\"ss-g-cp-step ss-g-cp-step--more\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile ss-g-cp-tile--faint\"><IconLock size={18} /></span>\n </span>\n <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.moreClubs(hidden - 1)}</span></span>\n </li>\n )}\n </ol>\n\n {isOver && (\n <ResultCard\n tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n title={outcome}\n score={result?.score}\n detail={clientState ? s.guessesLine(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={s.searchLabel}\n options={filtered.map(p => ({\n key: p.id,\n content: <><PlayerAvatar className=\"ss-g-opt-av\" name={p.name} /><span>{p.name}</span></>,\n }))}\n onPick={k => handleSelect(Number(k))}\n />\n )}\n <SearchField\n id={inputId}\n label={s.searchLabel}\n placeholder={s.searchPlaceholder}\n value={query}\n onChange={setQuery}\n disabled={submitting}\n />\n </FooterBar>\n )}\n </div>\n )\n}\n","import { useState } from 'react'\nimport { isPlaceholderImage } from '../PlayerAvatar'\n\nexport function CrestShield({ src, name, size = 28 }: { src?: string | null; name: string; size?: number }): JSX.Element {\n const [failed, setFailed] = useState(false)\n if (src && !isPlaceholderImage(src) && !failed) {\n return <img className=\"ss-g-crest\" src={src} alt={name} width={size} height={size} loading=\"lazy\" onError={() => setFailed(true)} />\n }\n return (\n <svg className=\"ss-g-crest ss-g-crest--ph\" width={size} height={size * 32 / 28} viewBox=\"0 0 28 32\" role=\"img\" aria-label={name}>\n <path d=\"M2 3h24v12c0 9-6 14-12 17C8 29 2 24 2 15z\" fill=\"currentColor\" />\n </svg>\n )\n}\n","import React, { useEffect, useId, useRef, useState } from 'react'\nimport type { GameScreenProps, BeatTheGridConfig, BtgClientState, BtgCellResult, BtgCriterionMeta } from './types'\nimport type { UiConfig } from '../../config'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { SearchField } from './ui/SearchField'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport {\n IconCalendar, IconBall, IconBoot, IconGloves, IconShield, IconFlag, IconCheck, IconClose, IconPlus,\n} from './ui/icons'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { CrestShield } from './ui/CrestShield'\nimport { nationalityFlag } from './nationFlags'\n\nexport interface PlayerEntry {\n id: number\n name: string\n imagePath?: string\n}\n\n// playerPool comes from config.playerPool, threaded through by GameScreenHost.\nexport interface BeatTheGridGameProps extends GameScreenProps<BeatTheGridConfig> {\n playerPool: PlayerEntry[]\n}\n\ninterface ActiveCell {\n row: number\n col: number\n}\n\nexport type CriterionIconKind = 'calendar' | 'ball' | 'boot' | 'gloves' | 'shield' | 'flag'\n\n// Header icon from the criterion key when present (stable across languages), else the English\n// label text of a pre-u400 game; unknown criteria (nationality groups, yellow cards) get the flag.\nexport function criterionIconKind(label: string, key?: string): CriterionIconKind {\n const l = (key ?? label).toLowerCase()\n if (l.includes('app')) return 'calendar'\n if (l.includes('goal')) return 'ball'\n if (l.includes('assist')) return 'boot'\n if (l.includes('clean')) return 'gloves'\n if (l.includes('tackle')) return 'shield'\n return 'flag'\n}\n\n// The abbreviation map is keyed by the English position; a key like \"games.grid.row.forward\"\n// names it even when the label arrives translated (\"Forvet\").\nexport function rowAbbrev(label: string, map: Record<string, string>, key?: string): string {\n const suffix = key?.split('.').pop()\n const english = suffix ? suffix.charAt(0).toUpperCase() + suffix.slice(1) : label\n return map[english] ?? map[label] ?? label\n}\n\nfunction CriterionIcon({ kind }: { kind: CriterionIconKind }): JSX.Element {\n switch (kind) {\n case 'calendar': return <IconCalendar />\n case 'ball': return <IconBall />\n case 'boot': return <IconBoot />\n case 'gloves': return <IconGloves />\n case 'shield': return <IconShield />\n default: return <IconFlag />\n }\n}\n\n// Renders the visual prefix of a header cell based on BtgCriterionMeta when present.\n// Without meta, falls back to the stat/nationality icon (today's behaviour).\nfunction HeaderVisual({ label, textKey: iKey, meta }: { label: string; textKey?: string; meta?: BtgCriterionMeta }): JSX.Element {\n if (!meta) {\n return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n }\n switch (meta.kind) {\n case 'club':\n return <CrestShield src={meta.imageUrl} name={label} size={24} />\n case 'coach':\n return <PlayerAvatar name={label} imagePath={meta.imageUrl} className=\"ss-g-btg-coach-av\" />\n case 'country':\n return <span className=\"ss-g-btg-hdr-flag\" aria-hidden=\"true\">{nationalityFlag(meta.country ?? label)}</span>\n case 'position':\n // Full localized label only (no icon, no abbreviation); the caller omits the icon slot.\n return <></>\n default:\n return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n }\n}\n\nfunction parseClientState(json: string | null | undefined): BtgClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as BtgClientState\n } catch {\n return null\n }\n}\n\nfunction findCellResult(cells: BtgCellResult[], row: number, col: number): BtgCellResult | undefined {\n return cells.find(c => c.row === row && c.col === col)\n}\n\n// Compact initials for a placed player, e.g. \"Andrew Robertson\" → \"A. Robertson\".\n// Falls back to an empty string when the name is unknown.\nfunction shortName(name: string | undefined): string {\n if (!name) return ''\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n if (parts.length === 0) return ''\n const first = parts[0]!\n if (parts.length === 1) return first\n const last = parts[parts.length - 1]!\n return `${first.charAt(0)}. ${last}`\n}\n\nfunction SearchSheet({\n row,\n col,\n rowLabel,\n colLabel,\n playerPool,\n alreadyFilledIds,\n onPick,\n onDismiss,\n ui,\n}: {\n row: number\n col: number\n rowLabel: string\n colLabel: string\n playerPool: PlayerEntry[]\n alreadyFilledIds: Set<number>\n onPick: (row: number, col: number, playerId: number) => void\n onDismiss: () => void\n ui: UiConfig\n}): JSX.Element {\n const s = ui.games.beatTheGrid\n const [query, setQuery] = useState('')\n const inputId = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n\n useEffect(() => { inputRef.current?.focus() }, [row, col])\n\n const filtered = playerPool.filter(\n p => !alreadyFilledIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n\n return (\n <div className=\"ss-g-btg-sheet\" data-testid=\"btg-search-sheet\">\n <div className=\"ss-g-btg-sheet-hdr\">\n <Chip variant=\"neutral\">{rowLabel}</Chip>\n <span className=\"ss-g-btg-sheet-x\" aria-hidden=\"true\"><IconClose size={12} /></span>\n <Chip variant=\"accent\">{colLabel}</Chip>\n <button\n type=\"button\"\n className=\"ss-g-btg-sheet-close\"\n data-testid=\"btg-sheet-dismiss\"\n aria-label={s.closeSearch}\n onClick={onDismiss}\n >\n <IconClose />\n </button>\n </div>\n {playerPool.length === 0 ? (\n <div className=\"ss-g-btg-sheet-empty\">{s.emptyPool}</div>\n ) : (\n <>\n <SearchField\n id={inputId}\n label={s.searchLabel(rowLabel, colLabel)}\n labelHidden\n placeholder={s.searchPlaceholder}\n value={query}\n onChange={setQuery}\n inputRef={inputRef}\n />\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={s.searchLabel(rowLabel, colLabel)}\n options={filtered.map(p => ({\n key: p.id,\n content: (\n <>\n <PlayerAvatar name={p.name} imagePath={p.imagePath} className=\"ss-g-opt-av\" />\n <span className=\"ss-g-btg-result-name\">{p.name}</span>\n <span className=\"ss-g-btg-result-plus\" aria-hidden=\"true\"><IconPlus size={18} /></span>\n </>\n ),\n }))}\n onPick={k => onPick(row, col, Number(k))}\n />\n )}\n </>\n )}\n </div>\n )\n}\n\nexport function BeatTheGridGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n playerPool,\n}: BeatTheGridGameProps): JSX.Element {\n const s = ui.games.beatTheGrid\n const title = gameTitle({ gameId: 'beat-the-grid' }, ui.games.titles)\n const [activeCell, setActiveCell] = useState<ActiveCell | null>(null)\n\n const clientState = parseClientState(result?.clientStateJson)\n const filledCells = clientState?.cells ?? []\n\n const isLocked =\n result?.alreadyPlayed === true ||\n clientState?.isComplete === true\n\n const alreadyFilledIds = new Set<number>(filledCells.map(c => c.playerId))\n\n function handleCellClick(row: number, col: number): void {\n if (isLocked || submitting) return\n const alreadyFilled = findCellResult(filledCells, row, col)\n if (alreadyFilled) return\n setActiveCell({ row, col })\n }\n\n function handlePick(row: number, col: number, playerId: number): void {\n setActiveCell(null)\n const prevCells = filledCells.map(c => ({ row: c.row, col: c.col, playerId: c.playerId }))\n const newCells = [...prevCells, { row, col, playerId }]\n onSubmit(JSON.stringify({ cells: newCells }))\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-beat-the-grid\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const rows = config.rows\n const cols = config.cols\n const total = rows.length * cols.length\n const correctCount = filledCells.filter(c => c.isCorrect).length\n const wrongCount = filledCells.length - correctCount\n const segments: SegmentState[] = Array.from({ length: total }, (_, i) =>\n i < correctCount ? 'correct' : i < correctCount + wrongCount ? 'wrong' : 'todo',\n )\n // A returning fan may come back with no client state: show the stored play score then.\n const totalScore = clientState?.totalScore ?? result?.score ?? 0\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-beat-the-grid\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress\n segments={segments}\n ariaLabel={s.progressAria(filledCells.length, total)}\n leftLabel={s.filled(filledCells.length, total)}\n rightLabel={s.toGo(Math.max(0, total - filledCells.length))}\n right={<Chip variant=\"accent\">{`${totalScore} ${ui.games.unitPts}`}</Chip>}\n />\n\n <div className=\"ss-g-body\">\n <div\n className={activeCell !== null ? 'ss-g-btg-grid ss-g-btg-grid--fit' : 'ss-g-btg-grid'}\n style={{\n gridTemplateColumns: `64px repeat(${cols.length}, minmax(0, 1fr))`,\n gridTemplateRows: `minmax(44px, 60px) repeat(${rows.length}, minmax(44px, 98px))`,\n } as React.CSSProperties}\n role=\"grid\"\n >\n <div className=\"ss-g-btg-corner\" />\n {cols.map((col, colIdx) => {\n const colMeta = config.colsMeta?.[colIdx]\n return (\n <div key={col} className=\"ss-g-btg-colhdr\" data-meta={colMeta ? 'true' : undefined}>\n <HeaderVisual label={col} textKey={config.colsI18n?.[colIdx]?.key} meta={colMeta} />\n <span>{col}</span>\n </div>\n )\n })}\n {rows.map((rowLabel, rowIdx) => {\n const rowMeta = config.rowsMeta?.[rowIdx]\n const abbr = rowAbbrev(rowLabel, s.rowAbbrev, config.rowsI18n?.[rowIdx]?.key)\n // With meta, render using HeaderVisual (empty for position) + the full label.\n // Without meta, use the abbreviation pattern (existing behaviour).\n const rowHeaderContent = rowMeta ? (\n <>\n <HeaderVisual label={rowLabel} textKey={config.rowsI18n?.[rowIdx]?.key} meta={rowMeta} />\n <span>{rowLabel}</span>\n </>\n ) : abbr === rowLabel ? (\n <span>{rowLabel}</span>\n ) : (\n <>\n <span aria-hidden=\"true\">{abbr}</span>\n <span className=\"ss-g-sr\">{rowLabel}</span>\n </>\n )\n return (\n <React.Fragment key={rowIdx}>\n <div className=\"ss-g-btg-rowhdr\" data-meta={rowMeta ? 'true' : undefined}>\n {rowHeaderContent}\n </div>\n {cols.map((colLabel, colIdx) => {\n const filled = findCellResult(filledCells, rowIdx, colIdx)\n const isActive = activeCell?.row === rowIdx && activeCell?.col === colIdx\n const state = filled ? (filled.isCorrect ? 'correct' : 'wrong') : isActive ? 'active' : 'empty'\n return (\n <button\n key={`cell-${rowIdx}-${colIdx}`}\n type=\"button\"\n data-testid={`btg-cell-${rowIdx}-${colIdx}`}\n data-state={state}\n aria-label={\n filled\n ? s.cellFilled(rowLabel, colLabel, playerPool.find(p => p.id === filled.playerId)?.name ?? '', filled.isCorrect ? s.correct : s.wrong)\n : s.pickCell(rowLabel, colLabel)\n }\n aria-pressed={isActive}\n className=\"ss-g-btg-cell\"\n disabled={isLocked || submitting}\n onClick={() => handleCellClick(rowIdx, colIdx)}\n >\n {filled ? (\n <>\n <span\n className={`ss-g-btg-badge ss-g-btg-badge--${filled.isCorrect ? 'correct' : 'wrong'}`}\n role=\"img\"\n aria-label={filled.isCorrect ? s.correct : s.wrong}\n >\n {filled.isCorrect ? <IconCheck size={11} /> : <IconClose size={11} />}\n </span>\n <span className=\"ss-g-btg-rarity\">{filled.rarityScore}</span>\n {(() => {\n const entry = playerPool.find(p => p.id === filled.playerId)\n return (\n <PlayerAvatar\n name={entry?.name ?? ''}\n imagePath={entry?.imagePath}\n className=\"ss-g-btg-av\"\n />\n )\n })()}\n <span className=\"ss-g-btg-name\">\n {shortName(playerPool.find(p => p.id === filled.playerId)?.name)}\n </span>\n </>\n ) : (\n <span className=\"ss-g-btg-plus\" aria-hidden=\"true\"><IconPlus size={22} /></span>\n )}\n </button>\n )\n })}\n </React.Fragment>\n )\n })}\n </div>\n\n {isLocked && (\n <ResultCard\n tone=\"neutral\"\n title={s.complete}\n score={totalScore}\n detail={s.summary(correctCount, filledCells.length)}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {activeCell !== null && (\n <div className=\"ss-g-btg-pin\">\n <SearchSheet\n key={`${activeCell.row}-${activeCell.col}`}\n row={activeCell.row}\n col={activeCell.col}\n rowLabel={rows[activeCell.row] ?? ''}\n colLabel={cols[activeCell.col] ?? ''}\n playerPool={playerPool}\n alreadyFilledIds={alreadyFilledIds}\n onPick={handlePick}\n onDismiss={() => setActiveCell(null)}\n ui={ui}\n />\n </div>\n )}\n </div>\n )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, GuessTheXiConfig, XiClientState } from './types'\nimport { isNationCode, nationalityFlag } from './nationFlags'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { CrestShield } from './ui/CrestShield'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { toRows, formationLabel, positionsBySlot } from './ui/formations'\nimport { PlayerAvatar } from './PlayerAvatar'\n\n// Total guesses allowed per day. Kept in sync with GuessTheXiScorer.MaxGuesses on the backend.\nconst MAX_GUESSES = 3\n\nfunction parseClientState(json: string | null | undefined): XiClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as XiClientState\n } catch {\n return null\n }\n}\n\nexport function GuessTheXiGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<GuessTheXiConfig>): JSX.Element {\n const t = ui.games.guessTheXi\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.status === 'solved' ||\n clientState?.status === 'failed'\n const solved = clientState?.status === 'solved'\n const failed = clientState?.status === 'failed'\n\n const guessedTeamIds = new Set<number>(clientState?.guessHistory.map(g => g.teamId) ?? [])\n const rows = config ? toRows(config.positions) : []\n // Only name the shape when the data is a real formation; a neutral fallback grid has no shape.\n const formation = config?.hasRealFormation ? formationLabel(rows) : ''\n // Position label under every node (GK/CB/CM/ST…), derived from the formation coordinates only.\n const posBySlot = config?.hasRealFormation ? positionsBySlot(formation, rows) : new Map<string, string>()\n\n // A wrong guess can earn a player-name reveal; pin each to its slot so the surname replaces that\n // node's position tag. Position-type reveals are redundant now that every position is shown.\n const nameBySlot = new Map<string, string>()\n ;(clientState?.earnedReveals ?? []).forEach(r => { if (r.slot && r.type !== 'position') nameBySlot.set(r.slot, r.value) })\n\n // When the game ends and a lineup is present, map slot → lineup entry for photo + name display.\n const lineupBySlot = new Map<string, { name: string; imagePath?: string }>()\n ;(clientState?.lineup ?? []).forEach(e => { lineupBySlot.set(e.slot, { name: e.name, imagePath: e.imagePath }) })\n\n const filtered =\n config && !isOver\n ? config.teamPool.filter(\n tm => !guessedTeamIds.has(tm.teamId) && tm.teamName.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handlePick(teamId: number): void {\n if (!config || isOver || submitting) return\n const prevGuesses = clientState?.guessHistory.map(g => ({ teamId: g.teamId })) ?? []\n const newGuesses = [...prevGuesses, { teamId }]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const wrongGuesses = (clientState?.guessHistory ?? []).filter(g => !g.wasCorrect)\n const guessesLeft = Math.max(0, MAX_GUESSES - (clientState?.guessesUsed ?? 0))\n const teamName = (id: number): string => config?.teamPool.find(tm => tm.teamId === id)?.teamName ?? `#${id}`\n\n return (\n <div className=\"ss-g-screen ss-g-gxi\" data-testid=\"game-screen-guess-the-xi\">\n <GameHeader\n title={gameTitle({ gameId: 'guess-the-xi' }, ui.games.titles)}\n eyebrow={config?.poolLabel}\n right={formation ? <Chip variant=\"accent\">{formation}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n {rows.length > 0 && (\n <div className=\"ss-g-gxi-pitch\" role=\"group\" aria-label={t.pitchLabel}>\n <PitchSvg variant=\"full\" />\n <div className=\"ss-g-gxi-rows\">\n {rows.map((row, r) => (\n <div key={r} className=\"ss-g-gxi-row\">\n {row.map((pos, c) => {\n const posLabel = pos.slot ? posBySlot.get(pos.slot) ?? '' : ''\n const name = pos.slot ? nameBySlot.get(pos.slot) : undefined\n const lineupEntry = pos.slot ? lineupBySlot.get(pos.slot) : undefined\n const flag = nationalityFlag(pos.nationality)\n // When lineup is present (terminal state), discs show photo + surname.\n if (lineupEntry) {\n return (\n <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed=\"true\">\n <PlayerAvatar\n name={lineupEntry.name}\n imagePath={lineupEntry.imagePath}\n className=\"ss-g-gxi-disc ss-g-gxi-disc--photo\"\n />\n <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(lineupEntry.name).last}</span>\n </div>\n )\n }\n return (\n <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed={name ? 'true' : undefined}>\n <span\n className=\"ss-g-gxi-disc\"\n data-code={isNationCode(flag) ? 'true' : undefined}\n role=\"img\"\n title={pos.nationality}\n aria-label={`${posLabel ? posLabel + ' — ' : ''}${pos.nationality}${name ? ' — ' + name : ''}`}\n >\n {flag}\n </span>\n {name\n ? <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(name).last}</span>\n : posLabel && <span className=\"ss-g-gxi-pos\">{posLabel}</span>}\n </div>\n )\n })}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {!isOver && wrongGuesses.length > 0 && (\n <div className=\"ss-g-gxi-wrong\">\n <span className=\"ss-g-gxi-wrong-l\">{t.notThem}</span>\n {wrongGuesses.map(g => {\n const crestUrl = config?.teamPool.find(tm => tm.teamId === g.teamId)?.crestUrl\n return (\n <span key={g.teamId} className=\"ss-g-gxi-wrong-chip\">\n <CrestShield src={crestUrl} name={teamName(g.teamId)} size={18} />\n <s>{teamName(g.teamId)}</s>\n </span>\n )\n })}\n </div>\n )}\n\n {isOver && (\n <>\n <ResultCard\n tone={solved ? 'win' : failed ? 'lose' : 'neutral'}\n title={solved ? t.solved : failed ? t.failed : ui.games.alreadyPlayedTitle}\n score={clientState?.score ?? result?.score ?? 0}\n detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n {(solved || failed) && clientState?.answer && (\n <div className=\"ss-g-gxi-answer\" data-testid=\"gxi-answer-reveal\">\n <span className=\"ss-g-gxi-answer-label\">{t.theAnswer}</span>\n <CrestShield src={clientState.answer.crestUrl} name={clientState.answer.teamName} size={32} />\n <span className=\"ss-g-gxi-answer-name\">{clientState.answer.teamName}</span>\n </div>\n )}\n </>\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={t.optionsLabel}\n options={filtered.map(tm => ({\n key: tm.teamId,\n content: <><CrestShield src={tm.crestUrl} name={tm.teamName} size={28} /><span>{tm.teamName}</span></>,\n }))}\n onPick={k => handlePick(Number(k))}\n />\n )}\n <SearchField id={inputId} label={t.whichClub(guessesLeft)} placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={submitting} />\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","export function PitchSvg({ variant }: { variant: 'full' | 'half' }): JSX.Element {\n return (\n <svg className=\"ss-g-pitch-svg\" viewBox={variant === 'full' ? '0 0 100 150' : '0 0 100 100'} preserveAspectRatio=\"none\" aria-hidden=\"true\">\n <rect x=\"4\" y=\"4\" width=\"92\" height={variant === 'full' ? 142 : 92} fill=\"none\" />\n {variant === 'full' ? (\n <>\n <line x1=\"4\" y1=\"75\" x2=\"96\" y2=\"75\" /><circle cx=\"50\" cy=\"75\" r=\"12\" fill=\"none\" />\n <rect x=\"26\" y=\"4\" width=\"48\" height=\"20\" fill=\"none\" /><rect x=\"26\" y=\"126\" width=\"48\" height=\"20\" fill=\"none\" />\n </>\n ) : (\n <>\n <path d=\"M38 4a12 12 0 0 0 24 0\" fill=\"none\" />\n <rect x=\"26\" y=\"76\" width=\"48\" height=\"20\" fill=\"none\" />\n </>\n )}\n </svg>\n )\n}\n","import type { XiSlotEntry } from '../types'\n\n/**\n * Groups the flat position list into formation rows keyed by the \"row:col\" slot's row part, then\n * orders the rows so the GOALKEEPER LINE (row 1) sits at the BOTTOM — the football convention: a\n * team defends the bottom goal and attacks upward (GK → defence → midfield → attack).\n *\n * Within a line the provider numbers positions from the team's RIGHT (Sportmonks formation_field:\n * \"2:1\" is the right-back, \"2:4\" the left-back). Drawn attacking upward, the right side is on the\n * screen's right, so each line is returned highest column first (left → right on screen).\n */\nexport function toRows(positions: XiSlotEntry[]): XiSlotEntry[][] {\n const byRow = new Map<number, XiSlotEntry[]>()\n positions.forEach((p, i) => {\n const rowKey = Number(p.slot?.split(':')[0]) || i + 1\n const bucket = byRow.get(rowKey) ?? []\n bucket.push(p)\n byRow.set(rowKey, bucket)\n })\n const col = (p: XiSlotEntry): number => Number(p.slot?.split(':')[1]) || 0\n // Descending: highest row number (forwards) at the top, row 1 (GK) at the bottom.\n return [...byRow.keys()].sort((a, b) => b - a).map(k => [...byRow.get(k)!].sort((a, b) => col(b) - col(a)))\n}\n\n// Football formation notation from the grouped rows — the outfield lines from defence to attack,\n// goalkeeper excluded (e.g. GK/4/2/3/1 → \"4-2-3-1\"). `rows` arrive attack-first (descending), so\n// read them bottom-up and drop the goalkeeper line.\nexport function formationLabel(rowsAttackFirst: XiSlotEntry[][]): string {\n if (rowsAttackFirst.length < 2) return ''\n const gkFirst = [...rowsAttackFirst].reverse()\n return gkFirst.slice(1).map(r => r.length).join('-')\n}\n\n// Canonical position labels per formation, goalkeeper first then each outfield line, left→right.\n// Lets us print a real position (GK, RB, CDM, ST…) under every node so the fan can read the shape\n// and see at a glance which end is the goalkeeper — without the config having to carry positions.\nexport const FORMATION_POSITIONS: Record<string, string[][]> = {\n '4-4-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['ST', 'ST']],\n '4-3-3': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CM', 'CM', 'CM'], ['LW', 'ST', 'RW']],\n '4-2-3-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM', 'CDM'], ['LW', 'CAM', 'RW'], ['ST']],\n '4-1-4-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n '4-5-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'CM', 'RM'], ['ST']],\n '4-4-1-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['CAM'], ['ST']],\n '4-1-2-1-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'RM'], ['CAM'], ['ST', 'ST']],\n '3-5-2': [['GK'], ['CB', 'CB', 'CB'], ['LWB', 'CM', 'CM', 'CM', 'RWB'], ['ST', 'ST']],\n '3-4-3': [['GK'], ['CB', 'CB', 'CB'], ['LM', 'CM', 'CM', 'RM'], ['LW', 'ST', 'RW']],\n '5-3-2': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['CM', 'CM', 'CM'], ['ST', 'ST']],\n '5-4-1': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n}\n\n// Line-level fallback when the exact formation is not in the table above: the goalkeeper line, the\n// forward line, then defence/midfield by depth. Always correct at the line grain even when the\n// specific role is not — enough to read the shape and spot the keeper.\nexport function lineFallback(lineIdx: number, totalLines: number): string {\n if (lineIdx === 0) return 'GK'\n if (lineIdx === totalLines - 1) return 'FWD'\n if (lineIdx === 1) return 'DEF'\n return 'MID'\n}\n\n// Map each slot (\"row:col\") to a position label, reading the rows goalkeeper-first.\nexport function positionsBySlot(formation: string, rowsAttackFirst: XiSlotEntry[][]): Map<string, string> {\n const gkFirst = [...rowsAttackFirst].reverse()\n const template = FORMATION_POSITIONS[formation]\n const map = new Map<string, string>()\n gkFirst.forEach((line, li) => {\n line.forEach((entry, ci) => {\n if (!entry.slot) return\n const label = template?.[li]?.[ci] ?? lineFallback(li, gkFirst.length)\n map.set(entry.slot, label)\n })\n })\n return map\n}\n","import { useState } from 'react'\nimport type { GameScreenProps, DailyQuizConfig, DailyQuizClientState, DailyQuizResult } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): DailyQuizClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as DailyQuizClientState\n } catch {\n return null\n }\n}\n\nfunction findResult(results: DailyQuizResult[], index: number): DailyQuizResult | undefined {\n return results.find(r => r.index === index)\n}\n\nconst TRAILING_PAREN = /\\s*\\(([^)]*)\\)$/\nconst NAME_TOKEN = /^[\\p{L}\\p{M}.'’-]+$/u\n\nfunction OptionName({ text }: { text: string }): JSX.Element {\n const match = TRAILING_PAREN.exec(text)\n const base = match ? text.slice(0, match.index).trim() : text.trim()\n const suffix = match?.[1]?.trim() ?? ''\n const tokens = base.split(/\\s+/).filter(Boolean)\n const isPlainName = tokens.length >= 1 && tokens.length <= 4 && tokens.every(t => NAME_TOKEN.test(t))\n if (!isPlainName || base === '') {\n return (\n <span className=\"ss-g-dq-opt-name\">\n <span className=\"ss-g-dq-opt-full\">{text}</span>\n </span>\n )\n }\n const { first, last } = splitName(base)\n return (\n <span className=\"ss-g-dq-opt-name\">\n {first && <span className=\"ss-g-dq-opt-first\">{first}</span>}\n <span className=\"ss-g-dq-opt-last\">{last}</span>\n {suffix && <span className=\"ss-g-dq-opt-suffix\">{suffix}</span>}\n </span>\n )\n}\n\nexport function DailyQuizGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n}: GameScreenProps<DailyQuizConfig>): JSX.Element {\n const s = ui.games.dailyQuiz\n const title = gameTitle({ gameId: 'daily-quiz' }, ui.games.titles)\n // Local selection state: map from question index → selected option index\n const [selections, setSelections] = useState<Map<number, number>>(new Map())\n const [page, setPage] = useState(0)\n\n const clientState = parseClientState(result?.clientStateJson)\n const results = clientState?.results ?? []\n const isRevealed = results.length > 0 || result?.alreadyPlayed === true\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const questions = config.questions\n const total = questions.length\n const current = questions[Math.min(page, total - 1)]\n const isLast = page >= total - 1\n const currentAnswered = current !== undefined && selections.has(current.index)\n const allAnswered = selections.size === total\n\n function handleSelect(questionIndex: number, optionIndex: number): void {\n if (isRevealed || submitting) return\n setSelections(prev => new Map(prev).set(questionIndex, optionIndex))\n }\n\n function goNext(): void {\n if (!currentAnswered || isLast) return\n setPage(p => p + 1)\n }\n\n function goPrev(): void {\n setPage(p => Math.max(0, p - 1))\n }\n\n function handleSubmit(): void {\n if (!config || !allAnswered || isRevealed || submitting) return\n const answers = config.questions.map(q => ({\n index: q.index,\n selectedOptionIndex: selections.get(q.index) ?? 0,\n }))\n onSubmit(JSON.stringify({ answers }))\n }\n\n if (isRevealed) {\n const segments: SegmentState[] = questions.map(q => {\n const r = findResult(results, q.index)\n if (!r) return 'done'\n return r.isCorrect ? 'correct' : 'wrong'\n })\n const correctCount = results.filter(r => r.isCorrect).length\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} eyebrow={s.results} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress segments={segments} ariaLabel={s.results} />\n <div className=\"ss-g-body\">\n <ResultCard\n tone=\"neutral\"\n title={results.length > 0 ? s.correctOf(correctCount, total) : ui.games.alreadyPlayedTitle}\n score={result?.score}\n onBack={onBack}\n ui={ui}\n />\n {questions.map(q => {\n const r = findResult(results, q.index)\n const picked = selections.get(q.index)\n return (\n <div key={q.index} className=\"ss-g-dq-rq\">\n <div className=\"ss-g-dq-rq-stem\">{q.stem}</div>\n {r && (\n <div className=\"ss-g-dq-rq-opts\">\n {q.options.map((opt, optIdx) => {\n let cls = 'ss-g-dq-rq-opt'\n if (optIdx === r.correctOptionIndex) cls += ' ss-g-dq-rq-opt--correct'\n else if (optIdx === picked && !r.isCorrect) cls += ' ss-g-dq-rq-opt--wrong'\n return <span key={optIdx} className={cls}>{opt}</span>\n })}\n </div>\n )}\n {r?.revealText && <div className=\"ss-g-dq-why\">{r.revealText}</div>}\n </div>\n )\n })}\n </div>\n </div>\n )\n }\n\n const segments: SegmentState[] = questions.map((_, i) => (i < page ? 'done' : i === page ? 'current' : 'todo'))\n const selectedIdx = current ? selections.get(current.index) : undefined\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} eyebrow={s.questionOf(page + 1, total)} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress segments={segments} ariaLabel={s.progressAria(page + 1, total)} />\n <div className=\"ss-g-body\">\n {current && (\n <>\n <h3 className=\"ss-g-dq-stem\">{current.stem}</h3>\n <div className=\"ss-g-dq-opts\">\n {current.options.map((opt, optIdx) => {\n const selected = optIdx === selectedIdx\n const imagePath = current.optionImagePaths?.[optIdx] ?? undefined\n const playerName = opt\n return (\n <button\n key={optIdx}\n type=\"button\"\n className=\"ss-g-dq-opt\"\n aria-pressed={selected}\n disabled={submitting}\n onClick={() => handleSelect(current.index, optIdx)}\n >\n {current.optionImagePaths && (\n <PlayerAvatar name={playerName} imagePath={imagePath} className=\"ss-g-dq-opt-av\" />\n )}\n <span className=\"ss-g-dq-badge\" aria-hidden=\"true\">\n {selected ? <IconCheck /> : String.fromCharCode(65 + optIdx)}\n </span>\n <OptionName text={opt} />\n </button>\n )\n })}\n </div>\n </>\n )}\n </div>\n <FooterBar>\n <div className=\"ss-g-dq-nav\">\n {page > 0 && (\n <GameButton variant=\"outline\" onClick={goPrev} disabled={submitting}>{s.previous}</GameButton>\n )}\n {isLast ? (\n <GameButton variant=\"primary\" block onClick={handleSubmit} disabled={!currentAnswered || !allAnswered || submitting}>\n {submitting ? s.submitting : s.submit}\n </GameButton>\n ) : (\n <GameButton variant=\"primary\" block onClick={goNext} disabled={!currentAnswered || submitting}>\n {s.next}\n </GameButton>\n )}\n </div>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n MatchdayPredictorConfig,\n MatchdayPredictorClientState,\n MatchdayPredictorTeam,\n} from './types'\nimport type { GamesStrings } from '../../i18n'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck, IconClose, IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Above this many scorers the card grid gets a search filter (spec §5.7).\nconst SCORER_SEARCH_THRESHOLD = 9\n\ntype Side = 'home' | 'away'\ntype PredictorStrings = GamesStrings['predictor']\n\nfunction parseClientState(json: string | null | undefined): MatchdayPredictorClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as MatchdayPredictorClientState\n } catch {\n return null\n }\n}\n\nfunction isLocked(kickoffUtc: string): boolean {\n try {\n return new Date(kickoffUtc).getTime() <= Date.now()\n } catch {\n return true\n }\n}\n\nfunction IconMinus(): JSX.Element {\n return (\n <svg width={18} height={18} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.2}\n strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M5 12h14\" /></svg>\n )\n}\n\nfunction TeamBadge({ team, label }: { team: MatchdayPredictorTeam; label: string }): JSX.Element {\n return (\n <div className=\"ss-g-mp-team\">\n <CrestShield name={team.name} size={44} />\n <span className=\"ss-g-mp-team-name\">{team.name}</span>\n <span className=\"ss-g-mp-team-side\">{label}</span>\n </div>\n )\n}\n\nfunction ScoreCard({ home, away, h, a, t, edit }: {\n home: MatchdayPredictorTeam\n away: MatchdayPredictorTeam\n h: number\n a: number\n t: PredictorStrings\n edit?: { disabled: boolean; active: Side; onStep: (side: Side, delta: 1 | -1) => void }\n}): JSX.Element {\n const col = (side: Side, team: MatchdayPredictorTeam, value: number): JSX.Element => (\n <div className=\"ss-g-mp-col\">\n {edit && (\n <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsUp(team.name)}\n disabled={edit.disabled} onClick={() => edit.onStep(side, 1)}>\n <IconPlus size={18} />\n </button>\n )}\n <span className=\"ss-g-mp-digit\" data-testid=\"mp-digit\" data-active={edit ? String(edit.active === side) : 'false'}>\n {value}\n </span>\n {edit && (\n <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsDown(team.name)}\n disabled={edit.disabled || value <= 0} onClick={() => edit.onStep(side, -1)}>\n <IconMinus />\n </button>\n )}\n </div>\n )\n return (\n <div className=\"ss-g-mp-card\">\n <TeamBadge team={home} label={t.home} />\n <div className=\"ss-g-mp-scores\">\n {col('home', home, h)}\n <span className=\"ss-g-mp-dash\" aria-hidden=\"true\">–</span>\n {col('away', away, a)}\n </div>\n <TeamBadge team={away} label={t.away} />\n </div>\n )\n}\n\nfunction OutcomeRow({ label, ok, detail, t }: { label: string; ok: boolean; detail?: string | null; t: PredictorStrings }): JSX.Element {\n return (\n <li className=\"ss-g-mp-row\" data-testid=\"mp-row\" data-ok={String(ok)}>\n <span className=\"ss-g-mp-row-k\">{label}</span>\n <span className=\"ss-g-mp-row-v\">\n {ok ? <IconCheck /> : <IconClose size={14} />}\n <span className=\"ss-g-sr\">{ok ? t.correct : t.incorrect}</span>\n {detail ? <span className=\"ss-g-mp-row-d\">{detail}</span> : null}\n </span>\n </li>\n )\n}\n\nexport function MatchdayPredictorGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<MatchdayPredictorConfig>): JSX.Element {\n const t = ui.games.predictor\n const [homeScore, setHomeScore] = useState(0)\n const [awayScore, setAwayScore] = useState(0)\n const [firstScorerPlayerId, setFirstScorerPlayerId] = useState<number | null>(null)\n const [lastEdited, setLastEdited] = useState<Side>('home')\n const [query, setQuery] = useState('')\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyPlayed = result?.alreadyPlayed === true\n\n const header = (\n <GameHeader\n title={gameTitle({ gameId: 'matchday-predictor' }, ui.games.titles)}\n eyebrow={config ? t.eyebrow(config.homeTeam.name, config.awayTeam.name) : undefined}\n right={config ? <Chip icon={<IconLock />}>{ui.games.formatDayTime(config.kickoffUtc)}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n // Played states (pending or graded) when the fan has already submitted\n if (alreadyPlayed && clientState) {\n if (!clientState.graded) {\n const scorer = config?.scorerPool.find(p => p.playerId === clientState.predictedFirstScorerPlayerId) ?? null\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n {config && (\n <ScoreCard home={config.homeTeam} away={config.awayTeam}\n h={clientState.predictedHomeScore} a={clientState.predictedAwayScore} t={t} />\n )}\n <ResultCard\n tone=\"neutral\"\n title={t.saved}\n detail={t.savedDetail({\n home: config?.homeTeam.name ?? '',\n away: config?.awayTeam.name ?? '',\n h: clientState.predictedHomeScore,\n a: clientState.predictedAwayScore,\n scorer: scorer ? splitName(scorer.playerName).last : null,\n })}\n onBack={onBack}\n ui={ui}\n />\n </div>\n <FooterBar>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n }\n\n const r = clientState.result\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n {config && <ScoreCard home={config.homeTeam} away={config.awayTeam} h={r.homeScore} a={r.awayScore} t={t} />}\n <ResultCard tone=\"neutral\" title={t.fullTime(r.homeScore, r.awayScore)} onBack={onBack} ui={ui} />\n <ul className=\"ss-g-mp-rows\">\n <OutcomeRow label={t.exactScore} ok={clientState.exactScoreCorrect} t={t} />\n <OutcomeRow label={t.outcome} ok={clientState.outcomeCorrect} t={t} />\n {!clientState.firstScorerVoid && (\n <OutcomeRow label={t.firstScorerRow} ok={clientState.firstScorerCorrect} detail={r.firstScorerName} t={t} />\n )}\n </ul>\n </div>\n <FooterBar>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const locked = isLocked(config.kickoffUtc)\n const disabled = locked || submitting\n\n function step(side: Side, delta: 1 | -1): void {\n setLastEdited(side)\n if (side === 'home') setHomeScore(s => Math.max(0, s + delta))\n else setAwayScore(s => Math.max(0, s + delta))\n }\n\n function handleSubmit(): void {\n if (disabled || !config) return\n onSubmit(\n JSON.stringify({\n homeScore,\n awayScore,\n ...(firstScorerPlayerId !== null ? { firstScorerPlayerId } : {}),\n }),\n )\n }\n\n const pool = config.scorerPool\n const showSearch = pool.length > SCORER_SEARCH_THRESHOLD\n const q = query.trim().toLowerCase()\n const visible = showSearch && q ? pool.filter(p => p.playerName.toLowerCase().includes(q)) : pool\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n <ScoreCard\n home={config.homeTeam}\n away={config.awayTeam}\n h={homeScore}\n a={awayScore}\n t={t}\n edit={{ disabled, active: lastEdited, onStep: step }}\n />\n\n {pool.length > 0 && (\n <section className=\"ss-g-mp-scorer\">\n <div className=\"ss-g-mp-sec-head\">\n <h3>{t.firstScorer}</h3>\n <span>{t.optional}</span>\n </div>\n {showSearch && (\n <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={disabled} />\n )}\n <div className=\"ss-g-mp-grid\">\n {visible.map(p => {\n const selected = firstScorerPlayerId === p.playerId\n return (\n <button\n key={p.playerId}\n type=\"button\"\n className=\"ss-g-mp-pcard\"\n aria-pressed={selected}\n aria-label={p.playerName}\n disabled={disabled}\n onClick={() => setFirstScorerPlayerId(id => (id === p.playerId ? null : p.playerId))}\n >\n {selected && <span className=\"ss-g-mp-pcheck\"><IconCheck size={12} /></span>}\n <Silhouette size={52} variant={selected ? 'selected' : 'default'} />\n <span className=\"ss-g-mp-pname\">{splitName(p.playerName).last}</span>\n </button>\n )\n })}\n </div>\n <button\n type=\"button\"\n className=\"ss-g-mp-none\"\n aria-pressed={firstScorerPlayerId === null}\n disabled={disabled}\n onClick={() => setFirstScorerPlayerId(null)}\n >\n <span className=\"ss-g-mp-radio\" aria-hidden=\"true\" />\n {t.noScorer}\n </button>\n </section>\n )}\n\n {locked && <p className=\"ss-g-mp-closed\">{t.closed}</p>}\n </div>\n\n <FooterBar>\n <GameButton variant=\"primary\" block disabled={disabled} onClick={handleSubmit}>\n {submitting ? t.saving : t.save}\n </GameButton>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n StartingXiConfig,\n StartingXiClientState,\n StartingXiSquadEntry,\n} from './types'\nimport { FORMATION_POSITIONS, lineFallback } from './ui/formations'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Display only — mirrors StartingXiScorer.PointsPerCorrectStarter (StartingXiScorer.cs:47).\nconst POINTS_PER_STARTER = 8\nconst XI_SIZE = 11\nconst DEFAULT_FORMATION = '4-3-3'\n\nexport interface XiSlot {\n index: number\n label: string\n left: number\n top: number\n}\n\nfunction parseClientState(json: string | null | undefined): StartingXiClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as StartingXiClientState\n } catch {\n return null\n }\n}\n\n/**\n * Pitch slots for a formation, goalkeeper first then each outfield line left→right. Positions are\n * percentages of an attacking-half pitch: the keeper sits lowest (top 88%), the front line highest.\n * A formation that does not add up to 10 outfield players falls back to 4-3-3 so there are always 11.\n */\nexport function formationSlots(formation: string): { formation: string; slots: XiSlot[] } {\n const parts = formation.split('-').map(Number).filter(n => n > 0)\n const valid = parts.reduce((s, n) => s + n, 0) === XI_SIZE - 1\n const used = valid ? formation : DEFAULT_FORMATION\n const outfield = valid ? parts : DEFAULT_FORMATION.split('-').map(Number)\n const lines = [1, ...outfield]\n const template = FORMATION_POSITIONS[used]\n const slots: XiSlot[] = []\n lines.forEach((count, li) => {\n const top = 88 - li * (77 / (lines.length - 1))\n for (let ci = 0; ci < count; ci++) {\n const left = count === 1 ? 50 : 12 + ci * (76 / (count - 1))\n slots.push({ index: slots.length, label: template?.[li]?.[ci] ?? lineFallback(li, lines.length), left, top })\n }\n })\n return { formation: used, slots }\n}\n\nfunction firstEmpty(slotPlayers: (number | null)[]): number | null {\n const i = slotPlayers.findIndex(p => p === null)\n return i === -1 ? null : i\n}\n\nexport function StartingXiGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n lockAtUtc,\n}: GameScreenProps<StartingXiConfig>): JSX.Element {\n const t = ui.games.startingXi\n const [slotPlayers, setSlotPlayers] = useState<(number | null)[]>(() => Array<number | null>(XI_SIZE).fill(null))\n const [active, setActive] = useState<number | null>(0)\n const [query, setQuery] = useState('')\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyPlayed = result?.alreadyPlayed === true\n\n const header = (\n <GameHeader\n title={gameTitle({ gameId: 'starting-xi' }, ui.games.titles)}\n eyebrow={t.eyebrow}\n right={<Chip variant=\"accent\">{t.perStarter(POINTS_PER_STARTER)}</Chip>}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n // Pending, graded and voided all render the spec §6 result card with a way back to the hub.\n function statusScreen(title: string, score?: number): JSX.Element {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <div className=\"ss-g-body\">\n <ResultCard tone=\"neutral\" title={title} score={score} onBack={onBack} ui={ui} />\n </div>\n </div>\n )\n }\n\n if (alreadyPlayed) {\n if (!clientState) return statusScreen(t.voided)\n if (clientState.status === 'pending') return statusScreen(t.pending(clientState.predictedCount))\n if (clientState.status === 'graded') return statusScreen(t.gradedLine(clientState.correctCount), clientState.score)\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const { formation, slots } = formationSlots(config.formation)\n const byId = new Map<number, StartingXiSquadEntry>(config.squadSheet.map(p => [p.playerId, p]))\n const pickedCount = slotPlayers.filter(p => p !== null).length\n const canSubmit = pickedCount === XI_SIZE && !submitting\n const pickedSet = new Set(slotPlayers.filter((p): p is number => p !== null))\n const q = query.trim().toLowerCase()\n const available = config.squadSheet.filter(\n p => !pickedSet.has(p.playerId) && (!q || (p.playerName ?? '').toLowerCase().includes(q)),\n )\n const activeSlot = active !== null ? slots[active] ?? null : null\n\n function pick(playerId: number): void {\n if (submitting || active === null) return\n const next = [...slotPlayers]\n next[active] = playerId\n setSlotPlayers(next)\n setActive(firstEmpty(next))\n setQuery('')\n }\n\n function tapSlot(index: number): void {\n if (submitting) return\n if (slotPlayers[index] !== null) {\n const next = [...slotPlayers]\n next[index] = null\n setSlotPlayers(next)\n }\n setActive(index)\n }\n\n function handleSubmit(): void {\n if (!canSubmit) return\n onSubmit(JSON.stringify({ predictedPlayerIds: slotPlayers }))\n }\n\n const segments: SegmentState[] = slotPlayers.map(p => (p !== null ? 'current' : 'todo'))\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <SegmentProgress\n segments={segments}\n ariaLabel={t.picked(pickedCount)}\n leftLabel={t.picked(pickedCount)}\n rightLabel={t.toGo(XI_SIZE - pickedCount)}\n right={<Chip>{formation}</Chip>}\n />\n <div className=\"ss-g-body\">\n <div className=\"ss-g-xi-pitch\">\n <PitchSvg variant=\"half\" />\n {slots.map(s => {\n const playerId = slotPlayers[s.index] ?? null\n const player = playerId !== null ? byId.get(playerId) ?? null : null\n const name = player?.playerName ?? ''\n const state = player ? 'filled' : active === s.index ? 'active' : 'empty'\n return (\n <button\n key={s.index}\n type=\"button\"\n className=\"ss-g-xi-slot\"\n data-state={state}\n style={{ left: `${s.left}%`, top: `${s.top}%` }}\n aria-pressed={active === s.index}\n aria-label={player ? t.clearSlot(s.label, name) : t.pickSlot(s.label)}\n disabled={submitting}\n onClick={() => tapSlot(s.index)}\n >\n <span className=\"ss-g-xi-ring\" aria-hidden=\"true\">\n {player ? (player.jerseyNumber ?? '') : <IconPlus size={18} />}\n </span>\n <span className=\"ss-g-xi-tag\" aria-hidden=\"true\">{player ? splitName(name).last : s.label}</span>\n </button>\n )\n })}\n </div>\n\n <div className=\"ss-g-xi-picker\">\n <div className=\"ss-g-xi-picker-head\">\n {activeSlot ? (\n <>\n <Chip variant=\"badge\">{activeSlot.label}</Chip>\n <strong>{t.pickFor(activeSlot.label)}</strong>\n </>\n ) : (\n <strong>{t.allPicked}</strong>\n )}\n </div>\n {activeSlot && (\n <>\n <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchLabel}\n value={query} onChange={setQuery} disabled={submitting} />\n <ul className=\"ss-g-xi-list\">\n {available.map(p => (\n <li key={p.playerId}>\n <button type=\"button\" className=\"ss-g-xi-opt\" disabled={submitting} onClick={() => pick(p.playerId)}>\n <span className=\"ss-g-xi-opt-no\" aria-hidden=\"true\">{p.jerseyNumber ?? ''}</span>\n <span className=\"ss-g-xi-opt-name\">{p.playerName}</span>\n <span className=\"ss-g-xi-opt-pos\">{p.positionName}</span>\n </button>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n </div>\n <FooterBar>\n <GameButton variant=\"primary\" block disabled={!canSubmit} onClick={handleSubmit}>\n {submitting ? t.submitting : t.submit}\n </GameButton>\n <p className=\"ss-g-xi-lock\">\n <IconLock />\n {lockAtUtc ? t.locksAt(ui.games.formatDayTime(lockAtUtc)) : t.locksSoon}\n </p>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n StatLadderConfig,\n StatLadderClientState,\n StatLadderRung,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconBulb, IconCheck, IconShield } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nexport interface LadderClue {\n value: number\n above: { name: string; diff: number } | null\n below: { name: string; diff: number } | null\n}\n\n/** Pure: the mystery rung's value plus its gaps to the named rungs directly above (rank 1) and below (rank 3). */\nexport function ladderClue(ladder: StatLadderRung[]): LadderClue | null {\n const mystery = ladder.find(r => r.rank === 2)\n if (!mystery) return null\n const above = ladder.find(r => r.rank === 1)\n const below = ladder.find(r => r.rank === 3)\n return {\n value: mystery.statValue,\n above: above?.playerName ? { name: above.playerName, diff: above.statValue - mystery.statValue } : null,\n below: below?.playerName ? { name: below.playerName, diff: mystery.statValue - below.statValue } : null,\n }\n}\n\nfunction parseClientState(json: string | null | undefined): StatLadderClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as StatLadderClientState\n } catch {\n return null\n }\n}\n\nfunction NameStack({ name }: { name: string }): JSX.Element {\n const { first, last } = splitName(name)\n return (\n <span className=\"ss-g-sl-name\">\n {first && <small>{`${first[0]}.`}</small>}\n <b>{last}</b>\n </span>\n )\n}\n\nexport function StatLadderGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<StatLadderConfig>): JSX.Element {\n const t = ui.games.statLadder\n const [query, setQuery] = useState('')\n const [selectedId, setSelectedId] = useState<number | null>(null)\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const revealed = clientState != null\n\n const header = (\n <GameHeader title={gameTitle({ gameId: 'stat-ladder' }, ui.games.titles)} eyebrow={t.eyebrow} onBack={onBack} backLabel={ui.back} />\n )\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-stat-ladder\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const question = t.question(config.statLabel)\n const clue = revealed ? null : ladderClue(config.ladder)\n const rungs = [...config.ladder].sort((a, b) => a.rank - b.rank)\n const q = query.trim().toLowerCase()\n const pool = q ? config.playerPool.filter(p => p.playerName.toLowerCase().includes(q)) : config.playerPool\n\n function guess(): void {\n if (selectedId === null || submitting || revealed) return\n onSubmit(JSON.stringify({ guessedPlayerId: selectedId }))\n }\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-stat-ladder\">\n {header}\n <div className=\"ss-g-body\">\n <div className=\"ss-g-sl-prompt\">\n <Chip variant=\"accent\" icon={<IconShield size={14} />} className=\"ss-g-sl-stat\">{config.statLabel}</Chip>\n <h3 className=\"ss-g-sl-q\">\n {question.pre}<em>{question.emph}</em>{question.post}\n </h3>\n </div>\n\n <ol className=\"ss-g-sl-rungs\">\n {rungs.map(rung =>\n rung.rank === 2 ? (\n <li\n key={rung.rank}\n className=\"ss-g-sl-rung ss-g-sl-rung--mystery\"\n data-testid=\"sl-mystery-rung\"\n data-result={revealed ? (clientState!.isCorrect ? 'correct' : 'wrong') : undefined}\n >\n <span className=\"ss-g-sl-rank\">2</span>\n {revealed\n ? <PlayerAvatar name={clientState!.revealedRank2.playerName} className=\"ss-g-sl-av\" />\n : <Silhouette size={52} variant=\"mystery\" />}\n {revealed\n ? <NameStack name={clientState!.revealedRank2.playerName} />\n : <span className=\"ss-g-sl-who\">{t.whoSecond}</span>}\n <span className=\"ss-g-sl-val ss-g-sl-val--mystery\">{rung.statValue}</span>\n </li>\n ) : (\n <li key={rung.rank} className=\"ss-g-sl-rung\">\n <span className=\"ss-g-sl-rank\">{rung.rank}</span>\n <PlayerAvatar name={rung.playerName ?? '?'} className=\"ss-g-sl-av\" />\n <NameStack name={rung.playerName ?? '?'} />\n <span className=\"ss-g-sl-val\">{rung.statValue}</span>\n </li>\n ),\n )}\n </ol>\n\n {clue && (\n <p className=\"ss-g-sl-clue\">\n <IconBulb />\n <span>{t.clue(clue, config.statLabel)}</span>\n </p>\n )}\n\n {!revealed && (\n <ul className=\"ss-g-sl-pool\">\n {pool.map(p => (\n <li key={p.playerId}>\n <button\n type=\"button\"\n className=\"ss-g-sl-opt\"\n aria-label={p.playerName}\n aria-pressed={selectedId === p.playerId}\n disabled={submitting}\n onClick={() => { setSelectedId(p.playerId); setQuery(p.playerName) }}\n >\n <PlayerAvatar name={p.playerName} className=\"ss-g-sl-opt-av\" />\n <span className=\"ss-g-sl-opt-name\">{p.playerName}</span>\n {selectedId === p.playerId && <IconCheck />}\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {revealed && (\n <ResultCard\n tone={clientState!.isCorrect ? 'win' : 'lose'}\n title={clientState!.isCorrect ? t.correct : t.wrong(clientState!.revealedRank2.playerName)}\n score={result?.score}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!revealed && (\n <FooterBar>\n <div className=\"ss-g-sl-guess\">\n <SearchField\n id={searchId}\n label={t.searchLabel}\n labelHidden\n placeholder={t.searchPlaceholder}\n value={query}\n onChange={v => { setQuery(v); setSelectedId(null) }}\n disabled={submitting}\n />\n <GameButton variant=\"primary\" disabled={selectedId === null || submitting} onClick={guess}>\n {t.guess}\n </GameButton>\n </div>\n </FooterBar>\n )}\n </div>\n )\n}\n","import type {\n GameScreenProps,\n FanMotmConfig,\n FanMotmClientState,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): FanMotmClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as FanMotmClientState\n } catch {\n return null\n }\n}\n\nexport function FanMotmGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<FanMotmConfig>): JSX.Element {\n const t = ui.games.motm\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyVoted = result?.alreadyPlayed === true\n const pickedId = clientState?.pickedPlayerId ?? null\n\n const header = (\n <GameHeader\n title={t.title}\n eyebrow={t.eyebrow}\n right={alreadyVoted ? <Chip variant=\"success\" icon={<IconCheck />}>{t.voted}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-fan-motm\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const picked = config.candidates.find(c => c.playerId === pickedId) ?? null\n\n function handleVote(candidateId: number): void {\n if (alreadyVoted || submitting) return\n onSubmit(JSON.stringify({ pickedPlayerId: candidateId }))\n }\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-fan-motm\">\n {header}\n <div className=\"ss-g-body\">\n <ul className=\"ss-g-motm-list\">\n {config.candidates.map(c => {\n const isVoted = alreadyVoted && pickedId === c.playerId\n return (\n <li key={c.playerId}>\n <button\n type=\"button\"\n className={`ss-g-motm-row${isVoted ? ' ss-g-motm-row--voted' : ''}`}\n data-testid={`motm-candidate-${c.playerId}`}\n disabled={alreadyVoted || submitting}\n onClick={() => handleVote(c.playerId)}\n >\n <PlayerAvatar name={c.playerName} className=\"ss-g-motm-av\" />\n <span className=\"ss-g-motm-name\">{c.playerName}</span>\n {isVoted && <Chip variant=\"accent\" className=\"ss-g-motm-pill\">{t.yourVote}</Chip>}\n </button>\n </li>\n )\n })}\n </ul>\n {alreadyVoted && picked && (\n <ResultCard tone=\"neutral\" title={t.youVoted(picked.playerName)} detail={t.thanks} onBack={onBack} ui={ui} />\n )}\n </div>\n <FooterBar>\n {!alreadyVoted && <p className=\"ss-g-motm-foot\">{t.tapToVote}</p>}\n <p className=\"ss-g-motm-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n}\n","const FONTS_LINK_ID = 'ss-w-games-fonts'\nconst FONTS_HREF =\n 'https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Barlow:wght@400;500;600;700&display=swap'\n\n// Registered at document level: @font-face inside a shadow root is ignored by browsers, but\n// document fonts resolve inside the embed's shadow tree. If CSP blocks it the fallback stack renders.\nexport function ensureGamesFonts(doc: Document = document): void {\n if (!doc.head) return\n if (doc.getElementById(FONTS_LINK_ID)) return\n const link = doc.createElement('link')\n link.id = FONTS_LINK_ID\n link.rel = 'stylesheet'\n link.href = FONTS_HREF\n doc.head.appendChild(link)\n}\n","import { useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { LeaderboardWeeklyRow, LeaderboardAllTimeRow, formatPoints } from './LeaderboardRow'\nimport { LeaderboardEmpty } from './LeaderboardEmpty'\n\ntype Segment = 'weekly' | 'alltime'\n\nexport function Leaderboard({\n data,\n ui,\n onPlay,\n}: {\n data: LeaderboardPayload\n ui: UiConfig\n /** Jumps to the Games tab from the empty-state CTA. */\n onPlay?: () => void\n}): JSX.Element {\n const [segment, setSegment] = useState<Segment>('weekly')\n\n const myRow = segment === 'weekly' ? data.myWeeklyRow : data.myAllTimeRow\n const offBoard = myRow !== null && myRow !== undefined && myRow.rank === -1\n const isEmpty = segment === 'weekly'\n ? data.weeklyTop.length === 0\n : data.allTimeTop.length === 0\n\n return (\n <div className=\"ss-w-lb2\">\n <div className=\"ss-w-seg\">\n <button\n type=\"button\"\n className=\"ss-w-seg-btn\"\n {...(segment === 'weekly' ? { 'data-on': '' } : {})}\n onClick={() => setSegment('weekly')}\n >\n {ui.leaderboardThisWeek}\n </button>\n <button\n type=\"button\"\n className=\"ss-w-seg-btn\"\n {...(segment === 'alltime' ? { 'data-on': '' } : {})}\n onClick={() => setSegment('alltime')}\n >\n {ui.leaderboardAllTime}\n </button>\n </div>\n\n {isEmpty ? (\n <LeaderboardEmpty\n segment={segment}\n lastWeek={data.lastWeek}\n weeklyPrize={data.weeklyPrize}\n onPlay={onPlay}\n ui={ui}\n />\n ) : (\n <>\n <div className=\"ss-w-lb2-rows\">\n {segment === 'weekly'\n ? data.weeklyTop.map((row) => (\n <LeaderboardWeeklyRow\n key={row.operatorUserId}\n row={row}\n isMe={row.operatorUserId === data.myWeeklyRow?.operatorUserId}\n />\n ))\n : data.allTimeTop.map((row) => (\n <LeaderboardAllTimeRow\n key={row.operatorUserId}\n row={row}\n isMe={row.operatorUserId === data.myAllTimeRow?.operatorUserId}\n />\n ))}\n </div>\n\n {/* Kit-prize separator */}\n <div className=\"ss-w-kitline\">🎽</div>\n\n {/* Pinned \"you\" row or off-board treatment */}\n {myRow != null && (\n offBoard ? (\n <div className=\"ss-w-lbgap\">{ui.leaderboardOffBoard}</div>\n ) : (\n <div className=\"ss-w-lb2-rows\">\n {segment === 'weekly' && data.myWeeklyRow && (\n <LeaderboardWeeklyRow row={data.myWeeklyRow} isMe />\n )}\n {segment === 'alltime' && data.myAllTimeRow && (\n <LeaderboardAllTimeRow row={data.myAllTimeRow} isMe />\n )}\n </div>\n )\n )}\n\n {/* All-time footer: show rank + total when available */}\n {segment === 'alltime' && data.myAllTimeRow && !offBoard && (\n <div className=\"ss-w-lb2-rows\">\n <div className=\"ss-w-lb2-row\">\n <span className=\"ss-w-lb2-handle\">\n {formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0))}\n </span>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n","import type { LeaderboardRow as SDKRow, AllTimeRow } from '@sensiblestats/widget-sdk'\n\n/** Formats a points integer with thousands separators. */\nexport function formatPoints(n: number): string {\n return n.toLocaleString('en')\n}\n\nexport function LeaderboardWeeklyRow({\n row,\n isMe,\n}: {\n row: SDKRow\n isMe: boolean\n}): JSX.Element {\n const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n return (\n <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n <span className={rankClass}>#{row.rank}</span>\n <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n <span className=\"ss-w-lb2-points\">{formatPoints(row.points)}</span>\n {row.currentStreak > 0 && (\n <span className=\"ss-w-lb2-streak\">🔥 {row.currentStreak}</span>\n )}\n </div>\n )\n}\n\nexport function LeaderboardAllTimeRow({\n row,\n isMe,\n}: {\n row: AllTimeRow\n isMe: boolean\n}): JSX.Element {\n const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n return (\n <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n <span className={rankClass}>#{row.rank}</span>\n <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n <span className=\"ss-w-lb2-points\">{formatPoints(row.allTimePoints)}</span>\n </div>\n )\n}\n","import type { LeaderboardChampion } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { formatPoints } from './LeaderboardRow'\n\ntype Segment = 'weekly' | 'alltime'\n\n/**\n * Default state for the leaderboard when the active segment has no ranked rows.\n * Weekly boards reset every week, so this is what most fans see at the start of a week.\n * - weekly + a prior champion -> \"fresh week\" copy plus a last-week continuity strip\n * - weekly + no history -> \"cold start\" copy (club's first-ever week)\n * - all-time -> a quiet single line; it fills as fans play\n */\nexport function LeaderboardEmpty({\n segment,\n lastWeek,\n weeklyPrize,\n onPlay,\n ui,\n}: {\n segment: Segment\n lastWeek?: LeaderboardChampion | null\n weeklyPrize?: string | null\n onPlay?: () => void\n ui: UiConfig\n}): JSX.Element {\n if (segment === 'alltime') {\n return (\n <div className=\"ss-w-lb-empty ss-w-lb-empty--alltime\">\n <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">📊</div>\n <p className=\"ss-w-lb-empty-body\">{ui.leaderboardAllTimeEmpty}</p>\n </div>\n )\n }\n\n const fresh = lastWeek != null\n const title = fresh ? ui.leaderboardEmptyFreshTitle : ui.leaderboardEmptyColdTitle\n const body = fresh ? ui.leaderboardEmptyFreshBody : ui.leaderboardEmptyColdBody\n\n return (\n <div className=\"ss-w-lb-empty\">\n {weeklyPrize && (\n <div className=\"ss-w-prize\">\n <span className=\"ss-w-prize-icon\" aria-hidden=\"true\">🏆</span>\n <div className=\"ss-w-prize-body\">\n <span className=\"ss-w-prize-text\">{weeklyPrize}</span>\n </div>\n </div>\n )}\n\n <div className=\"ss-w-lb-empty-hero\">\n <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">{fresh ? '🏆' : '🎮'}</div>\n <h4 className=\"ss-w-lb-empty-title\">{title}</h4>\n <p className=\"ss-w-lb-empty-body\">{body}</p>\n {onPlay && (\n <button type=\"button\" className=\"ss-w-lb-empty-cta\" onClick={onPlay}>\n {ui.leaderboardEmptyCta}\n </button>\n )}\n </div>\n\n {fresh && lastWeek && (\n <div className=\"ss-w-lb-last\">\n <span className=\"ss-w-lb-last-label\">{ui.leaderboardLastWeekLabel}</span>\n <span className=\"ss-w-lb-last-champ\" aria-hidden=\"true\">🥇</span>\n <span className=\"ss-w-lb-last-handle\">{lastWeek.handle}</span>\n <span className=\"ss-w-lb-last-points\">{formatPoints(lastWeek.points)}</span>\n </div>\n )}\n </div>\n )\n}\n","import type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { Leaderboard } from './Leaderboard'\n\n/** Settled empty board (no rows yet) — a fetch that returned null once loading is done. */\nconst EMPTY_PAYLOAD: LeaderboardPayload = {\n week: '',\n weeklyTop: [],\n myWeeklyRow: null,\n allTimeTop: [],\n myAllTimeRow: null,\n weeklyPrize: null,\n lastWeek: null,\n}\n\nexport function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }: {\n loggedIn: boolean\n data: LeaderboardPayload | null\n loading?: boolean\n onPlay?: () => void\n ui: UiConfig\n}): JSX.Element {\n if (!loggedIn) return <GamesLoginWall ui={ui} />\n // Still fetching with nothing to show yet: keep the panel blank (skeleton-free).\n if (data === null && loading) return <div className=\"ss-w-mon-list\" />\n return (\n <div className=\"ss-w-mon-list\">\n <Leaderboard data={data ?? EMPTY_PAYLOAD} ui={ui} onPlay={onPlay} />\n </div>\n )\n}\n","import { isValidId } from './host'\n\nexport const VIEW_DEDUPE_MS = 30 * 60 * 1000\nexport const HELD_MAX = 5\n\n/** duplicate: seen inside the window. log: report it now. held: kept until the panel opens. */\nexport type ViewResult = 'duplicate' | 'log' | 'held'\n\nexport interface MatchViews {\n /** A match page view, or a click on a match link. */\n view(matchId: number): ViewResult\n /** The panel opened. Returns the matches held until now, oldest first; empty on later opens. */\n markOpened(): number[]\n}\n\nexport interface MatchViewsOptions {\n /** operatorUserId of the current visitor; undefined when anonymous. */\n user?: string\n /** Defaults to window.sessionStorage. Pass null for a memory-only state. */\n storage?: Storage | null\n now?: () => number\n}\n\ninterface ViewState {\n opened: boolean\n seen: Record<string, number>\n held: number[]\n}\n\nconst empty = (): ViewState => ({ opened: false, seen: {}, held: [] })\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parse(raw: string | null, user: string | undefined): ViewState {\n if (!raw) return empty()\n let blob: unknown\n try {\n blob = JSON.parse(raw)\n } catch {\n return empty()\n }\n if (!isRecord(blob) || blob.v !== 1) return empty()\n // One visitor's panel open and held views must not count for the next visitor of the tab. A\n // blob with no user was written while logged out and carries over to whoever logs in.\n if (blob.user !== undefined && blob.user !== user) return empty()\n const state = empty()\n state.opened = blob.opened === true\n if (isRecord(blob.seen)) {\n for (const [key, at] of Object.entries(blob.seen)) {\n if (typeof at === 'number' && Number.isFinite(at)) state.seen[key] = at\n }\n }\n // Held ids are logged when the panel opens, so they are re-checked and capped here: a blob\n // someone edited must not be able to put a bad id, or more events than a batch holds, on the wire.\n if (Array.isArray(blob.held)) {\n state.held = blob.held.filter(isValidId).slice(-HELD_MAX)\n }\n return state\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n try {\n return window.sessionStorage\n } catch {\n return null\n }\n}\n\n/**\n * What this tab has already reported about match views. It lives in sessionStorage because a host\n * can remount the widget on every navigation, and memory would forget that the visitor had opened\n * the panel. After the first storage failure the state lives in memory for the rest of the mount.\n */\nexport function createMatchViews(storageKey: string, options: MatchViewsOptions = {}): MatchViews {\n const now = options.now ?? (() => Date.now())\n const user = options.user\n let storage: Storage | null | undefined = options.storage\n let memory: ViewState = empty()\n\n const read = (): ViewState => {\n if (storage === undefined) storage = browserStorage()\n if (storage) {\n try {\n memory = parse(storage.getItem(storageKey), user)\n } catch {\n storage = null\n }\n }\n return memory\n }\n\n const write = (state: ViewState): void => {\n memory = state\n if (!storage) return\n try {\n storage.setItem(storageKey, JSON.stringify({ v: 1, user, ...state }))\n } catch {\n storage = null\n }\n }\n\n return {\n view(matchId) {\n const at = now()\n const state = read()\n for (const key of Object.keys(state.seen)) {\n if (at - (state.seen[key] ?? 0) >= VIEW_DEDUPE_MS) delete state.seen[key]\n }\n const key = String(matchId)\n if (state.seen[key] !== undefined) return 'duplicate'\n state.seen[key] = at\n let result: ViewResult = 'log'\n if (!state.opened) {\n state.held = [...state.held.filter((id) => id !== matchId), matchId].slice(-HELD_MAX)\n result = 'held'\n }\n write(state)\n return result\n },\n markOpened() {\n const state = read()\n if (state.opened) return []\n const at = now()\n const held = state.held\n // Stamped now, so the dedupe window starts when the row is written, not when it was held.\n for (const id of held) state.seen[String(id)] = at\n write({ opened: true, seen: state.seen, held: [] })\n return held\n },\n }\n}\n","import type { WidgetEventInput } from '@sensiblestats/widget-sdk'\nimport { isValidId } from './host'\nimport { MAX_LINE, MAX_ODDS, MAX_SELECTION } from './slip'\n\nexport const LEDGER_TTL_MS = 7 * 24 * 60 * 60 * 1000\nexport const LEDGER_MAX = 100\n// The most ledger hits one host call reports. The server rejects a batch of more than 50 events\n// and the logger sends its whole queue as one batch, so an uncapped bet could fail a batch and\n// lose every event in it.\nexport const BET_REPORT_MAX = 25\nconst MAX_MARKET = 128\n// The server's floor (WidgetEventBatchRequest.Odds). An event below it fails its whole batch.\nconst MIN_ODDS = 1.0001\n\nexport interface LedgerEntry {\n /** matchOddsId */\n id: number\n /** market developer name */\n market: string\n matchId?: number\n selection?: string\n line?: string\n odds?: number\n /** operatorUserId at add time; absent for an anonymous visitor */\n user?: string\n /** epoch milliseconds */\n at: number\n}\n\nexport interface SlipLedger {\n record(entry: Omit<LedgerEntry, 'at'>): void\n take(id: number, currentUser: string | undefined): LedgerEntry | null\n}\n\nexport interface SlipLedgerOptions {\n /** Defaults to window.localStorage. Pass null for a memory-only ledger. */\n storage?: Storage | null\n now?: () => number\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction fits(value: unknown, max: number): value is string {\n return typeof value === 'string' && value.trim().length > 0 && value.length <= max\n}\n\n// Storage is not trusted: someone can edit the blob, and one bad value in a logged event fails\n// the whole batch at the gateway. An entry that cannot be identified is dropped; a bad optional\n// field is left out and the entry kept.\nfunction clean(item: unknown): LedgerEntry | null {\n if (!isRecord(item)) return null\n const { id, market, at, user } = item\n if (!isValidId(id)) return null\n if (typeof at !== 'number' || !Number.isFinite(at)) return null\n if (!fits(market, MAX_MARKET)) return null\n if (user !== undefined && (typeof user !== 'string' || user.length === 0)) return null\n const entry: LedgerEntry = { id, market, at }\n if (typeof user === 'string') entry.user = user\n if (isValidId(item.matchId)) entry.matchId = item.matchId\n if (fits(item.selection, MAX_SELECTION)) entry.selection = item.selection\n if (fits(item.line, MAX_LINE)) entry.line = item.line\n const odds = item.odds\n if (typeof odds === 'number' && Number.isFinite(odds) && odds >= MIN_ODDS && odds <= MAX_ODDS) entry.odds = odds\n return entry\n}\n\nfunction parse(raw: string | null): LedgerEntry[] {\n if (!raw) return []\n let blob: unknown\n try {\n blob = JSON.parse(raw)\n } catch {\n return []\n }\n if (!isRecord(blob) || blob.v !== 1 || !Array.isArray(blob.entries)) return []\n const entries: LedgerEntry[] = []\n for (const item of blob.entries) {\n const entry = clean(item)\n if (entry) entries.push(entry)\n }\n return entries\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n try {\n return window.localStorage\n } catch {\n return null\n }\n}\n\n/**\n * The widget's record of its own adds, so a later slipRemoved/betPlaced from the host can be\n * reported with the fields the add logged. Every call reads storage, so two tabs share one\n * ledger. After the first storage failure the ledger keeps working from memory for the rest of\n * the mount and stops touching storage.\n */\nexport function createSlipLedger(storageKey: string, options: SlipLedgerOptions = {}): SlipLedger {\n const now = options.now ?? (() => Date.now())\n let storage: Storage | null | undefined = options.storage\n // The entries last read or written. It becomes the ledger itself once storage has failed.\n let memory: LedgerEntry[] = []\n\n const read = (): LedgerEntry[] => {\n if (storage === undefined) storage = browserStorage()\n if (storage) {\n try {\n memory = parse(storage.getItem(storageKey))\n } catch {\n storage = null\n }\n }\n return memory\n }\n\n const write = (entries: LedgerEntry[]): void => {\n memory = entries\n if (!storage) return\n try {\n storage.setItem(storageKey, JSON.stringify({ v: 1, entries }))\n } catch {\n storage = null\n }\n }\n\n const live = (entry: LedgerEntry, at: number): boolean => at - entry.at <= LEDGER_TTL_MS\n\n return {\n record(entry) {\n const at = now()\n const cleaned = clean({ ...entry, at })\n if (!cleaned) return\n const kept = read().filter((e) => e.id !== cleaned.id && live(e, at))\n // Entries are appended in time order, so the last LEDGER_MAX are the newest.\n kept.push(cleaned)\n write(kept.slice(-LEDGER_MAX))\n },\n take(id, currentUser) {\n const at = now()\n const entries = read().filter((e) => live(e, at))\n const index = entries.findIndex((e) => e.id === id)\n const entry = entries[index]\n if (!entry) return null\n // One user's pick must not count for the next user of a shared browser. An entry with no\n // user was added while logged out and belongs to whoever is here now.\n if (entry.user !== undefined && entry.user !== currentUser) return null\n entries.splice(index, 1)\n write(entries)\n return entry\n },\n }\n}\n\n/** The wire event for a host call that hit this entry: the same fields the add logged. A field\n * the entry lacks is undefined here and so absent from the JSON that goes out. */\nexport function toSlipEvent(name: 'slip_remove' | 'bet_placed', entry: LedgerEntry): WidgetEventInput {\n return {\n name, entityType: 'market', entityId: entry.market, marketDeveloperName: entry.market,\n matchId: entry.matchId, selection: entry.selection, line: entry.line, odds: entry.odds,\n }\n}\n","import { ENTITY_TYPE_CODES, type Conversation, type EventLogger, type GreetingDashboardLayout, type GreetingDashboardTile, type SignalEntityType, type WidgetEntityType } from '@sensiblestats/widget-sdk'\n\nexport type DashboardTapHandler = (tile: GreetingDashboardTile, index: number, layout: GreetingDashboardLayout) => void\n\n// tile.signal.entityType is a plain string on the wire (GreetingDashboardSignalRef), so a value\n// outside the union must be checked, not asserted -- an unchecked cast would let an unrecognised\n// value reach toSignalWireBody, which throws synchronously and is swallowed by the try/catch\n// below, silently dropping the tap the same way an unresolved entityId used to.\nfunction isSignalEntityType(value: string): value is SignalEntityType {\n return Object.prototype.hasOwnProperty.call(ENTITY_TYPE_CODES, value)\n}\n\n// The server's GreetingDashboardSignalRef.entityType is PascalCase ('Team', 'Market', ...) and\n// carries a couple of values (Article/Session/Query/Conversation) that have no widget-event\n// counterpart -- those, and anything unrecognised, map to null so the caller can skip the emit\n// instead of sending a bogus entityType.\nfunction toWidgetEntityType(value: string): WidgetEntityType | null {\n switch (value.toLowerCase()) {\n case 'match': return 'match'\n case 'team': return 'team'\n case 'player': return 'player'\n case 'competition': return 'competition'\n case 'market': return 'market'\n default: return null\n }\n}\n\n/**\n * Builds the tap-to-signal side effect for a greeting dashboard tile.\n * Every tap is a MarketView signal (spec 9.4) regardless of the tile's own entity type --\n * entityType/entityId identify what was tapped, dashboardLayout/tileIndex identify where.\n *\n * `log` is threaded in as a parameter (not read via `useEventLog()`) because this module is a\n * plain factory, not a component or hook -- the caller (a component) owns the logger instance.\n */\nexport function createDashboardTapSignal(sendSignal: Conversation['sendSignal'], log?: EventLogger | null): DashboardTapHandler {\n return (tile, index, layout) => {\n const widgetEntityType = toWidgetEntityType(tile.signal.entityType)\n if (widgetEntityType) {\n log?.log({ name: 'tile_tap', entityType: widgetEntityType, entityId: tile.signal.entityId })\n }\n if (!isSignalEntityType(tile.signal.entityType)) return\n // sendSignal throws synchronously with no identity configured, and its returned promise\n // can reject on a gateway failure. Neither may break the tap -- the message this tile sent\n // still has to reach the model even when the Interest Engine can't be reached.\n try {\n void sendSignal({\n signalType: 'MarketView',\n entityType: tile.signal.entityType,\n entityId: tile.signal.entityId,\n dashboardLayout: layout,\n tileIndex: index,\n }).catch(() => undefined)\n } catch {\n // ignored -- see comment above\n }\n }\n}\n","import type { UiConfig } from './config'\n\nexport interface ThemeAttrs {\n 'data-ss-w-theme': string\n 'data-ss-w-pos': string\n style: Record<string, string>\n}\n\nexport function themeAttrs(ui: UiConfig): ThemeAttrs {\n const style: Record<string, string> = {\n '--ss-w-offset-x': `${ui.offset.x}px`,\n '--ss-w-offset-y': `${ui.offset.y}px`,\n '--ss-w-radius': `${ui.radius}px`,\n }\n if (ui.accent) style['--ss-w-accent'] = ui.accent\n if (ui.cta) style['--ss-w-cta'] = ui.cta\n if (ui.surface) style['--ss-w-panel'] = ui.surface\n if (ui.ink) style['--ss-w-ink'] = ui.ink\n if (ui.surface && ui.ink) {\n style['--ss-w-bubble'] = 'color-mix(in srgb, var(--ss-w-ink) 5%, var(--ss-w-panel))'\n style['--ss-w-line'] = 'color-mix(in srgb, var(--ss-w-ink) 12%, var(--ss-w-panel))'\n style['--ss-w-faint'] = 'color-mix(in srgb, var(--ss-w-ink) 55%, var(--ss-w-panel))'\n }\n return { 'data-ss-w-theme': ui.theme, 'data-ss-w-pos': ui.position, style }\n}\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'\nimport type { ChatGrounding, ChatHandle, ChatInput, Conversation } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { reducer, initialState, type WidgetState, type AssistantTurn } from './reducer'\nimport { chipFromText } from './model'\nimport { useLiveDashboardPoll } from './useLiveDashboardPoll'\nimport { readConversation, writeConversation, clearConversation } from './conversationStore'\n\n// An assistant turn counts as an answer only if it carries something to show. Deliberately\n// excludes `actions` -- follow-up chips are not answer content, so an errored turn that only\n// has fallback chips must not count as answered.\nfunction hasAnswerContent(t: AssistantTurn): boolean {\n return !!t.text || t.cards.length > 0 || t.insights.length > 0 ||\n t.marketOdds.length > 0 || t.oddsMovement.length > 0 ||\n !!t.greetingDashboard || !!t.clubFanDashboard\n}\n\n// If the server never emits a terminal event (turn_complete/error) within this window, the\n// panel would otherwise spin forever -- an async generator that just ends without yielding a\n// terminal event leaves isStreaming stuck at true, since only turn_complete/error/STOP clear it.\nexport const STREAM_FALLBACK_TIMEOUT_MS = 30_000\n\n// Next id must not collide with restored m{n} ids (React keys + live-dashboard id matching).\nfunction seedIdCounter(messages: { id: string }[]): number {\n let max = -1\n for (const m of messages) {\n const n = Number(m.id.slice(1)) // ids are `m${n}`\n if (m.id[0] === 'm' && Number.isFinite(n) && n > max) max = n\n }\n return max + 1\n}\n\nexport interface SendOptions {\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap) — forwarded on ChatInput.actionRef. */\n actionRef?: string\n /** Text shown in the user bubble when it differs from the message sent upstream (e.g. an action's label). */\n displayText?: string\n /** Structured context for the turn (a tapped live fact) — forwarded on ChatInput.grounding. */\n grounding?: ChatGrounding\n}\n\nexport interface ChatController {\n state: WidgetState\n open(): void\n close(): void\n stop(): void\n toggle(): void\n send(text: string, opts?: SendOptions): void\n retry(): void\n dismissPopup(): void\n reset(): void\n}\n\nexport function useChatStream(conversation: Conversation, starterTexts: string[], greetingMessage?: string, storageKey?: string): ChatController {\n const boot = useMemo(() => {\n const payload = storageKey ? readConversation(storageKey, Date.now()) : null\n const restored = payload != null && payload !== 'expired' && payload !== 'corrupt'\n const base = initialState(starterTexts.map(chipFromText))\n if (restored) {\n return { state: { ...base, messages: payload.messages, conversationId: payload.conversationId, starters: [] }, restored: true, stale: false }\n }\n return { state: base, restored: false, stale: payload === 'expired' || payload === 'corrupt' }\n }, [])\n const [state, dispatch] = useReducer(reducer, boot.state)\n const idRef = useRef(seedIdCounter(boot.state.messages))\n const handleRef = useRef<ChatHandle | null>(null)\n const fallbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const stateRef = useRef(state)\n stateRef.current = state\n const greetedRef = useRef(boot.restored) // restored -> greeting already \"handled\" (suppressed)\n const hydratedRef = useRef(false) // suppresses the single re-persist a cross-tab sync would echo\n\n const restoreSeededRef = useRef(false)\n if (!restoreSeededRef.current) {\n restoreSeededRef.current = true\n if (boot.restored && boot.state.conversationId) conversation.conversationId = boot.state.conversationId\n }\n\n const nextId = () => `m${idRef.current++}`\n\n const clearFallbackTimer = useCallback(() => {\n if (fallbackTimerRef.current != null) {\n clearTimeout(fallbackTimerRef.current)\n fallbackTimerRef.current = null\n }\n }, [])\n\n // Arms a watchdog for one in-flight send. clearFallbackTimer() is called on every path that\n // supersedes this send (a newer run(), stop(), close()) or that sees a terminal event, so a\n // firing timer always means neither happened in time -- including the case where the async\n // generator simply ends without ever yielding turn_complete/error: consume()'s own `finally`\n // nulls handleRef as soon as that happens, so this cannot key off handle identity (it would\n // already look \"stale\" and the very hang it exists to catch would go unreported).\n const armFallbackTimer = useCallback((onFire: () => void) => {\n clearFallbackTimer()\n fallbackTimerRef.current = setTimeout(() => {\n fallbackTimerRef.current = null\n handleRef.current?.cancel()\n handleRef.current = null\n onFire()\n }, STREAM_FALLBACK_TIMEOUT_MS)\n }, [clearFallbackTimer])\n\n const consume = useCallback((handle: ChatHandle, onError: (err: WidgetSdkError) => void) => {\n ;(async () => {\n try {\n for await (const event of handle) {\n dispatch({ kind: 'EVENT', event })\n if (event.type === 'turn_complete' || event.type === 'error') clearFallbackTimer()\n }\n } catch (err) {\n // A superseded handle's late rejection (run() already cancelled it and armed a new\n // timer for the newer send) must not touch the current send's timer -- only clear here\n // when this handle is still the one in flight.\n if (handleRef.current === handle) clearFallbackTimer()\n if (err instanceof WidgetSdkError) onError(err)\n else if ((err as { name?: string } | null)?.name === 'AbortError') { /* expected on cancel/close — ignore */ }\n else throw err\n } finally {\n if (handleRef.current === handle) handleRef.current = null\n }\n })()\n }, [clearFallbackTimer])\n\n const run = useCallback((input: ChatInput, displayText?: string) => {\n handleRef.current?.cancel()\n clearFallbackTimer()\n dispatch({ kind: 'USER_SENT', input, userId: nextId(), assistantId: nextId(), displayText })\n const handle = conversation.send(input)\n handleRef.current = handle\n armFallbackTimer(() => {\n dispatch({ kind: 'STOP' })\n dispatch({ kind: 'STREAM_ERROR', error: new WidgetSdkError('No response received in time', 'timeout') })\n })\n consume(handle, (err) => dispatch({ kind: 'STREAM_ERROR', error: err }))\n }, [conversation, consume, clearFallbackTimer, armFallbackTimer])\n\n const send = useCallback((text: string, opts?: SendOptions) => {\n const trimmed = text.trim()\n if (!trimmed) return\n run({ message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef, grounding: opts?.grounding }, opts?.displayText)\n }, [run])\n\n const retry = useCallback(() => {\n const last = stateRef.current.lastUserInput\n if (last) run(last, stateRef.current.lastDisplayText ?? undefined)\n }, [run])\n\n // Auto-greeting: fire once on mount when configured (and not restored from storage). No\n // user bubble; its response becomes the launcher popup. Fire-and-forget — failures\n // (including a fallback timeout) are swallowed (STOP only, no visible error) since this is\n // non-critical background chatter. Also reused by reset() to re-greet after clearing.\n const fireGreeting = useCallback(() => {\n const message = greetingMessage?.trim()\n if (!message) return\n try {\n handleRef.current?.cancel()\n clearFallbackTimer()\n dispatch({ kind: 'GREETING_SENT', assistantId: nextId() })\n const handle = conversation.send({ message })\n handleRef.current = handle\n armFallbackTimer(() => dispatch({ kind: 'STOP' }))\n consume(handle, () => dispatch({ kind: 'STOP' }))\n } catch {\n dispatch({ kind: 'STOP' })\n }\n }, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer])\n\n useEffect(() => {\n if (greetedRef.current) return // restored, or already greeted\n greetedRef.current = true\n fireGreeting()\n }, [fireGreeting])\n\n // Clear a stale/corrupt blob once, from an effect (never during the render seed).\n useEffect(() => {\n if (boot.stale && storageKey) clearConversation(storageKey)\n }, [])\n\n // Persist only complete exchanges after each settle (never mid-stream, never the greeting).\n // A user message is kept only when its paired assistant turn (USER_SENT always pushes\n // [user, assistant] together) is done, non-greeting, and has real content -- this drops a\n // trailing unanswered question (panel closed mid-stream) and an empty errored bubble alike.\n useEffect(() => {\n if (!storageKey || state.isStreaming) return\n if (hydratedRef.current) { hydratedRef.current = false; return } // don't echo a sync back out\n const msgs = state.messages\n const persistable = msgs.filter((m, i) => {\n if (m.role === 'user') {\n const next = msgs[i + 1]\n return !!next && next.role === 'assistant' && next.done && !next.isGreeting && hasAnswerContent(next)\n }\n return m.done && !m.isGreeting && hasAnswerContent(m)\n })\n if (persistable.length === 0) return\n writeConversation(storageKey, state.conversationId, persistable, Date.now())\n }, [storageKey, state.isStreaming, state.messages, state.conversationId])\n\n // Live multi-tab sync: mirror another tab's write/clear of the shared conversation.\n useEffect(() => {\n if (!storageKey) return\n const onStorage = (e: StorageEvent) => {\n if (e.key !== storageKey || e.storageArea !== window.localStorage) return\n if (stateRef.current.isStreaming) return // never clobber an in-flight turn in this tab\n if (e.newValue == null) {\n // cleared elsewhere (New conversation / expiry) -> mirror a fresh conversation\n idRef.current = 0\n conversation.conversationId = undefined\n hydratedRef.current = true\n dispatch({ kind: 'RESET' })\n greetedRef.current = true\n fireGreeting()\n return\n }\n const parsed = readConversation(storageKey, Date.now())\n if (!parsed || parsed === 'expired' || parsed === 'corrupt') return\n idRef.current = seedIdCounter(parsed.messages)\n conversation.conversationId = parsed.conversationId ?? undefined\n hydratedRef.current = true\n dispatch({ kind: 'RESTORE', messages: parsed.messages, conversationId: parsed.conversationId })\n }\n window.addEventListener('storage', onStorage)\n return () => window.removeEventListener('storage', onStorage)\n }, [storageKey, conversation, fireGreeting])\n\n const open = useCallback(() => dispatch({ kind: 'OPEN' }), [])\n const close = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'CLOSE' }) }, [clearFallbackTimer])\n const stop = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'STOP' }) }, [clearFallbackTimer])\n const toggle = useCallback(() => { if (stateRef.current.isOpen) close(); else open() }, [close, open])\n const dismissPopup = useCallback(() => dispatch({ kind: 'DISMISS_POPUP' }), [])\n\n const reset = useCallback(() => {\n handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer()\n if (storageKey) clearConversation(storageKey)\n idRef.current = 0\n conversation.conversationId = undefined\n dispatch({ kind: 'RESET' })\n greetedRef.current = true\n fireGreeting()\n }, [storageKey, conversation, clearFallbackTimer, fireGreeting])\n\n const getLiveDashboard = useCallback(() => conversation.getLiveDashboard(), [conversation])\n useLiveDashboardPoll({ messages: state.messages, dispatch, getLiveDashboard })\n\n return { state, open, close, stop, toggle, send, retry, dismissPopup, reset }\n}\n","import type { ChatEvent, ChatInput, ClubFanDashboardCard, ClubFanDashboardPayload, GreetingDashboard, StreamErrorEventData } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { toActionVM, toCardVM, toChipVM, toInsightVM, toMarketOddsVM, toOddsMovementVM, type ActionVM, type CardVM, type ChipVM, type InsightVM, type MarketOddsVM, type OddsMovementVM } from './model'\n\nexport interface UserMessage { role: 'user'; id: string; text: string }\nexport interface AssistantTurn { role: 'assistant'; id: string; text: string; cards: CardVM[]; actions: ActionVM[]; insights: InsightVM[]; marketOdds: MarketOddsVM[]; oddsMovement: OddsMovementVM[]; done: boolean; isGreeting?: boolean; greetingDashboard?: GreetingDashboard; clubFanDashboard?: ClubFanDashboardPayload }\nexport type Message = UserMessage | AssistantTurn\n\nexport interface WidgetState {\n isOpen: boolean\n messages: Message[]\n isStreaming: boolean\n status: string | null\n actionsLoading: boolean\n starters: ChipVM[]\n configuredStarters: ChipVM[]\n error: StreamErrorEventData | WidgetSdkError | null\n lastUserInput: ChatInput | null\n lastDisplayText: string | null\n // Launcher popup text (the auto-greeting response). Cleared on open/dismiss.\n popupText: string | null\n conversationId: string | null\n}\n\nexport type Action =\n | { kind: 'OPEN' }\n | { kind: 'CLOSE' }\n | { kind: 'USER_SENT'; input: ChatInput; userId: string; assistantId: string; displayText?: string }\n | { kind: 'GREETING_SENT'; assistantId: string }\n | { kind: 'EVENT'; event: ChatEvent }\n | { kind: 'STREAM_ERROR'; error: WidgetSdkError }\n | { kind: 'STOP' }\n | { kind: 'DISMISS_POPUP' }\n | { kind: 'LIVE_REFRESH'; messageId: string; cards: ClubFanDashboardCard[]; greeting?: string }\n | { kind: 'LIVE_TRANSITION'; messageId: string; dashboard: ClubFanDashboardPayload }\n | { kind: 'RESET' }\n | { kind: 'RESTORE'; messages: Message[]; conversationId: string | null }\n\nconst POPUP_MAX = 160\n\nexport function initialState(starters: ChipVM[]): WidgetState {\n return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, starters, configuredStarters: starters, error: null, lastUserInput: null, lastDisplayText: null, popupText: null, conversationId: null }\n}\n\nfunction activeTurn(state: WidgetState): AssistantTurn | null {\n const last = state.messages[state.messages.length - 1]\n return last && last.role === 'assistant' && !last.done ? last : null\n}\n\nfunction mapActive(state: WidgetState, fn: (t: AssistantTurn) => AssistantTurn): Message[] {\n const last = state.messages[state.messages.length - 1]\n if (!last || last.role !== 'assistant' || last.done) return state.messages\n return [...state.messages.slice(0, -1), fn(last)]\n}\n\nfunction applyEvent(state: WidgetState, event: ChatEvent): WidgetState {\n switch (event.type) {\n case 'progress':\n return { ...state, status: event.data.message }\n case 'answer':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, text: event.data.text })) }\n case 'entity_card': {\n if (event.data.card.isUsed === false) return state\n const card = toCardVM(event.data.card)\n // Generic cards (coach/referee/stadium/competition — anything not team or\n // player) carry no distinct identity and add no user value; drop them until\n // a purpose-built variant exists.\n if (card.kind === 'generic') return state\n return { ...state, messages: mapActive(state, (t) => ({ ...t, cards: [...t.cards, card] })) }\n }\n case 'action_button':\n return { ...state, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, actions: [...t.actions, toActionVM(event.data.action)] })) }\n case 'betting_insight':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, insights: [...t.insights, toInsightVM(event.data.insight)] })) }\n case 'market_odds':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, marketOdds: [...t.marketOdds, toMarketOddsVM(event.data.card)] })) }\n case 'odds_movement':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, oddsMovement: [...t.oddsMovement, toOddsMovementVM(event.data.card)] })) }\n case 'intent_chip': {\n const chip = toChipVM(event.data.intent)\n return chip ? { ...state, starters: [...state.starters, chip] } : state\n }\n case 'actions_loading':\n return { ...state, actionsLoading: true, status: event.data.message }\n case 'turn_complete': {\n const active = activeTurn(state)\n // A completed greeting turn surfaces its message as the launcher popup (unless already open).\n // The club fan dashboard carries its greeting line in the payload rather than as answer\n // text, so prefer that; fall back to any streamed answer text for other greeting shapes.\n const greetingLine = event.data.clubFanDashboard?.greeting?.trim() || (active?.text.trim() ?? '')\n const popupText = active?.isGreeting && !state.isOpen && greetingLine ? greetingLine.slice(0, POPUP_MAX) : state.popupText\n return {\n ...state, isStreaming: false, status: null, actionsLoading: false, popupText,\n conversationId: event.data.conversationId ?? state.conversationId,\n messages: mapActive(state, (t) => ({\n ...t,\n done: true,\n greetingDashboard: event.data.dashboard ?? undefined,\n clubFanDashboard: event.data.clubFanDashboard ?? undefined,\n })),\n }\n }\n case 'error': {\n // A failed greeting fails silently — it's non-critical background chatter.\n const suppress = activeTurn(state)?.isGreeting === true\n return { ...state, error: suppress ? state.error : event.data, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n }\n }\n // Unknown/unmodelled event type: never return undefined — that would corrupt\n // state and crash the next dispatch. Ignore the event and keep state intact.\n return state\n}\n\nexport function reducer(state: WidgetState, action: Action): WidgetState {\n switch (action.kind) {\n case 'OPEN':\n return { ...state, isOpen: true, popupText: null }\n case 'CLOSE':\n return { ...state, isOpen: false, isStreaming: false, status: null, actionsLoading: false }\n case 'USER_SENT': {\n const user: UserMessage = { role: 'user', id: action.userId, text: action.displayText ?? action.input.message }\n const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false }\n return { ...state, messages: [...state.messages, user, assistant], isStreaming: true, status: null, actionsLoading: false, starters: [], error: null, lastUserInput: action.input, lastDisplayText: action.displayText ?? null }\n }\n case 'GREETING_SENT': {\n // Auto-greeting: no user bubble; the assistant turn is flagged so its completion sets the popup.\n const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false, isGreeting: true }\n return { ...state, messages: [...state.messages, assistant], isStreaming: true, status: null, error: null }\n }\n case 'DISMISS_POPUP':\n return { ...state, popupText: null }\n case 'RESET':\n // Preserve panel open/closed state: \"New conversation\" is an in-panel control, so the\n // panel must stay open with the fresh greeting rather than snapping shut. Cross-tab\n // clear-mirroring likewise keeps each tab's panel as it was.\n return { ...initialState(state.configuredStarters), isOpen: state.isOpen }\n case 'RESTORE':\n return {\n ...state,\n messages: action.messages,\n conversationId: action.conversationId,\n isStreaming: false,\n status: null,\n actionsLoading: false,\n starters: action.messages.length ? [] : state.configuredStarters,\n error: null,\n }\n case 'EVENT':\n return applyEvent(state, action.event)\n case 'STREAM_ERROR':\n return { ...state, error: action.error, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n case 'STOP':\n return { ...state, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n case 'LIVE_REFRESH':\n return {\n ...state,\n messages: state.messages.map((m) =>\n m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n ? { ...m, clubFanDashboard: { ...m.clubFanDashboard, cards: action.cards, greeting: action.greeting ?? m.clubFanDashboard.greeting } }\n : m,\n ),\n }\n case 'LIVE_TRANSITION':\n return {\n ...state,\n messages: state.messages.map((m) =>\n m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n ? { ...m, clubFanDashboard: action.dashboard }\n : m,\n ),\n }\n }\n}\n","import { useEffect, useReducer, useRef } from 'react'\nimport type { ClubFanDashboardPayload, CountdownCard } from '@sensiblestats/widget-sdk'\nimport type { Action, Message } from './reducer'\n\nconst POLL_INTERVAL_MS = 60_000\nconst LEAD_MS = 120_000 // start polling 2 min before kickoff\nconst GIVE_UP_MS = 30 * 60_000 // stop polling 30 min after kickoff if match never went live\n\ntype Anchor =\n | { messageId: string; kind: 'live' }\n | { messageId: string; kind: 'preMatch'; kickoffMs: number }\n\nexport interface UseLiveDashboardPollOptions {\n messages: Message[]\n dispatch: (action: Action) => void\n getLiveDashboard: () => Promise<ClubFanDashboardPayload | null>\n}\n\nfunction extractKickoffMs(dashboard: ClubFanDashboardPayload): number | null {\n const countdown = dashboard.cards.find((c): c is CountdownCard => c.cardType === 'countdown')\n if (countdown) return countdown.data.kickoffUnix * 1_000\n // fall back to any card that exposes kickoffUnix in its data\n for (const c of dashboard.cards) {\n const d = (c as { data?: { kickoffUnix?: number } }).data\n if (typeof d?.kickoffUnix === 'number') return d.kickoffUnix * 1_000\n }\n return null\n}\n\n// Returns the most recent assistant message that can serve as a polling anchor:\n// — a live dashboard (always valid), or\n// — a preMatch dashboard whose kickoff is within [kickoff − LEAD_MS, kickoff + GIVE_UP_MS].\nfunction findAnchor(messages: Message[]): Anchor | null {\n const now = Date.now()\n for (const m of messages.slice().reverse()) {\n if (m.role !== 'assistant' || !m.clubFanDashboard) continue\n const { phase } = m.clubFanDashboard\n if (phase === 'live') return { messageId: m.id, kind: 'live' }\n if (phase === 'preMatch') {\n const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n if (kickoffMs === null) continue\n if (now >= kickoffMs - LEAD_MS && now <= kickoffMs + GIVE_UP_MS) {\n return { messageId: m.id, kind: 'preMatch', kickoffMs }\n }\n }\n }\n return null\n}\n\n// Returns the earliest future wakeup time for a preMatch dashboard that is not yet within the\n// poll window (kickoff − LEAD_MS still in the future). Returns null if none.\nfunction findEarliestWakeupMs(messages: Message[]): number | null {\n const now = Date.now()\n let earliest: number | null = null\n for (const m of messages) {\n if (m.role !== 'assistant' || m.clubFanDashboard?.phase !== 'preMatch') continue\n const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n if (kickoffMs === null) continue\n const wakeAt = kickoffMs - LEAD_MS\n if (wakeAt > now && (earliest === null || wakeAt < earliest)) earliest = wakeAt\n }\n return earliest\n}\n\n// Polls the live club-fan dashboard every 60s for the chosen anchor:\n//\n// — Live anchor: on a live payload → LIVE_REFRESH (cards + greeting). On a post-match payload →\n// LIVE_TRANSITION (full swap to the post-match dashboard) and stop polling. On null → stop.\n// — PreMatch anchor: on a live payload → LIVE_TRANSITION (full payload swap). On null → keep\n// polling (pre-kickoff 204s) but give up if now > kickoff + GIVE_UP_MS.\n//\n// Wake-up: if a preMatch dashboard's window hasn't opened yet (kickoff − 2min still in the\n// future), schedules a setTimeout to trigger a re-render exactly when polling should begin.\nexport function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }: UseLiveDashboardPollOptions): void {\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0)\n const anchor = findAnchor(messages)\n const anchorRef = useRef<Anchor | null>(anchor)\n anchorRef.current = anchor\n const inFlightRef = useRef(false)\n\n // Polling effect — keyed on the anchor identity so it restarts when anchor changes.\n const anchorKey = anchor ? `${anchor.messageId}:${anchor.kind}` : null\n\n useEffect(() => {\n if (!anchorKey || !anchorRef.current) return\n\n const tick = async () => {\n if (inFlightRef.current) return\n inFlightRef.current = true\n try {\n const payload = await getLiveDashboard()\n const current = anchorRef.current\n if (!current) return\n\n if (payload?.phase === 'live') {\n if (current.kind === 'preMatch') {\n dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n window.clearInterval(id)\n } else {\n dispatch({ kind: 'LIVE_REFRESH', messageId: current.messageId, cards: payload.cards, greeting: payload.greeting })\n }\n } else if (payload?.phase === 'postMatch' && current.kind === 'live') {\n // Match ended: the poll now returns the post-match dashboard. Swap the live card for it\n // and stop polling (the anchor is no longer live).\n dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n window.clearInterval(id)\n } else {\n // null (204) or non-live phase with no payload\n if (current.kind === 'live') {\n window.clearInterval(id)\n } else if (Date.now() > current.kickoffMs + GIVE_UP_MS) {\n window.clearInterval(id)\n }\n // preMatch within window: keep polling (these are pre-kickoff 204s)\n }\n } catch {\n // A network error must not crash the widget or stop the loop — swallow and retry\n // on the next tick.\n } finally {\n inFlightRef.current = false\n }\n }\n\n const id = window.setInterval(() => { void tick() }, POLL_INTERVAL_MS)\n return () => window.clearInterval(id)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [anchorKey, dispatch, getLiveDashboard])\n\n // Wake-up effect — schedules a re-render when a preMatch window opens in the future.\n useEffect(() => {\n if (anchorKey !== null) return // already polling, no wake-up needed\n const wakeAt = findEarliestWakeupMs(messages)\n if (wakeAt === null) return\n const delay = wakeAt - Date.now()\n if (delay <= 0) return\n const id = window.setTimeout(forceUpdate, delay)\n return () => window.clearTimeout(id)\n }, [anchorKey, messages, forceUpdate])\n}\n","import type { Message } from './reducer'\n\nexport const TTL_MS = 3_600_000\nexport const MAX_MESSAGES = 30\n\nexport interface StoredPayload {\n conversationId: string | null\n messages: Message[]\n}\n\ninterface StoredConversation {\n v: 1\n updatedAt: number\n conversationId: string | null\n messages: Message[]\n}\n\n// Pure read: returns the payload when a v:1 blob exists and is within TTL; a sentinel the caller\n// clears from an effect (never during render) when stale/unparseable; null when absent.\nexport function readConversation(storageKey: string, now: number): StoredPayload | 'expired' | 'corrupt' | null {\n let raw: string | null\n try {\n raw = window.localStorage.getItem(storageKey)\n } catch {\n return null // SSR / storage blocked\n }\n if (!raw) return null\n let parsed: StoredConversation\n try {\n parsed = JSON.parse(raw) as StoredConversation\n } catch {\n return 'corrupt'\n }\n if (parsed?.v !== 1 || !Array.isArray(parsed.messages) || typeof parsed.updatedAt !== 'number') return 'corrupt'\n if (now - parsed.updatedAt > TTL_MS) return 'expired'\n return { conversationId: parsed.conversationId ?? null, messages: parsed.messages }\n}\n\nexport function writeConversation(storageKey: string, conversationId: string | null, messages: Message[], now: number): void {\n let capped = messages.slice(-MAX_MESSAGES)\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, updatedAt: now, conversationId, messages: capped } satisfies StoredConversation))\n return\n } catch {\n // quota / blocked: drop the oldest half and retry once, then give up (in-memory only)\n if (capped.length <= 1) return\n capped = capped.slice(Math.ceil(capped.length / 2))\n }\n }\n}\n\nexport function clearConversation(storageKey: string): void {\n try {\n window.localStorage.removeItem(storageKey)\n } catch {\n // no-op\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LiveMonitorEvent, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from '@sensiblestats/widget-sdk'\nimport { createPinStore, type PinAddResult, type PinStore } from './pinStore'\nimport { useTabs, type WidgetTab } from './useTabs'\n\n// Re-exported for back-compat; callers that already import MonitorTab continue to compile.\nexport type MonitorTab = WidgetTab\n\nexport interface LiveMonitorController {\n /** Starts TRUE (the server-side pinEnabled flag is the real affordance gate); flips to\n * false permanently for the session on a 404 (null snapshot) from the monitor endpoint. */\n enabled: boolean\n pins: PinRef[]\n snapshot: LiveMonitorSnapshot | null\n activeTab: WidgetTab\n setActiveTab(tab: WidgetTab): void\n togglePin(pin: PinRef): PinAddResult\n isPinned(key: string): boolean\n /** Set by ChatPanel when a reply lands off-tab; cleared on chat tab. */\n chatDot: boolean\n markChatActivity(): void\n /** A goal/red event arrived on a pinned match since Maçlar was last viewed. */\n matchesDot: boolean\n /** A pinned market's price changed since Oranlar was last viewed. */\n oddsDot: boolean\n /** The live count rose from zero while Today was off-screen; suppressed on the active tab. */\n todayDot: boolean\n /** Set by the discovery owner when the live count rises from zero (mirrors markChatActivity). */\n markTodayActivity(): void\n /** Last-viewed price per pin key, for client-side movement badges. */\n lastViewedPrices: Record<string, number>\n /** The currently open accordion market per matchId (null = collapsed). One open at a time per match. */\n openMarket: Record<number, string | null>\n /** Lazy per-market odds cache, keyed `${matchId}:${marketDeveloperName}`. */\n marketOdds: Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n toggleMarket(matchId: number, marketDeveloperName: string): void\n /** Refetches a market's odds WITHOUT touching openMarket -- the tap-to-retry affordance for a\n * market that is already open and errored. toggleMarket would collapse it instead (it flips\n * openMarket unconditionally), which is the wrong move when the row is already showing. */\n retryMarket(matchId: number, marketDeveloperName: string): void\n /** Internal seam: applies a freshly-fetched snapshot (or null on a 404). The poll loop calls\n * this repeatedly; tests call it directly to drive dot/grace logic without a live timer.\n * Not part of the poll cadence/visibility policy itself. */\n _setSnapshot(next: LiveMonitorSnapshot | null): void\n}\n\nexport interface UseLiveMonitorOptions {\n getLiveMonitor: (pins: PinRef[]) => Promise<LiveMonitorSnapshot | null>\n getMarketOdds?: (matchId: number, marketDeveloperName: string) => Promise<MarketOddsBlock | null>\n storageKey: string\n /** false -> true transitions trigger an immediate poll tick (widget open). */\n isOpen: boolean\n /** Whether the Today tab currently has content -- picks the fallback target when a pinned tab\n * disappears, and sends the user to Chat when Today itself empties under them. */\n hasToday?: boolean\n}\n\nconst GOAL_OR_RED: ReadonlySet<LiveMonitorEvent['type']> = new Set(['goal', 'red'])\nconst MIN_POLL_MS = 5_000\nconst DEFAULT_POLL_MS = 60_000\n\nfunction eventIdentity(e: LiveMonitorEvent): string {\n return `${e.type}:${e.side}:${e.minuteLabel}:${e.player ?? ''}`\n}\n\nfunction priceForPin(snapshot: LiveMonitorSnapshot | null, pin: PinRef): number | undefined {\n if (!snapshot) return undefined\n const market = snapshot.markets.find((m) => m.key === pin.key)\n const rows = market?.card?.rows\n if (!rows || rows.length === 0) return undefined\n const row = pin.matchOddsId != null ? rows.find((r) => r.matchOddsId === pin.matchOddsId) : rows[0]\n return row?.price\n}\n\nfunction phaseForPin(snapshot: LiveMonitorSnapshot, pin: PinRef): string | undefined {\n if (pin.kind === 'match') return snapshot.matches.find((m) => m.matchId === pin.matchId)?.phase\n return snapshot.markets.find((mk) => mk.key === pin.key)?.phase\n}\n\nexport function useLiveMonitor(opts: UseLiveMonitorOptions): LiveMonitorController {\n const sessionIdRef = useRef(crypto.randomUUID())\n\n const [pins, setPins] = useState<PinRef[]>([])\n // Lazy initializer: the store fires an initial (no-op-from-the-caller's-view) onChange\n // synchronously during construction, which is a same-component render-phase state update\n // React explicitly supports — it must not run in an effect/later render.\n const [store] = useState<PinStore>(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins))\n\n const [enabled, setEnabled] = useState(true)\n const [snapshot, setSnapshotState] = useState<LiveMonitorSnapshot | null>(null)\n const { activeTab, setActiveTab: setActiveTabState } = useTabs('chat')\n const [chatDot, setChatDot] = useState(false)\n const [matchesDot, setMatchesDot] = useState(false)\n const [oddsDot, setOddsDot] = useState(false)\n const [todayDot, setTodayDot] = useState(false)\n const [lastViewedPrices, setLastViewedPrices] = useState<Record<string, number>>({})\n const [openMarket, setOpenMarket] = useState<Record<number, string | null>>({})\n const [marketOdds, setMarketOdds] = useState<\n Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n >({})\n\n const pinsRef = useRef(pins)\n pinsRef.current = pins\n const activeTabRef = useRef(activeTab)\n activeTabRef.current = activeTab\n const snapshotRef = useRef(snapshot)\n snapshotRef.current = snapshot\n const lastViewedPricesRef = useRef(lastViewedPrices)\n lastViewedPricesRef.current = lastViewedPrices\n const openMarketRef = useRef(openMarket)\n openMarketRef.current = openMarket\n const marketOddsRef = useRef(marketOdds)\n marketOddsRef.current = marketOdds\n const hasToday = opts.hasToday ?? false\n\n const marketKey = (matchId: number, dev: string): string => `${matchId}:${dev}`\n\n const getMarketOddsRef = useRef(opts.getMarketOdds)\n getMarketOddsRef.current = opts.getMarketOdds // latest-fn pattern; fetchMarket reads the ref, deps stay stable\n\n // Stable identity ([] deps, refs only) so callers (applySnapshot, tick) can invoke it without\n // needing to sit in a dependency array.\n const fetchMarket = useCallback((matchId: number, dev: string) => {\n const key = marketKey(matchId, dev)\n const existing = marketOddsRef.current[key]\n if (existing?.loading) return // already in flight -- don't double-fetch\n const loadingEntry = { ...existing, loading: true, error: false }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: loadingEntry }\n setMarketOdds((prev) => ({ ...prev, [key]: loadingEntry }))\n const fn = getMarketOddsRef.current\n if (!fn) return\n void fn(matchId, dev)\n .then((block) => {\n const entry = { block: block ?? undefined, loading: false, error: false }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n })\n .catch(() => {\n const entry = { ...marketOddsRef.current[key], loading: false, error: true }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n })\n }, [])\n\n const toggleMarket = useCallback((matchId: number, dev: string) => {\n const key = marketKey(matchId, dev)\n const wasOpen = openMarketRef.current[matchId] === dev\n const nextValue = wasOpen ? null : dev\n openMarketRef.current = { ...openMarketRef.current, [matchId]: nextValue }\n setOpenMarket((prev) => ({ ...prev, [matchId]: nextValue }))\n // Opening a market that isn't cached yet -- fetch it. A successfully-cached reopen is a\n // no-op fetch, but an entry that previously errored (no block) MUST be retried, not\n // treated as \"cached\" -- that's what drives the tap-to-retry affordance (Task 9).\n const existing = marketOddsRef.current[key]\n if (!wasOpen && !(existing?.loading || existing?.block)) {\n fetchMarket(matchId, dev)\n }\n }, [fetchMarket])\n\n const retryMarket = useCallback((matchId: number, dev: string) => {\n fetchMarket(matchId, dev)\n }, [fetchMarket])\n\n const applySnapshot = useCallback((next: LiveMonitorSnapshot | null) => {\n if (next === null) {\n setEnabled(false)\n return\n }\n const prev = snapshotRef.current\n const currentPins = pinsRef.current\n\n const pinnedMatchIds = new Set(currentPins.filter((p) => p.kind === 'match').map((p) => p.matchId))\n let sawNewGoalOrRed = false\n for (const m of next.matches) {\n if (!pinnedMatchIds.has(m.matchId)) continue\n const prevMatch = prev?.matches.find((pm) => pm.matchId === m.matchId)\n const prevKeys = new Set((prevMatch?.events ?? []).filter((e) => GOAL_OR_RED.has(e.type)).map(eventIdentity))\n if (m.events.some((e) => GOAL_OR_RED.has(e.type) && !prevKeys.has(eventIdentity(e)))) {\n sawNewGoalOrRed = true\n break\n }\n }\n if (sawNewGoalOrRed && activeTabRef.current !== 'following') setMatchesDot(true)\n\n // Default-open the first available market per pinned match, once -- an explicit close\n // (openMarket[matchId] === null) must stick, so the guard is \"no entry at all\" not \"falsy\".\n for (const m of next.matches) {\n if (!pinnedMatchIds.has(m.matchId)) continue\n const first = m.availableMarkets?.[0]\n if (!first) continue\n if (m.matchId in openMarketRef.current) continue\n const dev = first.marketDeveloperName\n openMarketRef.current = { ...openMarketRef.current, [m.matchId]: dev }\n setOpenMarket((prevOpen) => ({ ...prevOpen, [m.matchId]: dev }))\n fetchMarket(m.matchId, dev)\n }\n\n const marketPins = currentPins.filter((p) => p.kind !== 'match')\n if (activeTabRef.current === 'odds') {\n setLastViewedPrices((prevMap) => {\n let changed = false\n const out = { ...prevMap }\n for (const pin of marketPins) {\n const price = priceForPin(next, pin)\n if (price !== undefined && out[pin.key] !== price) {\n out[pin.key] = price\n changed = true\n }\n }\n return changed ? out : prevMap\n })\n } else {\n let sawPriceMove = false\n for (const pin of marketPins) {\n const price = priceForPin(next, pin)\n const last = lastViewedPricesRef.current[pin.key]\n if (price !== undefined && last !== undefined && price !== last) {\n sawPriceMove = true\n break\n }\n }\n if (sawPriceMove) setOddsDot(true)\n }\n\n const graceKeys = currentPins\n .filter((p) => {\n const phase = phaseForPin(next, p)\n return phase === 'fullTime' || phase === 'postponed' || phase === 'gone'\n })\n .map((p) => p.key)\n if (graceKeys.length > 0) store.markGrace(graceKeys, sessionIdRef.current, Date.now())\n\n // Sync the ref immediately (state updates are async) -- the poll loop's schedule step reads\n // this synchronously in the SAME tick, right after this call returns, to size the next\n // delay off the snapshot that was just received rather than the one from the prior tick.\n snapshotRef.current = next\n setSnapshotState(next)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store])\n\n // Poll loop. ALL mutable inputs live in refs so `tick` is created ONCE ([applySnapshot] deps,\n // and applySnapshot itself is stable across renders): an inline getLiveMonitor lambda handed\n // in fresh from StatsWidget on every render must not re-arm the visibility listener or\n // recreate the timer chain.\n const inFlightRef = useRef(false)\n const timerRef = useRef<number | undefined>(undefined)\n const disabledRef = useRef(false)\n const mountedRef = useRef(false)\n const getLiveMonitorRef = useRef(opts.getLiveMonitor)\n getLiveMonitorRef.current = opts.getLiveMonitor // latest-fn pattern; tick reads the ref, deps stay stable\n\n const tick = useCallback(async () => {\n if (inFlightRef.current || disabledRef.current || pinsRef.current.length === 0) return\n inFlightRef.current = true\n try {\n const snap = await getLiveMonitorRef.current(pinsRef.current)\n if (!mountedRef.current) return\n if (snap === null) {\n // 404 -> live monitor disabled for this operator: stop for the session, hide affordances.\n disabledRef.current = true\n applySnapshot(null)\n return\n }\n applySnapshot(snap)\n // Live-refresh the open accordion market per match. Bypasses the \"already cached\" skip\n // (that guard only lives in toggleMarket) -- fetchMarket itself only skips a fetch already\n // in flight, so this always requests fresh odds for a live match's open market.\n for (const m of snap.matches) {\n if (m.phase !== 'live') continue\n const dev = openMarketRef.current[m.matchId]\n if (dev) fetchMarket(m.matchId, dev)\n }\n } catch {\n // transient failure: keep the previous snapshot, retry on the next scheduled tick\n } finally {\n inFlightRef.current = false\n scheduleRef.current()\n }\n }, [applySnapshot, fetchMarket]) // reads refs only -- both callbacks are themselves stable\n\n const scheduleRef = useRef<() => void>(() => {})\n scheduleRef.current = () => {\n window.clearTimeout(timerRef.current)\n if (!mountedRef.current || disabledRef.current || pinsRef.current.length === 0 || document.visibilityState === 'hidden') return\n const hinted = (snapshotRef.current?.nextPollSeconds ?? DEFAULT_POLL_MS / 1000) * 1000\n timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted))\n }\n\n // Set before the effects below that tick; cleared on unmount so a tick already awaiting the\n // network drops its snapshot (no pin-grace write) and arms no timer after the hook is gone.\n useEffect(() => {\n mountedRef.current = true\n return () => { mountedRef.current = false }\n }, [])\n\n // Immediate tick: pin list transitions 0 -> 1+ (togglePin add, or pins already present at\n // mount -- the ref starts at 0 so the first run treats \"already have pins\" the same way).\n // Dropping to zero pins clears any pending timer so a stray tick never fires with no pins.\n // It deliberately does NOT move the active tab: PinToggle is reachable from a chat message\n // card, so unpinning mid-conversation must leave the reader where they are. The per-kind\n // effect below owns the fallback, and its `activeTab` guard covers zero pins too.\n const prevPinsLengthRef = useRef(0)\n useEffect(() => {\n const wasEmpty = prevPinsLengthRef.current === 0\n prevPinsLengthRef.current = pins.length\n if (pins.length === 0) {\n window.clearTimeout(timerRef.current)\n return\n }\n if (wasEmpty) void tick()\n }, [pins.length, tick])\n\n // A tab left active after the content backing it disappears strands the user on an empty panel\n // with no tab in the strip to escape from. Three ways in: the last match pin drops while an odds\n // pin remains (pins.length alone can't see it, the OTHER kind keeps it above zero), the mirror\n // case for odds, and Today emptying under the user at the local-date rollover.\n useEffect(() => {\n const matchPins = pins.filter((p) => p.kind === 'match').length\n const marketPins = pins.length - matchPins\n if (activeTab === 'following' && matchPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n if (activeTab === 'odds' && marketPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n if (activeTab === 'today' && !hasToday) setActiveTabState('chat')\n }, [pins, activeTab, hasToday])\n\n // Immediate tick: widget open (false -> true transition).\n const prevIsOpenRef = useRef(false)\n useEffect(() => {\n const wasClosed = !prevIsOpenRef.current\n prevIsOpenRef.current = opts.isOpen\n if (wasClosed && opts.isOpen) void tick()\n }, [opts.isOpen, tick])\n\n // Visibility: hidden clears the pending timer; visible ticks immediately. Mounted exactly\n // once -- `tick` never changes identity, so this effect never re-fires across re-renders.\n useEffect(() => {\n const onVisibility = () => {\n if (document.visibilityState === 'hidden') window.clearTimeout(timerRef.current)\n else void tick()\n }\n document.addEventListener('visibilitychange', onVisibility)\n return () => {\n document.removeEventListener('visibilitychange', onVisibility)\n window.clearTimeout(timerRef.current)\n }\n }, [tick])\n\n const setActiveTab = useCallback((tab: WidgetTab) => {\n setActiveTabState(tab)\n if (tab === 'chat') setChatDot(false)\n if (tab === 'today') setTodayDot(false)\n if (tab === 'following') {\n setMatchesDot(false)\n void tick()\n }\n if (tab === 'odds') {\n setOddsDot(false)\n setLastViewedPrices((prevMap) => {\n const out = { ...prevMap }\n for (const pin of pinsRef.current.filter((p) => p.kind !== 'match')) {\n const price = priceForPin(snapshotRef.current, pin)\n if (price !== undefined) out[pin.key] = price\n }\n return out\n })\n void tick()\n }\n }, [tick])\n\n // The ref is refreshed here, not only on the next render: a price history tap adds a pin and\n // opens the Odds tab in one handler, and that tab's immediate fetch must already carry the pin.\n const togglePin = useCallback((pin: PinRef): PinAddResult => {\n const result = store.toggle(pin)\n pinsRef.current = store.pins\n return result\n }, [store])\n const isPinned = useCallback((key: string): boolean => pinsRef.current.some((p) => p.key === key), [])\n const markChatActivity = useCallback(() => setChatDot(true), [])\n // Same shape as markChatActivity: the count that drives it lives in useMatchDiscovery, which\n // cannot be read from here without making the two hooks observe each other's own render.\n const markTodayActivity = useCallback(() => {\n if (activeTabRef.current !== 'today') setTodayDot(true)\n }, [])\n\n return {\n enabled,\n pins,\n snapshot,\n activeTab,\n setActiveTab,\n togglePin,\n isPinned,\n chatDot,\n markChatActivity,\n matchesDot,\n oddsDot,\n todayDot,\n markTodayActivity,\n lastViewedPrices,\n openMarket,\n marketOdds,\n toggleMarket,\n retryMarket,\n _setSnapshot: applySnapshot,\n }\n}\n","import { useState } from 'react'\n\nexport type WidgetTab = 'chat' | 'today' | 'following' | 'odds' | 'games' | 'leaderboard'\n\nexport function useTabs(initial: WidgetTab = 'chat'): { activeTab: WidgetTab; setActiveTab: (t: WidgetTab) => void } {\n const [activeTab, setActiveTab] = useState<WidgetTab>(initial)\n return { activeTab, setActiveTab }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { MatchState, SchedulePayload, ScheduleGroup, StatesPayload } from '@sensiblestats/widget-sdk'\nimport { readSchedule, readScheduleIgnoringTtl, writeSchedule } from './scheduleCache'\nimport { dueMatchIds } from './dueSet'\n\nconst POLL_MS = 60_000\n// Local re-render so the minute advances between network polls. Costs one render; the alternative\n// is a clock that only moves once a minute.\nconst ROLLOVER_CHECK_MS = 60_000\nconst STALE_AFTER_FAILURES = 2\n\nexport interface MatchDiscoveryController {\n groups: ScheduleGroup[]\n states: Record<number, MatchState>\n /** Advanced locally between polls so the minute ticks. */\n liveCount: number\n stale: boolean\n expanded: Record<number, boolean>\n toggleGroup(competitionId: number): void\n /** Test seam: run one states poll synchronously. Not part of the cadence policy. */\n _tick(): Promise<void>\n}\n\nexport interface UseMatchDiscoveryOptions {\n getSchedule: (localDate: string, utcOffsetMinutes: number) => Promise<SchedulePayload | null>\n getStates: (matchIds: number[]) => Promise<StatesPayload | null>\n operatorId: string\n isOpen: boolean\n pinnedMatchIds: number[]\n}\n\nfunction localDateOf(now: Date): string {\n const y = now.getFullYear()\n const m = `${now.getMonth() + 1}`.padStart(2, '0')\n const d = `${now.getDate()}`.padStart(2, '0')\n return `${y}-${m}-${d}`\n}\n\nexport function useMatchDiscovery(opts: UseMatchDiscoveryOptions): MatchDiscoveryController {\n const [groups, setGroups] = useState<ScheduleGroup[]>([])\n const [states, setStates] = useState<Record<number, MatchState>>({})\n const [failures, setFailures] = useState(0)\n const [expanded, setExpanded] = useState<Record<number, boolean>>({})\n const [touched, setTouched] = useState<Record<number, boolean>>({})\n\n const groupsRef = useRef(groups)\n groupsRef.current = groups\n const statesRef = useRef(states)\n statesRef.current = states\n // latest-fn pattern (mirrors useLiveMonitor's getLiveMonitorRef): tick reads the ref, so an\n // inline getStates lambda handed in fresh on every render cannot tear down and recreate the\n // poll interval.\n const getStatesRef = useRef(opts.getStates)\n getStatesRef.current = opts.getStates\n\n const pinnedKey = opts.pinnedMatchIds.join(',')\n\n // A widget left mounted across midnight has to move to the new day, or it holds yesterday's\n // fixtures forever with an empty due set and no polling. Cheap enough to check on a coarse\n // interval; the state only ever changes value once a day, so it re-renders once a day.\n const [localDate, setLocalDate] = useState(() => localDateOf(new Date()))\n useEffect(() => {\n const id = setInterval(() => {\n const next = localDateOf(new Date())\n setLocalDate((prev) => (prev === next ? prev : next))\n }, ROLLOVER_CHECK_MS)\n return () => clearInterval(id)\n }, [])\n\n // `states` is deliberately NOT cleared here: a 23:00 fixture still playing at 00:30 belongs to\n // neither day's window, and dropping its state would blank a score that is still true.\n useEffect(() => {\n let cancelled = false\n // getTimezoneOffset is minutes WEST of UTC, so Istanbul reports -180 for UTC+3.\n const utcOffsetMinutes = -new Date().getTimezoneOffset()\n\n const cached = readSchedule(opts.operatorId, localDate, Date.now())\n if (cached) {\n if (!cancelled) setGroups(cached.groups)\n return () => { cancelled = true }\n }\n\n void (async () => {\n try {\n const payload = await opts.getSchedule(localDate, utcOffsetMinutes)\n if (cancelled || !payload) return\n writeSchedule(opts.operatorId, localDate, payload, Date.now())\n setGroups(payload.groups)\n } catch {\n // Fixtures do not move, so an expired day beats an empty tab.\n const fallback = readScheduleIgnoringTtl(opts.operatorId, localDate)\n if (!cancelled && fallback) setGroups(fallback.groups)\n }\n })()\n\n return () => { cancelled = true }\n }, [opts.operatorId, localDate])\n\n useEffect(() => {\n setExpanded((prev) => {\n const next: Record<number, boolean> = {}\n for (const group of groups) {\n const hasPin = group.matches.some((m) => opts.pinnedMatchIds.includes(m.matchId))\n const seeded = group.expandedByDefault || hasPin\n next[group.competitionId] = touched[group.competitionId]\n ? (prev[group.competitionId] ?? seeded)\n : seeded\n }\n return next\n })\n }, [groups, pinnedKey, touched])\n\n const tick = useCallback(async () => {\n const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now())\n if (ids.length === 0) return\n try {\n const payload = await getStatesRef.current(ids)\n if (!payload) return\n setStates((prev) => {\n // Retained rather than replaced: a finished match keeps its final score after it leaves\n // the due set.\n const next = { ...prev }\n for (const state of payload.states) next[state.matchId] = state\n return next\n })\n setFailures(0)\n } catch {\n setFailures((n) => n + 1)\n }\n }, [])\n\n // `groups` is in the deps (beyond `tick`, which is now stable) so a schedule fetch that\n // resolves after the mount-time tick above gets an immediate follow-up poll, rather than\n // stranding the newly-loaded due set until the next 60s tick.\n useEffect(() => {\n if (!opts.isOpen) return\n void tick()\n const id = setInterval(() => { void tick() }, POLL_MS)\n return () => clearInterval(id)\n }, [opts.isOpen, tick, groups])\n\n const stale = failures >= STALE_AFTER_FAILURES\n\n const liveCount = useMemo(\n () => (stale\n ? 0\n // A match whose own reading has gone stale stops counting: a stalled window must not hold\n // the badge up at 1 for the rest of the day.\n : Object.values(states).filter((s) => s.phase === 'live').length),\n [states, stale],\n )\n\n const toggleGroup = useCallback((competitionId: number) => {\n setTouched((prev) => ({ ...prev, [competitionId]: true }))\n setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }))\n }, [])\n\n return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick }\n}\n","import type { SchedulePayload } from '@sensiblestats/widget-sdk'\n\nconst PREFIX = 'ss-w-schedule:'\nconst SCHEMA_VERSION = 1\nconst TTL_MS = 6 * 3600_000\n\ninterface Entry {\n v: number\n at: number\n payload: SchedulePayload\n}\n\nexport function scheduleCacheKey(operatorId: string, localDate: string): string {\n return `${PREFIX}${operatorId}:${localDate}`\n}\n\nfunction read(operatorId: string, localDate: string): Entry | null {\n try {\n const raw = localStorage.getItem(scheduleCacheKey(operatorId, localDate))\n if (!raw) return null\n const entry = JSON.parse(raw) as Entry\n // A wire change bumps SCHEMA_VERSION; without this an old entry deserializes into the new\n // shape and renders fields that are no longer there.\n if (entry.v !== SCHEMA_VERSION || !entry.payload) return null\n return entry\n } catch {\n return null\n }\n}\n\nexport function readSchedule(operatorId: string, localDate: string, nowMs: number): SchedulePayload | null {\n const entry = read(operatorId, localDate)\n if (!entry) return null\n return nowMs - entry.at > TTL_MS ? null : entry.payload\n}\n\n/** The /schedule-failed path: fixtures do not move, so a stale day beats an empty tab. */\nexport function readScheduleIgnoringTtl(operatorId: string, localDate: string): SchedulePayload | null {\n return read(operatorId, localDate)?.payload ?? null\n}\n\n// The cache is skeleton-only by construction, not by convention: a payload is rebuilt\n// field-by-field here so an excess live-state field on the wire can never be persisted.\nfunction skeletonOnly(payload: SchedulePayload): SchedulePayload {\n return {\n localDate: payload.localDate,\n groups: payload.groups.map((g) => ({\n competitionId: g.competitionId,\n competitionName: g.competitionName,\n competitionImagePath: g.competitionImagePath ?? null,\n rank: g.rank,\n expandedByDefault: g.expandedByDefault,\n matches: g.matches.map((m) => ({\n matchId: m.matchId,\n homeTeamName: m.homeTeamName,\n awayTeamName: m.awayTeamName,\n homeTeamImagePath: m.homeTeamImagePath ?? null,\n awayTeamImagePath: m.awayTeamImagePath ?? null,\n kickoffUnix: m.kickoffUnix,\n })),\n })),\n }\n}\n\nexport function writeSchedule(\n operatorId: string, localDate: string, payload: SchedulePayload, nowMs: number,\n): void {\n const keep = scheduleCacheKey(operatorId, localDate)\n const mine = `${PREFIX}${operatorId}:`\n try {\n // Scoped to this operator: two operators can share a browser, and pruning the whole prefix\n // would evict the other one's day on every write.\n for (let i = localStorage.length - 1; i >= 0; i--) {\n const key = localStorage.key(i)\n if (key && key.startsWith(mine) && key !== keep) localStorage.removeItem(key)\n }\n const entry: Entry = { v: SCHEMA_VERSION, at: nowMs, payload: skeletonOnly(payload) }\n localStorage.setItem(keep, JSON.stringify(entry))\n } catch {\n // A full or blocked localStorage must not break the tab; the schedule refetches next mount.\n }\n}\n","import type { ScheduleGroup, MatchState } from '@sensiblestats/widget-sdk'\n\n// Phases that never change again, so one answer is the last answer we need. Everything else --\n// preMatch (the clock passed but the feed has not flipped yet) and live -- is still moving.\nconst TERMINAL_PHASES: ReadonlySet<string> = new Set(['fullTime', 'postponed'])\n\n/**\n * Which of today's matches to ask about. Anything past its kickoff clock that has not yet given us\n * a terminal answer, and nothing else.\n *\n * This replaced a fixed 3.5-hour window after kickoff. The window bounded the REQUEST, but on a\n * cold load it also silently bounded what we could ever KNOW: open the widget at 15:13 and a match\n * that kicked off at 11:00 was already outside it, so it was never asked about, had no state, and\n * rendered as a fixture that had not started -- kickoff time, no score -- four hours after it\n * finished 0-1. Matches inside the window showed FT correctly, which is why only the older half of\n * the day looked wrong.\n *\n * Terminating on the answer rather than on the clock is also strictly cheaper in the steady state:\n * every finished match drops out permanently after one reply, so a late-evening poll carries only\n * what is actually still playing. The schedule is one day, and the endpoint caps at 200 ids.\n */\nexport function dueMatchIds(\n groups: ScheduleGroup[], states: Record<number, MatchState>, nowMs: number,\n): number[] {\n const due = new Set<number>()\n\n for (const group of groups) {\n for (const match of group.matches) {\n if (nowMs - match.kickoffUnix * 1000 < 0) continue\n const phase = states[match.matchId]?.phase\n if (phase !== undefined && TERMINAL_PHASES.has(phase)) continue\n due.add(match.matchId)\n }\n }\n\n return [...due]\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { GameListPayload, GameSummary } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nconst GAMES_POLL_MS = 60_000\nconst DEFAULT_TZ = 'Europe/London'\n\nfunction computeGameDay(timezone: string): string {\n // en-CA uses YYYY-MM-DD format\n return new Intl.DateTimeFormat('en-CA', { timeZone: timezone }).format(new Date())\n}\n\nexport interface UseGamesResult {\n enabled: boolean\n games: GameSummary[]\n loading: boolean\n refresh: () => void\n}\n\nexport function useGames(\n conversation: { getGames: (gameDay?: string) => Promise<GameListPayload | null> } | null | undefined,\n { activeTab, operatorTimezone }: { activeTab: WidgetTab; operatorTimezone?: string },\n): UseGamesResult {\n // Games/Leaderboard tabs are hidden until we KNOW this operator has games. Every operator shares\n // one games backend, so a non-games operator does not 404 — it returns 200 with an empty list.\n // Gating on games.length (not on the 404 sentinel) is what keeps the tabs off those operators;\n // defaulting to false avoids flashing the tabs on every operator during the first fetch.\n const [enabled, setEnabled] = useState(false)\n const [games, setGames] = useState<GameSummary[]>([])\n const [loading, setLoading] = useState(false)\n const [refreshCount, setRefreshCount] = useState(0)\n\n const inFlightRef = useRef(false)\n // Set only when the feature is entirely off for this operator (backend 404). Stops all polling —\n // distinct from \"enabled\", which merely reflects whether today's list has any games.\n const hardOffRef = useRef(false)\n const conversationRef = useRef(conversation)\n conversationRef.current = conversation\n const tzRef = useRef(operatorTimezone ?? DEFAULT_TZ)\n tzRef.current = operatorTimezone ?? DEFAULT_TZ\n\n // The conversation is often null on first render and set once the widget finishes initialising.\n // It is intentionally NOT read through the ref in the effect deps — the effect must re-run when\n // it becomes available, or the one-shot fetch never fires and the tabs never appear. (Defaulting\n // `enabled` to true used to paper over this; gating on the games list means we must actually\n // fetch.)\n const ready = conversation != null\n\n useEffect(() => {\n if (hardOffRef.current) return\n let active = true\n\n const doFetch = async (): Promise<void> => {\n const conv = conversationRef.current\n if (!conv || inFlightRef.current || !active) return\n inFlightRef.current = true\n setLoading(true)\n try {\n const gameDay = computeGameDay(tzRef.current)\n const result = await conv.getGames(gameDay)\n if (!active) return\n if (result === null) {\n // 404: games feature is not enabled for this operator at all — hide and stop polling.\n hardOffRef.current = true\n setEnabled(false)\n setGames([])\n } else {\n // 200: show the tabs only when this operator actually has games today.\n setGames(result.games)\n setEnabled(result.games.length > 0)\n }\n } catch {\n // swallow; retry next tick\n } finally {\n inFlightRef.current = false\n if (active) setLoading(false)\n }\n }\n\n // Always fetch once on mount or refresh\n void doFetch()\n\n // Poll while the games tab is active\n let intervalId: number | undefined\n if (activeTab === 'games') {\n intervalId = window.setInterval(() => {\n if (hardOffRef.current) {\n window.clearInterval(intervalId)\n return\n }\n void doFetch()\n }, GAMES_POLL_MS)\n }\n\n return () => {\n active = false\n // Release the in-flight guard so a remount (React StrictMode double-invokes effects, and any\n // dependency change re-runs this one) can fetch again. Without this, the first run's request\n // is still in flight when the second run checks the guard, the second run bails, and the\n // first run's result is dropped because `active` is now false — so `enabled` is never set.\n inFlightRef.current = false\n if (intervalId !== undefined) window.clearInterval(intervalId)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, refreshCount, ready])\n\n const refresh = useCallback(() => {\n setRefreshCount((c) => c + 1)\n }, [])\n\n return { enabled, games, loading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseLeaderboardResult {\n data: LeaderboardPayload | null\n loading: boolean\n refresh: () => void\n}\n\nexport function useLeaderboard(\n conversation: { getLeaderboard: () => Promise<LeaderboardPayload | null> } | null | undefined,\n { activeTab }: { activeTab: WidgetTab },\n): UseLeaderboardResult {\n const [data, setData] = useState<LeaderboardPayload | null>(null)\n const [loading, setLoading] = useState(false)\n const [refreshCount, setRefreshCount] = useState(0)\n\n const inFlightRef = useRef(false)\n const conversationRef = useRef(conversation)\n conversationRef.current = conversation\n\n useEffect(() => {\n // The Games hub's stat row (rank, streak) reads the same payload.\n if (activeTab !== 'leaderboard' && activeTab !== 'games') return\n let active = true\n\n const doFetch = async (): Promise<void> => {\n const conv = conversationRef.current\n if (!conv || inFlightRef.current) return\n inFlightRef.current = true\n setLoading(true)\n try {\n const result = await conv.getLeaderboard()\n if (active) setData(result)\n } catch {\n // swallow; keep previous data\n } finally {\n inFlightRef.current = false\n if (active) setLoading(false)\n }\n }\n\n void doFetch()\n return () => {\n active = false\n // Release the guard so a refresh fired while this fetch is still in flight (a quick tap into a\n // game and back) runs its own fetch instead of bailing — the same fix useGames carries.\n inFlightRef.current = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, refreshCount])\n\n const refresh = useCallback(() => {\n setRefreshCount((c) => c + 1)\n }, [])\n\n return { data, loading, refresh }\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\n// Returns the dismiss handler to hand the launcher. Opening is detected from state rather than\n// by wrapping open(): OPEN clears popupText in the same render, so the text seen while closed is\n// remembered to tell a popup open from a plain launcher open.\nexport function usePopupTelemetry(\n log: EventLogger | null,\n isOpen: boolean,\n popupText: string | null,\n dismissPopup: () => void,\n): () => void {\n const shownRef = useRef(new Set<string>())\n const closedTextRef = useRef<string | null>(null)\n\n useEffect(() => {\n if (isOpen) {\n if (closedTextRef.current) log?.log({ name: 'popup_opened' })\n closedTextRef.current = null\n return\n }\n closedTextRef.current = popupText\n if (popupText && !shownRef.current.has(popupText)) {\n shownRef.current.add(popupText)\n log?.log({ name: 'popup_shown' })\n }\n }, [log, isOpen, popupText])\n\n return useCallback(() => {\n log?.log({ name: 'popup_dismissed' })\n dismissPopup()\n }, [log, dismissPopup])\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { BrandMark } from './BrandMark'\nimport { GreetingBubble } from './GreetingBubble'\n\n// Only rendered while the panel is closed. The dynamic greeting popup takes\n// precedence over the static greeting and is dismissable; both open the panel.\n//\n// introAllowed/onIntroStart drive the one-shot attention animation (the FAB\n// nudges, then the greeting types in). The latch below fires it once, the first\n// time a bubble appears; onIntroStart lets the parent record that so it never\n// replays when the FAB remounts on a later panel close. Refreshing the page\n// remounts the whole widget and re-arms it.\nexport function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = 'Dismiss', introAllowed = false, onIntroStart }: { label: string; greeting?: string; popupText?: string | null; logoUrl?: string; onOpen: () => void; onDismissPopup: () => void; dismissLabel?: string; introAllowed?: boolean; onIntroStart?: () => void }): JSX.Element {\n const bubble = popupText ?? greeting\n const [intro, setIntro] = useState(false)\n const armedRef = useRef(introAllowed)\n useEffect(() => {\n if (armedRef.current && bubble) {\n armedRef.current = false\n setIntro(true)\n onIntroStart?.()\n }\n }, [bubble, onIntroStart])\n return (\n <div className={intro ? 'ss-w-fab-wrap ss-w-intro' : 'ss-w-fab-wrap'}>\n {bubble ? <GreetingBubble text={bubble} onOpen={onOpen} onDismiss={popupText ? onDismissPopup : undefined} dismissLabel={dismissLabel} /> : null}\n <button type=\"button\" className=\"ss-w-fab\" aria-label={label} onClick={onOpen}>\n <BrandMark logoUrl={logoUrl} className=\"ss-w-fab-mark\" />\n </button>\n </div>\n )\n}\n","export function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = 'Dismiss' }: { text: string; onOpen?: () => void; onDismiss?: () => void; dismissLabel?: string }): JSX.Element {\n return (\n <div className=\"ss-w-greeting\" role=\"note\">\n <button type=\"button\" className=\"ss-w-greeting-body\" onClick={onOpen}>\n <span className=\"ss-w-greeting-dots\" aria-hidden=\"true\"><i></i><i></i><i></i></span>\n <span className=\"ss-w-greeting-text\">{text}</span>\n </button>\n {onDismiss ? (\n <button type=\"button\" className=\"ss-w-greeting-x\" aria-label={dismissLabel} onClick={onDismiss}>×</button>\n ) : null}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { MatchLinkContext } from '../matchLinkContext'\nimport { SlipStateContext } from '../slipStateContext'\nimport type { HostEvents } from '../useHostEvents'\n\n/** Hands what useHostEvents returns to the components that read it. */\nexport function HostEventsProvider({ value, children }: { value: HostEvents; children: ReactNode }): JSX.Element {\n return (\n <SlipStateContext.Provider value={value.slipState}>\n <MatchLinkContext.Provider value={value.matchLink}>{children}</MatchLinkContext.Provider>\n </SlipStateContext.Provider>\n )\n}\n","// AUTO-GENERATED by scripts/gen-css.mjs from widget.css. Do not edit.\nexport const WIDGET_CSS = \".ss-w-root { all: revert; }\\n.ss-w-root, .ss-w-root * { box-sizing: border-box; margin: 0; padding: 0; }\\n.ss-w-root {\\n --ss-w-accent: #17936a;\\n --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580; --ss-w-line: #e4e8ec;\\n --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\\n --ss-w-pos: #1aa563; --ss-w-neg: #e0524b;\\n --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n --ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;\\n font-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, Helvetica, Arial, sans-serif;\\n font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);\\n}\\n@media (prefers-color-scheme: dark) {\\n .ss-w-root[data-ss-w-theme=\\\"auto\\\"] {\\n --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n --ss-w-pos: #37c891; --ss-w-neg: #f0655d;\\n --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n }\\n}\\n.ss-w-root[data-ss-w-theme=\\\"dark\\\"] {\\n --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n --ss-w-pos: #37c891; --ss-w-neg: #f0655d;\\n --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n}\\n.ss-w-root[data-ss-w-theme=\\\"light\\\"] {\\n --ss-w-accent: #17936a; --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580;\\n --ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\\n --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n}\\n\\n/* ── games design tokens (u393) ── derived from operator tokens so every tenant theme works.\\n Targets (Hull #F5A800/#0B0B0B/#F5F5F5): ground #0D0C0A, surface #17150F, warm #1C1810,\\n raised #211E17, line #26221A, line-warm #3A2F18, accent-tint #3A2C10, strong-line #4A4131. */\\n.ss-w-root {\\n --ss-g-ground: color-mix(in srgb, var(--ss-w-accent) 2%, var(--ss-w-panel));\\n --ss-g-surface: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n --ss-g-warm: color-mix(in srgb, var(--ss-w-accent) 6%, color-mix(in srgb, var(--ss-w-ink) 2%, var(--ss-w-panel)));\\n --ss-g-raised: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 6%, var(--ss-w-panel)));\\n --ss-g-line: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 8%, var(--ss-w-panel)));\\n --ss-g-line-warm: color-mix(in srgb, var(--ss-w-accent) 18%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n --ss-g-accent-tint: color-mix(in srgb, var(--ss-w-accent) 20%, var(--ss-w-panel));\\n --ss-g-strong-line: color-mix(in srgb, var(--ss-w-accent) 8%, color-mix(in srgb, var(--ss-w-ink) 18%, var(--ss-w-panel)));\\n --ss-g-ink: color-mix(in srgb, var(--ss-w-accent) 4%, var(--ss-w-ink));\\n --ss-g-ink-2: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 72%, var(--ss-w-panel)));\\n --ss-g-muted: color-mix(in srgb, var(--ss-w-accent) 5%, color-mix(in srgb, var(--ss-w-ink) 60%, var(--ss-w-panel)));\\n --ss-g-faint: color-mix(in srgb, var(--ss-w-ink) 45%, var(--ss-w-panel));\\n --ss-g-on-accent: #1a1206;\\n --ss-g-on-correct: #fff;\\n --ss-g-correct: color-mix(in srgb, var(--ss-w-correct) 55%, #000);\\n --ss-g-wrong: color-mix(in srgb, var(--ss-w-neg) 55%, #000);\\n /* Brighter wrong for thin marks (borders, icons, segments) that must read on dark surfaces; --ss-g-wrong stays for fills. */\\n --ss-g-wrong-mark: var(--ss-w-neg);\\n --ss-g-success: color-mix(in srgb, var(--ss-w-pos) 80%, var(--ss-w-ink));\\n --ss-g-success-tint: color-mix(in srgb, var(--ss-w-pos) 18%, var(--ss-w-panel));\\n --ss-g-close: #e3b341;\\n --ss-g-flame: #ff6a1a;\\n /* Pitch colours are fixed in both themes: the pitch is always a dark green. */\\n --ss-g-pitch: #123524;\\n --ss-g-pitch-line: #3e7055;\\n --ss-g-pitch-chip: #0d0c0a;\\n --ss-g-pitch-ink: #f4efe6;\\n --ss-g-pitch-mark: #c9d6cd;\\n --ss-g-font-display: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;\\n --ss-g-font-body: 'Barlow', system-ui, -apple-system, 'Segoe UI', sans-serif;\\n}\\n\\n/* ── match link (u443) ── a card's team names as a button that opens the operator's match page.\\n The button keeps the wrapped element's own class for its layout. Every one of those classes is\\n declared further down this file, so on equal specificity it wins over this reset: keep this\\n block above them. */\\n.ss-w-matchlink { appearance: none; position: relative; width: 100%; padding-right: 16px; background: none; border: 0; border-radius: 6px; font: inherit; color: inherit; text-align: inherit; cursor: pointer; }\\n.ss-w-matchlink::after { content: ''; position: absolute; right: 3px; top: 50%; width: 7px; height: 7px; margin-top: -4px; border-top: 1.5px solid var(--ss-w-faint); border-right: 1.5px solid var(--ss-w-faint); transform: rotate(45deg); }\\n.ss-w-matchlink:hover::after { border-color: var(--ss-w-accent); }\\n.ss-w-matchlink:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n/* The pinned match card centres its score in the card, so it pads both edges alike. */\\n.ss-w-mon-main.ss-w-matchlink { padding-left: 16px; }\\n\\n/* ── games ui kit (u393) ── */\\n.ss-g-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\\n.ss-g-head { display: flex; align-items: center; gap: 6px; padding: 8px 16px 8px 6px; font-family: var(--ss-g-font-body); }\\n.ss-g-back { width: 44px; height: 44px; flex: none; display: grid; place-items: center; border: 0; border-radius: 12px; background: transparent; color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-back:hover { background: var(--ss-g-surface); }\\n.ss-g-head-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.05; }\\n.ss-g-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; color: var(--ss-g-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-head-right { flex: none; }\\n.ss-g-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600; white-space: nowrap; }\\n.ss-g-chip--neutral { background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); }\\n.ss-g-chip--neutral .ss-g-num, .ss-g-chip--neutral svg { color: var(--ss-w-accent); }\\n.ss-g-chip--accent { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-weight: 700; }\\n.ss-g-chip--success { background: var(--ss-g-success-tint); color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-chip--badge { padding: 3px 8px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-chip--lock { padding: 3px 8px; border-radius: 6px; font-size: 12px; font-weight: 500; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-statstack { display: flex; flex-direction: column; align-items: flex-end; line-height: 1; }\\n.ss-g-statstack-v { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; color: var(--ss-w-accent); }\\n.ss-g-statstack-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-progress { display: flex; align-items: center; gap: 12px; padding: 0 16px 8px; }\\n.ss-g-progress-main { flex: 1; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-progress-labels { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--ss-g-ink); }\\n.ss-g-progress-rl { color: var(--ss-g-muted); }\\n.ss-g-segs { display: grid; gap: 4px; }\\n.ss-g-seg { height: 5px; border-radius: 3px; background: var(--ss-g-line); }\\n.ss-g-seg[data-state=\\\"done\\\"] { background: var(--ss-g-strong-line); }\\n.ss-g-seg[data-state=\\\"current\\\"] { background: var(--ss-w-accent); }\\n.ss-g-seg[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); }\\n.ss-g-seg[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); }\\n.ss-g-btn { min-height: 48px; padding: 0 16px; border-radius: 12px; font-family: var(--ss-g-font-body); font-size: 14px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }\\n.ss-g-btn:disabled { opacity: .45; cursor: default; }\\n.ss-g-btn--block { width: 100%; min-height: 54px; border-radius: 14px; font-size: 16px; font-weight: 800; }\\n.ss-g-btn--primary { border: 0; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-btn--outline { border: 1.5px solid var(--ss-g-strong-line); background: transparent; color: var(--ss-g-ink); }\\n.ss-g-btn--accent-outline { border: 1.5px solid var(--ss-w-accent); background: transparent; color: var(--ss-w-accent); }\\n.ss-g-btn--surface { border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font-weight: 600; font-size: 13px; }\\n.ss-g-search { display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-search-label { font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-search-box { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1.5px solid var(--ss-g-line); color: var(--ss-g-muted); }\\n.ss-g-search-box:focus-within { border-color: var(--ss-w-accent); }\\n.ss-g-search-box input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: var(--ss-g-ink); font: 500 15px var(--ss-g-font-body); }\\n.ss-g-footer { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--ss-g-line); display: flex; flex-direction: column; gap: 10px; background: var(--ss-g-ground); }\\n.ss-g-sil { position: relative; flex: none; display: inline-flex; align-items: flex-end; justify-content: center; overflow: hidden; border-radius: 50%; background: var(--ss-g-raised); color: var(--ss-g-strong-line); }\\n.ss-g-sil--selected { background: var(--ss-g-accent-tint); color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-g-raised)); }\\n.ss-g-sil--mystery { background: var(--ss-g-accent-tint); color: var(--ss-g-ground); }\\n.ss-g-sil-q { position: absolute; top: 22%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 1.1em; color: var(--ss-w-accent); }\\n.ss-g-crest { flex: none; object-fit: contain; }\\n.ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-pitch-svg { position: absolute; inset: 0; width: 100%; height: 100%; stroke: var(--ss-g-pitch-line); stroke-width: .6; }\\n/* ── games screen scaffold (u393) — shared by every game screen ── */\\n.ss-w-gscreen > .ss-g-screen { flex: 1; min-height: 0; }\\n.ss-g-screen { display: flex; flex-direction: column; min-height: 0; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-body); }\\n.ss-g-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 14px; padding: 4px 16px 16px; }\\n.ss-g-body .ss-g-progress { padding: 0; }\\n.ss-g-loading { align-items: center; justify-content: center; color: var(--ss-g-muted); font-size: 13px; }\\n.ss-g-opts { display: flex; flex-direction: column; gap: 4px; max-height: 232px; overflow-y: auto; }\\n.ss-g-opt { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 6px 8px; border: 0; border-radius: 12px; background: var(--ss-g-surface); color: var(--ss-g-ink); font: 600 15px var(--ss-g-font-body); text-align: left; cursor: pointer; }\\n.ss-g-opt:hover, .ss-g-opt:focus-visible { background: var(--ss-g-raised); outline: none; }\\n.ss-g-opt-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 13px; font-weight: 700; }\\n.ss-g-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-result { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 16px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-result[data-tone=\\\"win\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-result[data-tone=\\\"lose\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-result-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; line-height: 1; }\\n.ss-g-result-score { font-size: 13px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-result-num { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 40px; color: var(--ss-w-accent); margin-right: 4px; }\\n.ss-g-result-detail { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-result .ss-g-btn { margin-top: 6px; }\\n\\n/* launcher */\\n.ss-w-fab-wrap { position: fixed; bottom: var(--ss-w-offset-y); z-index: 2147483000; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-fab-wrap { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-fab-wrap { left: var(--ss-w-offset-x); align-items: flex-start; }\\n.ss-w-fab { width: 56px; height: 56px; border: none; border-radius: 50%; background: var(--ss-w-nav); color: #fff; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 20px rgba(0,0,0,.28); }\\n.ss-w-fab-mark { width: 30px; height: 30px; display: block; object-fit: contain; }\\n.ss-w-greeting { max-width: 240px; display: flex; align-items: flex-start; background: var(--ss-w-panel); color: var(--ss-w-ink); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-greeting-body { position: relative; flex: 1; min-width: 0; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 9px 4px 9px 12px; }\\n.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }\\n.ss-w-greeting-text { display: block; }\\n/* Typing indicator: overlays the text area so bubble height stays put; hidden at\\n rest, revealed only during the one-shot intro (see prefers-reduced-motion block). */\\n.ss-w-greeting-dots { position: absolute; top: 0; bottom: 0; left: 12px; display: flex; align-items: center; gap: 4px; opacity: 0; pointer-events: none; }\\n.ss-w-greeting-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-faint); display: block; }\\n/* One-shot launcher attention intro: FAB nudges, then the greeting types in.\\n Gated behind no-preference so reduce-motion users get the greeting shown\\n statically (text visible, no nudge, no typing). ChatFab adds .ss-w-intro once\\n per page load; every animation runs a single time and settles at rest. */\\n@media (prefers-reduced-motion: no-preference) {\\n .ss-w-intro .ss-w-fab { animation: ss-w-nudge .8s ease both; }\\n .ss-w-intro .ss-w-greeting { animation: ss-w-greet-in .45s cubic-bezier(.2,.8,.3,1.15) .8s both; }\\n .ss-w-intro .ss-w-greeting-text { animation: ss-w-greet-textin .4s ease 1.65s both; }\\n .ss-w-intro .ss-w-greeting-dots { animation: ss-w-greet-dots .95s ease .85s both; }\\n .ss-w-intro .ss-w-greeting-dots i { animation: ss-w-greet-dotbounce .5s ease .85s 2; }\\n .ss-w-intro .ss-w-greeting-dots i:nth-child(2) { animation-delay: 1s; }\\n .ss-w-intro .ss-w-greeting-dots i:nth-child(3) { animation-delay: 1.15s; }\\n}\\n@keyframes ss-w-nudge {\\n 0%, 100% { transform: none; }\\n 22% { transform: translateY(-9px) rotate(-9deg); }\\n 44% { transform: translateY(0) rotate(7deg); }\\n 64% { transform: translateY(-4px) rotate(-4deg); }\\n 82% { transform: rotate(2deg); }\\n}\\n@keyframes ss-w-greet-in {\\n from { opacity: 0; transform: translateY(8px) scale(.92); }\\n to { opacity: 1; transform: none; }\\n}\\n@keyframes ss-w-greet-textin { from { opacity: 0; } to { opacity: 1; } }\\n@keyframes ss-w-greet-dots { 0% { opacity: 0; } 14% { opacity: 1; } 78% { opacity: 1; } 100% { opacity: 0; } }\\n@keyframes ss-w-greet-dotbounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }\\n\\n/* panel */\\n.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(460px, calc(100vw - 40px)); height: min(640px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { left: var(--ss-w-offset-x); }\\n@media (max-width: 639px) {\\n /* Fill via inset with no explicit height (like the site's working panel) so the\\n input stays visible when the mobile keyboard/URL-bar shrinks the viewport. The\\n position-specific selectors override the right/left offsets set above. */\\n .ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel,\\n .ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { inset: 0; width: auto; height: auto; border: none; border-radius: 0; }\\n}\\n.ss-w-header { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-header-mark { width: 18px; height: 18px; display: block; object-fit: contain; }\\n.ss-w-header-title { font-weight: 660; flex: 1; }\\n.ss-w-close { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu-wrap { position: relative; display: grid; place-items: center; }\\n.ss-w-kebab { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 5; min-width: 184px; padding: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.18); }\\n.ss-w-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; background: none; border: none; border-radius: 8px; color: var(--ss-w-ink); font: inherit; font-size: 13px; text-align: left; cursor: pointer; }\\n.ss-w-menu-item:hover, .ss-w-menu-item:focus-visible { background: var(--ss-w-bubble); }\\n.ss-w-menu-item svg { color: var(--ss-w-faint); font-size: 15px; flex: none; }\\n\\n/* messages */\\n/* .ss-w-mon-list (Matches/Odds tab scrollers) shares .ss-w-list's box/scroll rules by design --\\n same visual rhythm as the chat message list -- but gets its own class so it isn't the same DOM\\n landmark as the chat list when both exist in the panel at once (Task 16 fix round, M4). */\\n/* Children of this scrolling column flex container must NOT shrink. The default flex-shrink:1\\n compresses every child to fit the panel instead of letting the container scroll, and\\n .ss-w-grp's own overflow:hidden then clips the compressed content away entirely — 27\\n competition groups rendered as blank bars on a phone. Applies to the pinned cards too. */\\n.ss-w-mon-list > * { flex: none; }\\n.ss-w-list, .ss-w-mon-list { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }\\n/* Transient bottom spacer: reserves a viewport of room below a new turn so its\\n top can be scrolled into view while the reply is still streaming in. Height is\\n set imperatively and flex must not shrink it away. */\\n.ss-w-turn-spacer { flex: none; }\\n.ss-w-msg { display: flex; }\\n.ss-w-user { justify-content: flex-end; }\\n.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }\\n.ss-w-bot { flex-direction: column; gap: 8px; }\\n.ss-w-status { font-size: 11px; color: var(--ss-w-faint); font-style: italic; }\\n.ss-w-error { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c0392b; }\\n.ss-w-retry { background: none; border: 1px solid currentColor; border-radius: 10px; padding: 2px 8px; cursor: pointer; color: inherit; }\\n\\n/* markdown */\\n.ss-w-md { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-md :where(p, ul, ol, table, pre, blockquote, h1, h2, h3, h4) { margin: 0; }\\n.ss-w-md > *:first-child { margin-top: 0; }\\n.ss-w-md > *:last-child { margin-bottom: 0; }\\n.ss-w-md-ul { list-style: disc outside; padding-left: 18px; }\\n.ss-w-md-ol { list-style: decimal outside; padding-left: 18px; }\\n.ss-w-md-ul li::marker, .ss-w-md-ol li::marker { color: var(--ss-w-accent); }\\n.ss-w-md-link { color: var(--ss-w-accent); text-decoration: underline; }\\n.ss-w-table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }\\n.ss-w-md-table { border-collapse: collapse; width: max-content; min-width: 100%; font-variant-numeric: tabular-nums; }\\n.ss-w-md-table td, .ss-w-md-table th { border: 1px solid var(--ss-w-line); padding: 4px 8px; text-align: left; white-space: nowrap; }\\n.ss-w-md-table th { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); font-weight: 700; }\\n.ss-w-md-table tbody tr:nth-child(even) { background: var(--ss-w-bubble); }\\n.ss-w-md-code { background: var(--ss-w-bubble); border-radius: 5px; padding: 1px 5px; font-family: ui-monospace, monospace; }\\n\\n/* entity cards */\\n.ss-w-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Entity card: identity header row over a horizontal stat strip */\\n.ss-w-ecard { display: flex; flex-direction: column; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; text-align: left; }\\n\\n.ss-w-ecard-idtext { display: flex; flex-direction: column; gap: 1px; min-width: 0; max-width: 100%; }\\n.ss-w-thumb { width: 54px; height: 54px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 16px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; box-shadow: 0 1px 3px rgba(0,0,0,.14); }\\n.ss-w-thumb.ss-w-team { border-radius: 12px; }\\n.ss-w-ecard[data-kind=\\\"player\\\"] .ss-w-thumb { background-color: var(--ss-w-accent); }\\n.ss-w-nm { font-weight: 680; line-height: 1.15; overflow-wrap: anywhere; }\\n.ss-w-sub { font-size: 11px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* bare card (no stat scopes): simple avatar + name row */\\n.ss-w-ecard-bare { display: flex; align-items: center; }\\n.ss-w-ecard-bare .ss-w-ecard-hd { padding: 10px 12px; }\\n\\n.ss-w-ecard-hd { display: flex; align-items: center; gap: 11px; padding: 11px 13px; }\\n.ss-w-ecard-hd .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }\\n.ss-w-ecard-hd .ss-w-thumb.ss-w-team { border-radius: 10px; }\\n.ss-w-ecard-meta { display: inline-flex; align-items: center; gap: 7px; flex: none; align-self: flex-start; margin-left: auto; }\\n.ss-w-ecard-meta .ss-w-ecard-season { margin: 0; }\\n\\n/* scope tabs: reuse the underline pattern, relocated above the strip */\\n.ss-w-ecard-scopes { display: flex; align-items: stretch; gap: 2px; padding: 0 11px; border-top: 1px solid var(--ss-w-line); flex-wrap: wrap; }\\n.ss-w-ecard-scope { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 7px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }\\n.ss-w-ecard-scope[aria-selected=\\\"true\\\"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-ecard-scope .ss-w-ecard-crest { width: 14px; height: 14px; }\\n.ss-w-ecard-scopes + .ss-w-ecard-strip { border-top: none; }\\n\\n.ss-w-ecard-crest { width: 15px; height: 15px; flex: none; display: block; border-radius: 4px; background-size: cover; background-position: center; }\\n.ss-w-ecard-season { flex: none; margin-left: auto; align-self: center; margin-bottom: 5px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n/* stat strip: 1px gap over a line-colored ground paints hairlines between cells, wrap-safe */\\n.ss-w-ecard-strip { display: grid; gap: 1px; background: var(--ss-w-line); border-top: 1px solid var(--ss-w-line); }\\n.ss-w-ecard-cell { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 4px; padding: 10px 4px 11px; background: var(--ss-w-panel); }\\n.ss-w-ecard-cval { height: 20px; display: flex; align-items: center; font-size: 17px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }\\n.ss-w-ecard-cval .ss-w-form { width: 42px; }\\n.ss-w-ecard-clabel { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); font-weight: 600; font-variant-numeric: tabular-nums; }\\n\\n.ss-w-form { justify-self: end; display: flex; height: 6px; width: 48px; border-radius: 4px; overflow: hidden; gap: 2px; }\\n.ss-w-form span { display: block; border-radius: 2px; }\\n.ss-w-form-w { background: var(--ss-w-pos); }\\n.ss-w-form-d { background: var(--ss-w-faint); }\\n.ss-w-form-l { background: var(--ss-w-neg); }\\n\\n.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }\\n.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }\\n.ss-w-cards-more:disabled { opacity: .5; cursor: default; }\\n\\n/* betting insights */\\n.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }\\n.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; }\\n\\n/* header, competition-hero fallback: comp on the left, live badge + kickoff + pin on the right,\\n all on one line (used when there is no fixture, and by MarketOddsCardList) */\\n.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); }\\n.ss-w-bi-header-left { display: inline-flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); }\\n.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n/* two-tier header: a quiet meta line (competition + kickoff + match pin) stacked above the\\n fixture, so long club names get the whole width to themselves and stop truncating (u350) */\\n.ss-w-bi-head { display: flex; flex-direction: column; gap: 6px; padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-bi-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-bi-meta-left { display: inline-flex; align-items: center; gap: 5px; min-width: 0; flex: 1; }\\n.ss-w-bi-meta-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n.ss-w-bi-fixture-line { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-kick { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); white-space: nowrap; flex: none; }\\n.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; }\\n.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }\\n.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; }\\n\\n/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */\\n.ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 10px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n\\n/* fixture atoms -- crest-flanked team pair; shared by the insight fixture line and MarketOddsCardList */\\n.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }\\n.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* shared crest-flanked team row (MarketOddsCardList); matches .ss-w-bi-fixture-line's hero weight\\n so the fixture reads the same on both card types (u350) */\\n.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n\\n/* row 2, two-tier: the market label owns a full-width line above the pick row (selection grows\\n left, odds + slip + pin sit right), so neither the market name nor the fixture clips (u350) */\\n.ss-w-bi-action { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.25; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-bi-pick-row { display: flex; align-items: center; gap: 9px; }\\n.ss-w-bi-sel { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; line-height: 1.2; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-odds { flex: none; margin-left: auto; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }\\n.ss-w-bi-odds b { font-size: 20px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }\\n.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }\\n.ss-w-bi-pick-row .ss-w-slip { flex: none; }\\n\\n/* row 3: bar-chart glyph + reasoning prose, in a subtle strip */\\n.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }\\n.ss-w-bi-chart { flex: none; width: 13px; height: 12px; margin-top: 2px; opacity: .55;\\n background:\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) left / 3px 55% no-repeat,\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) center / 3px 100% no-repeat,\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) right / 3px 75% no-repeat;\\n background-position: left bottom, center bottom, right bottom;\\n}\\n.ss-w-bi-text { flex: 1; min-width: 0; font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* market odds card */\\n.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-mocard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n/* Embedded inside the market accordion, which already provides the card frame + accent rail --\\n drop the inner frame so odds rows aren't double-bordered. */\\n.ss-w-mocard--bare { border: none; border-radius: 0; padding: 0; background: none; }\\n.ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }\\n.ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-market-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-more { 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; }\\n.ss-w-mo-more:hover { text-decoration: underline; }\\n.ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }\\n.ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }\\n.ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }\\n/* The card's stat, in the Live tab accordion's insight style. No row below it is marked (R17). */\\n.ss-w-mo-stat { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }\\n.ss-w-mo-row:last-child { border-bottom: none; }\\n.ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); flex: 1; min-width: 0; }\\n.ss-w-mo-price { margin-left: auto; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--ss-w-accent); }\\n/* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a\\n shortening price as a discount, which inverts what it actually means for the bettor. */\\n.ss-w-move { display: inline-flex; align-items: baseline; gap: 4px; color: var(--ss-w-faint); }\\n.ss-w-move-prev { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 12px; text-decoration: line-through; }\\n.ss-w-move-arrow { font-size: 9px; line-height: 1; }\\n/* margin-left:auto is row layout, not badge styling -- it belongs to the market-odds row, which is\\n a flex row, and must NOT follow the badge into the insight card's odds column. */\\n.ss-w-mo-row .ss-w-move { margin-left: auto; }\\n.ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }\\n.ss-w-mo-row .ss-w-slip { margin: 0; flex: none; }\\n.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }\\n\\n/* Compact price list (D16): three or more cards of one turn, one row per fixture. Team names wrap\\n to a second line and are never cut; the time sits above the match pin, with no column of its own. */\\n.ss-w-mol { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-mol-head, .ss-w-mol-row { display: grid; grid-template-columns: minmax(0, 1fr) 126px 30px; align-items: center; gap: 4px; }\\n.ss-w-mol-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow-wrap: anywhere; }\\n.ss-w-mol-cols, .ss-w-mol-cells { display: grid; gap: 4px; }\\n.ss-w-mol-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); text-align: center; overflow-wrap: break-word; min-width: 0; }\\n.ss-w-mol-comp { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding-top: 4px; }\\n.ss-w-mol-row { padding: 6px 0; border-bottom: 1px dashed var(--ss-w-line); min-height: 48px; box-sizing: border-box; }\\n.ss-w-mol-group .ss-w-mol-row:last-child { border-bottom: none; }\\n.ss-w-mol-fx { display: flex; flex-direction: column; gap: 3px; min-width: 0; background: none; border: none; padding: 0; text-align: left; font: inherit; color: inherit; }\\n.ss-w-mol-team { display: flex; align-items: center; gap: 5px; min-width: 0; }\\n.ss-w-mol-team > * { flex: none; }\\n.ss-w-mol-team > .ss-w-mol-nm { flex: 1 1 auto; }\\n.ss-w-mol-nm { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); overflow-wrap: break-word; hyphens: manual; line-height: 1.2; min-width: 0; }\\n.ss-w-mol-mkt { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-mol-cells { align-items: start; }\\n.ss-w-mol-cell { display: flex; flex-direction: column; align-items: stretch; gap: 2px; min-width: 0; }\\n.ss-w-mol-cell > .ss-w-mol-price { flex: none; }\\n.ss-w-mol-cell .ss-w-move { justify-content: center; gap: 2px; }\\n.ss-w-mol-cell .ss-w-move-prev { font-family: inherit; font-variant-numeric: tabular-nums; font-size: 10px; }\\n/* A 39 px cell fits four characters at 13 px: five step down to 11.5 px and six to 10.5 px. */\\n.ss-w-mol-cell--wide .ss-w-mol-price, .ss-w-mol-cell--wide .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 11.5px; }\\n.ss-w-mol-cell--wider .ss-w-mol-price, .ss-w-mol-cell--wider .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 10.5px; }\\n.ss-w-mol-cell .ss-w-slip { margin: 0; flex: none; min-width: 0; }\\n.ss-w-mol-price, .ss-w-slip-btn--price { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 5px 0; border-radius: 8px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); font-family: inherit; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-slip-btn.ss-w-slip-btn--price { width: 100%; cursor: pointer; background: var(--ss-w-panel); color: var(--ss-w-accent); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 5px 0; font-size: 13px; font-weight: 700; box-shadow: none; }\\n.ss-w-slip-btn--price:hover:not(:disabled) { border-color: var(--ss-w-accent); }\\n.ss-w-slip-btn--price[data-settled] { color: var(--ss-w-faint); }\\n.ss-w-mol-lab { font-family: inherit; font-size: 9.5px; font-weight: 600; color: var(--ss-w-faint); line-height: 1.1; text-align: center; overflow-wrap: anywhere; }\\n.ss-w-mol-side { display: flex; flex-direction: column; align-items: center; gap: 4px; }\\n.ss-w-mol-when { font-size: 9.5px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; text-align: center; line-height: 1.15; }\\n.ss-w-mol-side--live .ss-w-mol-when { color: var(--ss-w-neg); }\\n\\n/* odds movement card */\\n.ss-w-omcards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-omcard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-om-head { display: flex; align-items: center; gap: 8px; }\\n.ss-w-om-market { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-om-tag { margin-left: auto; flex: none; font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 2px 7px; }\\n.ss-w-om-fixture { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-om-comp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-om-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }\\n.ss-w-om-chart { display: block; width: 100%; height: auto; }\\n/* Single neutral accent in BOTH directions, deliberately. Colouring a shortening price green\\n frames it as a discount, which inverts what it means for the bettor -- the same reason\\n .ss-w-move keeps both directions on --ss-w-faint. */\\n.ss-w-om-line { stroke: var(--ss-w-accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }\\n.ss-w-om-dot { fill: var(--ss-w-accent); }\\n.ss-w-om-grid { stroke: var(--ss-w-line); stroke-width: 1; }\\n.ss-w-om-ylab, .ss-w-om-xlab { fill: var(--ss-w-faint); font-size: 9px; font-family: ui-monospace, monospace; }\\n.ss-w-om-empty { font-size: 11.5px; color: var(--ss-w-faint); padding: 6px 0; }\\n.ss-w-om-foot { display: flex; align-items: center; gap: 14px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-om-foot b { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; color: var(--ss-w-ink); }\\n.ss-w-om-excl { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-om-susp { font-size: 11px; font-weight: 600; color: #c0392b; }\\n.ss-w-om-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* action buttons */\\n.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\\n/* text-align is explicit because a <button> defaults to center, and a follow-up question long\\n enough to wrap then sets its second line ragged on both sides. */\\n.ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; text-align: left; }\\n.ss-w-abtn:disabled { opacity: .5; cursor: default; }\\n.ss-w-abtn-shimmer { width: 140px; height: 30px; border-radius: 16px; background: linear-gradient(90deg, var(--ss-w-bubble), var(--ss-w-line), var(--ss-w-bubble)); background-size: 200% 100%; animation: ss-w-shimmer 1.2s infinite; }\\n@keyframes ss-w-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }\\n\\n/* intent chips */\\n.ss-w-chips { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-chip { font-size: 11.5px; font-weight: 550; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 5px 11px; cursor: pointer; }\\n\\n/* input */\\n.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }\\n.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }\\n/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it\\n on touch devices only, so the desktop 13px design is unchanged. */\\n@media (pointer: coarse) {\\n .ss-w-textarea { font-size: 16px; }\\n}\\n.ss-w-send { width: 36px; height: 36px; flex: none; border: none; border-radius: 50%; background: var(--ss-w-accent); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 16px; }\\n.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }\\n\\n/* add to slip */\\n.ss-w-slip { position: relative; display: flex; }\\n.ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; white-space: nowrap; }\\n.ss-w-slip-btn:disabled { opacity: .6; cursor: default; background: var(--ss-w-bubble); color: var(--ss-w-faint); border-color: var(--ss-w-line); }\\n/* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward\\n into the card -- inheriting the wrapper's width squeezes the text to one character per line.\\n Every toast site (slip buttons, pin toggles) sits at the right edge of its row. */\\n.ss-w-toast { position: absolute; top: calc(100% + 6px); right: 0; z-index: 1; width: max-content; max-width: 210px; font-size: 11px; font-weight: 560; border-radius: 10px; padding: 5px 10px; overflow-wrap: anywhere; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-toast-success { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }\\n.ss-w-toast-error { color: #c0392b; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }\\n\\n/* pin affordance */\\n.ss-w-pin-wrap { position: relative; display: inline-flex; flex: none; }\\n.ss-w-pin { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-pin svg { width: 12px; height: 12px; }\\n.ss-w-pin:hover { color: var(--ss-w-ink); border-color: var(--ss-w-faint); }\\n.ss-w-pin[data-on] { background: var(--ss-w-accent); border-color: var(--ss-w-accent); color: #fff; }\\n.ss-w-pin[data-on]:hover { background: var(--ss-w-accent); color: #fff; }\\n.ss-w-hist { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-hist svg { width: 12px; height: 12px; }\\n.ss-w-hist:hover { color: var(--ss-w-accent); border-color: var(--ss-w-accent); }\\n\\n@media (prefers-reduced-motion: reduce) {\\n .ss-w-abtn-shimmer { animation: none; }\\n}\\n\\n/* greeting dashboard */\\n.ss-w-dash { display: flex; flex-direction: column; gap: 12px; padding: 4px 0; }\\n.ss-w-dash-head { display: flex; flex-direction: column; }\\n.ss-w-dash-title { font-size: 18px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }\\n.ss-w-dash-subtitle { font-size: 13px; color: var(--ss-w-faint); margin-top: 4px; }\\n.ss-w-dash-foot { font-size: 11px; color: var(--ss-w-faint); margin-top: 2px; }\\n\\n.ss-w-dash-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-dash-tile--half { grid-column: span 1; }\\n.ss-w-dash-tile--full { grid-column: 1 / -1; }\\n\\n.ss-w-dash-tile {\\n display: flex; align-items: center; gap: 10px;\\n padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n background: var(--ss-w-panel); text-align: left; cursor: pointer; width: 100%;\\n color: inherit; font: inherit;\\n min-width: 0; /* the panel is min(400px, 100vw - 40px): without this,\\n a long Turkish title blows the column out */\\n}\\n.ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 28px; height: 28px; font-size: 22px; }\\n.ss-w-dash-emoji { line-height: 1; }\\n.ss-w-dash-tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }\\n.ss-w-dash-tile-title { min-width: 0; font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }\\n.ss-w-dash-tile-subtitle { min-width: 0; font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-tile-chevron { flex: none; margin-left: auto; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n\\n/* Badge + crests share their own row, below the title -- NOT the icon/chevron row. A\\n nowrap badge (~70px) sitting beside icon+chevron in a ~180px half-span tile left the\\n title column at ~22px wide, wrapping every title character-by-character. Here the row\\n gets the body's full width, so a badge this size is comfortably inside it. */\\n.ss-w-dash-tile-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }\\n.ss-w-dash-tile-badge { flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n.ss-w-dash-tile-crests { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-tile-crest {\\n width: 18px; height: 18px; border-radius: 50%;\\n background-size: cover; background-position: center; background-color: var(--ss-w-bubble);\\n margin-left: -6px; border: 2px solid var(--ss-w-panel); /* overlapping stack, capped at 3 in DashboardTile */\\n}\\n.ss-w-dash-tile-crest:first-child { margin-left: 0; }\\n\\n/* Market: default 2-column grid, tiles get the same accent rail as the other card\\n families (.ss-w-binsight, .ss-w-mocard, .ss-w-omcard) so a market tile reads as\\n part of that visual language rather than a plain unstyled button. */\\n.ss-w-dash--market .ss-w-dash-tile { border-left: 3px solid var(--ss-w-accent); }\\n\\n/* Goal: one column of pill rows. */\\n.ss-w-dash--goal .ss-w-dash-grid { grid-template-columns: 1fr; }\\n.ss-w-dash--goal .ss-w-dash-tile { border-radius: 999px; padding: 10px 14px; }\\n\\n/* Discovery: tinted bento cards. Stacked (icon over text) so a two- or three-word title gets\\n the tile's full width instead of the ~100px left of a horizontal icon+chevron -- that narrow\\n column was wrapping \\\"Most interesting angles\\\" onto three lines. The chevron is dropped (the\\n whole card is the tap target) and the badge + crest row is forced onto one line. */\\n.ss-w-dash--discovery .ss-w-dash-tile { flex-direction: column; align-items: stretch; gap: 8px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-icon { align-self: flex-start; width: 32px; height: 32px; font-size: 26px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-chevron { display: none; }\\n/* The full-span trends tile has the whole panel width, so its icon and title sit on one row\\n (horizontal, centre-aligned) rather than stacking like the narrow half tiles. */\\n.ss-w-dash--discovery .ss-w-dash-tile--full { flex-direction: row; align-items: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile--full .ss-w-dash-tile-icon { align-self: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile-meta { flex-wrap: nowrap; }\\n.ss-w-dash--discovery .ss-w-dash-tile-crest { width: 22px; height: 22px; }\\n/* Tints mix a hue into the live panel rather than hardcoding a light pastel, so a dark\\n operator surface (e.g. --ss-w-panel set from a navy `surface` brand color) yields a\\n readable tinted-dark card instead of near-white ink on a fixed light pastel. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n/* A hero tile would take the first tint position; count only regular tiles where `of S` parses. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n\\n/* Hero: the personalized lead tile. Declared after the layout rules and at three-class\\n specificity so it keeps one look in every layout -- no market rail, no goal pill, no\\n discovery tint or stacking. Colours derive from accent/panel/ink so an operator surface\\n and dark mode both work without their own rules. */\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero {\\n display: flex; flex-direction: column; align-items: stretch; gap: 10px;\\n padding: 12px 14px 14px; border-radius: 16px;\\n border: 1px solid color-mix(in srgb, var(--ss-w-accent) 38%, var(--ss-w-line));\\n background:\\n radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--ss-w-accent) 18%, transparent) 0%, transparent 60%),\\n var(--ss-w-panel);\\n box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--ss-w-accent) 80%, transparent);\\n}\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:hover { border-color: var(--ss-w-accent); }\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-dash-hero-top { display: flex; align-items: center; gap: 8px; min-height: 20px; }\\n.ss-w-dash-hero-badge {\\n font-size: 10.5px; font-weight: 750; letter-spacing: .06em; text-transform: uppercase;\\n color: var(--ss-w-panel); background: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); border-radius: 999px; padding: 3px 10px;\\n white-space: nowrap;\\n}\\n.ss-w-dash-hero-chevron { flex: none; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n.ss-w-dash-hero-badge { margin-right: auto; }\\n.ss-w-dash-hero-chevron:only-child { margin-left: auto; }\\n.ss-w-dash-hero-main { display: flex; align-items: center; gap: 12px; min-width: 0; }\\n.ss-w-dash-hero-visual { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-hero-crest {\\n width: 40px; height: 40px; border-radius: 50%;\\n background-color: color-mix(in srgb, var(--ss-w-ink) 4%, var(--ss-w-panel));\\n background-size: 72%; background-position: center; background-repeat: no-repeat;\\n box-shadow: 0 0 0 2px var(--ss-w-panel), 0 0 0 3px color-mix(in srgb, var(--ss-w-ink) 10%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-crest + .ss-w-dash-hero-crest { margin-left: -8px; }\\n.ss-w-dash-hero-icon {\\n display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; font-size: 22px;\\n background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\\n.ss-w-dash-hero-title { font-size: 15.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-subtitle { font-size: 12px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-price {\\n flex: none; margin-left: auto;\\n font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 750; line-height: 1;\\n color: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); padding: 5px 9px; border-radius: 8px;\\n background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel));\\n border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-panel));\\n}\\n\\n/* club fan pre-match dashboard */\\n.ss-w-fandash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }\\n.ss-w-fandash-greeting { font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ss-w-ink); }\\n.ss-w-fandash-greeting--lead { font-weight: 400; }\\n.ss-w-fandash-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Shared card chrome -- a plain <div> for [data] cards, a <button> for [prefill] cards. Both\\n share the same box so the two families read as one system, not two ad hoc layouts. */\\n.ss-w-fandash-card {\\n display: flex; flex-direction: column; gap: 8px;\\n padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n background: var(--ss-w-panel); text-align: left;\\n color: inherit; font: inherit; width: 100%; min-width: 0;\\n}\\n.ss-w-fandash-card--tap { cursor: pointer; border-left: 3px solid var(--ss-w-accent); }\\n.ss-w-fandash-card--tap:hover { background: var(--ss-w-bubble); }\\n.ss-w-fandash-card-cta { align-self: flex-start; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); }\\n\\n/* Shared alignment primitives: a small letterspaced section eyebrow, and a 3-column value/label\\n split reused by the fixture head-to-head (and any future stat-row card). */\\n.ss-w-fandash-eyebrow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }\\n.ss-w-fandash-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-split-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; min-width: 0; }\\n.ss-w-fandash-split-value { font-size: 20px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); line-height: 1; }\\n.ss-w-fandash-split-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* fixture card */\\n.ss-w-fandash-fixture-teams { display: flex; align-items: center; gap: 10px; }\\n.ss-w-fandash-fixture-team { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }\\n.ss-w-fandash-fixture-team--away { justify-content: flex-end; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest { width: 30px; height: 30px; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest-mono { font-size: 12px; }\\n.ss-w-fandash-fixture-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-fixture-team--away .ss-w-fandash-fixture-name { text-align: right; }\\n.ss-w-fandash-fixture-vs { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n/* date + venue as labelled rows, so a long stadium name gets its own line to ellipsis in */\\n.ss-w-fandash-fixture-meta { border-top: 1px solid var(--ss-w-line); padding-top: 10px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-fixture-kickoff { font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-fixture-venue { font-weight: 600; }\\n.ss-w-fandash-fact { font-size: 12px; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 8px; }\\n/* each head-to-head figure sits on its own shaded tile, so the grid gap separates wins/draws/losses */\\n.ss-w-fandash-h2h .ss-w-fandash-split-cell { background: var(--ss-w-bubble); border-radius: 10px; padding: 12px 6px; }\\n/* extra breathing room between the tally row and the fact beyond the card's own gap */\\n.ss-w-fandash-h2h .ss-w-fandash-fact { margin-top: 4px; }\\n\\n/* Team form: a two-column result-card grid, left = home team's last 5, right = away team's last 5,\\n most-recent first. The head row carries each column's crest + name; the rows grid is filled\\n home-cell/away-cell per index so the 2-col grid lays out pairs without extra JS bookkeeping. */\\n.ss-w-fandash-teamform-head { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }\\n.ss-w-fandash-teamform-head-team { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11.5px; font-weight: 750; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest-mono { font-size: 8px; }\\n.ss-w-fandash-teamform-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-teamform-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 6px; }\\n.ss-w-fandash-teamform-slot { display: block; min-width: 0; }\\n.ss-w-fandash-teamform-cell {\\n display: flex; align-items: center; gap: 4px; border-radius: 7px; padding: 4px 5px; color: #fff;\\n}\\n.ss-w-fandash-teamform-cell--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-teamform-cell--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-teamform-cell--draw { background: var(--ss-w-faint); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest { width: 16px; height: 16px; flex: none; background: rgba(255, 255, 255, .22); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest-mono { font-size: 7px; color: #fff; }\\n.ss-w-fandash-teamform-score { flex: 1; text-align: center; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; }\\n.ss-w-fandash-injuries-more { margin-top: 10px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-injuries-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }\\n.ss-w-fandash-form-pill {\\n display: inline-grid; place-items: center; width: 16px; height: 16px;\\n border-radius: 4px; font-size: 9.5px; font-weight: 700; color: #fff;\\n}\\n.ss-w-fandash-form-pill--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-form-pill--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-form-pill--draw { background: var(--ss-w-faint); }\\n\\n/* countdown card: a compact top card -- section eyebrow left, colon-separated clock right. Each\\n segment stacks its figure over a small unit label (d/h/m/s). The exact kickoff date is not\\n repeated here; the fixture card below carries it. */\\n.ss-w-fandash-countdown-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-countdown-clock { display: inline-flex; align-items: flex-start; gap: 6px; color: var(--ss-w-accent); }\\n.ss-w-fandash-countdown-seg { display: inline-flex; flex-direction: column; align-items: center; }\\n.ss-w-fandash-countdown-value { font-size: 26px; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.01em; }\\n.ss-w-fandash-countdown-unit { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); margin-top: 3px; }\\n.ss-w-fandash-countdown-colon { font-size: 22px; font-weight: 750; line-height: 1; color: var(--ss-w-faint); }\\n\\n/* injuries + transfers: two-column ours/theirs, in/out */\\n.ss-w-fandash-transfers-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n/* injuries: a 1px divider column sits between the two team sections, each headed by crest + name */\\n.ss-w-fandash-injuries-cols { display: grid; grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1fr); gap: 12px; }\\n.ss-w-fandash-injuries-divider { background: var(--ss-w-line); }\\n.ss-w-fandash-injuries-col, .ss-w-fandash-transfers-col { min-width: 0; display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-transfers-col-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n.ss-w-fandash-injuries-col-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest-mono { font-size: 9px; }\\n.ss-w-fandash-injuries-col-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-injuries-empty, .ss-w-fandash-transfers-empty { font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-list, .ss-w-fandash-transfer-list { list-style: none; display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-fandash-injury-row, .ss-w-fandash-transfer-row { display: flex; flex-direction: column; gap: 1px; }\\n.ss-w-fandash-injury-name, .ss-w-fandash-transfer-name { font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }\\n.ss-w-fandash-injury-meta { display: flex; flex-wrap: wrap; gap: 4px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-status { font-weight: 700; color: var(--ss-w-neg); }\\n.ss-w-fandash-transfer-club { font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-transfer-type { align-self: flex-start; font-size: 9.5px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 1px 7px; margin-top: 2px; }\\n\\n/* reason-to-bet */\\n.ss-w-fandash-reason-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-reason-item { font-size: 12.5px; padding-left: 14px; position: relative; }\\n.ss-w-fandash-reason-item::before { content: \\\"•\\\"; position: absolute; left: 0; color: var(--ss-w-accent); font-weight: 700; }\\n\\n/* where-to-watch */\\n.ss-w-fandash-stations { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-fandash-station-chip { font-size: 11.5px; font-weight: 600; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 999px; padding: 4px 10px; }\\n\\n/* congested week: a fixed 3-column grid of upcoming fixtures (day / opponent / comp / time) */\\n.ss-w-fandash-congested-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-congested-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 8px; border-radius: 10px; background: var(--ss-w-bubble); }\\n.ss-w-fandash-congested-day { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n.ss-w-fandash-congested-opponent { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-comp { font-size: 10px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-time { font-size: 10.5px; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n\\n/* links: 2-column grid of tappable tiles */\\n.ss-w-fandash-link-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-link-tile { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 13px; border-radius: 10px; border: 1px solid transparent; text-decoration: none; color: inherit; background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-tile:hover { background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-label { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-link-chevron { flex: none; width: 12px; height: 12px; color: var(--ss-w-accent); }\\n\\n/* post-match result: full-time scoreboard, mirroring the live card's crest + big-score treatment.\\n A neutral \\\"Full time\\\" pill sits left of a coloured Win/Draw/Loss tag; the 3-column main row\\n (home crest+name | score | away crest+name, away reversed) puts the winner's score in full ink\\n and the loser's dimmed; a centered meta line sits under a divider. */\\n.ss-w-fandash-postmatch-top { display: flex; align-items: center; gap: 8px; margin-bottom: 15px; }\\n.ss-w-fandash-postmatch-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-postmatch-tag { margin-left: auto; flex: none; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-postmatch-tag--win { color: var(--ss-w-pos); }\\n.ss-w-fandash-postmatch-tag--loss { color: var(--ss-w-neg); }\\n.ss-w-fandash-postmatch-tag--draw { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-postmatch-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-postmatch-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-postmatch-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-postmatch-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; }\\n.ss-w-fandash-postmatch-score-value--win { color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-value--lose { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-postmatch-meta { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--ss-w-line); font-size: 12px; color: var(--ss-w-faint); text-align: center; }\\n\\n/* post-match goals: a football-ball icon per goal (mirrors the live timeline ball, duplicated here\\n under the postmatch prefix), text dimmed for opponent goals and picked out in full ink + bold\\n for the club's own goals */\\n.ss-w-fandash-postmatch-goal-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-postmatch-goal { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-goal-ball { width: 11px; height: 11px; flex: none; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-goal--club { color: var(--ss-w-ink); font-weight: 650; }\\n\\n/* post-match stats: home value / stat label / away value, oriented by venue (u316), each row now\\n backed by a home/away split bar -- the big upgrade from plain text -- plus a legend. Mirrors\\n LiveStatsCard's split-bar treatment under the postmatch-prefixed classes; the shared\\n --ss-w-home/--ss-w-away/--ss-w-track tokens are defined above. */\\n.ss-w-fandash-postmatch-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-postmatch-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-postmatch-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-postmatch-stat-value { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-postmatch-stat-label { font-size: 10.5px; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-fandash-postmatch-stat-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-postmatch-stat-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-fandash-postmatch-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-postmatch-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-postmatch-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* post-match top performer (full mockup treatment): gradient initials avatar + name + a\\n prominent rating chip. Avatar gradient reuses the --ss-w-away token, same pairing as the live\\n crest fallback; \\\"?\\\" renders through the same avatar span when the name is blank. */\\n.ss-w-fandash-postmatch-perf-row { display: flex; align-items: center; gap: 12px; }\\n.ss-w-fandash-postmatch-perf-avatar {\\n flex: none; width: 42px; height: 42px; border-radius: 50%;\\n display: grid; place-items: center;\\n font-size: 14px; font-weight: 800; color: #fff;\\n background: linear-gradient(135deg, var(--ss-w-away), color-mix(in srgb, var(--ss-w-away) 55%, #000));\\n}\\n.ss-w-fandash-postmatch-perf-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; }\\n.ss-w-fandash-postmatch-perf-rating { margin-left: auto; flex: none; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 11px; }\\n\\n/* post-match next (v1, modest): whenLabel is already a complete localized phrase (opponent +\\n venue + kickoff) composed server-side, so this card renders just that one line -- dressed up\\n with an accent rule rather than a duplicated opponent line. The richer opponent-headline/venue-\\n chip/crest layout from the mockup needs a server field split and is deferred. */\\n.ss-w-fandash-postmatch-next-row { display: flex; align-items: center; gap: 10px; border-left: 3px solid var(--ss-w-accent); padding-left: 10px; }\\n.ss-w-fandash-postmatch-next-when { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.3; }\\n\\n/* resting next: the between-matches fixture teaser -- when-label left, competition badge right */\\n.ss-w-fandash-resting-next-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-next-when { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-resting-next-competition { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n\\n/* resting standings: position figure left, W-D-L/points record right */\\n.ss-w-fandash-resting-standings-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-standings-position { font-size: 15px; font-weight: 750; color: var(--ss-w-ink); }\\n.ss-w-fandash-resting-standings-record { font-size: 11.5px; color: var(--ss-w-faint); text-align: right; }\\n\\n/* resting season: top scorer / key player / season tally as stacked rows */\\n.ss-w-fandash-resting-season-rows { display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-resting-season-row { font-size: 12.5px; color: var(--ss-w-ink); }\\n\\n/* resting form: reuses the fixture last-five pill classes (ss-w-fandash-form / -form-pill) */\\n.ss-w-fandash-resting-form .ss-w-fandash-form { margin-top: 2px; }\\n\\n/* live score: pulsing Live pill, crests (real image or a coloured initials fallback), a big\\n tabular score, and an optional scorers line. Also where the shared home/away venue-colour\\n tokens (--ss-w-home / --ss-w-away / --ss-w-track) are defined above -- the timeline and stats\\n cards reuse them. */\\n.ss-w-fandash-live-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-fandash-live-pill { display: inline-flex; flex: none; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: #fff; background: var(--ss-w-neg); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; animation: ss-w-fandash-live-pulse 1.3s ease-in-out infinite; }\\n@keyframes ss-w-fandash-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }\\n@media (prefers-reduced-motion: reduce) {\\n .ss-w-fandash-live-dot { animation: none; }\\n}\\n.ss-w-fandash-live-minute { flex: none; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-competition { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-live-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-live-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-live-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-live-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-live-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-live-scorers { margin-top: 12px; display: flex; justify-content: flex-end; gap: 7px; align-items: center; font-size: 12.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-live-scorers-icon { flex: none; color: var(--ss-w-away); }\\n\\n/* live timeline: a compact two-sided event list down a centre spine -- each club's events sit on\\n its own side (home left, away right), most-recent 3 shown with a \\\"See more\\\" toggle for the\\n rest. A 3-column grid (txt | badge | txt) per row; the spine itself is a ::before on the list. */\\n.ss-w-fandash-live-tl { position: relative; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-live-tl::before { content: \\\"\\\"; position: absolute; left: 50%; top: 1px; bottom: 1px; width: 2px; background: var(--ss-w-line); transform: translateX(-1px); }\\n.ss-w-fandash-live-tl-ev { display: grid; grid-template-columns: 1fr 32px 1fr; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-tl-txt { display: flex; align-items: center; gap: 7px; font-size: 13px; min-width: 0; }\\n.ss-w-fandash-live-tl-ev--home .ss-w-fandash-live-tl-txt { grid-column: 1; justify-content: flex-end; }\\n.ss-w-fandash-live-tl-ev--away .ss-w-fandash-live-tl-txt { grid-column: 3; justify-content: flex-start; flex-direction: row-reverse; }\\n.ss-w-fandash-live-tl-who { font-weight: 650; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-fandash-live-tl-off { font-weight: 500; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-who { font-weight: 800; }\\n.ss-w-fandash-live-tl-badge { grid-column: 2; justify-self: center; min-width: 29px; height: 19px; padding: 0 4px; border-radius: 6px; display: grid; place-items: center; font-size: 11px; font-weight: 800; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); font-variant-numeric: tabular-nums; z-index: 1; }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-badge { background: var(--ss-w-accent); color: #fff; border-color: transparent; }\\n.ss-w-fandash-live-tl-ico { width: 17px; height: 17px; flex: none; display: grid; place-items: center; }\\n.ss-w-fandash-live-tl-ico--goal { border-radius: 50%; background: color-mix(in srgb, var(--ss-w-away) 16%, transparent); }\\n.ss-w-fandash-live-tl-ball { width: 12px; height: 12px; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-live-tl-card { width: 9px; height: 12px; border-radius: 2px; display: block; }\\n.ss-w-fandash-live-tl-card--yellow { background: var(--ss-w-cta); }\\n.ss-w-fandash-live-tl-card--red { background: var(--ss-w-away); }\\n.ss-w-fandash-live-tl-subarrows { font-size: 11px; font-weight: 900; line-height: 1; letter-spacing: -1px; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-tl-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-more { margin-top: 4px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-live-tl-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n\\n/* live stats: club value / stat label / opponent value, each row backed by a home/away split\\n bar, plus an optional momentum wave (or its text fallback) and a club/opponent colour legend.\\n No side signal reaches this card, so the club is always the home token and the opponent is\\n always the away token -- see LiveStatsCard.tsx. */\\n.ss-w-fandash-live-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-live-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-live-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-live-stat-value { font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-live-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-live-stat-label { font-size: 10.5px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-live-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-live-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-live-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n\\n.ss-w-fandash-live-momentum { font-size: 11.5px; font-weight: 650; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fandash-live-mom-caption { display: block; margin-bottom: 5px; font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-mom-svg { width: 100%; height: 56px; display: block; overflow: visible; }\\n.ss-w-fandash-live-mom-home { fill: var(--ss-w-home); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-away { fill: var(--ss-w-away); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-line { fill: none; stroke: color-mix(in srgb, var(--ss-w-ink) 55%, transparent); stroke-width: 1.5; }\\n.ss-w-fandash-live-mom-base { stroke: var(--ss-w-line); stroke-width: 1; stroke-dasharray: 3 3; }\\n.ss-w-fandash-live-mom-plot { position: relative; }\\n.ss-w-fandash-live-mom-now {\\n position: absolute; width: 7px; height: 7px; border-radius: 50%;\\n transform: translate(-50%, -50%);\\n background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-ink);\\n pointer-events: none;\\n}\\n.ss-w-mon-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); text-align: center; }\\n.ss-w-mon-mom .ss-w-fandash-live-mom { margin-top: 6px; padding-top: 0; border-top: none; }\\n\\n.ss-w-fandash-live-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-live-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */\\n.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); overflow-x: auto; scrollbar-width: none; }\\n.ss-w-tabs::-webkit-scrollbar { display: none; }\\n.ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; flex: none; white-space: nowrap; }\\n.ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-tab-count { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 999px; padding: 1px 6px; }\\n.ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }\\n.ss-w-tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n\\n/* Matches tab match card (MonitorMatchCard): pill row, crest/score main row, per-stat split\\n bars (venue-oriented -- home always left/blue, away always right/red, never club-oriented,\\n the u316 bug class), a promoted-market strip for the user's pinned stat chips, and a grace\\n note once the match has gone full time. Reuses the --ss-w-home/--ss-w-away/--ss-w-track venue\\n tokens and .ss-w-fandash-live-pill for the Live pill so all live surfaces share one look. */\\n.ss-w-mon { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }\\n.ss-w-mon-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-mon-pill { display: inline-flex; flex: none; align-items: center; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-mon-min { flex: none; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-comp { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mon-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-mon-side { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-w-mon-side--away { flex-direction: row-reverse; text-align: right; }\\n/* long club names (Wolverhampton Wanderers) wrap to two lines instead of truncating mid-word */\\n.ss-w-mon-name { min-width: 0; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-mon-vs { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; }\\n.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); }\\n.ss-w-mon-score i { font-style: normal; color: var(--ss-w-faint); font-weight: 500; margin: 0 4px; }\\n.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); }\\n.ss-w-mon-scorers-col { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\\n.ss-w-mon-scorers-col li { overflow-wrap: anywhere; }\\n.ss-w-mon-scorers-home { text-align: right; }\\n.ss-w-mon-scorers-away { text-align: left; }\\n.ss-w-mon-scorers-ball { flex: none; align-self: start; line-height: 1.35; }\\n.ss-w-fact { display: flex; flex-direction: column; gap: 7px; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--ss-w-accent) 9%, transparent); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, transparent); }\\n.ss-w-fact-k { display: flex; align-items: center; gap: 6px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-w-fact-min { color: var(--ss-w-ink); letter-spacing: 0; }\\n.ss-w-fact-subj { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 650; color: var(--ss-w-faint); }\\n.ss-w-fact-text { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-fact-basis { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fact-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 8px; }\\n.ss-w-fact-foot { display: flex; align-items: center; gap: 14px; }\\n.ss-w-fact-link { font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); background: none; border: none; padding: 4px 0; min-height: 32px; cursor: pointer; }\\n.ss-w-fact-link--muted { color: var(--ss-w-faint); margin-left: auto; }\\n.ss-w-fact-hist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li { display: grid; grid-template-columns: 34px 1fr; gap: 8px; padding: 9px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li:last-child { border-bottom: none; }\\n.ss-w-fact-hmin { font-size: 11px; font-weight: 800; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-fact-htext { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-ink); }\\n.ss-w-mon-stats { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-mon-stat { display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-mon-pstrip { padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--ss-w-accent) 8%, transparent); }\\n.ss-w-mon-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-mon-stat-v { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-v--home { color: var(--ss-w-home); }\\n.ss-w-mon-stat-v--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-mon-stat-l { font-size: 10px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-mon-bar { position: relative; height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-mon-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-mon-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-mon-stat-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mon-mkt { background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 6px; padding: 3px 6px; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-mkt-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }\\n.ss-w-mon-price { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-mon-susp { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 2px 6px; }\\n.ss-w-mon-asof { display: block; font-size: 10.5px; font-weight: 600; color: var(--ss-w-cta); }\\n.ss-w-mon-grace { font-size: 11px; color: var(--ss-w-faint); border-top: 1px solid var(--ss-w-line); padding-top: 8px; }\\n\\n/* Matches/Odds tab panels (MonitorTabs): the shared per-market-pin context line, the empty\\n state shown when the snapshot carries no matches/markets yet, the persistent D5 in-slip badge,\\n and the per-market-pin wrapper card (struck price on settlement is a pure CSS hook off its\\n [data-settled] attribute -- no separate class on the price element itself). */\\n.ss-w-mk-ctx { display: flex; align-items: center; gap: 6px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--ss-w-line); }\\n/* the score and the trailing badges/pin never shrink or wrap -- only the fixture name truncates */\\n.ss-w-mk-ctx b { flex: none; white-space: nowrap; }\\n/* the context line's fixture name stays single-line (the two-line clamp is for the match card) */\\n.ss-w-mk-ctx .ss-w-mon-name { display: block; white-space: nowrap; text-overflow: ellipsis; }\\n.ss-w-mk-ctx-side { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-mk-ctx-right { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }\\n/* flex:1 keeps the composer pinned to the panel bottom when a tab is empty */\\n.ss-w-mon-empty { flex: 1; padding: 24px 16px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n/* Per-pin unavailable state: the pin's context line still rendered above (score, name, unpin), but\\n the pin has neither a card nor history (compose-time rescue failed) -- a small inline note beats\\n a bare context line with nothing under it. */\\n.ss-w-mon-empty-card { padding: 8px 0 2px; font-size: 12px; color: var(--ss-w-faint); }\\n.ss-w-mon-inslip { display: inline-flex; flex: none; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-pos); }\\n/* Odds-tab item is bare: the visible card is the market-odds card itself (no outer wrapper card),\\n with an optional slim live strip above it. */\\n.ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-mk-live { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0 2px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mk-live-score { color: var(--ss-w-ink); font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-w-mon-oddspin[data-settled] .ss-w-mo-price,\\n.ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }\\n\\n/* market accordion (Task 9): one collapsed row per available market, expanding into a reused\\n MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */\\n/* Pinned-match tile: the match card + its odds accordion, spaced apart. */\\n.ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-acc { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-acc-row { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); overflow: hidden; }\\n/* Row header: expand toggle (flex:1) + the market PinToggle as a sibling (no nested buttons). */\\n.ss-w-acc-head { display: flex; align-items: center; gap: 8px; padding: 6px 9px 6px 11px; }\\n.ss-w-acc-toggle { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); padding: 5px 0; }\\n/* Suspended: the row stays listed (knowing a market is off is useful) but is not tappable --\\n its card is unservable, so a pointer cursor would promise something that cannot load. */\\n.ss-w-acc-toggle--susp { cursor: default; color: var(--ss-w-faint); }\\n.ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; flex: none; }\\n.ss-w-acc-label { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); flex: none; }\\n.ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); flex: none; }\\n.ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-acc-insight { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }\\n\\n/* ---- Today tab (u355) ---- */\\n.ss-w-sec-head { display: flex; align-items: center; gap: 7px; padding: 2px 2px 0; font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }\\n.ss-w-sec-head::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n.ss-w-sec-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n.ss-w-today-live { display: flex; flex-direction: column; gap: 2px; }\\n\\n.ss-w-grp { border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }\\n.ss-w-grp-head { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 11px; background: var(--ss-w-bubble); border: none; font: inherit; color: var(--ss-w-ink); cursor: pointer; text-align: left; }\\n.ss-w-grp-head:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-grp-chev { color: var(--ss-w-faint); font-size: 10px; flex: none; }\\n.ss-w-grp-name { font-size: 12px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-grp-country { font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-grp-count { margin-left: auto; flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; }\\n.ss-w-grp-body { display: flex; flex-direction: column; padding: 2px 11px 6px; }\\n\\n.ss-w-drow { display: grid; grid-template-columns: 42px minmax(0,1fr) 22px; align-items: center; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-drow:last-child { border-bottom: none; }\\n.ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-drow-when--live { color: var(--ss-w-neg); }\\n/* Each side ellipsises independently: a single joined string truncates the away team off the end,\\n which is the u350 betting-card truncation one layer down. */\\n.ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-drow-side { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1 1 0; }\\n/* Away side mirrors home around the score: crest to the far edge, name aligned inward. */\\n.ss-w-drow-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-drow-nm { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* Centre slot of .ss-w-drow-fx, between the two sides: flex:none so a widening score never\\n steals width the team names need to avoid ellipsis. min-width holds the slot at the width of a\\n one-digit scoreline so an unscored row's bare dash does not pull the column out of line -- the\\n scores read as a column down the list, not a jitter. */\\n.ss-w-drow-sc { flex: none; min-width: 26px; text-align: center; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-drow--live { background: color-mix(in srgb, var(--ss-w-neg) 5%, transparent); border-radius: 8px; padding: 7px 6px; margin: 0 -6px; border-bottom: none; }\\n.ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }\\n\\n.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; }\\n\\n/* Prize banner: CTA-tinted card with icon + body column (label + chips) — still used by\\n LeaderboardEmpty.tsx's weekly-prize callout. */\\n.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)); }\\n.ss-w-prize-icon { flex: none; font-size: 20px; line-height: 1; padding-top: 1px; }\\n.ss-w-prize-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-prize-text { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.35; overflow-wrap: anywhere; }\\n\\n/* ── games hub (u393) ── */\\n.ss-g-hub-wrap { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; background: var(--ss-g-ground); font-family: var(--ss-g-font-body); color: var(--ss-g-ink); }\\n.ss-g-hub { display: flex; flex-direction: column; gap: 14px; padding: 14px 16px 20px; }\\n.ss-g-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-stat { display: flex; flex-direction: column; gap: 2px; padding: 9px 12px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); min-width: 0; }\\n.ss-g-stat-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-stat-v { display: flex; align-items: baseline; gap: 4px; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 24px; line-height: 1; white-space: nowrap; }\\n.ss-g-stat-v svg { color: var(--ss-g-flame); align-self: center; }\\n.ss-g-stat-v small { font-family: var(--ss-g-font-body); font-size: 12px; font-weight: 600; color: var(--ss-g-muted); overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-stat-v--accent { color: var(--ss-w-accent); }\\n.ss-g-prize { align-self: flex-start; }\\n.ss-g-tile { position: relative; display: flex; flex-direction: column; gap: 4px; padding: 10px; min-width: 0; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; }\\n.ss-g-tile:not([data-disabled]):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-tile[data-disabled] { opacity: .55; cursor: default; }\\n.ss-g-tile--tile { height: 148px; }\\n.ss-g-tile-art { height: 74px; border-radius: 10px; background: var(--ss-g-raised); display: flex; align-items: center; justify-content: center; margin-bottom: 4px; }\\n.ss-g-art { width: 100%; height: 100%; }\\n.ss-g-art-fg { fill: var(--ss-g-strong-line); }\\n.ss-g-art-accent { fill: var(--ss-w-accent); }\\n.ss-g-art-accent-stroke { fill: none; stroke: var(--ss-w-accent); stroke-width: 2; }\\n.ss-g-art-dot { fill: var(--ss-g-pitch-mark); }\\n.ss-g-art-pitch { fill: var(--ss-g-pitch); stroke: var(--ss-g-pitch-line); }\\n.ss-g-art-block { fill: var(--ss-g-line); }\\n.ss-g-art-correct { fill: var(--ss-g-correct); }\\n.ss-g-art-dash { fill: none; stroke: var(--ss-g-strong-line); stroke-dasharray: 3 2; stroke-width: 1.5; }\\n.ss-g-art-line { stroke: var(--ss-g-line-warm); stroke-width: 2; }\\n.ss-g-art-ink { fill: none; stroke: var(--ss-g-on-accent); stroke-width: 2; }\\n.ss-g-art-q { fill: var(--ss-w-accent); font: 800 20px var(--ss-g-font-display); }\\n.ss-g-tile-title { font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status[data-tone=\\\"accent\\\"] { color: var(--ss-w-accent); font-weight: 600; }\\n.ss-g-tile-status[data-tone=\\\"success\\\"] { color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-tile--hero { flex-direction: row; min-height: 184px; padding: 0; overflow: hidden; border-radius: 18px; background: var(--ss-g-warm); border-color: var(--ss-g-line-warm); }\\n.ss-g-hero-text { flex: 0 0 60%; display: flex; flex-direction: column; justify-content: center; gap: 6px; padding: 18px; min-width: 0; }\\n.ss-g-hero-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-hero-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: .95; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-hero-sub { font-size: 14px; color: var(--ss-g-ink-2); }\\n.ss-g-hero-cta { align-self: flex-start; margin-top: 6px; padding: 9px 16px; border-radius: 999px; background: var(--ss-w-accent); color: var(--ss-g-on-accent); font-size: 14px; font-weight: 700; }\\n.ss-g-hero-art { flex: 1; display: flex; align-items: center; justify-content: center; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sec { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 6px; }\\n.ss-g-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-sec-head span { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-tile--wide { flex-direction: row; align-items: center; gap: 14px; min-height: 104px; }\\n.ss-g-wide-art { width: 84px; height: 84px; flex: none; border-radius: 10px; background: var(--ss-g-raised); }\\n.ss-g-wide-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }\\n.ss-g-wide-chev { color: var(--ss-g-muted); transform: rotate(180deg); display: flex; }\\n\\n/* ── Mystery Tiger (u393) ── */\\n.ss-g-mt-card { flex: none; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); overflow: hidden; display: flex; flex-direction: column; }\\n.ss-g-mt-portrait { position: relative; height: 178px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 16px, var(--ss-g-warm) 16px 36px); }\\n.ss-g-mt-portrait .ss-g-sil { font-size: 46px; }\\n.ss-g-mt-photo { width: 132px; height: 132px; margin-bottom: 30px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 40px var(--ss-g-font-display); }\\n.ss-g-mt-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-cp-photo { width: 64px; height: 64px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 22px var(--ss-g-font-display); }\\n.ss-g-cp-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-mt-reveal-name { position: absolute; bottom: 6px; left: 12px; right: 12px; text-align: center; font: 800 20px var(--ss-g-font-display); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-known { display: grid; gap: 6px; padding: 12px; }\\n.ss-g-mt-known-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }\\n.ss-g-mt-lab { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-known-v { width: 100%; height: 38px; border-radius: 8px; display: grid; place-items: center; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-mt-known-v[data-state=\\\"known\\\"] { background: var(--ss-g-correct); color: var(--ss-g-on-correct); font-size: 18px; }\\n.ss-g-mt-known-v[data-state=\\\"range\\\"] { border: 1px dashed var(--ss-g-strong-line); }\\n.ss-g-mt-table { display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-mt-thead, .ss-g-mt-row { display: grid; gap: 5px; align-items: center; }\\n.ss-g-mt-thead { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-thead span:not(:first-child) { text-align: center; }\\n.ss-g-mt-who { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-mt-av { width: 38px; height: 38px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 12px; font-weight: 700; overflow: hidden; }\\n.ss-g-mt-names { display: flex; flex-direction: column; min-width: 0; line-height: 1.1; }\\n.ss-g-mt-first { font-size: 11px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-last { font-size: 14px; font-weight: 700; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-cell { height: 42px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); overflow: hidden; }\\n.ss-g-mt-cell[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); border-color: transparent; color: var(--ss-g-on-correct); }\\n.ss-g-mt-cell[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); border-color: transparent; color: var(--ss-g-on-accent); }\\n.ss-g-mt-cell-dir { font-size: 10px; margin-top: 2px; }\\n.ss-g-mt-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mt-legend span { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-g-mt-sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }\\n.ss-g-mt-sw[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); }\\n.ss-g-mt-sw[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); }\\n.ss-g-mt-hint { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-mt-hint svg { color: var(--ss-w-accent); flex: none; margin-top: 1px; }\\n\\n/* ── Higher or Lower (u393) ── */\\n.ss-g-hl-prompt { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; }\\n.ss-g-hl-prompt-q { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-hl-prompt-stat { font: 800 30px var(--ss-g-font-display); text-transform: uppercase; letter-spacing: .02em; line-height: 1.05; }\\n.ss-g-hl-prompt-season { font-size: 12px; color: var(--ss-g-muted); }\\n/* The pair fills whatever height the panel leaves (a laptop demo panel is ~670px, the design 860px):\\n both cards share it and the photos scale with them, so Higher/Lower never fall below the fold. */\\n.ss-g-hl .ss-g-body { overflow-y: auto; container: hl / size; }\\n.ss-g-hl-pair { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-hl-card { flex: 1 1 0; min-height: min-content; max-height: 240px; display: flex; border-radius: 18px; overflow: hidden; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-hl-card--b { border-color: var(--ss-g-line-warm); }\\n.ss-g-hl-photo-wrap { width: 38%; max-width: 160px; flex: none; align-self: stretch; display: flex; align-items: flex-end; justify-content: center; background: var(--ss-g-raised); overflow: hidden; }\\n.ss-g-hl-photo-wrap .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-hl-photo { width: 100%; height: 100%; display: grid; place-items: center; color: var(--ss-g-muted); font: 800 36px var(--ss-g-font-display); }\\n.ss-g-hl-photo img { width: 100%; height: 100%; object-fit: cover; object-position: top; }\\n.ss-g-hl-info { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 12px 14px; }\\n.ss-g-hl-first { font-size: 13px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-surname { font: 800 26px var(--ss-g-font-display); text-transform: uppercase; line-height: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-value { font: 800 56px var(--ss-g-font-display); line-height: .95; color: var(--ss-w-accent); margin-top: 6px; }\\n.ss-g-hl-stat { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-hl-btns { display: flex; flex-direction: row; gap: 8px; margin-top: 12px; }\\n.ss-g-hl-btns .ss-g-btn { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0 6px; gap: 4px; }\\n/* Labels stay on one line: Turkish \\\"DAHA FAZLA\\\" wrapped to two in a ~115px button. */\\n.ss-g-hl-btns .ss-g-btn { font-weight: 800; font-size: 13px; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }\\n.ss-g-hl-btns .ss-g-btn svg { flex: none; }\\n/* Phone-width cards: the info column is ~230px, too narrow for \\\"DAHA FAZLA\\\" + icon side by side.\\n Drop the icons and tighten the type first; stack the buttons only when even that cannot fit. */\\n.ss-g-hl-info { container: hlinfo / inline-size; }\\n@container hlinfo (max-width: 280px) {\\n .ss-g-hl-btns .ss-g-btn svg { display: none; }\\n .ss-g-hl-btns .ss-g-btn { font-size: 12px; letter-spacing: 0; padding: 0 4px; }\\n}\\n@container hlinfo (max-width: 180px) {\\n .ss-g-hl-btns { flex-direction: column; }\\n}\\n.ss-g-hl-vs { position: relative; z-index: 1; flex: none; align-self: center; width: 44px; height: 44px; margin: -28px 0; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-ground); border: 2px solid var(--ss-g-line-warm); color: var(--ss-w-accent); font: 800 18px var(--ss-g-font-display); }\\n/* Clear the VS badge that straddles the seam between the two cards. */\\n.ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 24px; }\\n.ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 24px; }\\n/* Short panels (a ~580px widget on a small laptop): tighten the type so both cards and the\\n Higher/Lower buttons stay on screen; below this the body scrolls rather than clipping names. */\\n@container hl (max-height: 420px) {\\n .ss-g-hl-prompt-stat { font-size: 24px; }\\n .ss-g-hl-prompt-season { display: none; }\\n .ss-g-hl-info { padding: 8px 12px; }\\n .ss-g-hl-surname { font-size: 22px; }\\n .ss-g-hl-value { font-size: 42px; margin-top: 2px; }\\n .ss-g-hl-btns { margin-top: 8px; }\\n .ss-g-hl-vs { width: 38px; height: 38px; margin: -22px 0; font-size: 15px; }\\n .ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 18px; }\\n .ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 18px; }\\n}\\n.ss-g-hl-feedback { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--ss-g-ink-2); }\\n.ss-g-hl-feedback[data-correct=\\\"true\\\"] svg { color: var(--ss-g-success); }\\n.ss-g-hl-feedback[data-correct=\\\"false\\\"] svg { color: var(--ss-g-wrong-mark); }\\n.ss-g-hl-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\\n.ss-g-hl-dots { display: flex; gap: 5px; }\\n.ss-g-hl-dot { width: 22px; height: 22px; border-radius: 50%; border: 1.5px dashed var(--ss-g-strong-line); }\\n.ss-g-hl-dot[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); border: 0; }\\n.ss-g-hl-dot[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); border: 0; }\\n.ss-g-hl-pts { font: 700 22px var(--ss-g-font-display); white-space: nowrap; }\\n.ss-g-hl-pts-unit { font-size: 13px; color: var(--ss-g-muted); }\\n\\n/* ── Guess the XI (u393) ── pitch colours are the fixed --ss-g-pitch* tokens (Task 1) */\\n.ss-g-gxi-pitch { position: relative; flex: none; height: 380px; border-radius: 18px; overflow: hidden; border: 1px solid var(--ss-g-pitch-line);\\n background: repeating-linear-gradient(180deg, color-mix(in srgb, var(--ss-g-pitch) 92%, var(--ss-g-pitch-mark)) 0 12.5%, var(--ss-g-pitch) 12.5% 25%); }\\n.ss-g-gxi-rows { position: absolute; inset: 14px 6px; display: flex; flex-direction: column; justify-content: space-between; }\\n.ss-g-gxi-row { display: flex; justify-content: space-evenly; align-items: flex-start; }\\n.ss-g-gxi-node { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; max-width: 72px; }\\n.ss-g-gxi-disc { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-pitch-chip); border: 2px solid var(--ss-g-pitch-ink); font-size: 22px; line-height: 1; }\\n.ss-g-gxi-node[data-revealed] .ss-g-gxi-disc { border-color: var(--ss-w-accent); }\\n.ss-g-gxi-disc[data-code] { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; letter-spacing: .02em; color: var(--ss-g-pitch-ink); }\\n.ss-g-gxi-pos { max-width: 100%; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-pitch-chip); color: var(--ss-g-pitch-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-gxi-pos--name { color: var(--ss-w-accent); text-transform: uppercase; }\\n.ss-g-gxi-wrong { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }\\n.ss-g-gxi-wrong-l { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-gxi-wrong-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 6px; border-radius: 999px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-muted); }\\n/* u407: lineup photo — fills the 44px disc like the flag does */\\n.ss-g-gxi-disc--photo { overflow: hidden; border: 2px solid var(--ss-w-accent); }\\n.ss-g-gxi-disc--photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-gxi-disc--photo .ss-w-av-initials { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; color: var(--ss-g-pitch-ink); }\\n/* u407: answer reveal — prominent row using theme tokens, works on dark/navy/light surfaces */\\n.ss-g-gxi-answer { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 12px 16px; border-radius: 14px; background: var(--ss-g-warm); border: 1.5px solid var(--ss-g-line-warm); }\\n.ss-g-gxi-answer-label { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); flex: none; }\\n.ss-g-gxi-answer-name { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; text-transform: uppercase; color: var(--ss-g-ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n\\n/* ---- Daily Quiz (u393) ---- */\\n.ss-g-dq-stem { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 30px; line-height: 1.05; overflow-wrap: anywhere; }\\n.ss-g-dq-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-dq-opt { position: relative; min-height: 96px; padding: 44px 12px 12px; border-radius: 16px; border: 1.5px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; display: flex; align-items: flex-end; min-width: 0; }\\n.ss-g-dq-opt:hover:not(:disabled) { border-color: var(--ss-g-line-warm); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-dq-opt:disabled { cursor: default; }\\n.ss-g-dq-badge { position: absolute; top: 10px; left: 10px; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; background: var(--ss-g-raised); font-weight: 700; font-size: 13px; color: var(--ss-g-ink); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] .ss-g-dq-badge { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-dq-opt-name { display: flex; flex-direction: column; min-width: 0; line-height: 1.05; }\\n.ss-g-dq-opt-first { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-dq-opt-last { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-dq-opt-suffix { margin-top: 2px; font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-dq-opt-full { font-size: 15px; font-weight: 600; line-height: 1.25; overflow-wrap: anywhere; }\\n.ss-g-dq-nav { display: flex; gap: 10px; }\\n.ss-g-dq-nav .ss-g-btn--block { flex: 1; }\\n.ss-g-dq-rq { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-dq-rq-stem { font-weight: 700; font-size: 14px; }\\n.ss-g-dq-rq-opts { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-g-dq-rq-opt { padding: 4px 10px; border-radius: 999px; font-size: 13px; font-weight: 600; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-dq-rq-opt--correct { background: var(--ss-g-correct); color: var(--ss-g-on-correct); }\\n.ss-g-dq-rq-opt--wrong { background: var(--ss-g-wrong); color: var(--ss-g-on-correct); }\\n.ss-g-dq-why { font-size: 13px; color: var(--ss-g-ink-2); }\\n/* u407: player avatar in quiz option — centered in top half, badge at top-left unaffected */\\n.ss-g-dq-opt-av { position: absolute; top: 7px; right: 10px; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 13px; font-weight: 700; flex: none; }\\n.ss-g-dq-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-dq-opt-av .ss-w-av-initials { font-size: 11px; }\\n\\n/* ---- Career Path (u393) ---- */\\n.ss-g-cp-card { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: 16px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-cp-card-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1; }\\n.ss-g-cp-card-title { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-cp-hint { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-cp-locks { display: flex; gap: 6px; flex-wrap: wrap; }\\n.ss-g-cp-line { list-style: none; display: flex; flex-direction: column; }\\n.ss-g-cp-step { display: flex; gap: 14px; align-items: stretch; }\\n.ss-g-cp-rail { display: flex; flex-direction: column; align-items: center; width: 52px; flex: none; }\\n.ss-g-cp-tile { width: 52px; height: 52px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; }\\n.ss-g-cp-tile--locked { border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); }\\n.ss-g-cp-tile--faint { border: 1.5px dashed var(--ss-g-line); background: transparent; color: var(--ss-g-faint); }\\n.ss-g-cp-conn { width: 2px; flex: 1; min-height: 14px; background: var(--ss-g-line-warm); }\\n.ss-g-cp-conn--faint { background: var(--ss-g-line); }\\n.ss-g-cp-step:last-child .ss-g-cp-conn { display: none; }\\n.ss-g-cp-step-text { display: flex; flex-direction: column; justify-content: center; min-height: 52px; padding-bottom: 14px; min-width: 0; }\\n.ss-g-cp-club { font-weight: 700; font-size: 16px; overflow-wrap: anywhere; }\\n.ss-g-cp-sub { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-cp-loan { color: var(--ss-w-accent); font-weight: 600; }\\n\\n/* Game screen host: fills the panel; each screen owns its header, gutters and scrolling. */\\n.ss-w-gscreen-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 0; overflow: hidden; background: var(--ss-g-ground); }\\n.ss-w-gscreen { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0; }\\n.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; }\\n\\n/* ---- Leaderboard (D2) ---- */\\n/* Outer shell */\\n.ss-w-lb2 { display: flex; flex-direction: column; gap: 12px; }\\n\\n/* Segmented control: This week / All time */\\n.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; }\\n.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; }\\n.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); }\\n\\n/* Row list */\\n.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); }\\n.ss-w-lb2-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-lb2-row:last-child { border-bottom: none; }\\n/* Highlighted \\\"you\\\" row: full-width tint via negative margin trick, contained by border-radius above */\\n.ss-w-lb2-row--you { background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); }\\n.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); }\\n.ss-w-lb2-rank--top3 { color: var(--ss-w-cta); }\\n.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); }\\n.ss-w-lb2-points { flex: none; font-size: 13px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-lb2-streak { flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); padding-left: 4px; }\\n\\n/* Kit-prize separator: a labelled hairline (eyebrow + two growing lines) */\\n.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); }\\n.ss-w-kitline::before, .ss-w-kitline::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n\\n/* Off-board treatment: dashed pill indicating rank is outside top N */\\n.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; }\\n\\n/* ---- Leaderboard empty / weekly-reset default state ---- */\\n.ss-w-lb-empty { display: flex; flex-direction: column; gap: 12px; flex: 1; }\\n.ss-w-lb-empty-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 20px 16px; border: 1px dashed color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); border-radius: 14px; background: color-mix(in srgb, var(--ss-w-cta) 6%, var(--ss-w-panel)); }\\n.ss-w-lb-empty--alltime { align-items: center; justify-content: center; text-align: center; padding: 24px 16px; }\\n.ss-w-lb-empty-icon { font-size: 30px; line-height: 1; }\\n.ss-w-lb-empty-title { margin: 2px 0 0; font-size: 16px; font-weight: 800; color: var(--ss-w-ink); }\\n.ss-w-lb-empty-body { margin: 0; max-width: 30ch; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-faint); }\\n.ss-w-lb-empty-cta { margin-top: 6px; border: none; border-radius: 10px; padding: 9px 18px; font: inherit; font-size: 13px; font-weight: 700; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); cursor: pointer; }\\n.ss-w-lb-empty-cta:hover { filter: brightness(1.04); }\\n.ss-w-lb-last { display: flex; align-items: center; gap: 7px; padding-top: 10px; border-top: 1px solid var(--ss-w-line); font-size: 11px; }\\n.ss-w-lb-last-label { text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--ss-w-faint); }\\n.ss-w-lb-last-handle { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-lb-last-points { flex: none; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n\\n/* PlayerAvatar initials fallback (PlayerAvatar.tsx) — size/colour inherit from the avatar class. */\\n.ss-w-av-initials { font-weight: 800; line-height: 1; text-transform: uppercase; letter-spacing: .02em; }\\n\\n/* ---- Beat the Grid (u393) ---- */\\n.ss-g-btg-grid { display: grid; gap: 6px; }\\n/* While the search sheet is pinned below, the grid shrinks its rows to share the body with it\\n instead of pushing the bottom row under the sheet. */\\n.ss-g-btg-grid--fit { flex: 0 1 auto; min-height: 0; }\\n.ss-g-btg-colhdr { min-height: 0; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; text-align: center; padding: 0 4px; font-size: 12px; font-weight: 700; line-height: 1.1; min-width: 0; overflow-wrap: anywhere; overflow: hidden; }\\n.ss-g-btg-colhdr[data-meta] { overflow-wrap: normal; word-break: normal; hyphens: none; font-size: 11px; letter-spacing: 0; }\\n.ss-g-btg-colhdr svg { color: var(--ss-w-accent); flex: none; }\\n.ss-g-btg-rowhdr { border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; letter-spacing: .04em; text-transform: uppercase; overflow-wrap: anywhere; text-align: center; overflow: hidden; }\\n.ss-g-btg-rowhdr[data-meta] { font-size: 10px; font-family: var(--ss-g-font-body); font-weight: 700; letter-spacing: -0.01em; text-transform: none; word-break: normal; overflow-wrap: normal; hyphens: none; line-height: 1.25; padding: 0 2px; }\\n.ss-g-btg-cell { position: relative; min-height: 0; min-width: 0; border-radius: 12px; border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; cursor: pointer; font: inherit; padding: 0; }\\n.ss-g-btg-cell:disabled { cursor: default; }\\n.ss-g-btg-cell[data-state=\\\"active\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"], .ss-g-btg-cell[data-state=\\\"wrong\\\"] { justify-content: flex-end; background: var(--ss-g-surface); border-style: solid; }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-btg-badge { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center; color: var(--ss-g-on-correct); }\\n.ss-g-btg-badge--correct { background: var(--ss-g-correct); }\\n.ss-g-btg-badge--wrong { background: var(--ss-g-wrong); }\\n.ss-g-btg-rarity { position: absolute; top: 6px; left: 6px; padding: 1px 6px; border-radius: 999px; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] .ss-g-btg-rarity { background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-btg-cell .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-btg-name { width: 100%; padding: 4px 2px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-display); font-weight: 700; font-size: 14px; text-transform: uppercase; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-plus { display: flex; }\\n.ss-g-btg-pin { flex: none; padding: 0 12px 12px; }\\n.ss-g-btg-sheet { padding: 14px; border-radius: 18px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-btg-sheet-hdr { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-btg-sheet-hdr .ss-g-chip { padding: 4px 10px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-sheet-x { color: var(--ss-g-muted); display: flex; flex: none; }\\n.ss-g-btg-sheet-close { margin-left: auto; flex: none; width: 44px; height: 44px; border: 0; border-radius: 10px; background: transparent; color: var(--ss-g-muted); display: grid; place-items: center; cursor: pointer; }\\n.ss-g-btg-sheet-close:hover { background: var(--ss-g-raised); color: var(--ss-g-ink); }\\n.ss-g-btg-sheet .ss-g-search-box { height: 48px; border-radius: 12px; background: var(--ss-g-ground); }\\n.ss-g-btg-sheet-empty { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-btg-sheet .ss-g-opt { background: var(--ss-g-raised); }\\n.ss-g-btg-sheet .ss-g-opts { max-height: 160px; }\\n.ss-g-btg-result-name { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-result-plus { color: var(--ss-w-accent); display: flex; }\\n/* u407: cell avatar replaces Silhouette */\\n.ss-g-btg-av { width: 38px; height: 38px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 12px; font-weight: 700; }\\n.ss-g-btg-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-btg-av .ss-w-av-initials { font-size: 12px; }\\n/* u407: coach photo in row/col header */\\n.ss-g-btg-coach-av { width: 28px; height: 28px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 10px; font-weight: 700; }\\n.ss-g-btg-coach-av img { width: 100%; height: 100%; object-fit: cover; }\\n/* u407: country flag emoji in header — sized to match other header icons */\\n.ss-g-btg-hdr-flag { font-size: 20px; line-height: 1; flex: none; }\\n/* u407: club crest in col/row header */\\n.ss-g-btg-colhdr .ss-g-crest, .ss-g-btg-rowhdr .ss-g-crest { width: 28px; height: 28px; flex: none; }\\n\\n/* ── Starting XI (u393) ── */\\n.ss-g-xi-pitch { position: relative; flex: none; height: 400px; border-radius: 18px; overflow: hidden; background: repeating-linear-gradient(180deg, var(--ss-g-pitch) 0 40px, color-mix(in srgb, var(--ss-g-pitch) 88%, var(--ss-g-pitch-mark)) 40px 80px); border: 1px solid var(--ss-g-pitch-line); }\\n.ss-g-xi-slot { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 48px; border: 0; padding: 0; background: transparent; color: var(--ss-g-pitch-mark); font: inherit; cursor: pointer; }\\n.ss-g-xi-slot:disabled { cursor: default; }\\n.ss-g-xi-ring { width: 48px; height: 48px; box-sizing: border-box; display: grid; place-items: center; border-radius: 50%; border: 1.5px dashed var(--ss-g-pitch-mark); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; }\\n.ss-g-xi-slot[data-state=\\\"filled\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-accent-tint); color: var(--ss-g-ink); }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-xi-tag { max-width: 72px; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-tag { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-xi-picker { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-xi-picker-head { display: flex; align-items: center; gap: 8px; font-size: 14px; }\\n.ss-g-xi-list { list-style: none; display: flex; flex-direction: column; gap: 4px; max-height: 240px; overflow-y: auto; }\\n.ss-g-xi-opt { width: 100%; display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 6px 10px; border: 0; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-xi-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-xi-opt-no { width: 28px; flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; color: var(--ss-w-accent); text-align: center; }\\n.ss-g-xi-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-opt-pos { flex: none; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 10px; font-weight: 700; }\\n.ss-g-xi-lock { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-xi-lock svg { color: var(--ss-w-accent); flex: none; }\\n\\n/* ── Stat Ladder (u393) ── */\\n.ss-g-sl-prompt { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 6px 0 6px; text-align: center; }\\n.ss-g-sl-stat { padding: 4px 10px; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }\\n.ss-g-sl-q { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; line-height: 1.05; text-transform: uppercase; }\\n.ss-g-sl-q em { font-style: normal; color: var(--ss-w-accent); }\\n.ss-g-sl-rungs { list-style: none; display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sl-rung { min-height: 84px; display: flex; align-items: center; gap: 12px; padding: 0 16px 0 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-sl-rung--mystery { min-height: 96px; border: 2px dashed var(--ss-w-accent); background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sl-rung--mystery[data-result=\\\"correct\\\"] { border: 2px solid var(--ss-g-correct); background: var(--ss-g-warm); }\\n.ss-g-sl-rung--mystery[data-result=\\\"wrong\\\"] { border: 2px solid var(--ss-g-wrong-mark); background: var(--ss-g-warm); }\\n.ss-g-sl-rank { width: 32px; height: 32px; flex: none; display: grid; place-items: center; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; }\\n.ss-g-sl-rung:first-child .ss-g-sl-rank { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-sl-rung--mystery .ss-g-sl-rank { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-sl-av { width: 52px; height: 52px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-weight: 700; }\\n.ss-g-sl-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-sl-name { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.1; }\\n.ss-g-sl-name small { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-sl-name b { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-who { flex: 1; min-width: 0; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-sl-val { flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: 1; }\\n.ss-g-sl-val--mystery { font-size: 40px; color: var(--ss-w-accent); }\\n.ss-g-sl-clue { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; line-height: 1.4; color: var(--ss-g-ink-2); }\\n.ss-g-sl-clue svg { flex: none; color: var(--ss-w-accent); }\\n.ss-g-sl-pool { list-style: none; display: flex; flex-direction: column; gap: 4px; }\\n.ss-g-sl-opt { width: 100%; min-height: 48px; display: flex; align-items: center; gap: 12px; padding: 6px 10px; border: 1px solid transparent; border-radius: 12px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] { border-color: var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] svg { color: var(--ss-w-accent); }\\n.ss-g-sl-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-sl-opt-av { width: 36px; height: 36px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 12px; font-weight: 700; }\\n.ss-g-sl-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-guess { display: flex; align-items: flex-end; gap: 8px; }\\n.ss-g-sl-guess .ss-g-search { flex: 1; min-width: 0; }\\n.ss-g-sl-guess .ss-g-btn { min-height: 50px; padding: 0 20px; border-radius: 14px; }\\n\\n/* ── Matchday Predictor (u393) ── */\\n.ss-g-mp-card { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 16px 10px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-mp-team { width: 84px; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }\\n.ss-g-mp-team .ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-mp-team-name { max-width: 100%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 17px; line-height: 1.05; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-mp-team-side { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mp-scores { display: flex; align-items: center; gap: 8px; }\\n.ss-g-mp-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }\\n.ss-g-mp-step { width: 64px; height: 44px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--ss-g-line-warm); background: var(--ss-g-raised); color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-mp-step:disabled { opacity: .4; cursor: default; }\\n.ss-g-mp-digit { width: 64px; height: 76px; display: grid; place-items: center; box-sizing: border-box; border-radius: 12px; background: var(--ss-g-ground); border: 2px solid var(--ss-g-strong-line); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 52px; line-height: 1; }\\n.ss-g-mp-digit[data-active=\\\"true\\\"] { border-color: var(--ss-w-accent); color: var(--ss-w-accent); }\\n.ss-g-mp-dash { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; color: var(--ss-g-faint); }\\n.ss-g-mp-scorer { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-mp-sec-head { display: flex; align-items: baseline; justify-content: space-between; margin-top: 10px; }\\n.ss-g-mp-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-mp-sec-head span { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mp-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-mp-pcard { position: relative; min-width: 0; height: 116px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 6px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; cursor: pointer; }\\n.ss-g-mp-pcard[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-mp-pcard:disabled { cursor: default; opacity: .6; }\\n.ss-g-mp-pcheck { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-mp-pname { max-width: 100%; font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mp-none { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--ss-g-line); background: transparent; color: var(--ss-g-muted); font: 600 14px var(--ss-g-font-body); cursor: pointer; text-align: left; }\\n.ss-g-mp-radio { width: 18px; height: 18px; flex: none; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--ss-g-strong-line); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] { color: var(--ss-g-ink); border-color: var(--ss-g-line-warm); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] .ss-g-mp-radio { border-color: var(--ss-w-accent); background: var(--ss-w-accent); box-shadow: inset 0 0 0 3px var(--ss-g-ground); }\\n.ss-g-mp-closed { padding: 10px 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-muted); font-size: 13px; text-align: center; }\\n.ss-g-mp-fun { font-size: 11px; color: var(--ss-g-faint); text-align: center; }\\n.ss-g-mp-rows { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-mp-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 14px; }\\n.ss-g-mp-row-k { color: var(--ss-g-ink-2); }\\n.ss-g-mp-row-v { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] .ss-g-mp-row-v { color: var(--ss-g-success); }\\n.ss-g-mp-row-d { color: var(--ss-g-ink); }\\n\\n/* ── Fan MOTM (u393) ── */\\n.ss-g-motm-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-motm-row { width: 100%; min-height: 60px; display: flex; align-items: center; gap: 12px; padding: 0 14px 0 10px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-motm-row:not(:disabled):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-motm-row:disabled { cursor: default; }\\n.ss-g-motm-row--voted { border: 1.5px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-motm-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-size: 13px; font-weight: 700; }\\n.ss-g-motm-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-motm-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-motm-pill { flex: none; padding: 3px 8px; font-size: 11px; }\\n.ss-g-motm-foot { font-size: 14px; font-weight: 600; }\\n.ss-g-motm-fun { font-size: 11px; color: var(--ss-g-faint); }\\n\"\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["import_react","import_widget_sdk","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","ReactMarkdown","remarkGfm","import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","directionWord","import_react","import_jsx_runtime","initials","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","Crest","import_react","head","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","initials","import_react","import_jsx_runtime","SHOWN","import_react","import_jsx_runtime","import_jsx_runtime","splitWidths","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","isTerminal","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_react","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","isLocked","React","import_react","import_jsx_runtime","import_jsx_runtime","MAX_GUESSES","parseClientState","import_react","import_jsx_runtime","parseClientState","segments","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_jsx_runtime","parseClientState","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","read","key","isRecord","parse","browserStorage","read","import_widget_sdk","import_react","import_widget_sdk","import_widget_sdk","import_react","import_react","import_react","import_react","TTL_MS","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/StatsWidget.tsx","../src/kickoff.ts","../src/i18n.ts","../src/config.ts","../src/slip.ts","../src/useHostEvents.ts","../src/components/ChatPanel.tsx","../src/components/ChatHeader.tsx","../src/assets/logo.ts","../src/components/Icons.tsx","../src/components/BrandMark.tsx","../src/components/MessageList.tsx","../src/components/Markdown.tsx","../src/components/EntityCardList.tsx","../src/components/AddToSlipButton.tsx","../src/chart.ts","../src/model.ts","../src/eventLogContext.ts","../src/slipStateContext.ts","../src/components/Toast.tsx","../src/components/OddsMovementBadge.tsx","../src/components/Crest.tsx","../src/components/PinToggle.tsx","../src/pinStore.ts","../src/components/PriceHistoryButton.tsx","../src/host.ts","../src/matchLinkContext.ts","../src/components/MatchLink.tsx","../src/components/BettingInsightList.tsx","../src/components/MarketOddsCardList.tsx","../src/components/CompactOddsList.tsx","../src/compactList.ts","../src/components/OddsMovementCard.tsx","../src/components/ActionButtons.tsx","../src/components/dashboard/DashboardTile.tsx","../src/components/dashboard/GreetingDashboard.tsx","../src/components/dashboard/FixtureCard.tsx","../src/components/dashboard/CountdownCard.tsx","../src/components/dashboard/InjuriesCard.tsx","../src/components/dashboard/ReasonToBetCard.tsx","../src/components/dashboard/WhereToWatchCard.tsx","../src/components/dashboard/CongestedWeekCard.tsx","../src/components/dashboard/TransfersCard.tsx","../src/components/dashboard/LinksCard.tsx","../src/components/dashboard/PostMatchResultCard.tsx","../src/components/dashboard/PostMatchGoalsCard.tsx","../src/components/dashboard/PostMatchStatsCard.tsx","../src/components/dashboard/PostMatchTopPerformerCard.tsx","../src/components/dashboard/PostMatchNextCard.tsx","../src/components/dashboard/RestingNextCard.tsx","../src/components/dashboard/RestingStandingsCard.tsx","../src/components/dashboard/RestingSeasonCard.tsx","../src/components/dashboard/RestingFormCard.tsx","../src/components/dashboard/LiveScoreCard.tsx","../src/useLiveClock.ts","../src/components/dashboard/LiveTimelineCard.tsx","../src/components/dashboard/MomentumWave.tsx","../src/components/dashboard/LiveStatsCard.tsx","../src/components/dashboard/ClubFanDashboard.tsx","../src/components/ChatMessage.tsx","../src/components/IntentChips.tsx","../src/scroll.ts","../src/components/ChatInput.tsx","../src/components/TabBar.tsx","../src/components/MarketAccordion.tsx","../src/components/LiveFactBlock.tsx","../src/components/MonitorMatchCard.tsx","../src/components/MonitorTabs.tsx","../src/components/FixtureRow.tsx","../src/liveClock.ts","../src/components/CompetitionGroup.tsx","../src/components/TodayPanel.tsx","../src/components/GamesPanel.tsx","../src/components/GamesLoginWall.tsx","../src/components/GamesHub.tsx","../src/components/games/ui/gameMeta.ts","../src/components/GameTileArt.tsx","../src/components/games/ui/Chip.tsx","../src/components/games/ui/icons.tsx","../src/components/GameTile.tsx","../src/components/GameScreenHost.tsx","../src/useGamePlay.ts","../src/components/games/MysteryTigerGame.tsx","../src/components/games/nationFlags.ts","../src/components/games/PlayerAvatar.tsx","../src/components/games/ui/GameHeader.tsx","../src/components/games/ui/SegmentProgress.tsx","../src/components/games/ui/SearchField.tsx","../src/components/games/ui/FooterBar.tsx","../src/components/games/ui/Silhouette.tsx","../src/components/games/ui/GameButton.tsx","../src/components/games/ui/ResultCard.tsx","../src/components/games/ui/OptionList.tsx","../src/components/games/HigherOrLowerGame.tsx","../src/components/games/CareerPathGame.tsx","../src/components/games/ui/CrestShield.tsx","../src/components/games/BeatTheGridGame.tsx","../src/components/games/GuessTheXiGame.tsx","../src/components/games/ui/PitchSvg.tsx","../src/components/games/ui/formations.ts","../src/components/games/DailyQuizGame.tsx","../src/components/games/MatchdayPredictorGame.tsx","../src/components/games/StartingXiGame.tsx","../src/components/games/StatLadderGame.tsx","../src/components/games/FanMotmGame.tsx","../src/components/games/ui/fonts.ts","../src/components/Leaderboard.tsx","../src/components/LeaderboardRow.tsx","../src/components/LeaderboardEmpty.tsx","../src/components/LeaderboardPanel.tsx","../src/matchViews.ts","../src/slipLedger.ts","../src/dashboardTap.ts","../src/theme.ts","../src/useChatStream.ts","../src/reducer.ts","../src/useLiveDashboardPoll.ts","../src/conversationStore.ts","../src/useLiveMonitor.ts","../src/useTabs.ts","../src/useMatchDiscovery.ts","../src/scheduleCache.ts","../src/dueSet.ts","../src/useGames.ts","../src/useLeaderboard.ts","../src/popupTelemetry.ts","../src/components/ChatFab.tsx","../src/components/GreetingBubble.tsx","../src/components/HostEventsProvider.tsx","../src/styles/css.generated.ts"],"sourcesContent":["export { StatsWidget } from './StatsWidget'\nexport type { StatsWidgetProps } from './StatsWidget'\nexport type { StatsWidgetConfig } from './config'\nexport { createWidgetHost } from './host'\nexport type { WidgetHost } from './host'\nexport { WIDGET_CSS } from './styles/css.generated'\n","import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from 'react'\nimport { StatsWidgetClient, type Conversation } from '@sensiblestats/widget-sdk'\nimport { normalizeUi, toClientOptions, toUserContext, type StatsWidgetConfig } from './config'\nimport { wasAdded, type SlipHandlerProps } from './slip'\nimport type { WidgetHost } from './host'\nimport { useHostEvents } from './useHostEvents'\nimport { createDashboardTapSignal } from './dashboardTap'\nimport { themeAttrs } from './theme'\nimport { useChatStream } from './useChatStream'\nimport { useLiveMonitor } from './useLiveMonitor'\nimport { useMatchDiscovery } from './useMatchDiscovery'\nimport { useGames } from './useGames'\nimport { useLeaderboard } from './useLeaderboard'\nimport { visibleGroupsOf } from './liveClock'\nimport { EventLogContext } from './eventLogContext'\nimport { usePopupTelemetry } from './popupTelemetry'\nimport { ChatFab } from './components/ChatFab'\nimport { ChatPanel } from './components/ChatPanel'\nimport { HostEventsProvider } from './components/HostEventsProvider'\nimport { WIDGET_CSS } from './styles/css.generated'\n\nexport type StatsWidgetProps =\n | { config: StatsWidgetConfig; client?: never; host?: WidgetHost }\n | { client: StatsWidgetClient; config?: Omit<StatsWidgetConfig, 'operatorId' | 'publicKey' | 'baseUrl' | 'userContext'>; host?: WidgetHost }\n\nfunction buildClient(props: StatsWidgetProps): { client: StatsWidgetClient; conversation: Conversation } | null {\n try {\n if ('client' in props && props.client) {\n return { client: props.client, conversation: props.client.conversation() }\n }\n const cfg = props.config as StatsWidgetConfig\n const client = new StatsWidgetClient(toClientOptions(cfg))\n return { client, conversation: client.conversation(toUserContext(cfg)) }\n } catch (err) {\n console.error('[StatsWidget] failed to initialize:', err instanceof Error ? err.message : err)\n return null\n }\n}\n\nfunction injectStyles(root: Document | ShadowRoot): void {\n const host: ParentNode = root instanceof ShadowRoot ? root : root.head\n if (host.querySelector('#ss-w-styles')) return\n const el = document.createElement('style')\n el.id = 'ss-w-styles'\n el.textContent = WIDGET_CSS\n host.appendChild(el)\n}\n\nexport function StatsWidget(props: StatsWidgetProps): JSX.Element | null {\n const injectedClient = 'client' in props ? props.client : undefined\n const cfg = props.config as Partial<StatsWidgetConfig> | undefined\n const built = useMemo(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl])\n // One logger per mount, keyed on the client identity (not on operatorUserId/anonymousUserId/\n // conversationId -- those change over the widget's lifetime and are pushed in via setIdentity\n // below, not by tearing down and recreating the logger).\n const logger = useMemo(\n () => (built ? built.client.createEventLogger({\n operatorUserId: cfg?.userContext?.operatorUserId,\n anonymousUserId: cfg?.userContext?.anonymousUserId,\n }) : null),\n [built?.client],\n )\n const ui = useMemo(() => normalizeUi((props.config ?? { operatorId: '', publicKey: '' }) as StatsWidgetConfig), [props.config])\n const rootRef = useRef<HTMLDivElement>(null)\n // One-shot launcher attention animation: the FAB nudges then the greeting\n // types in, exactly once per page load. The ref lives here (not in ChatFab,\n // which remounts every time the panel closes) so it never replays; a page\n // refresh remounts the widget and re-arms it.\n const introDoneRef = useRef(false)\n const markIntroDone = useCallback(() => { introDoneRef.current = true }, [])\n const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`\n const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : undefined, convStorageKey)\n // The two hooks are mutually dependent -- useMatchDiscovery needs monitor.pins, useLiveMonitor\n // needs to know whether Today has content -- so the cycle is broken with state rather than a\n // read of discovery's own render. It settles one render later, and unlike a ref it actually\n // re-renders, which is what lets the fallback effect fire when Today empties under the user.\n const [hasToday, setHasToday] = useState(false)\n const monitor = useLiveMonitor({\n getLiveMonitor: (pins) => (built ? built.conversation.getLiveMonitor(pins) : Promise.resolve(null)),\n getMarketOdds: (matchId, dev) => (built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null)),\n storageKey: `ss-w-pins:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`,\n isOpen: controller.state.isOpen,\n hasToday,\n })\n // Stable across renders (deps = [built], itself memoized on the client identity) -- the real\n // call site useMatchDiscovery.test.tsx's interval-churn test protects: a freshly-constructed\n // arrow here would defeat that guarantee even with the hook's own getStatesRef defense.\n const getSchedule = useCallback(\n (localDate: string, utcOffsetMinutes: number) =>\n built ? built.conversation.getSchedule(localDate, utcOffsetMinutes) : Promise.resolve(null),\n [built],\n )\n const getStates = useCallback(\n (matchIds: number[]) => (built ? built.conversation.getStates(matchIds) : Promise.resolve(null)),\n [built],\n )\n const pinnedMatchIds = useMemo(\n () => monitor.pins.filter((p) => p.kind === 'match').map((p) => p.matchId),\n [monitor.pins],\n )\n const discovery = useMatchDiscovery({\n getSchedule,\n getStates,\n operatorId: cfg?.operatorId ?? '',\n isOpen: controller.state.isOpen,\n pinnedMatchIds,\n })\n const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0\n useEffect(() => { setHasToday(todayHasContent) }, [todayHasContent])\n\n const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab })\n const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab })\n\n // The Today dot: the live count rising from zero is the \"something changed you have not seen\"\n // event for this tab. The hook suppresses it while Today is the active tab, exactly as the\n // other three dots are suppressed.\n const markTodayActivity = monitor.markTodayActivity\n const prevLiveCountRef = useRef(0)\n useEffect(() => {\n const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0\n prevLiveCountRef.current = discovery.liveCount\n if (rose) markTodayActivity()\n }, [discovery.liveCount, markTodayActivity])\n const hostEvents = useHostEvents({\n host: props.host,\n operatorId: cfg?.operatorId ?? '',\n currentUser: cfg?.userContext?.operatorUserId || undefined,\n logger,\n isOpen: controller.state.isOpen,\n closePanel: controller.close,\n onOpenMatch: props.config?.onOpenMatch,\n openMatchLabel: ui.openMatch,\n })\n const markAdded = hostEvents.markAdded\n const slip = useMemo<SlipHandlerProps>(\n () => {\n const handler = props.config?.onAddToSlip\n return {\n // I3: the D5 persistent in-slip badge must arm from ANY add path -- a chat-message\n // insight/market card, not just the ones rendered inside the Odds tab itself -- so the\n // wasAdded->markAdded wrap lives here (once), not duplicated per consumer. It awaits the\n // operator's handler itself, so a result that lands after the button's own timeout still\n // arms the badge.\n onAddToSlip: handler && (async (sel) => {\n const result = await handler(sel)\n if (wasAdded(result)) markAdded(sel.matchOddsId)\n return result\n }),\n conversationId: controller.state.conversationId ?? undefined,\n }\n },\n [props.config?.onAddToSlip, controller.state.conversationId, markAdded],\n )\n const onDashboardTap = useMemo(\n () => (built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : undefined),\n [built, logger],\n )\n\n const dismissPopup = usePopupTelemetry(logger, controller.state.isOpen, controller.state.popupText, controller.dismissPopup)\n\n const operatorUserId = cfg?.userContext?.operatorUserId\n const anonymousUserId = cfg?.userContext?.anonymousUserId\n const conversationId = controller.state.conversationId ?? undefined\n useEffect(() => {\n if (!logger) return\n logger.setIdentity({ operatorUserId, anonymousUserId, conversationId })\n }, [logger, operatorUserId, anonymousUserId, conversationId])\n\n useEffect(() => {\n if (!logger) return\n // React StrictMode runs this cleanup and then this setup again on the same memoized logger.\n // Without the resume the second pass keeps a disposed logger and every later event is dropped.\n logger.resume()\n const onHide = (): void => { logger.flushOnHide() }\n const onVisibilityHide = (): void => {\n if (document.visibilityState === 'hidden') logger.flushOnHide()\n }\n window.addEventListener('pagehide', onHide)\n document.addEventListener('visibilitychange', onVisibilityHide)\n return () => {\n window.removeEventListener('pagehide', onHide)\n document.removeEventListener('visibilitychange', onVisibilityHide)\n // dispose() only clears the internal timer -- it does NOT flush queued events, so an\n // unflushed dispose on unmount silently drops whatever is still queued.\n logger.flushOnHide()\n logger.dispose()\n }\n }, [logger])\n\n useEffect(() => {\n if (!built || !ui.injectStyles) return\n const node = rootRef.current?.getRootNode()\n if (node) injectStyles(node as Document | ShadowRoot)\n }, [built, ui.injectStyles])\n\n if (!built) return null\n const attrs = themeAttrs(ui)\n return (\n <EventLogContext.Provider value={logger}>\n <HostEventsProvider value={hostEvents}>\n <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 as CSSProperties}>\n {controller.state.isOpen ? (\n <ChatPanel\n controller={controller}\n ui={ui}\n slip={slip}\n onDashboardTap={onDashboardTap}\n monitor={monitor.enabled ? monitor : undefined}\n discovery={discovery}\n gamesResult={gamesResult}\n leaderboardResult={leaderboardResult}\n loggedIn={!!operatorUserId}\n conversation={built?.conversation ?? null}\n />\n ) : (\n <ChatFab\n label={ui.launcherLabel}\n greeting={ui.greeting}\n popupText={controller.state.popupText}\n logoUrl={ui.logoUrl}\n onOpen={controller.open}\n onDismissPopup={dismissPopup}\n dismissLabel={ui.dismissGreeting}\n introAllowed={!introDoneRef.current}\n onIntroStart={markIntroDone}\n />\n )}\n </div>\n </HostEventsProvider>\n </EventLogContext.Provider>\n )\n}\n\n// Hooks must run unconditionally; when the client failed to build we still need a Conversation-shaped stub for the hook.\nfunction emptyConversation(): Conversation {\n return { send: () => { throw new Error('widget not initialized') } } as unknown as Conversation\n}\n","export function formatBettingKickoff(\n kickoffUtc: string,\n ui: { today: string; tomorrow: string },\n locale: string,\n now: Date = new Date(),\n): { dayLabel: string; time: string } {\n const at = new Date(kickoffUtc)\n const intlLocale = locale === 'tr' ? 'tr-TR' : 'en-GB'\n const time = new Intl.DateTimeFormat(intlLocale, { hour: '2-digit', minute: '2-digit' }).format(at)\n const atLocalDate = new Date(at.getFullYear(), at.getMonth(), at.getDate())\n const nowLocalDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const dayDiff = Math.round((atLocalDate.getTime() - nowLocalDate.getTime()) / 86_400_000)\n const dayLabel =\n dayDiff === 0\n ? ui.today\n : dayDiff === 1\n ? ui.tomorrow\n : new Intl.DateTimeFormat(intlLocale, { weekday: 'short', day: 'numeric', month: 'short' }).format(at)\n return { dayLabel, time }\n}\n","import { formatBettingKickoff } from './kickoff'\n\nexport type Locale = 'en' | 'tr'\n\n// Games-tab copy (u393). Each game task adds its own keys here, in en AND tr.\nexport interface GamesStrings {\n // BCP-47 tag set on the games roots so CSS text-transform uppercases Turkish i → İ.\n lang: 'en' | 'tr'\n dailyChallenge: string\n playNow: string\n dailyGames: string\n newSetAtMidnight: string\n matchdayGames: string\n kickoffAt: (dayTime: string) => string\n statStreak: string\n statToday: string\n statRank: string\n unitDays: string\n unitPts: string\n thisWeek: string\n newToday: string\n resume: string\n done: string\n doneWithScore: (score: number) => string\n locksAt: (dayTime: string) => string\n // Points with the locale's digit grouping (\"1,200\" en / \"1.200\" tr). Used by the hub TODAY stat and doneWithScore.\n formatPts: (n: number) => string\n // Shared by every game screen (loading branch, result card, primary guess button).\n loading: string\n backToGames: string\n alreadyPlayedTitle: string\n guess: string\n // Localised \"Sat 15:00\". A function so each locale owns its Intl locale.\n formatDayTime: (iso: string) => string\n // Display names keyed by gameId — locale-specific replacements for the GAME_TITLES map.\n titles: Record<string, string>\n taglines: Record<string, string>\n mysteryTiger: {\n eyebrow: string\n labels: Record<'position' | 'nationality' | 'age' | 'shirtNumber' | 'apps', string>\n yourGuesses: string\n legendMatch: string\n legendClose: string\n legendHigher: string\n searchLabel: string\n searchPlaceholder: string\n optionsLabel: string\n progress: (used: number, total: number) => string\n solved: string\n failed: string\n detail: (guesses: number) => string\n }\n higherOrLower: {\n eyebrow: (points: number) => string\n streak: string\n whoHadMore: string\n season: (label: string) => string\n higher: string\n lower: string\n vs: string\n lastAnswer: (name: string, value: number) => string\n answersSoFar: (answered: number, total: number) => string\n runOver: string\n perfectRun: string\n runDetail: (correct: number) => string\n }\n guessTheXi: {\n pitchLabel: string\n notThem: string\n whichClub: (left: number) => string\n searchPlaceholder: string\n optionsLabel: string\n solved: string\n failed: string\n detail: (guesses: number) => string\n theAnswer: string\n }\n dailyQuiz: {\n questionOf: (i: number, n: number) => string\n results: string\n next: string\n previous: string\n submit: string\n submitting: string\n correctOf: (correct: number, n: number) => string\n progressAria: (i: number, n: number) => string\n }\n careerPath: {\n eyebrow: string\n mysteryPlayer: string\n lockPosition: string\n lockNationality: string\n firstClub: string\n loan: string\n nextClubHidden: string\n moreClubs: (k: number) => string\n searchLabel: string\n searchPlaceholder: string\n solved: string\n failed: string\n guessesLine: (n: number) => string\n }\n beatTheGrid: {\n eyebrow: string\n filled: (n: number, total: number) => string\n toGo: (n: number) => string\n progressAria: (n: number, total: number) => string\n rowAbbrev: Record<string, string>\n pickCell: (row: string, col: string) => string\n cellFilled: (row: string, col: string, name: string, verdict: string) => string\n correct: string\n wrong: string\n closeSearch: string\n searchLabel: (row: string, col: string) => string\n searchPlaceholder: string\n emptyPool: string\n complete: string\n summary: (correct: number, filled: number) => string\n }\n predictor: {\n eyebrow: (home: string, away: string) => string\n home: string\n away: string\n goalsUp: (team: string) => string\n goalsDown: (team: string) => string\n firstScorer: string\n optional: string\n searchLabel: string\n searchPlaceholder: string\n noScorer: string\n save: string\n saving: string\n closed: string\n saved: string\n savedDetail: (p: { home: string; away: string; h: number; a: number; scorer: string | null }) => string\n fullTime: (h: number, a: number) => string\n exactScore: string\n outcome: string\n firstScorerRow: string\n correct: string\n incorrect: string\n forFun: string\n }\n startingXi: {\n eyebrow: string\n perStarter: (n: number) => string\n picked: (n: number) => string\n toGo: (n: number) => string\n pickSlot: (pos: string) => string\n clearSlot: (pos: string, name: string) => string\n pickFor: (pos: string) => string\n allPicked: string\n searchLabel: string\n submit: string\n submitting: string\n locksAt: (dayTime: string) => string\n locksSoon: string\n pending: (n: number) => string\n gradedLine: (correct: number) => string\n voided: string\n }\n motm: {\n title: string\n eyebrow: string\n voted: string\n yourVote: string\n youVoted: (name: string) => string\n thanks: string\n tapToVote: string\n forFun: string\n }\n statLadder: {\n eyebrow: string\n question: (stat: string) => { pre: string; emph: string; post: string }\n whoSecond: string\n clue: (\n c: { value: number; above: { name: string; diff: number } | null; below: { name: string; diff: number } | null },\n stat: string,\n ) => string\n searchLabel: string\n searchPlaceholder: string\n guess: string\n correct: string\n wrong: (name: string) => string\n }\n}\n\nconst formatPtsEn = (n: number): string => new Intl.NumberFormat('en-GB').format(n)\nconst formatPtsTr = (n: number): string => new Intl.NumberFormat('tr-TR').format(n)\n\nexport interface LocaleStrings {\n launcherLabel: string\n placeholder: string\n closeChat: string\n newConversation: string\n moreOptions: string\n chatDialogLabel: string\n stopResponse: string\n sendMessage: string\n dismissGreeting: string\n somethingWentWrong: string\n retry: string\n showLess: string\n showMore: (n: number) => string\n oddsLabel: string\n liveLabel: string\n yourMarketTag: string\n marketFloorLabel: string\n addToSlip: string\n marketPrices: string\n moreLines: string\n hideLines: string\n oddsMoved: (was: string, now: string, direction: string) => string\n oddsShortened: string\n oddsDrifted: string\n updatedLabel: string\n priceMovement: string\n openingLabel: string\n currentLabel: string\n movementWindow: (hours: number) => string\n notEnoughHistory: string\n singlePricePoint: string\n selectionSuspended: string\n excludedSuspended: (n: number) => string\n chartTimeLabel: (ms: number) => string\n chartAria: (opening: string, current: string, direction: string, hours: number) => string\n inSlip: string\n slipAdded: string\n slipDuplicate: string\n slipPriceChanged: (from: string, to: string) => string\n slipPriceNotAccepted: (from: string, to: string) => string\n slipLoginRequired: string\n slipSuspended: string\n slipFailed: string\n today: string\n tomorrow: string\n bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n tabChat: string\n tabFollowing: string\n tabOdds: string\n tabToday: string\n sectionLive: string\n /** Short scoreboard badge for the fixture row's time column. The long-form phase name\n * for the monitor card is fullTimeLabel. */\n halfTime: string\n staleStates: string\n pinLabel: string\n unpinLabel: string\n matchPinLabel: string\n matchUnpinLabel: string\n matchLimitToast: string\n marketLimitToast: string\n priceHistoryLabel: string\n emptyMatchesTab: string\n emptyOddsTab: string\n asOf: (time: string) => string\n graceNote: string\n suspendedLabel: string\n fullTimeLabel: string\n ownGoalLabel: string\n inSlipLabel: string\n /** Accessible name of a match link. Both names when the card has them, else the short form. */\n openMatch: (home?: string, away?: string) => string\n oddsUnavailable: string\n momentumLabel: string\n liveFactLabel: string\n liveFactAsk: string\n liveFactEarlier: (n: number) => string\n liveFactHideEarlier: string\n accordionRetry: string\n accordionSuspended: string\n tabGames: string\n tabLeaderboard: string\n gamesLoginRequired: string\n back: string\n leaderboardOffBoard: string\n leaderboardThisWeek: string\n leaderboardAllTime: string\n leaderboardEmptyFreshTitle: string\n leaderboardEmptyFreshBody: string\n leaderboardEmptyColdTitle: string\n leaderboardEmptyColdBody: string\n leaderboardEmptyCta: string\n leaderboardLastWeekLabel: string\n leaderboardAllTimeEmpty: string\n gamePlay: string\n gameLocked: string\n gameVoided: string\n games: GamesStrings\n}\n\nconst STRINGS: Record<Locale, LocaleStrings> = {\n en: {\n launcherLabel: 'Chat with SensibleStats',\n placeholder: 'Ask about a team, player or match…',\n closeChat: 'Close chat',\n newConversation: 'New conversation',\n moreOptions: 'More options',\n chatDialogLabel: 'SensibleStats chat',\n stopResponse: 'Stop response',\n sendMessage: 'Send message',\n dismissGreeting: 'Dismiss',\n somethingWentWrong: 'Something went wrong.',\n retry: 'Retry',\n showLess: 'Show less',\n showMore: (n) => `Show ${n} more`,\n oddsLabel: 'Odds',\n liveLabel: 'Live',\n yourMarketTag: 'Your market',\n marketFloorLabel: 'Market price · not a value pick',\n addToSlip: 'Add to slip',\n marketPrices: 'Market prices',\n moreLines: 'More lines',\n hideLines: 'Hide lines',\n oddsMoved: (was, now, direction) => `was ${was}, now ${now}, ${direction}`,\n oddsShortened: 'shortened',\n oddsDrifted: 'drifted',\n updatedLabel: 'updated',\n priceMovement: 'Price movement',\n openingLabel: 'Opening',\n currentLabel: 'Current',\n movementWindow: (hours) => (hours % 24 === 0 ? `Last ${hours / 24}d` : `Last ${hours}h`),\n notEnoughHistory: 'No price history recorded yet for this selection.',\n singlePricePoint: 'Only one price recorded so far for this selection.',\n selectionSuspended: 'This selection is not currently available to bet.',\n excludedSuspended: (n) => `${n} suspended price${n === 1 ? '' : 's'} excluded from this chart.`,\n chartTimeLabel: (ms) =>\n new Intl.DateTimeFormat('en-GB', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n chartAria: (opening, current, direction, hours) => {\n const span = hours % 24 === 0 ? `${hours / 24} day${hours / 24 === 1 ? '' : 's'}` : `${hours} hour${hours === 1 ? '' : 's'}`\n // A flat price has no direction word; appending an empty one leaves \", .\" for a screen reader.\n const drift = direction ? `, ${direction}` : ''\n return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`\n },\n inSlip: 'In slip',\n slipAdded: 'Added to slip',\n slipDuplicate: 'Already in your slip',\n slipPriceChanged: (from, to) => `Added at ${to} (was ${from})`,\n slipPriceNotAccepted: (from, to) => `Price moved to ${to} (was ${from}). Tap to add.`,\n slipLoginRequired: 'Sign in to add to your slip',\n slipSuspended: 'Market suspended',\n slipFailed: \"Couldn't add to slip. Try again.\",\n today: 'Today',\n tomorrow: 'Tomorrow',\n bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, 'en', now),\n tabChat: 'Chat',\n tabFollowing: 'Following',\n tabOdds: 'Odds',\n pinLabel: 'Track odds',\n unpinLabel: 'Stop tracking odds',\n matchPinLabel: 'Track match',\n matchUnpinLabel: 'Stop tracking match',\n matchLimitToast: 'Match limit reached — unpin one first',\n marketLimitToast: 'Odds limit reached — unpin one first',\n priceHistoryLabel: 'Price history',\n emptyMatchesTab: 'No pinned matches yet. Pin a match from the conversation to track it live.',\n emptyOddsTab: 'No odds followed yet. Tap Price history on a price that moved to follow it here.',\n asOf: (time) => `Prices as of ${time}`,\n graceNote: 'Unpins on next open · or in 4 h',\n suspendedLabel: 'Suspended',\n fullTimeLabel: 'Full time',\n ownGoalLabel: 'OG',\n inSlipLabel: 'In slip',\n openMatch: (home, away) => (home && away ? `Open ${home} vs ${away}` : 'Open match'),\n oddsUnavailable: 'Odds unavailable right now',\n momentumLabel: 'Momentum',\n liveFactLabel: 'Live fact',\n liveFactAsk: 'Ask about this',\n liveFactEarlier: (n: number) => `Earlier facts (${n})`,\n liveFactHideEarlier: 'Hide earlier facts',\n accordionRetry: \"Couldn't load odds — tap to retry\",\n accordionSuspended: 'Suspended',\n tabToday: 'Today',\n sectionLive: 'Live',\n halfTime: 'HT',\n staleStates: \"Live scores can't be updated — showing the last known state.\",\n tabGames: 'Games',\n tabLeaderboard: 'Leaderboard',\n gamesLoginRequired: 'Sign in to play and climb the leaderboard',\n back: 'Back',\n leaderboardOffBoard: 'Outside top 50',\n leaderboardThisWeek: 'This week',\n leaderboardAllTime: 'All time',\n leaderboardEmptyFreshTitle: 'New week, blank slate',\n leaderboardEmptyFreshBody: 'No scores yet. The first fan to play a game takes #1.',\n leaderboardEmptyColdTitle: 'Be the first up',\n leaderboardEmptyColdBody: \"Nobody's on the board yet. Play a game and you're #1.\",\n leaderboardEmptyCta: \"Play today's games\",\n leaderboardLastWeekLabel: 'Last week',\n leaderboardAllTimeEmpty: 'The all-time board fills as fans play — nothing here yet.',\n gamePlay: 'Play',\n gameLocked: 'Locked',\n gameVoided: 'Voided',\n games: {\n lang: 'en',\n dailyChallenge: 'Daily challenge',\n playNow: 'Play now',\n dailyGames: 'Daily games',\n newSetAtMidnight: 'New set at midnight',\n matchdayGames: 'Matchday games',\n kickoffAt: (t) => `Kick-off ${t}`,\n statStreak: 'Streak',\n statToday: 'Today',\n statRank: 'Rank',\n unitDays: 'days',\n unitPts: 'pts',\n thisWeek: 'this week',\n newToday: 'New today',\n resume: 'Resume',\n done: 'Done',\n doneWithScore: (s) => `Done · +${formatPtsEn(s)}`,\n locksAt: (t) => `Locks ${t}`,\n formatPts: formatPtsEn,\n loading: 'Loading…',\n backToGames: 'Back to games',\n alreadyPlayedTitle: 'Played today',\n guess: 'Guess',\n formatDayTime: (iso) =>\n new Intl.DateTimeFormat('en-GB', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n titles: {\n 'mystery-tiger': 'Mystery Player',\n 'daily-quiz': 'Daily Quiz',\n 'career-path': 'Career Path',\n 'beat-the-grid': 'Beat the Grid',\n 'guess-the-xi': 'Guess the XI',\n 'higher-or-lower': 'Higher or Lower',\n 'matchday-predictor': 'Matchday Predictor',\n 'starting-xi': 'Starting XI',\n 'stat-ladder': 'Stat Ladder',\n 'fan-motm': 'Fan MOTM',\n },\n taglines: {\n 'mystery-tiger': 'One player. Six guesses.',\n 'higher-or-lower': 'Who had more?',\n 'guess-the-xi': 'Name the team',\n 'daily-quiz': 'Test your club knowledge',\n 'career-path': 'Follow the clubs',\n 'beat-the-grid': 'Fill all 9 cells',\n 'matchday-predictor': 'Call the score',\n 'starting-xi': 'Pick the lineup',\n 'stat-ladder': 'Find the missing rung',\n 'fan-motm': 'Vote at full time',\n },\n mysteryTiger: {\n eyebrow: 'Daily · resets 00:00',\n labels: { position: 'POS', nationality: 'NAT', age: 'AGE', shirtNumber: 'NO.', apps: 'APPS' },\n yourGuesses: 'Your guesses',\n legendMatch: 'Match',\n legendClose: 'Close',\n legendHigher: 'Mystery is higher',\n searchLabel: 'Guess a squad player',\n searchPlaceholder: 'Search by name',\n optionsLabel: 'Squad players',\n progress: (used, total) => `${used} of ${total} guesses used`,\n solved: 'You found them!',\n failed: 'Out of guesses',\n detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n },\n higherOrLower: {\n eyebrow: (p) => `+${p} per correct`,\n streak: 'Streak',\n whoHadMore: 'Who had more',\n season: (l) => `${l} season`,\n higher: 'Higher',\n lower: 'Lower',\n vs: 'VS',\n lastAnswer: (name, value) => `${name} had ${value}`,\n answersSoFar: (a, total) => `${a} of ${total} answered`,\n runOver: 'Run over',\n perfectRun: 'Perfect run!',\n runDetail: (c) => `${c} correct in a row · back tomorrow`,\n },\n guessTheXi: {\n pitchLabel: 'Starting line-up by nationality',\n notThem: 'Not them:',\n whichClub: (left) => `Which club is this? · ${left} left`,\n searchPlaceholder: 'Search clubs',\n optionsLabel: 'Clubs',\n solved: 'Solved!',\n failed: 'Out of guesses',\n detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n theAnswer: 'The answer',\n },\n dailyQuiz: {\n questionOf: (i, n) => `Question ${i} of ${n}`,\n results: 'Results',\n next: 'Next',\n previous: 'Previous',\n submit: 'Submit',\n submitting: 'Submitting…',\n correctOf: (c, n) => `${c} of ${n} correct`,\n progressAria: (i, n) => `Question ${i} of ${n}`,\n },\n careerPath: {\n eyebrow: 'Oldest club first',\n mysteryPlayer: 'Mystery player',\n lockPosition: 'Position',\n lockNationality: 'Nationality',\n firstClub: 'First club',\n loan: 'Loan',\n nextClubHidden: 'Next club — revealed after a wrong guess',\n moreClubs: (k) => `+ ${k} more club${k === 1 ? '' : 's'}`,\n searchLabel: 'Who is it?',\n searchPlaceholder: 'Search any player',\n solved: 'Career traced!',\n failed: 'Out of guesses',\n guessesLine: (n) => `${n} guess${n === 1 ? '' : 'es'} · come back tomorrow`,\n },\n beatTheGrid: {\n eyebrow: 'Fill each cell with a player who fits',\n filled: (n, t) => `${n} of ${t} filled`,\n toGo: (n) => `${n} to go`,\n progressAria: (n, t) => `${n} of ${t} cells filled`,\n rowAbbrev: { Goalkeeper: 'GK', Defender: 'DEF', Midfielder: 'MID', Forward: 'FWD' },\n pickCell: (r, c) => `Pick a ${r.toLowerCase()} with ${c}`,\n cellFilled: (r, c, name, verdict) => `${r} with ${c}: ${name}, ${verdict.toLowerCase()}`,\n correct: 'Correct',\n wrong: 'Wrong',\n closeSearch: 'Close player search',\n searchLabel: (r, c) => `Search player for ${r} × ${c}`,\n searchPlaceholder: 'Search players',\n emptyPool: 'No players available to search yet.',\n complete: 'Grid complete',\n summary: (c, f) => `${c}/${f} correct · come back tomorrow`,\n },\n predictor: {\n eyebrow: (home, away) => `${home} v ${away}`,\n home: 'Home',\n away: 'Away',\n goalsUp: (team) => `${team} goals up`,\n goalsDown: (team) => `${team} goals down`,\n firstScorer: 'First scorer',\n optional: 'Optional',\n searchLabel: 'Search first scorer',\n searchPlaceholder: 'Search squad',\n noScorer: 'No first scorer',\n save: 'Save prediction',\n saving: 'Saving…',\n closed: 'Submissions are now closed',\n saved: 'Prediction saved',\n savedDetail: (p) =>\n `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ${p.scorer} first` : ''} · awaiting result`,\n fullTime: (h, a) => `Full time ${h} – ${a}`,\n exactScore: 'Exact score',\n outcome: 'Result (W/D/L)',\n firstScorerRow: 'First scorer',\n correct: 'Correct',\n incorrect: 'Incorrect',\n forFun: 'For fun — not in the leaderboard',\n },\n startingXi: {\n eyebrow: 'Predict the lineup',\n perStarter: (n) => `+${n} per starter`,\n picked: (n) => `${n} of 11 picked`,\n toGo: (n) => `${n} to go`,\n pickSlot: (pos) => `Pick ${pos}`,\n clearSlot: (pos, name) => `Remove ${name} from ${pos}`,\n pickFor: (pos) => `Pick your ${pos}`,\n allPicked: 'All 11 picked — tap a player on the pitch to swap',\n searchLabel: 'Search squad',\n submit: 'Lock in my XI',\n submitting: 'Submitting…',\n locksAt: (t) => `Locks ${t}, about an hour before kick-off`,\n locksSoon: 'Locks about an hour before kick-off',\n pending: (n) => `Prediction locked in (${n} players) — awaiting result`,\n gradedLine: (c) => `${c} of 11 correct`,\n voided: 'This game has been voided',\n },\n motm: {\n title: 'Man of the Match',\n eyebrow: 'Fan vote',\n voted: 'Voted',\n yourVote: 'Your vote',\n youVoted: (name) => `You voted ${name}`,\n thanks: \"Thanks — results aren't shown for this vote\",\n tapToVote: 'Tap a player to vote',\n forFun: 'For fun — unranked community vote',\n },\n statLadder: {\n eyebrow: 'Last match',\n question: (stat) => ({ pre: 'Who made the ', emph: '2nd-most', post: ` ${stat.toLowerCase()}?` }),\n whoSecond: \"Who's 2nd?\",\n clue: (c, stat) => {\n const parts: string[] = []\n if (c.above) parts.push(c.above.diff === 0 ? `the same as ${c.above.name}` : `${c.above.diff} fewer than ${c.above.name}`)\n if (c.below) parts.push(c.below.diff === 0 ? `the same as ${c.below.name}` : `${c.below.diff} more than ${c.below.name}`)\n return `They made ${c.value} ${stat.toLowerCase()}${parts.length ? `, ${parts.join(' and ')}` : ''}.`\n },\n searchLabel: 'Guess the 2nd player',\n searchPlaceholder: 'Search squad',\n guess: 'Guess',\n correct: 'Correct!',\n wrong: (name) => `Wrong — it was ${name}`,\n },\n },\n },\n tr: {\n launcherLabel: 'SensibleStats ile sohbet et',\n placeholder: 'Bir takım, oyuncu veya maç hakkında sor…',\n closeChat: 'Sohbeti kapat',\n newConversation: 'Yeni sohbet',\n moreOptions: 'Diğer seçenekler',\n chatDialogLabel: 'SensibleStats sohbet',\n stopResponse: 'Yanıtı durdur',\n sendMessage: 'Mesaj gönder',\n dismissGreeting: 'Kapat',\n somethingWentWrong: 'Bir şeyler ters gitti.',\n retry: 'Tekrar dene',\n showLess: 'Daha az göster',\n showMore: (n) => `${n} tane daha göster`,\n oddsLabel: 'Oran',\n liveLabel: 'Canlı',\n yourMarketTag: 'İlgilendiğin bahis',\n marketFloorLabel: 'Piyasa oranı · değer bahsi değil',\n addToSlip: 'Kupona ekle',\n marketPrices: 'Piyasa fiyatları',\n moreLines: 'Diğer çizgiler',\n hideLines: 'Çizgileri gizle',\n oddsMoved: (was, now, direction) => `önce ${was}, şimdi ${now}, ${direction}`,\n oddsShortened: 'düştü',\n oddsDrifted: 'yükseldi',\n updatedLabel: 'güncellendi',\n priceMovement: 'Oran hareketi',\n openingLabel: 'Açılış',\n currentLabel: 'Güncel',\n movementWindow: (hours) => (hours % 24 === 0 ? `Son ${hours / 24} gün` : `Son ${hours} saat`),\n notEnoughHistory: 'Bu seçim için henüz oran geçmişi kaydedilmedi.',\n singlePricePoint: 'Bu seçim için şimdiye kadar yalnızca bir fiyat kaydedildi.',\n selectionSuspended: 'Bu seçim şu anda bahse kapalı.',\n excludedSuspended: (n) => `${n} askıya alınmış fiyat bu grafikten hariç tutuldu.`,\n chartTimeLabel: (ms) =>\n new Intl.DateTimeFormat('tr-TR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n chartAria: (opening, current, direction, hours) => {\n const span = hours % 24 === 0 ? `${hours / 24} gün` : `${hours} saat`\n const drift = direction ? `, ${direction}` : ''\n return `Son ${span} içindeki oran hareketi: ${opening} ile açıldı, şu anda ${current}${drift}.`\n },\n inSlip: 'Kuponda',\n slipAdded: 'Kupona eklendi',\n slipDuplicate: 'Bu seçim kuponunuzda zaten var',\n slipPriceChanged: (from, to) => `${to} oranıyla eklendi (önceki ${from})`,\n slipPriceNotAccepted: (from, to) => `Oran ${to} oldu (önceki ${from}). Eklemek için dokunun.`,\n slipLoginRequired: 'Kupona eklemek için giriş yapın',\n slipSuspended: 'Bu market askıya alındı',\n slipFailed: 'Kupona eklenemedi. Tekrar deneyin.',\n today: 'Bugün',\n tomorrow: 'Yarın',\n bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, 'tr', now),\n tabChat: 'Sohbet',\n tabFollowing: 'Takip',\n tabOdds: 'Oranlar',\n pinLabel: 'Oranı takip et',\n unpinLabel: 'Oran takibini bırak',\n matchPinLabel: 'Maçı takip et',\n matchUnpinLabel: 'Maç takibini bırak',\n matchLimitToast: 'Maç limiti dolu — önce bir maçı kaldır',\n marketLimitToast: 'Oran limiti dolu — önce birini kaldır',\n priceHistoryLabel: 'Oran geçmişi',\n emptyMatchesTab: 'Henüz sabitlenmiş maç yok. Canlı takip için sohbetteki bir maçı sabitle.',\n emptyOddsTab: 'Henüz takip edilen oran yok. Değişen bir oranda Oran geçmişi düğmesine dokunarak burada takip et.',\n asOf: (time) => `Fiyatlar ${time} itibarıyla`,\n graceNote: 'Bir sonraki açılışta kaldırılır · en geç 4 saat',\n suspendedLabel: 'Askıda',\n fullTimeLabel: 'Maç sonu',\n ownGoalLabel: 'KK',\n inSlipLabel: 'Kuponda',\n openMatch: (home, away) => (home && away ? `${home} - ${away} maçını aç` : 'Maçı aç'),\n oddsUnavailable: 'Oranlar şu anda kullanılamıyor',\n momentumLabel: 'Momentum',\n liveFactLabel: 'Canlı bilgi',\n liveFactAsk: 'Bunu sor',\n liveFactEarlier: (n: number) => `Önceki bilgiler (${n})`,\n liveFactHideEarlier: 'Önceki bilgileri gizle',\n accordionRetry: 'Oranlar yüklenemedi — yeniden dene',\n accordionSuspended: 'Askıda',\n tabToday: 'Bugün',\n sectionLive: 'Canlı',\n halfTime: 'İY',\n staleStates: 'Canlı skorlar güncellenemiyor — son bilinen durum gösteriliyor.',\n tabGames: 'Oyunlar',\n tabLeaderboard: 'Lider Tablosu',\n gamesLoginRequired: 'Oynamak ve lider tablosuna girmek için giriş yapın',\n back: 'Geri',\n leaderboardOffBoard: 'İlk 50 dışında',\n leaderboardThisWeek: 'Bu hafta',\n leaderboardAllTime: 'Tüm zamanlar',\n leaderboardEmptyFreshTitle: 'Yeni hafta, temiz sayfa',\n leaderboardEmptyFreshBody: 'Henüz skor yok. Oynayan ilk taraftar 1. sıraya geçer.',\n leaderboardEmptyColdTitle: 'İlk sen ol',\n leaderboardEmptyColdBody: 'Panoda henüz kimse yok. Bir oyun oyna, 1. sıra senin.',\n leaderboardEmptyCta: 'Bugünün oyunlarını oyna',\n leaderboardLastWeekLabel: 'Geçen hafta',\n leaderboardAllTimeEmpty: 'Tüm zamanlar panosu taraftarlar oynadıkça dolar — henüz bir şey yok.',\n gamePlay: 'Oyna',\n gameLocked: 'Kilitli',\n gameVoided: 'İptal edildi',\n games: {\n lang: 'tr',\n dailyChallenge: 'Günün meydan okuması',\n playNow: 'Hemen oyna',\n dailyGames: 'Günlük oyunlar',\n newSetAtMidnight: 'Yeni set gece yarısı',\n matchdayGames: 'Maç günü oyunları',\n kickoffAt: (t) => `Başlama ${t}`,\n statStreak: 'Seri',\n statToday: 'Bugün',\n statRank: 'Sıra',\n unitDays: 'gün',\n unitPts: 'puan',\n thisWeek: 'bu hafta',\n newToday: 'Bugün yeni',\n resume: 'Devam et',\n done: 'Tamamlandı',\n doneWithScore: (s) => `Tamamlandı · +${formatPtsTr(s)}`,\n locksAt: (t) => `Kilit ${t}`,\n formatPts: formatPtsTr,\n loading: 'Yükleniyor…',\n backToGames: 'Oyunlara dön',\n alreadyPlayedTitle: 'Bugün oynadın',\n guess: 'Tahmin',\n formatDayTime: (iso) =>\n new Intl.DateTimeFormat('tr-TR', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n titles: {\n 'mystery-tiger': 'Gizemli Oyuncu',\n 'daily-quiz': 'Günün Testi',\n 'career-path': 'Kariyer Yolu',\n 'beat-the-grid': 'Tabloyu Tamamla',\n 'guess-the-xi': 'Bu 11 Kimin?',\n 'higher-or-lower': 'Fazla mı, Az mı?',\n 'matchday-predictor': 'Skor Tahmini',\n 'starting-xi': 'İlk 11 Tahmini',\n 'stat-ladder': 'İstatistik Merdiveni',\n 'fan-motm': 'Maçın Oyuncusu',\n },\n taglines: {\n 'mystery-tiger': 'Bir oyuncu. Altı tahmin.',\n 'higher-or-lower': 'Kimin daha fazlası var?',\n 'guess-the-xi': 'Takımı bil',\n 'daily-quiz': 'Kulüp bilgini sına',\n 'career-path': 'Kulüpleri takip et',\n 'beat-the-grid': '9 hücreyi doldur',\n 'matchday-predictor': 'Skoru tahmin et',\n 'starting-xi': 'İlk 11’i seç',\n 'stat-ladder': 'Eksik basamağı bul',\n 'fan-motm': 'Maç sonunda oy ver',\n },\n mysteryTiger: {\n eyebrow: 'Günlük · 00:00’da yenilenir',\n labels: { position: 'POZ', nationality: 'UYR', age: 'YAŞ', shirtNumber: 'NO.', apps: 'MAÇ' },\n yourGuesses: 'Tahminlerin',\n legendMatch: 'Eşleşme',\n legendClose: 'Yakın',\n legendHigher: 'Gizli oyuncu daha yüksek',\n searchLabel: 'Kadrodan bir oyuncu tahmin et',\n searchPlaceholder: 'İsimle ara',\n optionsLabel: 'Kadro oyuncuları',\n progress: (used, total) => `${total} tahminden ${used} kullanıldı`,\n solved: 'Buldun!',\n failed: 'Tahmin hakkın bitti',\n detail: (n) => `${n} tahmin · yarın yine gel`,\n },\n higherOrLower: {\n eyebrow: (p) => `Doğru başına +${p}`,\n streak: 'Seri',\n whoHadMore: 'Kimin daha fazlası var',\n season: (l) => `${l} sezonu`,\n higher: 'Daha fazla',\n lower: 'Daha az',\n vs: 'VS',\n lastAnswer: (name, value) => `${name}: ${value}`,\n answersSoFar: (a, total) => `${total} eşleşmeden ${a} yanıtlandı`,\n runOver: 'Seri bitti',\n perfectRun: 'Kusursuz seri!',\n runDetail: (c) => `Üst üste ${c} doğru · yarın yine gel`,\n },\n guessTheXi: {\n pitchLabel: 'Uyruklara göre ilk 11',\n notThem: 'Bunlar değil:',\n whichClub: (left) => `Bu hangi kulüp? · ${left} hak kaldı`,\n searchPlaceholder: 'Kulüp ara',\n optionsLabel: 'Kulüpler',\n solved: 'Bildin!',\n failed: 'Tahmin hakkın bitti',\n detail: (n) => `${n} tahmin · yarın yine gel`,\n theAnswer: 'Doğru cevap',\n },\n dailyQuiz: {\n questionOf: (i, n) => `Soru ${i} / ${n}`,\n results: 'Sonuçlar',\n next: 'İleri',\n previous: 'Önceki',\n submit: 'Gönder',\n submitting: 'Gönderiliyor…',\n correctOf: (c, n) => `${n} soruda ${c} doğru`,\n progressAria: (i, n) => `Soru ${i} / ${n}`,\n },\n careerPath: {\n eyebrow: 'En eski kulüp önce',\n mysteryPlayer: 'Gizemli oyuncu',\n lockPosition: 'Mevki',\n lockNationality: 'Uyruk',\n firstClub: 'İlk kulüp',\n loan: 'Kiralık',\n nextClubHidden: 'Sıradaki kulüp — yanlış tahminden sonra açılır',\n moreClubs: (k) => `+ ${k} kulüp daha`,\n searchLabel: 'Bu kim?',\n searchPlaceholder: 'Herhangi bir oyuncu ara',\n solved: 'Kariyer çözüldü!',\n failed: 'Tahmin hakkın bitti',\n guessesLine: (n) => `${n} tahmin · yarın tekrar gel`,\n },\n beatTheGrid: {\n eyebrow: 'Her hücreye uyan bir oyuncu yerleştir',\n filled: (n, t) => `${t} hücreden ${n} dolu`,\n toGo: (n) => `${n} kaldı`,\n progressAria: (n, t) => `${t} hücreden ${n} dolu`,\n rowAbbrev: { Goalkeeper: 'KL', Defender: 'DEF', Midfielder: 'OS', Forward: 'FV' },\n pickCell: (r, c) => `${r} × ${c} için oyuncu seç`,\n cellFilled: (r, c, name, verdict) => `${r} × ${c}: ${name}, ${verdict.toLocaleLowerCase('tr')}`,\n correct: 'Doğru',\n wrong: 'Yanlış',\n closeSearch: 'Oyuncu aramayı kapat',\n searchLabel: (r, c) => `${r} × ${c} için oyuncu ara`,\n searchPlaceholder: 'Oyuncu ara',\n emptyPool: 'Henüz aranacak oyuncu yok.',\n complete: 'Tablo tamamlandı',\n summary: (c, f) => `${f} hücrede ${c} doğru · yarın tekrar gel`,\n },\n predictor: {\n eyebrow: (home, away) => `${home} - ${away}`,\n home: 'Ev sahibi',\n away: 'Deplasman',\n goalsUp: (team) => `${team} golünü artır`,\n goalsDown: (team) => `${team} golünü azalt`,\n firstScorer: 'İlk golü atan',\n optional: 'İsteğe bağlı',\n searchLabel: 'İlk golcüyü ara',\n searchPlaceholder: 'Kadroda ara',\n noScorer: 'İlk gol yok',\n save: 'Tahmini kaydet',\n saving: 'Kaydediliyor…',\n closed: 'Tahminler kapandı',\n saved: 'Tahmin kaydedildi',\n savedDetail: (p) =>\n `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ilk gol ${p.scorer}` : ''} · sonuç bekleniyor`,\n fullTime: (h, a) => `Maç sonu ${h} – ${a}`,\n exactScore: 'Tam skor',\n outcome: 'Sonuç (G/B/M)',\n firstScorerRow: 'İlk golü atan',\n correct: 'Doğru',\n incorrect: 'Yanlış',\n forFun: 'Eğlence için — sıralamaya girmez',\n },\n startingXi: {\n eyebrow: 'Kadroyu tahmin et',\n perStarter: (n) => `İlk 11 oyuncu başına +${n}`,\n picked: (n) => `11 oyuncudan ${n} seçildi`,\n toGo: (n) => `${n} kaldı`,\n pickSlot: (pos) => `${pos} seç`,\n clearSlot: (pos, name) => `${name} oyuncusunu ${pos} mevkiinden çıkar`,\n pickFor: (pos) => `${pos} için oyuncu seç`,\n allPicked: '11 oyuncu seçildi — değiştirmek için sahadaki oyuncuya dokun',\n searchLabel: 'Kadroda ara',\n submit: 'İlk 11’imi kilitle',\n submitting: 'Gönderiliyor…',\n locksAt: (t) => `${t} kilitlenir, başlamadan yaklaşık bir saat önce`,\n locksSoon: 'Başlamadan yaklaşık bir saat önce kilitlenir',\n pending: (n) => `Tahmin kilitlendi (${n} oyuncu) — sonuç bekleniyor`,\n gradedLine: (c) => `11 oyuncudan ${c} doğru`,\n voided: 'Bu oyun iptal edildi',\n },\n motm: {\n title: 'Maçın Oyuncusu',\n eyebrow: 'Taraftar oylaması',\n voted: 'Oy verildi',\n yourVote: 'Oy verdiğin',\n youVoted: (name) => `${name} için oy verdin`,\n thanks: 'Teşekkürler — bu oylamanın sonuçları gösterilmiyor',\n tapToVote: 'Oy vermek için bir oyuncuya dokun',\n forFun: 'Eğlence için — sıralamaya girmeyen taraftar oylaması',\n },\n statLadder: {\n eyebrow: 'Son maç',\n question: (stat) => ({ pre: `${stat.toLocaleLowerCase('tr')} sıralamasında `, emph: '2. sırada', post: ' kim var?' }),\n whoSecond: '2. kim?',\n clue: (c, stat) => {\n const parts: string[] = []\n if (c.above) parts.push(c.above.diff === 0 ? `${c.above.name} ile aynı` : `${c.above.name} oyuncusundan ${c.above.diff} eksik`)\n if (c.below) parts.push(c.below.diff === 0 ? `${c.below.name} ile aynı` : `${c.below.name} oyuncusundan ${c.below.diff} fazla`)\n return `${c.value} ${stat.toLocaleLowerCase('tr')}${parts.length ? `: ${parts.join(' ve ')}` : ''}.`\n },\n searchLabel: '2. oyuncuyu tahmin et',\n searchPlaceholder: 'Kadroda ara',\n guess: 'Tahmin et',\n correct: 'Doğru!',\n wrong: (name) => `Yanlış — doğru cevap ${name}`,\n },\n },\n },\n}\n\nexport function resolveLocaleStrings(locale?: string): LocaleStrings {\n return STRINGS[locale as Locale] ?? STRINGS.en\n}\n\n/** True unless the locale's language is one the widget supports other than English; a missing\n * or unsupported locale counts as English. Matches on the language subtag, so \"tr-TR\" is Turkish. */\nexport function isEnglishLocale(locale?: string): boolean {\n const lang = (locale ?? '').trim().toLowerCase().split(/[-_]/)[0] ?? ''\n return lang === 'en' || !Object.prototype.hasOwnProperty.call(STRINGS, lang)\n}\n","import type { AddToSlipHandler, StatsWidgetClientOptions, UserContext } from '@sensiblestats/widget-sdk'\nimport { isEnglishLocale, resolveLocaleStrings } from './i18n'\nimport type { GamesStrings } from './i18n'\n\nexport interface StatsWidgetConfig {\n operatorId: string\n publicKey: string\n baseUrl?: string\n userContext?: UserContext\n theme?: 'light' | 'dark' | 'auto'\n accent?: string\n position?: 'left' | 'right'\n offset?: { x?: number; y?: number }\n radius?: number\n /** BCP-47-ish locale code for the widget's own chrome text (e.g. \"en\", \"tr\"). Defaults to \"en\". */\n locale?: string\n launcherLabel?: string\n greeting?: string\n /** Message auto-sent once on load (e.g. \"hello\"); its response shows as the launcher popup. */\n greetingMessage?: string\n placeholder?: string\n starters?: string[]\n injectStyles?: boolean\n /** Called when the user adds an insight's selection to the operator's slip. */\n onAddToSlip?: AddToSlipHandler\n /** Called when the user taps a match in the widget; take them to your match page. Team names\n * become links only when this is set. A thrown error or a rejected promise is ignored. */\n onOpenMatch?: (match: { matchId: number }) => void | Promise<void>\n\n // — Branding —\n /** Operator logo; replaces the SS mark in the header and the FAB launcher. */\n logoUrl?: string\n /** Header title text. Default \"SensibleStats\". */\n headerTitle?: string\n /** CTA color → --ss-w-cta. */\n cta?: string\n /** Panel/surface color → --ss-w-panel. Pair with `ink`. */\n surface?: string\n /** Primary text color → --ss-w-ink. Pair with `surface`. */\n ink?: string\n /** Icon used for the pin/save toggle on matches and odds. Default \"pin\". */\n pinIcon?: 'pin' | 'star' | 'bookmark'\n}\n\ntype UiKeys =\n | 'theme' | 'accent' | 'position' | 'offset' | 'radius' | 'locale'\n | 'launcherLabel' | 'greeting' | 'greetingMessage' | 'placeholder' | 'starters' | 'injectStyles'\n | 'logoUrl' | 'headerTitle' | 'cta' | 'surface' | 'ink' | 'pinIcon'\n\nexport interface UiConfig {\n theme: 'light' | 'dark' | 'auto'\n accent?: string\n position: 'left' | 'right'\n offset: { x: number; y: number }\n radius: number\n launcherLabel: string\n greeting?: string\n greetingMessage?: string\n placeholder: string\n starters: string[]\n injectStyles: boolean\n logoUrl?: string\n headerTitle?: string\n /** The server localizes betting labels for non-English widgets (\"2.5 Üst\"), so only an English\n * widget can report the label it shows as the raw slip selection. */\n rawBettingLabels: boolean\n cta?: string\n surface?: string\n ink?: string\n pinIcon: 'pin' | 'star' | 'bookmark'\n closeChat: string\n newConversation: string\n moreOptions: string\n chatDialogLabel: string\n stopResponse: string\n sendMessage: string\n dismissGreeting: string\n somethingWentWrong: string\n retry: string\n showLess: string\n showMore: (n: number) => string\n oddsLabel: string\n liveLabel: string\n yourMarketTag: string\n marketFloorLabel: string\n marketPrices: string\n moreLines: string\n hideLines: string\n oddsMoved: (was: string, now: string, direction: string) => string\n oddsShortened: string\n oddsDrifted: string\n updatedLabel: string\n priceMovement: string\n openingLabel: string\n currentLabel: string\n movementWindow: (hours: number) => string\n notEnoughHistory: string\n singlePricePoint: string\n selectionSuspended: string\n excludedSuspended: (n: number) => string\n chartTimeLabel: (ms: number) => string\n chartAria: (opening: string, current: string, direction: string, hours: number) => string\n addToSlip: string\n inSlip: string\n slipAdded: string\n slipDuplicate: string\n slipPriceChanged: (from: string, to: string) => string\n slipPriceNotAccepted: (from: string, to: string) => string\n slipLoginRequired: string\n slipSuspended: string\n slipFailed: string\n today: string\n tomorrow: string\n bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n tabChat: string\n tabFollowing: string\n tabOdds: string\n tabToday: string\n sectionLive: string\n halfTime: string\n staleStates: string\n pinLabel: string\n unpinLabel: string\n matchPinLabel: string\n matchUnpinLabel: string\n matchLimitToast: string\n marketLimitToast: string\n priceHistoryLabel: string\n emptyMatchesTab: string\n emptyOddsTab: string\n asOf: (time: string) => string\n graceNote: string\n suspendedLabel: string\n fullTimeLabel: string\n ownGoalLabel: string\n inSlipLabel: string\n openMatch: (home?: string, away?: string) => string\n oddsUnavailable: string\n momentumLabel: string\n liveFactLabel: string\n liveFactAsk: string\n liveFactEarlier: (n: number) => string\n liveFactHideEarlier: string\n accordionRetry: string\n accordionSuspended: string\n tabGames: string\n tabLeaderboard: string\n gamesLoginRequired: string\n back: string\n leaderboardOffBoard: string\n leaderboardThisWeek: string\n leaderboardAllTime: string\n leaderboardEmptyFreshTitle: string\n leaderboardEmptyFreshBody: string\n leaderboardEmptyColdTitle: string\n leaderboardEmptyColdBody: string\n leaderboardEmptyCta: string\n leaderboardLastWeekLabel: string\n leaderboardAllTimeEmpty: string\n gamePlay: string\n gameLocked: string\n gameVoided: string\n games: GamesStrings\n}\n\nexport function normalizeUi(cfg: Pick<StatsWidgetConfig, UiKeys>): UiConfig {\n const strings = resolveLocaleStrings(cfg.locale)\n return {\n theme: cfg.theme ?? 'auto',\n accent: cfg.accent,\n logoUrl: cfg.logoUrl,\n headerTitle: cfg.headerTitle,\n rawBettingLabels: isEnglishLocale(cfg.locale),\n cta: cfg.cta,\n surface: cfg.surface,\n ink: cfg.ink,\n pinIcon: cfg.pinIcon ?? 'pin',\n position: cfg.position ?? 'right',\n offset: { x: cfg.offset?.x ?? 20, y: cfg.offset?.y ?? 20 },\n radius: cfg.radius ?? 16,\n launcherLabel: cfg.launcherLabel ?? strings.launcherLabel,\n greeting: cfg.greeting,\n greetingMessage: cfg.greetingMessage,\n placeholder: cfg.placeholder ?? strings.placeholder,\n starters: cfg.starters ?? [],\n injectStyles: cfg.injectStyles ?? true,\n closeChat: strings.closeChat,\n newConversation: strings.newConversation,\n moreOptions: strings.moreOptions,\n chatDialogLabel: strings.chatDialogLabel,\n stopResponse: strings.stopResponse,\n sendMessage: strings.sendMessage,\n dismissGreeting: strings.dismissGreeting,\n somethingWentWrong: strings.somethingWentWrong,\n retry: strings.retry,\n showLess: strings.showLess,\n showMore: strings.showMore,\n oddsLabel: strings.oddsLabel,\n liveLabel: strings.liveLabel,\n yourMarketTag: strings.yourMarketTag,\n marketFloorLabel: strings.marketFloorLabel,\n marketPrices: strings.marketPrices,\n moreLines: strings.moreLines,\n hideLines: strings.hideLines,\n oddsMoved: strings.oddsMoved,\n oddsShortened: strings.oddsShortened,\n oddsDrifted: strings.oddsDrifted,\n updatedLabel: strings.updatedLabel,\n priceMovement: strings.priceMovement,\n openingLabel: strings.openingLabel,\n currentLabel: strings.currentLabel,\n movementWindow: strings.movementWindow,\n notEnoughHistory: strings.notEnoughHistory,\n singlePricePoint: strings.singlePricePoint,\n selectionSuspended: strings.selectionSuspended,\n excludedSuspended: strings.excludedSuspended,\n chartTimeLabel: strings.chartTimeLabel,\n chartAria: strings.chartAria,\n addToSlip: strings.addToSlip,\n inSlip: strings.inSlip,\n slipAdded: strings.slipAdded,\n slipDuplicate: strings.slipDuplicate,\n slipPriceChanged: strings.slipPriceChanged,\n slipPriceNotAccepted: strings.slipPriceNotAccepted,\n slipLoginRequired: strings.slipLoginRequired,\n slipSuspended: strings.slipSuspended,\n slipFailed: strings.slipFailed,\n today: strings.today,\n tomorrow: strings.tomorrow,\n bettingKickoff: strings.bettingKickoff,\n tabChat: strings.tabChat,\n tabFollowing: strings.tabFollowing,\n tabOdds: strings.tabOdds,\n tabToday: strings.tabToday,\n sectionLive: strings.sectionLive,\n halfTime: strings.halfTime,\n staleStates: strings.staleStates,\n pinLabel: strings.pinLabel,\n unpinLabel: strings.unpinLabel,\n matchPinLabel: strings.matchPinLabel,\n matchUnpinLabel: strings.matchUnpinLabel,\n matchLimitToast: strings.matchLimitToast,\n marketLimitToast: strings.marketLimitToast,\n priceHistoryLabel: strings.priceHistoryLabel,\n emptyMatchesTab: strings.emptyMatchesTab,\n emptyOddsTab: strings.emptyOddsTab,\n asOf: strings.asOf,\n graceNote: strings.graceNote,\n suspendedLabel: strings.suspendedLabel,\n fullTimeLabel: strings.fullTimeLabel,\n ownGoalLabel: strings.ownGoalLabel,\n inSlipLabel: strings.inSlipLabel,\n openMatch: strings.openMatch,\n oddsUnavailable: strings.oddsUnavailable,\n momentumLabel: strings.momentumLabel,\n liveFactLabel: strings.liveFactLabel,\n liveFactAsk: strings.liveFactAsk,\n liveFactEarlier: strings.liveFactEarlier,\n liveFactHideEarlier: strings.liveFactHideEarlier,\n accordionRetry: strings.accordionRetry,\n accordionSuspended: strings.accordionSuspended,\n tabGames: strings.tabGames,\n tabLeaderboard: strings.tabLeaderboard,\n gamesLoginRequired: strings.gamesLoginRequired,\n back: strings.back,\n leaderboardOffBoard: strings.leaderboardOffBoard,\n leaderboardThisWeek: strings.leaderboardThisWeek,\n leaderboardAllTime: strings.leaderboardAllTime,\n leaderboardEmptyFreshTitle: strings.leaderboardEmptyFreshTitle,\n leaderboardEmptyFreshBody: strings.leaderboardEmptyFreshBody,\n leaderboardEmptyColdTitle: strings.leaderboardEmptyColdTitle,\n leaderboardEmptyColdBody: strings.leaderboardEmptyColdBody,\n leaderboardEmptyCta: strings.leaderboardEmptyCta,\n leaderboardLastWeekLabel: strings.leaderboardLastWeekLabel,\n leaderboardAllTimeEmpty: strings.leaderboardAllTimeEmpty,\n gamePlay: strings.gamePlay,\n gameLocked: strings.gameLocked,\n gameVoided: strings.gameVoided,\n games: strings.games,\n }\n}\n\nexport function toClientOptions(cfg: StatsWidgetConfig): StatsWidgetClientOptions {\n const opts: StatsWidgetClientOptions = { operatorId: cfg.operatorId, publicKey: cfg.publicKey }\n if (cfg.baseUrl !== undefined) opts.baseUrl = cfg.baseUrl\n return opts\n}\n\nexport function toUserContext(cfg: StatsWidgetConfig): UserContext | undefined {\n return cfg.userContext && Object.keys(cfg.userContext).length > 0 ? cfg.userContext : undefined\n}\n","import type { AddToSlipHandler, AddToSlipResult, LiveMonitorStatPrice, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from './config'\n\nexport const ADD_TO_SLIP_TIMEOUT_MS = 10_000\n\nexport interface SlipToast { kind: 'success' | 'error'; text: string }\n\nexport interface SlipHandlerProps {\n onAddToSlip?: AddToSlipHandler\n conversationId?: string\n}\n\nexport interface SlipPickFields { matchId?: number; selection?: string; line?: string; odds?: number }\n\nexport const MAX_SELECTION = 64\nexport const MAX_LINE = 32\nexport const MAX_ODDS = 10_000\n\n// The gateway rejects the whole batch when one event breaks a length or range rule, so a value\n// that would fail validation is dropped from the pick rather than risking every queued event.\nexport function slipPickFields(selection: SlipSelection, label?: string, line?: string): SlipPickFields {\n const fields: SlipPickFields = {}\n if (Number.isSafeInteger(selection.matchId) && selection.matchId > 0) fields.matchId = selection.matchId\n if (label && label.trim() && label.length <= MAX_SELECTION) fields.selection = label\n if (line && line.trim() && line.length <= MAX_LINE) fields.line = line\n const odds = selection.oddsDecimal\n if (Number.isFinite(odds) && odds > 1 && odds <= MAX_ODDS) fields.odds = odds\n return fields\n}\n\n// Shared by every market-chip renderer (stat rows, live facts): a chip only becomes a slip\n// selection when it carries a real, addable price -- otherwise there's nothing to submit.\nexport function chipSelection(market: LiveMonitorStatPrice | null | undefined, matchId: number, conversationId?: string): SlipSelection | null {\n if (!market || !market.addToSlipEnabled || typeof market.matchOddsId !== 'number' || typeof market.price !== 'number') return null\n const selection: SlipSelection = { matchOddsId: market.matchOddsId, matchId, oddsDecimal: market.price }\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n\nexport function wasAdded(result: AddToSlipResult | void): boolean {\n if (!result) return true\n if (result.status === 'price_changed') return result.accepted\n return result.status === 'added'\n}\n\nexport function isTerminal(result: AddToSlipResult | void): boolean {\n if (!result) return true\n if (result.status === 'price_changed') return result.accepted\n return result.status === 'added' || result.status === 'duplicate'\n}\n\n// slip_result's `outcome`: 'added' on success (including the assumed-success void/duplicate/\n// accepted-price-change cases), else the specific reject reason string -- so a downstream\n// consumer can tell \"the user added it\" from \"why it was refused\" without re-deriving toast text.\nexport function slipOutcome(result: AddToSlipResult | void): string {\n if (!result) return 'added'\n switch (result.status) {\n case 'added':\n case 'duplicate':\n return result.status\n case 'price_changed':\n return result.accepted ? 'added' : 'price_changed'\n case 'rejected':\n return result.reason\n }\n}\n\nexport function resultToToast(result: AddToSlipResult | void, shownOdds: string, ui: UiConfig): SlipToast {\n if (!result) return { kind: 'success', text: ui.slipAdded }\n switch (result.status) {\n case 'added':\n return { kind: 'success', text: ui.slipAdded }\n case 'duplicate':\n return { kind: 'success', text: ui.slipDuplicate }\n case 'price_changed':\n return result.accepted\n ? { kind: 'success', text: ui.slipPriceChanged(shownOdds, result.newOddsDecimal.toFixed(2)) }\n : { kind: 'error', text: ui.slipPriceNotAccepted(shownOdds, result.newOddsDecimal.toFixed(2)) }\n case 'rejected':\n if (result.reason === 'login_required') return { kind: 'error', text: ui.slipLoginRequired }\n if (result.reason === 'suspended') return { kind: 'error', text: ui.slipSuspended }\n return { kind: 'error', text: result.message ?? ui.slipFailed }\n }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\nimport { FULLSCREEN_QUERY } from './components/ChatPanel'\nimport type { StatsWidgetConfig, UiConfig } from './config'\nimport { attachHost, type HostSink, type WidgetHost } from './host'\nimport type { MatchLinkValue } from './matchLinkContext'\nimport { createMatchViews } from './matchViews'\nimport { BET_REPORT_MAX, createSlipLedger, toSlipEvent } from './slipLedger'\nimport type { SlipAdd, SlipState } from './slipStateContext'\n\nexport interface HostEventsOptions {\n host: WidgetHost | undefined\n operatorId: string\n /** operatorUserId of the visitor; undefined when anonymous. */\n currentUser: string | undefined\n logger: EventLogger | null\n isOpen: boolean\n closePanel: () => void\n onOpenMatch: StatsWidgetConfig['onOpenMatch']\n openMatchLabel: UiConfig['openMatch']\n}\n\nexport interface HostEvents {\n slipState: SlipState\n /** Arms the Odds tab badge for an odd the widget added to the slip. */\n markAdded(matchOddsId: number): void\n /** Null unless the operator passed onOpenMatch: without it nothing renders as a link. */\n matchLink: MatchLinkValue | null\n}\n\n/** The part of the widget the operator's side can change, and what the widget reports about it. */\nexport function useHostEvents(opts: HostEventsOptions): HostEvents {\n const { host, operatorId, currentUser, logger, isOpen, closePanel, onOpenMatch, openMatchLabel } = opts\n\n // The two marks live here, not in the button or the monitor hook, so a host call can clear\n // them. `added` arms the Odds tab badge; `settled` flips a button to \"In slip\".\n const [added, setAdded] = useState<Record<number, true>>({})\n const [settled, setSettled] = useState<Record<number, true>>({})\n const markAdded = useCallback((matchOddsId: number) => {\n setAdded((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n }, [])\n const settle = useCallback((matchOddsId: number) => {\n setSettled((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n }, [])\n const clearMarks = useCallback((ids: readonly number[]) => {\n const drop = (prev: Record<number, true>): Record<number, true> => {\n if (!ids.some((id) => prev[id])) return prev\n const next = { ...prev }\n for (const id of ids) delete next[id]\n return next\n }\n setAdded(drop)\n setSettled(drop)\n }, [])\n\n const hasHost = host !== undefined\n // Only an operator that passed a host can ever read the ledger, so only then is it written.\n const ledger = useMemo(\n () => (hasHost ? createSlipLedger(`ss-w-slip:${operatorId}`) : null),\n [hasHost, operatorId],\n )\n const currentUserRef = useRef(currentUser)\n currentUserRef.current = currentUser // latest-value pattern; recordAdd stays stable across logins\n const recordAdd = useCallback((add: SlipAdd) => {\n ledger?.record({ id: add.selection.matchOddsId, market: add.market, ...add.pick, user: currentUserRef.current })\n }, [ledger])\n const slipState = useMemo<SlipState>(\n () => ({ added, settled, settle, recordAdd }),\n [added, settled, settle, recordAdd],\n )\n\n const hasOpenMatch = typeof onOpenMatch === 'function'\n const tracksViews = hasHost || hasOpenMatch\n // What this tab has already reported about match views. Keyed on the user as well, so a login\n // or logout starts from the state stored for that visitor.\n const views = useMemo(\n () => (tracksViews ? createMatchViews(`ss-w-views:${operatorId}`, { user: currentUser }) : null),\n [tracksViews, operatorId, currentUser],\n )\n\n // What a host call does. It lives in a ref so the attach effect below depends only on the host,\n // while every call still sees the latest logger, ledger and user (the latest-fn pattern).\n const sinkRef = useRef<HostSink>(() => {})\n sinkRef.current = (command) => {\n if (command.kind === 'matchOpened') {\n if (views?.view(command.matchId) === 'log') {\n logger?.log({ name: 'match_view', entityType: 'match', entityId: String(command.matchId) })\n }\n return\n }\n const name = command.kind === 'slipRemoved' ? 'slip_remove' : 'bet_placed'\n const ids = command.kind === 'slipRemoved' ? [command.matchOddsId] : command.matchOddsIds\n // The marks clear for any odd the host names. Only an odd the widget itself added, a ledger\n // hit, is reported: the host passes every leg without filtering.\n clearMarks(ids)\n if (!ledger) return\n let reported = 0\n for (const id of ids) {\n const entry = ledger.take(id, currentUser)\n if (!entry || reported >= BET_REPORT_MAX) continue\n reported++\n logger?.log(toSlipEvent(name, entry))\n }\n }\n useEffect(() => {\n if (!host) return\n return attachHost(host, (command) => sinkRef.current(command))\n }, [host])\n\n // A view is reported only for a visitor who has opened the panel in this tab. The first open\n // logs what was held until then and sends it; a view is otherwise deferred and starts no\n // request of its own. `views` changes with the user, so a login while the panel is open\n // re-runs this for the new visitor.\n useEffect(() => {\n if (!isOpen || !views) return\n const held = views.markOpened()\n if (held.length === 0) return\n for (const matchId of held) {\n logger?.log({ name: 'match_view', entityType: 'match', entityId: String(matchId) })\n }\n void logger?.flushNow()\n }, [isOpen, views, logger])\n\n // What a tap on a match link does. In a ref for the same reason as the sink: the context value\n // below stays stable while the tap still sees the latest handler, logger and view state.\n const openMatchRef = useRef<(matchId: number) => void>(() => {})\n openMatchRef.current = (matchId) => {\n // The tap and the page view that follows it share one `seen` entry, so one visit to a match\n // writes one row.\n if (views?.view(matchId) === 'log') {\n logger?.log({ name: 'match_open', entityType: 'match', entityId: String(matchId) })\n }\n try {\n const done = onOpenMatch?.({ matchId })\n if (done && typeof done.then === 'function') done.then(undefined, () => {})\n } catch {\n // an operator handler that throws must not break the widget\n }\n // On a phone the panel covers the page, so the match page would open behind it.\n if (typeof window.matchMedia === 'function' && window.matchMedia(FULLSCREEN_QUERY).matches) closePanel()\n }\n const matchLink = useMemo<MatchLinkValue | null>(\n () => (hasOpenMatch ? { open: (matchId) => openMatchRef.current(matchId), label: openMatchLabel } : null),\n [hasOpenMatch, openMatchLabel],\n )\n\n return { slipState, markAdded, matchLink }\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { ChatHeader } from './ChatHeader'\nimport { MessageList } from './MessageList'\nimport { ChatInput } from './ChatInput'\nimport { TabBar } from './TabBar'\nimport { MatchesPanel, OddsPanel } from './MonitorTabs'\nimport type { AskHandler } from './LiveFactBlock'\nimport { TodayPanel } from './TodayPanel'\nimport { GamesPanel } from './GamesPanel'\nimport { LeaderboardPanel } from './LeaderboardPanel'\nimport { visibleGroupsOf } from '../liveClock'\n\n// Mirrors the panel's fullscreen breakpoint in widget.css (@media max-width: 639px).\n// The panel only traps the page — and is thus truly modal — when it fills the viewport.\nexport const FULLSCREEN_QUERY = '(max-width: 639px)'\n\nfunction useIsModal(): boolean {\n const [modal, setModal] = useState(false)\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return\n const mql = window.matchMedia(FULLSCREEN_QUERY)\n const sync = (): void => setModal(mql.matches)\n sync()\n mql.addEventListener('change', sync)\n return () => mql.removeEventListener('change', sync)\n }, [])\n return modal\n}\n\nexport function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, loggedIn, conversation }: {\n controller: ChatController\n ui: UiConfig\n slip: SlipHandlerProps\n onDashboardTap?: DashboardTapHandler\n /** Optional -- absent (feature off / not threaded) renders today's DOM byte-identically. */\n monitor?: LiveMonitorController\n /** Optional -- absent means the Today tab never qualifies (see hasToday below). */\n discovery?: MatchDiscoveryController\n /** Games hook result; absent for non-club operators. */\n gamesResult?: { enabled: boolean; games: GameSummary[]; loading: boolean; refresh: () => void }\n /** Leaderboard hook result; absent for non-club operators. */\n leaderboardResult?: { data: LeaderboardPayload | null; loading: boolean; refresh: () => void }\n /** True when the operator user is logged in (operatorUserId is set). */\n loggedIn?: boolean\n /** Conversation instance threaded down to GameScreenHost for game config fetching + play submits. */\n conversation?: GamePlayConversation | null\n}): JSX.Element {\n const { state, close, stop, send, reset } = controller\n const isModal = useIsModal()\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close() }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [close])\n\n // Composer always switches the visible tab to chat BEFORE the message is sent, so a reply\n // streaming in is never invisible behind the Matches/Odds tab.\n const handleSend = (text: string) => {\n monitor?.setActiveTab('chat')\n send(text)\n }\n\n // \"Ask about this\" on a live fact: same tab-first rule as the composer, plus the grounding the\n // server turns into [live_facts] context (spec §6).\n const handleAsk: AskHandler = (text, grounding) => {\n monitor?.setActiveTab('chat')\n send(text, { grounding })\n }\n\n // A reply landing while the user is on another tab must surface the chat dot -- markChatActivity\n // is idempotent (setChatDot(true) on an already-true dot is a no-op re-render), so re-running\n // this on every streaming/message-count change is safe.\n useEffect(() => {\n if (monitor && monitor.activeTab !== 'chat' && state.isStreaming) monitor.markChatActivity()\n }, [monitor, state.isStreaming, state.messages.length])\n\n return (\n <div className=\"ss-w-panel\" role=\"dialog\" aria-modal={isModal} aria-label={ui.chatDialogLabel}>\n <ChatHeader\n onClose={close}\n closeLabel={ui.closeChat}\n logoUrl={ui.logoUrl}\n headerTitle={ui.headerTitle}\n onNewConversation={reset}\n canReset={state.messages.length > 0}\n newConversationLabel={ui.newConversation}\n moreOptionsLabel={ui.moreOptions}\n />\n {monitor && (\n <TabBar\n monitor={monitor}\n ui={ui}\n matchCount={monitor.pins.filter((p) => p.kind === 'match').length}\n oddsCount={monitor.pins.filter((p) => p.kind !== 'match').length}\n todayCount={discovery?.liveCount ?? 0}\n hasToday={discovery ? visibleGroupsOf(discovery.groups, discovery.states).length > 0 : false}\n gamesEnabled={gamesResult?.enabled ?? false}\n />\n )}\n {/* MessageList stays MOUNTED across tab switches so its scroll-anchoring refs survive --\n `display: contents` makes the wrapper transparent to .ss-w-panel's flex layout when the\n chat tab is active. `display: none` would zero the list's clientHeight and reset its\n scrollTop, defeating MessageList's own scroll-anchoring math (and silently consuming its\n reserved-turn-space effect) the moment a tab switch happens mid-stream. Absolute-position\n + visibility:hidden instead: the list keeps its box (so its scroll position survives) but\n is pulled out of .ss-w-panel's flex flow (so it doesn't fight the active panel for space)\n and is neither painted nor interactive. `.ss-w-panel` is `position: fixed`, which already\n serves as the containing block for this. */}\n <div\n style={\n !monitor || monitor.activeTab === 'chat'\n ? { display: 'contents' }\n // display:flex (not the default block) is required here: MessageList's root carries\n // `.ss-w-list { flex: 1; ... }`, which only takes effect on a flex-item child. Without\n // it this wrapper lays out as a plain block, .ss-w-list collapses to its own\n // content height (no longer clipped by .ss-w-panel's fixed height), scrollHeight\n // drops to equal clientHeight, and the browser clamps its scrollTop to 0 --\n // silently destroying the exact scroll position this hidden-not-unmounted\n // wrapper exists to preserve.\n : { position: 'absolute', inset: 0, visibility: 'hidden', display: 'flex', flexDirection: 'column' }\n }\n >\n <MessageList controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} monitor={monitor} />\n </div>\n {monitor && discovery && monitor.activeTab === 'today' && <TodayPanel discovery={discovery} ui={ui} monitor={monitor} />}\n {monitor && monitor.activeTab === 'following' && <MatchesPanel monitor={monitor} ui={ui} slip={slip} onAsk={handleAsk} />}\n {monitor && monitor.activeTab === 'odds' && <OddsPanel monitor={monitor} ui={ui} slip={slip} />}\n {monitor && monitor.activeTab === 'games' && gamesResult && (\n <GamesPanel\n loggedIn={!!loggedIn}\n games={gamesResult.games}\n ui={ui}\n conversation={conversation}\n leaderboard={leaderboardResult?.data ?? null}\n refreshHub={() => { gamesResult.refresh(); leaderboardResult?.refresh() }}\n />\n )}\n {monitor && monitor.activeTab === 'leaderboard' && leaderboardResult && (\n <LeaderboardPanel\n loggedIn={!!loggedIn}\n data={leaderboardResult.data}\n loading={leaderboardResult.loading}\n onPlay={() => monitor.setActiveTab('games')}\n ui={ui}\n />\n )}\n {/* The composer is a chat affordance; hide it on the Games/Leaderboard tabs where it only confuses. */}\n {(!monitor || (monitor.activeTab !== 'games' && monitor.activeTab !== 'leaderboard')) && (\n <ChatInput placeholder={ui.placeholder} streaming={state.isStreaming} onSend={handleSend} onStop={stop} stopLabel={ui.stopResponse} sendLabel={ui.sendMessage} />\n )}\n </div>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { CloseIcon, KebabIcon } from './Icons'\nimport { BrandMark } from './BrandMark'\n\nexport function ChatHeader({\n onClose,\n closeLabel = 'Close chat',\n logoUrl,\n headerTitle,\n onNewConversation,\n canReset,\n newConversationLabel = 'New conversation',\n moreOptionsLabel = 'More options',\n}: {\n onClose: () => void\n closeLabel?: string\n logoUrl?: string\n headerTitle?: string\n onNewConversation?: () => void\n canReset?: boolean\n newConversationLabel?: string\n moreOptionsLabel?: string\n}): JSX.Element {\n const [menuOpen, setMenuOpen] = useState(false)\n const wrapRef = useRef<HTMLDivElement>(null)\n const kebabRef = useRef<HTMLButtonElement>(null)\n const firstItemRef = useRef<HTMLButtonElement>(null)\n\n // Secondary actions (currently just \"New conversation\") live behind the kebab; Close stays a\n // one-tap control since it is the most frequent action.\n const hasMenu = !!(canReset && onNewConversation)\n\n useEffect(() => {\n if (menuOpen) firstItemRef.current?.focus()\n }, [menuOpen])\n\n useEffect(() => {\n if (!menuOpen) return\n const onPointer = (e: MouseEvent) => {\n if (!wrapRef.current?.contains(e.target as Node)) setMenuOpen(false)\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setMenuOpen(false)\n kebabRef.current?.focus()\n }\n }\n document.addEventListener('mousedown', onPointer)\n document.addEventListener('keydown', onKey)\n return () => {\n document.removeEventListener('mousedown', onPointer)\n document.removeEventListener('keydown', onKey)\n }\n }, [menuOpen])\n\n const runNewConversation = (): void => {\n setMenuOpen(false)\n onNewConversation?.()\n }\n\n return (\n <header className=\"ss-w-header\">\n <BrandMark logoUrl={logoUrl} className=\"ss-w-header-mark\" />\n <span className=\"ss-w-header-title\">{headerTitle ?? 'SensibleStats'}</span>\n {hasMenu ? (\n <div className=\"ss-w-menu-wrap\" ref={wrapRef}>\n <button\n type=\"button\"\n className=\"ss-w-kebab\"\n ref={kebabRef}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n aria-label={moreOptionsLabel}\n onClick={() => setMenuOpen((open) => !open)}\n >\n <KebabIcon />\n </button>\n {menuOpen ? (\n <div className=\"ss-w-menu\" role=\"menu\" aria-label={moreOptionsLabel}>\n <button\n type=\"button\"\n className=\"ss-w-menu-item\"\n role=\"menuitem\"\n ref={firstItemRef}\n onClick={runNewConversation}\n >\n <span>{newConversationLabel}</span>\n </button>\n </div>\n ) : null}\n </div>\n ) : null}\n <button type=\"button\" className=\"ss-w-close\" aria-label={closeLabel} onClick={onClose}>\n <CloseIcon />\n </button>\n </header>\n )\n}\n","// SensibleStats brand mark, inlined as a data URI so the published widget\n// bundle stays self-contained (no external asset hosting / CORS concerns\n// for third-party embeds).\nexport const SS_LOGO_DATA_URI = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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\"\n","// SensibleStats brand mark, rendered from the official logo asset.\nimport { SS_LOGO_DATA_URI } from '../assets/logo'\n\nexport function SsMark({ className }: { className?: string }): JSX.Element {\n return <img className={className} src={SS_LOGO_DATA_URI} alt=\"\" aria-hidden=\"true\" />\n}\nexport function SendIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M3 20l18-8L3 4v6l12 2-12 2z\" /></svg>\n}\nexport function CloseIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M18 6L6 18M6 6l12 12\" stroke=\"currentColor\" strokeWidth=\"2\" /></svg>\n}\nexport function ChevronIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" /></svg>\n}\nexport function NewChatIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" /></svg>\n}\nexport function KebabIcon(): JSX.Element {\n return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><g fill=\"currentColor\"><circle cx=\"12\" cy=\"5\" r=\"1.6\" /><circle cx=\"12\" cy=\"12\" r=\"1.6\" /><circle cx=\"12\" cy=\"19\" r=\"1.6\" /></g></svg>\n}\n\n// Dashboard tile icons are emoji (matching the betting widget mockup), not the old monochrome\n// line glyphs: they carry their own colour and read at a larger size. Rendered as text.\nconst DASHBOARD_EMOJI: Record<string, string> = {\n football: '⚽', 'goal-net': '🥅', btts: '🤝',\n card: '🟨', 'corner-flag': '🚩', player: '👤',\n target: '🎯', trophy: '🏆', 'chart-line': '📈',\n 'chart-bar': '📊', chat: '💬', fire: '🔥', sparkle: '✨',\n}\n\nexport function DashboardIcon({ name }: { name: string }): JSX.Element {\n // hasOwnProperty (not `in`, not `?? fallback`) so a prototype member name like 'toString'\n // resolves to the fallback emoji rather than an inherited function or a stray property value.\n const glyph = Object.prototype.hasOwnProperty.call(DASHBOARD_EMOJI, name)\n ? DASHBOARD_EMOJI[name]\n : DASHBOARD_EMOJI.target\n return <span className=\"ss-w-dash-emoji\" aria-hidden=\"true\">{glyph}</span>\n}\n","import { useState } from 'react'\nimport { SsMark } from './Icons'\n\n// Operator logo with a hard fallback to the built-in SS mark: a missing or\n// broken logoUrl must never leave a blank in the header or launcher.\nexport function BrandMark({ logoUrl, className }: { logoUrl?: string; className?: string }): JSX.Element {\n const [failed, setFailed] = useState(false)\n if (!logoUrl || failed) return <SsMark className={className} />\n return <img className={className} src={logoUrl} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n}\n","import { useEffect, useRef } from 'react'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { ChatMessage } from './ChatMessage'\nimport { IntentChips } from './IntentChips'\nimport { ActionButtons } from './ActionButtons'\nimport { isPinnedToBottom } from '../scroll'\nimport type { Message } from '../reducer'\n\n// The element to pin to the top when a new turn begins: the user's question if\n// this turn has one (so the reply reads from just below it), otherwise the\n// assistant turn itself (an auto-greeting or greeting dashboard has no user\n// bubble, and we still want its top in view rather than its bottom).\nfunction turnAnchor(messages: Message[]): { turnId: string; anchorId: string } | null {\n const last = messages[messages.length - 1]\n if (!last || last.role !== 'assistant') return null\n const prev = messages[messages.length - 2]\n return { turnId: last.id, anchorId: prev && prev.role === 'user' ? prev.id : last.id }\n}\n\nexport function MessageList({ controller, ui, slip, onDashboardTap, monitor }: {\n controller: ChatController\n ui: UiConfig\n slip: SlipHandlerProps\n onDashboardTap?: DashboardTapHandler\n monitor?: LiveMonitorController\n}): JSX.Element {\n const { state, send } = controller\n const listRef = useRef<HTMLDivElement>(null)\n const endRef = useRef<HTMLDivElement>(null)\n // Follow the stream only while the user is at the bottom. pinnedRef is updated\n // on real scroll events (content growth fires none), so a user who scrolls up\n // stays put when late content — suggested actions, status — arrives.\n const pinnedRef = useRef(true)\n // The turn id we have already anchored to the top. On a new turn we pin its\n // start to the top so a long reply reads from its beginning instead of the\n // viewport jumping to the bottom of the answer.\n const anchoredTurnRef = useRef<string | null>(null)\n useEffect(() => {\n const anchor = turnAnchor(state.messages)\n const list = listRef.current\n if (anchor && anchor.turnId !== anchoredTurnRef.current) {\n anchoredTurnRef.current = anchor.turnId\n // Reserve a viewport of space below the new turn before scrolling, so the\n // anchor can actually reach the top even while the reply is still empty\n // (without it the scroll lands at the bottom, onScroll re-pins to bottom,\n // and the streaming reply then follows the bottom down). The spacer is the\n // endRef element; it collapses again once the turn stops streaming.\n //\n // Only reserve while the turn is actively streaming. A turn first anchored\n // when it is ALREADY complete -- panel opened after the greeting finished,\n // or a restored/cross-tab-synced conversation -- has its full height, so it\n // needs no spacer; reserving one here would never be collapsed (this branch\n // returns, and the collapse below only runs on a later !isStreaming pass\n // that never comes), leaving a viewport of dead scroll space below content.\n if (endRef.current && list) endRef.current.style.height = state.isStreaming ? `${list.clientHeight}px` : ''\n // Top-anchored, so the list is no longer pinned to the bottom; streaming\n // updates below won't yank it back down for the rest of this turn.\n pinnedRef.current = false\n list?.querySelector(`[data-msg-id=\"${anchor.anchorId}\"]`)?.scrollIntoView({ block: 'start' })\n return\n }\n // Turn finished: drop the reserved space (content above is unaffected, so the\n // anchored message keeps its position).\n if (!state.isStreaming && endRef.current) endRef.current.style.height = ''\n if (pinnedRef.current) endRef.current?.scrollIntoView({ block: 'end' })\n }, [state.messages, state.status, state.isStreaming])\n\n // Chips are always emitted by the server; the widget prefers the dashboard and\n // hides the chips client-side once a greeting dashboard, a club fan dashboard, or a\n // user message exists.\n const hasUserMessage = state.messages.some((m) => m.role === 'user')\n const hasDashboard = state.messages.some((m) => m.role === 'assistant' && (m.greetingDashboard || m.clubFanDashboard))\n return (\n <div\n className=\"ss-w-list\"\n aria-live=\"polite\"\n ref={listRef}\n onScroll={() => { if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current) }}\n >\n {state.messages.map((m) => (\n <ChatMessage\n key={m.id}\n message={m}\n disabled={state.isStreaming}\n onAct={(a) => send(a.message, { actionId: a.actionId, actionRef: a.actionRef, displayText: a.label })}\n onTap={(tile, index) => {\n send(tile.actionValue, tile.actionRef\n ? { actionRef: tile.actionRef, displayText: tile.title }\n : { displayText: tile.title })\n // Only fires from within the dashboard this message itself rendered (ChatMessage\n // renders GreetingDashboard only when message.greetingDashboard is set), so the\n // dashboard -- and its layout -- is guaranteed present here.\n if (m.role === 'assistant' && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout)\n }}\n ui={ui}\n slip={slip}\n monitor={monitor}\n />\n ))}\n {state.isStreaming && state.actionsLoading ? <ActionButtons actions={[]} loading onAct={() => {}} /> : null}\n {state.status ? <div className=\"ss-w-status\">{state.status}</div> : null}\n {state.error ? (\n <div className=\"ss-w-error\" role=\"alert\">\n <span>{'message' in state.error ? state.error.message : ui.somethingWentWrong}</span>\n <button type=\"button\" className=\"ss-w-retry\" onClick={() => controller.retry()}>{ui.retry}</button>\n </div>\n ) : null}\n {!hasUserMessage && !hasDashboard ? <IntentChips chips={state.starters} onPick={(t) => send(t)} /> : null}\n <div ref={endRef} className=\"ss-w-turn-spacer\" aria-hidden=\"true\" />\n </div>\n )\n}\n","import ReactMarkdown, { type Components } from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst components: Components = {\n a: ({ children, href }) => (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"ss-w-md-link\">{children}</a>\n ),\n table: ({ children }) => (\n <div className=\"ss-w-table-wrap\"><table className=\"ss-w-md-table\">{children}</table></div>\n ),\n ul: ({ children }) => <ul className=\"ss-w-md-ul\">{children}</ul>,\n ol: ({ children }) => <ol className=\"ss-w-md-ol\">{children}</ol>,\n code: ({ children }) => <code className=\"ss-w-md-code\">{children}</code>,\n}\n\nexport function Markdown({ text }: { text: string }): JSX.Element {\n return (\n <div className=\"ss-w-md\">\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>{text}</ReactMarkdown>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { CardVM, CardScope, StatCell } from '../model'\n\nconst MAX_VISIBLE = 3\nconst RECORD_RE = /^(\\d+)-(\\d+)-(\\d+)$/\n\nfunction initials(name: string): string {\n return name.split(/\\s+/).slice(0, 2).map((w) => w[0] ?? '').join('').toUpperCase()\n}\n\n// \"2026/2027\" -> \"26/27\", \"2026\" -> \"26\"; leaves any non-4-digit token untouched.\nfunction shortSeason(season: string): string {\n return season.replace(/\\d{4}/g, (year) => year.slice(2))\n}\n\nfunction Crest({ image, label }: { image: string; label?: string }): JSX.Element {\n return (\n <span\n className=\"ss-w-ecard-crest\"\n style={{ backgroundImage: `url(${image})` }}\n {...(label ? { role: 'img', title: label, 'aria-label': label } : { 'aria-hidden': 'true' as const })}\n />\n )\n}\n\n// Proportional win/draw/loss bar. Rendered for any stat value shaped \"w-d-l\".\nfunction FormBar({ w, d, l }: { w: number; d: number; l: number }): JSX.Element | null {\n if (w + d + l === 0) return null\n return (\n <span className=\"ss-w-form\" aria-hidden=\"true\">\n {w > 0 ? <span className=\"ss-w-form-w\" style={{ flexGrow: w }} /> : null}\n {d > 0 ? <span className=\"ss-w-form-d\" style={{ flexGrow: d }} /> : null}\n {l > 0 ? <span className=\"ss-w-form-l\" style={{ flexGrow: l }} /> : null}\n </span>\n )\n}\n\nfunction StatCellView({ s }: { s: StatCell }): JSX.Element {\n const m = RECORD_RE.exec(s.value)\n if (m) {\n return (\n <div className=\"ss-w-ecard-cell\">\n <span className=\"ss-w-ecard-cval\"><FormBar w={Number(m[1])} d={Number(m[2])} l={Number(m[3])} /></span>\n <span className=\"ss-w-ecard-clabel\">{s.value}</span>\n </div>\n )\n }\n return (\n <div className=\"ss-w-ecard-cell\">\n <span className=\"ss-w-ecard-cval\">{s.value}</span>\n <span className=\"ss-w-ecard-clabel\">{s.label}</span>\n </div>\n )\n}\n\nfunction StatStrip({ stats }: { stats: StatCell[] }): JSX.Element | null {\n if (stats.length === 0) return null\n const cols = Math.min(stats.length, 4)\n return (\n <div className=\"ss-w-ecard-strip\" style={{ gridTemplateColumns: `repeat(${cols}, 1fr)` }}>\n {stats.map((s) => <StatCellView key={s.label + s.value} s={s} />)}\n </div>\n )\n}\n\nfunction CardHeader({ c, showScopeCrest }: { c: CardVM; showScopeCrest: boolean }): JSX.Element {\n const onlyScope = c.scopes.length === 1 ? c.scopes[0]! : null\n return (\n <div className=\"ss-w-ecard-hd\">\n <span\n className={c.kind === 'team' ? 'ss-w-thumb ss-w-team' : 'ss-w-thumb'}\n style={c.image ? { backgroundImage: `url(${c.image})` } : undefined}\n >\n {c.image ? '' : initials(c.name)}\n </span>\n <span className=\"ss-w-ecard-idtext\">\n <span className=\"ss-w-nm\">{c.name}</span>\n {c.sub ? <span className=\"ss-w-sub\">{c.sub}</span> : null}\n </span>\n <span className=\"ss-w-ecard-meta\">\n {showScopeCrest && onlyScope?.image ? <Crest image={onlyScope.image} label={onlyScope.label} /> : null}\n {c.season ? <span className=\"ss-w-ecard-season\">{shortSeason(c.season)}</span> : null}\n </span>\n </div>\n )\n}\n\nfunction ScopeTabs({ scopes, active, onSelect }: { scopes: CardScope[]; active: number; onSelect: (i: number) => void }): JSX.Element {\n return (\n <div className=\"ss-w-ecard-scopes\" role=\"tablist\">\n {scopes.map((s, i) => (\n <button\n key={String(s.competitionId ?? 'all')}\n type=\"button\"\n role=\"tab\"\n className=\"ss-w-ecard-scope\"\n aria-selected={i === active}\n aria-label={s.label}\n title={s.label}\n onClick={() => onSelect(i)}\n >\n {s.image ? <Crest image={s.image} /> : s.label}\n </button>\n ))}\n </div>\n )\n}\n\nfunction EntityCardItem({ c }: { c: CardVM }): JSX.Element {\n const [active, setActive] = useState(0)\n const hasBody = c.scopes.length > 0\n if (!hasBody) {\n return (\n <div className=\"ss-w-ecard ss-w-ecard-bare\" data-kind={c.kind}>\n <CardHeader c={c} showScopeCrest={false} />\n </div>\n )\n }\n const multi = c.scopes.length > 1\n const scope = c.scopes[multi ? (c.scopes[active] ? active : 0) : 0]!\n return (\n <div className=\"ss-w-ecard\" data-kind={c.kind}>\n <CardHeader c={c} showScopeCrest={!multi} />\n {multi ? <ScopeTabs scopes={c.scopes} active={active} onSelect={setActive} /> : null}\n <StatStrip stats={scope.stats} />\n </div>\n )\n}\n\nexport function EntityCardList({ cards, disabled, showLessLabel = 'Show less', showMoreLabel = (n: number) => `Show ${n} more` }: { cards: CardVM[]; disabled?: boolean; showLessLabel?: string; showMoreLabel?: (n: number) => string }): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n if (cards.length === 0) return null\n const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE)\n const overflow = cards.length - MAX_VISIBLE\n return (\n <div className=\"ss-w-cards\">\n {visible.map((c) => <EntityCardItem key={c.id} c={c} />)}\n {overflow > 0 ? (\n <button type=\"button\" className=\"ss-w-cards-more\" disabled={disabled} onClick={() => setExpanded((v) => !v)}>\n {expanded ? showLessLabel : showMoreLabel(overflow)}\n </button>\n ) : null}\n </div>\n )\n}\n","import { useCallback, useState } from 'react'\nimport { isAddToSlipResult, type AddToSlipResult, type SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { toSlipSelection, type InsightVM } from '../model'\nimport { ADD_TO_SLIP_TIMEOUT_MS, isTerminal, resultToToast, slipOutcome, slipPickFields, wasAdded, type SlipHandlerProps, type SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { useSlipState } from '../slipStateContext'\nimport { Toast } from './Toast'\n\nfunction withTimeout(value: Promise<AddToSlipResult | void>): Promise<AddToSlipResult | void> {\n return Promise.race([\n value,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('add-to-slip timed out')), ADD_TO_SLIP_TIMEOUT_MS)),\n ])\n}\n\nexport function SlipButton(\n { selection, shownOdds, marketDeveloperName, selectionLabel, line, slip, ui, price }:\n {\n selection: SlipSelection | null; shownOdds: string; marketDeveloperName?: string\n /** The raw selection label and line, sent apart (never the joined display string). */\n selectionLabel?: string; line?: string\n slip: SlipHandlerProps; ui?: UiConfig\n /** Draws the price itself as the button, as a compact list row does. */\n price?: { label?: string; ariaLabel: string }\n },\n): JSX.Element | null {\n const [pending, setPending] = useState(false)\n const [settledLocal, setSettledLocal] = useState(false)\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n const slipState = useSlipState()\n\n const handler = slip.onAddToSlip\n if (!ui || !handler || !selection) return null\n // Inside a widget the mark belongs to the odd and lives at the root, where a host call can\n // clear it. Rendered on its own, with no provider, the button keeps its own state.\n const settled = slipState ? !!slipState.settled[selection.matchOddsId] : settledLocal\n\n const onClick = async (): Promise<void> => {\n setPending(true)\n const pick = slipPickFields(selection, ui.rawBettingLabels ? selectionLabel : undefined, line)\n // A market/selection with no marketDeveloperName has no entity to report under entityType\n // 'market' -- skip the emit rather than log entityId: undefined (mirrors the PinToggle guard).\n if (marketDeveloperName !== undefined) {\n log?.log({ name: 'slip_click', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, ...pick })\n }\n try {\n const raw = await withTimeout(Promise.resolve(handler(selection)))\n // Only a genuine void return means \"assume success\". A non-null value the\n // guard rejects is a broken contract (e.g. an operator forwarding their own\n // backend's reason string, which `any` lets past the compiler) — treating it\n // as void would report a refused bet to the user as added.\n if (raw != null && !isAddToSlipResult(raw)) throw new Error('malformed add-to-slip result')\n const result = raw ?? undefined\n if (marketDeveloperName !== undefined) {\n log?.log({\n name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName,\n outcome: slipOutcome(result), ...pick,\n })\n }\n setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui))\n if (slipState) {\n if (isTerminal(result)) slipState.settle(selection.matchOddsId)\n if (wasAdded(result) && marketDeveloperName !== undefined) {\n slipState.recordAdd({ selection, market: marketDeveloperName, pick })\n }\n } else {\n setSettledLocal(isTerminal(result))\n }\n } catch {\n if (marketDeveloperName !== undefined) {\n log?.log({ name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, outcome: 'timeout', ...pick })\n }\n setToast({ kind: 'error', text: ui.slipFailed })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"ss-w-slip\">\n {price ? (\n <button\n type=\"button\"\n className=\"ss-w-slip-btn ss-w-slip-btn--price\"\n data-settled={settled || undefined}\n aria-label={`${price.ariaLabel}, ${settled ? ui.inSlip : ui.addToSlip}`}\n disabled={pending || settled}\n onClick={onClick}\n >\n {settled ? <span className=\"ss-w-mol-tick\" aria-hidden=\"true\">✓</span> : null}\n {price.label ? <span className=\"ss-w-mol-lab\">{price.label}</span> : null}\n <span>{shownOdds}</span>\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"ss-w-slip-btn\"\n disabled={pending || settled}\n onClick={onClick}\n >\n {settled ? ui.inSlip : ui.addToSlip}\n </button>\n )}\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n\nexport function AddToSlipButton(\n { it, slip, ui }: { it: InsightVM; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n const selection = it.addToSlipEnabled ? toSlipSelection(it, slip.conversationId) : null\n return (\n <SlipButton\n selection={selection}\n shownOdds={it.odds ?? ''}\n marketDeveloperName={it.marketDeveloperName}\n selectionLabel={it.selectionLabel}\n line={it.line}\n slip={slip}\n ui={ui}\n />\n )\n}\n","export interface ChartSample { atMs: number; price: number }\nexport interface ChartGeometry {\n path: string\n markers: { x: number; y: number }[]\n gridlines: { y: number; price: number }[]\n viewBox: string\n startMs: number\n endMs: number\n}\n\nexport const CHART_VIEW_W = 320\nexport const CHART_VIEW_H = 140\n\nconst PLOT_X0 = 40\nconst PLOT_X1 = 312\nconst PLOT_Y0 = 10\nconst PLOT_Y1 = 110\n\n// Point markers are drawn only on sparse series. Measured on sandbox1, the median chartable\n// series has TWO points: without markers a two-point chart is one bare diagonal that reads as a\n// rendering glitch rather than as data. Above this count the dots crowd the line and the shape\n// carries itself.\nconst MARKER_MAX_POINTS = 8\n\n// A flat series has no price range to scale against. Widening the domain by a fixed amount keeps\n// the line horizontal through the middle of the plot instead of dividing by zero.\nconst FLAT_DOMAIN_PAD = 0.05\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100\n\nexport function projectSeries(samples: ChartSample[]): ChartGeometry | null {\n if (samples.length < 2) return null\n\n // noUncheckedIndexedAccess can't see that the length check above guarantees these exist.\n const tMin = samples[0]!.atMs\n const tMax = samples[samples.length - 1]!.atMs\n if (tMax <= tMin) return null\n\n const prices = samples.map((s) => s.price)\n const pMin = Math.min(...prices)\n const pMax = Math.max(...prices)\n\n let yMin: number\n let yMax: number\n if (pMax === pMin) {\n yMin = pMin - FLAT_DOMAIN_PAD\n yMax = pMax + FLAT_DOMAIN_PAD\n } else {\n const pad = (pMax - pMin) * 0.1\n yMin = pMin - pad\n yMax = pMax + pad\n }\n\n const x = (atMs: number): number =>\n round2(PLOT_X0 + ((atMs - tMin) / (tMax - tMin)) * (PLOT_X1 - PLOT_X0))\n const y = (price: number): number =>\n round2(PLOT_Y1 - ((price - yMin) / (yMax - yMin)) * (PLOT_Y1 - PLOT_Y0))\n\n const projected = samples.map((s) => ({ x: x(s.atMs), y: y(s.price) }))\n const path = projected.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`).join(' ')\n\n return {\n path,\n markers: samples.length <= MARKER_MAX_POINTS ? projected : [],\n // The real extremes, never the padded bounds: a gridline label is a price, and the padded\n // bounds are prices nobody was ever offered. A flat series has one real extreme, not two —\n // two identical gridlines would collide on both React key and rendered text.\n gridlines: pMax === pMin\n ? [{ y: y(pMax), price: pMax }]\n : [\n { y: y(pMax), price: pMax },\n { y: y(pMin), price: pMin },\n ],\n viewBox: `0 0 ${CHART_VIEW_W} ${CHART_VIEW_H}`,\n startMs: tMin,\n endMs: tMax,\n }\n}\n","import type { BettingInsight, EntityCard, MarketOddsCard, MarketOddsRow, OddsMovementCard, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { ChartGeometry, ChartSample } from './chart'\nimport { projectSeries } from './chart'\n\nexport type CardKind = 'player' | 'team' | 'generic'\nexport interface StatCell { label: string; value: string }\nexport interface CardScope { competitionId: number | null; label: string; image?: string; stats: StatCell[] }\nexport interface CardVM { id: string; kind: CardKind; name: string; image?: string; sub?: string; season?: string; scopes: CardScope[] }\nexport interface ActionVM { label: string; actionId?: string; actionRef?: string; message: string }\nexport interface ChipVM { text: string }\nexport interface InsightVM {\n id: string\n market: string\n selection?: string\n odds?: string\n bookmaker?: string\n isLive: boolean\n phase?: string\n fixture?: string\n competition?: string\n text: string\n disclaimer?: string\n matchId: number\n matchOddsId?: number\n marketDeveloperName?: string\n selectionLabel?: string\n line?: string\n addToSlipEnabled: boolean\n pinEnabled: boolean\n isMarketFloor: boolean\n oddsDecimal?: number\n quotedAtUtc?: string\n previousOdds?: string\n movementDirection?: 'shortened' | 'drifted'\n homeTeamName?: string\n awayTeamName?: string\n homeCrest?: string\n awayCrest?: string\n competitionCrest?: string\n kickoffUtc?: string\n kickoffLabel?: string\n}\n\nexport interface MarketOddsRowVM {\n key: string\n selection: string\n selectionLabel?: string\n line?: string\n odds: string\n oddsDecimal?: number\n matchOddsId?: number\n quotedAtUtc?: string\n isMain: boolean\n isSuspended: boolean\n previousOdds?: string\n movementDirection?: 'shortened' | 'drifted'\n}\nexport interface MarketOddsVM {\n id: string\n market: string\n fixture?: string\n homeTeamName?: string\n awayTeamName?: string\n homeCrest?: string\n awayCrest?: string\n competitionCrest?: string\n competition?: string\n kickoffUtc?: string\n kickoffLabel?: string\n bookmaker?: string\n updatedAt?: string\n isLive: boolean\n matchId: number\n mainRows: MarketOddsRowVM[]\n moreRows: MarketOddsRowVM[]\n disclaimer?: string\n addToSlipEnabled: boolean\n marketDeveloperName?: string\n mainLine?: string\n pinEnabled: boolean\n /** The stat drawn inside the card, above the rows. */\n statText?: string\n /** Set when the server sent the card for the market the user bets on. */\n tag?: 'your_market'\n}\n\nfunction str(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined\n}\nfunction num(v: unknown): string | undefined {\n return typeof v === 'number' && Number.isFinite(v) ? String(v) : undefined\n}\n\nfunction readStatCells(raw: unknown): StatCell[] {\n if (!Array.isArray(raw)) return []\n const cells: StatCell[] = []\n for (const entry of raw as Array<Record<string, unknown>>) {\n const label = str(entry.label)\n const value = num(entry.value) ?? str(entry.value)\n if (label !== undefined && value !== undefined) cells.push({ label, value })\n }\n return cells\n}\n\nexport function toCardVM(card: EntityCard): CardVM {\n const entityType = str(card.entityType)?.toLowerCase()\n const kind: CardKind = entityType === 'player' ? 'player' : entityType === 'team' ? 'team' : 'generic'\n const scopes = Array.isArray(card.scopes)\n ? (card.scopes as unknown as Array<Record<string, unknown>>)\n .map((s): CardScope | null => {\n const label = str(s.label)\n if (!label) return null\n return {\n competitionId: typeof s.competitionId === 'number' ? s.competitionId : null,\n label,\n image: str(s.imagePath),\n stats: readStatCells(s.stats),\n }\n })\n .filter((s): s is CardScope => s !== null)\n : []\n return {\n id: String(card.entityId),\n kind,\n name: card.canonicalName,\n image: str(card.imagePath) ?? str(card.imageUrl) ?? str(card.image_url) ?? str(card.logoUrl) ?? str(card.logo),\n sub: str(card.subtitle) ?? str(card.teamName) ?? str(card.leagueName) ?? str(card.position),\n season: str(card.seasonName),\n scopes,\n }\n}\n\nexport function toActionVM(action: Record<string, unknown>): ActionVM {\n const label = str(action.actionLabel) ?? str(action.label) ?? str(action.text) ?? str(action.title) ?? 'Continue'\n const actionId = str(action.actionId) ?? str(action.id)\n const actionRef = str(action.actionRef)\n const message = str(action.actionValue) ?? str(action.message) ?? str(action.query) ?? label\n return { label, actionId, actionRef, message }\n}\n\nexport function toChipVM(intent: Record<string, unknown>): ChipVM | null {\n const text = str(intent.text) ?? str(intent.label) ?? str(intent.title)\n return text ? { text } : null\n}\n\nexport function chipFromText(text: string): ChipVM {\n return { text }\n}\n\n// A localized label can already embed the line (TR \"2.5 Üst\") -- never append it twice.\n// Shared by every selection/line join site so they can't drift out of sync (u324).\nexport function joinSelection(label?: string, line?: string): string | undefined {\n if (label && line && label.includes(line)) return label\n return [label, line].filter(Boolean).join(' ') || undefined\n}\n\nexport function toInsightVM(insight: BettingInsight): InsightVM {\n const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? ''\n const selectionLabel = str(insight.selectionLabel)\n const selectionLine = str(insight.line)\n const selection = joinSelection(selectionLabel, selectionLine)\n const value = insight.odds?.value\n const odds = typeof value === 'number' && Number.isFinite(value) ? value.toFixed(2) : undefined\n const oddsValue = insight.odds?.value\n const matchOddsId = typeof insight.odds?.matchOddsId === 'number' ? insight.odds.matchOddsId : undefined\n const home = str(insight.homeTeamName)\n const away = str(insight.awayTeamName)\n const fixture = home && away ? `${home} vs ${away}` : undefined\n const competition = str(insight.competitionName)\n const previousValue = insight.odds?.previousValue\n const previous =\n typeof previousValue === 'number' && Number.isFinite(previousValue) ? previousValue : undefined\n const direction =\n insight.odds?.movementDirection === 'shortened' || insight.odds?.movementDirection === 'drifted'\n ? insight.odds.movementDirection\n : undefined\n return {\n id: str(insight.insightId) ?? `${str(insight.ruleId) ?? 'insight'}:${num(insight.matchId) ?? ''}`,\n market,\n selection,\n odds,\n // The wire payload carries bookmakerId (not a name); render a name only if one is present.\n bookmaker: str(insight.odds?.bookmakerName),\n isLive: insight.odds?.isLive === true,\n phase: str(insight.phase),\n fixture,\n competition,\n text: str(insight.text) ?? '',\n disclaimer: str(insight.disclaimer),\n matchId: typeof insight.matchId === 'number' ? insight.matchId : 0,\n matchOddsId,\n marketDeveloperName: str(insight.marketDeveloperName),\n selectionLabel: str(insight.selectionLabel),\n line: str(insight.line),\n addToSlipEnabled: insight.addToSlipEnabled === true,\n pinEnabled: insight.pinEnabled === true,\n isMarketFloor: insight.isMarketFloor === true,\n oddsDecimal: typeof oddsValue === 'number' && Number.isFinite(oddsValue) ? oddsValue : undefined,\n quotedAtUtc: str(insight.odds?.quotedAtUtc),\n previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n homeTeamName: home,\n awayTeamName: away,\n homeCrest: str(insight.homeTeamImagePath),\n awayCrest: str(insight.awayTeamImagePath),\n competitionCrest: str(insight.competitionImagePath),\n kickoffUtc: str(insight.kickoffUtc),\n kickoffLabel: str(insight.kickoffLabel),\n }\n}\n\nexport function toSlipSelection(vm: InsightVM, conversationId?: string): SlipSelection | null {\n if (vm.matchOddsId === undefined || vm.oddsDecimal === undefined) return null\n const selection: SlipSelection = {\n matchOddsId: vm.matchOddsId,\n matchId: vm.matchId,\n oddsDecimal: vm.oddsDecimal,\n }\n if (vm.quotedAtUtc !== undefined) selection.quotedAtUtc = vm.quotedAtUtc\n if (vm.id !== undefined) selection.insightId = vm.id\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n\nexport function toMarketOddsVM(card: MarketOddsCard): MarketOddsVM {\n const rows = Array.isArray(card.rows) ? card.rows : []\n const toRow = (r: MarketOddsRow, i: number): MarketOddsRowVM => {\n const selection = joinSelection(str(r.selectionLabel), str(r.line)) ?? ''\n const price = typeof r.price === 'number' && Number.isFinite(r.price) ? r.price : undefined\n const previous =\n typeof r.previousPrice === 'number' && Number.isFinite(r.previousPrice) ? r.previousPrice : undefined\n const direction =\n r.movementDirection === 'shortened' || r.movementDirection === 'drifted' ? r.movementDirection : undefined\n return {\n key: `${selection}:${str(r.line) ?? ''}:${i}`,\n selection,\n selectionLabel: str(r.selectionLabel),\n line: str(r.line),\n odds: price !== undefined ? price.toFixed(2) : '',\n oddsDecimal: price,\n matchOddsId: typeof r.matchOddsId === 'number' ? r.matchOddsId : undefined,\n quotedAtUtc: str(r.quotedAtUtc),\n isMain: r.isMainLine !== false,\n // === true, not !== false: a server that has not shipped the field yet leaves it undefined,\n // and undefined must read as open rather than hiding every price on the card.\n isSuspended: r.isSuspended === true,\n previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n }\n }\n // A suspended selection leaves the ladder entirely, same rule the live match card follows: we do\n // not show a price the bookmaker is not taking. If every line is suspended the card has no rows and\n // MarketOddsCardList renders nothing for it.\n const vms = rows.map(toRow).filter((r) => r.selection && r.odds && !r.isSuspended)\n const home = str(card.homeTeamName)\n const away = str(card.awayTeamName)\n const updated = rows.map((r) => str(r.quotedAtUtc)).filter((v): v is string => !!v).sort()\n return {\n id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}`,\n market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n fixture: home && away ? `${home} vs ${away}` : undefined,\n homeTeamName: home,\n awayTeamName: away,\n homeCrest: str(card.homeTeamImagePath),\n awayCrest: str(card.awayTeamImagePath),\n competitionCrest: str(card.competitionImagePath),\n competition: str(card.competitionName),\n kickoffUtc: str(card.kickoffUtc),\n kickoffLabel: str(card.kickoffLabel),\n bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),\n updatedAt: updated.length > 0 ? updated[updated.length - 1] : undefined,\n isLive: rows.some((r) => r.isLive === true),\n matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n mainRows: vms.filter((r) => r.isMain),\n moreRows: vms.filter((r) => !r.isMain),\n disclaimer: str(card.disclaimer),\n addToSlipEnabled: card.addToSlipEnabled === true,\n marketDeveloperName: str(card.marketDeveloperName),\n mainLine: str(card.mainLine),\n pinEnabled: card.pinEnabled === true,\n statText: card.insight && typeof card.insight === 'object' ? str(card.insight.text) : undefined,\n tag: card.tag === 'your_market' ? 'your_market' : undefined,\n }\n}\n\nexport interface OddsMovementVM {\n id: string\n matchId: number\n market: string\n marketDeveloperName?: string\n selection: string\n selectionLabel?: string\n line?: string\n fixture?: string\n competition?: string\n bookmaker?: string\n opening: string\n current: string\n direction?: 'shortened' | 'drifted'\n windowHours: number\n excludedCount: number\n isSuspended: boolean\n disclaimer?: string\n geometry: ChartGeometry | null\n observationCount: number\n pinEnabled: boolean\n matchOddsId?: number\n}\n\nexport function toOddsMovementVM(card: OddsMovementCard): OddsMovementVM {\n const raw = Array.isArray(card.points) ? card.points : []\n const samples: ChartSample[] = []\n for (const p of raw) {\n const price = typeof p.price === 'number' && Number.isFinite(p.price) ? p.price : undefined\n const atMs = typeof p.atUtc === 'string' ? Date.parse(p.atUtc) : NaN\n if (price === undefined || Number.isNaN(atMs)) continue\n samples.push({ atMs, price })\n }\n // projectSeries trusts sample order as the time domain (samples[0]/samples[^1] become tMin/tMax)\n // without re-checking it; every other field above is already validated, so this is the one\n // property whose violation is otherwise invisible.\n samples.sort((a, b) => a.atMs - b.atMs)\n\n const asNumber = (v: unknown): number | undefined =>\n typeof v === 'number' && Number.isFinite(v) ? v : undefined\n const opening = asNumber(card.openingPrice)\n const current = asNumber(card.currentPrice)\n const home = str(card.homeTeamName)\n const away = str(card.awayTeamName)\n const selection = joinSelection(str(card.selectionLabel), str(card.line)) ?? ''\n const bookmakerId = typeof card.bookmakerId === 'number' ? card.bookmakerId : ''\n\n return {\n id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}:${selection}:${bookmakerId}`,\n matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n marketDeveloperName: str(card.marketDeveloperName),\n selection,\n selectionLabel: str(card.selectionLabel),\n line: str(card.line),\n fixture: home && away ? `${home} vs ${away}` : undefined,\n competition: str(card.competitionName),\n bookmaker: str(card.bookmakerName),\n opening: opening !== undefined ? opening.toFixed(2) : '',\n current: current !== undefined ? current.toFixed(2) : '',\n direction:\n card.movementDirection === 'shortened' || card.movementDirection === 'drifted'\n ? card.movementDirection\n : undefined,\n windowHours: asNumber(card.windowHours) ?? 0,\n excludedCount: asNumber(card.excludedSuspendedCount) ?? 0,\n isSuspended: card.isSuspended === true,\n disclaimer: str(card.disclaimer),\n geometry: projectSeries(samples),\n observationCount: samples.length,\n pinEnabled: card.pinEnabled === true,\n matchOddsId: typeof card.matchOddsId === 'number' ? card.matchOddsId : undefined,\n }\n}\n\nexport function marketOddsRowToSlipSelection(\n vm: MarketOddsVM, row: MarketOddsRowVM, conversationId?: string,\n): SlipSelection | null {\n if (row.matchOddsId === undefined || row.oddsDecimal === undefined) return null\n const selection: SlipSelection = { matchOddsId: row.matchOddsId, matchId: vm.matchId, oddsDecimal: row.oddsDecimal }\n if (row.quotedAtUtc !== undefined) selection.quotedAtUtc = row.quotedAtUtc\n if (conversationId !== undefined) selection.conversationId = conversationId\n return selection\n}\n","import { createContext, useContext } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\nexport const EventLogContext = createContext<EventLogger | null>(null)\n\nexport function useEventLog(): EventLogger | null {\n return useContext(EventLogContext)\n}\n","import { createContext, useContext } from 'react'\nimport type { SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { SlipPickFields } from './slip'\n\nexport interface SlipAdd {\n selection: SlipSelection\n /** market developer name */\n market: string\n pick: SlipPickFields\n}\n\nexport interface SlipState {\n /** Odds the widget added in this mount. Drives the Odds tab's persistent in-slip badge. */\n added: Readonly<Record<number, true>>\n /** Odds whose button got a terminal answer in this mount. Drives the button's \"In slip\" label. */\n settled: Readonly<Record<number, true>>\n settle(matchOddsId: number): void\n /** Remembers an add the widget made, so a later host call for that odd can be reported. */\n recordAdd(add: SlipAdd): void\n}\n\nexport const SlipStateContext = createContext<SlipState | null>(null)\n\nexport function useSlipState(): SlipState | null {\n return useContext(SlipStateContext)\n}\n","import { useEffect } from 'react'\nimport type { SlipToast } from '../slip'\n\nconst DISMISS_MS = 4000\n\nexport function Toast({ toast, onDismiss }: { toast: SlipToast | null; onDismiss: () => void }): JSX.Element | null {\n useEffect(() => {\n if (!toast) return\n const timer = setTimeout(onDismiss, DISMISS_MS)\n return () => clearTimeout(timer)\n }, [toast, onDismiss])\n\n if (!toast) return null\n return (\n <div className={`ss-w-toast ss-w-toast-${toast.kind}`} role=\"status\" aria-live=\"polite\">\n {toast.text}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\n\n// One component for both card types. The market-odds row and the insight card must not drift into\n// two visual languages for the same signal, so there is exactly one place this markup exists.\nexport function OddsMovementBadge({\n previous,\n current,\n direction,\n ui,\n}: {\n previous?: string\n current: string\n direction?: 'shortened' | 'drifted'\n ui?: UiConfig\n}): JSX.Element | null {\n if (previous === undefined || direction === undefined) return null\n const directionWord =\n direction === 'shortened' ? (ui?.oddsShortened ?? 'shortened') : (ui?.oddsDrifted ?? 'drifted')\n const label =\n ui?.oddsMoved?.(previous, current, directionWord) ?? `was ${previous}, now ${current}, ${directionWord}`\n return (\n // Strikethrough is invisible to screen readers, so the whole was/now/direction sentence rides\n // on one aria-label and the visual glyphs are hidden from the accessibility tree.\n <span className=\"ss-w-move\" role=\"img\" aria-label={label}>\n <span className=\"ss-w-move-prev\" aria-hidden=\"true\">{previous}</span>\n <span className=\"ss-w-move-arrow\" aria-hidden=\"true\">{direction === 'shortened' ? '▼' : '▲'}</span>\n </span>\n )\n}\n","import { useState } from 'react'\n\nexport function initials(name?: string): string {\n return (name ?? '').trim().slice(0, 1).toUpperCase() || '?'\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a monogram (first initial) -- the design\n// wants the monogram whenever the crest is missing OR fails to load, which a background-image span\n// can't detect. onError flips to the monogram; the fixed sizing keeps the row height stable either way.\nexport function Crest({ url, name, kind }: { url?: string; name?: string; kind: 'team' | 'comp' }): JSX.Element {\n const cls = kind === 'comp' ? 'ss-w-bi-comp-logo' : 'ss-w-bi-crest'\n const [failed, setFailed] = useState(false)\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return <span className={`${cls} ss-w-bi-crest-mono`} aria-hidden=\"true\">{initials(name)}</span>\n}\n","import { useCallback, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\n// One glyph per pinIcon choice, drawn from a single silhouette path so the\n// pinned state can toggle outline (off) → filled (on) without a second asset.\n// The pin keeps its original thumbtack (scaled into a 24 box) so the default\n// look is unchanged in shape; star and bookmark are standard marks.\nconst PIN_GLYPHS: Record<'pin' | 'star' | 'bookmark', { viewBox: string; d: string; strokeWidth: number; transform?: string }> = {\n 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' },\n star: { viewBox: '0 0 24 24', strokeWidth: 2, d: 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z' },\n 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' },\n}\n\nexport function PinToggle({ pin, monitor, ui }: {\n pin: Omit<PinRef, 'key'>\n monitor: LiveMonitorController | undefined\n ui: UiConfig\n}): JSX.Element | null {\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n\n if (!monitor || !monitor.enabled) return null\n\n const key = pinKey(pin)\n const pinned = monitor.isPinned(key)\n // Match pins and odds pins are separate behaviors (2026-09-06 ruling): each toggle tracks\n // exactly its own pin, and the labels name which one this is.\n const labels = pin.kind === 'match'\n ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel }\n : { pin: ui.pinLabel, unpin: ui.unpinLabel }\n\n const onClick = (): void => {\n const result = monitor.togglePin({ ...pin, key })\n // A market/selection pin with no marketDeveloperName has no entity to report under\n // entityType 'market' -- skip the emit rather than fall back to the match id, which would\n // mislabel a match under a market entityType.\n if ((result === 'added' || result === 'removed') && (pin.kind === 'match' || pin.marketDeveloperName !== undefined)) {\n log?.log({\n name: result === 'added' ? 'pin_add' : 'pin_remove',\n entityType: pin.kind === 'match' ? 'match' : 'market',\n entityId: pin.kind === 'match' ? String(pin.matchId) : pin.marketDeveloperName,\n marketDeveloperName: pin.marketDeveloperName,\n })\n } else if (result === 'match_limit') {\n setToast({ kind: 'error', text: ui.matchLimitToast })\n } else if (result === 'market_limit') {\n setToast({ kind: 'error', text: ui.marketLimitToast })\n }\n }\n\n const glyph = PIN_GLYPHS[ui.pinIcon]\n return (\n <div className=\"ss-w-pin-wrap\">\n <button\n type=\"button\"\n className=\"ss-w-pin\"\n data-on={pinned || undefined}\n data-icon={ui.pinIcon}\n aria-pressed={pinned}\n aria-label={pinned ? labels.unpin : labels.pin}\n onClick={onClick}\n >\n <svg viewBox={glyph.viewBox} aria-hidden=\"true\">\n <path\n transform={glyph.transform}\n d={glyph.d}\n fill={pinned ? 'currentColor' : 'none'}\n stroke={pinned ? 'none' : 'currentColor'}\n strokeWidth={glyph.strokeWidth}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n","import type { PinRef } from '@sensiblestats/widget-sdk'\n\nexport const MAX_MATCH_PINS = 5\nexport const MAX_MARKET_PINS = 10\nexport type PinAddResult = 'added' | 'removed' | 'match_limit' | 'market_limit'\n\nexport type StoredPin = PinRef & { graceAt?: number; graceSession?: string }\n\nexport interface PinStore {\n pins: PinRef[]\n /** Toggle: same key present -> remove; else add if under the kind's cap. */\n toggle(pin: PinRef): PinAddResult\n remove(key: string): void\n has(key: string): boolean\n /** D7: stamps graceAt/graceSession on the given keys, only where not already stamped. */\n markGrace(keys: string[], sessionId: string, now: number): void\n}\n\nexport function pinKey(p: Omit<PinRef, 'key'>): string {\n return `${p.kind}:${p.matchId}:${p.marketDeveloperName ?? ''}:${p.selectionLabel ?? ''}:${p.line ?? ''}:${p.matchOddsId ?? ''}`\n}\n\nexport const GRACE_MS = 4 * 60 * 60 * 1000\n\n/** D7: drop pins whose grace started in a PREVIOUS session (next widget open) or > 4h ago. */\nexport function pruneExpired(pins: StoredPin[], sessionId: string, now: number): StoredPin[] {\n return pins.filter((p) => p.graceAt === undefined || (p.graceSession === sessionId && now - p.graceAt <= GRACE_MS))\n}\n\ninterface StoredPins {\n v: 1\n pins: StoredPin[]\n}\n\nfunction safeRead(storageKey: string): StoredPin[] {\n try {\n const raw = window.localStorage.getItem(storageKey)\n if (!raw) return []\n const parsed = JSON.parse(raw) as StoredPins\n return parsed.v === 1 && Array.isArray(parsed.pins) ? parsed.pins : []\n } catch {\n return []\n }\n}\n\nfunction safeWrite(storageKey: string, pins: StoredPin[]): void {\n try {\n window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, pins } satisfies StoredPins))\n } catch {\n // storage blocked -> in-memory only for the session (spec, degradation rules)\n }\n}\n\nexport function loadPins(storageKey: string): PinRef[] {\n return safeRead(storageKey)\n}\n\nexport function createPinStore(storageKey: string, sessionId: string, onChange: (pins: PinRef[]) => void): PinStore {\n // D7 grace: pins whose subject finished in a previous session (or >4h ago) are dropped on open.\n let pins = pruneExpired(safeRead(storageKey), sessionId, Date.now())\n\n const commit = (next: StoredPin[]) => {\n pins = next\n safeWrite(storageKey, pins)\n onChange(pins)\n }\n commit(pins)\n\n return {\n get pins() {\n return pins\n },\n has: (key) => pins.some((p) => p.key === key),\n remove: (key) => commit(pins.filter((p) => p.key !== key)),\n markGrace(keys, session, now) {\n commit(\n pins.map((p) => (keys.includes(p.key) && p.graceAt === undefined ? { ...p, graceAt: now, graceSession: session } : p)),\n )\n },\n toggle(pin) {\n if (pins.some((p) => p.key === pin.key)) {\n commit(pins.filter((p) => p.key !== pin.key))\n return 'removed'\n }\n const matchCount = pins.filter((p) => p.kind === 'match').length\n const marketCount = pins.length - matchCount\n if (pin.kind === 'match' && matchCount >= MAX_MATCH_PINS) return 'match_limit'\n if (pin.kind !== 'match' && marketCount >= MAX_MARKET_PINS) return 'market_limit'\n commit([...pins, pin])\n return 'added'\n },\n }\n}\n","import { useCallback, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { joinSelection } from '../model'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\ntype HistoryPin = Omit<PinRef, 'key' | 'kind' | 'withHistory'>\n\n// D27: in place of an odds pin, a price that moved opens its history in the Odds tab. The tap adds\n// the selection with its history, or finds it already there, and switches tab. It never removes\n// an entry: unpinning lives in the Odds tab.\nexport function PriceHistoryButton({ selection, monitor, ui }: {\n selection: HistoryPin\n monitor: LiveMonitorController | undefined\n ui: UiConfig\n}): JSX.Element | null {\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n const log = useEventLog()\n\n if (!monitor || !monitor.enabled) return null\n // The name carries the selection: two moved rows on one card must not read as two identical buttons.\n const name = joinSelection(selection.selectionLabel ?? undefined, selection.line ?? undefined)\n const label = name ? `${ui.priceHistoryLabel}, ${name}` : ui.priceHistoryLabel\n\n const onClick = (): void => {\n const pin = { ...selection, kind: 'selection' as const, withHistory: true }\n const key = pinKey(pin)\n if (!monitor.isPinned(key)) {\n const result = monitor.togglePin({ ...pin, key })\n if (result === 'market_limit' || result === 'match_limit') {\n setToast({ kind: 'error', text: result === 'market_limit' ? ui.marketLimitToast : ui.matchLimitToast })\n return\n }\n // Logged as the market pin it is, so the market signal behind \"Your market\" keeps its input.\n if (result === 'added' && pin.marketDeveloperName !== undefined) {\n log?.log({ name: 'pin_add', entityType: 'market', entityId: pin.marketDeveloperName, marketDeveloperName: pin.marketDeveloperName })\n }\n }\n monitor.setActiveTab('odds')\n }\n\n return (\n <div className=\"ss-w-pin-wrap\">\n <button type=\"button\" className=\"ss-w-hist\" aria-label={label} title={label} onClick={onClick}>\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 13.5h12M3 10.5l3.2-3.4 2.6 2.2L13 4.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n <Toast toast={toast} onDismiss={dismiss} />\n </div>\n )\n}\n","export interface WidgetHost {\n /** The user removed this selection from the operator's slip. */\n slipRemoved(selection: { matchOddsId: number }): void\n /** The user placed a bet. Pass every leg; the widget reports only the ones it added. */\n betPlaced(bet: { selections: ReadonlyArray<{ matchOddsId: number }> }): void\n /** The user opened this match's page on the operator's site. */\n matchOpened(match: { matchId: number }): void\n}\n\nexport type HostCommand =\n | { kind: 'slipRemoved'; matchOddsId: number }\n | { kind: 'betPlaced'; matchOddsIds: number[] }\n | { kind: 'matchOpened'; matchId: number }\n\nexport type HostSink = (command: HostCommand) => void\n\nexport const HOST_QUEUE_MAX = 20\n\ninterface HostState {\n queue: HostCommand[]\n sink: HostSink | null\n}\n\n// Keyed by the object createWidgetHost() returned. WidgetHost is an exported interface, so an\n// operator can pass an object it built by hand; that object has no entry here and stays inert.\nconst STATES = new WeakMap<WidgetHost, HostState>()\n\nexport function isValidId(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value > 0\n}\n\n/**\n * The operator's handle for telling the widget what happened on its side. Create it once at\n * module scope and pass it as the `host` prop. Calls made while no widget is mounted are queued\n * and replayed when one attaches. No method ever throws, and creating a host touches no browser\n * API, so a module-scope host is safe under server rendering.\n */\nexport function createWidgetHost(): WidgetHost {\n const state: HostState = { queue: [], sink: null }\n\n const dispatch = (command: HostCommand): void => {\n if (state.sink) {\n state.sink(command)\n return\n }\n state.queue.push(command)\n if (state.queue.length > HOST_QUEUE_MAX) state.queue.shift()\n }\n\n const host: WidgetHost = {\n // Every body sits in a try: a missing argument, a malformed one and a widget bug behind the\n // sink all end the same way, with the call ignored.\n slipRemoved(selection) {\n try {\n const id: unknown = selection.matchOddsId\n if (isValidId(id)) dispatch({ kind: 'slipRemoved', matchOddsId: id })\n } catch {\n // a host method never throws into operator code\n }\n },\n betPlaced(bet) {\n try {\n const legs: unknown = bet.selections\n if (!Array.isArray(legs)) return\n const ids: number[] = []\n for (const leg of legs as ReadonlyArray<{ matchOddsId?: unknown } | null | undefined>) {\n const id = leg?.matchOddsId\n if (isValidId(id) && !ids.includes(id)) ids.push(id)\n }\n if (ids.length > 0) dispatch({ kind: 'betPlaced', matchOddsIds: ids })\n } catch {\n // a host method never throws into operator code\n }\n },\n matchOpened(match) {\n try {\n const id: unknown = match.matchId\n if (isValidId(id)) dispatch({ kind: 'matchOpened', matchId: id })\n } catch {\n // a host method never throws into operator code\n }\n },\n }\n\n STATES.set(host, state)\n return host\n}\n\n/**\n * Internal: connects a mounted widget to a host, replays what was queued, and returns the detach.\n * Not exported from the package.\n */\nexport function attachHost(host: WidgetHost, sink: HostSink): () => void {\n const state = STATES.get(host)\n if (!state) return () => {}\n state.sink = sink\n const queued = state.queue\n state.queue = []\n for (const command of queued) {\n try {\n sink(command)\n } catch {\n // one failing command must not drop the ones queued behind it\n }\n }\n return () => {\n // A second widget may have attached since; only the current owner clears the slot.\n if (state.sink === sink) state.sink = null\n }\n}\n","import { createContext, useContext } from 'react'\n\nexport interface MatchLinkValue {\n /** Reports the tap, calls the operator's onOpenMatch, and closes the panel on a phone. */\n open(matchId: number): void\n /** Accessible name for the link, in the widget's language. */\n label(home?: string, away?: string): string\n}\n\n/** Present only when the operator passed `onOpenMatch`. Without it nothing renders as a link. */\nexport const MatchLinkContext = createContext<MatchLinkValue | null>(null)\n\nexport function useMatchLink(): MatchLinkValue | null {\n return useContext(MatchLinkContext)\n}\n","import type { ReactNode } from 'react'\nimport { isValidId } from '../host'\nimport { useMatchLink } from '../matchLinkContext'\n\n/**\n * Wraps a card's team names. With no `onOpenMatch` from the operator, or no usable match id, it\n * renders the element the card rendered before, class and children unchanged. Otherwise it is a\n * button that keeps that class for layout and opens the operator's match page.\n */\nexport function MatchLink({ matchId, home, away, detail, className, as: Tag = 'span', children }: {\n matchId: number\n home?: string | null\n away?: string | null\n /** What the link shows besides the names, such as the score. The label replaces the button's\n * content for a screen reader, so anything left out of it is never announced. */\n detail?: string\n className: string\n as?: 'span' | 'div'\n children: ReactNode\n}): JSX.Element {\n const link = useMatchLink()\n if (!link || !isValidId(matchId)) return <Tag className={className}>{children}</Tag>\n const label = link.label(home ?? undefined, away ?? undefined)\n return (\n <button\n type=\"button\"\n className={`${className} ss-w-matchlink`}\n aria-label={detail ? `${label}, ${detail}` : label}\n onClick={() => link.open(matchId)}\n >\n {children}\n </button>\n )\n}\n","import type { InsightVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { AddToSlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\nimport { MatchLink } from './MatchLink'\n\n// The reason-to-bet fact sentence, shown in full: the card carries no supporting stat rows and\n// nothing to expand.\nfunction ReasonStrip({ it }: { it: InsightVM }): JSX.Element | null {\n if (!it.text) return null\n return (\n <div className=\"ss-w-bi-reason\">\n <span className=\"ss-w-bi-chart\" aria-hidden=\"true\" />\n <p className=\"ss-w-bi-text\">{it.text}</p>\n </div>\n )\n}\n\n// Renders the fixture as the card's hero: the named team pair when present, else the prose\n// fixture, else the competition (the fallback that becomes the header hero when there is no\n// fixture at all). On a fixture card this fills its own line; the competition rides the meta line\n// above it (u350 two-tier).\nfunction CardFixture({ it }: { it: InsightVM }): JSX.Element | null {\n if (it.homeTeamName && it.awayTeamName) {\n return (\n <>\n <Crest kind=\"team\" url={it.homeCrest} name={it.homeTeamName} />\n <span className=\"ss-w-bi-team\">{it.homeTeamName}</span>\n <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n <span className=\"ss-w-bi-team\">{it.awayTeamName}</span>\n <Crest kind=\"team\" url={it.awayCrest} name={it.awayTeamName} />\n </>\n )\n }\n if (it.fixture) return <span className=\"ss-w-bi-fixture-txt\">{it.fixture}</span>\n if (it.competition) {\n return (\n <>\n <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n <span className=\"ss-w-bi-comp\">{it.competition}</span>\n </>\n )\n }\n return null\n}\n\nfunction InsightCard(\n { it, ui, slip, monitor }: { it: InsightVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element {\n const live = it.isLive || it.phase === 'live'\n // Prefer the server-rendered chip (operator timezone + language); fall back to browser-zone\n // formatting of the raw instant for older servers that don't send a label.\n const kickoffFallback = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : undefined\n const kickoff = it.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName\n // A fixture (team pair or prose string) is the card's hero and gets its own full-width line so\n // long club names stop truncating; the competition, kickoff and match pin sit on a quieter meta\n // line above it. Only when there is no fixture does the competition itself become the hero on a\n // single header line (u350 two-tier).\n const leftIsFixture = hasNamedTeams || !!it.fixture\n const showPin = !!monitor && it.pinEnabled\n const showHeader = leftIsFixture || !!it.competition || live || !!kickoff || showPin\n // live badge + kickoff + match pin: shared by the fixture card's meta line and the\n // competition-hero card's header-right, so the trio renders identically on both. The pin here\n // pins the MATCH; a moved price opens its history from the pick row below (D27).\n const headerControls = (\n <>\n {live ? (\n <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n ) : null}\n {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n {showPin && ui ? (\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: it.matchId }} />\n ) : null}\n </>\n )\n return (\n <div className=\"ss-w-binsight\">\n {showHeader ? (\n leftIsFixture ? (\n <div className=\"ss-w-bi-head\">\n {(it.competition || live || kickoff || showPin) ? (\n <div className=\"ss-w-bi-meta\">\n <span className=\"ss-w-bi-meta-left\">\n {it.competition ? (\n <>\n <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n <span className=\"ss-w-bi-comp\">{it.competition}</span>\n </>\n ) : null}\n </span>\n <span className=\"ss-w-bi-meta-right\">{headerControls}</span>\n </div>\n ) : null}\n <MatchLink as=\"div\" matchId={it.matchId} home={it.homeTeamName} away={it.awayTeamName} className=\"ss-w-bi-fixture-line\">\n <CardFixture it={it} />\n </MatchLink>\n </div>\n ) : (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-left\"><CardFixture it={it} /></span>\n <span className=\"ss-w-bi-header-right\">{headerControls}</span>\n </div>\n )\n ) : null}\n <div className=\"ss-w-bi-action\">\n {it.market ? <span className=\"ss-w-bi-market\">{it.market}</span> : null}\n <div className=\"ss-w-bi-pick-row\">\n {it.selection ? <span className=\"ss-w-bi-sel\">{it.selection}</span> : null}\n {it.odds ? (\n <span className=\"ss-w-bi-odds\">\n <b>{it.odds}</b>\n <OddsMovementBadge previous={it.previousOdds} current={it.odds} direction={it.movementDirection} ui={ui} />\n {it.bookmaker ? <span className=\"ss-w-bi-book\">{it.bookmaker}</span> : null}\n </span>\n ) : null}\n {it.odds && showPin && ui && it.previousOdds ? (\n <PriceHistoryButton\n ui={ui}\n monitor={monitor}\n selection={{ matchId: it.matchId, marketDeveloperName: it.marketDeveloperName, selectionLabel: it.selectionLabel, line: it.line, matchOddsId: it.matchOddsId }}\n />\n ) : null}\n <AddToSlipButton it={it} slip={slip} ui={ui} />\n </div>\n </div>\n {it.isMarketFloor ? (\n <span className=\"ss-w-bi-floor\">{ui?.marketFloorLabel ?? 'Market price · not a value pick'}</span>\n ) : null}\n <ReasonStrip it={it} />\n {it.disclaimer ? <p className=\"ss-w-bi-disc\">{it.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function BettingInsightList(\n { insights, ui, slip, monitor }:\n { insights: InsightVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element | null {\n if (!insights || insights.length === 0) return null\n return (\n <div className=\"ss-w-binsights\">\n {insights.map((it) => <InsightCard key={it.id} it={it} ui={ui} slip={slip} monitor={monitor} />)}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { MarketOddsVM, MarketOddsRowVM } from '../model'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { SlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\nimport { MatchLink } from './MatchLink'\n\nfunction OddsRow(\n { vm, row, ui, slip, inSlipIds, history }:\n { vm: MarketOddsVM; row: MarketOddsRowVM; ui?: UiConfig; slip: SlipHandlerProps; inSlipIds?: Record<number, true>; history?: LiveMonitorController },\n): JSX.Element {\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null\n // D5 persistent in-slip badge: keyed by matchOddsId in the widget's slip state (`added`, set by\n // StatsWidget's onAddToSlip wrap), NOT the button's own \"In slip\" mark -- the two follow\n // different rules (a duplicate answer marks the button and not the badge). Passed as a plain\n // id map (not the full LiveMonitorController) so callers can surface the badge without also\n // turning on this list's OWN pin-toggle header (OddsPanel already owns that pin via the\n // market snapshot's context line -- a second, independently-keyed toggle here could drift out\n // of sync with it).\n const inSlip = !!inSlipIds && row.matchOddsId != null && !!inSlipIds[row.matchOddsId]\n return (\n <div className=\"ss-w-mo-row\">\n <span className=\"ss-w-mo-sel\">{row.selection}</span>\n <OddsMovementBadge previous={row.previousOdds} current={row.odds} direction={row.movementDirection} ui={ui} />\n <span className=\"ss-w-mo-price\">{row.odds}</span>\n {history && ui && row.previousOdds ? (\n <PriceHistoryButton\n ui={ui}\n monitor={history}\n selection={{ matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, selectionLabel: row.selectionLabel, line: row.line, matchOddsId: row.matchOddsId }}\n />\n ) : null}\n {inSlip && ui ? <span className=\"ss-w-mon-inslip\">✓ {ui.inSlipLabel}</span> : null}\n <SlipButton selection={selection} shownOdds={row.odds} marketDeveloperName={vm.marketDeveloperName} selectionLabel={row.selectionLabel} line={row.line} slip={slip} ui={ui} />\n </div>\n )\n}\n\nfunction MarketOddsCard(\n { vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n { vm: MarketOddsVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element {\n const [open, setOpen] = useState(false)\n const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName\n const showPin = !!monitor && vm.pinEnabled\n // Chat path (no pinRef): the header pin is the MATCH pin, and a price that moved opens its\n // history (D27). The OddsPanel path passes pinRef and keeps its single market pin in the header;\n // the Live tab accordion (hideHeader) has neither.\n const history = showPin && !pinRef && !hideHeader ? monitor : undefined\n const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin\n return (\n <div className={hideHeader ? 'ss-w-mocard ss-w-mocard--bare' : 'ss-w-mocard'}>\n {!hideHeader && (\n <>\n {showHeader ? (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-left\">\n {vm.competition ? (\n <>\n <Crest kind=\"comp\" url={vm.competitionCrest} name={vm.competition} />\n <span className=\"ss-w-bi-comp\">{vm.competition}</span>\n </>\n ) : null}\n </span>\n <span className=\"ss-w-bi-header-right\">\n {vm.isLive ? (\n <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n ) : null}\n {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n {showPin && ui ? (\n <PinToggle\n ui={ui}\n monitor={monitor}\n pin={pinRef ?? { kind: 'match', matchId: vm.matchId }}\n />\n ) : null}\n </span>\n </div>\n ) : null}\n {(hasNamedTeams || vm.fixture || vm.market) ? (\n <div className=\"ss-w-mo-sub\">\n {hasNamedTeams ? (\n <MatchLink as=\"div\" matchId={vm.matchId} home={vm.homeTeamName} away={vm.awayTeamName} className=\"ss-w-bi-fixture\">\n <Crest kind=\"team\" url={vm.homeCrest} name={vm.homeTeamName} />\n <span className=\"ss-w-bi-team\">{vm.homeTeamName}</span>\n <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n <span className=\"ss-w-bi-team\">{vm.awayTeamName}</span>\n <Crest kind=\"team\" url={vm.awayCrest} name={vm.awayTeamName} />\n </MatchLink>\n ) : vm.fixture ? <span className=\"ss-w-mo-teams\">{vm.fixture}</span> : null}\n {vm.market ? (\n <div className=\"ss-w-mo-market-row\">\n <span className=\"ss-w-mo-market\">{vm.market}</span>\n {vm.tag === 'your_market' ? <span className=\"ss-w-mo-tag\">{ui?.yourMarketTag ?? 'Your market'}</span> : null}\n </div>\n ) : null}\n </div>\n ) : null}\n </>\n )}\n {vm.statText && !hideHeader && !pinRef ? <div className=\"ss-w-mo-stat\">{vm.statText}</div> : null}\n <div className=\"ss-w-mo-rows\">\n {vm.mainRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} />)}\n {open ? vm.moreRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} />) : null}\n </div>\n {vm.moreRows.length > 0 ? (\n <button type=\"button\" className=\"ss-w-mo-more\" aria-expanded={open} onClick={() => setOpen((v) => !v)}>\n <span>{open ? ui?.hideLines ?? 'Hide lines' : `${ui?.moreLines ?? 'More lines'} (${vm.moreRows.length})`}</span>\n <span className={`ss-w-mo-more-chev${open ? ' ss-w-mo-more-chev-up' : ''}`} aria-hidden=\"true\" />\n </button>\n ) : null}\n {vm.bookmaker ? (\n <div className=\"ss-w-mo-foot\">\n <span>{vm.bookmaker}</span>\n </div>\n ) : null}\n {vm.disclaimer ? <p className=\"ss-w-bi-disc\">{vm.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function MarketOddsCardList(\n { cards, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n { cards: MarketOddsVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-mocards\">\n {cards.map((vm) => (\n <MarketOddsCard key={vm.id} vm={vm} ui={ui} slip={slip} monitor={monitor} inSlipIds={inSlipIds} hideHeader={hideHeader} pinRef={pinRef} />\n ))}\n </div>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { Ref } from 'react'\nimport type { CompactCellVM, CompactListVM, CompactRowVM } from '../compactList'\nimport { COMPACT_PAGE } from '../compactList'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { MatchLink } from './MatchLink'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PinToggle } from './PinToggle'\n\nfunction Cell({ row, cell, ui, slip }: { row: CompactRowVM; cell: CompactCellVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const vm = row.card\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, cell.row, slip.conversationId) : null\n const name = `${vm.homeTeamName ?? ''} ${vm.awayTeamName ?? ''}, ${cell.row.selection} ${cell.row.odds}`\n const button = (\n <SlipButton\n selection={selection}\n shownOdds={cell.row.odds}\n marketDeveloperName={vm.marketDeveloperName}\n selectionLabel={cell.row.selectionLabel}\n line={cell.row.line}\n slip={slip}\n ui={ui}\n price={{ label: cell.label, ariaLabel: name }}\n />\n )\n return (\n // A third of the price column fits four characters at the row's size: 13.00 steps down a size\n // and 101.00 two.\n <span className={['ss-w-mol-cell', cell.row.odds.length >= 5 && 'ss-w-mol-cell--wide', cell.row.odds.length >= 6 && 'ss-w-mol-cell--wider'].filter(Boolean).join(' ')}>\n {selection && slip.onAddToSlip && ui ? button : (\n <span className=\"ss-w-mol-price\">\n {cell.label ? <span className=\"ss-w-mol-lab\" aria-hidden=\"true\">{cell.label}</span> : null}\n <span aria-hidden=\"true\">{cell.row.odds}</span>\n <span className=\"ss-w-vh\">{name}</span>\n </span>\n )}\n <OddsMovementBadge previous={cell.row.previousOdds} current={cell.row.odds} direction={cell.row.movementDirection} ui={ui} />\n </span>\n )\n}\n\nfunction Row({ row, columns, ui, slip, monitor, rowRef }: {\n row: CompactRowVM; columns: number; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n rowRef?: Ref<HTMLDivElement>\n}): JSX.Element {\n const vm = row.card\n const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const when = vm.isLive\n ? ui?.liveLabel ?? 'Live'\n : vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n return (\n <div className=\"ss-w-mol-row\" ref={rowRef} tabIndex={rowRef ? -1 : undefined}>\n <MatchLink as=\"div\" matchId={vm.matchId} home={vm.homeTeamName} away={vm.awayTeamName} className=\"ss-w-mol-fx\">\n <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.homeCrest} name={vm.homeTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.homeTeamName}</span></span>\n <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.awayCrest} name={vm.awayTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.awayTeamName}</span></span>\n {row.otherMarket ? <span className=\"ss-w-mol-mkt\">{row.otherMarket}</span> : null}\n </MatchLink>\n <span className=\"ss-w-mol-cells\" style={{ gridTemplateColumns: `repeat(${row.cells.length || columns}, minmax(0, 1fr))` }}>\n {row.cells.map((cell) => <Cell key={cell.row.key} row={row} cell={cell} ui={ui} slip={slip} />)}\n </span>\n <span className={vm.isLive ? 'ss-w-mol-side ss-w-mol-side--live' : 'ss-w-mol-side'}>\n {when ? <span className=\"ss-w-mol-when\">{when}</span> : null}\n {monitor && vm.pinEnabled && ui ? <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: vm.matchId }} /> : null}\n </span>\n </div>\n )\n}\n\nexport function CompactOddsList({ list, ui, slip, monitor }: {\n list: CompactListVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n}): JSX.Element {\n const [shown, setShown] = useState(COMPACT_PAGE)\n const hidden = list.rowCount - shown\n // \"Show more\" can unmount itself; focus goes to the first row it revealed, not to the page body.\n const [focusIndex, setFocusIndex] = useState<number | null>(null)\n const focusRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (focusIndex !== null) focusRef.current?.focus()\n }, [focusIndex])\n let left = shown\n let index = 0\n return (\n <div className=\"ss-w-mol\">\n <div className=\"ss-w-mol-head\">\n <span className=\"ss-w-mol-market\">{list.market}</span>\n <span className=\"ss-w-mol-cols\" aria-hidden=\"true\" style={{ gridTemplateColumns: `repeat(${list.columns.length}, minmax(0, 1fr))` }}>\n {list.columns.map((c, i) => <span key={`${c}:${i}`} className=\"ss-w-mol-col\">{c}</span>)}\n </span>\n <span className=\"ss-w-mol-side\" aria-hidden=\"true\" />\n </div>\n {list.groups.map((group, gi) => {\n const rows = group.rows.slice(0, Math.max(0, left))\n left -= rows.length\n if (rows.length === 0) return null\n return (\n <div className=\"ss-w-mol-group\" key={`${group.competition ?? ''}:${gi}`}>\n {group.competition ? (\n <div className=\"ss-w-mol-comp\">\n <Crest kind=\"comp\" url={group.competitionCrest} name={group.competition} />\n <span>{group.competition}</span>\n </div>\n ) : null}\n {rows.map((row) => {\n const at = index++\n return <Row key={row.card.id} row={row} columns={list.columns.length} ui={ui} slip={slip} monitor={monitor} rowRef={at === focusIndex ? focusRef : undefined} />\n })}\n </div>\n )\n })}\n {hidden > 0 ? (\n <button type=\"button\" className=\"ss-w-mo-more\" onClick={() => { setFocusIndex(shown); setShown((n) => n + COMPACT_PAGE) }}>\n <span>{ui?.showMore ? ui.showMore(Math.min(COMPACT_PAGE, hidden)) : `Show ${Math.min(COMPACT_PAGE, hidden)} more`}</span>\n <span className=\"ss-w-mo-more-chev\" aria-hidden=\"true\" />\n </button>\n ) : null}\n {list.bookmaker ? <div className=\"ss-w-mo-foot\"><span>{list.bookmaker}</span></div> : null}\n {list.disclaimer ? <p className=\"ss-w-bi-disc\">{list.disclaimer}</p> : null}\n </div>\n )\n}\n","import type { MarketOddsRowVM, MarketOddsVM } from './model'\n\n/** One price in a compact list row. `label` is set when the column head does not say what it is. */\nexport interface CompactCellVM {\n row: MarketOddsRowVM\n label?: string\n}\n\nexport interface CompactRowVM {\n card: MarketOddsVM\n /** The row's market name, set when it differs from the list's market. */\n otherMarket?: string\n cells: CompactCellVM[]\n}\n\nexport interface CompactGroupVM {\n competition?: string\n competitionCrest?: string\n rows: CompactRowVM[]\n}\n\nexport interface CompactListVM {\n market: string\n columns: string[]\n groups: CompactGroupVM[]\n rowCount: number\n bookmaker?: string\n disclaimer?: string\n}\n\nexport const COMPACT_MIN_CARDS = 3\n\n/** A row holds one to three prices in the price column. A market with more, such as correct score,\n * or a card with every price suspended, keeps the stack. */\nconst COMPACT_MAX_PRICES = 3\n\n/** Match Result heads are the betting convention, 1 X 2, in every language: \"Beraberlik\" and\n * \"Deplasman\" do not fit a price column. */\nconst RESULT_MARKET = 'FULLTIME_RESULT'\nconst RESULT_HEADS = ['1', 'X', '2']\nexport const COMPACT_PAGE = 5\n\n/** The list's market: the one most cards carry, the first card's on a tie. */\nfunction referenceMarket(cards: MarketOddsVM[]): string | undefined {\n const counts = new Map<string | undefined, number>()\n for (const c of cards) counts.set(c.marketDeveloperName, (counts.get(c.marketDeveloperName) ?? 0) + 1)\n let best = cards[0]!.marketDeveloperName\n for (const c of cards) {\n if ((counts.get(c.marketDeveloperName) ?? 0) > (counts.get(best) ?? 0)) best = c.marketDeveloperName\n }\n return best\n}\n\n/**\n * D16: three or more price cards on one turn, one per fixture, draw as one compact list. Returns\n * null for anything else, which keeps the stack: fewer cards, or two cards of the same fixture.\n * A row of another market than the list's names its market and labels its own prices (R19, Ertu\n * 2026-10-03).\n */\nexport function toCompactList(cards: MarketOddsVM[]): CompactListVM | null {\n if (cards.length < COMPACT_MIN_CARDS) return null\n if (new Set(cards.map((c) => c.matchId)).size !== cards.length) return null\n if (cards.some((c) => c.mainRows.length === 0 || c.mainRows.length > COMPACT_MAX_PRICES)) return null\n\n const market = referenceMarket(cards)\n // The heads come from the card of the list's market with the most open prices: a suspended price\n // on the first card must not drop a column for every row.\n const head = cards\n .filter((c) => c.marketDeveloperName === market)\n .reduce((best, c) => (c.mainRows.length > best.mainRows.length ? c : best))\n const labels = head.mainRows.map((r) => r.selectionLabel ?? r.selection)\n const columns = market === RESULT_MARKET && labels.length === RESULT_HEADS.length ? RESULT_HEADS : labels\n\n const toRow = (card: MarketOddsVM): CompactRowVM => {\n const sameMarket = card.marketDeveloperName === market\n const own = card.mainRows.map((r) => r.selectionLabel ?? r.selection)\n const aligned = sameMarket && own.length === labels.length && own.every((l, i) => l === labels[i])\n return {\n card,\n otherMarket: sameMarket ? undefined : card.market,\n cells: card.mainRows.map((row) => ({\n row,\n label: !aligned ? row.selection : row.line !== head.mainLine && row.line ? row.line : undefined,\n })),\n }\n }\n\n const groups: CompactGroupVM[] = []\n for (const card of cards) {\n let group = groups.find((g) => g.competition === card.competition)\n if (!group) {\n group = { competition: card.competition, competitionCrest: card.competitionCrest, rows: [] }\n groups.push(group)\n }\n group.rows.push(toRow(card))\n }\n\n return {\n market: head.market,\n columns,\n groups,\n rowCount: cards.length,\n bookmaker: cards.map((c) => c.bookmaker).find(Boolean),\n disclaimer: cards.map((c) => c.disclaimer).find(Boolean),\n }\n}\n","import type { UiConfig } from '../config'\nimport type { OddsMovementVM } from '../model'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { CHART_VIEW_H, CHART_VIEW_W } from '../chart'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PriceHistoryButton } from './PriceHistoryButton'\n\nfunction directionWord(vm: OddsMovementVM, ui?: UiConfig): string {\n if (vm.direction === 'shortened') return ui?.oddsShortened ?? 'shortened'\n if (vm.direction === 'drifted') return ui?.oddsDrifted ?? 'drifted'\n return ''\n}\n\nfunction OddsMovementCard(\n { vm, ui, monitor }: { vm: OddsMovementVM; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element {\n const word = directionWord(vm, ui)\n const drift = word ? `, ${word}` : ''\n const aria = ui?.chartAria\n ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours)\n : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`\n const showPin = !!monitor && vm.pinEnabled\n\n return (\n <div className=\"ss-w-omcard\">\n <div className=\"ss-w-om-head\">\n <span className=\"ss-w-om-market\">{vm.market}</span>\n <span className=\"ss-w-om-tag\">{ui?.priceMovement ?? 'Price movement'}</span>\n {showPin && ui ? (\n <PriceHistoryButton\n ui={ui}\n monitor={monitor}\n selection={{\n matchId: vm.matchId,\n marketDeveloperName: vm.marketDeveloperName,\n selectionLabel: vm.selectionLabel,\n line: vm.line,\n matchOddsId: vm.matchOddsId,\n }}\n />\n ) : null}\n </div>\n {vm.fixture ? (\n <div className=\"ss-w-om-fixture\">\n <span>{vm.fixture}</span>\n {vm.competition ? <span className=\"ss-w-om-comp\">{vm.competition}</span> : null}\n </div>\n ) : null}\n <div className=\"ss-w-om-sel\">{vm.selection}</div>\n <OddsMovementBadge previous={vm.opening} current={vm.current} direction={vm.direction} ui={ui} />\n\n {vm.geometry === null ? (\n <div className=\"ss-w-om-empty\">\n {vm.observationCount === 1\n ? ui?.singlePricePoint ?? 'Only one price recorded so far for this selection.'\n : ui?.notEnoughHistory ?? 'No price history recorded yet for this selection.'}\n </div>\n ) : (\n <svg\n className=\"ss-w-om-chart\"\n viewBox={vm.geometry.viewBox}\n width=\"100%\"\n role=\"img\"\n aria-label={aria}\n >\n {vm.geometry.gridlines.map((g) => (\n <g key={g.price}>\n <line className=\"ss-w-om-grid\" x1={40} y1={g.y} x2={CHART_VIEW_W - 8} y2={g.y} />\n <text className=\"ss-w-om-ylab\" x={34} y={g.y + 3} textAnchor=\"end\">{g.price.toFixed(2)}</text>\n </g>\n ))}\n <path className=\"ss-w-om-line\" d={vm.geometry.path} fill=\"none\" />\n {vm.geometry.markers.map((m, i) => (\n <circle key={i} className=\"ss-w-om-dot\" cx={m.x} cy={m.y} r={2.5} />\n ))}\n {ui?.chartTimeLabel ? (\n <>\n <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8} textAnchor=\"start\">\n {ui.chartTimeLabel(vm.geometry.startMs)}\n </text>\n <text className=\"ss-w-om-xlab\" x={CHART_VIEW_W - 8} y={CHART_VIEW_H - 8} textAnchor=\"end\">\n {ui.chartTimeLabel(vm.geometry.endMs)}\n </text>\n </>\n ) : (\n <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8}>\n {ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h`}\n </text>\n )}\n </svg>\n )}\n\n <div className=\"ss-w-om-foot\">\n <span>{ui?.openingLabel ?? 'Opening'} <b>{vm.opening}</b></span>\n <span>{ui?.currentLabel ?? 'Current'} <b>{vm.current}</b></span>\n </div>\n {vm.bookmaker ? (\n <div className=\"ss-w-om-foot\">\n <span>{vm.bookmaker}</span>\n </div>\n ) : null}\n {vm.excludedCount > 0 ? (\n <div className=\"ss-w-om-excl\">\n {ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.`}\n </div>\n ) : null}\n {vm.isSuspended ? (\n <div className=\"ss-w-om-susp\">{ui?.selectionSuspended ?? 'This selection is not currently available to bet.'}</div>\n ) : null}\n {vm.disclaimer ? <div className=\"ss-w-om-disc\">{vm.disclaimer}</div> : null}\n </div>\n )\n}\n\nexport function OddsMovementCardList(\n { cards, ui, monitor }: { cards: OddsMovementVM[]; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-omcards\">\n {cards.map((vm) => <OddsMovementCard key={vm.id} vm={vm} ui={ui} monitor={monitor} />)}\n </div>\n )\n}\n","import type { ActionVM } from '../model'\n\nexport function ActionButtons({ actions, loading, disabled, onAct }: { actions: ActionVM[]; loading: boolean; disabled?: boolean; onAct: (action: ActionVM) => void }): JSX.Element | null {\n if (actions.length === 0 && !loading) return null\n return (\n <div className=\"ss-w-actions\">\n {actions.map((a, i) => (\n <button key={`${a.label}-${i}`} type=\"button\" className=\"ss-w-abtn\" disabled={disabled} onClick={() => onAct(a)}>{a.label}</button>\n ))}\n {actions.length === 0 && loading ? (\n <>\n <span className=\"ss-w-abtn-shimmer\" />\n <span className=\"ss-w-abtn-shimmer\" />\n </>\n ) : null}\n </div>\n )\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport { DashboardIcon, ChevronIcon } from '../Icons'\n\n// The server payload caps crests at 3 (spec D2); slicing here is a defensive floor, not a\n// server-side promise, since a badge + crest row this wide already competes for the same\n// space the title needs.\nconst MAX_CRESTS = 3\n\n// The server appends the price as a last \" · @1.85\" segment; it is lifted out so the hero can show\n// it as a price rather than as the tail of a sentence.\nconst ODDS_TAIL = /\\s*·\\s*@(\\d+(?:\\.\\d+)?)\\s*$/\n\nfunction splitOdds(subtitle: string): { text: string; odds?: string } {\n const m = ODDS_TAIL.exec(subtitle)\n return m ? { text: subtitle.slice(0, m.index), odds: m[1] } : { text: subtitle }\n}\n\nfunction HeroTile({ tile, onTap, oddsLabel }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel: string }): JSX.Element {\n const crests = (tile.imageUrls ?? []).filter(Boolean).slice(0, 2)\n const sub = tile.subtitle ? splitOdds(tile.subtitle) : null\n return (\n <button type=\"button\" className=\"ss-w-dash-tile ss-w-dash-tile--full ss-w-dash-hero\" onClick={onTap}>\n <span className=\"ss-w-dash-hero-top\">\n {tile.badgeText ? <span className=\"ss-w-dash-hero-badge\">{tile.badgeText}</span> : null}\n {sub?.odds ? <span className=\"ss-w-dash-hero-price\"><span className=\"ss-g-sr\">{oddsLabel} </span>{sub.odds}</span> : null}\n <span className=\"ss-w-dash-hero-chevron\"><ChevronIcon /></span>\n </span>\n <span className=\"ss-w-dash-hero-main\">\n <span className=\"ss-w-dash-hero-visual\" aria-hidden=\"true\">\n {crests.length > 0\n ? crests.map((url, i) => (\n <span key={`${url}-${i}`} className=\"ss-w-dash-hero-crest\" style={{ backgroundImage: `url(${url})` }} />\n ))\n : <span className=\"ss-w-dash-hero-icon\"><DashboardIcon name={tile.icon} /></span>}\n </span>\n <span className=\"ss-w-dash-hero-body\">\n <span className=\"ss-w-dash-hero-title\">{tile.title}</span>\n {sub?.text ? <span className=\"ss-w-dash-hero-subtitle\">{sub.text}</span> : null}\n </span>\n </span>\n </button>\n )\n}\n\nexport function DashboardTile({ tile, onTap, oddsLabel = 'Odds' }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel?: string }): JSX.Element {\n if (tile.emphasis === 'hero') return <HeroTile tile={tile} onTap={onTap} oddsLabel={oddsLabel} />\n const spanClass = tile.span === 'full' ? 'ss-w-dash-tile--full' : 'ss-w-dash-tile--half'\n const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS)\n const hasMeta = Boolean(tile.badgeText) || crests.length > 0\n return (\n <button type=\"button\" className={`ss-w-dash-tile ${spanClass}`} onClick={onTap}>\n <span className=\"ss-w-dash-tile-icon\"><DashboardIcon name={tile.icon} /></span>\n <span className=\"ss-w-dash-tile-body\">\n <span className=\"ss-w-dash-tile-title\">{tile.title}</span>\n {tile.subtitle ? <span className=\"ss-w-dash-tile-subtitle\">{tile.subtitle}</span> : null}\n {hasMeta ? (\n // Badge + crests sit on their own row, below the title, instead of sharing the\n // icon/chevron row -- at the half-span tile's ~180px width a nowrap badge alone\n // (~70px) left the title column at ~22px and forced character-by-character wrapping.\n <span className=\"ss-w-dash-tile-meta\">\n {tile.badgeText ? <span className=\"ss-w-dash-tile-badge\">{tile.badgeText}</span> : null}\n {crests.length > 0 ? (\n <span className=\"ss-w-dash-tile-crests\">\n {crests.map((url, i) => (\n <span key={`${url}-${i}`} className=\"ss-w-dash-tile-crest\" style={{ backgroundImage: `url(${url})` }} aria-hidden=\"true\" />\n ))}\n </span>\n ) : null}\n </span>\n ) : null}\n </span>\n <span className=\"ss-w-dash-tile-chevron\"><ChevronIcon /></span>\n </button>\n )\n}\n","import type { GreetingDashboard as GreetingDashboardData, GreetingDashboardLayout, GreetingDashboardTile as GreetingDashboardTileData } from '@sensiblestats/widget-sdk'\nimport { DashboardTile } from './DashboardTile'\n\nconst LAYOUT_CLASSES: Record<GreetingDashboardLayout, string> = {\n market: 'ss-w-dash--market',\n goal: 'ss-w-dash--goal',\n discovery: 'ss-w-dash--discovery',\n}\n\n// The server's layout is a closed set, but a mismatched deploy or a future value\n// could still send something outside it. Falling back to goal (an allowlist check,\n// not a truthiness test) avoids emitting a class with no CSS rule behind it.\n// hasOwnProperty (not `in`) so a prototype member name like 'toString' can't slip\n// through as a layout and get interpolated into the className.\nfunction layoutClass(layout: string): string {\n return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout)\n ? LAYOUT_CLASSES[layout as GreetingDashboardLayout]\n : LAYOUT_CLASSES.goal\n}\n\nexport function GreetingDashboard({ dashboard, onTap, oddsLabel }: { dashboard: GreetingDashboardData; onTap: (tile: GreetingDashboardTileData, index: number) => void; oddsLabel?: string }): JSX.Element {\n return (\n <div className={`ss-w-dash ${layoutClass(dashboard.layout)}`}>\n <div className=\"ss-w-dash-head\">\n <span className=\"ss-w-dash-title\">{dashboard.title}</span>\n {dashboard.subtitle ? <span className=\"ss-w-dash-subtitle\">{dashboard.subtitle}</span> : null}\n </div>\n <div className=\"ss-w-dash-grid\">\n {dashboard.tiles.map((t, i) => (\n <DashboardTile key={`${t.title}-${i}`} tile={t} onTap={() => onTap(t, i)} oddsLabel={oddsLabel} />\n ))}\n </div>\n {dashboard.footerTip ? <span className=\"ss-w-dash-foot\">{dashboard.footerTip}</span> : null}\n </div>\n )\n}\n","import type { FixtureCard as FixtureCardData, FormMatch } from '@sensiblestats/widget-sdk'\nimport { Crest } from '../Crest'\n\nfunction teamFormResultClass(result: FormMatch['result']): string {\n if (result === 'W') return 'ss-w-fandash-teamform-cell--win'\n if (result === 'L') return 'ss-w-fandash-teamform-cell--loss'\n return 'ss-w-fandash-teamform-cell--draw'\n}\n\n// One historical-match cell: subject crest + score + opponent crest, ordered by which side the\n// subject team played on so the score always reads left-to-right as it happened on the pitch.\nfunction TeamFormCell({ m, subjectCrestUrl, subjectName }: {\n m: FormMatch\n subjectCrestUrl?: string | null\n subjectName: string\n}): JSX.Element {\n const subjectCrest = <Crest url={subjectCrestUrl ?? undefined} name={subjectName} kind=\"team\" />\n const opponentCrest = <Crest url={m.opponentCrestUrl ?? undefined} kind=\"team\" />\n const score = m.teamIsHome ? `${m.teamScore} - ${m.oppScore}` : `${m.oppScore} - ${m.teamScore}`\n return (\n <div className={`ss-w-fandash-teamform-cell ${teamFormResultClass(m.result)}`}>\n {m.teamIsHome ? subjectCrest : opponentCrest}\n <span className=\"ss-w-fandash-teamform-score\">{score}</span>\n {m.teamIsHome ? opponentCrest : subjectCrest}\n </div>\n )\n}\n\nconst TEAM_FORM_ROWS = 5\n\n// Two-column \"Team form\" card: left = home team's last 5, right = away team's last 5, most-recent\n// first. The rows grid is filled home-cell, away-cell per index (matching the approved two-column\n// mock) so a 2-col CSS grid lays them out in the right pairs without any extra layout wiring. A\n// shorter side just leaves later slots blank rather than shifting the other column's rows.\nfunction teamFormRows(data: FixtureCardData['data']): JSX.Element[] {\n return Array.from({ length: TEAM_FORM_ROWS }, (_, i) => i).flatMap((i) => [\n <span key={`h-${i}`} className=\"ss-w-fandash-teamform-slot\">\n {data.homeForm[i] ? (\n <TeamFormCell m={data.homeForm[i]} subjectCrestUrl={data.homeCrestUrl} subjectName={data.homeName} />\n ) : null}\n </span>,\n <span key={`a-${i}`} className=\"ss-w-fandash-teamform-slot\">\n {data.awayForm[i] ? (\n <TeamFormCell m={data.awayForm[i]} subjectCrestUrl={data.awayCrestUrl} subjectName={data.awayName} />\n ) : null}\n </span>,\n ])\n}\n\n// The fixture payload renders as three stacked [data] cards -- the fixture head (teams, kickoff,\n// venue), the last-five form, and the head-to-head record -- so each block reads as its own unit.\n// None is a tap target: the compare-form action lives in the greeting chips, so the card carries no\n// redundant CTA. (u319: the server now issues FixtureCard as a plain DataCard with no actionRef.)\nexport function FixtureCard({ card }: { card: FixtureCardData }): JSX.Element {\n const { data } = card\n const h2h = data.h2H\n return (\n <>\n <div className=\"ss-w-fandash-card ss-w-fandash-fixture\">\n <span className=\"ss-w-fandash-eyebrow\">{card.title} · {data.competition}</span>\n <div className=\"ss-w-fandash-fixture-teams\">\n <span className=\"ss-w-fandash-fixture-team\">\n <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n <span className=\"ss-w-fandash-fixture-name\">{data.homeName}</span>\n </span>\n <span className=\"ss-w-fandash-fixture-vs\">v</span>\n <span className=\"ss-w-fandash-fixture-team ss-w-fandash-fixture-team--away\">\n <span className=\"ss-w-fandash-fixture-name\">{data.awayName}</span>\n <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n </span>\n </div>\n <div className=\"ss-w-fandash-fixture-meta\">\n <span className=\"ss-w-fandash-fixture-kickoff\">{data.kickoffLabel}</span>\n {data.venue ? <span className=\"ss-w-fandash-fixture-venue\"> · {data.venue}</span> : null}\n </div>\n </div>\n\n <div className=\"ss-w-fandash-card ss-w-fandash-lastfive\">\n <span className=\"ss-w-fandash-eyebrow\">{data.formLabel}</span>\n <div className=\"ss-w-fandash-teamform-head\">\n <span className=\"ss-w-fandash-teamform-head-team\">\n <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n <span className=\"ss-w-fandash-teamform-head-name\">{data.homeName}</span>\n </span>\n <span className=\"ss-w-fandash-teamform-head-team\">\n <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n <span className=\"ss-w-fandash-teamform-head-name\">{data.awayName}</span>\n </span>\n </div>\n <div className=\"ss-w-fandash-teamform-rows\">\n {teamFormRows(data)}\n </div>\n </div>\n\n {h2h || data.fact ? (\n <div className=\"ss-w-fandash-card ss-w-fandash-h2h\">\n {h2h ? (\n <>\n <span className=\"ss-w-fandash-eyebrow\">{h2h.label}</span>\n <div className=\"ss-w-fandash-split\">\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.wins}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.homeWinsLabel}</span>\n </span>\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.draws}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.drawsLabel}</span>\n </span>\n <span className=\"ss-w-fandash-split-cell\">\n <span className=\"ss-w-fandash-split-value\">{h2h.losses}</span>\n <span className=\"ss-w-fandash-split-label\">{h2h.awayWinsLabel}</span>\n </span>\n </div>\n </>\n ) : null}\n {data.fact ? <span className=\"ss-w-fandash-fact\">{data.fact}</span> : null}\n </div>\n ) : null}\n </>\n )\n}\n","import { Fragment, useEffect, useState } from 'react'\nimport type { CountdownCard as CountdownCardData } from '@sensiblestats/widget-sdk'\n\ntype UnitKind = 'd' | 'h' | 'm' | 's'\ntype Segment = { value: string; unit: UnitKind }\n\nconst DAY_MS = 86_400_000\n\n// The countdown reads day:hour while the match is more than a day out, and switches to a live\n// hour:minute:second clock on match day (under a day to kickoff). `withSeconds` is dropped under\n// reduced motion so the card never shows a seconds figure it will never refresh. Returns null once\n// kickoff has passed.\nfunction remainingSegments(kickoffUnix: number, nowMs: number, withSeconds: boolean): Segment[] | null {\n const totalSeconds = Math.floor((kickoffUnix * 1000 - nowMs) / 1000)\n if (totalSeconds <= 0) return null\n const days = Math.floor(totalSeconds / 86_400)\n const hours = Math.floor((totalSeconds % 86_400) / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n const pad = (n: number) => String(n).padStart(2, '0')\n if (days > 0) return [{ value: pad(days), unit: 'd' }, { value: pad(hours), unit: 'h' }]\n const segs: Segment[] = [{ value: pad(hours), unit: 'h' }, { value: pad(minutes), unit: 'm' }]\n if (withSeconds) segs.push({ value: pad(seconds), unit: 's' })\n return segs\n}\n\nexport function CountdownCard({ card }: { card: CountdownCardData }): JSX.Element {\n const { data } = card\n // Unit labels are server-localized; the numbers are computed client-side.\n const unitLabel: Record<UnitKind, string> = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit }\n const [nowMs, setNowMs] = useState(() => Date.now())\n // Reduced motion is read once at mount: it decides whether the card ticks at all and whether it\n // shows a (necessarily static, so potentially stale) seconds figure. Ticking is otherwise\n // additive -- the segments computed at mount keep showing even if no interval ever fires.\n const [reduced] = useState(\n () => typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches,\n )\n const withinDay = data.kickoffUnix * 1000 - nowMs < DAY_MS\n useEffect(() => {\n if (reduced) return\n const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1000 : 60_000)\n return () => window.clearInterval(id)\n }, [reduced, withinDay])\n const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced)\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-countdown\">\n <div className=\"ss-w-fandash-countdown-top\">\n <span className=\"ss-w-fandash-eyebrow\">{card.title ?? 'Kick-off in'}</span>\n {segments ? (\n <span className=\"ss-w-fandash-countdown-clock\">\n {segments.map((s, i) => (\n <Fragment key={s.unit}>\n {i > 0 ? <span className=\"ss-w-fandash-countdown-colon\">:</span> : null}\n <span className=\"ss-w-fandash-countdown-seg\">\n <span className=\"ss-w-fandash-countdown-value\">{s.value}</span>\n <span className=\"ss-w-fandash-countdown-unit\">{unitLabel[s.unit]}</span>\n </span>\n </Fragment>\n ))}\n </span>\n ) : null}\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { InjuriesCard as InjuriesCardData, InjuryRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { Crest } from '../Crest'\n\nconst SHOWN = 3\n\nfunction ColHead({ name, crestUrl }: { name: string; crestUrl?: string | null }): JSX.Element {\n return (\n <span className=\"ss-w-fandash-injuries-col-head\">\n <Crest url={crestUrl ?? undefined} name={name} kind=\"team\" />\n <span className=\"ss-w-fandash-injuries-col-head-name\">{name}</span>\n </span>\n )\n}\n\nfunction InjuryList({ rows, emptyLabel, limit }: { rows: InjuryRow[]; emptyLabel: string; limit?: number }): JSX.Element {\n if (rows.length === 0) return <span className=\"ss-w-fandash-injuries-empty\">{emptyLabel}</span>\n const shown = limit === undefined ? rows : rows.slice(0, limit)\n return (\n <ul className=\"ss-w-fandash-injury-list\">\n {shown.map((r, i) => (\n <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-injury-row\">\n <span className=\"ss-w-fandash-injury-name\">{r.playerName}</span>\n <span className=\"ss-w-fandash-injury-meta\">\n <span className=\"ss-w-fandash-injury-status\">{r.status}</span>\n {r.injuryType ? <span className=\"ss-w-fandash-injury-type\">{r.injuryType}</span> : null}\n {r.expectedReturnLabel ? <span className=\"ss-w-fandash-injury-return\">{r.expectedReturnLabel}</span> : null}\n </span>\n </li>\n ))}\n </ul>\n )\n}\n\nexport function InjuriesCard({ card, ui }: { card: InjuriesCardData; ui?: UiConfig }): JSX.Element {\n const { data } = card\n const [expanded, setExpanded] = useState(false)\n // Either side's list can be long; a shared toggle collapses both to SHOWN and reveals the rest,\n // so the card doesn't push the input off-screen. The count is how many are hidden across both sides.\n const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN)\n const limit = expanded ? undefined : SHOWN\n const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n const showLess = ui?.showLess ?? 'Show less'\n // \"Ours\" is club-vs-opponent, not home-vs-away — reorder into home/away columns so the card\n // reads left-to-right like the rest of the dashboard regardless of which side the club is on.\n const homeCol = data.oursIsHome\n ? { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n : { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n const awayCol = data.oursIsHome\n ? { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n : { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-injuries\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-injuries-cols\">\n <div className=\"ss-w-fandash-injuries-col\">\n <ColHead name={homeCol.name} crestUrl={homeCol.crest} />\n <InjuryList rows={homeCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n </div>\n <div className=\"ss-w-fandash-injuries-divider\" />\n <div className=\"ss-w-fandash-injuries-col\">\n <ColHead name={awayCol.name} crestUrl={awayCol.crest} />\n <InjuryList rows={awayCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n </div>\n </div>\n {hidden > 0 ? (\n <button\n type=\"button\"\n className=\"ss-w-fandash-injuries-more\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? showLess : showMore(hidden)}\n </button>\n ) : null}\n </div>\n )\n}\n","import type { ReasonToBetCard as ReasonToBetCardData } from '@sensiblestats/widget-sdk'\n\nexport function ReasonToBetCard({ card }: { card: ReasonToBetCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-reasons\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <ul className=\"ss-w-fandash-reason-list\">\n {card.data.angles.map((angle, i) => (\n <li key={`${angle}-${i}`} className=\"ss-w-fandash-reason-item\">{angle}</li>\n ))}\n </ul>\n </div>\n )\n}\n","import type { WhereToWatchCard as WhereToWatchCardData } from '@sensiblestats/widget-sdk'\n\nexport function WhereToWatchCard({ card }: { card: WhereToWatchCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-watch\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <span className=\"ss-w-fandash-stations\">\n {card.data.stations.map((station, i) => (\n <span key={`${station}-${i}`} className=\"ss-w-fandash-station-chip\">{station}</span>\n ))}\n </span>\n </div>\n )\n}\n","import type { CongestedWeekCard as CongestedWeekCardData } from '@sensiblestats/widget-sdk'\n\nexport function CongestedWeekCard({ card, onTap }: { card: CongestedWeekCardData; onTap: (card: CongestedWeekCardData) => void }): JSX.Element {\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-congested\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-congested-grid\">\n {card.data.entries.map((entry, i) => (\n <span key={`${entry.opponent}-${i}`} className=\"ss-w-fandash-congested-cell\">\n <span className=\"ss-w-fandash-congested-day\">{entry.dayLabel}</span>\n <span className=\"ss-w-fandash-congested-opponent\">{entry.opponent}</span>\n <span className=\"ss-w-fandash-congested-comp\">{entry.competition}</span>\n <span className=\"ss-w-fandash-congested-time\">{entry.timeLabel}</span>\n </span>\n ))}\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { TransfersCard as TransfersCardData, TransferRow } from '@sensiblestats/widget-sdk'\n\nfunction TransferList({ rows }: { rows: TransferRow[] }): JSX.Element {\n if (rows.length === 0) return <span className=\"ss-w-fandash-transfers-empty\">None</span>\n return (\n <ul className=\"ss-w-fandash-transfer-list\">\n {rows.map((r, i) => (\n <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-transfer-row\">\n <span className=\"ss-w-fandash-transfer-name\">{r.playerName}</span>\n <span className=\"ss-w-fandash-transfer-club\">{r.otherClub}</span>\n {r.type ? <span className=\"ss-w-fandash-transfer-type\">{r.type}</span> : null}\n </li>\n ))}\n </ul>\n )\n}\n\nexport function TransfersCard({ card }: { card: TransfersCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-transfers\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-transfers-cols\">\n <div className=\"ss-w-fandash-transfers-col\">\n <span className=\"ss-w-fandash-transfers-col-head\">In</span>\n <TransferList rows={data.in} />\n </div>\n <div className=\"ss-w-fandash-transfers-col\">\n <span className=\"ss-w-fandash-transfers-col-head\">Out</span>\n <TransferList rows={data.out} />\n </div>\n </div>\n </div>\n )\n}\n","import type { LinksCard as LinksCardData } from '@sensiblestats/widget-sdk'\nimport { ChevronIcon } from '../Icons'\n\nexport function LinksCard({ card }: { card: LinksCardData }): JSX.Element {\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-links\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-link-grid\">\n {card.data.links.map((link, i) => (\n <a key={`${link.url}-${i}`} className=\"ss-w-fandash-link-tile\" href={link.url} target=\"_blank\" rel=\"noopener noreferrer\">\n <span className=\"ss-w-fandash-link-label\">{link.label}</span>\n <span className=\"ss-w-fandash-link-chevron\"><ChevronIcon /></span>\n </a>\n ))}\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { PostMatchResultCard as PostMatchResultCardData } from '@sensiblestats/widget-sdk'\n\nfunction initials(name: string): string {\n return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Same img-with-fallback treatment as LiveScoreCard's LiveCrest -- a broken/absent URL falls back\n// to a coloured initials chip, which a background-image span can't detect on its own.\nfunction PostMatchCrest({\n url,\n name,\n side,\n}: {\n url?: string | null\n name: string\n side: 'home' | 'away'\n}): JSX.Element {\n const [failed, setFailed] = useState(false)\n const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return (\n <span className={`${cls} ss-w-fandash-postmatch-crest--fallback`} aria-hidden=\"true\">\n {initials(name)}\n </span>\n )\n}\n\n// [data] card -- the full-time scoreboard. No tap target: the score itself is the payload, and\n// the goals/stats/top-performer cards below carry the actionRef taps for this match.\nexport function PostMatchResultCard({ card }: { card: PostMatchResultCardData }): JSX.Element {\n const { data } = card\n const homeWon = data.homeScore >= data.awayScore\n const awayWon = data.awayScore >= data.homeScore\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-result\">\n <div className=\"ss-w-fandash-postmatch-top\">\n {/* card.title carries the server-localized \"Full time\" label -- reused as the pill text\n rather than a hardcoded English literal. */}\n {card.title ? <span className=\"ss-w-fandash-postmatch-pill\">{card.title}</span> : null}\n <span className={`ss-w-fandash-postmatch-tag ss-w-fandash-postmatch-tag--${data.outcome}`}>\n {data.resultLabel}\n </span>\n </div>\n <div className=\"ss-w-fandash-postmatch-main\">\n <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--home\">\n <PostMatchCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n <span className=\"ss-w-fandash-postmatch-team-name\">{data.homeName}</span>\n </div>\n <div className=\"ss-w-fandash-postmatch-score-main\">\n <span\n className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? 'win' : 'lose'}`}\n >\n {data.homeScore}\n </span>\n <span className=\"ss-w-fandash-postmatch-score-sep\">–</span>\n <span\n className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? 'win' : 'lose'}`}\n >\n {data.awayScore}\n </span>\n </div>\n <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--away\">\n <PostMatchCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n <span className=\"ss-w-fandash-postmatch-team-name\">{data.awayName}</span>\n </div>\n </div>\n <div className=\"ss-w-fandash-postmatch-meta\">\n {data.kickoffLabel}\n {data.competition ? ` · ${data.competition}` : ''}\n </div>\n </div>\n )\n}\n","import type { PostMatchGoalsCard as PostMatchGoalsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see FixtureCard/CongestedWeekCard).\nexport function PostMatchGoalsCard({ card, onTap }: {\n card: PostMatchGoalsCardData\n onTap: (card: PostMatchGoalsCardData) => void\n}): JSX.Element {\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-goals\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <ul className=\"ss-w-fandash-postmatch-goal-list\">\n {card.data.goals.map((g, i) => (\n <li key={`${g.text}-${i}`} className={g.scoredByClub ? 'ss-w-fandash-postmatch-goal ss-w-fandash-postmatch-goal--club' : 'ss-w-fandash-postmatch-goal'}>\n <span className=\"ss-w-fandash-postmatch-goal-ball\" />\n <span>{g.text}</span>\n </li>\n ))}\n </ul>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchStatsCard as PostMatchStatsCardData } from '@sensiblestats/widget-sdk'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width. Mirrors LiveStatsCard's splitWidths.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n const total = homeNum + awayNum\n if (total <= 0) return { home: '50%', away: '50%' }\n const homePct = Math.round((homeNum / total) * 1000) / 10\n return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function PostMatchStatsCard({ card, onTap }: {\n card: PostMatchStatsCardData\n onTap: (card: PostMatchStatsCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-stats\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-stat-rows\">\n {data.rows.map((r, i) => {\n // Row values are club-first, but the result card above renders home-left/away-right, so\n // orient by venue: the home team's value on the left, the away team's on the right. When\n // the club is the away side, that means the club's value is the RIGHT column.\n const leftValue = data.clubIsHome ? r.clubValue : r.oppValue\n const rightValue = data.clubIsHome ? r.oppValue : r.clubValue\n const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n const { home, away } = splitWidths(homeNum, awayNum)\n return (\n <div key={`${r.label}-${i}`} className=\"ss-w-fandash-postmatch-stat\">\n <div className=\"ss-w-fandash-postmatch-stat-row\">\n <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--home\">{leftValue}</span>\n <span className=\"ss-w-fandash-postmatch-stat-label\">{r.label}</span>\n <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--away\">{rightValue}</span>\n </div>\n <div className=\"ss-w-fandash-postmatch-stat-bar\">\n <span className=\"ss-w-fandash-postmatch-stat-bar-home\" style={{ width: home }} />\n <span className=\"ss-w-fandash-postmatch-stat-bar-away\" style={{ width: away }} />\n </div>\n </div>\n )\n })}\n </div>\n {data.rows.length > 0 ? (\n <div className=\"ss-w-fandash-postmatch-legend\">\n <span className=\"ss-w-fandash-postmatch-legend-item\">\n <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--home\" />\n {data.homeName}\n </span>\n <span className=\"ss-w-fandash-postmatch-legend-item\">\n <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--away\" />\n {data.awayName}\n </span>\n </div>\n ) : null}\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchTopPerformerCard as PostMatchTopPerformerCardData } from '@sensiblestats/widget-sdk'\n\n// First letter of the first and last word (a single-word name yields just that one letter, since\n// first === last); whitespace/empty falls back to \"?\" rather than rendering a blank avatar.\nfunction initials(playerName: string): string {\n const words = playerName.trim().split(/\\s+/).filter(Boolean)\n if (words.length === 0) return '?'\n const first = words[0]!.charAt(0)\n const last = words[words.length - 1]!.charAt(0)\n return (words.length > 1 ? `${first}${last}` : first).toUpperCase()\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard. Full mockup treatment:\n// gradient initials avatar + name + a prominent rating chip. No \"2 goals\" sub-line -- there's no\n// data for it.\nexport function PostMatchTopPerformerCard({ card, onTap }: {\n card: PostMatchTopPerformerCardData\n onTap: (card: PostMatchTopPerformerCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-performer\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-perf-row\">\n <span className=\"ss-w-fandash-postmatch-perf-avatar\" aria-hidden=\"true\">{initials(data.playerName)}</span>\n <span className=\"ss-w-fandash-postmatch-perf-name\">{data.playerName}</span>\n <span className=\"ss-w-fandash-postmatch-perf-rating\">{data.ratingLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { PostMatchNextCard as PostMatchNextCardData } from '@sensiblestats/widget-sdk'\n\n// [data] card -- the upcoming fixture teaser that follows a post-match dashboard. No tap target.\n// v1 (modest): whenLabel is already a complete localized phrase composed server-side -- it\n// includes the opponent, venue and kickoff time (EN \"vs Bournemouth (H) · Sat 12 Sep · 15:00\",\n// TR \"İç sahada Bournemouth · ...\"). Rendering opponentName alongside it would duplicate the\n// opponent, so this card shows only whenLabel, dressed up with an accent rule rather than a second\n// line. The richer opponent-headline + venue chip + crest layout needs a server field split\n// (opponent vs venue vs time as separate fields) and is deferred.\nexport function PostMatchNextCard({ card }: { card: PostMatchNextCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-next\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-postmatch-next-row\">\n <span className=\"ss-w-fandash-postmatch-next-when\">{data.whenLabel}</span>\n </div>\n </div>\n )\n}\n","import type { RestingNextCard as RestingNextCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see PostMatchGoalsCard/FixtureCard).\nexport function RestingNextCard({ card, onTap }: {\n card: RestingNextCardData\n onTap: (card: RestingNextCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-next\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-next-row\">\n <span className=\"ss-w-fandash-resting-next-when\">{data.whenLabel}</span>\n {data.competition ? <span className=\"ss-w-fandash-resting-next-competition\">{data.competition}</span> : null}\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingStandingsCard as RestingStandingsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingStandingsCard({ card, onTap }: {\n card: RestingStandingsCardData\n onTap: (card: RestingStandingsCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-standings\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-standings-row\">\n <span className=\"ss-w-fandash-resting-standings-position\">{data.positionLabel}</span>\n <span className=\"ss-w-fandash-resting-standings-record\">{data.recordLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingSeasonCard as RestingSeasonCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingSeasonCard({ card, onTap }: {\n card: RestingSeasonCardData\n onTap: (card: RestingSeasonCardData) => void\n}): JSX.Element {\n const { data } = card\n return (\n <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-season\" onClick={() => onTap(card)}>\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-resting-season-rows\">\n {data.scorerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.scorerLabel}</span> : null}\n {data.playerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.playerLabel}</span> : null}\n <span className=\"ss-w-fandash-resting-season-row\">{data.tallyLabel}</span>\n </div>\n <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n </button>\n )\n}\n","import type { RestingFormCard as RestingFormCardData } from '@sensiblestats/widget-sdk'\n\nfunction resultClass(result: string): string {\n const upper = result.toUpperCase()\n if (upper === 'W') return 'ss-w-fandash-form-pill--win'\n if (upper === 'L') return 'ss-w-fandash-form-pill--loss'\n return 'ss-w-fandash-form-pill--draw'\n}\n\n// [data] card -- recent form as one styled W/D/L pill per letter (same pill classes as the\n// fixture card's last-five strip). No tap target.\nexport function RestingFormCard({ card }: { card: RestingFormCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-resting-form\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <span className=\"ss-w-fandash-form\">\n {data.letters.map((r, i) => (\n <span key={`${r}-${i}`} className={`ss-w-fandash-form-pill ${resultClass(r)}`}>{r}</span>\n ))}\n </span>\n </div>\n )\n}\n","import { useRef, useState } from 'react'\nimport type { LiveScoreCard as LiveScoreCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport { useLiveClock } from '../../useLiveClock'\n\nfunction initials(name: string): string {\n return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a coloured initials chip -- the design\n// wants the chip whenever the crest is missing OR fails to load, which a background-image span\n// can't detect on its own.\nfunction LiveCrest({ url, name, side }: { url?: string | null; name: string; side: 'home' | 'away' }): JSX.Element {\n const [failed, setFailed] = useState(false)\n const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`\n if (url && !failed) {\n return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n }\n return (\n <span className={`${cls} ss-w-fandash-live-crest--fallback`} aria-hidden=\"true\">\n {initials(name)}\n </span>\n )\n}\n\n// Renders \"Salah 6', Núñez 9'\" from the goal events the parent filtered out of the live timeline,\n// oldest first. Events with no player name are dropped rather than rendered blank; if nothing is\n// left, the scorers line is omitted entirely.\nfunction scorersLine(goalEvents: LiveEventLine[] | undefined): string | null {\n if (!goalEvents || goalEvents.length === 0) return null\n // Defensive: only ever render actual goals, even if a caller passes an unfiltered event list.\n const named = goalEvents.filter((e) => e.type === 'goal' && e.player)\n if (named.length === 0) return null\n return named\n .slice()\n .sort((a, b) => a.minute - b.minute)\n .map((e) => `${e.player} ${e.minuteLabel}`)\n .join(', ')\n}\n\n// [data] card -- the in-play scoreboard. No tap target: the live score itself is the payload,\n// and the timeline/stats cards below carry the rest of the in-play picture.\nexport function LiveScoreCard({\n card,\n goalEvents,\n}: {\n card: LiveScoreCardData\n goalEvents?: LiveEventLine[]\n}): JSX.Element {\n const { data } = card\n\n // The reducer replaces the card object on every ~60s poll, so seeding the live-clock hook with\n // `Date.now()` on every render would restart its elapsed-time math each time and the minute\n // would never tick between polls. Reseed only when the server minute or score actually changes.\n const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`\n const seedRef = useRef<{ key: string; receivedAtMs: number } | null>(null)\n if (!seedRef.current || seedRef.current.key !== seedKey) {\n seedRef.current = { key: seedKey, receivedAtMs: Date.now() }\n }\n\n const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs)\n const minuteSuffix = data.minuteLabel.replace(/^\\d+/, '')\n const scorers = scorersLine(goalEvents)\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-score\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-top\">\n <span className=\"ss-w-fandash-live-pill\">\n <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n {data.statusLabel}\n </span>\n <span className=\"ss-w-fandash-live-minute\">{`${displayMinute}${minuteSuffix}`}</span>\n {data.competition ? <span className=\"ss-w-fandash-live-competition\">{data.competition}</span> : null}\n </div>\n <div className=\"ss-w-fandash-live-main\">\n <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--home\">\n <LiveCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n <span className=\"ss-w-fandash-live-team-name\">{data.homeName}</span>\n </div>\n <div className=\"ss-w-fandash-live-score-main\">\n <span className=\"ss-w-fandash-live-score-value\">{data.homeScore}</span>\n <span className=\"ss-w-fandash-live-score-sep\">–</span>\n <span className=\"ss-w-fandash-live-score-value\">{data.awayScore}</span>\n </div>\n <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--away\">\n <LiveCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n <span className=\"ss-w-fandash-live-team-name\">{data.awayName}</span>\n </div>\n </div>\n {scorers ? (\n <div className=\"ss-w-fandash-live-scorers\">\n <span className=\"ss-w-fandash-live-scorers-icon\" aria-hidden=\"true\">\n ⚽\n </span>\n {scorers}\n </div>\n ) : null}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst TICK_MS = 60_000\n// Generous stoppage-time headroom. The server clamps 2H to 105; if a live poll never\n// delivers a \"Finished\" transition (resolver drops the match before that lands), a stuck\n// clockRunning:true must hold here instead of climbing forever.\nconst MAX_LIVE_TICK_MINUTES = 15\n\nfunction computeDisplayMinute(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n if (!clockRunning) return minute\n const elapsedMinutes = Math.floor((Date.now() - receivedAtMs) / TICK_MS)\n return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES)\n}\n\n// Ticks a live match minute forward once per real minute between server polls, so the\n// clock doesn't look frozen during the 60s gap. Reseeds immediately whenever `minute` or\n// `receivedAtMs` changes (a fresh poll), rather than waiting for the next interval tick.\nexport function useLiveClock(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n const [displayMinute, setDisplayMinute] = useState(() =>\n computeDisplayMinute(minute, clockRunning, receivedAtMs),\n )\n\n useEffect(() => {\n setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n\n if (!clockRunning) return\n\n const id = window.setInterval(() => {\n setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n }, TICK_MS)\n\n return () => window.clearInterval(id)\n }, [minute, clockRunning, receivedAtMs])\n\n return displayMinute\n}\n","import { useState } from 'react'\nimport type { LiveTimelineCard as LiveTimelineCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nconst SHOWN = 3\n\n// Per-type icon: a ball mark for goals, a coloured card rectangle for yellow/red, up/down\n// arrows for a substitution. An unrecognised type (forward-compat with the server's union)\n// renders a neutral dot rather than nothing, so a new event type never looks broken.\nfunction EventIcon({ type }: { type: LiveEventLine['type'] }): JSX.Element {\n if (type === 'goal') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico ss-w-fandash-live-tl-ico--goal\" aria-hidden=\"true\">\n <span className=\"ss-w-fandash-live-tl-ball\" />\n </span>\n )\n }\n if (type === 'yellow' || type === 'red') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n <span className={`ss-w-fandash-live-tl-card ss-w-fandash-live-tl-card--${type}`} />\n </span>\n )\n }\n if (type === 'sub') {\n return (\n <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n <span className=\"ss-w-fandash-live-tl-subarrows\">⇅</span>\n </span>\n )\n }\n return <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\"><span className=\"ss-w-fandash-live-tl-dot\" /></span>\n}\n\n// Sub events name both players; the \"for {playerOff}\" half only renders when the server sent\n// it, and everything falls back to the server's plain text if a name field is missing.\nfunction EventLabel({ e }: { e: LiveEventLine }): JSX.Element {\n if (e.type === 'sub') {\n return (\n <span className=\"ss-w-fandash-live-tl-who\">\n {e.player ?? e.text}\n {e.playerOff ? <span className=\"ss-w-fandash-live-tl-off\"> for {e.playerOff}</span> : null}\n </span>\n )\n }\n return <span className=\"ss-w-fandash-live-tl-who\">{e.player ?? e.text}</span>\n}\n\nfunction EventRow({ e }: { e: LiveEventLine }): JSX.Element {\n const cls = [\n 'ss-w-fandash-live-tl-ev',\n e.side === 'home' ? 'ss-w-fandash-live-tl-ev--home' : 'ss-w-fandash-live-tl-ev--away',\n e.type === 'goal' ? 'ss-w-fandash-live-tl-ev--goal' : '',\n ]\n .filter(Boolean)\n .join(' ')\n return (\n <div className={cls}>\n <span className=\"ss-w-fandash-live-tl-txt\">\n <EventLabel e={e} />\n <EventIcon type={e.type} />\n </span>\n <span className=\"ss-w-fandash-live-tl-badge\">{e.minuteLabel}</span>\n </div>\n )\n}\n\n// [data] card -- the in-play event feed as a compact two-sided timeline down a centre spine:\n// each club's events sit on its own side, most-recent 3 shown with a \"See more\" toggle for the\n// rest. No tap target.\nexport function LiveTimelineCard({ card, ui }: { card: LiveTimelineCardData; ui?: UiConfig }): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n const events = card.data.events\n if (!events || events.length === 0) return null\n\n const sorted = [...events].sort((a, b) => b.minute - a.minute)\n const rest = sorted.length - SHOWN\n const shown = expanded ? sorted : sorted.slice(0, SHOWN)\n\n const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n const showLess = ui?.showLess ?? 'Show less'\n\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-timeline\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-tl\">\n {shown.map((e, i) => (\n <EventRow key={`${e.minute}-${e.side}-${e.type}-${i}`} e={e} />\n ))}\n </div>\n {rest > 0 ? (\n <button\n type=\"button\"\n className=\"ss-w-fandash-live-tl-more\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? showLess : showMore(rest)}\n </button>\n ) : null}\n </div>\n )\n}\n","import { useId } from 'react'\nimport type { LiveStatsData } from '@sensiblestats/widget-sdk'\n\n// widget-sdk's events.ts defines `MomentumPoint` but its barrel (index.ts) never re-exports it on\n// its own -- only as the element type of `LiveStatsData.momentum`. Indexing off that field avoids\n// widening this task's scope to a widget-sdk barrel edit for a type alias.\ntype MomentumPoint = LiveStatsData['momentum'][number]\n\nconst WIDTH = 270\nconst HEIGHT = 56\nconst BASELINE = HEIGHT / 2 // mid-height, matches the mockup's BASE=28 for H=56\nconst SCALE = 0.26 // value ±100 -> ±26px around the baseline, same as the mockup\n\nfunction buildPaths(\n points: MomentumPoint[],\n): { area: string; line: string; lastLeftPct: number; lastTopPx: number } {\n const lastIndex = points.length - 1\n const px = (i: number): number => (lastIndex === 0 ? 0 : (i / lastIndex) * WIDTH)\n const py = (v: number): number => BASELINE - v * SCALE\n const linePts = points.map((p, i) => `${px(i).toFixed(1)},${py(p.value).toFixed(1)}`)\n const area = `M0,${BASELINE} L${linePts.join(' L')} L${WIDTH},${BASELINE} Z`\n const line = `M${linePts.join(' L')}`\n // The caller (MomentumWave) already returns null for an empty series, so lastIndex is always a\n // valid index here -- the `?? 0` only satisfies noUncheckedIndexedAccess, it never triggers.\n const lastValue = points[lastIndex]?.value ?? 0\n // The marker is an HTML overlay positioned by PERCENT of width (so it survives the SVG's\n // preserveAspectRatio=\"none\" scaling undistorted) -- always 0 for a single point, always 100 for\n // the last of more than one, matching px()'s own 0..WIDTH mapping.\n const lastLeftPct = lastIndex === 0 ? 0 : 100\n return { area, line, lastLeftPct, lastTopPx: py(lastValue) }\n}\n\n// [data] momentum wave -- no tap target. `value` is club-positive (clubPressure - oppPressure),\n// but colour follows VENUE, not club, to stay consistent with the score/timeline cards: the club's\n// own colour is --ss-w-home when `clubIsHome`, --ss-w-away otherwise. So a club-positive swing (up,\n// above the baseline) is filled with the club's venue colour, and an opponent-positive swing (down)\n// with the opponent's venue colour -- top/bottom are NOT fixed to home/away, they flip with\n// `clubIsHome` so the same team is always the same colour across every live card.\nexport function MomentumWave({\n points,\n caption,\n clubIsHome,\n}: {\n points: MomentumPoint[]\n caption?: string | null\n clubIsHome: boolean\n}): JSX.Element | null {\n if (points.length === 0) return null\n\n const { area, line, lastLeftPct, lastTopPx } = buildPaths(points)\n const clipId = useId()\n const topClipId = `${clipId}-top`\n const bottomClipId = `${clipId}-bottom`\n const topClass = clubIsHome ? 'ss-w-fandash-live-mom-home' : 'ss-w-fandash-live-mom-away'\n const bottomClass = clubIsHome ? 'ss-w-fandash-live-mom-away' : 'ss-w-fandash-live-mom-home'\n\n return (\n <div className=\"ss-w-fandash-live-mom\">\n {caption ? <span className=\"ss-w-fandash-live-mom-caption\">{caption}</span> : null}\n <div className=\"ss-w-fandash-live-mom-plot\">\n <svg\n className=\"ss-w-fandash-live-mom-svg\"\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n preserveAspectRatio=\"none\"\n role=\"img\"\n aria-label={caption ?? 'Momentum'}\n >\n <defs>\n <clipPath id={topClipId}>\n <rect x={0} y={0} width={WIDTH} height={BASELINE} />\n </clipPath>\n <clipPath id={bottomClipId}>\n <rect x={0} y={BASELINE} width={WIDTH} height={HEIGHT - BASELINE} />\n </clipPath>\n </defs>\n <path d={area} className={topClass} clipPath={`url(#${topClipId})`} />\n <path d={area} className={bottomClass} clipPath={`url(#${bottomClipId})`} />\n <line x1={0} y1={BASELINE} x2={WIDTH} y2={BASELINE} className=\"ss-w-fandash-live-mom-base\" />\n <path d={line} className=\"ss-w-fandash-live-mom-line\" vectorEffect=\"non-scaling-stroke\" />\n </svg>\n {/* HTML overlay dot, not an SVG <circle> -- the SVG's preserveAspectRatio=\"none\" stretches\n non-uniform scaling into an oval, and at x=WIDTH half of a circle hangs off the edge.\n An HTML element can't be deformed by the SVG's viewBox scaling, and clamp() keeps it\n fully inside the plot at both ends. */}\n <span\n className=\"ss-w-fandash-live-mom-now\"\n style={{ left: `clamp(4px, ${lastLeftPct}%, calc(100% - 4px))`, top: `${lastTopPx}px` }}\n aria-hidden=\"true\"\n />\n </div>\n </div>\n )\n}\n","import type { LiveStatsCard as LiveStatsCardData } from '@sensiblestats/widget-sdk'\nimport { MomentumWave } from './MomentumWave'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width, since a stat can legitimately be 0-0 early in a match.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n const total = homeNum + awayNum\n if (total <= 0) return { home: '50%', away: '50%' }\n const homePct = Math.round((homeNum / total) * 1000) / 10\n return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [data] card -- in-play match stats, home value / stat label / away value per row, each backed\n// by a home/away split bar, plus an optional momentum wave (or its text fallback). No tap target.\n//\n// LiveStatRow itself only carries clubNum/oppNum (club vs opponent), but LiveStatsData now also\n// carries `clubIsHome`/`homeName`/`awayName` (mirroring the venue signal LiveScoreCard already\n// has and the ClubIsHome pattern on RestingNextData/PostMatchNextData) -- so this card orients by\n// VENUE, not by club, to stay colour-consistent with the score and timeline cards: home is always\n// --ss-w-home on the left, away is always --ss-w-away on the right, and clubNum/oppNum are placed\n// on whichever side `clubIsHome` says the club actually occupies this match.\nexport function LiveStatsCard({ card }: { card: LiveStatsCardData }): JSX.Element {\n const { data } = card\n return (\n <div className=\"ss-w-fandash-card ss-w-fandash-live-stats\">\n {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n <div className=\"ss-w-fandash-live-stat-rows\">\n {data.rows.map((r, i) => {\n const homeValue = data.clubIsHome ? r.clubValue : r.oppValue\n const awayValue = data.clubIsHome ? r.oppValue : r.clubValue\n const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n const { home, away } = splitWidths(homeNum, awayNum)\n return (\n <div key={`${r.label}-${i}`} className=\"ss-w-fandash-live-stat\">\n <div className=\"ss-w-fandash-live-stat-row\">\n <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--home\">{homeValue}</span>\n <span className=\"ss-w-fandash-live-stat-label\">{r.label}</span>\n <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--away\">{awayValue}</span>\n </div>\n <div className=\"ss-w-fandash-live-bar\">\n <span className=\"ss-w-fandash-live-bar-home\" style={{ width: home }} />\n <span className=\"ss-w-fandash-live-bar-away\" style={{ width: away }} />\n </div>\n </div>\n )\n })}\n </div>\n {data.momentum.length > 0 ? (\n <MomentumWave points={data.momentum} caption={data.momentumLabel} clubIsHome={data.clubIsHome} />\n ) : data.momentumLabel ? (\n <span className=\"ss-w-fandash-live-momentum\">{data.momentumLabel}</span>\n ) : null}\n {data.rows.length > 0 ? (\n <div className=\"ss-w-fandash-live-legend\">\n <span className=\"ss-w-fandash-live-legend-item\">\n <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--home\" />\n {data.homeName}\n </span>\n <span className=\"ss-w-fandash-live-legend-item\">\n <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--away\" />\n {data.awayName}\n </span>\n </div>\n ) : null}\n </div>\n )\n}\n","import type {\n ClubFanDashboardCard,\n ClubFanDashboardPayload,\n CongestedWeekCard as CongestedWeekCardData,\n LiveEventLine,\n LiveTimelineCard as LiveTimelineCardData,\n PostMatchGoalsCard as PostMatchGoalsCardData,\n PostMatchStatsCard as PostMatchStatsCardData,\n PostMatchTopPerformerCard as PostMatchTopPerformerCardData,\n RestingNextCard as RestingNextCardData,\n RestingStandingsCard as RestingStandingsCardData,\n RestingSeasonCard as RestingSeasonCardData,\n} from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { FixtureCard } from './FixtureCard'\nimport { CountdownCard } from './CountdownCard'\nimport { InjuriesCard } from './InjuriesCard'\nimport { ReasonToBetCard } from './ReasonToBetCard'\nimport { WhereToWatchCard } from './WhereToWatchCard'\nimport { CongestedWeekCard } from './CongestedWeekCard'\nimport { TransfersCard } from './TransfersCard'\nimport { LinksCard } from './LinksCard'\nimport { PostMatchResultCard } from './PostMatchResultCard'\nimport { PostMatchGoalsCard } from './PostMatchGoalsCard'\nimport { PostMatchStatsCard } from './PostMatchStatsCard'\nimport { PostMatchTopPerformerCard } from './PostMatchTopPerformerCard'\nimport { PostMatchNextCard } from './PostMatchNextCard'\nimport { RestingNextCard } from './RestingNextCard'\nimport { RestingStandingsCard } from './RestingStandingsCard'\nimport { RestingSeasonCard } from './RestingSeasonCard'\nimport { RestingFormCard } from './RestingFormCard'\nimport { LiveScoreCard } from './LiveScoreCard'\nimport { LiveTimelineCard } from './LiveTimelineCard'\nimport { LiveStatsCard } from './LiveStatsCard'\n\n// The [prefill] card types (see ClubFanDashboardPayload.cs) -- tapping any of them sends its\n// actionLabel as a follow-up message, carrying the opaque actionRef so the server resolves the\n// pre-issued binding. Every other card type is a [data] card with no tap target. FixtureCard is a\n// DataCard now (u319): its tap moved to the greeting chips, so it's not in this union any more.\nexport type ClubFanDashboardTapCard =\n | CongestedWeekCardData\n | PostMatchGoalsCardData\n | PostMatchStatsCardData\n | PostMatchTopPerformerCardData\n | RestingNextCardData\n | RestingStandingsCardData\n | RestingSeasonCardData\n\nexport function ClubFanDashboard({ dashboard, onTap, ui }: {\n dashboard: ClubFanDashboardPayload\n onTap: (card: ClubFanDashboardTapCard) => void\n ui?: UiConfig\n}): JSX.Element {\n // The clock leads the dashboard, so any countdown card is floated to the top; the rest keep\n // their server order.\n const orderedCards = [\n ...dashboard.cards.filter((c) => c.cardType === 'countdown'),\n ...dashboard.cards.filter((c) => c.cardType !== 'countdown'),\n ]\n // The score card's scorers line is derived from the sibling timeline card's goal events, so it\n // needs pulling out here where the full card list is in scope. Null-safe: no timeline card (or\n // no goals in it) means no scorers line, not a crash.\n const timelineCard = dashboard.cards.find(\n (c): c is LiveTimelineCardData => c.cardType === 'liveTimeline',\n )\n const goalEvents = timelineCard?.data.events.filter((e) => e.type === 'goal')\n return (\n <div className=\"ss-w-fandash\">\n {dashboard.greeting ? <span className={dashboard.greetingIsLead ? 'ss-w-fandash-greeting ss-w-fandash-greeting--lead' : 'ss-w-fandash-greeting'}>{dashboard.greeting}</span> : null}\n <div className=\"ss-w-fandash-cards\">\n {orderedCards.map((card, i) => (\n <FanDashboardCard key={`${card.cardType}-${i}`} card={card} onTap={onTap} ui={ui} goalEvents={goalEvents} />\n ))}\n </div>\n </div>\n )\n}\n\nfunction FanDashboardCard({ card, onTap, ui, goalEvents }: {\n card: ClubFanDashboardCard\n onTap: (card: ClubFanDashboardTapCard) => void\n ui?: UiConfig\n goalEvents?: LiveEventLine[]\n}): JSX.Element | null {\n switch (card.cardType) {\n case 'fixture':\n return <FixtureCard card={card} />\n case 'countdown':\n return <CountdownCard card={card} />\n case 'injuries':\n return <InjuriesCard card={card} ui={ui} />\n case 'reasonToBet':\n return <ReasonToBetCard card={card} />\n case 'whereToWatch':\n return <WhereToWatchCard card={card} />\n case 'congestedWeek':\n return <CongestedWeekCard card={card} onTap={onTap} />\n case 'transfers':\n return <TransfersCard card={card} />\n case 'links':\n return <LinksCard card={card} />\n case 'postMatchResult':\n return <PostMatchResultCard card={card} />\n case 'postMatchGoals':\n return <PostMatchGoalsCard card={card} onTap={onTap} />\n case 'postMatchStats':\n return <PostMatchStatsCard card={card} onTap={onTap} />\n case 'postMatchTopPerformer':\n return <PostMatchTopPerformerCard card={card} onTap={onTap} />\n case 'postMatchNext':\n return <PostMatchNextCard card={card} />\n case 'restingNext':\n return <RestingNextCard card={card} onTap={onTap} />\n case 'restingStandings':\n return <RestingStandingsCard card={card} onTap={onTap} />\n case 'restingSeason':\n return <RestingSeasonCard card={card} onTap={onTap} />\n case 'restingForm':\n return <RestingFormCard card={card} />\n case 'liveScore':\n return <LiveScoreCard card={card} goalEvents={goalEvents} />\n case 'liveTimeline':\n return <LiveTimelineCard card={card} ui={ui} />\n case 'liveStats':\n return <LiveStatsCard card={card} />\n default:\n // The server's cardType is a closed set, but a mismatched deploy could still send an\n // unrecognised discriminator -- render nothing for it rather than crash the whole turn.\n return null\n }\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport type { Message } from '../reducer'\nimport type { ActionVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { Markdown } from './Markdown'\nimport { EntityCardList } from './EntityCardList'\nimport { BettingInsightList } from './BettingInsightList'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { CompactOddsList } from './CompactOddsList'\nimport { toCompactList } from '../compactList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { ActionButtons } from './ActionButtons'\nimport { GreetingDashboard } from './dashboard/GreetingDashboard'\nimport { ClubFanDashboard, type ClubFanDashboardTapCard } from './dashboard/ClubFanDashboard'\n\nexport function ChatMessage({ message, disabled, onAct, onTap, ui, slip, monitor }: {\n message: Message\n disabled: boolean\n onAct: (a: ActionVM) => void\n onTap: (tile: GreetingDashboardTile, index: number) => void\n ui?: UiConfig\n slip: SlipHandlerProps\n monitor?: LiveMonitorController\n}): JSX.Element {\n if (message.role === 'user') {\n return <div className=\"ss-w-msg ss-w-user\" data-msg-id={message.id}><div className=\"ss-w-bubble\">{message.text}</div></div>\n }\n // A [prefill] club-fan-dashboard card tap reuses the same send path as an action button --\n // actionLabel becomes both the message and the display text, and the opaque actionRef rides\n // along so the server resolves the card's pre-issued action binding rather than re-planning\n // a prose command -- rather than threading a second tap handler through MessageList.\n const onFanDashboardTap = (card: ClubFanDashboardTapCard): void => {\n onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || '' })\n }\n const compact = toCompactList(message.marketOdds)\n return (\n <div className=\"ss-w-msg ss-w-bot\" data-msg-id={message.id}>\n {message.text && !message.greetingDashboard && !message.clubFanDashboard ? <Markdown text={message.text} /> : null}\n {message.greetingDashboard && !message.clubFanDashboard ? <GreetingDashboard dashboard={message.greetingDashboard} onTap={onTap} oddsLabel={ui?.oddsLabel} /> : null}\n {message.clubFanDashboard ? <ClubFanDashboard dashboard={message.clubFanDashboard} onTap={onFanDashboardTap} ui={ui} /> : null}\n <EntityCardList cards={message.cards} disabled={disabled} showLessLabel={ui?.showLess} showMoreLabel={ui?.showMore} />\n <BettingInsightList insights={message.insights} ui={ui} slip={slip} monitor={monitor} />\n {compact\n ? <CompactOddsList list={compact} ui={ui} slip={slip} monitor={monitor} />\n : <MarketOddsCardList cards={message.marketOdds} ui={ui} slip={slip} monitor={monitor} />}\n <OddsMovementCardList cards={message.oddsMovement} ui={ui} monitor={monitor} />\n <ActionButtons actions={message.actions} loading={false} disabled={disabled} onAct={onAct} />\n </div>\n )\n}\n","import type { ChipVM } from '../model'\n\nexport function IntentChips({ chips, onPick }: { chips: ChipVM[]; onPick: (text: string) => void }): JSX.Element | null {\n if (chips.length === 0) return null\n return (\n <div className=\"ss-w-chips\">\n {chips.map((c, i) => (\n <button key={`${c.text}-${i}`} type=\"button\" className=\"ss-w-chip\" onClick={() => onPick(c.text)}>{c.text}</button>\n ))}\n </div>\n )\n}\n","// Distance (px) from the bottom within which the list is still considered\n// \"pinned\" — small enough that a user reading earlier content isn't counted\n// as pinned, large enough to absorb sub-pixel/rounding drift while streaming.\nexport const PIN_THRESHOLD = 48\n\n/**\n * True when the scroll container is at (or within PIN_THRESHOLD of) its bottom.\n * Used to decide whether new content should auto-scroll: we follow the stream\n * only while the user is already at the bottom, so late arrivals (e.g. suggested\n * actions) never yank a user who has scrolled up to read.\n */\nexport function isPinnedToBottom(el: Pick<HTMLElement, 'scrollHeight' | 'scrollTop' | 'clientHeight'>, threshold = PIN_THRESHOLD): boolean {\n return el.scrollHeight - el.scrollTop - el.clientHeight <= threshold\n}\n","import { useState, type KeyboardEvent } from 'react'\nimport { SendIcon } from './Icons'\n\nexport function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = 'Stop response', sendLabel = 'Send message' }: { placeholder: string; streaming: boolean; onSend: (t: string) => void; onStop: () => void; stopLabel?: string; sendLabel?: string }): JSX.Element {\n const [value, setValue] = useState('')\n const submit = () => { const t = value.trim(); if (!t) return; onSend(t); setValue('') }\n const onKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit() }\n }\n return (\n <div className=\"ss-w-input\">\n <textarea className=\"ss-w-textarea\" rows={1} placeholder={placeholder} value={value} disabled={streaming} onChange={(e) => setValue(e.target.value)} onKeyDown={onKeyDown} />\n {streaming ? (\n <button type=\"button\" className=\"ss-w-send ss-w-stop\" aria-label={stopLabel} onClick={onStop}><span className=\"ss-w-stop-glyph\" /></button>\n ) : (\n <button type=\"button\" className=\"ss-w-send\" aria-label={sendLabel} onClick={submit}><SendIcon /></button>\n )}\n </div>\n )\n}\n","import type { LiveMonitorController, MonitorTab } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\n\nexport function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday, gamesEnabled }: {\n monitor: LiveMonitorController\n ui: UiConfig\n matchCount: number\n oddsCount: number\n /** Live match count. NEVER the fixture count -- a Saturday would badge 41. */\n todayCount: number\n hasToday: boolean\n /** Enabled when getGames resolves non-null; false for betting operators (404 sentinel). */\n gamesEnabled?: boolean\n}): JSX.Element | null {\n const tabs: { tab: MonitorTab; label: string; count: number; dot: boolean }[] = [\n { tab: 'chat', label: ui.tabChat, count: 0, dot: monitor.chatDot },\n ...(hasToday ? [{ tab: 'today' as MonitorTab, label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : []),\n ...(matchCount > 0 ? [{ tab: 'following' as MonitorTab, label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : []),\n ...(oddsCount > 0 ? [{ tab: 'odds' as MonitorTab, label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []),\n ...(gamesEnabled ? [\n { tab: 'games' as MonitorTab, label: ui.tabGames, count: 0, dot: false },\n { tab: 'leaderboard' as MonitorTab, label: ui.tabLeaderboard, count: 0, dot: false },\n ] : []),\n ]\n\n // A lone Chat tab is chrome that selects nothing -- the strip stays hidden, as it does today\n // when nothing is pinned.\n if (tabs.length < 2) return null\n\n return (\n <div className=\"ss-w-tabs\" role=\"tablist\">\n {tabs.map(({ tab, label, count, dot }) => {\n const active = monitor.activeTab === tab\n return (\n <button\n key={tab}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n data-on={active ? '' : undefined}\n className=\"ss-w-tab\"\n onClick={() => monitor.setActiveTab(tab)}\n >\n {label}\n {count > 0 && <span className=\"ss-w-tab-count\">{count}</span>}\n {dot && !active && <span className=\"ss-w-tab-dot\" aria-hidden=\"true\" />}\n </button>\n )\n })}\n </div>\n )\n}\n","import type { LiveMonitorMatch } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { toMarketOddsVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\n\nexport function MarketAccordion({ match, monitor, ui, slip }: {\n match: LiveMonitorMatch\n monitor: LiveMonitorController\n ui: UiConfig\n slip: SlipHandlerProps\n}): JSX.Element | null {\n const slipState = useSlipState()\n const markets = match.availableMarkets ?? []\n if (markets.length === 0) return null\n const open = monitor.openMarket[match.matchId] ?? null\n\n return (\n <div className=\"ss-w-acc\">\n {markets.map((m) => {\n // A suspended market has no servable card: the odds lookup drops every suspended/stopped\n // row, so /live-monitor/market answers 404 MarketNotPriced and the panel lands on the\n // tap-to-retry affordance, which can never succeed. Don't offer the tap. `&& !m.suspended`\n // also collapses a market that suspends WHILE open, instead of leaving stale rows up.\n const isOpen = open === m.marketDeveloperName && !m.suspended\n const key = `${match.matchId}:${m.marketDeveloperName}`\n const entry = monitor.marketOdds[key]\n return (\n <div key={m.marketDeveloperName} className={isOpen ? 'ss-w-acc-row ss-w-acc-row-open' : 'ss-w-acc-row'}>\n <div className=\"ss-w-acc-head\">\n <button\n type=\"button\"\n className={m.suspended ? 'ss-w-acc-toggle ss-w-acc-toggle--susp' : 'ss-w-acc-toggle'}\n aria-expanded={isOpen}\n disabled={m.suspended}\n onClick={() => monitor.toggleMarket(match.matchId, m.marketDeveloperName)}\n >\n <span className=\"ss-w-acc-chevron\">{m.suspended ? '' : isOpen ? '▾' : '▸'}</span>\n <span className=\"ss-w-acc-label\">{m.marketLabel}</span>\n {m.hasInsight && <span className=\"ss-w-acc-badge\">★</span>}\n {m.suspended && <span className=\"ss-w-acc-susp\">{ui.accordionSuspended}</span>}\n </button>\n </div>\n {isOpen && (\n <div className=\"ss-w-acc-panel\">\n {entry?.error && (\n <div\n className=\"ss-w-acc-retry\"\n onClick={() => monitor.retryMarket(match.matchId, m.marketDeveloperName)}\n >\n {ui.accordionRetry}\n </div>\n )}\n {entry?.block?.insight?.text && (\n <div className=\"ss-w-acc-insight\">{entry.block.insight.text}</div>\n )}\n {entry?.block?.card && (\n <MarketOddsCardList\n cards={[toMarketOddsVM(entry.block.card)]}\n ui={ui}\n slip={slip}\n monitor={monitor}\n inSlipIds={slipState?.added}\n hideHeader\n />\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { ChatGrounding, LiveMonitorFact } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\n\nexport type AskHandler = (text: string, grounding: ChatGrounding) => void\n\n// Spec §6: the newest fact under the score, one at a time; earlier ones expand below it. A fact\n// with no market (unpriced, suspended, or a record) renders without the chip row at all.\nexport function LiveFactBlock({ facts, matchId, ui, slip, onAsk }: {\n facts: LiveMonitorFact[]\n matchId: number\n ui: UiConfig\n slip: SlipHandlerProps\n onAsk?: AskHandler\n}): JSX.Element | null {\n const [expanded, setExpanded] = useState(false)\n const [current, ...earlier] = facts\n if (!current) return null\n const m = current.market\n return (\n <section className=\"ss-w-fact\" aria-label={ui.liveFactLabel}>\n <div className=\"ss-w-fact-k\">\n <span>{ui.liveFactLabel}</span>\n <span className=\"ss-w-fact-min\">· {current.minuteLabel}</span>\n <span className=\"ss-w-fact-subj\">{current.subjectLabel}</span>\n </div>\n <p className=\"ss-w-fact-text\">{current.text}</p>\n <div className=\"ss-w-fact-basis\">{current.basis}</div>\n {m && !m.isSuspended && (\n <div className=\"ss-w-fact-mkt\">\n <span>{m.marketLabel} · {m.selectionLabel}</span>\n <span className=\"ss-w-mon-stat-mkt-right\">\n {typeof m.price === 'number' && <span className=\"ss-w-mon-price\">{m.price.toFixed(2)}</span>}\n <SlipButton\n selection={chipSelection(m, matchId, slip.conversationId)}\n shownOdds={typeof m.price === 'number' ? m.price.toFixed(2) : ''}\n marketDeveloperName={m.marketDeveloperName}\n selectionLabel={m.selectionLabel}\n slip={slip}\n ui={ui}\n />\n </span>\n </div>\n )}\n {expanded && earlier.length > 0 && (\n <ul className=\"ss-w-fact-hist\">\n {earlier.map((f) => (\n <li key={f.id}>\n <span className=\"ss-w-fact-hmin\">{f.minuteLabel}</span>\n <div>\n <p className=\"ss-w-fact-htext\">{f.text}</p>\n <div className=\"ss-w-fact-basis\">{f.basis}</div>\n </div>\n </li>\n ))}\n </ul>\n )}\n <div className=\"ss-w-fact-foot\">\n {onAsk && (\n <button type=\"button\" className=\"ss-w-fact-link\"\n onClick={() => onAsk(current.text, { kind: 'liveFact', matchId, subject: current.text.slice(0, 400) })}>\n {ui.liveFactAsk}\n </button>\n )}\n {earlier.length > 0 && (\n <button type=\"button\" className=\"ss-w-fact-link ss-w-fact-link--muted\" aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}>\n {expanded ? ui.liveFactHideEarlier : ui.liveFactEarlier(earlier.length)}\n </button>\n )}\n </div>\n </section>\n )\n}\n","import type { LiveMonitorEvent, LiveMonitorMatch, LiveMonitorStatRow, PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { MomentumWave } from './dashboard/MomentumWave'\nimport { LiveFactBlock, type AskHandler } from './LiveFactBlock'\nimport { PinToggle } from './PinToggle'\nimport { MatchLink } from './MatchLink'\n\n// A stat row's market chip promotes to the top when the user has pinned that market -- matched by\n// FIELD, never by a reconstructed pin key. LiveMonitorStatPrice carries no `line`, and its\n// selectionLabel is server-localized (TR \"2.5 Üst\" vs the stored pin's raw \"Over\"), so any key\n// string built from the chip would never equal the stored pin's key. marketDeveloperName is the\n// one field both sides always share in its raw, unlocalized form; matchOddsId is an unambiguous\n// same-selection identifier when both sides carry it.\nfunction isPromoted(row: LiveMonitorStatRow, promotedPins: readonly PinRef[]): boolean {\n const chip = row.market\n if (!chip) return false\n return promotedPins.some((pin) =>\n pin.marketDeveloperName === chip.marketDeveloperName ||\n (chip.matchOddsId != null && pin.matchOddsId === chip.matchOddsId))\n}\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface ScorerLine { player: string; label: string }\n\n// One line per scorer for a single side, in the order goals were scored, with a brace collapsed\n// onto that scorer's line (\"Powell 87', 90+6'\"). An own goal carries an \"(OG)\" marker on its\n// minute. Goals arrive already ascending from the server; grouping by name preserves that order\n// via the first appearance of each scorer.\nfunction groupScorers(goals: LiveMonitorEvent[], ownGoalLabel: string): ScorerLine[] {\n const order: string[] = []\n const minutesByPlayer = new Map<string, string[]>()\n for (const g of goals) {\n const name = g.player ?? ''\n const minute = g.ownGoal ? `${g.minuteLabel} (${ownGoalLabel})` : g.minuteLabel\n if (!minutesByPlayer.has(name)) {\n minutesByPlayer.set(name, [])\n order.push(name)\n }\n minutesByPlayer.get(name)!.push(minute)\n }\n return order.map((name) => {\n const minutes = minutesByPlayer.get(name)!.join(', ')\n return { player: name, label: name ? `${name} ${minutes}` : minutes }\n })\n}\n\nexport function MonitorMatchCard({ match, promotedPins, monitor, ui, slip, onAsk }: {\n match: LiveMonitorMatch\n /** the user's non-match pins on this match — their stat rows promote to the top strip */\n promotedPins: PinRef[]\n monitor: LiveMonitorController\n ui: UiConfig\n slip: SlipHandlerProps\n onAsk?: AskHandler\n}): JSX.Element {\n const live = match.phase === 'live'\n const goals = match.events.filter((e) => e.type === 'goal')\n const homeScorers = groupScorers(goals.filter((e) => e.side === 'home'), ui.ownGoalLabel)\n const awayScorers = groupScorers(goals.filter((e) => e.side === 'away'), ui.ownGoalLabel)\n const promotedRows = match.statRows.filter((row) => isPromoted(row, promotedPins))\n const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins))\n const orderedRows = [...promotedRows, ...otherRows]\n const kickoff = match.phase === 'preMatch' && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : undefined\n\n return (\n <div className=\"ss-w-mon\">\n <div className=\"ss-w-mon-top\">\n {live && (\n <span className=\"ss-w-fandash-live-pill\">\n <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n {ui.liveLabel}\n </span>\n )}\n {match.phase === 'fullTime' && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n {kickoff && <span className=\"ss-w-mon-pill\">{kickoff.dayLabel} · {kickoff.time}</span>}\n {live && match.minuteLabel && <span className=\"ss-w-mon-min\">{match.minuteLabel}</span>}\n {match.competitionName && <span className=\"ss-w-mon-comp\">{match.competitionName}</span>}\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n </div>\n <MatchLink\n as=\"div\"\n matchId={match.matchId}\n home={match.homeTeamName}\n away={match.awayTeamName}\n detail={match.phase !== 'preMatch' ? `${match.homeScore}–${match.awayScore}` : undefined}\n className=\"ss-w-mon-main\"\n >\n <span className=\"ss-w-mon-side\">\n <Crest kind=\"team\" url={match.homeCrestUrl ?? undefined} name={match.homeTeamName ?? undefined} />\n <span className=\"ss-w-mon-name\">{match.homeTeamName}</span>\n </span>\n {match.phase === 'preMatch' ? (\n <span className=\"ss-w-mon-vs\">vs</span>\n ) : (\n <span className=\"ss-w-mon-score\">{match.homeScore}<i>–</i>{match.awayScore}</span>\n )}\n <span className=\"ss-w-mon-side ss-w-mon-side--away\">\n <Crest kind=\"team\" url={match.awayCrestUrl ?? undefined} name={match.awayTeamName ?? undefined} />\n <span className=\"ss-w-mon-name\">{match.awayTeamName}</span>\n </span>\n </MatchLink>\n {(homeScorers.length > 0 || awayScorers.length > 0) && (\n <div className=\"ss-w-mon-scorers\">\n <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-home\">\n {homeScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n </ul>\n <span className=\"ss-w-mon-scorers-ball\" aria-hidden=\"true\">⚽</span>\n <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-away\">\n {awayScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n </ul>\n </div>\n )}\n {live && match.facts && match.facts.length > 0 && (\n <LiveFactBlock facts={match.facts} matchId={match.matchId} ui={ui} slip={slip} onAsk={onAsk} />\n )}\n <div className=\"ss-w-mon-stats\">\n {orderedRows.map((row) => {\n const total = row.homeNum + row.awayNum\n const homePct = total > 0 ? (row.homeNum / total) * 75 : 0\n const awayPct = total > 0 ? (row.awayNum / total) * 75 : 0\n const promoted = isPromoted(row, promotedPins)\n const selection = chipSelection(row.market, match.matchId, slip.conversationId)\n return (\n <div className={promoted ? 'ss-w-mon-stat ss-w-mon-pstrip' : 'ss-w-mon-stat'} key={row.label}>\n <div className=\"ss-w-mon-stat-row\">\n <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--home\">{row.homeValue}</span>\n <span className=\"ss-w-mon-stat-l\">{row.label}</span>\n <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--away\">{row.awayValue}</span>\n </div>\n <div className=\"ss-w-mon-bar\">\n <b className=\"ss-w-mon-bar-home\" style={{ width: `${homePct}%` }} />\n <i className=\"ss-w-mon-bar-away\" style={{ width: `${awayPct}%` }} />\n </div>\n {/* A suspended market drops its whole betting line -- label, price and button -- and\n the stat row keeps its bar, exactly like a row with no market at all. Showing it\n offered a price the bookmaker was not taking next to a live Add to slip whose\n only possible outcome was the slipSuspended error toast. bet365 suspends\n derivative in-play markets constantly: measured across 20 live matches, 61% of\n Goals Over/Under rows and 69% of 1st Half Goals rows were suspended against 9%\n of Fulltime Result. */}\n {row.market && !row.market.isSuspended && (\n <div className={promoted ? 'ss-w-mon-stat-mkt ss-w-mon-mkt' : 'ss-w-mon-stat-mkt'}>\n <span>{row.market.marketLabel} · {row.market.selectionLabel}</span>\n <span className=\"ss-w-mon-stat-mkt-right\">\n {typeof row.market.price === 'number' && <span className=\"ss-w-mon-price\">{row.market.price.toFixed(2)}</span>}\n <SlipButton\n selection={selection}\n shownOdds={typeof row.market.price === 'number' ? row.market.price.toFixed(2) : ''}\n marketDeveloperName={row.market.marketDeveloperName}\n selectionLabel={row.market.selectionLabel}\n slip={slip}\n ui={ui}\n />\n </span>\n </div>\n )}\n </div>\n )\n })}\n </div>\n {match.status === 'stale' && <span className=\"ss-w-mon-asof\">{ui.asOf(formatTime(match.asOfUtc))}</span>}\n {match.momentum.length > 0 && (\n <div className=\"ss-w-mon-mom\">\n {/* Label only -- no percentage split. momentumHomePct is a share of the WHOLE match's\n accumulated pressure, so it reads as a verdict on the match (\"99% - 1%\") when the\n wave beneath it is showing minute-by-minute swing. The two disagree on sight, and\n the share is the one that misleads. */}\n <span className=\"ss-w-mon-stat-l\">{ui.momentumLabel}</span>\n <MomentumWave points={match.momentum} clubIsHome={true} />\n </div>\n )}\n {match.phase === 'fullTime' && <div className=\"ss-w-mon-grace\">{ui.graceNote}</div>}\n </div>\n )\n}\n","import type { LiveMonitorMarket } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { MarketOddsRowVM, MarketOddsVM } from '../model'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { MarketAccordion } from './MarketAccordion'\nimport { MonitorMatchCard } from './MonitorMatchCard'\nimport { toMarketOddsVM, toOddsMovementVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\nimport type { AskHandler } from './LiveFactBlock'\n\n// Slim live-only strip above an Odds-tab market card. The card itself already shows the\n// competition, fixture, market, kickoff and the unpin — so this renders ONLY the match-live\n// context the card lacks (score, minute, suspended/settled, stale as-of), and nothing at all for\n// a pre-match market (avoids duplicating the card's fixture/kickoff). (u342)\nfunction OddsLiveStrip({ m, ui }: { m: LiveMonitorMarket; ui: UiConfig }): JSX.Element | null {\n const showScore = m.phase !== 'preMatch' && typeof m.homeScore === 'number'\n const stale = m.status === 'stale'\n if (!showScore && !m.minuteLabel && !(m.isSuspended && !m.isSettled) && !m.isSettled && !stale) return null\n return (\n <div className=\"ss-w-mk-live\">\n {showScore && (\n <b className=\"ss-w-mk-live-score\">{m.homeTeamName} {m.homeScore}–{m.awayScore} {m.awayTeamName}</b>\n )}\n {m.minuteLabel && <span className=\"ss-w-mon-min\">{m.minuteLabel}</span>}\n {m.isSuspended && !m.isSettled && <span className=\"ss-w-mon-susp\">{ui.suspendedLabel}</span>}\n {m.isSettled && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n {stale && (\n <span className=\"ss-w-mon-asof\">{ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }))}</span>\n )}\n </div>\n )\n}\n\nexport function MatchesPanel({ monitor, ui, slip, onAsk }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps; onAsk?: AskHandler }): JSX.Element {\n // Only EXPLICIT match pins surface here (2026-09-06 ruling: an odds pin tracks odds, a match\n // pin tracks the match -- never combined). Filtering against current pins, not just the\n // snapshot, also makes an unpin drop the card immediately.\n const matches = (monitor.snapshot?.matches ?? []).filter((m) =>\n monitor.pins.some((p) => p.kind === 'match' && p.matchId === m.matchId))\n if (matches.length === 0) return <div className=\"ss-w-mon-empty\">{ui.emptyMatchesTab}</div>\n return (\n <div className=\"ss-w-mon-list\">\n {matches.map((m) => (\n <div key={m.matchId} className=\"ss-w-mon-item\">\n <MonitorMatchCard\n match={m}\n // promotion is PER MATCH: only odds pins on THIS match promote their stat row\n promotedPins={monitor.pins.filter((p) => p.kind !== 'match' && p.matchId === m.matchId)}\n monitor={monitor}\n ui={ui}\n slip={slip}\n onAsk={onAsk}\n />\n <MarketAccordion match={m} monitor={monitor} ui={ui} slip={slip} />\n </div>\n ))}\n </div>\n )\n}\n\n// I2 (since-view movement): the badge on a pin's PRIMARY row must reflect what THIS operator's\n// client last saw (monitor.lastViewedPrices, keyed by the market snapshot's own key), never the\n// server's own previousPrice/movementDirection window -- those two clocks are unrelated. Only the\n// first main row carries this override; other rows/lines keep whatever (if anything) the server\n// sent.\nfunction withSinceViewMovement(vm: MarketOddsVM, prev: number | undefined): MarketOddsVM {\n const primary = vm.mainRows[0]\n if (prev === undefined || !primary || primary.oddsDecimal === undefined || primary.oddsDecimal === prev) return vm\n const updatedPrimary: MarketOddsRowVM = {\n ...primary,\n previousOdds: prev.toFixed(2),\n movementDirection: primary.oddsDecimal < prev ? 'shortened' : 'drifted',\n }\n return { ...vm, mainRows: [updatedPrimary, ...vm.mainRows.slice(1)] }\n}\n\nexport function OddsPanel({ monitor, ui, slip }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const slipState = useSlipState()\n // Same current-pins filter as MatchesPanel: only markets a stored pin still claims render, so\n // every card carries its unpin affordance and vanishes the moment that pin is removed.\n const markets = (monitor.snapshot?.markets ?? []).filter((m) =>\n monitor.pins.some((p) => p.key === m.key))\n if (markets.length === 0) return <div className=\"ss-w-mon-empty\">{ui.emptyOddsTab}</div>\n return (\n <div className=\"ss-w-mon-list\">\n {markets.map((m) => {\n // The unpin lives in the card's own header now; pass the ORIGINAL stored pin ref (found by\n // key) so its pinKey matches exactly -- the card would otherwise reconstruct a market pin\n // with line=mainLine, which never matches an accordion pin stored without a line.\n const pin = monitor.pins.find((p) => p.key === m.key)\n return (\n <div className=\"ss-w-mon-oddspin\" key={m.key} data-settled={m.isSettled || undefined}>\n <OddsLiveStrip m={m} ui={ui} />\n {/* D5 persistent in-slip badge: the wasAdded->markAdded wrapping lives in StatsWidget's\n own slip memo (so a conversation-path add also arms the badge) -- this panel only\n reads the widget's slip state to render it. */}\n {m.card && (\n <MarketOddsCardList\n cards={[withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])]}\n ui={ui}\n slip={slip}\n monitor={monitor}\n pinRef={pin ?? undefined}\n inSlipIds={slipState?.added}\n />\n )}\n {m.history && <OddsMovementCardList cards={[toOddsMovementVM(m.history)]} ui={ui} />}\n {!m.card && !m.history && <div className=\"ss-w-mon-empty-card\">{ui.oddsUnavailable}</div>}\n </div>\n )\n })}\n </div>\n )\n}\n","import type { MatchState, ScheduleMatch } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { PinToggle } from './PinToggle'\nimport { MatchLink } from './MatchLink'\n\nfunction kickoffLabel(kickoffUnix: number): string {\n const d = new Date(kickoffUnix * 1000)\n return `${`${d.getHours()}`.padStart(2, '0')}:${`${d.getMinutes()}`.padStart(2, '0')}`\n}\n\n// The away side mirrors the home side around the score: crest on the far (right)\n// edge, name aligned inward toward the score. Reversing the flow in CSS keeps the\n// DOM order crest→name identical to home, matching the away pattern used by the\n// fandash fixture/live cards.\nfunction Side({ name, crest, away = false }: { name: string; crest?: string | null; away?: boolean }): JSX.Element {\n return (\n <span className={away ? 'ss-w-drow-side ss-w-drow-side--away' : 'ss-w-drow-side'}>\n {crest ? <img className=\"ss-w-drow-crest\" src={crest} alt=\"\" /> : null}\n <span className=\"ss-w-drow-nm\">{name}</span>\n </span>\n )\n}\n\nexport function FixtureRow({ match, state, stale, ui, monitor }: {\n match: ScheduleMatch\n state?: MatchState\n stale: boolean\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element {\n // Deliberately no per-match staleness test. u357 added one, reading Match.UpdatedAt through\n // stateAsOfUtc — but that column advances only when the DATA CHANGES, not when we poll. Measured\n // on sandbox1: every live match had a poll age of 31-48s while UpdatedAt ages ran 32-1451s, so\n // the guard suppressed the clock on 9 of 17 healthy matches, Levante v Barcelona among them. The\n // stalled window it was built for does not exist; `stale` (our own fetch failing) is the only\n // real signal we have, and it already covers the whole payload.\n const isLive = state?.phase === 'live' && !stale\n // Gated on phase, never on the presence of a number: /states counts goal rows, so it reports 0\n // for a fixture with none whatever its phase, and the due set polls anything whose kickoff clock\n // has passed. A \"NotStarted\" fixture between the clock passing and the live feed flipping would\n // otherwise read 0-0. The typeof pair only narrows the template below.\n const hasScore = (state?.phase === 'live' || state?.phase === 'fullTime')\n && typeof state.homeScore === 'number' && typeof state.awayScore === 'number'\n const score = hasScore ? `${state!.homeScore}–${state!.awayScore}` : undefined\n\n // Rendered verbatim. The minute runs ~2 min behind wall clock because the provider's own\n // `minutes` field is a snapshot we freeze until the next poll -- that is being corrected at the\n // source in the hub (deriving from the ticking period's start), NOT compensated for here. Two\n // layers each adding elapsed to the same number is how you get a 139th minute.\n const ticked = state?.phase === 'live' ? (state.minuteLabel ?? null) : null\n const when = state?.isHalfTime && !stale\n ? ui.halfTime\n : isLive\n ? (ticked ?? '\\u2014')\n : state?.phase === 'live'\n ? '\\u2014'\n : kickoffLabel(match.kickoffUnix)\n\n return (\n <div className={isLive || state?.isHalfTime ? 'ss-w-drow ss-w-drow--live' : 'ss-w-drow'}>\n <span className={isLive || state?.isHalfTime ? 'ss-w-drow-when ss-w-drow-when--live' : 'ss-w-drow-when'}>{when}</span>\n <MatchLink matchId={match.matchId} home={match.homeTeamName} away={match.awayTeamName} detail={score} className=\"ss-w-drow-fx\">\n <Side name={match.homeTeamName} crest={match.homeTeamImagePath} />\n {/* The score sits between the two sides, where a scoreboard puts it. With no score yet it\n is the separating dash, so the row keeps one shape before and after kickoff. */}\n <span className={hasScore ? 'ss-w-drow-sc' : 'ss-w-drow-sc ss-w-drow-sc--idle'}>\n {score ?? '–'}\n </span>\n <Side name={match.awayTeamName} crest={match.awayTeamImagePath} away />\n </MatchLink>\n <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n </div>\n )\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\n\n/**\n * The single question \"is this match being presented as live right now\". Both sides of the seam\n * must ask it the same way: TodayPanel uses it to pick the live band, CompetitionGroup uses its\n * negation to decide what stays in the group. If the two ever disagree a match falls through the\n * gap and renders nowhere — that is a defect this codebase has already shipped once.\n *\n * `pollStale` is OUR fetch failing, which is a real reason to stop trusting every state at once.\n * There is deliberately no per-match staleness test here; see the note in FixtureRow.\n */\nexport function isTreatedLive(state: MatchState | undefined, pollStale: boolean): boolean {\n return state?.phase === 'live' && !pollStale\n}\n\n/**\n * A match the Today tab has no reason to keep listing. The schedule endpoint already excludes\n * terminal matches server-side (LiveMonitorScheduleComposer filters Match.MatchState), but the\n * client caches a day's schedule in localStorage for six hours — so a match that finishes while\n * the panel is open would linger in a list a fresh load would not show it in. This closes that\n * gap so both paths agree.\n *\n * fullTime only, deliberately. `postponed` arises server-side when a fixture has no kickoff\n * timestamp, which the schedule query already excludes, and hiding a postponed fixture from the\n * day it was scheduled for would be a different decision than the one being made here.\n */\nexport function isFinished(state: MatchState | undefined): boolean {\n return state?.phase === 'fullTime'\n}\n\n/**\n * What the Today tab actually contains, after the finished matches leave. This is the ONE answer\n * both the panel and the tab strip read: TodayPanel renders it, and `hasToday` decides from its\n * length whether the tab exists at all. Deciding the tab from the raw schedule instead is what\n * shipped a Today tab opening onto a blank panel once every match of the day had ended.\n */\nexport function visibleGroupsOf(\n groups: readonly ScheduleGroup[],\n states: Record<number, MatchState>,\n): ScheduleGroup[] {\n return groups\n .map((group) => ({ ...group, matches: group.matches.filter((m) => !isFinished(states[m.matchId])) }))\n .filter((group) => group.matches.length > 0)\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { FixtureRow } from './FixtureRow'\nimport { isTreatedLive } from '../liveClock'\n\nexport function CompetitionGroup({ group, open, onToggle, states, stale, ui, monitor, disambiguate = false }: {\n group: ScheduleGroup\n open: boolean\n onToggle(): void\n /** True when another group on screen shares this competition's name, so the name alone\n * does not identify it. Only then is the country worth the horizontal space. */\n disambiguate?: boolean\n states: Record<number, MatchState>\n stale: boolean\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element | null {\n // A live fixture is rendered in the live band above, so it is absent here AND absent from the\n // count -- the badge has to agree with what is under the header. But once the poll goes stale\n // the live band hides itself (Task 13), so a cached phase:'live' match must fall back into its\n // group rather than vanish from the tab entirely -- mirrors FixtureRow's own isLive check.\n const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale))\n const hasLive = own.length !== group.matches.length\n\n // Every match hoisted into the live band leaves nothing under this header. Rendering anyway\n // produced a header reading \"Championship ... 0\" whose body was empty however you toggled it.\n // Hiding it is safe against the vanish bug the filter above guards: when the poll goes stale\n // isTreatedLive is false for everything, so own is the full list and the group comes back.\n if (own.length === 0) {\n return null\n }\n\n return (\n <div className=\"ss-w-grp\">\n <button type=\"button\" className=\"ss-w-grp-head\" aria-expanded={open} onClick={onToggle}>\n <span className=\"ss-w-grp-chev\">{open ? '▾' : '▸'}</span>\n {hasLive && <span className=\"ss-w-sec-dot\" aria-hidden=\"true\" />}\n <span className=\"ss-w-grp-name\">\n {group.competitionName}\n {disambiguate && group.competitionCountry\n ? <span className=\"ss-w-grp-country\"> ({group.competitionCountry})</span>\n : null}\n </span>\n <span className=\"ss-w-grp-count\">{own.length}</span>\n </button>\n {open && (\n <div className=\"ss-w-grp-body\">\n {own.map((m) => (\n <FixtureRow key={m.matchId} match={m} state={states[m.matchId]} stale={stale} ui={ui} monitor={monitor} />\n ))}\n </div>\n )}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport { CompetitionGroup } from './CompetitionGroup'\nimport { FixtureRow } from './FixtureRow'\nimport { isTreatedLive, visibleGroupsOf } from '../liveClock'\n\nexport function TodayPanel({ discovery, ui, monitor }: {\n discovery: MatchDiscoveryController\n ui: UiConfig\n monitor: LiveMonitorController\n}): JSX.Element {\n const { groups, states, stale, expanded, toggleGroup } = discovery\n\n // Finished matches leave the day. Everything below reads visibleGroups, never groups: the live\n // band, the name-collision count, the group list and the tab strip that decides whether this\n // panel is reachable at all have to agree on what the day contains, and filtering in one place\n // is what guarantees that.\n const visibleGroups = visibleGroupsOf(groups, states)\n\n // Flat across competitions but ordered by the competition's rank, then by the fixture's position\n // inside its group -- no ranking field of the client's own. Array.sort is stable, so ties within\n // a rank keep the flatMap's group-then-match order.\n // The sort is NOT dead code: `rank` is the contract, the array order is not. That the composer\n // currently emits groups already in rank order is incidental -- nothing in the wire format\n // promises it, and a server-side reordering would silently scramble the live band without this.\n const liveRows = stale\n ? []\n : visibleGroups\n .flatMap((group) =>\n group.matches\n .filter((m) => isTreatedLive(states[m.matchId], stale))\n .map((match) => ({ match, rank: group.rank })))\n .sort((a, b) => a.rank - b.rank)\n\n // competitionName is not an identity: a real Saturday returns four groups named \"Premier\n // League\". Only collide-on-screen names pay the horizontal cost of a country suffix.\n const nameCounts = visibleGroups.reduce<Record<string, number>>((acc, g) => {\n acc[g.competitionName] = (acc[g.competitionName] ?? 0) + 1\n return acc\n }, {})\n\n return (\n <div className=\"ss-w-mon-list\">\n {stale && <div className=\"ss-w-stale\">{ui.staleStates}</div>}\n\n {liveRows.length > 0 && (\n <>\n <div className=\"ss-w-sec-head\">\n <span className=\"ss-w-sec-dot\" aria-hidden=\"true\" />\n {ui.sectionLive}\n </div>\n <div className=\"ss-w-today-live\">\n {liveRows.map(({ match }) => (\n <FixtureRow key={match.matchId} match={match} state={states[match.matchId]}\n stale={stale} ui={ui} monitor={monitor} />\n ))}\n </div>\n </>\n )}\n\n {visibleGroups.map((group) => (\n <CompetitionGroup\n key={group.competitionId}\n group={group}\n open={expanded[group.competitionId] ?? group.expandedByDefault}\n onToggle={() => toggleGroup(group.competitionId)}\n disambiguate={(nameCounts[group.competitionName] ?? 0) > 1}\n states={states}\n stale={stale}\n ui={ui}\n monitor={monitor}\n />\n ))}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { GamesHub } from './GamesHub'\nimport { GameScreenHost } from './GameScreenHost'\nimport { ensureGamesFonts } from './games/ui/fonts'\n\nexport function GamesPanel({\n loggedIn,\n games,\n ui,\n conversation,\n leaderboard,\n refreshHub,\n}: {\n loggedIn: boolean\n games: GameSummary[]\n ui: UiConfig\n conversation?: GamePlayConversation | null\n leaderboard?: LeaderboardPayload | null\n /** Called when a play is saved and when the fan leaves a game screen, so the hub's tiles and stat row reflect the play. */\n refreshHub?: () => void\n}): JSX.Element {\n const [selected, setSelected] = useState<{ gameId: string; fixtureId: number; gameDay: string; lockAtUtc: string | null } | null>(null)\n\n useEffect(() => { ensureGamesFonts() }, [])\n\n if (!loggedIn) return <GamesLoginWall ui={ui} />\n\n if (selected !== null) {\n return (\n <div className=\"ss-w-gscreen-wrap\" lang={ui.games.lang}>\n <GameScreenHost\n selected={selected}\n onBack={() => { setSelected(null); refreshHub?.() }}\n onPlayed={refreshHub}\n conversation={conversation ?? null}\n ui={ui}\n />\n </div>\n )\n }\n\n return (\n <div className=\"ss-g-hub-wrap\" data-testid=\"games-hub\" lang={ui.games.lang}>\n <GamesHub\n games={games}\n onOpen={(g: GameSummary) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId, gameDay: g.gameDay, lockAtUtc: g.lockAtUtc ?? null })}\n myWeeklyRow={leaderboard?.myWeeklyRow ?? null}\n ui={ui}\n />\n </div>\n )\n}\n","import type { UiConfig } from '../config'\n\nexport function GamesLoginWall({ ui }: { ui: UiConfig }): JSX.Element {\n return (\n <div className=\"ss-w-mon-list\">\n <div className=\"ss-w-games-wall\">\n <p>{ui.gamesLoginRequired}</p>\n </div>\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GameTile } from './GameTile'\nimport { Chip } from './games/ui/Chip'\nimport { IconFlame } from './games/ui/icons'\n\nconst PLAYABLE = new Set<GameSummary['status']>(['available', 'in_progress'])\nconst DONE = new Set<GameSummary['status']>(['played', 'graded'])\n\nexport function pickHeroGame(games: GameSummary[]): GameSummary | null {\n const daily = games.filter(g => g.kind === 'daily')\n const tiger = daily.find(g => g.gameId === 'mystery-tiger')\n if (tiger && PLAYABLE.has(tiger.status)) return tiger\n const firstPlayable = daily.find(g => PLAYABLE.has(g.status))\n if (firstPlayable) return firstPlayable\n return tiger ?? daily[0] ?? null\n}\n\n// Two fixtures of one game on one day must not share a key.\nexport const tileKey = (g: GameSummary): string => `${g.gameId}-${g.gameDay}-${g.fixtureId}`\n\nexport function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }: {\n games: GameSummary[]\n myWeeklyRow?: LeaderboardRow | null\n weeklyPrize?: string\n onOpen: (g: GameSummary) => void\n ui: UiConfig\n}): JSX.Element {\n const [, setTick] = useState(0)\n useEffect(() => {\n const id = setInterval(() => setTick(t => t + 1), 60_000)\n return () => clearInterval(id)\n }, [])\n\n const hero = pickHeroGame(games)\n const daily = games.filter(g => g.kind === 'daily' && g !== hero)\n const grid = daily.filter(g => g.gameId !== 'beat-the-grid')\n const wide = daily.find(g => g.gameId === 'beat-the-grid')\n const fixtures = games.filter(g => g.kind === 'fixture')\n const kickoffs = fixtures.map(g => g.kickoffUtc).filter((k): k is string => !!k).sort()\n const todayPts = games.filter(g => DONE.has(g.status)).reduce((s, g) => s + (g.score ?? 0), 0)\n const dash = '—'\n\n return (\n <div className=\"ss-g-hub\">\n <div className=\"ss-g-stats\">\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statStreak}</span>\n <span className=\"ss-g-stat-v\" data-testid=\"stat-streak\">\n {myWeeklyRow ? <><IconFlame />{myWeeklyRow.currentStreak}</> : dash}\n {myWeeklyRow && <small>{ui.games.unitDays}</small>}\n </span></div>\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statToday}</span>\n <span className=\"ss-g-stat-v ss-g-stat-v--accent\" data-testid=\"stat-today\">{ui.games.formatPts(todayPts)}<small>{ui.games.unitPts}</small></span></div>\n <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statRank}</span>\n <span className=\"ss-g-stat-v\" data-testid=\"stat-rank\">{myWeeklyRow ? `#${myWeeklyRow.rank}` : dash}\n {myWeeklyRow && <small>{ui.games.thisWeek}</small>}</span></div>\n </div>\n\n {weeklyPrize && <Chip variant=\"accent\" className=\"ss-g-prize\">{weeklyPrize}</Chip>}\n\n {hero && <GameTile game={hero} onOpen={onOpen} ui={ui} variant=\"hero\" />}\n\n {(grid.length > 0 || wide) && (\n <section className=\"ss-g-sec\">\n <div className=\"ss-g-sec-head\"><h3>{ui.games.dailyGames}</h3><span>{ui.games.newSetAtMidnight}</span></div>\n {grid.length > 0 && <div className=\"ss-g-grid\">{grid.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>}\n {wide && <GameTile game={wide} onOpen={onOpen} ui={ui} variant=\"wide\" />}\n </section>\n )}\n\n {fixtures.length > 0 && (\n <section className=\"ss-g-sec\">\n <div className=\"ss-g-sec-head\"><h3>{ui.games.matchdayGames}</h3>\n {kickoffs[0] && <span>{ui.games.kickoffAt(ui.games.formatDayTime(kickoffs[0]))}</span>}</div>\n <div className=\"ss-g-grid\">{fixtures.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>\n </section>\n )}\n </div>\n )\n}\n","function prettifyGameId(gameId: string): string {\n return gameId.split('-').map(w => (w ? w[0]!.toUpperCase() + w.slice(1) : w)).join(' ')\n}\n\n// `title` is nullable because GameSummary.title is `string | null` (widget-sdk events.ts).\n// `titles` is the locale-specific map from GamesStrings — caller passes `ui.games.titles`.\nexport function gameTitle(g: { gameId: string; title?: string | null }, titles: Record<string, string>): string {\n return g.title ?? titles[g.gameId] ?? prettifyGameId(g.gameId)\n}\n\n// Design renders \"first name\" small over \"SURNAME\" big. Surname = last token.\nexport function splitName(full: string): { first: string; last: string } {\n const parts = full.trim().split(/\\s+/).filter(Boolean)\n if (parts.length <= 1) return { first: '', last: parts[0] ?? '' }\n return { first: parts.slice(0, -1).join(' '), last: parts[parts.length - 1]! }\n}\n","export function GameTileArt({ gameId }: { gameId: string }): JSX.Element {\n return (\n <svg className=\"ss-g-art\" viewBox=\"0 0 120 74\" aria-hidden=\"true\">{ART[gameId] ?? ART.default}</svg>\n )\n}\n\nconst head = (cx: number, cy: number, r: number, cls = 'ss-g-art-fg') => (\n <g className={cls}><circle cx={cx} cy={cy - r * 0.3} r={r * 0.45} /><path d={`M${cx - r} ${cy + r}c0-${r * 0.8} ${r * 0.45}-${r * 1.1} ${r}-${r * 1.1}s${r} ${r * 0.3} ${r} ${r * 1.1}z`} /></g>\n)\n\nconst ART: Record<string, JSX.Element> = {\n 'mystery-tiger': <>{head(60, 38, 26, 'ss-g-art-fg')}<text x=\"60\" y=\"36\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n 'higher-or-lower': <>{head(32, 38, 20)}{head(88, 38, 20)}<circle cx=\"60\" cy=\"37\" r=\"11\" className=\"ss-g-art-accent\" /><path d=\"M57 33l3-3 3 3M57 41l3 3 3-3\" className=\"ss-g-art-ink\" /></>,\n 'guess-the-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60, 'a'], [24, 46], [48, 46], [72, 46], [96, 46], [36, 30], [60, 30], [84, 30], [40, 14], [60, 14], [80, 14]].map(([x, y, a], i) => <circle key={i} cx={x as number} cy={y as number} r=\"4\" className={a ? 'ss-g-art-accent' : 'ss-g-art-dot'} />)}</>,\n 'daily-quiz': <>{[[14, 8], [62, 8], [14, 40], [62, 40]].map(([x, y], i) => <rect key={i} x={x} y={y} width=\"44\" height=\"26\" rx=\"5\" className={i === 1 ? 'ss-g-art-correct' : 'ss-g-art-block'} />)}</>,\n 'career-path': <><path d=\"M18 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><path d=\"M48 37h8M84 37h8\" className=\"ss-g-art-line\" /><path d=\"M60 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><rect x=\"96\" y=\"22\" width=\"18\" height=\"26\" rx=\"4\" className=\"ss-g-art-dash\" /><text x=\"105\" y=\"40\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n 'beat-the-grid': <>{[0, 1, 2].flatMap(r => [0, 1, 2].map(c => <rect key={`${r}${c}`} x={33 + c * 19} y={10 + r * 19} width=\"16\" height=\"16\" rx=\"3\" className={(r + c) % 3 === 0 ? 'ss-g-art-accent' : 'ss-g-art-block'} />))}</>,\n 'matchday-predictor': <><path d=\"M10 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /><rect x=\"38\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-accent-stroke\" /><rect x=\"64\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-dash\" /><path d=\"M90 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /></>,\n 'starting-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60], [30, 46], [50, 46], [70, 46], [90, 46], [45, 30], [75, 30], [30, 16], [60, 16], [90, 16]].map(([x, y], i) => <circle key={i} cx={x} cy={y} r=\"5\" className={i < 7 ? 'ss-g-art-accent' : 'ss-g-art-dash'} />)}</>,\n 'stat-ladder': <>{[[20, 70], [34, 52], [48, 34]].map(([y, w], i) => <rect key={i} x=\"24\" y={y} width={w} height=\"12\" rx=\"3\" className={i === 1 ? 'ss-g-art-accent' : 'ss-g-art-block'} />)}</>,\n 'fan-motm': <><circle cx=\"60\" cy=\"37\" r=\"26\" className=\"ss-g-art-accent-stroke\" />{head(60, 40, 18)}<path d=\"M84 8l2.4 5 5.4.6-4 3.7 1.1 5.4-4.9-2.7-4.9 2.7 1.1-5.4-4-3.7 5.4-.6z\" className=\"ss-g-art-accent\" /></>,\n default: <circle cx=\"60\" cy=\"37\" r=\"22\" className=\"ss-g-art-fg\" />,\n}\n","import type { ReactNode } from 'react'\n\nexport type ChipVariant = 'neutral' | 'accent' | 'success' | 'badge' | 'lock'\n\nexport function Chip({ variant = 'neutral', icon, children, className }: {\n variant?: ChipVariant; icon?: ReactNode; children: ReactNode; className?: string\n}): JSX.Element {\n return (\n <span className={`ss-g-chip ss-g-chip--${variant}${className ? ` ${className}` : ''}`}>\n {icon}{children}\n </span>\n )\n}\n\nexport function StatStack({ value, label }: { value: ReactNode; label: string }): JSX.Element {\n return (\n <span className=\"ss-g-statstack\">\n <span className=\"ss-g-statstack-v\">{value}</span>\n <span className=\"ss-g-statstack-l\">{label}</span>\n </span>\n )\n}\n","type P = { size?: number }\nconst svg = (size: number, children: JSX.Element | JSX.Element[], fill = false): JSX.Element => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={fill ? 'currentColor' : 'none'} stroke={fill ? 'none' : 'currentColor'}\n strokeWidth={2.2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">{children}</svg>\n)\nexport const IconChevronLeft = ({ size = 20 }: P) => svg(size, <path d=\"M15 18l-6-6 6-6\" />)\nexport const IconLock = ({ size = 14 }: P) => svg(size, [<rect key=\"a\" x=\"5\" y=\"11\" width=\"14\" height=\"10\" rx=\"2\" />, <path key=\"b\" d=\"M8 11V7a4 4 0 0 1 8 0v4\" />])\nexport const IconCheck = ({ size = 14 }: P) => svg(size, <path d=\"M5 12l5 5 9-10\" />)\nexport const IconClose = ({ size = 16 }: P) => svg(size, <path d=\"M6 6l12 12M18 6L6 18\" />)\nexport const IconSearch = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"11\" cy=\"11\" r=\"7\" />, <path key=\"b\" d=\"M20 20l-3.5-3.5\" />])\nexport const IconPlus = ({ size = 20 }: P) => svg(size, <path d=\"M12 5v14M5 12h14\" />)\nexport const IconStar = ({ size = 14 }: P) => svg(size, <path d=\"M12 2.5l2.9 6 6.6.8-4.9 4.5 1.3 6.5L12 17l-5.9 3.3 1.3-6.5L2.5 9.3l6.6-.8z\" />, true)\nexport const IconBulb = ({ size = 16 }: P) => svg(size, [<path key=\"a\" d=\"M9 18h6M10 21h4\" />, <path key=\"b\" d=\"M12 3a6 6 0 0 0-3.5 10.9V16h7v-2.1A6 6 0 0 0 12 3z\" />])\nexport const IconArrowUp = ({ size = 12 }: P) => svg(size, <path d=\"M12 19V5M5 12l7-7 7 7\" />)\nexport const IconArrowDown = ({ size = 12 }: P) => svg(size, <path d=\"M12 5v14M19 12l-7 7-7-7\" />)\nexport const IconCalendar = ({ size = 18 }: P) => svg(size, [<rect key=\"a\" x=\"4\" y=\"5\" width=\"16\" height=\"15\" rx=\"2\" />, <path key=\"b\" d=\"M4 10h16M9 3v4M15 3v4\" />])\nexport const IconShield = ({ size = 18 }: P) => svg(size, <path d=\"M12 3l7 3v6c0 5-3 8-7 9-4-1-7-4-7-9V6z\" />)\nexport const IconFlag = ({ size = 18 }: P) => svg(size, <path d=\"M5 21V4M5 4h12l-2 4 2 4H5\" />)\nexport const IconBall = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"12\" cy=\"12\" r=\"9\" />, <path key=\"b\" d=\"M12 7l4 3-1.5 4.5h-5L8 10z\" />])\nexport const IconBoot = ({ size = 18 }: P) => svg(size, <path d=\"M4 6h6l1 6 8 3v3H4z\" />)\nexport const IconGloves = ({ size = 18 }: P) => svg(size, <path d=\"M7 21v-8l-2-3V6a1.5 1.5 0 0 1 3 0v3V4a1.5 1.5 0 0 1 3 0v5V3.5a1.5 1.5 0 0 1 3 0V9V5a1.5 1.5 0 0 1 3 0v9l-2 3v4z\" />)\nexport const IconFlame = ({ size = 16 }: P) => svg(size, <path d=\"M12 3c1 4 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-7 1.5 1 2 2 2 3 1-2 1-4 1-6z\" />, true)\n","import type { GameSummary } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { gameTitle } from './games/ui/gameMeta'\nimport { GameTileArt } from './GameTileArt'\nimport { Chip } from './games/ui/Chip'\nimport { IconChevronLeft } from './games/ui/icons'\n\nexport type TileTone = 'new' | 'accent' | 'success' | 'muted'\n\n/** Pure: the tile's status line and tone, from the existing GameSummary fields only. */\nexport function tileStatus(game: GameSummary, ui: UiConfig): { text: string; tone: TileTone } {\n switch (game.status) {\n case 'locked': return { text: ui.gameLocked, tone: 'muted' }\n case 'voided': return { text: ui.gameVoided, tone: 'muted' }\n case 'in_progress': return { text: ui.games.resume, tone: 'accent' }\n case 'played':\n case 'graded':\n return game.ranked\n ? { text: ui.games.doneWithScore(game.score ?? 0), tone: 'success' }\n : { text: ui.games.done, tone: 'success' }\n default:\n if (game.kind === 'fixture' && game.lockAtUtc && new Date(game.lockAtUtc).getTime() > Date.now()) {\n return { text: ui.games.locksAt(ui.games.formatDayTime(game.lockAtUtc)), tone: 'accent' }\n }\n return { text: ui.games.taglines[game.gameId] ?? ui.gamePlay, tone: 'new' }\n }\n}\n\nconst DISABLED = new Set<GameSummary['status']>(['locked', 'voided'])\n\nexport function GameTile({ game, onOpen, ui, variant = 'tile' }: {\n game: GameSummary; onOpen: (g: GameSummary) => void; ui: UiConfig; variant?: 'tile' | 'wide' | 'hero'\n}): JSX.Element {\n const status = tileStatus(game, ui)\n const disabled = DISABLED.has(game.status)\n const title = gameTitle(game, ui.games.titles)\n\n const body = variant === 'hero' ? (\n <>\n <span className=\"ss-g-hero-text\">\n <span className=\"ss-g-hero-eyebrow\">{ui.games.dailyChallenge}</span>\n {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n <span className=\"ss-g-hero-title\">{title}</span>\n <span className=\"ss-g-hero-sub\">{ui.games.taglines[game.gameId] ?? ''}</span>\n {status.tone === 'success'\n ? <span className=\"ss-g-tile-status\" data-tone=\"success\">{status.text}</span>\n : <span className=\"ss-g-hero-cta\">{status.tone === 'accent' ? ui.games.resume : ui.games.playNow} →</span>}\n </span>\n <span className=\"ss-g-hero-art\"><GameTileArt gameId={game.gameId} /></span>\n </>\n ) : variant === 'wide' ? (\n <>\n <span className=\"ss-g-wide-art\"><GameTileArt gameId={game.gameId} /></span>\n <span className=\"ss-g-wide-text\">\n <span className=\"ss-g-tile-title\">{title}</span>\n <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n </span>\n <span className=\"ss-g-wide-chev\"><IconChevronLeft size={18} /></span>\n </>\n ) : (\n <>\n <span className=\"ss-g-tile-art\"><GameTileArt gameId={game.gameId} /></span>\n <span className=\"ss-g-tile-title\">{title}</span>\n <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n </>\n )\n\n const cls = `ss-g-tile ss-g-tile--${variant}`\n if (disabled) return <div className={cls} data-disabled aria-disabled=\"true\">{body}</div>\n return <button type=\"button\" className={cls} aria-label={`${title} — ${status.text}`} onClick={() => onOpen(game)}>{body}</button>\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { useGamePlay } from '../useGamePlay'\nimport { MysteryTigerGame } from './games/MysteryTigerGame'\nimport { HigherOrLowerGame } from './games/HigherOrLowerGame'\nimport { CareerPathGame } from './games/CareerPathGame'\nimport { BeatTheGridGame } from './games/BeatTheGridGame'\nimport { GuessTheXiGame } from './games/GuessTheXiGame'\nimport { DailyQuizGame } from './games/DailyQuizGame'\nimport { MatchdayPredictorGame } from './games/MatchdayPredictorGame'\nimport { StartingXiGame } from './games/StartingXiGame'\nimport { StatLadderGame } from './games/StatLadderGame'\nimport { FanMotmGame } from './games/FanMotmGame'\nimport { GameHeader } from './games/ui/GameHeader'\nimport { gameTitle } from './games/ui/gameMeta'\nimport type {\n MysteryTigerConfig,\n HolConfig,\n CareerPathConfig,\n BeatTheGridConfig,\n GuessTheXiConfig,\n DailyQuizConfig,\n MatchdayPredictorConfig,\n StartingXiConfig,\n StatLadderConfig,\n FanMotmConfig,\n} from './games/types'\n\n// Fixture games need a pending-result poll: they submit once before kickoff,\n// then remain in \"pending\" until resolved at full time.\nconst FIXTURE_GAME_IDS = new Set([\n 'matchday-predictor',\n 'starting-xi',\n 'stat-ladder',\n 'fan-motm',\n])\n\n// Poll cadence while a fixture game result is pending (30 seconds).\nconst PENDING_POLL_INTERVAL_MS = 30_000\n\nfunction safeParseConfig<T>(json: string | null | undefined): T | null {\n if (!json) return null\n try {\n return JSON.parse(json) as T\n } catch {\n return null\n }\n}\n\nexport function GameScreenHost({\n selected,\n onBack,\n onPlayed,\n conversation,\n ui,\n}: {\n selected: { gameId: string; fixtureId: number; gameDay?: string; lockAtUtc?: string | null }\n onBack: () => void\n /** Called once a submitted play has been saved, so the hub can refetch points and status. */\n onPlayed?: () => void\n conversation: GamePlayConversation | null | undefined\n ui: UiConfig\n}): JSX.Element {\n const { gameId, fixtureId, gameDay = '', lockAtUtc = null } = selected\n\n // Fetch config on open\n const [configJson, setConfigJson] = useState<string | null>(null)\n\n useEffect(() => {\n setConfigJson(null)\n if (!conversation) return\n let cancelled = false\n void (async () => {\n try {\n const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || undefined, ui.games.lang)\n if (!cancelled && payload?.configJson) {\n setConfigJson(payload.configJson)\n }\n } catch {\n // best-effort\n }\n })()\n return () => { cancelled = true }\n }, [conversation, gameId, fixtureId, gameDay, ui.games.lang])\n\n // Shared submit lifecycle\n const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {\n gameId,\n gameDay: gameDay,\n fixtureId: fixtureId || undefined,\n locale: ui.games.lang,\n })\n\n // Hydrate on open for a returning fan\n useEffect(() => {\n if (conversation) hydrate()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversation, gameId])\n\n // Pending-result poll: while a fixture game result is pending (submitted but not yet\n // resolved at full time), poll getGameResult at a low cadence until graded or voided.\n const hydrateRef = useRef(hydrate)\n hydrateRef.current = hydrate\n\n useEffect(() => {\n if (!FIXTURE_GAME_IDS.has(gameId)) return\n if (rawStatus !== 'pending') return\n\n const timerId = setInterval(() => {\n hydrateRef.current()\n }, PENDING_POLL_INTERVAL_MS)\n\n return () => clearInterval(timerId)\n }, [gameId, rawStatus])\n\n const sharedProps = {\n result,\n submitting,\n // Refresh only after the play is saved: a fan can tap Back while a submit is still in flight,\n // and a refetch fired from Back alone would read the hub's pre-play state.\n onSubmit: (answerJson: string) => { void submit(answerJson).then(() => onPlayed?.()) },\n ui,\n onBack,\n lockAtUtc,\n }\n\n function renderScreen(): JSX.Element {\n switch (gameId) {\n case 'mystery-tiger':\n return (\n <MysteryTigerGame\n {...sharedProps}\n config={safeParseConfig<MysteryTigerConfig>(configJson)}\n />\n )\n case 'higher-or-lower':\n return (\n <HigherOrLowerGame\n {...sharedProps}\n config={safeParseConfig<HolConfig>(configJson)}\n />\n )\n case 'career-path':\n return (\n <CareerPathGame\n {...sharedProps}\n config={safeParseConfig<CareerPathConfig>(configJson)}\n />\n )\n case 'beat-the-grid': {\n const btgConfig = safeParseConfig<BeatTheGridConfig>(configJson)\n return (\n <BeatTheGridGame\n {...sharedProps}\n config={btgConfig}\n playerPool={btgConfig?.playerPool ?? []}\n />\n )\n }\n case 'guess-the-xi':\n return (\n <GuessTheXiGame\n {...sharedProps}\n config={safeParseConfig<GuessTheXiConfig>(configJson)}\n />\n )\n case 'daily-quiz':\n return (\n <DailyQuizGame\n {...sharedProps}\n config={safeParseConfig<DailyQuizConfig>(configJson)}\n />\n )\n case 'matchday-predictor':\n return (\n <MatchdayPredictorGame\n {...sharedProps}\n config={safeParseConfig<MatchdayPredictorConfig>(configJson)}\n />\n )\n case 'starting-xi':\n return (\n <StartingXiGame\n {...sharedProps}\n config={safeParseConfig<StartingXiConfig>(configJson)}\n />\n )\n case 'stat-ladder':\n return (\n <StatLadderGame\n {...sharedProps}\n config={safeParseConfig<StatLadderConfig>(configJson)}\n />\n )\n case 'fan-motm':\n return (\n <FanMotmGame\n {...sharedProps}\n config={safeParseConfig<FanMotmConfig>(configJson)}\n />\n )\n default:\n return (\n <div className=\"ss-g-screen\" data-testid={`game-screen-${gameId}`}>\n <GameHeader title={gameTitle({ gameId }, ui.games.titles)} onBack={onBack} backLabel={ui.back} />\n </div>\n )\n }\n }\n\n return (\n <div className=\"ss-w-gscreen\" data-testid=\"gscreen\" data-lock-at={lockAtUtc ?? undefined}>\n {renderScreen()}\n </div>\n )\n}\n","import { useCallback, useRef, useState } from 'react'\nimport type { GameResultPayload, GameStatePayload, SubmitPlayResult } from '@sensiblestats/widget-sdk'\n\nexport interface UseGamePlayOptions {\n gameId: string\n gameDay: string\n fixtureId?: number\n locale?: string\n /** Called after a ranked play completes (pointsDelta present). */\n refresh?: () => void\n}\n\nexport interface UseGamePlayResult {\n result: SubmitPlayResult | null\n submitting: boolean\n submit: (answerJson: string) => Promise<void>\n hydrate: () => void\n /** Raw status string from the last getGameResult call (null until hydrated). */\n rawStatus: string | null\n}\n\nexport type GamePlayConversation = {\n postPlay: (gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string) => Promise<SubmitPlayResult | null>\n getGameResult: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameResultPayload | null>\n getGameConfig: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameStatePayload | null>\n}\n\nfunction toSubmitResult(payload: GameResultPayload): SubmitPlayResult {\n return {\n // 'pending' means the play is recorded but awaiting resolution (fixture games)\n alreadyPlayed: payload.status === 'played' || payload.status === 'graded' || payload.status === 'pending',\n score: payload.score,\n isCorrect: payload.isCorrect,\n clientStateJson: payload.clientStateJson,\n attemptsUsed: payload.attemptsUsed,\n }\n}\n\nexport function useGamePlay(\n conversation: GamePlayConversation | null | undefined,\n { gameId, gameDay, fixtureId, locale, refresh }: UseGamePlayOptions,\n): UseGamePlayResult {\n const [result, setResult] = useState<SubmitPlayResult | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const [rawStatus, setRawStatus] = useState<string | null>(null)\n\n const inFlightRef = useRef(false)\n const convRef = useRef(conversation)\n convRef.current = conversation\n const optsRef = useRef({ gameId, gameDay, fixtureId, locale, refresh })\n optsRef.current = { gameId, gameDay, fixtureId, locale, refresh }\n // Mirror the latest result so submit() (a stable [] callback) can tell whether we\n // already hold in-progress state without wiping it.\n const resultRef = useRef<SubmitPlayResult | null>(null)\n resultRef.current = result\n\n const refetch = useCallback(async (): Promise<void> => {\n const conv = convRef.current\n if (!conv) return\n const opts = optsRef.current\n try {\n const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay, opts.locale)\n if (payload === null) return\n // Never let a null-clientState payload blank a board we already hold (e.g. a rescore that\n // couldn't reconstruct state). A first hydrate holds nothing, so a legitimately terminal\n // null-state play (voided / already-played) still renders; the status always updates.\n if (payload.clientStateJson == null && resultRef.current?.clientStateJson != null) {\n setRawStatus(payload.status)\n return\n }\n setResult(toSubmitResult(payload))\n setRawStatus(payload.status)\n } catch {\n // best-effort\n }\n }, [])\n\n const submit = useCallback(async (answerJson: string): Promise<void> => {\n const conv = convRef.current\n if (!conv || inFlightRef.current) return\n inFlightRef.current = true\n setSubmitting(true)\n try {\n const opts = optsRef.current\n const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId, opts.locale)\n if (playResult !== null) {\n // Guard against a state-losing response: a still-in-progress submit that carries no\n // ClientStateJson (e.g. a server-side concurrency retry) must NOT overwrite the board\n // we already hold. Reconcile from the server instead of rendering an empty state.\n const hasFreshState = playResult.clientStateJson != null\n const isTerminal = playResult.alreadyPlayed === true\n const holdsState = resultRef.current?.clientStateJson != null\n if (!hasFreshState && !isTerminal && holdsState) {\n await refetch()\n } else {\n setResult(playResult)\n }\n if (playResult.pointsDelta != null) {\n opts.refresh?.()\n }\n }\n } catch {\n // best-effort; leave result unchanged\n } finally {\n inFlightRef.current = false\n setSubmitting(false)\n }\n }, [refetch])\n\n const hydrate = useCallback((): void => {\n void refetch()\n }, [refetch])\n\n return { result, submitting, submit, hydrate, rawStatus }\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, MysteryTigerConfig, MysteryTigerClientState, MysteryTigerGuessResult, MysteryTigerAttributeVerdict } from './types'\nimport { nationalityFlag } from './nationFlags'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress, type SegmentState } from './ui/SegmentProgress'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { IconBulb } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\nfunction parseClientState(json: string | null | undefined): MysteryTigerClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as MysteryTigerClientState\n } catch {\n return null\n }\n}\n\nexport type MtAttrKey = keyof Omit<MysteryTigerGuessResult, 'playerId'>\nconst ATTR_KEYS: MtAttrKey[] = ['position', 'nationality', 'age', 'shirtNumber', 'apps']\nconst NUMERIC_KEYS: ReadonlySet<MtAttrKey> = new Set<MtAttrKey>(['age', 'shirtNumber', 'apps'])\n\nconst MAX_GUESSES = 6\n\nfunction verdictGlyph(v: MysteryTigerAttributeVerdict): string {\n if (v.verdict === 'exact') return '✓'\n if (v.verdict === 'miss') return '✗'\n if (v.direction === 'up') return '↑'\n if (v.direction === 'down') return '↓'\n return '≈'\n}\n\n// Direction arrow shown under a numeric value (\"22 ▲\" = mystery player is older/higher/more).\nfunction directionArrow(v: MysteryTigerAttributeVerdict): string {\n if (v.direction === 'up') return '▲'\n if (v.direction === 'down') return '▼'\n return ''\n}\n\n// Full position names (Sportmonks \"Centre Forward\", \"Goalkeeper\", …) overflow the small square\n// tile, so map them to a short code for display. Anything unmapped falls back to its initials.\nconst POSITION_SHORT: Record<string, string> = {\n goalkeeper: 'GK', keeper: 'GK',\n defender: 'DEF', 'centre back': 'CB', 'center back': 'CB', 'centre-back': 'CB', 'center-back': 'CB',\n 'left back': 'LB', 'right back': 'RB', 'left wing-back': 'LWB', 'right wing-back': 'RWB', sweeper: 'SW',\n midfielder: 'MID', 'defensive midfield': 'DM', 'central midfield': 'CM', 'centre midfield': 'CM',\n 'attacking midfield': 'AM', 'left midfield': 'LM', 'right midfield': 'RM',\n 'left wing': 'LW', 'right wing': 'RW', 'left winger': 'LW', 'right winger': 'RW',\n forward: 'FWD', attacker: 'FWD', striker: 'ST', 'second striker': 'SS',\n 'centre forward': 'CF', 'center forward': 'CF', 'centre-forward': 'CF',\n}\n\nfunction shortPosition(value: string): string {\n const mapped = POSITION_SHORT[value.trim().toLowerCase()]\n if (mapped) return mapped\n if (value.length <= 3) return value.toUpperCase() // already a code (GK, ST, CB, …)\n return value.split(/[\\s-]+/).filter(Boolean).map(w => (w[0] ?? '').toUpperCase()).join('').slice(0, 3)\n}\n\n// The display face of a tile: the guessed player's own value (a flag for nationality, a short\n// code for position), falling back to the verdict glyph when the backend sent no value.\nfunction tileFace(key: MtAttrKey, v: MysteryTigerAttributeVerdict): string {\n if (!v.value) return verdictGlyph(v)\n if (key === 'nationality') return nationalityFlag(v.value)\n if (key === 'position') return shortPosition(v.value)\n return v.value\n}\n\nexport interface KnownAttribute { key: MtAttrKey; state: 'known' | 'range' | 'unknown'; text: string }\n\n// What the fan has pinned down so far, per attribute. An exact verdict reveals the value. For the\n// numeric attributes each ▲ (\"mystery is higher than v\") raises the floor and each ▼ lowers the\n// ceiling, so 23▲ + 26▼ reads \"24–25\", only ▼9 reads \"< 9\", only ▲31 reads \"> 31\".\nexport function deriveKnownAttributes(guesses: MysteryTigerGuessResult[], keys: MtAttrKey[]): KnownAttribute[] {\n return keys.map((key): KnownAttribute => {\n const exact = guesses.find(g => g[key].verdict === 'exact')\n if (exact) return { key, state: 'known', text: tileFace(key, exact[key]) }\n if (!NUMERIC_KEYS.has(key)) return { key, state: 'unknown', text: '?' }\n let maxUp: number | null = null\n let minDown: number | null = null\n for (const g of guesses) {\n const v = g[key]\n if (!v.value || !v.direction) continue\n const n = Number(v.value)\n if (!Number.isFinite(n)) continue\n if (v.direction === 'up') maxUp = maxUp === null ? n : Math.max(maxUp, n)\n else minDown = minDown === null ? n : Math.min(minDown, n)\n }\n if (maxUp !== null && minDown !== null) {\n const lo = maxUp + 1\n const hi = minDown - 1\n return { key, state: 'range', text: lo >= hi ? String(lo) : `${lo}–${hi}` }\n }\n if (minDown !== null) return { key, state: 'range', text: `< ${minDown}` }\n if (maxUp !== null) return { key, state: 'range', text: `> ${maxUp}` }\n return { key, state: 'unknown', text: '?' }\n })\n}\n\nexport function MysteryTigerGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<MysteryTigerConfig>): JSX.Element {\n const t = ui.games.mysteryTiger\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const guessResults = clientState?.guessResults ?? []\n const alreadyGuessedIds = new Set<number>(guessResults.map(g => g.playerId))\n const shirtEnabled = config?.shirtTileEnabled ?? clientState?.shirtTileEnabled ?? false\n const keys = ATTR_KEYS.filter(k => k !== 'shirtNumber' || shirtEnabled)\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.solved === true ||\n clientState?.failed === true\n\n const guessesUsed = clientState?.guessesUsed ?? guessResults.length\n const totalGuesses = clientState ? clientState.guessesUsed + clientState.guessesRemaining : MAX_GUESSES\n const score = result?.score ?? 0\n const revealName = isOver ? clientState?.revealedPlayerName : undefined\n\n const filtered =\n config && !isOver\n ? config.squadPlayers.filter(\n p => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handleSelect(playerId: number) {\n if (!config || isOver || submitting) return\n const prevGuesses = guessResults.map(g => g.playerId)\n const newGuesses = [...prevGuesses, playerId]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const headerRight = !config ? undefined : isOver ? (\n <Chip variant=\"accent\">{score} {ui.games.unitPts}</Chip>\n ) : (\n <span data-testid=\"mt-chip\">\n <Chip>{ui.games.guess} <span className=\"ss-g-num\">{guessesUsed + 1}</span> / {totalGuesses}</Chip>\n </span>\n )\n\n const segments: SegmentState[] = Array.from({ length: totalGuesses }, (_, i) =>\n i < guessesUsed ? 'done' : i === guessesUsed ? 'current' : 'todo')\n const cols = { gridTemplateColumns: `minmax(0, 1fr) repeat(${keys.length}, 42px)` }\n const known = deriveKnownAttributes(guessResults, keys)\n\n return (\n <div className=\"ss-g-screen ss-g-mt\" data-testid=\"game-screen-mystery-tiger\">\n <GameHeader title={gameTitle({ gameId: 'mystery-tiger' }, ui.games.titles)} eyebrow={t.eyebrow} right={headerRight}\n onBack={onBack} backLabel={ui.back} />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n <div className={`ss-g-mt-card${isOver ? ' ss-g-mt-card--reveal' : ''}`}>\n <div className=\"ss-g-mt-portrait\">\n {revealName ? (\n <PlayerAvatar className=\"ss-g-mt-photo\" name={revealName} imagePath={clientState?.revealedPlayerImagePath} />\n ) : (\n <Silhouette size={150} variant=\"mystery\" />\n )}\n {revealName && <span className=\"ss-g-mt-reveal-name\">{revealName}</span>}\n </div>\n <div className=\"ss-g-mt-known\" style={{ gridTemplateColumns: `repeat(${keys.length}, minmax(0, 1fr))` }}>\n {known.map(k => (\n <div key={k.key} className=\"ss-g-mt-known-cell\">\n <span className=\"ss-g-mt-lab\">{t.labels[k.key]}</span>\n <span className=\"ss-g-mt-known-v\" data-state={k.state} data-testid={`known-${k.key}`}>{k.text}</span>\n </div>\n ))}\n </div>\n </div>\n\n {!isOver && <SegmentProgress segments={segments} ariaLabel={t.progress(guessesUsed, totalGuesses)} />}\n\n {guessResults.length > 0 && (\n <div className=\"ss-g-mt-table\">\n <div className=\"ss-g-mt-thead\" style={cols}>\n <span>{t.yourGuesses}</span>\n {keys.map(k => <span key={k}>{t.labels[k]}</span>)}\n </div>\n {guessResults.map((gr, i) => {\n const name = config.squadPlayers.find(p => p.id === gr.playerId)?.name ?? `#${gr.playerId}`\n const { first, last } = splitName(name)\n return (\n <div key={gr.playerId} className=\"ss-g-mt-row\" style={cols}>\n <div className=\"ss-g-mt-who\">\n <PlayerAvatar className=\"ss-g-mt-av\" name={name} />\n <span className=\"ss-g-mt-names\">\n {first && <span className=\"ss-g-mt-first\">{first}</span>}\n <span className=\"ss-g-mt-last\">{last}</span>\n </span>\n </div>\n {keys.map(key => {\n const v = gr[key]\n const arrow = directionArrow(v)\n return (\n <div\n key={key}\n className=\"ss-g-mt-cell\"\n data-testid={`verdict-${key}-${i}`}\n data-verdict={v.verdict}\n aria-label={`${t.labels[key]}: ${v.value ?? v.verdict}${v.direction ? ` ${v.direction}` : ''}`}\n >\n <span className=\"ss-g-mt-cell-v\" aria-hidden=\"true\">{tileFace(key, v)}</span>\n {arrow && <span className=\"ss-g-mt-cell-dir\" aria-hidden=\"true\">{arrow}</span>}\n </div>\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n\n {!isOver && (\n <div className=\"ss-g-mt-legend\">\n <span><i className=\"ss-g-mt-sw\" data-verdict=\"exact\" />{t.legendMatch}</span>\n <span><i className=\"ss-g-mt-sw\" data-verdict=\"near\" />{t.legendClose}</span>\n <span>▲ {t.legendHigher}</span>\n </div>\n )}\n\n {clientState?.hintLine && !isOver && (\n <div className=\"ss-g-mt-hint\"><IconBulb /><span>{clientState.hintLine}</span></div>\n )}\n\n {isOver && (\n <ResultCard\n tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n title={clientState?.solved ? t.solved : clientState?.failed ? t.failed : ui.games.alreadyPlayedTitle}\n score={score}\n detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={t.optionsLabel}\n options={filtered.map(p => ({\n key: p.id,\n content: <><PlayerAvatar className=\"ss-g-opt-av\" name={p.name} /><span>{p.name}</span></>,\n }))}\n onPick={k => handleSelect(Number(k))}\n />\n )}\n <SearchField id={inputId} label={t.searchLabel} placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={submitting} />\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","// Maps a nationality country-name string (as the games backend emits it) to a flag emoji.\n// UK home nations use subdivision flag emoji; everything else uses regional-indicator pairs.\n// Unmapped nationalities fall back to a short uppercased code so a slot is never blank.\n\nconst FLAGS: Record<string, string> = {\n // UK home nations (subdivision flags)\n england: '🏴\\u{E0067}\\u{E0062}\\u{E0065}\\u{E006E}\\u{E0067}\\u{E007F}',\n scotland: '🏴\\u{E0067}\\u{E0062}\\u{E0073}\\u{E0063}\\u{E0074}\\u{E007F}',\n wales: '🏴\\u{E0067}\\u{E0062}\\u{E0077}\\u{E006C}\\u{E0073}\\u{E007F}',\n 'northern ireland': '🇬🇧',\n 'republic of ireland': '🇮🇪',\n ireland: '🇮🇪',\n 'united kingdom': '🇬🇧',\n\n // Western & Southern Europe\n france: '🇫🇷', spain: '🇪🇸', portugal: '🇵🇹', germany: '🇩🇪', italy: '🇮🇹',\n netherlands: '🇳🇱', belgium: '🇧🇪', switzerland: '🇨🇭', austria: '🇦🇹',\n luxembourg: '🇱🇺', malta: '🇲🇹', cyprus: '🇨🇾',\n andorra: '🇦🇩', liechtenstein: '🇱🇮', 'san marino': '🇸🇲', monaco: '🇲🇨',\n\n // Northern Europe\n denmark: '🇩🇰', sweden: '🇸🇪', norway: '🇳🇴', finland: '🇫🇮', iceland: '🇮🇸',\n\n // Central & Eastern Europe\n poland: '🇵🇱', czechia: '🇨🇿', 'czech republic': '🇨🇿', croatia: '🇭🇷',\n serbia: '🇷🇸', 'bosnia and herzegovina': '🇧🇦', bosnia: '🇧🇦',\n greece: '🇬🇷', romania: '🇷🇴', ukraine: '🇺🇦', russia: '🇷🇺',\n hungary: '🇭🇺', slovakia: '🇸🇰', slovenia: '🇸🇮', bulgaria: '🇧🇬',\n lithuania: '🇱🇹', latvia: '🇱🇻', estonia: '🇪🇪', moldova: '🇲🇩', belarus: '🇧🇾',\n\n // South-East Europe / Balkans\n turkey: '🇹🇷', türkiye: '🇹🇷', albania: '🇦🇱', 'north macedonia': '🇲🇰',\n kosovo: '🇽🇰', montenegro: '🇲🇪',\n\n // Caucasus & Central Asia\n armenia: '🇦🇲', georgia: '🇬🇪', azerbaijan: '🇦🇿',\n kazakhstan: '🇰🇿', uzbekistan: '🇺🇿', kyrgyzstan: '🇰🇬',\n tajikistan: '🇹🇯', turkmenistan: '🇹🇲',\n\n // South America\n brazil: '🇧🇷', argentina: '🇦🇷', uruguay: '🇺🇾', colombia: '🇨🇴', chile: '🇨🇱',\n peru: '🇵🇪', ecuador: '🇪🇨', paraguay: '🇵🇾', venezuela: '🇻🇪', bolivia: '🇧🇴',\n guyana: '🇬🇾', suriname: '🇸🇷',\n\n // North & Central America\n mexico: '🇲🇽', 'united states': '🇺🇸', usa: '🇺🇸', canada: '🇨🇦',\n 'costa rica': '🇨🇷', panama: '🇵🇦', honduras: '🇭🇳', 'el salvador': '🇸🇻',\n guatemala: '🇬🇹', nicaragua: '🇳🇮',\n\n // Caribbean\n jamaica: '🇯🇲', cuba: '🇨🇺', haiti: '🇭🇹', 'dominican republic': '🇩🇴',\n 'trinidad and tobago': '🇹🇹', trinidad: '🇹🇹',\n 'curaçao': '🇨🇼', curacao: '🇨🇼',\n barbados: '🇧🇧',\n\n // West Africa\n nigeria: '🇳🇬', ghana: '🇬🇭', senegal: '🇸🇳',\n ivorycoast: '🇨🇮', \"cote d'ivoire\": '🇨🇮', \"côte d'ivoire\": '🇨🇮', 'ivory coast': '🇨🇮',\n cameroon: '🇨🇲', mali: '🇲🇱', guinea: '🇬🇳', 'guinea-bissau': '🇬🇼',\n 'sierra leone': '🇸🇱', liberia: '🇱🇷', 'cape verde': '🇨🇻', 'gambia': '🇬🇲',\n mauritania: '🇲🇷', togo: '🇹🇬', benin: '🇧🇯', 'burkina faso': '🇧🇫', niger: '🇳🇪',\n\n // Central & East Africa\n 'dr congo': '🇨🇩', 'democratic republic of the congo': '🇨🇩', 'congo dr': '🇨🇩',\n 'republic of the congo': '🇨🇬', congo: '🇨🇬', 'congo republic': '🇨🇬', 'congo-brazzaville': '🇨🇬',\n 'central african republic': '🇨🇫', gabon: '🇬🇦', 'equatorial guinea': '🇬🇶',\n 'south africa': '🇿🇦', angola: '🇦🇴', namibia: '🇳🇦', botswana: '🇧🇼',\n zimbabwe: '🇿🇼', zambia: '🇿🇲', malawi: '🇲🇼', mozambique: '🇲🇿',\n tanzania: '🇹🇿', kenya: '🇰🇪', uganda: '🇺🇬', rwanda: '🇷🇼',\n ethiopia: '🇪🇹', eritrea: '🇪🇷', djibouti: '🇩🇯', somalia: '🇸🇴',\n sudan: '🇸🇩', 'south sudan': '🇸🇸', chad: '🇹🇩',\n lesotho: '🇱🇸', eswatini: '🇸🇿', swaziland: '🇸🇿',\n madagascar: '🇲🇬', mauritius: '🇲🇺', comoros: '🇰🇲', seychelles: '🇸🇨',\n\n // North Africa\n egypt: '🇪🇬', morocco: '🇲🇦', algeria: '🇩🇿', tunisia: '🇹🇳',\n\n // Middle East\n 'saudi arabia': '🇸🇦', iran: '🇮🇷', iraq: '🇮🇶', lebanon: '🇱🇧',\n syria: '🇸🇾', jordan: '🇯🇴', qatar: '🇶🇦', 'united arab emirates': '🇦🇪', uae: '🇦🇪',\n kuwait: '🇰🇼', bahrain: '🇧🇭', oman: '🇴🇲', yemen: '🇾🇪',\n israel: '🇮🇱', palestine: '🇵🇸',\n\n // East & South-East Asia\n japan: '🇯🇵', 'south korea': '🇰🇷', korea: '🇰🇷', china: '🇨🇳',\n india: '🇮🇳', thailand: '🇹🇭', indonesia: '🇮🇩', malaysia: '🇲🇾',\n philippines: '🇵🇭', vietnam: '🇻🇳',\n\n // Oceania\n australia: '🇦🇺', 'new zealand': '🇳🇿', fiji: '🇫🇯',\n}\n\nexport function nationalityFlag(nationality: string | null | undefined): string {\n if (!nationality) return '🏳️'\n const key = nationality.trim().toLowerCase()\n return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase()\n}\n\n// A nationality without a flag falls back to its first three letters (\"BEN\"); callers size that\n// text down so it fits the disc a flag emoji would fill.\nexport function isNationCode(flag: string): boolean {\n return /^[A-Z]{1,3}$/.test(flag)\n}\n","import { useState } from 'react'\n\n// Two-letter initials from a display name: first + last token, or the first two letters\n// of a single-token name. Used as the photo fallback so an avatar circle is never a bare ball.\nexport function initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n const first = parts[0]\n if (!first) return '?'\n const last = parts[parts.length - 1]\n if (parts.length === 1 || !last) return first.slice(0, 2).toUpperCase()\n return ((first[0] ?? '') + (last[0] ?? '')).toUpperCase()\n}\n\n// The data provider (Sportmonks) serves a generic grey silhouette at .../placeholder.png for\n// people it has no photo of. Treat it as no photo so the fallback (initials, shield) shows.\nexport function isPlaceholderImage(url: string | null | undefined): boolean {\n return !!url && /\\/placeholder\\.(png|jpe?g|svg|webp)(\\?|$)/i.test(url)\n}\n\n// Circular player avatar. Shows the photo when an imagePath is present and loads; otherwise\n// (missing URL or a broken image) falls back to the player's initials on the same circle.\nexport function PlayerAvatar({\n name,\n imagePath,\n className,\n}: {\n name: string\n imagePath?: string\n className: string\n}): JSX.Element {\n const [failed, setFailed] = useState(false)\n const showImage = Boolean(imagePath) && !isPlaceholderImage(imagePath) && !failed\n\n return (\n <div className={className} aria-hidden=\"true\">\n {showImage ? (\n <img src={imagePath} alt=\"\" loading=\"lazy\" onError={() => setFailed(true)} />\n ) : (\n <span className=\"ss-w-av-initials\">{initialsOf(name)}</span>\n )}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { IconChevronLeft } from './icons'\n\nexport function GameHeader({ title, eyebrow, right, onBack, backLabel }: {\n title: string; eyebrow?: string; right?: ReactNode; onBack?: () => void; backLabel: string\n}): JSX.Element {\n return (\n <div className=\"ss-g-head\">\n {onBack && (\n <button type=\"button\" className=\"ss-g-back\" aria-label={backLabel} onClick={onBack}>\n <IconChevronLeft />\n </button>\n )}\n <div className=\"ss-g-head-text\">\n {eyebrow && <span className=\"ss-g-eyebrow\">{eyebrow}</span>}\n <h2 className=\"ss-g-title\">{title}</h2>\n </div>\n {right && <div className=\"ss-g-head-right\">{right}</div>}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\n\nexport type SegmentState = 'done' | 'current' | 'todo' | 'correct' | 'wrong'\n\nexport function SegmentProgress({ segments, ariaLabel, leftLabel, rightLabel, right }: {\n segments: SegmentState[]; ariaLabel: string; leftLabel?: string; rightLabel?: string; right?: ReactNode\n}): JSX.Element {\n return (\n <div className=\"ss-g-progress\">\n <div className=\"ss-g-progress-main\">\n {(leftLabel || rightLabel) && (\n <div className=\"ss-g-progress-labels\">\n <span>{leftLabel}</span><span className=\"ss-g-progress-rl\">{rightLabel}</span>\n </div>\n )}\n <div className=\"ss-g-segs\" role=\"img\" aria-label={ariaLabel}\n style={{ gridTemplateColumns: `repeat(${segments.length}, minmax(0, 1fr))` }}>\n {segments.map((s, i) => <span key={i} className=\"ss-g-seg\" data-state={s} />)}\n </div>\n </div>\n {right}\n </div>\n )\n}\n","import type { KeyboardEvent, Ref } from 'react'\nimport { IconSearch } from './icons'\n\nexport function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown }: {\n id: string; label: string; labelHidden?: boolean; placeholder: string; value: string\n onChange: (v: string) => void; disabled?: boolean; inputRef?: Ref<HTMLInputElement>\n onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void\n}): JSX.Element {\n return (\n <div className=\"ss-g-search\">\n <label htmlFor={id} className={labelHidden ? 'ss-g-sr' : 'ss-g-search-label'}>{label}</label>\n <div className=\"ss-g-search-box\">\n <IconSearch />\n <input id={id} ref={inputRef} type=\"text\" autoComplete=\"off\" placeholder={placeholder} value={value}\n disabled={disabled} onKeyDown={onKeyDown} onChange={e => onChange(e.target.value)} />\n </div>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nexport function FooterBar({ children }: { children: ReactNode }): JSX.Element {\n return <div className=\"ss-g-footer\">{children}</div>\n}\n","export function Silhouette({ size, variant = 'default' }: { size: number; variant?: 'default' | 'selected' | 'mystery' }): JSX.Element {\n return (\n <span className={`ss-g-sil ss-g-sil--${variant}`} style={{ width: size, height: size }} aria-hidden=\"true\">\n <svg width={size * 0.86} height={size * 0.86} viewBox=\"0 0 100 100\">\n <circle cx=\"50\" cy=\"40\" r=\"19\" fill=\"currentColor\" />\n <path d=\"M12 100c0-23 17-38 38-38s38 15 38 38z\" fill=\"currentColor\" />\n </svg>\n {variant === 'mystery' && <span className=\"ss-g-sil-q\">?</span>}\n </span>\n )\n}\n","import type { ButtonHTMLAttributes } from 'react'\n\nexport type GameButtonVariant = 'primary' | 'outline' | 'accent-outline' | 'surface'\n\nexport function GameButton({ variant = 'primary', block = false, className, type = 'button', ...rest }:\n ButtonHTMLAttributes<HTMLButtonElement> & { variant?: GameButtonVariant; block?: boolean }): JSX.Element {\n const cls = `ss-g-btn ss-g-btn--${variant}${block ? ' ss-g-btn--block' : ''}${className ? ` ${className}` : ''}`\n return <button type={type} className={cls} {...rest} />\n}\n","import type { UiConfig } from '../../../config'\nimport { GameButton } from './GameButton'\n\nexport type ResultTone = 'win' | 'lose' | 'neutral'\n\n// Spec §6: every game's solved / lost / already-played state uses this one card.\nexport function ResultCard({ tone, title, score, detail, onBack, ui }: {\n tone: ResultTone; title: string; score?: number; detail?: string; onBack?: () => void; ui: UiConfig\n}): JSX.Element {\n return (\n <div className=\"ss-g-result\" data-tone={tone} role=\"status\">\n <span className=\"ss-g-result-title\">{title}</span>\n {score !== undefined && (\n <span className=\"ss-g-result-score\"><span className=\"ss-g-result-num\">{score}</span>{ui.games.unitPts}</span>\n )}\n {detail && <span className=\"ss-g-result-detail\">{detail}</span>}\n {onBack && <GameButton variant=\"outline\" onClick={onBack}>{ui.games.backToGames}</GameButton>}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\n\nexport interface OptionItem { key: string | number; content: ReactNode }\n\n// Typeahead results. Real <button>s (keyboard reachable) carrying role=option inside a listbox.\nexport function OptionList({ label, options, onPick }: {\n label: string; options: OptionItem[]; onPick: (key: string | number) => void\n}): JSX.Element {\n return (\n <div className=\"ss-g-opts\" role=\"listbox\" aria-label={label}>\n {options.map(o => (\n <button key={o.key} type=\"button\" role=\"option\" aria-selected={false} className=\"ss-g-opt\" onClick={() => onPick(o.key)}>\n {o.content}\n </button>\n ))}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport type { GameScreenProps, HolConfig, HolClientState } from './types'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { StatStack } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconArrowUp, IconArrowDown, IconCheck, IconClose } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Points awarded per correct pick — mirrors HigherOrLowerContentGenerator.PointsPerCorrect.\nconst POINTS_PER_CORRECT = 10\n\nfunction parseClientState(json: string | null | undefined): HolClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as HolClientState\n } catch {\n return null\n }\n}\n\nfunction PlayerCard({ name, imagePath, highlight, children }: {\n name: string; imagePath?: string; highlight?: boolean; children: ReactNode\n}): JSX.Element {\n const { first, last } = splitName(name)\n return (\n <div className={`ss-g-hl-card${highlight ? ' ss-g-hl-card--b' : ''}`}>\n <div className=\"ss-g-hl-photo-wrap\">\n {imagePath\n ? <PlayerAvatar className=\"ss-g-hl-photo\" name={name} imagePath={imagePath} />\n : <Silhouette size={150} />}\n </div>\n <div className=\"ss-g-hl-info\">\n {first && <span className=\"ss-g-hl-first\">{first}</span>}\n <span className=\"ss-g-hl-surname\">{last}</span>\n {children}\n </div>\n </div>\n )\n}\n\nexport function HigherOrLowerGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<HolConfig>): JSX.Element {\n const t = ui.games.higherOrLower\n const clientState = parseClientState(result?.clientStateJson)\n\n const answeredPairs = clientState?.answeredPairs ?? []\n const answeredCount = answeredPairs.length\n const runEndedWrong = answeredPairs.some(p => !p.wasCorrect)\n const allPairsAnswered = config != null && answeredCount >= config.pairs.length\n const isOver = result?.alreadyPlayed === true || runEndedWrong || allPairsAnswered\n\n const currentPair = config && !isOver ? config.pairs[answeredCount] ?? null : null\n\n const correctCount = answeredPairs.filter(p => p.wasCorrect).length\n // A returning fan may come back with no client state: show the stored play score then.\n const score = clientState?.score ?? result?.score ?? 0\n const runLength = clientState?.runLength ?? 0\n\n const lastAnswer = answeredPairs[answeredPairs.length - 1]\n const lastAnswerPair = lastAnswer ? config?.pairs.find(p => p.pairIndex === lastAnswer.pairIndex) : undefined\n\n function handlePick(pick: 'higher' | 'lower') {\n if (!config || isOver || submitting || !currentPair) return\n const prevAnswers = answeredPairs.map(p => ({ pairIndex: p.pairIndex, pick: p.pick }))\n const newAnswers = [...prevAnswers, { pairIndex: currentPair.pairIndex, pick }]\n onSubmit(JSON.stringify({ answers: newAnswers }))\n }\n\n return (\n <div className=\"ss-g-screen ss-g-hl\" data-testid=\"game-screen-higher-or-lower\">\n <GameHeader\n title={gameTitle({ gameId: 'higher-or-lower' }, ui.games.titles)}\n eyebrow={t.eyebrow(POINTS_PER_CORRECT)}\n right={config ? <StatStack value={runLength} label={t.streak} /> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n <div className=\"ss-g-hl-prompt\" data-testid=\"hol-prompt\">\n <span className=\"ss-g-hl-prompt-q\">{t.whoHadMore}</span>\n <span className=\"ss-g-hl-prompt-stat\">{config.statLabel}</span>\n <span className=\"ss-g-hl-prompt-season\">{t.season(config.seasonLabel)}</span>\n </div>\n\n {currentPair && (\n <div className=\"ss-g-hl-pair\">\n <PlayerCard name={currentPair.playerAName} imagePath={currentPair.playerAImagePath}>\n <span className=\"ss-g-hl-value\">{currentPair.playerAValue}</span>\n <span className=\"ss-g-hl-stat\">{config.statLabel}</span>\n </PlayerCard>\n <span className=\"ss-g-hl-vs\" aria-hidden=\"true\">{t.vs}</span>\n <PlayerCard name={currentPair.playerBName} imagePath={currentPair.playerBImagePath} highlight>\n <div className=\"ss-g-hl-btns\">\n <GameButton variant=\"primary\" disabled={submitting} onClick={() => handlePick('higher')}>\n <IconArrowUp size={16} />{t.higher}\n </GameButton>\n <GameButton variant=\"outline\" disabled={submitting} onClick={() => handlePick('lower')}>\n <IconArrowDown size={16} />{t.lower}\n </GameButton>\n </div>\n </PlayerCard>\n </div>\n )}\n\n {lastAnswer && lastAnswerPair && (\n <p className=\"ss-g-hl-feedback\" data-testid=\"hol-last\" data-correct={lastAnswer.wasCorrect ? 'true' : 'false'}>\n {lastAnswer.wasCorrect ? <IconCheck /> : <IconClose />}\n {t.lastAnswer(splitName(lastAnswerPair.playerBName).last, lastAnswer.playerBValue)}\n </p>\n )}\n\n {isOver && (\n <ResultCard\n tone={runEndedWrong ? 'lose' : allPairsAnswered ? 'win' : 'neutral'}\n title={runEndedWrong ? t.runOver : allPairsAnswered ? t.perfectRun : ui.games.alreadyPlayedTitle}\n score={score}\n detail={clientState ? t.runDetail(correctCount) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n <div className=\"ss-g-hl-foot\">\n <div className=\"ss-g-hl-dots\" role=\"img\" aria-label={t.answersSoFar(answeredCount, config.pairs.length)}>\n {config.pairs.map((p, i) => {\n const a = answeredPairs[i]\n return <span key={p.pairIndex} className=\"ss-g-hl-dot\" data-state={a ? (a.wasCorrect ? 'correct' : 'wrong') : 'todo'} />\n })}\n </div>\n <span className=\"ss-g-hl-pts\">\n <span data-testid=\"hol-score\">{score}</span> <span className=\"ss-g-hl-pts-unit\">{ui.games.unitPts}</span>\n </span>\n </div>\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, CareerPathConfig, CareerPathClientState, CareerPathClubSpell } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { IconLock } from './ui/icons'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): CareerPathClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as CareerPathClientState\n } catch {\n return null\n }\n}\n\n// \"2012–2015\", \"2012\" when single-season or open-ended, '' when the generator had no start year.\nexport function spellYears(spell: CareerPathClubSpell): string {\n if (!spell.startYear) return ''\n if (spell.endYear && spell.endYear !== spell.startYear) return `${spell.startYear}–${spell.endYear}`\n return String(spell.startYear)\n}\n\nexport function CareerPathGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n}: GameScreenProps<CareerPathConfig>): JSX.Element {\n const s = ui.games.careerPath\n const title = gameTitle({ gameId: 'career-path' }, ui.games.titles)\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyGuessedIds = new Set<number>(clientState?.guessResults.map(g => g.playerId) ?? [])\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.solved === true ||\n clientState?.failed === true\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-career-path\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const visiblePath = clientState?.visiblePath ?? config.initialPath\n const totalClubs = clientState?.totalClubs ?? config.totalClubs\n const hidden = isOver ? 0 : Math.max(0, totalClubs - visiblePath.length)\n\n const filtered = !isOver\n ? config.typeaheadPool.filter(\n p => !alreadyGuessedIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handleSelect(playerId: number): void {\n if (!config || isOver || submitting) return\n const prevGuesses = clientState?.guessResults.map(g => g.playerId) ?? []\n const newGuesses = [...prevGuesses, playerId]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const right = !isOver && clientState\n ? (\n <span data-testid=\"cp-guess-chip\">\n <Chip variant=\"neutral\">\n {ui.games.guess} <span className=\"ss-g-num\">{clientState.guessesUsed + 1}</span> / {clientState.guessesUsed + clientState.guessesRemaining}\n </Chip>\n </span>\n )\n : undefined\n\n const outcome = clientState?.solved ? s.solved : clientState?.failed ? s.failed : ui.games.done\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-career-path\">\n <GameHeader title={title} eyebrow={s.eyebrow} right={right} onBack={onBack} backLabel={ui.back} />\n\n <div className=\"ss-g-body\">\n <div className=\"ss-g-cp-card\">\n {isOver && clientState?.revealedPlayerName ? (\n <PlayerAvatar className=\"ss-g-cp-photo\" name={clientState.revealedPlayerName} imagePath={clientState.revealedPlayerImagePath} />\n ) : (\n <Silhouette size={64} variant={isOver ? 'default' : 'mystery'} />\n )}\n <div className=\"ss-g-cp-card-text\">\n <span className=\"ss-g-cp-card-title\">\n {isOver && clientState?.revealedPlayerName ? clientState.revealedPlayerName : s.mysteryPlayer}\n </span>\n {clientState?.hintLine ? (\n <span className=\"ss-g-cp-hint\">{clientState.hintLine}</span>\n ) : !isOver ? (\n <span className=\"ss-g-cp-locks\">\n <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockPosition}</Chip>\n <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockNationality}</Chip>\n </span>\n ) : null}\n </div>\n </div>\n\n <ol className=\"ss-g-cp-line\">\n {visiblePath.map((spell, i) => {\n const years = i === 0 ? s.firstClub : spellYears(spell)\n return (\n <li key={`${spell.clubName}-${i}`} className=\"ss-g-cp-step\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile\"><CrestShield src={spell.crestUrl} name={spell.clubName} size={30} /></span>\n <span className=\"ss-g-cp-conn\" aria-hidden=\"true\" />\n </span>\n <span className=\"ss-g-cp-step-text\">\n <span className=\"ss-g-cp-club\">{spell.clubName}</span>\n <span className=\"ss-g-cp-sub\">\n <span className=\"ss-g-cp-years\">{years}</span>\n {spell.isLoan && (\n <>\n {years ? ' · ' : ''}\n <span className=\"ss-g-cp-loan\">{s.loan}</span>\n </>\n )}\n </span>\n </span>\n </li>\n )\n })}\n {hidden > 0 && (\n <li className=\"ss-g-cp-step ss-g-cp-step--hidden\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile ss-g-cp-tile--locked\"><IconLock size={18} /></span>\n {hidden > 1 && <span className=\"ss-g-cp-conn ss-g-cp-conn--faint\" aria-hidden=\"true\" />}\n </span>\n <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.nextClubHidden}</span></span>\n </li>\n )}\n {hidden > 1 && (\n <li className=\"ss-g-cp-step ss-g-cp-step--more\">\n <span className=\"ss-g-cp-rail\">\n <span className=\"ss-g-cp-tile ss-g-cp-tile--faint\"><IconLock size={18} /></span>\n </span>\n <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.moreClubs(hidden - 1)}</span></span>\n </li>\n )}\n </ol>\n\n {isOver && (\n <ResultCard\n tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n title={outcome}\n score={result?.score}\n detail={clientState ? s.guessesLine(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={s.searchLabel}\n options={filtered.map(p => ({\n key: p.id,\n content: <><PlayerAvatar className=\"ss-g-opt-av\" name={p.name} /><span>{p.name}</span></>,\n }))}\n onPick={k => handleSelect(Number(k))}\n />\n )}\n <SearchField\n id={inputId}\n label={s.searchLabel}\n placeholder={s.searchPlaceholder}\n value={query}\n onChange={setQuery}\n disabled={submitting}\n />\n </FooterBar>\n )}\n </div>\n )\n}\n","import { useState } from 'react'\nimport { isPlaceholderImage } from '../PlayerAvatar'\n\nexport function CrestShield({ src, name, size = 28 }: { src?: string | null; name: string; size?: number }): JSX.Element {\n const [failed, setFailed] = useState(false)\n if (src && !isPlaceholderImage(src) && !failed) {\n return <img className=\"ss-g-crest\" src={src} alt={name} width={size} height={size} loading=\"lazy\" onError={() => setFailed(true)} />\n }\n return (\n <svg className=\"ss-g-crest ss-g-crest--ph\" width={size} height={size * 32 / 28} viewBox=\"0 0 28 32\" role=\"img\" aria-label={name}>\n <path d=\"M2 3h24v12c0 9-6 14-12 17C8 29 2 24 2 15z\" fill=\"currentColor\" />\n </svg>\n )\n}\n","import React, { useEffect, useId, useRef, useState } from 'react'\nimport type { GameScreenProps, BeatTheGridConfig, BtgClientState, BtgCellResult, BtgCriterionMeta } from './types'\nimport type { UiConfig } from '../../config'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { SearchField } from './ui/SearchField'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport {\n IconCalendar, IconBall, IconBoot, IconGloves, IconShield, IconFlag, IconCheck, IconClose, IconPlus,\n} from './ui/icons'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { CrestShield } from './ui/CrestShield'\nimport { nationalityFlag } from './nationFlags'\n\nexport interface PlayerEntry {\n id: number\n name: string\n imagePath?: string\n}\n\n// playerPool comes from config.playerPool, threaded through by GameScreenHost.\nexport interface BeatTheGridGameProps extends GameScreenProps<BeatTheGridConfig> {\n playerPool: PlayerEntry[]\n}\n\ninterface ActiveCell {\n row: number\n col: number\n}\n\nexport type CriterionIconKind = 'calendar' | 'ball' | 'boot' | 'gloves' | 'shield' | 'flag'\n\n// Header icon from the criterion key when present (stable across languages), else the English\n// label text of a pre-u400 game; unknown criteria (nationality groups, yellow cards) get the flag.\nexport function criterionIconKind(label: string, key?: string): CriterionIconKind {\n const l = (key ?? label).toLowerCase()\n if (l.includes('app')) return 'calendar'\n if (l.includes('goal')) return 'ball'\n if (l.includes('assist')) return 'boot'\n if (l.includes('clean')) return 'gloves'\n if (l.includes('tackle')) return 'shield'\n return 'flag'\n}\n\n// The abbreviation map is keyed by the English position; a key like \"games.grid.row.forward\"\n// names it even when the label arrives translated (\"Forvet\").\nexport function rowAbbrev(label: string, map: Record<string, string>, key?: string): string {\n const suffix = key?.split('.').pop()\n const english = suffix ? suffix.charAt(0).toUpperCase() + suffix.slice(1) : label\n return map[english] ?? map[label] ?? label\n}\n\nfunction CriterionIcon({ kind }: { kind: CriterionIconKind }): JSX.Element {\n switch (kind) {\n case 'calendar': return <IconCalendar />\n case 'ball': return <IconBall />\n case 'boot': return <IconBoot />\n case 'gloves': return <IconGloves />\n case 'shield': return <IconShield />\n default: return <IconFlag />\n }\n}\n\n// Renders the visual prefix of a header cell based on BtgCriterionMeta when present.\n// Without meta, falls back to the stat/nationality icon (today's behaviour).\nfunction HeaderVisual({ label, textKey: iKey, meta }: { label: string; textKey?: string; meta?: BtgCriterionMeta }): JSX.Element {\n if (!meta) {\n return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n }\n switch (meta.kind) {\n case 'club':\n return <CrestShield src={meta.imageUrl} name={label} size={24} />\n case 'coach':\n return <PlayerAvatar name={label} imagePath={meta.imageUrl} className=\"ss-g-btg-coach-av\" />\n case 'country':\n return <span className=\"ss-g-btg-hdr-flag\" aria-hidden=\"true\">{nationalityFlag(meta.country ?? label)}</span>\n case 'position':\n // Full localized label only (no icon, no abbreviation); the caller omits the icon slot.\n return <></>\n default:\n return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n }\n}\n\nfunction parseClientState(json: string | null | undefined): BtgClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as BtgClientState\n } catch {\n return null\n }\n}\n\nfunction findCellResult(cells: BtgCellResult[], row: number, col: number): BtgCellResult | undefined {\n return cells.find(c => c.row === row && c.col === col)\n}\n\n// Compact initials for a placed player, e.g. \"Andrew Robertson\" → \"A. Robertson\".\n// Falls back to an empty string when the name is unknown.\nfunction shortName(name: string | undefined): string {\n if (!name) return ''\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n if (parts.length === 0) return ''\n const first = parts[0]!\n if (parts.length === 1) return first\n const last = parts[parts.length - 1]!\n return `${first.charAt(0)}. ${last}`\n}\n\nfunction SearchSheet({\n row,\n col,\n rowLabel,\n colLabel,\n playerPool,\n alreadyFilledIds,\n onPick,\n onDismiss,\n ui,\n}: {\n row: number\n col: number\n rowLabel: string\n colLabel: string\n playerPool: PlayerEntry[]\n alreadyFilledIds: Set<number>\n onPick: (row: number, col: number, playerId: number) => void\n onDismiss: () => void\n ui: UiConfig\n}): JSX.Element {\n const s = ui.games.beatTheGrid\n const [query, setQuery] = useState('')\n const inputId = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n\n useEffect(() => { inputRef.current?.focus() }, [row, col])\n\n const filtered = playerPool.filter(\n p => !alreadyFilledIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n )\n\n return (\n <div className=\"ss-g-btg-sheet\" data-testid=\"btg-search-sheet\">\n <div className=\"ss-g-btg-sheet-hdr\">\n <Chip variant=\"neutral\">{rowLabel}</Chip>\n <span className=\"ss-g-btg-sheet-x\" aria-hidden=\"true\"><IconClose size={12} /></span>\n <Chip variant=\"accent\">{colLabel}</Chip>\n <button\n type=\"button\"\n className=\"ss-g-btg-sheet-close\"\n data-testid=\"btg-sheet-dismiss\"\n aria-label={s.closeSearch}\n onClick={onDismiss}\n >\n <IconClose />\n </button>\n </div>\n {playerPool.length === 0 ? (\n <div className=\"ss-g-btg-sheet-empty\">{s.emptyPool}</div>\n ) : (\n <>\n <SearchField\n id={inputId}\n label={s.searchLabel(rowLabel, colLabel)}\n labelHidden\n placeholder={s.searchPlaceholder}\n value={query}\n onChange={setQuery}\n inputRef={inputRef}\n />\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={s.searchLabel(rowLabel, colLabel)}\n options={filtered.map(p => ({\n key: p.id,\n content: (\n <>\n <PlayerAvatar name={p.name} imagePath={p.imagePath} className=\"ss-g-opt-av\" />\n <span className=\"ss-g-btg-result-name\">{p.name}</span>\n <span className=\"ss-g-btg-result-plus\" aria-hidden=\"true\"><IconPlus size={18} /></span>\n </>\n ),\n }))}\n onPick={k => onPick(row, col, Number(k))}\n />\n )}\n </>\n )}\n </div>\n )\n}\n\nexport function BeatTheGridGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n playerPool,\n}: BeatTheGridGameProps): JSX.Element {\n const s = ui.games.beatTheGrid\n const title = gameTitle({ gameId: 'beat-the-grid' }, ui.games.titles)\n const [activeCell, setActiveCell] = useState<ActiveCell | null>(null)\n\n const clientState = parseClientState(result?.clientStateJson)\n const filledCells = clientState?.cells ?? []\n\n const isLocked =\n result?.alreadyPlayed === true ||\n clientState?.isComplete === true\n\n const alreadyFilledIds = new Set<number>(filledCells.map(c => c.playerId))\n\n function handleCellClick(row: number, col: number): void {\n if (isLocked || submitting) return\n const alreadyFilled = findCellResult(filledCells, row, col)\n if (alreadyFilled) return\n setActiveCell({ row, col })\n }\n\n function handlePick(row: number, col: number, playerId: number): void {\n setActiveCell(null)\n const prevCells = filledCells.map(c => ({ row: c.row, col: c.col, playerId: c.playerId }))\n const newCells = [...prevCells, { row, col, playerId }]\n onSubmit(JSON.stringify({ cells: newCells }))\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-beat-the-grid\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const rows = config.rows\n const cols = config.cols\n const total = rows.length * cols.length\n const correctCount = filledCells.filter(c => c.isCorrect).length\n const wrongCount = filledCells.length - correctCount\n const segments: SegmentState[] = Array.from({ length: total }, (_, i) =>\n i < correctCount ? 'correct' : i < correctCount + wrongCount ? 'wrong' : 'todo',\n )\n // A returning fan may come back with no client state: show the stored play score then.\n const totalScore = clientState?.totalScore ?? result?.score ?? 0\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-beat-the-grid\">\n <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress\n segments={segments}\n ariaLabel={s.progressAria(filledCells.length, total)}\n leftLabel={s.filled(filledCells.length, total)}\n rightLabel={s.toGo(Math.max(0, total - filledCells.length))}\n right={<Chip variant=\"accent\">{`${totalScore} ${ui.games.unitPts}`}</Chip>}\n />\n\n <div className=\"ss-g-body\">\n <div\n className={activeCell !== null ? 'ss-g-btg-grid ss-g-btg-grid--fit' : 'ss-g-btg-grid'}\n style={{\n gridTemplateColumns: `64px repeat(${cols.length}, minmax(0, 1fr))`,\n gridTemplateRows: `minmax(44px, 60px) repeat(${rows.length}, minmax(44px, 98px))`,\n } as React.CSSProperties}\n role=\"grid\"\n >\n <div className=\"ss-g-btg-corner\" />\n {cols.map((col, colIdx) => {\n const colMeta = config.colsMeta?.[colIdx]\n return (\n <div key={col} className=\"ss-g-btg-colhdr\" data-meta={colMeta ? 'true' : undefined}>\n <HeaderVisual label={col} textKey={config.colsI18n?.[colIdx]?.key} meta={colMeta} />\n <span>{col}</span>\n </div>\n )\n })}\n {rows.map((rowLabel, rowIdx) => {\n const rowMeta = config.rowsMeta?.[rowIdx]\n const abbr = rowAbbrev(rowLabel, s.rowAbbrev, config.rowsI18n?.[rowIdx]?.key)\n // With meta, render using HeaderVisual (empty for position) + the full label.\n // Without meta, use the abbreviation pattern (existing behaviour).\n const rowHeaderContent = rowMeta ? (\n <>\n <HeaderVisual label={rowLabel} textKey={config.rowsI18n?.[rowIdx]?.key} meta={rowMeta} />\n <span>{rowLabel}</span>\n </>\n ) : abbr === rowLabel ? (\n <span>{rowLabel}</span>\n ) : (\n <>\n <span aria-hidden=\"true\">{abbr}</span>\n <span className=\"ss-g-sr\">{rowLabel}</span>\n </>\n )\n return (\n <React.Fragment key={rowIdx}>\n <div className=\"ss-g-btg-rowhdr\" data-meta={rowMeta ? 'true' : undefined}>\n {rowHeaderContent}\n </div>\n {cols.map((colLabel, colIdx) => {\n const filled = findCellResult(filledCells, rowIdx, colIdx)\n const isActive = activeCell?.row === rowIdx && activeCell?.col === colIdx\n const state = filled ? (filled.isCorrect ? 'correct' : 'wrong') : isActive ? 'active' : 'empty'\n return (\n <button\n key={`cell-${rowIdx}-${colIdx}`}\n type=\"button\"\n data-testid={`btg-cell-${rowIdx}-${colIdx}`}\n data-state={state}\n aria-label={\n filled\n ? s.cellFilled(rowLabel, colLabel, playerPool.find(p => p.id === filled.playerId)?.name ?? '', filled.isCorrect ? s.correct : s.wrong)\n : s.pickCell(rowLabel, colLabel)\n }\n aria-pressed={isActive}\n className=\"ss-g-btg-cell\"\n disabled={isLocked || submitting}\n onClick={() => handleCellClick(rowIdx, colIdx)}\n >\n {filled ? (\n <>\n <span\n className={`ss-g-btg-badge ss-g-btg-badge--${filled.isCorrect ? 'correct' : 'wrong'}`}\n role=\"img\"\n aria-label={filled.isCorrect ? s.correct : s.wrong}\n >\n {filled.isCorrect ? <IconCheck size={11} /> : <IconClose size={11} />}\n </span>\n <span className=\"ss-g-btg-rarity\">{filled.rarityScore}</span>\n {(() => {\n const entry = playerPool.find(p => p.id === filled.playerId)\n return (\n <PlayerAvatar\n name={entry?.name ?? ''}\n imagePath={entry?.imagePath}\n className=\"ss-g-btg-av\"\n />\n )\n })()}\n <span className=\"ss-g-btg-name\">\n {shortName(playerPool.find(p => p.id === filled.playerId)?.name)}\n </span>\n </>\n ) : (\n <span className=\"ss-g-btg-plus\" aria-hidden=\"true\"><IconPlus size={22} /></span>\n )}\n </button>\n )\n })}\n </React.Fragment>\n )\n })}\n </div>\n\n {isLocked && (\n <ResultCard\n tone=\"neutral\"\n title={s.complete}\n score={totalScore}\n detail={s.summary(correctCount, filledCells.length)}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {activeCell !== null && (\n <div className=\"ss-g-btg-pin\">\n <SearchSheet\n key={`${activeCell.row}-${activeCell.col}`}\n row={activeCell.row}\n col={activeCell.col}\n rowLabel={rows[activeCell.row] ?? ''}\n colLabel={cols[activeCell.col] ?? ''}\n playerPool={playerPool}\n alreadyFilledIds={alreadyFilledIds}\n onPick={handlePick}\n onDismiss={() => setActiveCell(null)}\n ui={ui}\n />\n </div>\n )}\n </div>\n )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, GuessTheXiConfig, XiClientState } from './types'\nimport { isNationCode, nationalityFlag } from './nationFlags'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { CrestShield } from './ui/CrestShield'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { toRows, formationLabel, positionsBySlot } from './ui/formations'\nimport { PlayerAvatar } from './PlayerAvatar'\n\n// Total guesses allowed per day. Kept in sync with GuessTheXiScorer.MaxGuesses on the backend.\nconst MAX_GUESSES = 3\n\nfunction parseClientState(json: string | null | undefined): XiClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as XiClientState\n } catch {\n return null\n }\n}\n\nexport function GuessTheXiGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<GuessTheXiConfig>): JSX.Element {\n const t = ui.games.guessTheXi\n const [query, setQuery] = useState('')\n const inputId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n\n const isOver =\n result?.alreadyPlayed === true ||\n clientState?.status === 'solved' ||\n clientState?.status === 'failed'\n const solved = clientState?.status === 'solved'\n const failed = clientState?.status === 'failed'\n\n const guessedTeamIds = new Set<number>(clientState?.guessHistory.map(g => g.teamId) ?? [])\n const rows = config ? toRows(config.positions) : []\n // Only name the shape when the data is a real formation; a neutral fallback grid has no shape.\n const formation = config?.hasRealFormation ? formationLabel(rows) : ''\n // Position label under every node (GK/CB/CM/ST…), derived from the formation coordinates only.\n const posBySlot = config?.hasRealFormation ? positionsBySlot(formation, rows) : new Map<string, string>()\n\n // A wrong guess can earn a player-name reveal; pin each to its slot so the surname replaces that\n // node's position tag. Position-type reveals are redundant now that every position is shown.\n const nameBySlot = new Map<string, string>()\n ;(clientState?.earnedReveals ?? []).forEach(r => { if (r.slot && r.type !== 'position') nameBySlot.set(r.slot, r.value) })\n\n // When the game ends and a lineup is present, map slot → lineup entry for photo + name display.\n const lineupBySlot = new Map<string, { name: string; imagePath?: string }>()\n ;(clientState?.lineup ?? []).forEach(e => { lineupBySlot.set(e.slot, { name: e.name, imagePath: e.imagePath }) })\n\n const filtered =\n config && !isOver\n ? config.teamPool.filter(\n tm => !guessedTeamIds.has(tm.teamId) && tm.teamName.toLowerCase().includes(query.toLowerCase()),\n )\n : []\n\n function handlePick(teamId: number): void {\n if (!config || isOver || submitting) return\n const prevGuesses = clientState?.guessHistory.map(g => ({ teamId: g.teamId })) ?? []\n const newGuesses = [...prevGuesses, { teamId }]\n setQuery('')\n onSubmit(JSON.stringify({ guesses: newGuesses }))\n }\n\n const wrongGuesses = (clientState?.guessHistory ?? []).filter(g => !g.wasCorrect)\n const guessesLeft = Math.max(0, MAX_GUESSES - (clientState?.guessesUsed ?? 0))\n const teamName = (id: number): string => config?.teamPool.find(tm => tm.teamId === id)?.teamName ?? `#${id}`\n\n return (\n <div className=\"ss-g-screen ss-g-gxi\" data-testid=\"game-screen-guess-the-xi\">\n <GameHeader\n title={gameTitle({ gameId: 'guess-the-xi' }, ui.games.titles)}\n eyebrow={config?.poolLabel}\n right={formation ? <Chip variant=\"accent\">{formation}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n\n {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n {config && (\n <>\n <div className=\"ss-g-body\">\n {rows.length > 0 && (\n <div className=\"ss-g-gxi-pitch\" role=\"group\" aria-label={t.pitchLabel}>\n <PitchSvg variant=\"full\" />\n <div className=\"ss-g-gxi-rows\">\n {rows.map((row, r) => (\n <div key={r} className=\"ss-g-gxi-row\">\n {row.map((pos, c) => {\n const posLabel = pos.slot ? posBySlot.get(pos.slot) ?? '' : ''\n const name = pos.slot ? nameBySlot.get(pos.slot) : undefined\n const lineupEntry = pos.slot ? lineupBySlot.get(pos.slot) : undefined\n const flag = nationalityFlag(pos.nationality)\n // When lineup is present (terminal state), discs show photo + surname.\n if (lineupEntry) {\n return (\n <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed=\"true\">\n <PlayerAvatar\n name={lineupEntry.name}\n imagePath={lineupEntry.imagePath}\n className=\"ss-g-gxi-disc ss-g-gxi-disc--photo\"\n />\n <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(lineupEntry.name).last}</span>\n </div>\n )\n }\n return (\n <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed={name ? 'true' : undefined}>\n <span\n className=\"ss-g-gxi-disc\"\n data-code={isNationCode(flag) ? 'true' : undefined}\n role=\"img\"\n title={pos.nationality}\n aria-label={`${posLabel ? posLabel + ' — ' : ''}${pos.nationality}${name ? ' — ' + name : ''}`}\n >\n {flag}\n </span>\n {name\n ? <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(name).last}</span>\n : posLabel && <span className=\"ss-g-gxi-pos\">{posLabel}</span>}\n </div>\n )\n })}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {!isOver && wrongGuesses.length > 0 && (\n <div className=\"ss-g-gxi-wrong\">\n <span className=\"ss-g-gxi-wrong-l\">{t.notThem}</span>\n {wrongGuesses.map(g => {\n const crestUrl = config?.teamPool.find(tm => tm.teamId === g.teamId)?.crestUrl\n return (\n <span key={g.teamId} className=\"ss-g-gxi-wrong-chip\">\n <CrestShield src={crestUrl} name={teamName(g.teamId)} size={18} />\n <s>{teamName(g.teamId)}</s>\n </span>\n )\n })}\n </div>\n )}\n\n {isOver && (\n <>\n <ResultCard\n tone={solved ? 'win' : failed ? 'lose' : 'neutral'}\n title={solved ? t.solved : failed ? t.failed : ui.games.alreadyPlayedTitle}\n score={clientState?.score ?? result?.score ?? 0}\n detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n onBack={onBack}\n ui={ui}\n />\n {(solved || failed) && clientState?.answer && (\n <div className=\"ss-g-gxi-answer\" data-testid=\"gxi-answer-reveal\">\n <span className=\"ss-g-gxi-answer-label\">{t.theAnswer}</span>\n <CrestShield src={clientState.answer.crestUrl} name={clientState.answer.teamName} size={32} />\n <span className=\"ss-g-gxi-answer-name\">{clientState.answer.teamName}</span>\n </div>\n )}\n </>\n )}\n </div>\n\n {!isOver && (\n <FooterBar>\n {query.length > 0 && filtered.length > 0 && (\n <OptionList\n label={t.optionsLabel}\n options={filtered.map(tm => ({\n key: tm.teamId,\n content: <><CrestShield src={tm.crestUrl} name={tm.teamName} size={28} /><span>{tm.teamName}</span></>,\n }))}\n onPick={k => handlePick(Number(k))}\n />\n )}\n <SearchField id={inputId} label={t.whichClub(guessesLeft)} placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={submitting} />\n </FooterBar>\n )}\n </>\n )}\n </div>\n )\n}\n","export function PitchSvg({ variant }: { variant: 'full' | 'half' }): JSX.Element {\n return (\n <svg className=\"ss-g-pitch-svg\" viewBox={variant === 'full' ? '0 0 100 150' : '0 0 100 100'} preserveAspectRatio=\"none\" aria-hidden=\"true\">\n <rect x=\"4\" y=\"4\" width=\"92\" height={variant === 'full' ? 142 : 92} fill=\"none\" />\n {variant === 'full' ? (\n <>\n <line x1=\"4\" y1=\"75\" x2=\"96\" y2=\"75\" /><circle cx=\"50\" cy=\"75\" r=\"12\" fill=\"none\" />\n <rect x=\"26\" y=\"4\" width=\"48\" height=\"20\" fill=\"none\" /><rect x=\"26\" y=\"126\" width=\"48\" height=\"20\" fill=\"none\" />\n </>\n ) : (\n <>\n <path d=\"M38 4a12 12 0 0 0 24 0\" fill=\"none\" />\n <rect x=\"26\" y=\"76\" width=\"48\" height=\"20\" fill=\"none\" />\n </>\n )}\n </svg>\n )\n}\n","import type { XiSlotEntry } from '../types'\n\n/**\n * Groups the flat position list into formation rows keyed by the \"row:col\" slot's row part, then\n * orders the rows so the GOALKEEPER LINE (row 1) sits at the BOTTOM — the football convention: a\n * team defends the bottom goal and attacks upward (GK → defence → midfield → attack).\n *\n * Within a line the provider numbers positions from the team's RIGHT (Sportmonks formation_field:\n * \"2:1\" is the right-back, \"2:4\" the left-back). Drawn attacking upward, the right side is on the\n * screen's right, so each line is returned highest column first (left → right on screen).\n */\nexport function toRows(positions: XiSlotEntry[]): XiSlotEntry[][] {\n const byRow = new Map<number, XiSlotEntry[]>()\n positions.forEach((p, i) => {\n const rowKey = Number(p.slot?.split(':')[0]) || i + 1\n const bucket = byRow.get(rowKey) ?? []\n bucket.push(p)\n byRow.set(rowKey, bucket)\n })\n const col = (p: XiSlotEntry): number => Number(p.slot?.split(':')[1]) || 0\n // Descending: highest row number (forwards) at the top, row 1 (GK) at the bottom.\n return [...byRow.keys()].sort((a, b) => b - a).map(k => [...byRow.get(k)!].sort((a, b) => col(b) - col(a)))\n}\n\n// Football formation notation from the grouped rows — the outfield lines from defence to attack,\n// goalkeeper excluded (e.g. GK/4/2/3/1 → \"4-2-3-1\"). `rows` arrive attack-first (descending), so\n// read them bottom-up and drop the goalkeeper line.\nexport function formationLabel(rowsAttackFirst: XiSlotEntry[][]): string {\n if (rowsAttackFirst.length < 2) return ''\n const gkFirst = [...rowsAttackFirst].reverse()\n return gkFirst.slice(1).map(r => r.length).join('-')\n}\n\n// Canonical position labels per formation, goalkeeper first then each outfield line, left→right.\n// Lets us print a real position (GK, RB, CDM, ST…) under every node so the fan can read the shape\n// and see at a glance which end is the goalkeeper — without the config having to carry positions.\nexport const FORMATION_POSITIONS: Record<string, string[][]> = {\n '4-4-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['ST', 'ST']],\n '4-3-3': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CM', 'CM', 'CM'], ['LW', 'ST', 'RW']],\n '4-2-3-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM', 'CDM'], ['LW', 'CAM', 'RW'], ['ST']],\n '4-1-4-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n '4-5-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'CM', 'RM'], ['ST']],\n '4-4-1-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['CAM'], ['ST']],\n '4-1-2-1-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'RM'], ['CAM'], ['ST', 'ST']],\n '3-5-2': [['GK'], ['CB', 'CB', 'CB'], ['LWB', 'CM', 'CM', 'CM', 'RWB'], ['ST', 'ST']],\n '3-4-3': [['GK'], ['CB', 'CB', 'CB'], ['LM', 'CM', 'CM', 'RM'], ['LW', 'ST', 'RW']],\n '5-3-2': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['CM', 'CM', 'CM'], ['ST', 'ST']],\n '5-4-1': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n}\n\n// Line-level fallback when the exact formation is not in the table above: the goalkeeper line, the\n// forward line, then defence/midfield by depth. Always correct at the line grain even when the\n// specific role is not — enough to read the shape and spot the keeper.\nexport function lineFallback(lineIdx: number, totalLines: number): string {\n if (lineIdx === 0) return 'GK'\n if (lineIdx === totalLines - 1) return 'FWD'\n if (lineIdx === 1) return 'DEF'\n return 'MID'\n}\n\n// Map each slot (\"row:col\") to a position label, reading the rows goalkeeper-first.\nexport function positionsBySlot(formation: string, rowsAttackFirst: XiSlotEntry[][]): Map<string, string> {\n const gkFirst = [...rowsAttackFirst].reverse()\n const template = FORMATION_POSITIONS[formation]\n const map = new Map<string, string>()\n gkFirst.forEach((line, li) => {\n line.forEach((entry, ci) => {\n if (!entry.slot) return\n const label = template?.[li]?.[ci] ?? lineFallback(li, gkFirst.length)\n map.set(entry.slot, label)\n })\n })\n return map\n}\n","import { useState } from 'react'\nimport type { GameScreenProps, DailyQuizConfig, DailyQuizClientState, DailyQuizResult } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): DailyQuizClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as DailyQuizClientState\n } catch {\n return null\n }\n}\n\nfunction findResult(results: DailyQuizResult[], index: number): DailyQuizResult | undefined {\n return results.find(r => r.index === index)\n}\n\nconst TRAILING_PAREN = /\\s*\\(([^)]*)\\)$/\nconst NAME_TOKEN = /^[\\p{L}\\p{M}.'’-]+$/u\n\nfunction OptionName({ text }: { text: string }): JSX.Element {\n const match = TRAILING_PAREN.exec(text)\n const base = match ? text.slice(0, match.index).trim() : text.trim()\n const suffix = match?.[1]?.trim() ?? ''\n const tokens = base.split(/\\s+/).filter(Boolean)\n const isPlainName = tokens.length >= 1 && tokens.length <= 4 && tokens.every(t => NAME_TOKEN.test(t))\n if (!isPlainName || base === '') {\n return (\n <span className=\"ss-g-dq-opt-name\">\n <span className=\"ss-g-dq-opt-full\">{text}</span>\n </span>\n )\n }\n const { first, last } = splitName(base)\n return (\n <span className=\"ss-g-dq-opt-name\">\n {first && <span className=\"ss-g-dq-opt-first\">{first}</span>}\n <span className=\"ss-g-dq-opt-last\">{last}</span>\n {suffix && <span className=\"ss-g-dq-opt-suffix\">{suffix}</span>}\n </span>\n )\n}\n\nexport function DailyQuizGame({\n config,\n result,\n submitting,\n onSubmit,\n onBack,\n ui,\n}: GameScreenProps<DailyQuizConfig>): JSX.Element {\n const s = ui.games.dailyQuiz\n const title = gameTitle({ gameId: 'daily-quiz' }, ui.games.titles)\n // Local selection state: map from question index → selected option index\n const [selections, setSelections] = useState<Map<number, number>>(new Map())\n const [page, setPage] = useState(0)\n\n const clientState = parseClientState(result?.clientStateJson)\n const results = clientState?.results ?? []\n const isRevealed = results.length > 0 || result?.alreadyPlayed === true\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} onBack={onBack} backLabel={ui.back} />\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const questions = config.questions\n const total = questions.length\n const current = questions[Math.min(page, total - 1)]\n const isLast = page >= total - 1\n const currentAnswered = current !== undefined && selections.has(current.index)\n const allAnswered = selections.size === total\n\n function handleSelect(questionIndex: number, optionIndex: number): void {\n if (isRevealed || submitting) return\n setSelections(prev => new Map(prev).set(questionIndex, optionIndex))\n }\n\n function goNext(): void {\n if (!currentAnswered || isLast) return\n setPage(p => p + 1)\n }\n\n function goPrev(): void {\n setPage(p => Math.max(0, p - 1))\n }\n\n function handleSubmit(): void {\n if (!config || !allAnswered || isRevealed || submitting) return\n const answers = config.questions.map(q => ({\n index: q.index,\n selectedOptionIndex: selections.get(q.index) ?? 0,\n }))\n onSubmit(JSON.stringify({ answers }))\n }\n\n if (isRevealed) {\n const segments: SegmentState[] = questions.map(q => {\n const r = findResult(results, q.index)\n if (!r) return 'done'\n return r.isCorrect ? 'correct' : 'wrong'\n })\n const correctCount = results.filter(r => r.isCorrect).length\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} eyebrow={s.results} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress segments={segments} ariaLabel={s.results} />\n <div className=\"ss-g-body\">\n <ResultCard\n tone=\"neutral\"\n title={results.length > 0 ? s.correctOf(correctCount, total) : ui.games.alreadyPlayedTitle}\n score={result?.score}\n onBack={onBack}\n ui={ui}\n />\n {questions.map(q => {\n const r = findResult(results, q.index)\n const picked = selections.get(q.index)\n return (\n <div key={q.index} className=\"ss-g-dq-rq\">\n <div className=\"ss-g-dq-rq-stem\">{q.stem}</div>\n {r && (\n <div className=\"ss-g-dq-rq-opts\">\n {q.options.map((opt, optIdx) => {\n let cls = 'ss-g-dq-rq-opt'\n if (optIdx === r.correctOptionIndex) cls += ' ss-g-dq-rq-opt--correct'\n else if (optIdx === picked && !r.isCorrect) cls += ' ss-g-dq-rq-opt--wrong'\n return <span key={optIdx} className={cls}>{opt}</span>\n })}\n </div>\n )}\n {r?.revealText && <div className=\"ss-g-dq-why\">{r.revealText}</div>}\n </div>\n )\n })}\n </div>\n </div>\n )\n }\n\n const segments: SegmentState[] = questions.map((_, i) => (i < page ? 'done' : i === page ? 'current' : 'todo'))\n const selectedIdx = current ? selections.get(current.index) : undefined\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-daily-quiz\">\n <GameHeader title={title} eyebrow={s.questionOf(page + 1, total)} onBack={onBack} backLabel={ui.back} />\n <SegmentProgress segments={segments} ariaLabel={s.progressAria(page + 1, total)} />\n <div className=\"ss-g-body\">\n {current && (\n <>\n <h3 className=\"ss-g-dq-stem\">{current.stem}</h3>\n <div className=\"ss-g-dq-opts\">\n {current.options.map((opt, optIdx) => {\n const selected = optIdx === selectedIdx\n const imagePath = current.optionImagePaths?.[optIdx] ?? undefined\n const playerName = opt\n return (\n <button\n key={optIdx}\n type=\"button\"\n className=\"ss-g-dq-opt\"\n aria-pressed={selected}\n disabled={submitting}\n onClick={() => handleSelect(current.index, optIdx)}\n >\n {current.optionImagePaths && (\n <PlayerAvatar name={playerName} imagePath={imagePath} className=\"ss-g-dq-opt-av\" />\n )}\n <span className=\"ss-g-dq-badge\" aria-hidden=\"true\">\n {selected ? <IconCheck /> : String.fromCharCode(65 + optIdx)}\n </span>\n <OptionName text={opt} />\n </button>\n )\n })}\n </div>\n </>\n )}\n </div>\n <FooterBar>\n <div className=\"ss-g-dq-nav\">\n {page > 0 && (\n <GameButton variant=\"outline\" onClick={goPrev} disabled={submitting}>{s.previous}</GameButton>\n )}\n {isLast ? (\n <GameButton variant=\"primary\" block onClick={handleSubmit} disabled={!currentAnswered || !allAnswered || submitting}>\n {submitting ? s.submitting : s.submit}\n </GameButton>\n ) : (\n <GameButton variant=\"primary\" block onClick={goNext} disabled={!currentAnswered || submitting}>\n {s.next}\n </GameButton>\n )}\n </div>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n MatchdayPredictorConfig,\n MatchdayPredictorClientState,\n MatchdayPredictorTeam,\n} from './types'\nimport type { GamesStrings } from '../../i18n'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck, IconClose, IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Above this many scorers the card grid gets a search filter (spec §5.7).\nconst SCORER_SEARCH_THRESHOLD = 9\n\ntype Side = 'home' | 'away'\ntype PredictorStrings = GamesStrings['predictor']\n\nfunction parseClientState(json: string | null | undefined): MatchdayPredictorClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as MatchdayPredictorClientState\n } catch {\n return null\n }\n}\n\nfunction isLocked(kickoffUtc: string): boolean {\n try {\n return new Date(kickoffUtc).getTime() <= Date.now()\n } catch {\n return true\n }\n}\n\nfunction IconMinus(): JSX.Element {\n return (\n <svg width={18} height={18} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.2}\n strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M5 12h14\" /></svg>\n )\n}\n\nfunction TeamBadge({ team, label }: { team: MatchdayPredictorTeam; label: string }): JSX.Element {\n return (\n <div className=\"ss-g-mp-team\">\n <CrestShield name={team.name} size={44} />\n <span className=\"ss-g-mp-team-name\">{team.name}</span>\n <span className=\"ss-g-mp-team-side\">{label}</span>\n </div>\n )\n}\n\nfunction ScoreCard({ home, away, h, a, t, edit }: {\n home: MatchdayPredictorTeam\n away: MatchdayPredictorTeam\n h: number\n a: number\n t: PredictorStrings\n edit?: { disabled: boolean; active: Side; onStep: (side: Side, delta: 1 | -1) => void }\n}): JSX.Element {\n const col = (side: Side, team: MatchdayPredictorTeam, value: number): JSX.Element => (\n <div className=\"ss-g-mp-col\">\n {edit && (\n <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsUp(team.name)}\n disabled={edit.disabled} onClick={() => edit.onStep(side, 1)}>\n <IconPlus size={18} />\n </button>\n )}\n <span className=\"ss-g-mp-digit\" data-testid=\"mp-digit\" data-active={edit ? String(edit.active === side) : 'false'}>\n {value}\n </span>\n {edit && (\n <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsDown(team.name)}\n disabled={edit.disabled || value <= 0} onClick={() => edit.onStep(side, -1)}>\n <IconMinus />\n </button>\n )}\n </div>\n )\n return (\n <div className=\"ss-g-mp-card\">\n <TeamBadge team={home} label={t.home} />\n <div className=\"ss-g-mp-scores\">\n {col('home', home, h)}\n <span className=\"ss-g-mp-dash\" aria-hidden=\"true\">–</span>\n {col('away', away, a)}\n </div>\n <TeamBadge team={away} label={t.away} />\n </div>\n )\n}\n\nfunction OutcomeRow({ label, ok, detail, t }: { label: string; ok: boolean; detail?: string | null; t: PredictorStrings }): JSX.Element {\n return (\n <li className=\"ss-g-mp-row\" data-testid=\"mp-row\" data-ok={String(ok)}>\n <span className=\"ss-g-mp-row-k\">{label}</span>\n <span className=\"ss-g-mp-row-v\">\n {ok ? <IconCheck /> : <IconClose size={14} />}\n <span className=\"ss-g-sr\">{ok ? t.correct : t.incorrect}</span>\n {detail ? <span className=\"ss-g-mp-row-d\">{detail}</span> : null}\n </span>\n </li>\n )\n}\n\nexport function MatchdayPredictorGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<MatchdayPredictorConfig>): JSX.Element {\n const t = ui.games.predictor\n const [homeScore, setHomeScore] = useState(0)\n const [awayScore, setAwayScore] = useState(0)\n const [firstScorerPlayerId, setFirstScorerPlayerId] = useState<number | null>(null)\n const [lastEdited, setLastEdited] = useState<Side>('home')\n const [query, setQuery] = useState('')\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyPlayed = result?.alreadyPlayed === true\n\n const header = (\n <GameHeader\n title={gameTitle({ gameId: 'matchday-predictor' }, ui.games.titles)}\n eyebrow={config ? t.eyebrow(config.homeTeam.name, config.awayTeam.name) : undefined}\n right={config ? <Chip icon={<IconLock />}>{ui.games.formatDayTime(config.kickoffUtc)}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n // Played states (pending or graded) when the fan has already submitted\n if (alreadyPlayed && clientState) {\n if (!clientState.graded) {\n const scorer = config?.scorerPool.find(p => p.playerId === clientState.predictedFirstScorerPlayerId) ?? null\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n {config && (\n <ScoreCard home={config.homeTeam} away={config.awayTeam}\n h={clientState.predictedHomeScore} a={clientState.predictedAwayScore} t={t} />\n )}\n <ResultCard\n tone=\"neutral\"\n title={t.saved}\n detail={t.savedDetail({\n home: config?.homeTeam.name ?? '',\n away: config?.awayTeam.name ?? '',\n h: clientState.predictedHomeScore,\n a: clientState.predictedAwayScore,\n scorer: scorer ? splitName(scorer.playerName).last : null,\n })}\n onBack={onBack}\n ui={ui}\n />\n </div>\n <FooterBar>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n }\n\n const r = clientState.result\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n {config && <ScoreCard home={config.homeTeam} away={config.awayTeam} h={r.homeScore} a={r.awayScore} t={t} />}\n <ResultCard tone=\"neutral\" title={t.fullTime(r.homeScore, r.awayScore)} onBack={onBack} ui={ui} />\n <ul className=\"ss-g-mp-rows\">\n <OutcomeRow label={t.exactScore} ok={clientState.exactScoreCorrect} t={t} />\n <OutcomeRow label={t.outcome} ok={clientState.outcomeCorrect} t={t} />\n {!clientState.firstScorerVoid && (\n <OutcomeRow label={t.firstScorerRow} ok={clientState.firstScorerCorrect} detail={r.firstScorerName} t={t} />\n )}\n </ul>\n </div>\n <FooterBar>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const locked = isLocked(config.kickoffUtc)\n const disabled = locked || submitting\n\n function step(side: Side, delta: 1 | -1): void {\n setLastEdited(side)\n if (side === 'home') setHomeScore(s => Math.max(0, s + delta))\n else setAwayScore(s => Math.max(0, s + delta))\n }\n\n function handleSubmit(): void {\n if (disabled || !config) return\n onSubmit(\n JSON.stringify({\n homeScore,\n awayScore,\n ...(firstScorerPlayerId !== null ? { firstScorerPlayerId } : {}),\n }),\n )\n }\n\n const pool = config.scorerPool\n const showSearch = pool.length > SCORER_SEARCH_THRESHOLD\n const q = query.trim().toLowerCase()\n const visible = showSearch && q ? pool.filter(p => p.playerName.toLowerCase().includes(q)) : pool\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-matchday-predictor\">\n {header}\n <div className=\"ss-g-body\">\n <ScoreCard\n home={config.homeTeam}\n away={config.awayTeam}\n h={homeScore}\n a={awayScore}\n t={t}\n edit={{ disabled, active: lastEdited, onStep: step }}\n />\n\n {pool.length > 0 && (\n <section className=\"ss-g-mp-scorer\">\n <div className=\"ss-g-mp-sec-head\">\n <h3>{t.firstScorer}</h3>\n <span>{t.optional}</span>\n </div>\n {showSearch && (\n <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchPlaceholder}\n value={query} onChange={setQuery} disabled={disabled} />\n )}\n <div className=\"ss-g-mp-grid\">\n {visible.map(p => {\n const selected = firstScorerPlayerId === p.playerId\n return (\n <button\n key={p.playerId}\n type=\"button\"\n className=\"ss-g-mp-pcard\"\n aria-pressed={selected}\n aria-label={p.playerName}\n disabled={disabled}\n onClick={() => setFirstScorerPlayerId(id => (id === p.playerId ? null : p.playerId))}\n >\n {selected && <span className=\"ss-g-mp-pcheck\"><IconCheck size={12} /></span>}\n <Silhouette size={52} variant={selected ? 'selected' : 'default'} />\n <span className=\"ss-g-mp-pname\">{splitName(p.playerName).last}</span>\n </button>\n )\n })}\n </div>\n <button\n type=\"button\"\n className=\"ss-g-mp-none\"\n aria-pressed={firstScorerPlayerId === null}\n disabled={disabled}\n onClick={() => setFirstScorerPlayerId(null)}\n >\n <span className=\"ss-g-mp-radio\" aria-hidden=\"true\" />\n {t.noScorer}\n </button>\n </section>\n )}\n\n {locked && <p className=\"ss-g-mp-closed\">{t.closed}</p>}\n </div>\n\n <FooterBar>\n <GameButton variant=\"primary\" block disabled={disabled} onClick={handleSubmit}>\n {submitting ? t.saving : t.save}\n </GameButton>\n <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n StartingXiConfig,\n StartingXiClientState,\n StartingXiSquadEntry,\n} from './types'\nimport { FORMATION_POSITIONS, lineFallback } from './ui/formations'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Display only — mirrors StartingXiScorer.PointsPerCorrectStarter (StartingXiScorer.cs:47).\nconst POINTS_PER_STARTER = 8\nconst XI_SIZE = 11\nconst DEFAULT_FORMATION = '4-3-3'\n\nexport interface XiSlot {\n index: number\n label: string\n left: number\n top: number\n}\n\nfunction parseClientState(json: string | null | undefined): StartingXiClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as StartingXiClientState\n } catch {\n return null\n }\n}\n\n/**\n * Pitch slots for a formation, goalkeeper first then each outfield line left→right. Positions are\n * percentages of an attacking-half pitch: the keeper sits lowest (top 88%), the front line highest.\n * A formation that does not add up to 10 outfield players falls back to 4-3-3 so there are always 11.\n */\nexport function formationSlots(formation: string): { formation: string; slots: XiSlot[] } {\n const parts = formation.split('-').map(Number).filter(n => n > 0)\n const valid = parts.reduce((s, n) => s + n, 0) === XI_SIZE - 1\n const used = valid ? formation : DEFAULT_FORMATION\n const outfield = valid ? parts : DEFAULT_FORMATION.split('-').map(Number)\n const lines = [1, ...outfield]\n const template = FORMATION_POSITIONS[used]\n const slots: XiSlot[] = []\n lines.forEach((count, li) => {\n const top = 88 - li * (77 / (lines.length - 1))\n for (let ci = 0; ci < count; ci++) {\n const left = count === 1 ? 50 : 12 + ci * (76 / (count - 1))\n slots.push({ index: slots.length, label: template?.[li]?.[ci] ?? lineFallback(li, lines.length), left, top })\n }\n })\n return { formation: used, slots }\n}\n\nfunction firstEmpty(slotPlayers: (number | null)[]): number | null {\n const i = slotPlayers.findIndex(p => p === null)\n return i === -1 ? null : i\n}\n\nexport function StartingXiGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n lockAtUtc,\n}: GameScreenProps<StartingXiConfig>): JSX.Element {\n const t = ui.games.startingXi\n const [slotPlayers, setSlotPlayers] = useState<(number | null)[]>(() => Array<number | null>(XI_SIZE).fill(null))\n const [active, setActive] = useState<number | null>(0)\n const [query, setQuery] = useState('')\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyPlayed = result?.alreadyPlayed === true\n\n const header = (\n <GameHeader\n title={gameTitle({ gameId: 'starting-xi' }, ui.games.titles)}\n eyebrow={t.eyebrow}\n right={<Chip variant=\"accent\">{t.perStarter(POINTS_PER_STARTER)}</Chip>}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n // Pending, graded and voided all render the spec §6 result card with a way back to the hub.\n function statusScreen(title: string, score?: number): JSX.Element {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <div className=\"ss-g-body\">\n <ResultCard tone=\"neutral\" title={title} score={score} onBack={onBack} ui={ui} />\n </div>\n </div>\n )\n }\n\n if (alreadyPlayed) {\n if (!clientState) return statusScreen(t.voided)\n if (clientState.status === 'pending') return statusScreen(t.pending(clientState.predictedCount))\n if (clientState.status === 'graded') return statusScreen(t.gradedLine(clientState.correctCount), clientState.score)\n }\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const { formation, slots } = formationSlots(config.formation)\n const byId = new Map<number, StartingXiSquadEntry>(config.squadSheet.map(p => [p.playerId, p]))\n const pickedCount = slotPlayers.filter(p => p !== null).length\n const canSubmit = pickedCount === XI_SIZE && !submitting\n const pickedSet = new Set(slotPlayers.filter((p): p is number => p !== null))\n const q = query.trim().toLowerCase()\n const available = config.squadSheet.filter(\n p => !pickedSet.has(p.playerId) && (!q || (p.playerName ?? '').toLowerCase().includes(q)),\n )\n const activeSlot = active !== null ? slots[active] ?? null : null\n\n function pick(playerId: number): void {\n if (submitting || active === null) return\n const next = [...slotPlayers]\n next[active] = playerId\n setSlotPlayers(next)\n setActive(firstEmpty(next))\n setQuery('')\n }\n\n function tapSlot(index: number): void {\n if (submitting) return\n if (slotPlayers[index] !== null) {\n const next = [...slotPlayers]\n next[index] = null\n setSlotPlayers(next)\n }\n setActive(index)\n }\n\n function handleSubmit(): void {\n if (!canSubmit) return\n onSubmit(JSON.stringify({ predictedPlayerIds: slotPlayers }))\n }\n\n const segments: SegmentState[] = slotPlayers.map(p => (p !== null ? 'current' : 'todo'))\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-starting-xi\">\n {header}\n <SegmentProgress\n segments={segments}\n ariaLabel={t.picked(pickedCount)}\n leftLabel={t.picked(pickedCount)}\n rightLabel={t.toGo(XI_SIZE - pickedCount)}\n right={<Chip>{formation}</Chip>}\n />\n <div className=\"ss-g-body\">\n <div className=\"ss-g-xi-pitch\">\n <PitchSvg variant=\"half\" />\n {slots.map(s => {\n const playerId = slotPlayers[s.index] ?? null\n const player = playerId !== null ? byId.get(playerId) ?? null : null\n const name = player?.playerName ?? ''\n const state = player ? 'filled' : active === s.index ? 'active' : 'empty'\n return (\n <button\n key={s.index}\n type=\"button\"\n className=\"ss-g-xi-slot\"\n data-state={state}\n style={{ left: `${s.left}%`, top: `${s.top}%` }}\n aria-pressed={active === s.index}\n aria-label={player ? t.clearSlot(s.label, name) : t.pickSlot(s.label)}\n disabled={submitting}\n onClick={() => tapSlot(s.index)}\n >\n <span className=\"ss-g-xi-ring\" aria-hidden=\"true\">\n {player ? (player.jerseyNumber ?? '') : <IconPlus size={18} />}\n </span>\n <span className=\"ss-g-xi-tag\" aria-hidden=\"true\">{player ? splitName(name).last : s.label}</span>\n </button>\n )\n })}\n </div>\n\n <div className=\"ss-g-xi-picker\">\n <div className=\"ss-g-xi-picker-head\">\n {activeSlot ? (\n <>\n <Chip variant=\"badge\">{activeSlot.label}</Chip>\n <strong>{t.pickFor(activeSlot.label)}</strong>\n </>\n ) : (\n <strong>{t.allPicked}</strong>\n )}\n </div>\n {activeSlot && (\n <>\n <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchLabel}\n value={query} onChange={setQuery} disabled={submitting} />\n <ul className=\"ss-g-xi-list\">\n {available.map(p => (\n <li key={p.playerId}>\n <button type=\"button\" className=\"ss-g-xi-opt\" disabled={submitting} onClick={() => pick(p.playerId)}>\n <span className=\"ss-g-xi-opt-no\" aria-hidden=\"true\">{p.jerseyNumber ?? ''}</span>\n <span className=\"ss-g-xi-opt-name\">{p.playerName}</span>\n <span className=\"ss-g-xi-opt-pos\">{p.positionName}</span>\n </button>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n </div>\n <FooterBar>\n <GameButton variant=\"primary\" block disabled={!canSubmit} onClick={handleSubmit}>\n {submitting ? t.submitting : t.submit}\n </GameButton>\n <p className=\"ss-g-xi-lock\">\n <IconLock />\n {lockAtUtc ? t.locksAt(ui.games.formatDayTime(lockAtUtc)) : t.locksSoon}\n </p>\n </FooterBar>\n </div>\n )\n}\n","import { useId, useState } from 'react'\nimport type {\n GameScreenProps,\n StatLadderConfig,\n StatLadderClientState,\n StatLadderRung,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconBulb, IconCheck, IconShield } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nexport interface LadderClue {\n value: number\n above: { name: string; diff: number } | null\n below: { name: string; diff: number } | null\n}\n\n/** Pure: the mystery rung's value plus its gaps to the named rungs directly above (rank 1) and below (rank 3). */\nexport function ladderClue(ladder: StatLadderRung[]): LadderClue | null {\n const mystery = ladder.find(r => r.rank === 2)\n if (!mystery) return null\n const above = ladder.find(r => r.rank === 1)\n const below = ladder.find(r => r.rank === 3)\n return {\n value: mystery.statValue,\n above: above?.playerName ? { name: above.playerName, diff: above.statValue - mystery.statValue } : null,\n below: below?.playerName ? { name: below.playerName, diff: mystery.statValue - below.statValue } : null,\n }\n}\n\nfunction parseClientState(json: string | null | undefined): StatLadderClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as StatLadderClientState\n } catch {\n return null\n }\n}\n\nfunction NameStack({ name }: { name: string }): JSX.Element {\n const { first, last } = splitName(name)\n return (\n <span className=\"ss-g-sl-name\">\n {first && <small>{`${first[0]}.`}</small>}\n <b>{last}</b>\n </span>\n )\n}\n\nexport function StatLadderGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<StatLadderConfig>): JSX.Element {\n const t = ui.games.statLadder\n const [query, setQuery] = useState('')\n const [selectedId, setSelectedId] = useState<number | null>(null)\n const searchId = useId()\n\n const clientState = parseClientState(result?.clientStateJson)\n const revealed = clientState != null\n\n const header = (\n <GameHeader title={gameTitle({ gameId: 'stat-ladder' }, ui.games.titles)} eyebrow={t.eyebrow} onBack={onBack} backLabel={ui.back} />\n )\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-stat-ladder\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const question = t.question(config.statLabel)\n const clue = revealed ? null : ladderClue(config.ladder)\n const rungs = [...config.ladder].sort((a, b) => a.rank - b.rank)\n const q = query.trim().toLowerCase()\n const pool = q ? config.playerPool.filter(p => p.playerName.toLowerCase().includes(q)) : config.playerPool\n\n function guess(): void {\n if (selectedId === null || submitting || revealed) return\n onSubmit(JSON.stringify({ guessedPlayerId: selectedId }))\n }\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-stat-ladder\">\n {header}\n <div className=\"ss-g-body\">\n <div className=\"ss-g-sl-prompt\">\n <Chip variant=\"accent\" icon={<IconShield size={14} />} className=\"ss-g-sl-stat\">{config.statLabel}</Chip>\n <h3 className=\"ss-g-sl-q\">\n {question.pre}<em>{question.emph}</em>{question.post}\n </h3>\n </div>\n\n <ol className=\"ss-g-sl-rungs\">\n {rungs.map(rung =>\n rung.rank === 2 ? (\n <li\n key={rung.rank}\n className=\"ss-g-sl-rung ss-g-sl-rung--mystery\"\n data-testid=\"sl-mystery-rung\"\n data-result={revealed ? (clientState!.isCorrect ? 'correct' : 'wrong') : undefined}\n >\n <span className=\"ss-g-sl-rank\">2</span>\n {revealed\n ? <PlayerAvatar name={clientState!.revealedRank2.playerName} className=\"ss-g-sl-av\" />\n : <Silhouette size={52} variant=\"mystery\" />}\n {revealed\n ? <NameStack name={clientState!.revealedRank2.playerName} />\n : <span className=\"ss-g-sl-who\">{t.whoSecond}</span>}\n <span className=\"ss-g-sl-val ss-g-sl-val--mystery\">{rung.statValue}</span>\n </li>\n ) : (\n <li key={rung.rank} className=\"ss-g-sl-rung\">\n <span className=\"ss-g-sl-rank\">{rung.rank}</span>\n <PlayerAvatar name={rung.playerName ?? '?'} className=\"ss-g-sl-av\" />\n <NameStack name={rung.playerName ?? '?'} />\n <span className=\"ss-g-sl-val\">{rung.statValue}</span>\n </li>\n ),\n )}\n </ol>\n\n {clue && (\n <p className=\"ss-g-sl-clue\">\n <IconBulb />\n <span>{t.clue(clue, config.statLabel)}</span>\n </p>\n )}\n\n {!revealed && (\n <ul className=\"ss-g-sl-pool\">\n {pool.map(p => (\n <li key={p.playerId}>\n <button\n type=\"button\"\n className=\"ss-g-sl-opt\"\n aria-label={p.playerName}\n aria-pressed={selectedId === p.playerId}\n disabled={submitting}\n onClick={() => { setSelectedId(p.playerId); setQuery(p.playerName) }}\n >\n <PlayerAvatar name={p.playerName} className=\"ss-g-sl-opt-av\" />\n <span className=\"ss-g-sl-opt-name\">{p.playerName}</span>\n {selectedId === p.playerId && <IconCheck />}\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {revealed && (\n <ResultCard\n tone={clientState!.isCorrect ? 'win' : 'lose'}\n title={clientState!.isCorrect ? t.correct : t.wrong(clientState!.revealedRank2.playerName)}\n score={result?.score}\n onBack={onBack}\n ui={ui}\n />\n )}\n </div>\n\n {!revealed && (\n <FooterBar>\n <div className=\"ss-g-sl-guess\">\n <SearchField\n id={searchId}\n label={t.searchLabel}\n labelHidden\n placeholder={t.searchPlaceholder}\n value={query}\n onChange={v => { setQuery(v); setSelectedId(null) }}\n disabled={submitting}\n />\n <GameButton variant=\"primary\" disabled={selectedId === null || submitting} onClick={guess}>\n {t.guess}\n </GameButton>\n </div>\n </FooterBar>\n )}\n </div>\n )\n}\n","import type {\n GameScreenProps,\n FanMotmConfig,\n FanMotmClientState,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): FanMotmClientState | null {\n if (!json) return null\n try {\n return JSON.parse(json) as FanMotmClientState\n } catch {\n return null\n }\n}\n\nexport function FanMotmGame({\n config,\n result,\n submitting,\n onSubmit,\n ui,\n onBack,\n}: GameScreenProps<FanMotmConfig>): JSX.Element {\n const t = ui.games.motm\n const clientState = parseClientState(result?.clientStateJson)\n const alreadyVoted = result?.alreadyPlayed === true\n const pickedId = clientState?.pickedPlayerId ?? null\n\n const header = (\n <GameHeader\n title={t.title}\n eyebrow={t.eyebrow}\n right={alreadyVoted ? <Chip variant=\"success\" icon={<IconCheck />}>{t.voted}</Chip> : undefined}\n onBack={onBack}\n backLabel={ui.back}\n />\n )\n\n if (!config) {\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-fan-motm\">\n {header}\n <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n </div>\n )\n }\n\n const picked = config.candidates.find(c => c.playerId === pickedId) ?? null\n\n function handleVote(candidateId: number): void {\n if (alreadyVoted || submitting) return\n onSubmit(JSON.stringify({ pickedPlayerId: candidateId }))\n }\n\n return (\n <div className=\"ss-g-screen\" data-testid=\"game-screen-fan-motm\">\n {header}\n <div className=\"ss-g-body\">\n <ul className=\"ss-g-motm-list\">\n {config.candidates.map(c => {\n const isVoted = alreadyVoted && pickedId === c.playerId\n return (\n <li key={c.playerId}>\n <button\n type=\"button\"\n className={`ss-g-motm-row${isVoted ? ' ss-g-motm-row--voted' : ''}`}\n data-testid={`motm-candidate-${c.playerId}`}\n disabled={alreadyVoted || submitting}\n onClick={() => handleVote(c.playerId)}\n >\n <PlayerAvatar name={c.playerName} className=\"ss-g-motm-av\" />\n <span className=\"ss-g-motm-name\">{c.playerName}</span>\n {isVoted && <Chip variant=\"accent\" className=\"ss-g-motm-pill\">{t.yourVote}</Chip>}\n </button>\n </li>\n )\n })}\n </ul>\n {alreadyVoted && picked && (\n <ResultCard tone=\"neutral\" title={t.youVoted(picked.playerName)} detail={t.thanks} onBack={onBack} ui={ui} />\n )}\n </div>\n <FooterBar>\n {!alreadyVoted && <p className=\"ss-g-motm-foot\">{t.tapToVote}</p>}\n <p className=\"ss-g-motm-fun\">{t.forFun}</p>\n </FooterBar>\n </div>\n )\n}\n","const FONTS_LINK_ID = 'ss-w-games-fonts'\nconst FONTS_HREF =\n 'https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Barlow:wght@400;500;600;700&display=swap'\n\n// Registered at document level: @font-face inside a shadow root is ignored by browsers, but\n// document fonts resolve inside the embed's shadow tree. If CSP blocks it the fallback stack renders.\nexport function ensureGamesFonts(doc: Document = document): void {\n if (!doc.head) return\n if (doc.getElementById(FONTS_LINK_ID)) return\n const link = doc.createElement('link')\n link.id = FONTS_LINK_ID\n link.rel = 'stylesheet'\n link.href = FONTS_HREF\n doc.head.appendChild(link)\n}\n","import { useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { LeaderboardWeeklyRow, LeaderboardAllTimeRow, formatPoints } from './LeaderboardRow'\nimport { LeaderboardEmpty } from './LeaderboardEmpty'\n\ntype Segment = 'weekly' | 'alltime'\n\nexport function Leaderboard({\n data,\n ui,\n onPlay,\n}: {\n data: LeaderboardPayload\n ui: UiConfig\n /** Jumps to the Games tab from the empty-state CTA. */\n onPlay?: () => void\n}): JSX.Element {\n const [segment, setSegment] = useState<Segment>('weekly')\n\n const myRow = segment === 'weekly' ? data.myWeeklyRow : data.myAllTimeRow\n const offBoard = myRow !== null && myRow !== undefined && myRow.rank === -1\n const isEmpty = segment === 'weekly'\n ? data.weeklyTop.length === 0\n : data.allTimeTop.length === 0\n\n return (\n <div className=\"ss-w-lb2\">\n <div className=\"ss-w-seg\">\n <button\n type=\"button\"\n className=\"ss-w-seg-btn\"\n {...(segment === 'weekly' ? { 'data-on': '' } : {})}\n onClick={() => setSegment('weekly')}\n >\n {ui.leaderboardThisWeek}\n </button>\n <button\n type=\"button\"\n className=\"ss-w-seg-btn\"\n {...(segment === 'alltime' ? { 'data-on': '' } : {})}\n onClick={() => setSegment('alltime')}\n >\n {ui.leaderboardAllTime}\n </button>\n </div>\n\n {isEmpty ? (\n <LeaderboardEmpty\n segment={segment}\n lastWeek={data.lastWeek}\n weeklyPrize={data.weeklyPrize}\n onPlay={onPlay}\n ui={ui}\n />\n ) : (\n <>\n <div className=\"ss-w-lb2-rows\">\n {segment === 'weekly'\n ? data.weeklyTop.map((row) => (\n <LeaderboardWeeklyRow\n key={row.operatorUserId}\n row={row}\n isMe={row.operatorUserId === data.myWeeklyRow?.operatorUserId}\n />\n ))\n : data.allTimeTop.map((row) => (\n <LeaderboardAllTimeRow\n key={row.operatorUserId}\n row={row}\n isMe={row.operatorUserId === data.myAllTimeRow?.operatorUserId}\n />\n ))}\n </div>\n\n {/* Kit-prize separator */}\n <div className=\"ss-w-kitline\">🎽</div>\n\n {/* Pinned \"you\" row or off-board treatment */}\n {myRow != null && (\n offBoard ? (\n <div className=\"ss-w-lbgap\">{ui.leaderboardOffBoard}</div>\n ) : (\n <div className=\"ss-w-lb2-rows\">\n {segment === 'weekly' && data.myWeeklyRow && (\n <LeaderboardWeeklyRow row={data.myWeeklyRow} isMe />\n )}\n {segment === 'alltime' && data.myAllTimeRow && (\n <LeaderboardAllTimeRow row={data.myAllTimeRow} isMe />\n )}\n </div>\n )\n )}\n\n {/* All-time footer: show rank + total when available */}\n {segment === 'alltime' && data.myAllTimeRow && !offBoard && (\n <div className=\"ss-w-lb2-rows\">\n <div className=\"ss-w-lb2-row\">\n <span className=\"ss-w-lb2-handle\">\n {formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0))}\n </span>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n","import type { LeaderboardRow as SDKRow, AllTimeRow } from '@sensiblestats/widget-sdk'\n\n/** Formats a points integer with thousands separators. */\nexport function formatPoints(n: number): string {\n return n.toLocaleString('en')\n}\n\nexport function LeaderboardWeeklyRow({\n row,\n isMe,\n}: {\n row: SDKRow\n isMe: boolean\n}): JSX.Element {\n const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n return (\n <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n <span className={rankClass}>#{row.rank}</span>\n <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n <span className=\"ss-w-lb2-points\">{formatPoints(row.points)}</span>\n {row.currentStreak > 0 && (\n <span className=\"ss-w-lb2-streak\">🔥 {row.currentStreak}</span>\n )}\n </div>\n )\n}\n\nexport function LeaderboardAllTimeRow({\n row,\n isMe,\n}: {\n row: AllTimeRow\n isMe: boolean\n}): JSX.Element {\n const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n return (\n <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n <span className={rankClass}>#{row.rank}</span>\n <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n <span className=\"ss-w-lb2-points\">{formatPoints(row.allTimePoints)}</span>\n </div>\n )\n}\n","import type { LeaderboardChampion } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { formatPoints } from './LeaderboardRow'\n\ntype Segment = 'weekly' | 'alltime'\n\n/**\n * Default state for the leaderboard when the active segment has no ranked rows.\n * Weekly boards reset every week, so this is what most fans see at the start of a week.\n * - weekly + a prior champion -> \"fresh week\" copy plus a last-week continuity strip\n * - weekly + no history -> \"cold start\" copy (club's first-ever week)\n * - all-time -> a quiet single line; it fills as fans play\n */\nexport function LeaderboardEmpty({\n segment,\n lastWeek,\n weeklyPrize,\n onPlay,\n ui,\n}: {\n segment: Segment\n lastWeek?: LeaderboardChampion | null\n weeklyPrize?: string | null\n onPlay?: () => void\n ui: UiConfig\n}): JSX.Element {\n if (segment === 'alltime') {\n return (\n <div className=\"ss-w-lb-empty ss-w-lb-empty--alltime\">\n <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">📊</div>\n <p className=\"ss-w-lb-empty-body\">{ui.leaderboardAllTimeEmpty}</p>\n </div>\n )\n }\n\n const fresh = lastWeek != null\n const title = fresh ? ui.leaderboardEmptyFreshTitle : ui.leaderboardEmptyColdTitle\n const body = fresh ? ui.leaderboardEmptyFreshBody : ui.leaderboardEmptyColdBody\n\n return (\n <div className=\"ss-w-lb-empty\">\n {weeklyPrize && (\n <div className=\"ss-w-prize\">\n <span className=\"ss-w-prize-icon\" aria-hidden=\"true\">🏆</span>\n <div className=\"ss-w-prize-body\">\n <span className=\"ss-w-prize-text\">{weeklyPrize}</span>\n </div>\n </div>\n )}\n\n <div className=\"ss-w-lb-empty-hero\">\n <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">{fresh ? '🏆' : '🎮'}</div>\n <h4 className=\"ss-w-lb-empty-title\">{title}</h4>\n <p className=\"ss-w-lb-empty-body\">{body}</p>\n {onPlay && (\n <button type=\"button\" className=\"ss-w-lb-empty-cta\" onClick={onPlay}>\n {ui.leaderboardEmptyCta}\n </button>\n )}\n </div>\n\n {fresh && lastWeek && (\n <div className=\"ss-w-lb-last\">\n <span className=\"ss-w-lb-last-label\">{ui.leaderboardLastWeekLabel}</span>\n <span className=\"ss-w-lb-last-champ\" aria-hidden=\"true\">🥇</span>\n <span className=\"ss-w-lb-last-handle\">{lastWeek.handle}</span>\n <span className=\"ss-w-lb-last-points\">{formatPoints(lastWeek.points)}</span>\n </div>\n )}\n </div>\n )\n}\n","import type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { Leaderboard } from './Leaderboard'\n\n/** Settled empty board (no rows yet) — a fetch that returned null once loading is done. */\nconst EMPTY_PAYLOAD: LeaderboardPayload = {\n week: '',\n weeklyTop: [],\n myWeeklyRow: null,\n allTimeTop: [],\n myAllTimeRow: null,\n weeklyPrize: null,\n lastWeek: null,\n}\n\nexport function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }: {\n loggedIn: boolean\n data: LeaderboardPayload | null\n loading?: boolean\n onPlay?: () => void\n ui: UiConfig\n}): JSX.Element {\n if (!loggedIn) return <GamesLoginWall ui={ui} />\n // Still fetching with nothing to show yet: keep the panel blank (skeleton-free).\n if (data === null && loading) return <div className=\"ss-w-mon-list\" />\n return (\n <div className=\"ss-w-mon-list\">\n <Leaderboard data={data ?? EMPTY_PAYLOAD} ui={ui} onPlay={onPlay} />\n </div>\n )\n}\n","import { isValidId } from './host'\n\nexport const VIEW_DEDUPE_MS = 30 * 60 * 1000\nexport const HELD_MAX = 5\n\n/** duplicate: seen inside the window. log: report it now. held: kept until the panel opens. */\nexport type ViewResult = 'duplicate' | 'log' | 'held'\n\nexport interface MatchViews {\n /** A match page view, or a click on a match link. */\n view(matchId: number): ViewResult\n /** The panel opened. Returns the matches held until now, oldest first; empty on later opens. */\n markOpened(): number[]\n}\n\nexport interface MatchViewsOptions {\n /** operatorUserId of the current visitor; undefined when anonymous. */\n user?: string\n /** Defaults to window.sessionStorage. Pass null for a memory-only state. */\n storage?: Storage | null\n now?: () => number\n}\n\ninterface ViewState {\n opened: boolean\n seen: Record<string, number>\n held: number[]\n}\n\nconst empty = (): ViewState => ({ opened: false, seen: {}, held: [] })\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parse(raw: string | null, user: string | undefined): ViewState {\n if (!raw) return empty()\n let blob: unknown\n try {\n blob = JSON.parse(raw)\n } catch {\n return empty()\n }\n if (!isRecord(blob) || blob.v !== 1) return empty()\n // One visitor's panel open and held views must not count for the next visitor of the tab. A\n // blob with no user was written while logged out and carries over to whoever logs in.\n if (blob.user !== undefined && blob.user !== user) return empty()\n const state = empty()\n state.opened = blob.opened === true\n if (isRecord(blob.seen)) {\n for (const [key, at] of Object.entries(blob.seen)) {\n if (typeof at === 'number' && Number.isFinite(at)) state.seen[key] = at\n }\n }\n // Held ids are logged when the panel opens, so they are re-checked and capped here: a blob\n // someone edited must not be able to put a bad id, or more events than a batch holds, on the wire.\n if (Array.isArray(blob.held)) {\n state.held = blob.held.filter(isValidId).slice(-HELD_MAX)\n }\n return state\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n try {\n return window.sessionStorage\n } catch {\n return null\n }\n}\n\n/**\n * What this tab has already reported about match views. It lives in sessionStorage because a host\n * can remount the widget on every navigation, and memory would forget that the visitor had opened\n * the panel. After the first storage failure the state lives in memory for the rest of the mount.\n */\nexport function createMatchViews(storageKey: string, options: MatchViewsOptions = {}): MatchViews {\n const now = options.now ?? (() => Date.now())\n const user = options.user\n let storage: Storage | null | undefined = options.storage\n let memory: ViewState = empty()\n\n const read = (): ViewState => {\n if (storage === undefined) storage = browserStorage()\n if (storage) {\n try {\n memory = parse(storage.getItem(storageKey), user)\n } catch {\n storage = null\n }\n }\n return memory\n }\n\n const write = (state: ViewState): void => {\n memory = state\n if (!storage) return\n try {\n storage.setItem(storageKey, JSON.stringify({ v: 1, user, ...state }))\n } catch {\n storage = null\n }\n }\n\n return {\n view(matchId) {\n const at = now()\n const state = read()\n for (const key of Object.keys(state.seen)) {\n if (at - (state.seen[key] ?? 0) >= VIEW_DEDUPE_MS) delete state.seen[key]\n }\n const key = String(matchId)\n if (state.seen[key] !== undefined) return 'duplicate'\n state.seen[key] = at\n let result: ViewResult = 'log'\n if (!state.opened) {\n state.held = [...state.held.filter((id) => id !== matchId), matchId].slice(-HELD_MAX)\n result = 'held'\n }\n write(state)\n return result\n },\n markOpened() {\n const state = read()\n if (state.opened) return []\n const at = now()\n const held = state.held\n // Stamped now, so the dedupe window starts when the row is written, not when it was held.\n for (const id of held) state.seen[String(id)] = at\n write({ opened: true, seen: state.seen, held: [] })\n return held\n },\n }\n}\n","import type { WidgetEventInput } from '@sensiblestats/widget-sdk'\nimport { isValidId } from './host'\nimport { MAX_LINE, MAX_ODDS, MAX_SELECTION } from './slip'\n\nexport const LEDGER_TTL_MS = 7 * 24 * 60 * 60 * 1000\nexport const LEDGER_MAX = 100\n// The most ledger hits one host call reports. The server rejects a batch of more than 50 events\n// and the logger sends its whole queue as one batch, so an uncapped bet could fail a batch and\n// lose every event in it.\nexport const BET_REPORT_MAX = 25\nconst MAX_MARKET = 128\n// The server's floor (WidgetEventBatchRequest.Odds). An event below it fails its whole batch.\nconst MIN_ODDS = 1.0001\n\nexport interface LedgerEntry {\n /** matchOddsId */\n id: number\n /** market developer name */\n market: string\n matchId?: number\n selection?: string\n line?: string\n odds?: number\n /** operatorUserId at add time; absent for an anonymous visitor */\n user?: string\n /** epoch milliseconds */\n at: number\n}\n\nexport interface SlipLedger {\n record(entry: Omit<LedgerEntry, 'at'>): void\n take(id: number, currentUser: string | undefined): LedgerEntry | null\n}\n\nexport interface SlipLedgerOptions {\n /** Defaults to window.localStorage. Pass null for a memory-only ledger. */\n storage?: Storage | null\n now?: () => number\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction fits(value: unknown, max: number): value is string {\n return typeof value === 'string' && value.trim().length > 0 && value.length <= max\n}\n\n// Storage is not trusted: someone can edit the blob, and one bad value in a logged event fails\n// the whole batch at the gateway. An entry that cannot be identified is dropped; a bad optional\n// field is left out and the entry kept.\nfunction clean(item: unknown): LedgerEntry | null {\n if (!isRecord(item)) return null\n const { id, market, at, user } = item\n if (!isValidId(id)) return null\n if (typeof at !== 'number' || !Number.isFinite(at)) return null\n if (!fits(market, MAX_MARKET)) return null\n if (user !== undefined && (typeof user !== 'string' || user.length === 0)) return null\n const entry: LedgerEntry = { id, market, at }\n if (typeof user === 'string') entry.user = user\n if (isValidId(item.matchId)) entry.matchId = item.matchId\n if (fits(item.selection, MAX_SELECTION)) entry.selection = item.selection\n if (fits(item.line, MAX_LINE)) entry.line = item.line\n const odds = item.odds\n if (typeof odds === 'number' && Number.isFinite(odds) && odds >= MIN_ODDS && odds <= MAX_ODDS) entry.odds = odds\n return entry\n}\n\nfunction parse(raw: string | null): LedgerEntry[] {\n if (!raw) return []\n let blob: unknown\n try {\n blob = JSON.parse(raw)\n } catch {\n return []\n }\n if (!isRecord(blob) || blob.v !== 1 || !Array.isArray(blob.entries)) return []\n const entries: LedgerEntry[] = []\n for (const item of blob.entries) {\n const entry = clean(item)\n if (entry) entries.push(entry)\n }\n return entries\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n try {\n return window.localStorage\n } catch {\n return null\n }\n}\n\n/**\n * The widget's record of its own adds, so a later slipRemoved/betPlaced from the host can be\n * reported with the fields the add logged. Every call reads storage, so two tabs share one\n * ledger. After the first storage failure the ledger keeps working from memory for the rest of\n * the mount and stops touching storage.\n */\nexport function createSlipLedger(storageKey: string, options: SlipLedgerOptions = {}): SlipLedger {\n const now = options.now ?? (() => Date.now())\n let storage: Storage | null | undefined = options.storage\n // The entries last read or written. It becomes the ledger itself once storage has failed.\n let memory: LedgerEntry[] = []\n\n const read = (): LedgerEntry[] => {\n if (storage === undefined) storage = browserStorage()\n if (storage) {\n try {\n memory = parse(storage.getItem(storageKey))\n } catch {\n storage = null\n }\n }\n return memory\n }\n\n const write = (entries: LedgerEntry[]): void => {\n memory = entries\n if (!storage) return\n try {\n storage.setItem(storageKey, JSON.stringify({ v: 1, entries }))\n } catch {\n storage = null\n }\n }\n\n const live = (entry: LedgerEntry, at: number): boolean => at - entry.at <= LEDGER_TTL_MS\n\n return {\n record(entry) {\n const at = now()\n const cleaned = clean({ ...entry, at })\n if (!cleaned) return\n const kept = read().filter((e) => e.id !== cleaned.id && live(e, at))\n // Entries are appended in time order, so the last LEDGER_MAX are the newest.\n kept.push(cleaned)\n write(kept.slice(-LEDGER_MAX))\n },\n take(id, currentUser) {\n const at = now()\n const entries = read().filter((e) => live(e, at))\n const index = entries.findIndex((e) => e.id === id)\n const entry = entries[index]\n if (!entry) return null\n // One user's pick must not count for the next user of a shared browser. An entry with no\n // user was added while logged out and belongs to whoever is here now.\n if (entry.user !== undefined && entry.user !== currentUser) return null\n entries.splice(index, 1)\n write(entries)\n return entry\n },\n }\n}\n\n/** The wire event for a host call that hit this entry: the same fields the add logged. A field\n * the entry lacks is undefined here and so absent from the JSON that goes out. */\nexport function toSlipEvent(name: 'slip_remove' | 'bet_placed', entry: LedgerEntry): WidgetEventInput {\n return {\n name, entityType: 'market', entityId: entry.market, marketDeveloperName: entry.market,\n matchId: entry.matchId, selection: entry.selection, line: entry.line, odds: entry.odds,\n }\n}\n","import { ENTITY_TYPE_CODES, type Conversation, type EventLogger, type GreetingDashboardLayout, type GreetingDashboardTile, type SignalEntityType, type WidgetEntityType } from '@sensiblestats/widget-sdk'\n\nexport type DashboardTapHandler = (tile: GreetingDashboardTile, index: number, layout: GreetingDashboardLayout) => void\n\n// tile.signal.entityType is a plain string on the wire (GreetingDashboardSignalRef), so a value\n// outside the union must be checked, not asserted -- an unchecked cast would let an unrecognised\n// value reach toSignalWireBody, which throws synchronously and is swallowed by the try/catch\n// below, silently dropping the tap the same way an unresolved entityId used to.\nfunction isSignalEntityType(value: string): value is SignalEntityType {\n return Object.prototype.hasOwnProperty.call(ENTITY_TYPE_CODES, value)\n}\n\n// The server's GreetingDashboardSignalRef.entityType is PascalCase ('Team', 'Market', ...) and\n// carries a couple of values (Article/Session/Query/Conversation) that have no widget-event\n// counterpart -- those, and anything unrecognised, map to null so the caller can skip the emit\n// instead of sending a bogus entityType.\nfunction toWidgetEntityType(value: string): WidgetEntityType | null {\n switch (value.toLowerCase()) {\n case 'match': return 'match'\n case 'team': return 'team'\n case 'player': return 'player'\n case 'competition': return 'competition'\n case 'market': return 'market'\n default: return null\n }\n}\n\n/**\n * Builds the tap-to-signal side effect for a greeting dashboard tile.\n * Every tap is a MarketView signal (spec 9.4) regardless of the tile's own entity type --\n * entityType/entityId identify what was tapped, dashboardLayout/tileIndex identify where.\n *\n * `log` is threaded in as a parameter (not read via `useEventLog()`) because this module is a\n * plain factory, not a component or hook -- the caller (a component) owns the logger instance.\n */\nexport function createDashboardTapSignal(sendSignal: Conversation['sendSignal'], log?: EventLogger | null): DashboardTapHandler {\n return (tile, index, layout) => {\n const widgetEntityType = toWidgetEntityType(tile.signal.entityType)\n if (widgetEntityType) {\n log?.log({ name: 'tile_tap', entityType: widgetEntityType, entityId: tile.signal.entityId })\n }\n if (!isSignalEntityType(tile.signal.entityType)) return\n // sendSignal throws synchronously with no identity configured, and its returned promise\n // can reject on a gateway failure. Neither may break the tap -- the message this tile sent\n // still has to reach the model even when the Interest Engine can't be reached.\n try {\n void sendSignal({\n signalType: 'MarketView',\n entityType: tile.signal.entityType,\n entityId: tile.signal.entityId,\n dashboardLayout: layout,\n tileIndex: index,\n }).catch(() => undefined)\n } catch {\n // ignored -- see comment above\n }\n }\n}\n","import type { UiConfig } from './config'\n\nexport interface ThemeAttrs {\n 'data-ss-w-theme': string\n 'data-ss-w-pos': string\n style: Record<string, string>\n}\n\nexport function themeAttrs(ui: UiConfig): ThemeAttrs {\n const style: Record<string, string> = {\n '--ss-w-offset-x': `${ui.offset.x}px`,\n '--ss-w-offset-y': `${ui.offset.y}px`,\n '--ss-w-radius': `${ui.radius}px`,\n }\n if (ui.accent) style['--ss-w-accent'] = ui.accent\n if (ui.cta) style['--ss-w-cta'] = ui.cta\n if (ui.surface) style['--ss-w-panel'] = ui.surface\n if (ui.ink) style['--ss-w-ink'] = ui.ink\n if (ui.surface && ui.ink) {\n style['--ss-w-bubble'] = 'color-mix(in srgb, var(--ss-w-ink) 5%, var(--ss-w-panel))'\n style['--ss-w-line'] = 'color-mix(in srgb, var(--ss-w-ink) 12%, var(--ss-w-panel))'\n style['--ss-w-faint'] = 'color-mix(in srgb, var(--ss-w-ink) 55%, var(--ss-w-panel))'\n }\n return { 'data-ss-w-theme': ui.theme, 'data-ss-w-pos': ui.position, style }\n}\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'\nimport type { ChatGrounding, ChatHandle, ChatInput, Conversation } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { reducer, initialState, type WidgetState, type AssistantTurn } from './reducer'\nimport { chipFromText } from './model'\nimport { useLiveDashboardPoll } from './useLiveDashboardPoll'\nimport { readConversation, writeConversation, clearConversation } from './conversationStore'\n\n// An assistant turn counts as an answer only if it carries something to show. Deliberately\n// excludes `actions` -- follow-up chips are not answer content, so an errored turn that only\n// has fallback chips must not count as answered.\nfunction hasAnswerContent(t: AssistantTurn): boolean {\n return !!t.text || t.cards.length > 0 || t.insights.length > 0 ||\n t.marketOdds.length > 0 || t.oddsMovement.length > 0 ||\n !!t.greetingDashboard || !!t.clubFanDashboard\n}\n\n// If the server never emits a terminal event (turn_complete/error) within this window, the\n// panel would otherwise spin forever -- an async generator that just ends without yielding a\n// terminal event leaves isStreaming stuck at true, since only turn_complete/error/STOP clear it.\nexport const STREAM_FALLBACK_TIMEOUT_MS = 30_000\n\n// Next id must not collide with restored m{n} ids (React keys + live-dashboard id matching).\nfunction seedIdCounter(messages: { id: string }[]): number {\n let max = -1\n for (const m of messages) {\n const n = Number(m.id.slice(1)) // ids are `m${n}`\n if (m.id[0] === 'm' && Number.isFinite(n) && n > max) max = n\n }\n return max + 1\n}\n\nexport interface SendOptions {\n actionId?: string\n /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap) — forwarded on ChatInput.actionRef. */\n actionRef?: string\n /** Text shown in the user bubble when it differs from the message sent upstream (e.g. an action's label). */\n displayText?: string\n /** Structured context for the turn (a tapped live fact) — forwarded on ChatInput.grounding. */\n grounding?: ChatGrounding\n}\n\nexport interface ChatController {\n state: WidgetState\n open(): void\n close(): void\n stop(): void\n toggle(): void\n send(text: string, opts?: SendOptions): void\n retry(): void\n dismissPopup(): void\n reset(): void\n}\n\nexport function useChatStream(conversation: Conversation, starterTexts: string[], greetingMessage?: string, storageKey?: string): ChatController {\n const boot = useMemo(() => {\n const payload = storageKey ? readConversation(storageKey, Date.now()) : null\n const restored = payload != null && payload !== 'expired' && payload !== 'corrupt'\n const base = initialState(starterTexts.map(chipFromText))\n if (restored) {\n return { state: { ...base, messages: payload.messages, conversationId: payload.conversationId, starters: [] }, restored: true, stale: false }\n }\n return { state: base, restored: false, stale: payload === 'expired' || payload === 'corrupt' }\n }, [])\n const [state, dispatch] = useReducer(reducer, boot.state)\n const idRef = useRef(seedIdCounter(boot.state.messages))\n const handleRef = useRef<ChatHandle | null>(null)\n const fallbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const stateRef = useRef(state)\n stateRef.current = state\n const greetedRef = useRef(boot.restored) // restored -> greeting already \"handled\" (suppressed)\n const hydratedRef = useRef(false) // suppresses the single re-persist a cross-tab sync would echo\n\n const restoreSeededRef = useRef(false)\n if (!restoreSeededRef.current) {\n restoreSeededRef.current = true\n if (boot.restored && boot.state.conversationId) conversation.conversationId = boot.state.conversationId\n }\n\n const nextId = () => `m${idRef.current++}`\n\n const clearFallbackTimer = useCallback(() => {\n if (fallbackTimerRef.current != null) {\n clearTimeout(fallbackTimerRef.current)\n fallbackTimerRef.current = null\n }\n }, [])\n\n // Arms a watchdog for one in-flight send. clearFallbackTimer() is called on every path that\n // supersedes this send (a newer run(), stop(), close()) or that sees a terminal event, so a\n // firing timer always means neither happened in time -- including the case where the async\n // generator simply ends without ever yielding turn_complete/error: consume()'s own `finally`\n // nulls handleRef as soon as that happens, so this cannot key off handle identity (it would\n // already look \"stale\" and the very hang it exists to catch would go unreported).\n const armFallbackTimer = useCallback((onFire: () => void) => {\n clearFallbackTimer()\n fallbackTimerRef.current = setTimeout(() => {\n fallbackTimerRef.current = null\n handleRef.current?.cancel()\n handleRef.current = null\n onFire()\n }, STREAM_FALLBACK_TIMEOUT_MS)\n }, [clearFallbackTimer])\n\n const consume = useCallback((handle: ChatHandle, onError: (err: WidgetSdkError) => void) => {\n ;(async () => {\n try {\n for await (const event of handle) {\n dispatch({ kind: 'EVENT', event })\n if (event.type === 'turn_complete' || event.type === 'error') clearFallbackTimer()\n }\n } catch (err) {\n // A superseded handle's late rejection (run() already cancelled it and armed a new\n // timer for the newer send) must not touch the current send's timer -- only clear here\n // when this handle is still the one in flight.\n if (handleRef.current === handle) clearFallbackTimer()\n if (err instanceof WidgetSdkError) onError(err)\n else if ((err as { name?: string } | null)?.name === 'AbortError') { /* expected on cancel/close — ignore */ }\n else throw err\n } finally {\n if (handleRef.current === handle) handleRef.current = null\n }\n })()\n }, [clearFallbackTimer])\n\n const run = useCallback((input: ChatInput, displayText?: string) => {\n handleRef.current?.cancel()\n clearFallbackTimer()\n dispatch({ kind: 'USER_SENT', input, userId: nextId(), assistantId: nextId(), displayText })\n const handle = conversation.send(input)\n handleRef.current = handle\n armFallbackTimer(() => {\n dispatch({ kind: 'STOP' })\n dispatch({ kind: 'STREAM_ERROR', error: new WidgetSdkError('No response received in time', 'timeout') })\n })\n consume(handle, (err) => dispatch({ kind: 'STREAM_ERROR', error: err }))\n }, [conversation, consume, clearFallbackTimer, armFallbackTimer])\n\n const send = useCallback((text: string, opts?: SendOptions) => {\n const trimmed = text.trim()\n if (!trimmed) return\n run({ message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef, grounding: opts?.grounding }, opts?.displayText)\n }, [run])\n\n const retry = useCallback(() => {\n const last = stateRef.current.lastUserInput\n if (last) run(last, stateRef.current.lastDisplayText ?? undefined)\n }, [run])\n\n // Auto-greeting: fire once on mount when configured (and not restored from storage). No\n // user bubble; its response becomes the launcher popup. Fire-and-forget — failures\n // (including a fallback timeout) are swallowed (STOP only, no visible error) since this is\n // non-critical background chatter. Also reused by reset() to re-greet after clearing.\n const fireGreeting = useCallback(() => {\n const message = greetingMessage?.trim()\n if (!message) return\n try {\n handleRef.current?.cancel()\n clearFallbackTimer()\n dispatch({ kind: 'GREETING_SENT', assistantId: nextId() })\n const handle = conversation.send({ message })\n handleRef.current = handle\n armFallbackTimer(() => dispatch({ kind: 'STOP' }))\n consume(handle, () => dispatch({ kind: 'STOP' }))\n } catch {\n dispatch({ kind: 'STOP' })\n }\n }, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer])\n\n useEffect(() => {\n if (greetedRef.current) return // restored, or already greeted\n greetedRef.current = true\n fireGreeting()\n }, [fireGreeting])\n\n // Clear a stale/corrupt blob once, from an effect (never during the render seed).\n useEffect(() => {\n if (boot.stale && storageKey) clearConversation(storageKey)\n }, [])\n\n // Persist only complete exchanges after each settle (never mid-stream, never the greeting).\n // A user message is kept only when its paired assistant turn (USER_SENT always pushes\n // [user, assistant] together) is done, non-greeting, and has real content -- this drops a\n // trailing unanswered question (panel closed mid-stream) and an empty errored bubble alike.\n useEffect(() => {\n if (!storageKey || state.isStreaming) return\n if (hydratedRef.current) { hydratedRef.current = false; return } // don't echo a sync back out\n const msgs = state.messages\n const persistable = msgs.filter((m, i) => {\n if (m.role === 'user') {\n const next = msgs[i + 1]\n return !!next && next.role === 'assistant' && next.done && !next.isGreeting && hasAnswerContent(next)\n }\n return m.done && !m.isGreeting && hasAnswerContent(m)\n })\n if (persistable.length === 0) return\n writeConversation(storageKey, state.conversationId, persistable, Date.now())\n }, [storageKey, state.isStreaming, state.messages, state.conversationId])\n\n // Live multi-tab sync: mirror another tab's write/clear of the shared conversation.\n useEffect(() => {\n if (!storageKey) return\n const onStorage = (e: StorageEvent) => {\n if (e.key !== storageKey || e.storageArea !== window.localStorage) return\n if (stateRef.current.isStreaming) return // never clobber an in-flight turn in this tab\n if (e.newValue == null) {\n // cleared elsewhere (New conversation / expiry) -> mirror a fresh conversation\n idRef.current = 0\n conversation.conversationId = undefined\n hydratedRef.current = true\n dispatch({ kind: 'RESET' })\n greetedRef.current = true\n fireGreeting()\n return\n }\n const parsed = readConversation(storageKey, Date.now())\n if (!parsed || parsed === 'expired' || parsed === 'corrupt') return\n idRef.current = seedIdCounter(parsed.messages)\n conversation.conversationId = parsed.conversationId ?? undefined\n hydratedRef.current = true\n dispatch({ kind: 'RESTORE', messages: parsed.messages, conversationId: parsed.conversationId })\n }\n window.addEventListener('storage', onStorage)\n return () => window.removeEventListener('storage', onStorage)\n }, [storageKey, conversation, fireGreeting])\n\n const open = useCallback(() => dispatch({ kind: 'OPEN' }), [])\n const close = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'CLOSE' }) }, [clearFallbackTimer])\n const stop = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'STOP' }) }, [clearFallbackTimer])\n const toggle = useCallback(() => { if (stateRef.current.isOpen) close(); else open() }, [close, open])\n const dismissPopup = useCallback(() => dispatch({ kind: 'DISMISS_POPUP' }), [])\n\n const reset = useCallback(() => {\n handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer()\n if (storageKey) clearConversation(storageKey)\n idRef.current = 0\n conversation.conversationId = undefined\n dispatch({ kind: 'RESET' })\n greetedRef.current = true\n fireGreeting()\n }, [storageKey, conversation, clearFallbackTimer, fireGreeting])\n\n const getLiveDashboard = useCallback(() => conversation.getLiveDashboard(), [conversation])\n useLiveDashboardPoll({ messages: state.messages, dispatch, getLiveDashboard })\n\n return { state, open, close, stop, toggle, send, retry, dismissPopup, reset }\n}\n","import type { ChatEvent, ChatInput, ClubFanDashboardCard, ClubFanDashboardPayload, GreetingDashboard, StreamErrorEventData } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { toActionVM, toCardVM, toChipVM, toInsightVM, toMarketOddsVM, toOddsMovementVM, type ActionVM, type CardVM, type ChipVM, type InsightVM, type MarketOddsVM, type OddsMovementVM } from './model'\n\nexport interface UserMessage { role: 'user'; id: string; text: string }\nexport interface AssistantTurn { role: 'assistant'; id: string; text: string; cards: CardVM[]; actions: ActionVM[]; insights: InsightVM[]; marketOdds: MarketOddsVM[]; oddsMovement: OddsMovementVM[]; done: boolean; isGreeting?: boolean; greetingDashboard?: GreetingDashboard; clubFanDashboard?: ClubFanDashboardPayload }\nexport type Message = UserMessage | AssistantTurn\n\nexport interface WidgetState {\n isOpen: boolean\n messages: Message[]\n isStreaming: boolean\n status: string | null\n actionsLoading: boolean\n starters: ChipVM[]\n configuredStarters: ChipVM[]\n error: StreamErrorEventData | WidgetSdkError | null\n lastUserInput: ChatInput | null\n lastDisplayText: string | null\n // Launcher popup text (the auto-greeting response). Cleared on open/dismiss.\n popupText: string | null\n conversationId: string | null\n}\n\nexport type Action =\n | { kind: 'OPEN' }\n | { kind: 'CLOSE' }\n | { kind: 'USER_SENT'; input: ChatInput; userId: string; assistantId: string; displayText?: string }\n | { kind: 'GREETING_SENT'; assistantId: string }\n | { kind: 'EVENT'; event: ChatEvent }\n | { kind: 'STREAM_ERROR'; error: WidgetSdkError }\n | { kind: 'STOP' }\n | { kind: 'DISMISS_POPUP' }\n | { kind: 'LIVE_REFRESH'; messageId: string; cards: ClubFanDashboardCard[]; greeting?: string }\n | { kind: 'LIVE_TRANSITION'; messageId: string; dashboard: ClubFanDashboardPayload }\n | { kind: 'RESET' }\n | { kind: 'RESTORE'; messages: Message[]; conversationId: string | null }\n\nconst POPUP_MAX = 160\n\nexport function initialState(starters: ChipVM[]): WidgetState {\n return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, starters, configuredStarters: starters, error: null, lastUserInput: null, lastDisplayText: null, popupText: null, conversationId: null }\n}\n\nfunction activeTurn(state: WidgetState): AssistantTurn | null {\n const last = state.messages[state.messages.length - 1]\n return last && last.role === 'assistant' && !last.done ? last : null\n}\n\nfunction mapActive(state: WidgetState, fn: (t: AssistantTurn) => AssistantTurn): Message[] {\n const last = state.messages[state.messages.length - 1]\n if (!last || last.role !== 'assistant' || last.done) return state.messages\n return [...state.messages.slice(0, -1), fn(last)]\n}\n\nfunction applyEvent(state: WidgetState, event: ChatEvent): WidgetState {\n switch (event.type) {\n case 'progress':\n return { ...state, status: event.data.message }\n case 'answer':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, text: event.data.text })) }\n case 'entity_card': {\n if (event.data.card.isUsed === false) return state\n const card = toCardVM(event.data.card)\n // Generic cards (coach/referee/stadium/competition — anything not team or\n // player) carry no distinct identity and add no user value; drop them until\n // a purpose-built variant exists.\n if (card.kind === 'generic') return state\n return { ...state, messages: mapActive(state, (t) => ({ ...t, cards: [...t.cards, card] })) }\n }\n case 'action_button':\n return { ...state, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, actions: [...t.actions, toActionVM(event.data.action)] })) }\n case 'betting_insight':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, insights: [...t.insights, toInsightVM(event.data.insight)] })) }\n case 'market_odds':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, marketOdds: [...t.marketOdds, toMarketOddsVM(event.data.card)] })) }\n case 'odds_movement':\n return { ...state, messages: mapActive(state, (t) => ({ ...t, oddsMovement: [...t.oddsMovement, toOddsMovementVM(event.data.card)] })) }\n case 'intent_chip': {\n const chip = toChipVM(event.data.intent)\n return chip ? { ...state, starters: [...state.starters, chip] } : state\n }\n case 'actions_loading':\n return { ...state, actionsLoading: true, status: event.data.message }\n case 'turn_complete': {\n const active = activeTurn(state)\n // A completed greeting turn surfaces its message as the launcher popup (unless already open).\n // The club fan dashboard carries its greeting line in the payload rather than as answer\n // text, so prefer that; fall back to any streamed answer text for other greeting shapes.\n const greetingLine = event.data.clubFanDashboard?.greeting?.trim() || (active?.text.trim() ?? '')\n const popupText = active?.isGreeting && !state.isOpen && greetingLine ? greetingLine.slice(0, POPUP_MAX) : state.popupText\n return {\n ...state, isStreaming: false, status: null, actionsLoading: false, popupText,\n conversationId: event.data.conversationId ?? state.conversationId,\n messages: mapActive(state, (t) => ({\n ...t,\n done: true,\n greetingDashboard: event.data.dashboard ?? undefined,\n clubFanDashboard: event.data.clubFanDashboard ?? undefined,\n })),\n }\n }\n case 'error': {\n // A failed greeting fails silently — it's non-critical background chatter.\n const suppress = activeTurn(state)?.isGreeting === true\n return { ...state, error: suppress ? state.error : event.data, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n }\n }\n // Unknown/unmodelled event type: never return undefined — that would corrupt\n // state and crash the next dispatch. Ignore the event and keep state intact.\n return state\n}\n\nexport function reducer(state: WidgetState, action: Action): WidgetState {\n switch (action.kind) {\n case 'OPEN':\n return { ...state, isOpen: true, popupText: null }\n case 'CLOSE':\n return { ...state, isOpen: false, isStreaming: false, status: null, actionsLoading: false }\n case 'USER_SENT': {\n const user: UserMessage = { role: 'user', id: action.userId, text: action.displayText ?? action.input.message }\n const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false }\n return { ...state, messages: [...state.messages, user, assistant], isStreaming: true, status: null, actionsLoading: false, starters: [], error: null, lastUserInput: action.input, lastDisplayText: action.displayText ?? null }\n }\n case 'GREETING_SENT': {\n // Auto-greeting: no user bubble; the assistant turn is flagged so its completion sets the popup.\n const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false, isGreeting: true }\n return { ...state, messages: [...state.messages, assistant], isStreaming: true, status: null, error: null }\n }\n case 'DISMISS_POPUP':\n return { ...state, popupText: null }\n case 'RESET':\n // Preserve panel open/closed state: \"New conversation\" is an in-panel control, so the\n // panel must stay open with the fresh greeting rather than snapping shut. Cross-tab\n // clear-mirroring likewise keeps each tab's panel as it was.\n return { ...initialState(state.configuredStarters), isOpen: state.isOpen }\n case 'RESTORE':\n return {\n ...state,\n messages: action.messages,\n conversationId: action.conversationId,\n isStreaming: false,\n status: null,\n actionsLoading: false,\n starters: action.messages.length ? [] : state.configuredStarters,\n error: null,\n }\n case 'EVENT':\n return applyEvent(state, action.event)\n case 'STREAM_ERROR':\n return { ...state, error: action.error, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n case 'STOP':\n return { ...state, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n case 'LIVE_REFRESH':\n return {\n ...state,\n messages: state.messages.map((m) =>\n m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n ? { ...m, clubFanDashboard: { ...m.clubFanDashboard, cards: action.cards, greeting: action.greeting ?? m.clubFanDashboard.greeting } }\n : m,\n ),\n }\n case 'LIVE_TRANSITION':\n return {\n ...state,\n messages: state.messages.map((m) =>\n m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n ? { ...m, clubFanDashboard: action.dashboard }\n : m,\n ),\n }\n }\n}\n","import { useEffect, useReducer, useRef } from 'react'\nimport type { ClubFanDashboardPayload, CountdownCard } from '@sensiblestats/widget-sdk'\nimport type { Action, Message } from './reducer'\n\nconst POLL_INTERVAL_MS = 60_000\nconst LEAD_MS = 120_000 // start polling 2 min before kickoff\nconst GIVE_UP_MS = 30 * 60_000 // stop polling 30 min after kickoff if match never went live\n\ntype Anchor =\n | { messageId: string; kind: 'live' }\n | { messageId: string; kind: 'preMatch'; kickoffMs: number }\n\nexport interface UseLiveDashboardPollOptions {\n messages: Message[]\n dispatch: (action: Action) => void\n getLiveDashboard: () => Promise<ClubFanDashboardPayload | null>\n}\n\nfunction extractKickoffMs(dashboard: ClubFanDashboardPayload): number | null {\n const countdown = dashboard.cards.find((c): c is CountdownCard => c.cardType === 'countdown')\n if (countdown) return countdown.data.kickoffUnix * 1_000\n // fall back to any card that exposes kickoffUnix in its data\n for (const c of dashboard.cards) {\n const d = (c as { data?: { kickoffUnix?: number } }).data\n if (typeof d?.kickoffUnix === 'number') return d.kickoffUnix * 1_000\n }\n return null\n}\n\n// Returns the most recent assistant message that can serve as a polling anchor:\n// — a live dashboard (always valid), or\n// — a preMatch dashboard whose kickoff is within [kickoff − LEAD_MS, kickoff + GIVE_UP_MS].\nfunction findAnchor(messages: Message[]): Anchor | null {\n const now = Date.now()\n for (const m of messages.slice().reverse()) {\n if (m.role !== 'assistant' || !m.clubFanDashboard) continue\n const { phase } = m.clubFanDashboard\n if (phase === 'live') return { messageId: m.id, kind: 'live' }\n if (phase === 'preMatch') {\n const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n if (kickoffMs === null) continue\n if (now >= kickoffMs - LEAD_MS && now <= kickoffMs + GIVE_UP_MS) {\n return { messageId: m.id, kind: 'preMatch', kickoffMs }\n }\n }\n }\n return null\n}\n\n// Returns the earliest future wakeup time for a preMatch dashboard that is not yet within the\n// poll window (kickoff − LEAD_MS still in the future). Returns null if none.\nfunction findEarliestWakeupMs(messages: Message[]): number | null {\n const now = Date.now()\n let earliest: number | null = null\n for (const m of messages) {\n if (m.role !== 'assistant' || m.clubFanDashboard?.phase !== 'preMatch') continue\n const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n if (kickoffMs === null) continue\n const wakeAt = kickoffMs - LEAD_MS\n if (wakeAt > now && (earliest === null || wakeAt < earliest)) earliest = wakeAt\n }\n return earliest\n}\n\n// Polls the live club-fan dashboard every 60s for the chosen anchor:\n//\n// — Live anchor: on a live payload → LIVE_REFRESH (cards + greeting). On a post-match payload →\n// LIVE_TRANSITION (full swap to the post-match dashboard) and stop polling. On null → stop.\n// — PreMatch anchor: on a live payload → LIVE_TRANSITION (full payload swap). On null → keep\n// polling (pre-kickoff 204s) but give up if now > kickoff + GIVE_UP_MS.\n//\n// Wake-up: if a preMatch dashboard's window hasn't opened yet (kickoff − 2min still in the\n// future), schedules a setTimeout to trigger a re-render exactly when polling should begin.\nexport function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }: UseLiveDashboardPollOptions): void {\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0)\n const anchor = findAnchor(messages)\n const anchorRef = useRef<Anchor | null>(anchor)\n anchorRef.current = anchor\n const inFlightRef = useRef(false)\n\n // Polling effect — keyed on the anchor identity so it restarts when anchor changes.\n const anchorKey = anchor ? `${anchor.messageId}:${anchor.kind}` : null\n\n useEffect(() => {\n if (!anchorKey || !anchorRef.current) return\n\n const tick = async () => {\n if (inFlightRef.current) return\n inFlightRef.current = true\n try {\n const payload = await getLiveDashboard()\n const current = anchorRef.current\n if (!current) return\n\n if (payload?.phase === 'live') {\n if (current.kind === 'preMatch') {\n dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n window.clearInterval(id)\n } else {\n dispatch({ kind: 'LIVE_REFRESH', messageId: current.messageId, cards: payload.cards, greeting: payload.greeting })\n }\n } else if (payload?.phase === 'postMatch' && current.kind === 'live') {\n // Match ended: the poll now returns the post-match dashboard. Swap the live card for it\n // and stop polling (the anchor is no longer live).\n dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n window.clearInterval(id)\n } else {\n // null (204) or non-live phase with no payload\n if (current.kind === 'live') {\n window.clearInterval(id)\n } else if (Date.now() > current.kickoffMs + GIVE_UP_MS) {\n window.clearInterval(id)\n }\n // preMatch within window: keep polling (these are pre-kickoff 204s)\n }\n } catch {\n // A network error must not crash the widget or stop the loop — swallow and retry\n // on the next tick.\n } finally {\n inFlightRef.current = false\n }\n }\n\n const id = window.setInterval(() => { void tick() }, POLL_INTERVAL_MS)\n return () => window.clearInterval(id)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [anchorKey, dispatch, getLiveDashboard])\n\n // Wake-up effect — schedules a re-render when a preMatch window opens in the future.\n useEffect(() => {\n if (anchorKey !== null) return // already polling, no wake-up needed\n const wakeAt = findEarliestWakeupMs(messages)\n if (wakeAt === null) return\n const delay = wakeAt - Date.now()\n if (delay <= 0) return\n const id = window.setTimeout(forceUpdate, delay)\n return () => window.clearTimeout(id)\n }, [anchorKey, messages, forceUpdate])\n}\n","import type { Message } from './reducer'\n\nexport const TTL_MS = 3_600_000\nexport const MAX_MESSAGES = 30\n\nexport interface StoredPayload {\n conversationId: string | null\n messages: Message[]\n}\n\ninterface StoredConversation {\n v: 1\n updatedAt: number\n conversationId: string | null\n messages: Message[]\n}\n\n// Pure read: returns the payload when a v:1 blob exists and is within TTL; a sentinel the caller\n// clears from an effect (never during render) when stale/unparseable; null when absent.\nexport function readConversation(storageKey: string, now: number): StoredPayload | 'expired' | 'corrupt' | null {\n let raw: string | null\n try {\n raw = window.localStorage.getItem(storageKey)\n } catch {\n return null // SSR / storage blocked\n }\n if (!raw) return null\n let parsed: StoredConversation\n try {\n parsed = JSON.parse(raw) as StoredConversation\n } catch {\n return 'corrupt'\n }\n if (parsed?.v !== 1 || !Array.isArray(parsed.messages) || typeof parsed.updatedAt !== 'number') return 'corrupt'\n if (now - parsed.updatedAt > TTL_MS) return 'expired'\n return { conversationId: parsed.conversationId ?? null, messages: parsed.messages }\n}\n\nexport function writeConversation(storageKey: string, conversationId: string | null, messages: Message[], now: number): void {\n let capped = messages.slice(-MAX_MESSAGES)\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, updatedAt: now, conversationId, messages: capped } satisfies StoredConversation))\n return\n } catch {\n // quota / blocked: drop the oldest half and retry once, then give up (in-memory only)\n if (capped.length <= 1) return\n capped = capped.slice(Math.ceil(capped.length / 2))\n }\n }\n}\n\nexport function clearConversation(storageKey: string): void {\n try {\n window.localStorage.removeItem(storageKey)\n } catch {\n // no-op\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LiveMonitorEvent, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from '@sensiblestats/widget-sdk'\nimport { createPinStore, type PinAddResult, type PinStore } from './pinStore'\nimport { useTabs, type WidgetTab } from './useTabs'\n\n// Re-exported for back-compat; callers that already import MonitorTab continue to compile.\nexport type MonitorTab = WidgetTab\n\nexport interface LiveMonitorController {\n /** Starts TRUE (the server-side pinEnabled flag is the real affordance gate); flips to\n * false permanently for the session on a 404 (null snapshot) from the monitor endpoint. */\n enabled: boolean\n pins: PinRef[]\n snapshot: LiveMonitorSnapshot | null\n activeTab: WidgetTab\n setActiveTab(tab: WidgetTab): void\n togglePin(pin: PinRef): PinAddResult\n isPinned(key: string): boolean\n /** Set by ChatPanel when a reply lands off-tab; cleared on chat tab. */\n chatDot: boolean\n markChatActivity(): void\n /** A goal/red event arrived on a pinned match since Maçlar was last viewed. */\n matchesDot: boolean\n /** A pinned market's price changed since Oranlar was last viewed. */\n oddsDot: boolean\n /** The live count rose from zero while Today was off-screen; suppressed on the active tab. */\n todayDot: boolean\n /** Set by the discovery owner when the live count rises from zero (mirrors markChatActivity). */\n markTodayActivity(): void\n /** Last-viewed price per pin key, for client-side movement badges. */\n lastViewedPrices: Record<string, number>\n /** The currently open accordion market per matchId (null = collapsed). One open at a time per match. */\n openMarket: Record<number, string | null>\n /** Lazy per-market odds cache, keyed `${matchId}:${marketDeveloperName}`. */\n marketOdds: Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n toggleMarket(matchId: number, marketDeveloperName: string): void\n /** Refetches a market's odds WITHOUT touching openMarket -- the tap-to-retry affordance for a\n * market that is already open and errored. toggleMarket would collapse it instead (it flips\n * openMarket unconditionally), which is the wrong move when the row is already showing. */\n retryMarket(matchId: number, marketDeveloperName: string): void\n /** Internal seam: applies a freshly-fetched snapshot (or null on a 404). The poll loop calls\n * this repeatedly; tests call it directly to drive dot/grace logic without a live timer.\n * Not part of the poll cadence/visibility policy itself. */\n _setSnapshot(next: LiveMonitorSnapshot | null): void\n}\n\nexport interface UseLiveMonitorOptions {\n getLiveMonitor: (pins: PinRef[]) => Promise<LiveMonitorSnapshot | null>\n getMarketOdds?: (matchId: number, marketDeveloperName: string) => Promise<MarketOddsBlock | null>\n storageKey: string\n /** false -> true transitions trigger an immediate poll tick (widget open). */\n isOpen: boolean\n /** Whether the Today tab currently has content -- picks the fallback target when a pinned tab\n * disappears, and sends the user to Chat when Today itself empties under them. */\n hasToday?: boolean\n}\n\nconst GOAL_OR_RED: ReadonlySet<LiveMonitorEvent['type']> = new Set(['goal', 'red'])\nconst MIN_POLL_MS = 5_000\nconst DEFAULT_POLL_MS = 60_000\n\nfunction eventIdentity(e: LiveMonitorEvent): string {\n return `${e.type}:${e.side}:${e.minuteLabel}:${e.player ?? ''}`\n}\n\nfunction priceForPin(snapshot: LiveMonitorSnapshot | null, pin: PinRef): number | undefined {\n if (!snapshot) return undefined\n const market = snapshot.markets.find((m) => m.key === pin.key)\n const rows = market?.card?.rows\n if (!rows || rows.length === 0) return undefined\n const row = pin.matchOddsId != null ? rows.find((r) => r.matchOddsId === pin.matchOddsId) : rows[0]\n return row?.price\n}\n\nfunction phaseForPin(snapshot: LiveMonitorSnapshot, pin: PinRef): string | undefined {\n if (pin.kind === 'match') return snapshot.matches.find((m) => m.matchId === pin.matchId)?.phase\n return snapshot.markets.find((mk) => mk.key === pin.key)?.phase\n}\n\nexport function useLiveMonitor(opts: UseLiveMonitorOptions): LiveMonitorController {\n const sessionIdRef = useRef(crypto.randomUUID())\n\n const [pins, setPins] = useState<PinRef[]>([])\n // Lazy initializer: the store fires an initial (no-op-from-the-caller's-view) onChange\n // synchronously during construction, which is a same-component render-phase state update\n // React explicitly supports — it must not run in an effect/later render.\n const [store] = useState<PinStore>(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins))\n\n const [enabled, setEnabled] = useState(true)\n const [snapshot, setSnapshotState] = useState<LiveMonitorSnapshot | null>(null)\n const { activeTab, setActiveTab: setActiveTabState } = useTabs('chat')\n const [chatDot, setChatDot] = useState(false)\n const [matchesDot, setMatchesDot] = useState(false)\n const [oddsDot, setOddsDot] = useState(false)\n const [todayDot, setTodayDot] = useState(false)\n const [lastViewedPrices, setLastViewedPrices] = useState<Record<string, number>>({})\n const [openMarket, setOpenMarket] = useState<Record<number, string | null>>({})\n const [marketOdds, setMarketOdds] = useState<\n Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n >({})\n\n const pinsRef = useRef(pins)\n pinsRef.current = pins\n const activeTabRef = useRef(activeTab)\n activeTabRef.current = activeTab\n const snapshotRef = useRef(snapshot)\n snapshotRef.current = snapshot\n const lastViewedPricesRef = useRef(lastViewedPrices)\n lastViewedPricesRef.current = lastViewedPrices\n const openMarketRef = useRef(openMarket)\n openMarketRef.current = openMarket\n const marketOddsRef = useRef(marketOdds)\n marketOddsRef.current = marketOdds\n const hasToday = opts.hasToday ?? false\n\n const marketKey = (matchId: number, dev: string): string => `${matchId}:${dev}`\n\n const getMarketOddsRef = useRef(opts.getMarketOdds)\n getMarketOddsRef.current = opts.getMarketOdds // latest-fn pattern; fetchMarket reads the ref, deps stay stable\n\n // Stable identity ([] deps, refs only) so callers (applySnapshot, tick) can invoke it without\n // needing to sit in a dependency array.\n const fetchMarket = useCallback((matchId: number, dev: string) => {\n const key = marketKey(matchId, dev)\n const existing = marketOddsRef.current[key]\n if (existing?.loading) return // already in flight -- don't double-fetch\n const loadingEntry = { ...existing, loading: true, error: false }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: loadingEntry }\n setMarketOdds((prev) => ({ ...prev, [key]: loadingEntry }))\n const fn = getMarketOddsRef.current\n if (!fn) return\n void fn(matchId, dev)\n .then((block) => {\n const entry = { block: block ?? undefined, loading: false, error: false }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n })\n .catch(() => {\n const entry = { ...marketOddsRef.current[key], loading: false, error: true }\n marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n })\n }, [])\n\n const toggleMarket = useCallback((matchId: number, dev: string) => {\n const key = marketKey(matchId, dev)\n const wasOpen = openMarketRef.current[matchId] === dev\n const nextValue = wasOpen ? null : dev\n openMarketRef.current = { ...openMarketRef.current, [matchId]: nextValue }\n setOpenMarket((prev) => ({ ...prev, [matchId]: nextValue }))\n // Opening a market that isn't cached yet -- fetch it. A successfully-cached reopen is a\n // no-op fetch, but an entry that previously errored (no block) MUST be retried, not\n // treated as \"cached\" -- that's what drives the tap-to-retry affordance (Task 9).\n const existing = marketOddsRef.current[key]\n if (!wasOpen && !(existing?.loading || existing?.block)) {\n fetchMarket(matchId, dev)\n }\n }, [fetchMarket])\n\n const retryMarket = useCallback((matchId: number, dev: string) => {\n fetchMarket(matchId, dev)\n }, [fetchMarket])\n\n const applySnapshot = useCallback((next: LiveMonitorSnapshot | null) => {\n if (next === null) {\n setEnabled(false)\n return\n }\n const prev = snapshotRef.current\n const currentPins = pinsRef.current\n\n const pinnedMatchIds = new Set(currentPins.filter((p) => p.kind === 'match').map((p) => p.matchId))\n let sawNewGoalOrRed = false\n for (const m of next.matches) {\n if (!pinnedMatchIds.has(m.matchId)) continue\n const prevMatch = prev?.matches.find((pm) => pm.matchId === m.matchId)\n const prevKeys = new Set((prevMatch?.events ?? []).filter((e) => GOAL_OR_RED.has(e.type)).map(eventIdentity))\n if (m.events.some((e) => GOAL_OR_RED.has(e.type) && !prevKeys.has(eventIdentity(e)))) {\n sawNewGoalOrRed = true\n break\n }\n }\n if (sawNewGoalOrRed && activeTabRef.current !== 'following') setMatchesDot(true)\n\n // Default-open the first available market per pinned match, once -- an explicit close\n // (openMarket[matchId] === null) must stick, so the guard is \"no entry at all\" not \"falsy\".\n for (const m of next.matches) {\n if (!pinnedMatchIds.has(m.matchId)) continue\n const first = m.availableMarkets?.[0]\n if (!first) continue\n if (m.matchId in openMarketRef.current) continue\n const dev = first.marketDeveloperName\n openMarketRef.current = { ...openMarketRef.current, [m.matchId]: dev }\n setOpenMarket((prevOpen) => ({ ...prevOpen, [m.matchId]: dev }))\n fetchMarket(m.matchId, dev)\n }\n\n const marketPins = currentPins.filter((p) => p.kind !== 'match')\n if (activeTabRef.current === 'odds') {\n setLastViewedPrices((prevMap) => {\n let changed = false\n const out = { ...prevMap }\n for (const pin of marketPins) {\n const price = priceForPin(next, pin)\n if (price !== undefined && out[pin.key] !== price) {\n out[pin.key] = price\n changed = true\n }\n }\n return changed ? out : prevMap\n })\n } else {\n let sawPriceMove = false\n for (const pin of marketPins) {\n const price = priceForPin(next, pin)\n const last = lastViewedPricesRef.current[pin.key]\n if (price !== undefined && last !== undefined && price !== last) {\n sawPriceMove = true\n break\n }\n }\n if (sawPriceMove) setOddsDot(true)\n }\n\n const graceKeys = currentPins\n .filter((p) => {\n const phase = phaseForPin(next, p)\n return phase === 'fullTime' || phase === 'postponed' || phase === 'gone'\n })\n .map((p) => p.key)\n if (graceKeys.length > 0) store.markGrace(graceKeys, sessionIdRef.current, Date.now())\n\n // Sync the ref immediately (state updates are async) -- the poll loop's schedule step reads\n // this synchronously in the SAME tick, right after this call returns, to size the next\n // delay off the snapshot that was just received rather than the one from the prior tick.\n snapshotRef.current = next\n setSnapshotState(next)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store])\n\n // Poll loop. ALL mutable inputs live in refs so `tick` is created ONCE ([applySnapshot] deps,\n // and applySnapshot itself is stable across renders): an inline getLiveMonitor lambda handed\n // in fresh from StatsWidget on every render must not re-arm the visibility listener or\n // recreate the timer chain.\n const inFlightRef = useRef(false)\n const timerRef = useRef<number | undefined>(undefined)\n const disabledRef = useRef(false)\n const mountedRef = useRef(false)\n const getLiveMonitorRef = useRef(opts.getLiveMonitor)\n getLiveMonitorRef.current = opts.getLiveMonitor // latest-fn pattern; tick reads the ref, deps stay stable\n\n const tick = useCallback(async () => {\n if (inFlightRef.current || disabledRef.current || pinsRef.current.length === 0) return\n inFlightRef.current = true\n try {\n const snap = await getLiveMonitorRef.current(pinsRef.current)\n if (!mountedRef.current) return\n if (snap === null) {\n // 404 -> live monitor disabled for this operator: stop for the session, hide affordances.\n disabledRef.current = true\n applySnapshot(null)\n return\n }\n applySnapshot(snap)\n // Live-refresh the open accordion market per match. Bypasses the \"already cached\" skip\n // (that guard only lives in toggleMarket) -- fetchMarket itself only skips a fetch already\n // in flight, so this always requests fresh odds for a live match's open market.\n for (const m of snap.matches) {\n if (m.phase !== 'live') continue\n const dev = openMarketRef.current[m.matchId]\n if (dev) fetchMarket(m.matchId, dev)\n }\n } catch {\n // transient failure: keep the previous snapshot, retry on the next scheduled tick\n } finally {\n inFlightRef.current = false\n scheduleRef.current()\n }\n }, [applySnapshot, fetchMarket]) // reads refs only -- both callbacks are themselves stable\n\n const scheduleRef = useRef<() => void>(() => {})\n scheduleRef.current = () => {\n window.clearTimeout(timerRef.current)\n if (!mountedRef.current || disabledRef.current || pinsRef.current.length === 0 || document.visibilityState === 'hidden') return\n const hinted = (snapshotRef.current?.nextPollSeconds ?? DEFAULT_POLL_MS / 1000) * 1000\n timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted))\n }\n\n // Set before the effects below that tick; cleared on unmount so a tick already awaiting the\n // network drops its snapshot (no pin-grace write) and arms no timer after the hook is gone.\n useEffect(() => {\n mountedRef.current = true\n return () => { mountedRef.current = false }\n }, [])\n\n // Immediate tick: pin list transitions 0 -> 1+ (togglePin add, or pins already present at\n // mount -- the ref starts at 0 so the first run treats \"already have pins\" the same way).\n // Dropping to zero pins clears any pending timer so a stray tick never fires with no pins.\n // It deliberately does NOT move the active tab: PinToggle is reachable from a chat message\n // card, so unpinning mid-conversation must leave the reader where they are. The per-kind\n // effect below owns the fallback, and its `activeTab` guard covers zero pins too.\n const prevPinsLengthRef = useRef(0)\n useEffect(() => {\n const wasEmpty = prevPinsLengthRef.current === 0\n prevPinsLengthRef.current = pins.length\n if (pins.length === 0) {\n window.clearTimeout(timerRef.current)\n return\n }\n if (wasEmpty) void tick()\n }, [pins.length, tick])\n\n // A tab left active after the content backing it disappears strands the user on an empty panel\n // with no tab in the strip to escape from. Three ways in: the last match pin drops while an odds\n // pin remains (pins.length alone can't see it, the OTHER kind keeps it above zero), the mirror\n // case for odds, and Today emptying under the user at the local-date rollover.\n useEffect(() => {\n const matchPins = pins.filter((p) => p.kind === 'match').length\n const marketPins = pins.length - matchPins\n if (activeTab === 'following' && matchPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n if (activeTab === 'odds' && marketPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n if (activeTab === 'today' && !hasToday) setActiveTabState('chat')\n }, [pins, activeTab, hasToday])\n\n // Immediate tick: widget open (false -> true transition).\n const prevIsOpenRef = useRef(false)\n useEffect(() => {\n const wasClosed = !prevIsOpenRef.current\n prevIsOpenRef.current = opts.isOpen\n if (wasClosed && opts.isOpen) void tick()\n }, [opts.isOpen, tick])\n\n // Visibility: hidden clears the pending timer; visible ticks immediately. Mounted exactly\n // once -- `tick` never changes identity, so this effect never re-fires across re-renders.\n useEffect(() => {\n const onVisibility = () => {\n if (document.visibilityState === 'hidden') window.clearTimeout(timerRef.current)\n else void tick()\n }\n document.addEventListener('visibilitychange', onVisibility)\n return () => {\n document.removeEventListener('visibilitychange', onVisibility)\n window.clearTimeout(timerRef.current)\n }\n }, [tick])\n\n const setActiveTab = useCallback((tab: WidgetTab) => {\n setActiveTabState(tab)\n if (tab === 'chat') setChatDot(false)\n if (tab === 'today') setTodayDot(false)\n if (tab === 'following') {\n setMatchesDot(false)\n void tick()\n }\n if (tab === 'odds') {\n setOddsDot(false)\n setLastViewedPrices((prevMap) => {\n const out = { ...prevMap }\n for (const pin of pinsRef.current.filter((p) => p.kind !== 'match')) {\n const price = priceForPin(snapshotRef.current, pin)\n if (price !== undefined) out[pin.key] = price\n }\n return out\n })\n void tick()\n }\n }, [tick])\n\n // The ref is refreshed here, not only on the next render: a price history tap adds a pin and\n // opens the Odds tab in one handler, and that tab's immediate fetch must already carry the pin.\n const togglePin = useCallback((pin: PinRef): PinAddResult => {\n const result = store.toggle(pin)\n pinsRef.current = store.pins\n return result\n }, [store])\n const isPinned = useCallback((key: string): boolean => pinsRef.current.some((p) => p.key === key), [])\n const markChatActivity = useCallback(() => setChatDot(true), [])\n // Same shape as markChatActivity: the count that drives it lives in useMatchDiscovery, which\n // cannot be read from here without making the two hooks observe each other's own render.\n const markTodayActivity = useCallback(() => {\n if (activeTabRef.current !== 'today') setTodayDot(true)\n }, [])\n\n return {\n enabled,\n pins,\n snapshot,\n activeTab,\n setActiveTab,\n togglePin,\n isPinned,\n chatDot,\n markChatActivity,\n matchesDot,\n oddsDot,\n todayDot,\n markTodayActivity,\n lastViewedPrices,\n openMarket,\n marketOdds,\n toggleMarket,\n retryMarket,\n _setSnapshot: applySnapshot,\n }\n}\n","import { useState } from 'react'\n\nexport type WidgetTab = 'chat' | 'today' | 'following' | 'odds' | 'games' | 'leaderboard'\n\nexport function useTabs(initial: WidgetTab = 'chat'): { activeTab: WidgetTab; setActiveTab: (t: WidgetTab) => void } {\n const [activeTab, setActiveTab] = useState<WidgetTab>(initial)\n return { activeTab, setActiveTab }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { MatchState, SchedulePayload, ScheduleGroup, StatesPayload } from '@sensiblestats/widget-sdk'\nimport { readSchedule, readScheduleIgnoringTtl, writeSchedule } from './scheduleCache'\nimport { dueMatchIds } from './dueSet'\n\nconst POLL_MS = 60_000\n// Local re-render so the minute advances between network polls. Costs one render; the alternative\n// is a clock that only moves once a minute.\nconst ROLLOVER_CHECK_MS = 60_000\nconst STALE_AFTER_FAILURES = 2\n\nexport interface MatchDiscoveryController {\n groups: ScheduleGroup[]\n states: Record<number, MatchState>\n /** Advanced locally between polls so the minute ticks. */\n liveCount: number\n stale: boolean\n expanded: Record<number, boolean>\n toggleGroup(competitionId: number): void\n /** Test seam: run one states poll synchronously. Not part of the cadence policy. */\n _tick(): Promise<void>\n}\n\nexport interface UseMatchDiscoveryOptions {\n getSchedule: (localDate: string, utcOffsetMinutes: number) => Promise<SchedulePayload | null>\n getStates: (matchIds: number[]) => Promise<StatesPayload | null>\n operatorId: string\n isOpen: boolean\n pinnedMatchIds: number[]\n}\n\nfunction localDateOf(now: Date): string {\n const y = now.getFullYear()\n const m = `${now.getMonth() + 1}`.padStart(2, '0')\n const d = `${now.getDate()}`.padStart(2, '0')\n return `${y}-${m}-${d}`\n}\n\nexport function useMatchDiscovery(opts: UseMatchDiscoveryOptions): MatchDiscoveryController {\n const [groups, setGroups] = useState<ScheduleGroup[]>([])\n const [states, setStates] = useState<Record<number, MatchState>>({})\n const [failures, setFailures] = useState(0)\n const [expanded, setExpanded] = useState<Record<number, boolean>>({})\n const [touched, setTouched] = useState<Record<number, boolean>>({})\n\n const groupsRef = useRef(groups)\n groupsRef.current = groups\n const statesRef = useRef(states)\n statesRef.current = states\n // latest-fn pattern (mirrors useLiveMonitor's getLiveMonitorRef): tick reads the ref, so an\n // inline getStates lambda handed in fresh on every render cannot tear down and recreate the\n // poll interval.\n const getStatesRef = useRef(opts.getStates)\n getStatesRef.current = opts.getStates\n\n const pinnedKey = opts.pinnedMatchIds.join(',')\n\n // A widget left mounted across midnight has to move to the new day, or it holds yesterday's\n // fixtures forever with an empty due set and no polling. Cheap enough to check on a coarse\n // interval; the state only ever changes value once a day, so it re-renders once a day.\n const [localDate, setLocalDate] = useState(() => localDateOf(new Date()))\n useEffect(() => {\n const id = setInterval(() => {\n const next = localDateOf(new Date())\n setLocalDate((prev) => (prev === next ? prev : next))\n }, ROLLOVER_CHECK_MS)\n return () => clearInterval(id)\n }, [])\n\n // `states` is deliberately NOT cleared here: a 23:00 fixture still playing at 00:30 belongs to\n // neither day's window, and dropping its state would blank a score that is still true.\n useEffect(() => {\n let cancelled = false\n // getTimezoneOffset is minutes WEST of UTC, so Istanbul reports -180 for UTC+3.\n const utcOffsetMinutes = -new Date().getTimezoneOffset()\n\n const cached = readSchedule(opts.operatorId, localDate, Date.now())\n if (cached) {\n if (!cancelled) setGroups(cached.groups)\n return () => { cancelled = true }\n }\n\n void (async () => {\n try {\n const payload = await opts.getSchedule(localDate, utcOffsetMinutes)\n if (cancelled || !payload) return\n writeSchedule(opts.operatorId, localDate, payload, Date.now())\n setGroups(payload.groups)\n } catch {\n // Fixtures do not move, so an expired day beats an empty tab.\n const fallback = readScheduleIgnoringTtl(opts.operatorId, localDate)\n if (!cancelled && fallback) setGroups(fallback.groups)\n }\n })()\n\n return () => { cancelled = true }\n }, [opts.operatorId, localDate])\n\n useEffect(() => {\n setExpanded((prev) => {\n const next: Record<number, boolean> = {}\n for (const group of groups) {\n const hasPin = group.matches.some((m) => opts.pinnedMatchIds.includes(m.matchId))\n const seeded = group.expandedByDefault || hasPin\n next[group.competitionId] = touched[group.competitionId]\n ? (prev[group.competitionId] ?? seeded)\n : seeded\n }\n return next\n })\n }, [groups, pinnedKey, touched])\n\n const tick = useCallback(async () => {\n const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now())\n if (ids.length === 0) return\n try {\n const payload = await getStatesRef.current(ids)\n if (!payload) return\n setStates((prev) => {\n // Retained rather than replaced: a finished match keeps its final score after it leaves\n // the due set.\n const next = { ...prev }\n for (const state of payload.states) next[state.matchId] = state\n return next\n })\n setFailures(0)\n } catch {\n setFailures((n) => n + 1)\n }\n }, [])\n\n // `groups` is in the deps (beyond `tick`, which is now stable) so a schedule fetch that\n // resolves after the mount-time tick above gets an immediate follow-up poll, rather than\n // stranding the newly-loaded due set until the next 60s tick.\n useEffect(() => {\n if (!opts.isOpen) return\n void tick()\n const id = setInterval(() => { void tick() }, POLL_MS)\n return () => clearInterval(id)\n }, [opts.isOpen, tick, groups])\n\n const stale = failures >= STALE_AFTER_FAILURES\n\n const liveCount = useMemo(\n () => (stale\n ? 0\n // A match whose own reading has gone stale stops counting: a stalled window must not hold\n // the badge up at 1 for the rest of the day.\n : Object.values(states).filter((s) => s.phase === 'live').length),\n [states, stale],\n )\n\n const toggleGroup = useCallback((competitionId: number) => {\n setTouched((prev) => ({ ...prev, [competitionId]: true }))\n setExpanded((prev) => ({ ...prev, [competitionId]: !prev[competitionId] }))\n }, [])\n\n return { groups, states, liveCount, stale, expanded, toggleGroup, _tick: tick }\n}\n","import type { SchedulePayload } from '@sensiblestats/widget-sdk'\n\nconst PREFIX = 'ss-w-schedule:'\nconst SCHEMA_VERSION = 1\nconst TTL_MS = 6 * 3600_000\n\ninterface Entry {\n v: number\n at: number\n payload: SchedulePayload\n}\n\nexport function scheduleCacheKey(operatorId: string, localDate: string): string {\n return `${PREFIX}${operatorId}:${localDate}`\n}\n\nfunction read(operatorId: string, localDate: string): Entry | null {\n try {\n const raw = localStorage.getItem(scheduleCacheKey(operatorId, localDate))\n if (!raw) return null\n const entry = JSON.parse(raw) as Entry\n // A wire change bumps SCHEMA_VERSION; without this an old entry deserializes into the new\n // shape and renders fields that are no longer there.\n if (entry.v !== SCHEMA_VERSION || !entry.payload) return null\n return entry\n } catch {\n return null\n }\n}\n\nexport function readSchedule(operatorId: string, localDate: string, nowMs: number): SchedulePayload | null {\n const entry = read(operatorId, localDate)\n if (!entry) return null\n return nowMs - entry.at > TTL_MS ? null : entry.payload\n}\n\n/** The /schedule-failed path: fixtures do not move, so a stale day beats an empty tab. */\nexport function readScheduleIgnoringTtl(operatorId: string, localDate: string): SchedulePayload | null {\n return read(operatorId, localDate)?.payload ?? null\n}\n\n// The cache is skeleton-only by construction, not by convention: a payload is rebuilt\n// field-by-field here so an excess live-state field on the wire can never be persisted.\nfunction skeletonOnly(payload: SchedulePayload): SchedulePayload {\n return {\n localDate: payload.localDate,\n groups: payload.groups.map((g) => ({\n competitionId: g.competitionId,\n competitionName: g.competitionName,\n competitionImagePath: g.competitionImagePath ?? null,\n rank: g.rank,\n expandedByDefault: g.expandedByDefault,\n matches: g.matches.map((m) => ({\n matchId: m.matchId,\n homeTeamName: m.homeTeamName,\n awayTeamName: m.awayTeamName,\n homeTeamImagePath: m.homeTeamImagePath ?? null,\n awayTeamImagePath: m.awayTeamImagePath ?? null,\n kickoffUnix: m.kickoffUnix,\n })),\n })),\n }\n}\n\nexport function writeSchedule(\n operatorId: string, localDate: string, payload: SchedulePayload, nowMs: number,\n): void {\n const keep = scheduleCacheKey(operatorId, localDate)\n const mine = `${PREFIX}${operatorId}:`\n try {\n // Scoped to this operator: two operators can share a browser, and pruning the whole prefix\n // would evict the other one's day on every write.\n for (let i = localStorage.length - 1; i >= 0; i--) {\n const key = localStorage.key(i)\n if (key && key.startsWith(mine) && key !== keep) localStorage.removeItem(key)\n }\n const entry: Entry = { v: SCHEMA_VERSION, at: nowMs, payload: skeletonOnly(payload) }\n localStorage.setItem(keep, JSON.stringify(entry))\n } catch {\n // A full or blocked localStorage must not break the tab; the schedule refetches next mount.\n }\n}\n","import type { ScheduleGroup, MatchState } from '@sensiblestats/widget-sdk'\n\n// Phases that never change again, so one answer is the last answer we need. Everything else --\n// preMatch (the clock passed but the feed has not flipped yet) and live -- is still moving.\nconst TERMINAL_PHASES: ReadonlySet<string> = new Set(['fullTime', 'postponed'])\n\n/**\n * Which of today's matches to ask about. Anything past its kickoff clock that has not yet given us\n * a terminal answer, and nothing else.\n *\n * This replaced a fixed 3.5-hour window after kickoff. The window bounded the REQUEST, but on a\n * cold load it also silently bounded what we could ever KNOW: open the widget at 15:13 and a match\n * that kicked off at 11:00 was already outside it, so it was never asked about, had no state, and\n * rendered as a fixture that had not started -- kickoff time, no score -- four hours after it\n * finished 0-1. Matches inside the window showed FT correctly, which is why only the older half of\n * the day looked wrong.\n *\n * Terminating on the answer rather than on the clock is also strictly cheaper in the steady state:\n * every finished match drops out permanently after one reply, so a late-evening poll carries only\n * what is actually still playing. The schedule is one day, and the endpoint caps at 200 ids.\n */\nexport function dueMatchIds(\n groups: ScheduleGroup[], states: Record<number, MatchState>, nowMs: number,\n): number[] {\n const due = new Set<number>()\n\n for (const group of groups) {\n for (const match of group.matches) {\n if (nowMs - match.kickoffUnix * 1000 < 0) continue\n const phase = states[match.matchId]?.phase\n if (phase !== undefined && TERMINAL_PHASES.has(phase)) continue\n due.add(match.matchId)\n }\n }\n\n return [...due]\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { GameListPayload, GameSummary } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nconst GAMES_POLL_MS = 60_000\nconst DEFAULT_TZ = 'Europe/London'\n\nfunction computeGameDay(timezone: string): string {\n // en-CA uses YYYY-MM-DD format\n return new Intl.DateTimeFormat('en-CA', { timeZone: timezone }).format(new Date())\n}\n\nexport interface UseGamesResult {\n enabled: boolean\n games: GameSummary[]\n loading: boolean\n refresh: () => void\n}\n\nexport function useGames(\n conversation: { getGames: (gameDay?: string) => Promise<GameListPayload | null> } | null | undefined,\n { activeTab, operatorTimezone }: { activeTab: WidgetTab; operatorTimezone?: string },\n): UseGamesResult {\n // Games/Leaderboard tabs are hidden until we KNOW this operator has games. Every operator shares\n // one games backend, so a non-games operator does not 404 — it returns 200 with an empty list.\n // Gating on games.length (not on the 404 sentinel) is what keeps the tabs off those operators;\n // defaulting to false avoids flashing the tabs on every operator during the first fetch.\n const [enabled, setEnabled] = useState(false)\n const [games, setGames] = useState<GameSummary[]>([])\n const [loading, setLoading] = useState(false)\n const [refreshCount, setRefreshCount] = useState(0)\n\n const inFlightRef = useRef(false)\n // Set only when the feature is entirely off for this operator (backend 404). Stops all polling —\n // distinct from \"enabled\", which merely reflects whether today's list has any games.\n const hardOffRef = useRef(false)\n const conversationRef = useRef(conversation)\n conversationRef.current = conversation\n const tzRef = useRef(operatorTimezone ?? DEFAULT_TZ)\n tzRef.current = operatorTimezone ?? DEFAULT_TZ\n\n // The conversation is often null on first render and set once the widget finishes initialising.\n // It is intentionally NOT read through the ref in the effect deps — the effect must re-run when\n // it becomes available, or the one-shot fetch never fires and the tabs never appear. (Defaulting\n // `enabled` to true used to paper over this; gating on the games list means we must actually\n // fetch.)\n const ready = conversation != null\n\n useEffect(() => {\n if (hardOffRef.current) return\n let active = true\n\n const doFetch = async (): Promise<void> => {\n const conv = conversationRef.current\n if (!conv || inFlightRef.current || !active) return\n inFlightRef.current = true\n setLoading(true)\n try {\n const gameDay = computeGameDay(tzRef.current)\n const result = await conv.getGames(gameDay)\n if (!active) return\n if (result === null) {\n // 404: games feature is not enabled for this operator at all — hide and stop polling.\n hardOffRef.current = true\n setEnabled(false)\n setGames([])\n } else {\n // 200: show the tabs only when this operator actually has games today.\n setGames(result.games)\n setEnabled(result.games.length > 0)\n }\n } catch {\n // swallow; retry next tick\n } finally {\n inFlightRef.current = false\n if (active) setLoading(false)\n }\n }\n\n // Always fetch once on mount or refresh\n void doFetch()\n\n // Poll while the games tab is active\n let intervalId: number | undefined\n if (activeTab === 'games') {\n intervalId = window.setInterval(() => {\n if (hardOffRef.current) {\n window.clearInterval(intervalId)\n return\n }\n void doFetch()\n }, GAMES_POLL_MS)\n }\n\n return () => {\n active = false\n // Release the in-flight guard so a remount (React StrictMode double-invokes effects, and any\n // dependency change re-runs this one) can fetch again. Without this, the first run's request\n // is still in flight when the second run checks the guard, the second run bails, and the\n // first run's result is dropped because `active` is now false — so `enabled` is never set.\n inFlightRef.current = false\n if (intervalId !== undefined) window.clearInterval(intervalId)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, refreshCount, ready])\n\n const refresh = useCallback(() => {\n setRefreshCount((c) => c + 1)\n }, [])\n\n return { enabled, games, loading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseLeaderboardResult {\n data: LeaderboardPayload | null\n loading: boolean\n refresh: () => void\n}\n\nexport function useLeaderboard(\n conversation: { getLeaderboard: () => Promise<LeaderboardPayload | null> } | null | undefined,\n { activeTab }: { activeTab: WidgetTab },\n): UseLeaderboardResult {\n const [data, setData] = useState<LeaderboardPayload | null>(null)\n const [loading, setLoading] = useState(false)\n const [refreshCount, setRefreshCount] = useState(0)\n\n const inFlightRef = useRef(false)\n const conversationRef = useRef(conversation)\n conversationRef.current = conversation\n\n useEffect(() => {\n // The Games hub's stat row (rank, streak) reads the same payload.\n if (activeTab !== 'leaderboard' && activeTab !== 'games') return\n let active = true\n\n const doFetch = async (): Promise<void> => {\n const conv = conversationRef.current\n if (!conv || inFlightRef.current) return\n inFlightRef.current = true\n setLoading(true)\n try {\n const result = await conv.getLeaderboard()\n if (active) setData(result)\n } catch {\n // swallow; keep previous data\n } finally {\n inFlightRef.current = false\n if (active) setLoading(false)\n }\n }\n\n void doFetch()\n return () => {\n active = false\n // Release the guard so a refresh fired while this fetch is still in flight (a quick tap into a\n // game and back) runs its own fetch instead of bailing — the same fix useGames carries.\n inFlightRef.current = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, refreshCount])\n\n const refresh = useCallback(() => {\n setRefreshCount((c) => c + 1)\n }, [])\n\n return { data, loading, refresh }\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\n// Returns the dismiss handler to hand the launcher. Opening is detected from state rather than\n// by wrapping open(): OPEN clears popupText in the same render, so the text seen while closed is\n// remembered to tell a popup open from a plain launcher open.\nexport function usePopupTelemetry(\n log: EventLogger | null,\n isOpen: boolean,\n popupText: string | null,\n dismissPopup: () => void,\n): () => void {\n const shownRef = useRef(new Set<string>())\n const closedTextRef = useRef<string | null>(null)\n\n useEffect(() => {\n if (isOpen) {\n if (closedTextRef.current) log?.log({ name: 'popup_opened' })\n closedTextRef.current = null\n return\n }\n closedTextRef.current = popupText\n if (popupText && !shownRef.current.has(popupText)) {\n shownRef.current.add(popupText)\n log?.log({ name: 'popup_shown' })\n }\n }, [log, isOpen, popupText])\n\n return useCallback(() => {\n log?.log({ name: 'popup_dismissed' })\n dismissPopup()\n }, [log, dismissPopup])\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { BrandMark } from './BrandMark'\nimport { GreetingBubble } from './GreetingBubble'\n\n// Only rendered while the panel is closed. The dynamic greeting popup takes\n// precedence over the static greeting and is dismissable; both open the panel.\n//\n// introAllowed/onIntroStart drive the one-shot attention animation (the FAB\n// nudges, then the greeting types in). The latch below fires it once, the first\n// time a bubble appears; onIntroStart lets the parent record that so it never\n// replays when the FAB remounts on a later panel close. Refreshing the page\n// remounts the whole widget and re-arms it.\nexport function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = 'Dismiss', introAllowed = false, onIntroStart }: { label: string; greeting?: string; popupText?: string | null; logoUrl?: string; onOpen: () => void; onDismissPopup: () => void; dismissLabel?: string; introAllowed?: boolean; onIntroStart?: () => void }): JSX.Element {\n const bubble = popupText ?? greeting\n const [intro, setIntro] = useState(false)\n const armedRef = useRef(introAllowed)\n useEffect(() => {\n if (armedRef.current && bubble) {\n armedRef.current = false\n setIntro(true)\n onIntroStart?.()\n }\n }, [bubble, onIntroStart])\n return (\n <div className={intro ? 'ss-w-fab-wrap ss-w-intro' : 'ss-w-fab-wrap'}>\n {bubble ? <GreetingBubble text={bubble} onOpen={onOpen} onDismiss={popupText ? onDismissPopup : undefined} dismissLabel={dismissLabel} /> : null}\n <button type=\"button\" className=\"ss-w-fab\" aria-label={label} onClick={onOpen}>\n <BrandMark logoUrl={logoUrl} className=\"ss-w-fab-mark\" />\n </button>\n </div>\n )\n}\n","export function GreetingBubble({ text, onOpen, onDismiss, dismissLabel = 'Dismiss' }: { text: string; onOpen?: () => void; onDismiss?: () => void; dismissLabel?: string }): JSX.Element {\n return (\n <div className=\"ss-w-greeting\" role=\"note\">\n <button type=\"button\" className=\"ss-w-greeting-body\" onClick={onOpen}>\n <span className=\"ss-w-greeting-dots\" aria-hidden=\"true\"><i></i><i></i><i></i></span>\n <span className=\"ss-w-greeting-text\">{text}</span>\n </button>\n {onDismiss ? (\n <button type=\"button\" className=\"ss-w-greeting-x\" aria-label={dismissLabel} onClick={onDismiss}>×</button>\n ) : null}\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { MatchLinkContext } from '../matchLinkContext'\nimport { SlipStateContext } from '../slipStateContext'\nimport type { HostEvents } from '../useHostEvents'\n\n/** Hands what useHostEvents returns to the components that read it. */\nexport function HostEventsProvider({ value, children }: { value: HostEvents; children: ReactNode }): JSX.Element {\n return (\n <SlipStateContext.Provider value={value.slipState}>\n <MatchLinkContext.Provider value={value.matchLink}>{children}</MatchLinkContext.Provider>\n </SlipStateContext.Provider>\n )\n}\n","// AUTO-GENERATED by scripts/gen-css.mjs from widget.css. Do not edit.\nexport const WIDGET_CSS = \".ss-w-root { all: revert; }\\n.ss-w-root, .ss-w-root * { box-sizing: border-box; margin: 0; padding: 0; }\\n.ss-w-root {\\n --ss-w-accent: #17936a;\\n --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580; --ss-w-line: #e4e8ec;\\n --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\\n --ss-w-pos: #1aa563; --ss-w-neg: #e0524b;\\n --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n --ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;\\n font-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, Helvetica, Arial, sans-serif;\\n font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);\\n}\\n@media (prefers-color-scheme: dark) {\\n .ss-w-root[data-ss-w-theme=\\\"auto\\\"] {\\n --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n --ss-w-pos: #37c891; --ss-w-neg: #f0655d;\\n --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n }\\n}\\n.ss-w-root[data-ss-w-theme=\\\"dark\\\"] {\\n --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n --ss-w-pos: #37c891; --ss-w-neg: #f0655d;\\n --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n}\\n.ss-w-root[data-ss-w-theme=\\\"light\\\"] {\\n --ss-w-accent: #17936a; --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;\\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580;\\n --ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\\n --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n}\\n\\n/* ── games design tokens (u393) ── derived from operator tokens so every tenant theme works.\\n Targets (Hull #F5A800/#0B0B0B/#F5F5F5): ground #0D0C0A, surface #17150F, warm #1C1810,\\n raised #211E17, line #26221A, line-warm #3A2F18, accent-tint #3A2C10, strong-line #4A4131. */\\n.ss-w-root {\\n --ss-g-ground: color-mix(in srgb, var(--ss-w-accent) 2%, var(--ss-w-panel));\\n --ss-g-surface: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n --ss-g-warm: color-mix(in srgb, var(--ss-w-accent) 6%, color-mix(in srgb, var(--ss-w-ink) 2%, var(--ss-w-panel)));\\n --ss-g-raised: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 6%, var(--ss-w-panel)));\\n --ss-g-line: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 8%, var(--ss-w-panel)));\\n --ss-g-line-warm: color-mix(in srgb, var(--ss-w-accent) 18%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n --ss-g-accent-tint: color-mix(in srgb, var(--ss-w-accent) 20%, var(--ss-w-panel));\\n --ss-g-strong-line: color-mix(in srgb, var(--ss-w-accent) 8%, color-mix(in srgb, var(--ss-w-ink) 18%, var(--ss-w-panel)));\\n --ss-g-ink: color-mix(in srgb, var(--ss-w-accent) 4%, var(--ss-w-ink));\\n --ss-g-ink-2: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 72%, var(--ss-w-panel)));\\n --ss-g-muted: color-mix(in srgb, var(--ss-w-accent) 5%, color-mix(in srgb, var(--ss-w-ink) 60%, var(--ss-w-panel)));\\n --ss-g-faint: color-mix(in srgb, var(--ss-w-ink) 45%, var(--ss-w-panel));\\n --ss-g-on-accent: #1a1206;\\n --ss-g-on-correct: #fff;\\n --ss-g-correct: color-mix(in srgb, var(--ss-w-correct) 55%, #000);\\n --ss-g-wrong: color-mix(in srgb, var(--ss-w-neg) 55%, #000);\\n /* Brighter wrong for thin marks (borders, icons, segments) that must read on dark surfaces; --ss-g-wrong stays for fills. */\\n --ss-g-wrong-mark: var(--ss-w-neg);\\n --ss-g-success: color-mix(in srgb, var(--ss-w-pos) 80%, var(--ss-w-ink));\\n --ss-g-success-tint: color-mix(in srgb, var(--ss-w-pos) 18%, var(--ss-w-panel));\\n --ss-g-close: #e3b341;\\n --ss-g-flame: #ff6a1a;\\n /* Pitch colours are fixed in both themes: the pitch is always a dark green. */\\n --ss-g-pitch: #123524;\\n --ss-g-pitch-line: #3e7055;\\n --ss-g-pitch-chip: #0d0c0a;\\n --ss-g-pitch-ink: #f4efe6;\\n --ss-g-pitch-mark: #c9d6cd;\\n --ss-g-font-display: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;\\n --ss-g-font-body: 'Barlow', system-ui, -apple-system, 'Segoe UI', sans-serif;\\n}\\n\\n/* ── match link (u443) ── a card's team names as a button that opens the operator's match page.\\n The button keeps the wrapped element's own class for its layout. Every one of those classes is\\n declared further down this file, so on equal specificity it wins over this reset: keep this\\n block above them. */\\n.ss-w-matchlink { appearance: none; position: relative; width: 100%; padding-right: 16px; background: none; border: 0; border-radius: 6px; font: inherit; color: inherit; text-align: inherit; cursor: pointer; }\\n.ss-w-matchlink::after { content: ''; position: absolute; right: 3px; top: 50%; width: 7px; height: 7px; margin-top: -4px; border-top: 1.5px solid var(--ss-w-faint); border-right: 1.5px solid var(--ss-w-faint); transform: rotate(45deg); }\\n.ss-w-matchlink:hover::after { border-color: var(--ss-w-accent); }\\n.ss-w-matchlink:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n/* The pinned match card centres its score in the card, so it pads both edges alike. */\\n.ss-w-mon-main.ss-w-matchlink { padding-left: 16px; }\\n\\n/* ── games ui kit (u393) ── */\\n.ss-g-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\\n.ss-g-head { display: flex; align-items: center; gap: 6px; padding: 8px 16px 8px 6px; font-family: var(--ss-g-font-body); }\\n.ss-g-back { width: 44px; height: 44px; flex: none; display: grid; place-items: center; border: 0; border-radius: 12px; background: transparent; color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-back:hover { background: var(--ss-g-surface); }\\n.ss-g-head-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.05; }\\n.ss-g-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; color: var(--ss-g-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-head-right { flex: none; }\\n.ss-g-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600; white-space: nowrap; }\\n.ss-g-chip--neutral { background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); }\\n.ss-g-chip--neutral .ss-g-num, .ss-g-chip--neutral svg { color: var(--ss-w-accent); }\\n.ss-g-chip--accent { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-weight: 700; }\\n.ss-g-chip--success { background: var(--ss-g-success-tint); color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-chip--badge { padding: 3px 8px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-chip--lock { padding: 3px 8px; border-radius: 6px; font-size: 12px; font-weight: 500; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-statstack { display: flex; flex-direction: column; align-items: flex-end; line-height: 1; }\\n.ss-g-statstack-v { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; color: var(--ss-w-accent); }\\n.ss-g-statstack-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-progress { display: flex; align-items: center; gap: 12px; padding: 0 16px 8px; }\\n.ss-g-progress-main { flex: 1; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-progress-labels { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--ss-g-ink); }\\n.ss-g-progress-rl { color: var(--ss-g-muted); }\\n.ss-g-segs { display: grid; gap: 4px; }\\n.ss-g-seg { height: 5px; border-radius: 3px; background: var(--ss-g-line); }\\n.ss-g-seg[data-state=\\\"done\\\"] { background: var(--ss-g-strong-line); }\\n.ss-g-seg[data-state=\\\"current\\\"] { background: var(--ss-w-accent); }\\n.ss-g-seg[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); }\\n.ss-g-seg[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); }\\n.ss-g-btn { min-height: 48px; padding: 0 16px; border-radius: 12px; font-family: var(--ss-g-font-body); font-size: 14px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }\\n.ss-g-btn:disabled { opacity: .45; cursor: default; }\\n.ss-g-btn--block { width: 100%; min-height: 54px; border-radius: 14px; font-size: 16px; font-weight: 800; }\\n.ss-g-btn--primary { border: 0; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-btn--outline { border: 1.5px solid var(--ss-g-strong-line); background: transparent; color: var(--ss-g-ink); }\\n.ss-g-btn--accent-outline { border: 1.5px solid var(--ss-w-accent); background: transparent; color: var(--ss-w-accent); }\\n.ss-g-btn--surface { border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font-weight: 600; font-size: 13px; }\\n.ss-g-search { display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-search-label { font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-search-box { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1.5px solid var(--ss-g-line); color: var(--ss-g-muted); }\\n.ss-g-search-box:focus-within { border-color: var(--ss-w-accent); }\\n.ss-g-search-box input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: var(--ss-g-ink); font: 500 15px var(--ss-g-font-body); }\\n.ss-g-footer { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--ss-g-line); display: flex; flex-direction: column; gap: 10px; background: var(--ss-g-ground); }\\n.ss-g-sil { position: relative; flex: none; display: inline-flex; align-items: flex-end; justify-content: center; overflow: hidden; border-radius: 50%; background: var(--ss-g-raised); color: var(--ss-g-strong-line); }\\n.ss-g-sil--selected { background: var(--ss-g-accent-tint); color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-g-raised)); }\\n.ss-g-sil--mystery { background: var(--ss-g-accent-tint); color: var(--ss-g-ground); }\\n.ss-g-sil-q { position: absolute; top: 22%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 1.1em; color: var(--ss-w-accent); }\\n.ss-g-crest { flex: none; object-fit: contain; }\\n.ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-pitch-svg { position: absolute; inset: 0; width: 100%; height: 100%; stroke: var(--ss-g-pitch-line); stroke-width: .6; }\\n/* ── games screen scaffold (u393) — shared by every game screen ── */\\n.ss-w-gscreen > .ss-g-screen { flex: 1; min-height: 0; }\\n.ss-g-screen { display: flex; flex-direction: column; min-height: 0; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-body); }\\n.ss-g-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 14px; padding: 4px 16px 16px; }\\n.ss-g-body .ss-g-progress { padding: 0; }\\n.ss-g-loading { align-items: center; justify-content: center; color: var(--ss-g-muted); font-size: 13px; }\\n.ss-g-opts { display: flex; flex-direction: column; gap: 4px; max-height: 232px; overflow-y: auto; }\\n.ss-g-opt { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 6px 8px; border: 0; border-radius: 12px; background: var(--ss-g-surface); color: var(--ss-g-ink); font: 600 15px var(--ss-g-font-body); text-align: left; cursor: pointer; }\\n.ss-g-opt:hover, .ss-g-opt:focus-visible { background: var(--ss-g-raised); outline: none; }\\n.ss-g-opt-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 13px; font-weight: 700; }\\n.ss-g-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-result { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 16px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-result[data-tone=\\\"win\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-result[data-tone=\\\"lose\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-result-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; line-height: 1; }\\n.ss-g-result-score { font-size: 13px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-result-num { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 40px; color: var(--ss-w-accent); margin-right: 4px; }\\n.ss-g-result-detail { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-result .ss-g-btn { margin-top: 6px; }\\n\\n/* launcher */\\n.ss-w-fab-wrap { position: fixed; bottom: var(--ss-w-offset-y); z-index: 2147483000; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-fab-wrap { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-fab-wrap { left: var(--ss-w-offset-x); align-items: flex-start; }\\n.ss-w-fab { width: 56px; height: 56px; border: none; border-radius: 50%; background: var(--ss-w-nav); color: #fff; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 20px rgba(0,0,0,.28); }\\n.ss-w-fab-mark { width: 30px; height: 30px; display: block; object-fit: contain; }\\n.ss-w-greeting { max-width: 240px; display: flex; align-items: flex-start; background: var(--ss-w-panel); color: var(--ss-w-ink); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-greeting-body { position: relative; flex: 1; min-width: 0; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 9px 4px 9px 12px; }\\n.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }\\n.ss-w-greeting-text { display: block; }\\n/* Typing indicator: overlays the text area so bubble height stays put; hidden at\\n rest, revealed only during the one-shot intro (see prefers-reduced-motion block). */\\n.ss-w-greeting-dots { position: absolute; top: 0; bottom: 0; left: 12px; display: flex; align-items: center; gap: 4px; opacity: 0; pointer-events: none; }\\n.ss-w-greeting-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-faint); display: block; }\\n/* One-shot launcher attention intro: FAB nudges, then the greeting types in.\\n Gated behind no-preference so reduce-motion users get the greeting shown\\n statically (text visible, no nudge, no typing). ChatFab adds .ss-w-intro once\\n per page load; every animation runs a single time and settles at rest. */\\n@media (prefers-reduced-motion: no-preference) {\\n .ss-w-intro .ss-w-fab { animation: ss-w-nudge .8s ease both; }\\n .ss-w-intro .ss-w-greeting { animation: ss-w-greet-in .45s cubic-bezier(.2,.8,.3,1.15) .8s both; }\\n .ss-w-intro .ss-w-greeting-text { animation: ss-w-greet-textin .4s ease 1.65s both; }\\n .ss-w-intro .ss-w-greeting-dots { animation: ss-w-greet-dots .95s ease .85s both; }\\n .ss-w-intro .ss-w-greeting-dots i { animation: ss-w-greet-dotbounce .5s ease .85s 2; }\\n .ss-w-intro .ss-w-greeting-dots i:nth-child(2) { animation-delay: 1s; }\\n .ss-w-intro .ss-w-greeting-dots i:nth-child(3) { animation-delay: 1.15s; }\\n}\\n@keyframes ss-w-nudge {\\n 0%, 100% { transform: none; }\\n 22% { transform: translateY(-9px) rotate(-9deg); }\\n 44% { transform: translateY(0) rotate(7deg); }\\n 64% { transform: translateY(-4px) rotate(-4deg); }\\n 82% { transform: rotate(2deg); }\\n}\\n@keyframes ss-w-greet-in {\\n from { opacity: 0; transform: translateY(8px) scale(.92); }\\n to { opacity: 1; transform: none; }\\n}\\n@keyframes ss-w-greet-textin { from { opacity: 0; } to { opacity: 1; } }\\n@keyframes ss-w-greet-dots { 0% { opacity: 0; } 14% { opacity: 1; } 78% { opacity: 1; } 100% { opacity: 0; } }\\n@keyframes ss-w-greet-dotbounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }\\n\\n/* panel */\\n.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(460px, calc(100vw - 40px)); height: min(640px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { left: var(--ss-w-offset-x); }\\n@media (max-width: 639px) {\\n /* Fill via inset with no explicit height (like the site's working panel) so the\\n input stays visible when the mobile keyboard/URL-bar shrinks the viewport. The\\n position-specific selectors override the right/left offsets set above. */\\n .ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel,\\n .ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { inset: 0; width: auto; height: auto; border: none; border-radius: 0; }\\n}\\n.ss-w-header { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-header-mark { width: 18px; height: 18px; display: block; object-fit: contain; }\\n.ss-w-header-title { font-weight: 660; flex: 1; }\\n.ss-w-close { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu-wrap { position: relative; display: grid; place-items: center; }\\n.ss-w-kebab { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 5; min-width: 184px; padding: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.18); }\\n.ss-w-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; background: none; border: none; border-radius: 8px; color: var(--ss-w-ink); font: inherit; font-size: 13px; text-align: left; cursor: pointer; }\\n.ss-w-menu-item:hover, .ss-w-menu-item:focus-visible { background: var(--ss-w-bubble); }\\n.ss-w-menu-item svg { color: var(--ss-w-faint); font-size: 15px; flex: none; }\\n\\n/* messages */\\n/* .ss-w-mon-list (Matches/Odds tab scrollers) shares .ss-w-list's box/scroll rules by design --\\n same visual rhythm as the chat message list -- but gets its own class so it isn't the same DOM\\n landmark as the chat list when both exist in the panel at once (Task 16 fix round, M4). */\\n/* Children of this scrolling column flex container must NOT shrink. The default flex-shrink:1\\n compresses every child to fit the panel instead of letting the container scroll, and\\n .ss-w-grp's own overflow:hidden then clips the compressed content away entirely — 27\\n competition groups rendered as blank bars on a phone. Applies to the pinned cards too. */\\n.ss-w-mon-list > * { flex: none; }\\n.ss-w-list, .ss-w-mon-list { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }\\n/* Transient bottom spacer: reserves a viewport of room below a new turn so its\\n top can be scrolled into view while the reply is still streaming in. Height is\\n set imperatively and flex must not shrink it away. */\\n.ss-w-turn-spacer { flex: none; }\\n.ss-w-msg { display: flex; }\\n.ss-w-user { justify-content: flex-end; }\\n.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }\\n.ss-w-bot { flex-direction: column; gap: 8px; }\\n.ss-w-status { font-size: 11px; color: var(--ss-w-faint); font-style: italic; }\\n.ss-w-error { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c0392b; }\\n.ss-w-retry { background: none; border: 1px solid currentColor; border-radius: 10px; padding: 2px 8px; cursor: pointer; color: inherit; }\\n\\n/* markdown */\\n.ss-w-md { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-md :where(p, ul, ol, table, pre, blockquote, h1, h2, h3, h4) { margin: 0; }\\n.ss-w-md > *:first-child { margin-top: 0; }\\n.ss-w-md > *:last-child { margin-bottom: 0; }\\n.ss-w-md-ul { list-style: disc outside; padding-left: 18px; }\\n.ss-w-md-ol { list-style: decimal outside; padding-left: 18px; }\\n.ss-w-md-ul li::marker, .ss-w-md-ol li::marker { color: var(--ss-w-accent); }\\n.ss-w-md-link { color: var(--ss-w-accent); text-decoration: underline; }\\n.ss-w-table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }\\n.ss-w-md-table { border-collapse: collapse; width: max-content; min-width: 100%; font-variant-numeric: tabular-nums; }\\n.ss-w-md-table td, .ss-w-md-table th { border: 1px solid var(--ss-w-line); padding: 4px 8px; text-align: left; white-space: nowrap; }\\n.ss-w-md-table th { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); font-weight: 700; }\\n.ss-w-md-table tbody tr:nth-child(even) { background: var(--ss-w-bubble); }\\n.ss-w-md-code { background: var(--ss-w-bubble); border-radius: 5px; padding: 1px 5px; font-family: ui-monospace, monospace; }\\n\\n/* entity cards */\\n.ss-w-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Entity card: identity header row over a horizontal stat strip */\\n.ss-w-ecard { display: flex; flex-direction: column; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; text-align: left; }\\n\\n.ss-w-ecard-idtext { display: flex; flex-direction: column; gap: 1px; min-width: 0; max-width: 100%; }\\n.ss-w-thumb { width: 54px; height: 54px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 16px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; box-shadow: 0 1px 3px rgba(0,0,0,.14); }\\n.ss-w-thumb.ss-w-team { border-radius: 12px; }\\n.ss-w-ecard[data-kind=\\\"player\\\"] .ss-w-thumb { background-color: var(--ss-w-accent); }\\n.ss-w-nm { font-weight: 680; line-height: 1.15; overflow-wrap: anywhere; }\\n.ss-w-sub { font-size: 11px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* bare card (no stat scopes): simple avatar + name row */\\n.ss-w-ecard-bare { display: flex; align-items: center; }\\n.ss-w-ecard-bare .ss-w-ecard-hd { padding: 10px 12px; }\\n\\n.ss-w-ecard-hd { display: flex; align-items: center; gap: 11px; padding: 11px 13px; }\\n.ss-w-ecard-hd .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }\\n.ss-w-ecard-hd .ss-w-thumb.ss-w-team { border-radius: 10px; }\\n.ss-w-ecard-meta { display: inline-flex; align-items: center; gap: 7px; flex: none; align-self: flex-start; margin-left: auto; }\\n.ss-w-ecard-meta .ss-w-ecard-season { margin: 0; }\\n\\n/* scope tabs: reuse the underline pattern, relocated above the strip */\\n.ss-w-ecard-scopes { display: flex; align-items: stretch; gap: 2px; padding: 0 11px; border-top: 1px solid var(--ss-w-line); flex-wrap: wrap; }\\n.ss-w-ecard-scope { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 7px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }\\n.ss-w-ecard-scope[aria-selected=\\\"true\\\"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-ecard-scope .ss-w-ecard-crest { width: 14px; height: 14px; }\\n.ss-w-ecard-scopes + .ss-w-ecard-strip { border-top: none; }\\n\\n.ss-w-ecard-crest { width: 15px; height: 15px; flex: none; display: block; border-radius: 4px; background-size: cover; background-position: center; }\\n.ss-w-ecard-season { flex: none; margin-left: auto; align-self: center; margin-bottom: 5px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n/* stat strip: 1px gap over a line-colored ground paints hairlines between cells, wrap-safe */\\n.ss-w-ecard-strip { display: grid; gap: 1px; background: var(--ss-w-line); border-top: 1px solid var(--ss-w-line); }\\n.ss-w-ecard-cell { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 4px; padding: 10px 4px 11px; background: var(--ss-w-panel); }\\n.ss-w-ecard-cval { height: 20px; display: flex; align-items: center; font-size: 17px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }\\n.ss-w-ecard-cval .ss-w-form { width: 42px; }\\n.ss-w-ecard-clabel { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); font-weight: 600; font-variant-numeric: tabular-nums; }\\n\\n.ss-w-form { justify-self: end; display: flex; height: 6px; width: 48px; border-radius: 4px; overflow: hidden; gap: 2px; }\\n.ss-w-form span { display: block; border-radius: 2px; }\\n.ss-w-form-w { background: var(--ss-w-pos); }\\n.ss-w-form-d { background: var(--ss-w-faint); }\\n.ss-w-form-l { background: var(--ss-w-neg); }\\n\\n.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }\\n.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }\\n.ss-w-cards-more:disabled { opacity: .5; cursor: default; }\\n\\n/* betting insights */\\n.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }\\n.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; }\\n\\n/* header, competition-hero fallback: comp on the left, live badge + kickoff + pin on the right,\\n all on one line (used when there is no fixture, and by MarketOddsCardList) */\\n.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); }\\n.ss-w-bi-header-left { display: inline-flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); }\\n.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n/* two-tier header: a quiet meta line (competition + kickoff + match pin) stacked above the\\n fixture, so long club names get the whole width to themselves and stop truncating (u350) */\\n.ss-w-bi-head { display: flex; flex-direction: column; gap: 6px; padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-bi-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-bi-meta-left { display: inline-flex; align-items: center; gap: 5px; min-width: 0; flex: 1; }\\n.ss-w-bi-meta-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n.ss-w-bi-fixture-line { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-kick { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); white-space: nowrap; flex: none; }\\n.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; }\\n.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }\\n.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; }\\n\\n/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */\\n.ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 10px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n\\n/* fixture atoms -- crest-flanked team pair; shared by the insight fixture line and MarketOddsCardList */\\n.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }\\n.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* shared crest-flanked team row (MarketOddsCardList); matches .ss-w-bi-fixture-line's hero weight\\n so the fixture reads the same on both card types (u350) */\\n.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n\\n/* row 2, two-tier: the market label owns a full-width line above the pick row (selection grows\\n left, odds + slip + pin sit right), so neither the market name nor the fixture clips (u350) */\\n.ss-w-bi-action { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.25; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-bi-pick-row { display: flex; align-items: center; gap: 9px; }\\n.ss-w-bi-sel { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; line-height: 1.2; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-odds { flex: none; margin-left: auto; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }\\n.ss-w-bi-odds b { font-size: 20px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }\\n.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }\\n.ss-w-bi-pick-row .ss-w-slip { flex: none; }\\n\\n/* row 3: bar-chart glyph + reasoning prose, in a subtle strip */\\n.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }\\n.ss-w-bi-chart { flex: none; width: 13px; height: 12px; margin-top: 2px; opacity: .55;\\n background:\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) left / 3px 55% no-repeat,\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) center / 3px 100% no-repeat,\\n linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) right / 3px 75% no-repeat;\\n background-position: left bottom, center bottom, right bottom;\\n}\\n.ss-w-bi-text { flex: 1; min-width: 0; font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* market odds card */\\n.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-mocard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n/* Embedded inside the market accordion, which already provides the card frame + accent rail --\\n drop the inner frame so odds rows aren't double-bordered. */\\n.ss-w-mocard--bare { border: none; border-radius: 0; padding: 0; background: none; }\\n.ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }\\n.ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-market-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-tag { flex: none; font-size: 10.5px; font-weight: 700; line-height: 1.4; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, transparent); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }\\n.ss-w-mo-more { 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; }\\n.ss-w-mo-more:hover { text-decoration: underline; }\\n.ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }\\n.ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }\\n.ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }\\n/* The card's stat, in the Live tab accordion's insight style. No row below it is marked (R17). */\\n.ss-w-mo-stat { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }\\n.ss-w-mo-row:last-child { border-bottom: none; }\\n.ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); flex: 1; min-width: 0; }\\n.ss-w-mo-price { margin-left: auto; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--ss-w-accent); }\\n/* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a\\n shortening price as a discount, which inverts what it actually means for the bettor. */\\n.ss-w-move { display: inline-flex; align-items: baseline; gap: 4px; color: var(--ss-w-faint); }\\n.ss-w-move-prev { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 12px; text-decoration: line-through; }\\n.ss-w-move-arrow { font-size: 9px; line-height: 1; }\\n/* margin-left:auto is row layout, not badge styling -- it belongs to the market-odds row, which is\\n a flex row, and must NOT follow the badge into the insight card's odds column. */\\n.ss-w-mo-row .ss-w-move { margin-left: auto; }\\n.ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }\\n.ss-w-mo-row .ss-w-slip { margin: 0; flex: none; }\\n.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }\\n\\n/* Compact price list (D16): three or more cards of one turn, one row per fixture. Team names wrap\\n to a second line and are never cut; the time sits above the match pin, with no column of its own. */\\n.ss-w-mol { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-mol-head, .ss-w-mol-row { display: grid; grid-template-columns: minmax(0, 1fr) 126px 30px; align-items: center; gap: 4px; }\\n.ss-w-mol-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow-wrap: anywhere; }\\n.ss-w-mol-cols, .ss-w-mol-cells { display: grid; gap: 4px; }\\n.ss-w-mol-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); text-align: center; overflow-wrap: break-word; min-width: 0; }\\n.ss-w-mol-comp { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding-top: 4px; }\\n.ss-w-mol-row { padding: 6px 0; border-bottom: 1px dashed var(--ss-w-line); min-height: 48px; box-sizing: border-box; }\\n.ss-w-mol-row:focus { outline: none; }\\n.ss-w-mol-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; border-radius: 6px; }\\n.ss-w-mol-tick { font-family: inherit; font-size: 9.5px; font-weight: 700; line-height: 1.1; }\\n.ss-w-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }\\n.ss-w-mol-group .ss-w-mol-row:last-child { border-bottom: none; }\\n.ss-w-mol-fx { display: flex; flex-direction: column; gap: 3px; min-width: 0; background: none; border: none; padding: 0; text-align: left; font: inherit; color: inherit; }\\n.ss-w-mol-team { display: flex; align-items: center; gap: 5px; min-width: 0; }\\n.ss-w-mol-team > * { flex: none; }\\n.ss-w-mol-team > .ss-w-mol-nm { flex: 1 1 auto; }\\n.ss-w-mol-nm { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); overflow-wrap: break-word; hyphens: manual; line-height: 1.2; min-width: 0; }\\n.ss-w-mol-mkt { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-mol-cells { align-items: start; }\\n.ss-w-mol-cell { display: flex; flex-direction: column; align-items: stretch; gap: 2px; min-width: 0; }\\n.ss-w-mol-cell > .ss-w-mol-price { flex: none; }\\n.ss-w-mol-cell .ss-w-move { justify-content: center; gap: 2px; }\\n.ss-w-mol-cell .ss-w-move-prev { font-family: inherit; font-variant-numeric: tabular-nums; font-size: 10px; }\\n/* A 39 px cell fits four characters at 13 px: five step down to 11.5 px and six to 10.5 px. */\\n.ss-w-mol-cell--wide .ss-w-mol-price, .ss-w-mol-cell--wide .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 11.5px; }\\n.ss-w-mol-cell--wider .ss-w-mol-price, .ss-w-mol-cell--wider .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 10.5px; }\\n.ss-w-mol-cell .ss-w-slip { margin: 0; flex: none; min-width: 0; }\\n.ss-w-mol-price, .ss-w-slip-btn--price { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 5px 0; border-radius: 8px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); font-family: inherit; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-slip-btn.ss-w-slip-btn--price { width: 100%; cursor: pointer; background: var(--ss-w-panel); color: var(--ss-w-accent); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 5px 0; font-size: 13px; font-weight: 700; box-shadow: none; }\\n.ss-w-slip-btn--price:hover:not(:disabled) { border-color: var(--ss-w-accent); }\\n.ss-w-slip-btn--price[data-settled] { color: var(--ss-w-faint); }\\n.ss-w-mol-lab { font-family: inherit; font-size: 9.5px; font-weight: 600; color: var(--ss-w-faint); line-height: 1.1; text-align: center; overflow-wrap: anywhere; }\\n.ss-w-mol-side { display: flex; flex-direction: column; align-items: center; gap: 4px; }\\n.ss-w-mol-when { font-size: 9.5px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; text-align: center; line-height: 1.15; }\\n.ss-w-mol-side--live .ss-w-mol-when { color: var(--ss-w-neg); }\\n\\n/* odds movement card */\\n.ss-w-omcards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-omcard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-om-head { display: flex; align-items: center; gap: 8px; }\\n.ss-w-om-market { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-om-tag { margin-left: auto; flex: none; font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 2px 7px; }\\n.ss-w-om-fixture { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-om-comp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-om-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }\\n.ss-w-om-chart { display: block; width: 100%; height: auto; }\\n/* Single neutral accent in BOTH directions, deliberately. Colouring a shortening price green\\n frames it as a discount, which inverts what it means for the bettor -- the same reason\\n .ss-w-move keeps both directions on --ss-w-faint. */\\n.ss-w-om-line { stroke: var(--ss-w-accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }\\n.ss-w-om-dot { fill: var(--ss-w-accent); }\\n.ss-w-om-grid { stroke: var(--ss-w-line); stroke-width: 1; }\\n.ss-w-om-ylab, .ss-w-om-xlab { fill: var(--ss-w-faint); font-size: 9px; font-family: ui-monospace, monospace; }\\n.ss-w-om-empty { font-size: 11.5px; color: var(--ss-w-faint); padding: 6px 0; }\\n.ss-w-om-foot { display: flex; align-items: center; gap: 14px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-om-foot b { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; color: var(--ss-w-ink); }\\n.ss-w-om-excl { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-om-susp { font-size: 11px; font-weight: 600; color: #c0392b; }\\n.ss-w-om-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* action buttons */\\n.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\\n/* text-align is explicit because a <button> defaults to center, and a follow-up question long\\n enough to wrap then sets its second line ragged on both sides. */\\n.ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; text-align: left; }\\n.ss-w-abtn:disabled { opacity: .5; cursor: default; }\\n.ss-w-abtn-shimmer { width: 140px; height: 30px; border-radius: 16px; background: linear-gradient(90deg, var(--ss-w-bubble), var(--ss-w-line), var(--ss-w-bubble)); background-size: 200% 100%; animation: ss-w-shimmer 1.2s infinite; }\\n@keyframes ss-w-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }\\n\\n/* intent chips */\\n.ss-w-chips { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-chip { font-size: 11.5px; font-weight: 550; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 5px 11px; cursor: pointer; }\\n\\n/* input */\\n.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }\\n.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }\\n/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it\\n on touch devices only, so the desktop 13px design is unchanged. */\\n@media (pointer: coarse) {\\n .ss-w-textarea { font-size: 16px; }\\n}\\n.ss-w-send { width: 36px; height: 36px; flex: none; border: none; border-radius: 50%; background: var(--ss-w-accent); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 16px; }\\n.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }\\n\\n/* add to slip */\\n.ss-w-slip { position: relative; display: flex; }\\n.ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; white-space: nowrap; }\\n.ss-w-slip-btn:disabled { opacity: .6; cursor: default; background: var(--ss-w-bubble); color: var(--ss-w-faint); border-color: var(--ss-w-line); }\\n/* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward\\n into the card -- inheriting the wrapper's width squeezes the text to one character per line.\\n Every toast site (slip buttons, pin toggles) sits at the right edge of its row. */\\n.ss-w-toast { position: absolute; top: calc(100% + 6px); right: 0; z-index: 1; width: max-content; max-width: 210px; font-size: 11px; font-weight: 560; border-radius: 10px; padding: 5px 10px; overflow-wrap: anywhere; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-toast-success { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }\\n.ss-w-toast-error { color: #c0392b; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }\\n\\n/* pin affordance */\\n.ss-w-pin-wrap { position: relative; display: inline-flex; flex: none; }\\n.ss-w-pin { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-pin svg { width: 12px; height: 12px; }\\n.ss-w-pin:hover { color: var(--ss-w-ink); border-color: var(--ss-w-faint); }\\n.ss-w-pin[data-on] { background: var(--ss-w-accent); border-color: var(--ss-w-accent); color: #fff; }\\n.ss-w-pin[data-on]:hover { background: var(--ss-w-accent); color: #fff; }\\n.ss-w-hist { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-hist svg { width: 12px; height: 12px; }\\n.ss-w-hist:hover { color: var(--ss-w-accent); border-color: var(--ss-w-accent); }\\n\\n@media (prefers-reduced-motion: reduce) {\\n .ss-w-abtn-shimmer { animation: none; }\\n}\\n\\n/* greeting dashboard */\\n.ss-w-dash { display: flex; flex-direction: column; gap: 12px; padding: 4px 0; }\\n.ss-w-dash-head { display: flex; flex-direction: column; }\\n.ss-w-dash-title { font-size: 18px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }\\n.ss-w-dash-subtitle { font-size: 13px; color: var(--ss-w-faint); margin-top: 4px; }\\n.ss-w-dash-foot { font-size: 11px; color: var(--ss-w-faint); margin-top: 2px; }\\n\\n.ss-w-dash-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-dash-tile--half { grid-column: span 1; }\\n.ss-w-dash-tile--full { grid-column: 1 / -1; }\\n\\n.ss-w-dash-tile {\\n display: flex; align-items: center; gap: 10px;\\n padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n background: var(--ss-w-panel); text-align: left; cursor: pointer; width: 100%;\\n color: inherit; font: inherit;\\n min-width: 0; /* the panel is min(400px, 100vw - 40px): without this,\\n a long Turkish title blows the column out */\\n}\\n.ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 28px; height: 28px; font-size: 22px; }\\n.ss-w-dash-emoji { line-height: 1; }\\n.ss-w-dash-tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }\\n.ss-w-dash-tile-title { min-width: 0; font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }\\n.ss-w-dash-tile-subtitle { min-width: 0; font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-tile-chevron { flex: none; margin-left: auto; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n\\n/* Badge + crests share their own row, below the title -- NOT the icon/chevron row. A\\n nowrap badge (~70px) sitting beside icon+chevron in a ~180px half-span tile left the\\n title column at ~22px wide, wrapping every title character-by-character. Here the row\\n gets the body's full width, so a badge this size is comfortably inside it. */\\n.ss-w-dash-tile-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }\\n.ss-w-dash-tile-badge { flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n.ss-w-dash-tile-crests { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-tile-crest {\\n width: 18px; height: 18px; border-radius: 50%;\\n background-size: cover; background-position: center; background-color: var(--ss-w-bubble);\\n margin-left: -6px; border: 2px solid var(--ss-w-panel); /* overlapping stack, capped at 3 in DashboardTile */\\n}\\n.ss-w-dash-tile-crest:first-child { margin-left: 0; }\\n\\n/* Market: default 2-column grid, tiles get the same accent rail as the other card\\n families (.ss-w-binsight, .ss-w-mocard, .ss-w-omcard) so a market tile reads as\\n part of that visual language rather than a plain unstyled button. */\\n.ss-w-dash--market .ss-w-dash-tile { border-left: 3px solid var(--ss-w-accent); }\\n\\n/* Goal: one column of pill rows. */\\n.ss-w-dash--goal .ss-w-dash-grid { grid-template-columns: 1fr; }\\n.ss-w-dash--goal .ss-w-dash-tile { border-radius: 999px; padding: 10px 14px; }\\n\\n/* Discovery: tinted bento cards. Stacked (icon over text) so a two- or three-word title gets\\n the tile's full width instead of the ~100px left of a horizontal icon+chevron -- that narrow\\n column was wrapping \\\"Most interesting angles\\\" onto three lines. The chevron is dropped (the\\n whole card is the tap target) and the badge + crest row is forced onto one line. */\\n.ss-w-dash--discovery .ss-w-dash-tile { flex-direction: column; align-items: stretch; gap: 8px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-icon { align-self: flex-start; width: 32px; height: 32px; font-size: 26px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-chevron { display: none; }\\n/* The full-span trends tile has the whole panel width, so its icon and title sit on one row\\n (horizontal, centre-aligned) rather than stacking like the narrow half tiles. */\\n.ss-w-dash--discovery .ss-w-dash-tile--full { flex-direction: row; align-items: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile--full .ss-w-dash-tile-icon { align-self: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile-meta { flex-wrap: nowrap; }\\n.ss-w-dash--discovery .ss-w-dash-tile-crest { width: 22px; height: 22px; }\\n/* Tints mix a hue into the live panel rather than hardcoding a light pastel, so a dark\\n operator surface (e.g. --ss-w-panel set from a navy `surface` brand color) yields a\\n readable tinted-dark card instead of near-white ink on a fixed light pastel. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n/* A hero tile would take the first tint position; count only regular tiles where `of S` parses. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n\\n/* Hero: the personalized lead tile. Declared after the layout rules and at three-class\\n specificity so it keeps one look in every layout -- no market rail, no goal pill, no\\n discovery tint or stacking. Colours derive from accent/panel/ink so an operator surface\\n and dark mode both work without their own rules. */\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero {\\n display: flex; flex-direction: column; align-items: stretch; gap: 10px;\\n padding: 12px 14px 14px; border-radius: 16px;\\n border: 1px solid color-mix(in srgb, var(--ss-w-accent) 38%, var(--ss-w-line));\\n background:\\n radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--ss-w-accent) 18%, transparent) 0%, transparent 60%),\\n var(--ss-w-panel);\\n box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--ss-w-accent) 80%, transparent);\\n}\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:hover { border-color: var(--ss-w-accent); }\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-dash-hero-top { display: flex; align-items: center; gap: 8px; min-height: 20px; }\\n.ss-w-dash-hero-badge {\\n font-size: 10.5px; font-weight: 750; letter-spacing: .06em; text-transform: uppercase;\\n color: var(--ss-w-panel); background: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); border-radius: 999px; padding: 3px 10px;\\n white-space: nowrap;\\n}\\n.ss-w-dash-hero-chevron { flex: none; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n.ss-w-dash-hero-badge { margin-right: auto; }\\n.ss-w-dash-hero-chevron:only-child { margin-left: auto; }\\n.ss-w-dash-hero-main { display: flex; align-items: center; gap: 12px; min-width: 0; }\\n.ss-w-dash-hero-visual { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-hero-crest {\\n width: 40px; height: 40px; border-radius: 50%;\\n background-color: color-mix(in srgb, var(--ss-w-ink) 4%, var(--ss-w-panel));\\n background-size: 72%; background-position: center; background-repeat: no-repeat;\\n box-shadow: 0 0 0 2px var(--ss-w-panel), 0 0 0 3px color-mix(in srgb, var(--ss-w-ink) 10%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-crest + .ss-w-dash-hero-crest { margin-left: -8px; }\\n.ss-w-dash-hero-icon {\\n display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; font-size: 22px;\\n background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\\n.ss-w-dash-hero-title { font-size: 15.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-subtitle { font-size: 12px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-price {\\n flex: none; margin-left: auto;\\n font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 750; line-height: 1;\\n color: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); padding: 5px 9px; border-radius: 8px;\\n background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel));\\n border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-panel));\\n}\\n\\n/* club fan pre-match dashboard */\\n.ss-w-fandash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }\\n.ss-w-fandash-greeting { font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ss-w-ink); }\\n.ss-w-fandash-greeting--lead { font-weight: 400; }\\n.ss-w-fandash-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Shared card chrome -- a plain <div> for [data] cards, a <button> for [prefill] cards. Both\\n share the same box so the two families read as one system, not two ad hoc layouts. */\\n.ss-w-fandash-card {\\n display: flex; flex-direction: column; gap: 8px;\\n padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n background: var(--ss-w-panel); text-align: left;\\n color: inherit; font: inherit; width: 100%; min-width: 0;\\n}\\n.ss-w-fandash-card--tap { cursor: pointer; border-left: 3px solid var(--ss-w-accent); }\\n.ss-w-fandash-card--tap:hover { background: var(--ss-w-bubble); }\\n.ss-w-fandash-card-cta { align-self: flex-start; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); }\\n\\n/* Shared alignment primitives: a small letterspaced section eyebrow, and a 3-column value/label\\n split reused by the fixture head-to-head (and any future stat-row card). */\\n.ss-w-fandash-eyebrow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }\\n.ss-w-fandash-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-split-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; min-width: 0; }\\n.ss-w-fandash-split-value { font-size: 20px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); line-height: 1; }\\n.ss-w-fandash-split-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* fixture card */\\n.ss-w-fandash-fixture-teams { display: flex; align-items: center; gap: 10px; }\\n.ss-w-fandash-fixture-team { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }\\n.ss-w-fandash-fixture-team--away { justify-content: flex-end; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest { width: 30px; height: 30px; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest-mono { font-size: 12px; }\\n.ss-w-fandash-fixture-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-fixture-team--away .ss-w-fandash-fixture-name { text-align: right; }\\n.ss-w-fandash-fixture-vs { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n/* date + venue as labelled rows, so a long stadium name gets its own line to ellipsis in */\\n.ss-w-fandash-fixture-meta { border-top: 1px solid var(--ss-w-line); padding-top: 10px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-fixture-kickoff { font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-fixture-venue { font-weight: 600; }\\n.ss-w-fandash-fact { font-size: 12px; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 8px; }\\n/* each head-to-head figure sits on its own shaded tile, so the grid gap separates wins/draws/losses */\\n.ss-w-fandash-h2h .ss-w-fandash-split-cell { background: var(--ss-w-bubble); border-radius: 10px; padding: 12px 6px; }\\n/* extra breathing room between the tally row and the fact beyond the card's own gap */\\n.ss-w-fandash-h2h .ss-w-fandash-fact { margin-top: 4px; }\\n\\n/* Team form: a two-column result-card grid, left = home team's last 5, right = away team's last 5,\\n most-recent first. The head row carries each column's crest + name; the rows grid is filled\\n home-cell/away-cell per index so the 2-col grid lays out pairs without extra JS bookkeeping. */\\n.ss-w-fandash-teamform-head { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }\\n.ss-w-fandash-teamform-head-team { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11.5px; font-weight: 750; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest-mono { font-size: 8px; }\\n.ss-w-fandash-teamform-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-teamform-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 6px; }\\n.ss-w-fandash-teamform-slot { display: block; min-width: 0; }\\n.ss-w-fandash-teamform-cell {\\n display: flex; align-items: center; gap: 4px; border-radius: 7px; padding: 4px 5px; color: #fff;\\n}\\n.ss-w-fandash-teamform-cell--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-teamform-cell--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-teamform-cell--draw { background: var(--ss-w-faint); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest { width: 16px; height: 16px; flex: none; background: rgba(255, 255, 255, .22); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest-mono { font-size: 7px; color: #fff; }\\n.ss-w-fandash-teamform-score { flex: 1; text-align: center; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; }\\n.ss-w-fandash-injuries-more { margin-top: 10px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-injuries-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }\\n.ss-w-fandash-form-pill {\\n display: inline-grid; place-items: center; width: 16px; height: 16px;\\n border-radius: 4px; font-size: 9.5px; font-weight: 700; color: #fff;\\n}\\n.ss-w-fandash-form-pill--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-form-pill--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-form-pill--draw { background: var(--ss-w-faint); }\\n\\n/* countdown card: a compact top card -- section eyebrow left, colon-separated clock right. Each\\n segment stacks its figure over a small unit label (d/h/m/s). The exact kickoff date is not\\n repeated here; the fixture card below carries it. */\\n.ss-w-fandash-countdown-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-countdown-clock { display: inline-flex; align-items: flex-start; gap: 6px; color: var(--ss-w-accent); }\\n.ss-w-fandash-countdown-seg { display: inline-flex; flex-direction: column; align-items: center; }\\n.ss-w-fandash-countdown-value { font-size: 26px; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.01em; }\\n.ss-w-fandash-countdown-unit { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); margin-top: 3px; }\\n.ss-w-fandash-countdown-colon { font-size: 22px; font-weight: 750; line-height: 1; color: var(--ss-w-faint); }\\n\\n/* injuries + transfers: two-column ours/theirs, in/out */\\n.ss-w-fandash-transfers-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n/* injuries: a 1px divider column sits between the two team sections, each headed by crest + name */\\n.ss-w-fandash-injuries-cols { display: grid; grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1fr); gap: 12px; }\\n.ss-w-fandash-injuries-divider { background: var(--ss-w-line); }\\n.ss-w-fandash-injuries-col, .ss-w-fandash-transfers-col { min-width: 0; display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-transfers-col-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n.ss-w-fandash-injuries-col-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest-mono { font-size: 9px; }\\n.ss-w-fandash-injuries-col-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-injuries-empty, .ss-w-fandash-transfers-empty { font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-list, .ss-w-fandash-transfer-list { list-style: none; display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-fandash-injury-row, .ss-w-fandash-transfer-row { display: flex; flex-direction: column; gap: 1px; }\\n.ss-w-fandash-injury-name, .ss-w-fandash-transfer-name { font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }\\n.ss-w-fandash-injury-meta { display: flex; flex-wrap: wrap; gap: 4px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-status { font-weight: 700; color: var(--ss-w-neg); }\\n.ss-w-fandash-transfer-club { font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-transfer-type { align-self: flex-start; font-size: 9.5px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 1px 7px; margin-top: 2px; }\\n\\n/* reason-to-bet */\\n.ss-w-fandash-reason-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-reason-item { font-size: 12.5px; padding-left: 14px; position: relative; }\\n.ss-w-fandash-reason-item::before { content: \\\"•\\\"; position: absolute; left: 0; color: var(--ss-w-accent); font-weight: 700; }\\n\\n/* where-to-watch */\\n.ss-w-fandash-stations { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-fandash-station-chip { font-size: 11.5px; font-weight: 600; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 999px; padding: 4px 10px; }\\n\\n/* congested week: a fixed 3-column grid of upcoming fixtures (day / opponent / comp / time) */\\n.ss-w-fandash-congested-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-congested-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 8px; border-radius: 10px; background: var(--ss-w-bubble); }\\n.ss-w-fandash-congested-day { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n.ss-w-fandash-congested-opponent { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-comp { font-size: 10px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-time { font-size: 10.5px; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n\\n/* links: 2-column grid of tappable tiles */\\n.ss-w-fandash-link-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-link-tile { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 13px; border-radius: 10px; border: 1px solid transparent; text-decoration: none; color: inherit; background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-tile:hover { background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-label { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-link-chevron { flex: none; width: 12px; height: 12px; color: var(--ss-w-accent); }\\n\\n/* post-match result: full-time scoreboard, mirroring the live card's crest + big-score treatment.\\n A neutral \\\"Full time\\\" pill sits left of a coloured Win/Draw/Loss tag; the 3-column main row\\n (home crest+name | score | away crest+name, away reversed) puts the winner's score in full ink\\n and the loser's dimmed; a centered meta line sits under a divider. */\\n.ss-w-fandash-postmatch-top { display: flex; align-items: center; gap: 8px; margin-bottom: 15px; }\\n.ss-w-fandash-postmatch-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-postmatch-tag { margin-left: auto; flex: none; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-postmatch-tag--win { color: var(--ss-w-pos); }\\n.ss-w-fandash-postmatch-tag--loss { color: var(--ss-w-neg); }\\n.ss-w-fandash-postmatch-tag--draw { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-postmatch-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-postmatch-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-postmatch-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-postmatch-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; }\\n.ss-w-fandash-postmatch-score-value--win { color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-value--lose { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-postmatch-meta { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--ss-w-line); font-size: 12px; color: var(--ss-w-faint); text-align: center; }\\n\\n/* post-match goals: a football-ball icon per goal (mirrors the live timeline ball, duplicated here\\n under the postmatch prefix), text dimmed for opponent goals and picked out in full ink + bold\\n for the club's own goals */\\n.ss-w-fandash-postmatch-goal-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-postmatch-goal { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-goal-ball { width: 11px; height: 11px; flex: none; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-goal--club { color: var(--ss-w-ink); font-weight: 650; }\\n\\n/* post-match stats: home value / stat label / away value, oriented by venue (u316), each row now\\n backed by a home/away split bar -- the big upgrade from plain text -- plus a legend. Mirrors\\n LiveStatsCard's split-bar treatment under the postmatch-prefixed classes; the shared\\n --ss-w-home/--ss-w-away/--ss-w-track tokens are defined above. */\\n.ss-w-fandash-postmatch-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-postmatch-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-postmatch-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-postmatch-stat-value { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-postmatch-stat-label { font-size: 10.5px; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-fandash-postmatch-stat-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-postmatch-stat-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-fandash-postmatch-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-postmatch-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-postmatch-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* post-match top performer (full mockup treatment): gradient initials avatar + name + a\\n prominent rating chip. Avatar gradient reuses the --ss-w-away token, same pairing as the live\\n crest fallback; \\\"?\\\" renders through the same avatar span when the name is blank. */\\n.ss-w-fandash-postmatch-perf-row { display: flex; align-items: center; gap: 12px; }\\n.ss-w-fandash-postmatch-perf-avatar {\\n flex: none; width: 42px; height: 42px; border-radius: 50%;\\n display: grid; place-items: center;\\n font-size: 14px; font-weight: 800; color: #fff;\\n background: linear-gradient(135deg, var(--ss-w-away), color-mix(in srgb, var(--ss-w-away) 55%, #000));\\n}\\n.ss-w-fandash-postmatch-perf-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; }\\n.ss-w-fandash-postmatch-perf-rating { margin-left: auto; flex: none; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 11px; }\\n\\n/* post-match next (v1, modest): whenLabel is already a complete localized phrase (opponent +\\n venue + kickoff) composed server-side, so this card renders just that one line -- dressed up\\n with an accent rule rather than a duplicated opponent line. The richer opponent-headline/venue-\\n chip/crest layout from the mockup needs a server field split and is deferred. */\\n.ss-w-fandash-postmatch-next-row { display: flex; align-items: center; gap: 10px; border-left: 3px solid var(--ss-w-accent); padding-left: 10px; }\\n.ss-w-fandash-postmatch-next-when { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.3; }\\n\\n/* resting next: the between-matches fixture teaser -- when-label left, competition badge right */\\n.ss-w-fandash-resting-next-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-next-when { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-resting-next-competition { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n\\n/* resting standings: position figure left, W-D-L/points record right */\\n.ss-w-fandash-resting-standings-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-standings-position { font-size: 15px; font-weight: 750; color: var(--ss-w-ink); }\\n.ss-w-fandash-resting-standings-record { font-size: 11.5px; color: var(--ss-w-faint); text-align: right; }\\n\\n/* resting season: top scorer / key player / season tally as stacked rows */\\n.ss-w-fandash-resting-season-rows { display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-resting-season-row { font-size: 12.5px; color: var(--ss-w-ink); }\\n\\n/* resting form: reuses the fixture last-five pill classes (ss-w-fandash-form / -form-pill) */\\n.ss-w-fandash-resting-form .ss-w-fandash-form { margin-top: 2px; }\\n\\n/* live score: pulsing Live pill, crests (real image or a coloured initials fallback), a big\\n tabular score, and an optional scorers line. Also where the shared home/away venue-colour\\n tokens (--ss-w-home / --ss-w-away / --ss-w-track) are defined above -- the timeline and stats\\n cards reuse them. */\\n.ss-w-fandash-live-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-fandash-live-pill { display: inline-flex; flex: none; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: #fff; background: var(--ss-w-neg); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; animation: ss-w-fandash-live-pulse 1.3s ease-in-out infinite; }\\n@keyframes ss-w-fandash-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }\\n@media (prefers-reduced-motion: reduce) {\\n .ss-w-fandash-live-dot { animation: none; }\\n}\\n.ss-w-fandash-live-minute { flex: none; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-competition { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-live-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-live-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-live-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-live-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-live-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-live-scorers { margin-top: 12px; display: flex; justify-content: flex-end; gap: 7px; align-items: center; font-size: 12.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-live-scorers-icon { flex: none; color: var(--ss-w-away); }\\n\\n/* live timeline: a compact two-sided event list down a centre spine -- each club's events sit on\\n its own side (home left, away right), most-recent 3 shown with a \\\"See more\\\" toggle for the\\n rest. A 3-column grid (txt | badge | txt) per row; the spine itself is a ::before on the list. */\\n.ss-w-fandash-live-tl { position: relative; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-live-tl::before { content: \\\"\\\"; position: absolute; left: 50%; top: 1px; bottom: 1px; width: 2px; background: var(--ss-w-line); transform: translateX(-1px); }\\n.ss-w-fandash-live-tl-ev { display: grid; grid-template-columns: 1fr 32px 1fr; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-tl-txt { display: flex; align-items: center; gap: 7px; font-size: 13px; min-width: 0; }\\n.ss-w-fandash-live-tl-ev--home .ss-w-fandash-live-tl-txt { grid-column: 1; justify-content: flex-end; }\\n.ss-w-fandash-live-tl-ev--away .ss-w-fandash-live-tl-txt { grid-column: 3; justify-content: flex-start; flex-direction: row-reverse; }\\n.ss-w-fandash-live-tl-who { font-weight: 650; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-fandash-live-tl-off { font-weight: 500; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-who { font-weight: 800; }\\n.ss-w-fandash-live-tl-badge { grid-column: 2; justify-self: center; min-width: 29px; height: 19px; padding: 0 4px; border-radius: 6px; display: grid; place-items: center; font-size: 11px; font-weight: 800; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); font-variant-numeric: tabular-nums; z-index: 1; }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-badge { background: var(--ss-w-accent); color: #fff; border-color: transparent; }\\n.ss-w-fandash-live-tl-ico { width: 17px; height: 17px; flex: none; display: grid; place-items: center; }\\n.ss-w-fandash-live-tl-ico--goal { border-radius: 50%; background: color-mix(in srgb, var(--ss-w-away) 16%, transparent); }\\n.ss-w-fandash-live-tl-ball { width: 12px; height: 12px; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-live-tl-card { width: 9px; height: 12px; border-radius: 2px; display: block; }\\n.ss-w-fandash-live-tl-card--yellow { background: var(--ss-w-cta); }\\n.ss-w-fandash-live-tl-card--red { background: var(--ss-w-away); }\\n.ss-w-fandash-live-tl-subarrows { font-size: 11px; font-weight: 900; line-height: 1; letter-spacing: -1px; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-tl-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-more { margin-top: 4px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-live-tl-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n\\n/* live stats: club value / stat label / opponent value, each row backed by a home/away split\\n bar, plus an optional momentum wave (or its text fallback) and a club/opponent colour legend.\\n No side signal reaches this card, so the club is always the home token and the opponent is\\n always the away token -- see LiveStatsCard.tsx. */\\n.ss-w-fandash-live-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-live-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-live-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-live-stat-value { font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-live-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-live-stat-label { font-size: 10.5px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-live-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-live-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-live-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n\\n.ss-w-fandash-live-momentum { font-size: 11.5px; font-weight: 650; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fandash-live-mom-caption { display: block; margin-bottom: 5px; font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-mom-svg { width: 100%; height: 56px; display: block; overflow: visible; }\\n.ss-w-fandash-live-mom-home { fill: var(--ss-w-home); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-away { fill: var(--ss-w-away); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-line { fill: none; stroke: color-mix(in srgb, var(--ss-w-ink) 55%, transparent); stroke-width: 1.5; }\\n.ss-w-fandash-live-mom-base { stroke: var(--ss-w-line); stroke-width: 1; stroke-dasharray: 3 3; }\\n.ss-w-fandash-live-mom-plot { position: relative; }\\n.ss-w-fandash-live-mom-now {\\n position: absolute; width: 7px; height: 7px; border-radius: 50%;\\n transform: translate(-50%, -50%);\\n background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-ink);\\n pointer-events: none;\\n}\\n.ss-w-mon-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); text-align: center; }\\n.ss-w-mon-mom .ss-w-fandash-live-mom { margin-top: 6px; padding-top: 0; border-top: none; }\\n\\n.ss-w-fandash-live-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-live-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */\\n.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); overflow-x: auto; scrollbar-width: none; }\\n.ss-w-tabs::-webkit-scrollbar { display: none; }\\n.ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 12px; margin-bottom: -1px; border-bottom: 2px solid transparent; flex: none; white-space: nowrap; }\\n.ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-tab-count { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 999px; padding: 1px 6px; }\\n.ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }\\n.ss-w-tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n\\n/* Matches tab match card (MonitorMatchCard): pill row, crest/score main row, per-stat split\\n bars (venue-oriented -- home always left/blue, away always right/red, never club-oriented,\\n the u316 bug class), a promoted-market strip for the user's pinned stat chips, and a grace\\n note once the match has gone full time. Reuses the --ss-w-home/--ss-w-away/--ss-w-track venue\\n tokens and .ss-w-fandash-live-pill for the Live pill so all live surfaces share one look. */\\n.ss-w-mon { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }\\n.ss-w-mon-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-mon-pill { display: inline-flex; flex: none; align-items: center; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-mon-min { flex: none; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-comp { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mon-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-mon-side { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-w-mon-side--away { flex-direction: row-reverse; text-align: right; }\\n/* long club names (Wolverhampton Wanderers) wrap to two lines instead of truncating mid-word */\\n.ss-w-mon-name { min-width: 0; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-mon-vs { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; }\\n.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); }\\n.ss-w-mon-score i { font-style: normal; color: var(--ss-w-faint); font-weight: 500; margin: 0 4px; }\\n.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); }\\n.ss-w-mon-scorers-col { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\\n.ss-w-mon-scorers-col li { overflow-wrap: anywhere; }\\n.ss-w-mon-scorers-home { text-align: right; }\\n.ss-w-mon-scorers-away { text-align: left; }\\n.ss-w-mon-scorers-ball { flex: none; align-self: start; line-height: 1.35; }\\n.ss-w-fact { display: flex; flex-direction: column; gap: 7px; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--ss-w-accent) 9%, transparent); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, transparent); }\\n.ss-w-fact-k { display: flex; align-items: center; gap: 6px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-w-fact-min { color: var(--ss-w-ink); letter-spacing: 0; }\\n.ss-w-fact-subj { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 650; color: var(--ss-w-faint); }\\n.ss-w-fact-text { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-fact-basis { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fact-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 8px; }\\n.ss-w-fact-foot { display: flex; align-items: center; gap: 14px; }\\n.ss-w-fact-link { font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); background: none; border: none; padding: 4px 0; min-height: 32px; cursor: pointer; }\\n.ss-w-fact-link--muted { color: var(--ss-w-faint); margin-left: auto; }\\n.ss-w-fact-hist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li { display: grid; grid-template-columns: 34px 1fr; gap: 8px; padding: 9px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li:last-child { border-bottom: none; }\\n.ss-w-fact-hmin { font-size: 11px; font-weight: 800; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-fact-htext { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-ink); }\\n.ss-w-mon-stats { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-mon-stat { display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-mon-pstrip { padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--ss-w-accent) 8%, transparent); }\\n.ss-w-mon-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-mon-stat-v { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-v--home { color: var(--ss-w-home); }\\n.ss-w-mon-stat-v--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-mon-stat-l { font-size: 10px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-mon-bar { position: relative; height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-mon-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-mon-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-mon-stat-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mon-mkt { background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 6px; padding: 3px 6px; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-mkt-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }\\n.ss-w-mon-price { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-mon-susp { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 2px 6px; }\\n.ss-w-mon-asof { display: block; font-size: 10.5px; font-weight: 600; color: var(--ss-w-cta); }\\n.ss-w-mon-grace { font-size: 11px; color: var(--ss-w-faint); border-top: 1px solid var(--ss-w-line); padding-top: 8px; }\\n\\n/* Matches/Odds tab panels (MonitorTabs): the shared per-market-pin context line, the empty\\n state shown when the snapshot carries no matches/markets yet, the persistent D5 in-slip badge,\\n and the per-market-pin wrapper card (struck price on settlement is a pure CSS hook off its\\n [data-settled] attribute -- no separate class on the price element itself). */\\n.ss-w-mk-ctx { display: flex; align-items: center; gap: 6px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--ss-w-line); }\\n/* the score and the trailing badges/pin never shrink or wrap -- only the fixture name truncates */\\n.ss-w-mk-ctx b { flex: none; white-space: nowrap; }\\n/* the context line's fixture name stays single-line (the two-line clamp is for the match card) */\\n.ss-w-mk-ctx .ss-w-mon-name { display: block; white-space: nowrap; text-overflow: ellipsis; }\\n.ss-w-mk-ctx-side { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-mk-ctx-right { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }\\n/* flex:1 keeps the composer pinned to the panel bottom when a tab is empty */\\n.ss-w-mon-empty { flex: 1; padding: 24px 16px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n/* Per-pin unavailable state: the pin's context line still rendered above (score, name, unpin), but\\n the pin has neither a card nor history (compose-time rescue failed) -- a small inline note beats\\n a bare context line with nothing under it. */\\n.ss-w-mon-empty-card { padding: 8px 0 2px; font-size: 12px; color: var(--ss-w-faint); }\\n.ss-w-mon-inslip { display: inline-flex; flex: none; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-pos); }\\n/* Odds-tab item is bare: the visible card is the market-odds card itself (no outer wrapper card),\\n with an optional slim live strip above it. */\\n.ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-mk-live { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0 2px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mk-live-score { color: var(--ss-w-ink); font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-w-mon-oddspin[data-settled] .ss-w-mo-price,\\n.ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }\\n\\n/* market accordion (Task 9): one collapsed row per available market, expanding into a reused\\n MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */\\n/* Pinned-match tile: the match card + its odds accordion, spaced apart. */\\n.ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-acc { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-acc-row { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); overflow: hidden; }\\n/* Row header: expand toggle (flex:1) + the market PinToggle as a sibling (no nested buttons). */\\n.ss-w-acc-head { display: flex; align-items: center; gap: 8px; padding: 6px 9px 6px 11px; }\\n.ss-w-acc-toggle { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); padding: 5px 0; }\\n/* Suspended: the row stays listed (knowing a market is off is useful) but is not tappable --\\n its card is unservable, so a pointer cursor would promise something that cannot load. */\\n.ss-w-acc-toggle--susp { cursor: default; color: var(--ss-w-faint); }\\n.ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; flex: none; }\\n.ss-w-acc-label { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); flex: none; }\\n.ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); flex: none; }\\n.ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-acc-insight { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }\\n\\n/* ---- Today tab (u355) ---- */\\n.ss-w-sec-head { display: flex; align-items: center; gap: 7px; padding: 2px 2px 0; font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }\\n.ss-w-sec-head::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n.ss-w-sec-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n.ss-w-today-live { display: flex; flex-direction: column; gap: 2px; }\\n\\n.ss-w-grp { border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }\\n.ss-w-grp-head { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 11px; background: var(--ss-w-bubble); border: none; font: inherit; color: var(--ss-w-ink); cursor: pointer; text-align: left; }\\n.ss-w-grp-head:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-grp-chev { color: var(--ss-w-faint); font-size: 10px; flex: none; }\\n.ss-w-grp-name { font-size: 12px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-grp-country { font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-grp-count { margin-left: auto; flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; }\\n.ss-w-grp-body { display: flex; flex-direction: column; padding: 2px 11px 6px; }\\n\\n.ss-w-drow { display: grid; grid-template-columns: 42px minmax(0,1fr) 22px; align-items: center; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-drow:last-child { border-bottom: none; }\\n.ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-drow-when--live { color: var(--ss-w-neg); }\\n/* Each side ellipsises independently: a single joined string truncates the away team off the end,\\n which is the u350 betting-card truncation one layer down. */\\n.ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-drow-side { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1 1 0; }\\n/* Away side mirrors home around the score: crest to the far edge, name aligned inward. */\\n.ss-w-drow-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-drow-nm { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* Centre slot of .ss-w-drow-fx, between the two sides: flex:none so a widening score never\\n steals width the team names need to avoid ellipsis. min-width holds the slot at the width of a\\n one-digit scoreline so an unscored row's bare dash does not pull the column out of line -- the\\n scores read as a column down the list, not a jitter. */\\n.ss-w-drow-sc { flex: none; min-width: 26px; text-align: center; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-drow--live { background: color-mix(in srgb, var(--ss-w-neg) 5%, transparent); border-radius: 8px; padding: 7px 6px; margin: 0 -6px; border-bottom: none; }\\n.ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }\\n\\n.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; }\\n\\n/* Prize banner: CTA-tinted card with icon + body column (label + chips) — still used by\\n LeaderboardEmpty.tsx's weekly-prize callout. */\\n.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)); }\\n.ss-w-prize-icon { flex: none; font-size: 20px; line-height: 1; padding-top: 1px; }\\n.ss-w-prize-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-prize-text { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.35; overflow-wrap: anywhere; }\\n\\n/* ── games hub (u393) ── */\\n.ss-g-hub-wrap { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; background: var(--ss-g-ground); font-family: var(--ss-g-font-body); color: var(--ss-g-ink); }\\n.ss-g-hub { display: flex; flex-direction: column; gap: 14px; padding: 14px 16px 20px; }\\n.ss-g-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-stat { display: flex; flex-direction: column; gap: 2px; padding: 9px 12px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); min-width: 0; }\\n.ss-g-stat-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-stat-v { display: flex; align-items: baseline; gap: 4px; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 24px; line-height: 1; white-space: nowrap; }\\n.ss-g-stat-v svg { color: var(--ss-g-flame); align-self: center; }\\n.ss-g-stat-v small { font-family: var(--ss-g-font-body); font-size: 12px; font-weight: 600; color: var(--ss-g-muted); overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-stat-v--accent { color: var(--ss-w-accent); }\\n.ss-g-prize { align-self: flex-start; }\\n.ss-g-tile { position: relative; display: flex; flex-direction: column; gap: 4px; padding: 10px; min-width: 0; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; }\\n.ss-g-tile:not([data-disabled]):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-tile[data-disabled] { opacity: .55; cursor: default; }\\n.ss-g-tile--tile { height: 148px; }\\n.ss-g-tile-art { height: 74px; border-radius: 10px; background: var(--ss-g-raised); display: flex; align-items: center; justify-content: center; margin-bottom: 4px; }\\n.ss-g-art { width: 100%; height: 100%; }\\n.ss-g-art-fg { fill: var(--ss-g-strong-line); }\\n.ss-g-art-accent { fill: var(--ss-w-accent); }\\n.ss-g-art-accent-stroke { fill: none; stroke: var(--ss-w-accent); stroke-width: 2; }\\n.ss-g-art-dot { fill: var(--ss-g-pitch-mark); }\\n.ss-g-art-pitch { fill: var(--ss-g-pitch); stroke: var(--ss-g-pitch-line); }\\n.ss-g-art-block { fill: var(--ss-g-line); }\\n.ss-g-art-correct { fill: var(--ss-g-correct); }\\n.ss-g-art-dash { fill: none; stroke: var(--ss-g-strong-line); stroke-dasharray: 3 2; stroke-width: 1.5; }\\n.ss-g-art-line { stroke: var(--ss-g-line-warm); stroke-width: 2; }\\n.ss-g-art-ink { fill: none; stroke: var(--ss-g-on-accent); stroke-width: 2; }\\n.ss-g-art-q { fill: var(--ss-w-accent); font: 800 20px var(--ss-g-font-display); }\\n.ss-g-tile-title { font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status[data-tone=\\\"accent\\\"] { color: var(--ss-w-accent); font-weight: 600; }\\n.ss-g-tile-status[data-tone=\\\"success\\\"] { color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-tile--hero { flex-direction: row; min-height: 184px; padding: 0; overflow: hidden; border-radius: 18px; background: var(--ss-g-warm); border-color: var(--ss-g-line-warm); }\\n.ss-g-hero-text { flex: 0 0 60%; display: flex; flex-direction: column; justify-content: center; gap: 6px; padding: 18px; min-width: 0; }\\n.ss-g-hero-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-hero-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: .95; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-hero-sub { font-size: 14px; color: var(--ss-g-ink-2); }\\n.ss-g-hero-cta { align-self: flex-start; margin-top: 6px; padding: 9px 16px; border-radius: 999px; background: var(--ss-w-accent); color: var(--ss-g-on-accent); font-size: 14px; font-weight: 700; }\\n.ss-g-hero-art { flex: 1; display: flex; align-items: center; justify-content: center; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sec { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 6px; }\\n.ss-g-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-sec-head span { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-tile--wide { flex-direction: row; align-items: center; gap: 14px; min-height: 104px; }\\n.ss-g-wide-art { width: 84px; height: 84px; flex: none; border-radius: 10px; background: var(--ss-g-raised); }\\n.ss-g-wide-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }\\n.ss-g-wide-chev { color: var(--ss-g-muted); transform: rotate(180deg); display: flex; }\\n\\n/* ── Mystery Tiger (u393) ── */\\n.ss-g-mt-card { flex: none; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); overflow: hidden; display: flex; flex-direction: column; }\\n.ss-g-mt-portrait { position: relative; height: 178px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 16px, var(--ss-g-warm) 16px 36px); }\\n.ss-g-mt-portrait .ss-g-sil { font-size: 46px; }\\n.ss-g-mt-photo { width: 132px; height: 132px; margin-bottom: 30px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 40px var(--ss-g-font-display); }\\n.ss-g-mt-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-cp-photo { width: 64px; height: 64px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 22px var(--ss-g-font-display); }\\n.ss-g-cp-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-mt-reveal-name { position: absolute; bottom: 6px; left: 12px; right: 12px; text-align: center; font: 800 20px var(--ss-g-font-display); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-known { display: grid; gap: 6px; padding: 12px; }\\n.ss-g-mt-known-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }\\n.ss-g-mt-lab { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-known-v { width: 100%; height: 38px; border-radius: 8px; display: grid; place-items: center; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-mt-known-v[data-state=\\\"known\\\"] { background: var(--ss-g-correct); color: var(--ss-g-on-correct); font-size: 18px; }\\n.ss-g-mt-known-v[data-state=\\\"range\\\"] { border: 1px dashed var(--ss-g-strong-line); }\\n.ss-g-mt-table { display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-mt-thead, .ss-g-mt-row { display: grid; gap: 5px; align-items: center; }\\n.ss-g-mt-thead { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-thead span:not(:first-child) { text-align: center; }\\n.ss-g-mt-who { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-mt-av { width: 38px; height: 38px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 12px; font-weight: 700; overflow: hidden; }\\n.ss-g-mt-names { display: flex; flex-direction: column; min-width: 0; line-height: 1.1; }\\n.ss-g-mt-first { font-size: 11px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-last { font-size: 14px; font-weight: 700; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-cell { height: 42px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); overflow: hidden; }\\n.ss-g-mt-cell[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); border-color: transparent; color: var(--ss-g-on-correct); }\\n.ss-g-mt-cell[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); border-color: transparent; color: var(--ss-g-on-accent); }\\n.ss-g-mt-cell-dir { font-size: 10px; margin-top: 2px; }\\n.ss-g-mt-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mt-legend span { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-g-mt-sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }\\n.ss-g-mt-sw[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); }\\n.ss-g-mt-sw[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); }\\n.ss-g-mt-hint { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-mt-hint svg { color: var(--ss-w-accent); flex: none; margin-top: 1px; }\\n\\n/* ── Higher or Lower (u393) ── */\\n.ss-g-hl-prompt { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; }\\n.ss-g-hl-prompt-q { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-hl-prompt-stat { font: 800 30px var(--ss-g-font-display); text-transform: uppercase; letter-spacing: .02em; line-height: 1.05; }\\n.ss-g-hl-prompt-season { font-size: 12px; color: var(--ss-g-muted); }\\n/* The pair fills whatever height the panel leaves (a laptop demo panel is ~670px, the design 860px):\\n both cards share it and the photos scale with them, so Higher/Lower never fall below the fold. */\\n.ss-g-hl .ss-g-body { overflow-y: auto; container: hl / size; }\\n.ss-g-hl-pair { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-hl-card { flex: 1 1 0; min-height: min-content; max-height: 240px; display: flex; border-radius: 18px; overflow: hidden; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-hl-card--b { border-color: var(--ss-g-line-warm); }\\n.ss-g-hl-photo-wrap { width: 38%; max-width: 160px; flex: none; align-self: stretch; display: flex; align-items: flex-end; justify-content: center; background: var(--ss-g-raised); overflow: hidden; }\\n.ss-g-hl-photo-wrap .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-hl-photo { width: 100%; height: 100%; display: grid; place-items: center; color: var(--ss-g-muted); font: 800 36px var(--ss-g-font-display); }\\n.ss-g-hl-photo img { width: 100%; height: 100%; object-fit: cover; object-position: top; }\\n.ss-g-hl-info { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 12px 14px; }\\n.ss-g-hl-first { font-size: 13px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-surname { font: 800 26px var(--ss-g-font-display); text-transform: uppercase; line-height: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-value { font: 800 56px var(--ss-g-font-display); line-height: .95; color: var(--ss-w-accent); margin-top: 6px; }\\n.ss-g-hl-stat { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-hl-btns { display: flex; flex-direction: row; gap: 8px; margin-top: 12px; }\\n.ss-g-hl-btns .ss-g-btn { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0 6px; gap: 4px; }\\n/* Labels stay on one line: Turkish \\\"DAHA FAZLA\\\" wrapped to two in a ~115px button. */\\n.ss-g-hl-btns .ss-g-btn { font-weight: 800; font-size: 13px; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }\\n.ss-g-hl-btns .ss-g-btn svg { flex: none; }\\n/* Phone-width cards: the info column is ~230px, too narrow for \\\"DAHA FAZLA\\\" + icon side by side.\\n Drop the icons and tighten the type first; stack the buttons only when even that cannot fit. */\\n.ss-g-hl-info { container: hlinfo / inline-size; }\\n@container hlinfo (max-width: 280px) {\\n .ss-g-hl-btns .ss-g-btn svg { display: none; }\\n .ss-g-hl-btns .ss-g-btn { font-size: 12px; letter-spacing: 0; padding: 0 4px; }\\n}\\n@container hlinfo (max-width: 180px) {\\n .ss-g-hl-btns { flex-direction: column; }\\n}\\n.ss-g-hl-vs { position: relative; z-index: 1; flex: none; align-self: center; width: 44px; height: 44px; margin: -28px 0; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-ground); border: 2px solid var(--ss-g-line-warm); color: var(--ss-w-accent); font: 800 18px var(--ss-g-font-display); }\\n/* Clear the VS badge that straddles the seam between the two cards. */\\n.ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 24px; }\\n.ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 24px; }\\n/* Short panels (a ~580px widget on a small laptop): tighten the type so both cards and the\\n Higher/Lower buttons stay on screen; below this the body scrolls rather than clipping names. */\\n@container hl (max-height: 420px) {\\n .ss-g-hl-prompt-stat { font-size: 24px; }\\n .ss-g-hl-prompt-season { display: none; }\\n .ss-g-hl-info { padding: 8px 12px; }\\n .ss-g-hl-surname { font-size: 22px; }\\n .ss-g-hl-value { font-size: 42px; margin-top: 2px; }\\n .ss-g-hl-btns { margin-top: 8px; }\\n .ss-g-hl-vs { width: 38px; height: 38px; margin: -22px 0; font-size: 15px; }\\n .ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 18px; }\\n .ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 18px; }\\n}\\n.ss-g-hl-feedback { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--ss-g-ink-2); }\\n.ss-g-hl-feedback[data-correct=\\\"true\\\"] svg { color: var(--ss-g-success); }\\n.ss-g-hl-feedback[data-correct=\\\"false\\\"] svg { color: var(--ss-g-wrong-mark); }\\n.ss-g-hl-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\\n.ss-g-hl-dots { display: flex; gap: 5px; }\\n.ss-g-hl-dot { width: 22px; height: 22px; border-radius: 50%; border: 1.5px dashed var(--ss-g-strong-line); }\\n.ss-g-hl-dot[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); border: 0; }\\n.ss-g-hl-dot[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); border: 0; }\\n.ss-g-hl-pts { font: 700 22px var(--ss-g-font-display); white-space: nowrap; }\\n.ss-g-hl-pts-unit { font-size: 13px; color: var(--ss-g-muted); }\\n\\n/* ── Guess the XI (u393) ── pitch colours are the fixed --ss-g-pitch* tokens (Task 1) */\\n.ss-g-gxi-pitch { position: relative; flex: none; height: 380px; border-radius: 18px; overflow: hidden; border: 1px solid var(--ss-g-pitch-line);\\n background: repeating-linear-gradient(180deg, color-mix(in srgb, var(--ss-g-pitch) 92%, var(--ss-g-pitch-mark)) 0 12.5%, var(--ss-g-pitch) 12.5% 25%); }\\n.ss-g-gxi-rows { position: absolute; inset: 14px 6px; display: flex; flex-direction: column; justify-content: space-between; }\\n.ss-g-gxi-row { display: flex; justify-content: space-evenly; align-items: flex-start; }\\n.ss-g-gxi-node { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; max-width: 72px; }\\n.ss-g-gxi-disc { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-pitch-chip); border: 2px solid var(--ss-g-pitch-ink); font-size: 22px; line-height: 1; }\\n.ss-g-gxi-node[data-revealed] .ss-g-gxi-disc { border-color: var(--ss-w-accent); }\\n.ss-g-gxi-disc[data-code] { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; letter-spacing: .02em; color: var(--ss-g-pitch-ink); }\\n.ss-g-gxi-pos { max-width: 100%; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-pitch-chip); color: var(--ss-g-pitch-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-gxi-pos--name { color: var(--ss-w-accent); text-transform: uppercase; }\\n.ss-g-gxi-wrong { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }\\n.ss-g-gxi-wrong-l { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-gxi-wrong-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 6px; border-radius: 999px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-muted); }\\n/* u407: lineup photo — fills the 44px disc like the flag does */\\n.ss-g-gxi-disc--photo { overflow: hidden; border: 2px solid var(--ss-w-accent); }\\n.ss-g-gxi-disc--photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-gxi-disc--photo .ss-w-av-initials { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; color: var(--ss-g-pitch-ink); }\\n/* u407: answer reveal — prominent row using theme tokens, works on dark/navy/light surfaces */\\n.ss-g-gxi-answer { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 12px 16px; border-radius: 14px; background: var(--ss-g-warm); border: 1.5px solid var(--ss-g-line-warm); }\\n.ss-g-gxi-answer-label { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); flex: none; }\\n.ss-g-gxi-answer-name { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; text-transform: uppercase; color: var(--ss-g-ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n\\n/* ---- Daily Quiz (u393) ---- */\\n.ss-g-dq-stem { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 30px; line-height: 1.05; overflow-wrap: anywhere; }\\n.ss-g-dq-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-dq-opt { position: relative; min-height: 96px; padding: 44px 12px 12px; border-radius: 16px; border: 1.5px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; display: flex; align-items: flex-end; min-width: 0; }\\n.ss-g-dq-opt:hover:not(:disabled) { border-color: var(--ss-g-line-warm); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-dq-opt:disabled { cursor: default; }\\n.ss-g-dq-badge { position: absolute; top: 10px; left: 10px; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; background: var(--ss-g-raised); font-weight: 700; font-size: 13px; color: var(--ss-g-ink); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] .ss-g-dq-badge { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-dq-opt-name { display: flex; flex-direction: column; min-width: 0; line-height: 1.05; }\\n.ss-g-dq-opt-first { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-dq-opt-last { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-dq-opt-suffix { margin-top: 2px; font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-dq-opt-full { font-size: 15px; font-weight: 600; line-height: 1.25; overflow-wrap: anywhere; }\\n.ss-g-dq-nav { display: flex; gap: 10px; }\\n.ss-g-dq-nav .ss-g-btn--block { flex: 1; }\\n.ss-g-dq-rq { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-dq-rq-stem { font-weight: 700; font-size: 14px; }\\n.ss-g-dq-rq-opts { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-g-dq-rq-opt { padding: 4px 10px; border-radius: 999px; font-size: 13px; font-weight: 600; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-dq-rq-opt--correct { background: var(--ss-g-correct); color: var(--ss-g-on-correct); }\\n.ss-g-dq-rq-opt--wrong { background: var(--ss-g-wrong); color: var(--ss-g-on-correct); }\\n.ss-g-dq-why { font-size: 13px; color: var(--ss-g-ink-2); }\\n/* u407: player avatar in quiz option — centered in top half, badge at top-left unaffected */\\n.ss-g-dq-opt-av { position: absolute; top: 7px; right: 10px; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 13px; font-weight: 700; flex: none; }\\n.ss-g-dq-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-dq-opt-av .ss-w-av-initials { font-size: 11px; }\\n\\n/* ---- Career Path (u393) ---- */\\n.ss-g-cp-card { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: 16px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-cp-card-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1; }\\n.ss-g-cp-card-title { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-cp-hint { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-cp-locks { display: flex; gap: 6px; flex-wrap: wrap; }\\n.ss-g-cp-line { list-style: none; display: flex; flex-direction: column; }\\n.ss-g-cp-step { display: flex; gap: 14px; align-items: stretch; }\\n.ss-g-cp-rail { display: flex; flex-direction: column; align-items: center; width: 52px; flex: none; }\\n.ss-g-cp-tile { width: 52px; height: 52px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; }\\n.ss-g-cp-tile--locked { border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); }\\n.ss-g-cp-tile--faint { border: 1.5px dashed var(--ss-g-line); background: transparent; color: var(--ss-g-faint); }\\n.ss-g-cp-conn { width: 2px; flex: 1; min-height: 14px; background: var(--ss-g-line-warm); }\\n.ss-g-cp-conn--faint { background: var(--ss-g-line); }\\n.ss-g-cp-step:last-child .ss-g-cp-conn { display: none; }\\n.ss-g-cp-step-text { display: flex; flex-direction: column; justify-content: center; min-height: 52px; padding-bottom: 14px; min-width: 0; }\\n.ss-g-cp-club { font-weight: 700; font-size: 16px; overflow-wrap: anywhere; }\\n.ss-g-cp-sub { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-cp-loan { color: var(--ss-w-accent); font-weight: 600; }\\n\\n/* Game screen host: fills the panel; each screen owns its header, gutters and scrolling. */\\n.ss-w-gscreen-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 0; overflow: hidden; background: var(--ss-g-ground); }\\n.ss-w-gscreen { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0; }\\n.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; }\\n\\n/* ---- Leaderboard (D2) ---- */\\n/* Outer shell */\\n.ss-w-lb2 { display: flex; flex-direction: column; gap: 12px; }\\n\\n/* Segmented control: This week / All time */\\n.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; }\\n.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; }\\n.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); }\\n\\n/* Row list */\\n.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); }\\n.ss-w-lb2-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-lb2-row:last-child { border-bottom: none; }\\n/* Highlighted \\\"you\\\" row: full-width tint via negative margin trick, contained by border-radius above */\\n.ss-w-lb2-row--you { background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); }\\n.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); }\\n.ss-w-lb2-rank--top3 { color: var(--ss-w-cta); }\\n.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); }\\n.ss-w-lb2-points { flex: none; font-size: 13px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-lb2-streak { flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); padding-left: 4px; }\\n\\n/* Kit-prize separator: a labelled hairline (eyebrow + two growing lines) */\\n.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); }\\n.ss-w-kitline::before, .ss-w-kitline::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n\\n/* Off-board treatment: dashed pill indicating rank is outside top N */\\n.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; }\\n\\n/* ---- Leaderboard empty / weekly-reset default state ---- */\\n.ss-w-lb-empty { display: flex; flex-direction: column; gap: 12px; flex: 1; }\\n.ss-w-lb-empty-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 20px 16px; border: 1px dashed color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); border-radius: 14px; background: color-mix(in srgb, var(--ss-w-cta) 6%, var(--ss-w-panel)); }\\n.ss-w-lb-empty--alltime { align-items: center; justify-content: center; text-align: center; padding: 24px 16px; }\\n.ss-w-lb-empty-icon { font-size: 30px; line-height: 1; }\\n.ss-w-lb-empty-title { margin: 2px 0 0; font-size: 16px; font-weight: 800; color: var(--ss-w-ink); }\\n.ss-w-lb-empty-body { margin: 0; max-width: 30ch; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-faint); }\\n.ss-w-lb-empty-cta { margin-top: 6px; border: none; border-radius: 10px; padding: 9px 18px; font: inherit; font-size: 13px; font-weight: 700; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); cursor: pointer; }\\n.ss-w-lb-empty-cta:hover { filter: brightness(1.04); }\\n.ss-w-lb-last { display: flex; align-items: center; gap: 7px; padding-top: 10px; border-top: 1px solid var(--ss-w-line); font-size: 11px; }\\n.ss-w-lb-last-label { text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--ss-w-faint); }\\n.ss-w-lb-last-handle { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-lb-last-points { flex: none; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n\\n/* PlayerAvatar initials fallback (PlayerAvatar.tsx) — size/colour inherit from the avatar class. */\\n.ss-w-av-initials { font-weight: 800; line-height: 1; text-transform: uppercase; letter-spacing: .02em; }\\n\\n/* ---- Beat the Grid (u393) ---- */\\n.ss-g-btg-grid { display: grid; gap: 6px; }\\n/* While the search sheet is pinned below, the grid shrinks its rows to share the body with it\\n instead of pushing the bottom row under the sheet. */\\n.ss-g-btg-grid--fit { flex: 0 1 auto; min-height: 0; }\\n.ss-g-btg-colhdr { min-height: 0; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; text-align: center; padding: 0 4px; font-size: 12px; font-weight: 700; line-height: 1.1; min-width: 0; overflow-wrap: anywhere; overflow: hidden; }\\n.ss-g-btg-colhdr[data-meta] { overflow-wrap: normal; word-break: normal; hyphens: none; font-size: 11px; letter-spacing: 0; }\\n.ss-g-btg-colhdr svg { color: var(--ss-w-accent); flex: none; }\\n.ss-g-btg-rowhdr { border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; letter-spacing: .04em; text-transform: uppercase; overflow-wrap: anywhere; text-align: center; overflow: hidden; }\\n.ss-g-btg-rowhdr[data-meta] { font-size: 10px; font-family: var(--ss-g-font-body); font-weight: 700; letter-spacing: -0.01em; text-transform: none; word-break: normal; overflow-wrap: normal; hyphens: none; line-height: 1.25; padding: 0 2px; }\\n.ss-g-btg-cell { position: relative; min-height: 0; min-width: 0; border-radius: 12px; border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; cursor: pointer; font: inherit; padding: 0; }\\n.ss-g-btg-cell:disabled { cursor: default; }\\n.ss-g-btg-cell[data-state=\\\"active\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"], .ss-g-btg-cell[data-state=\\\"wrong\\\"] { justify-content: flex-end; background: var(--ss-g-surface); border-style: solid; }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-btg-badge { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center; color: var(--ss-g-on-correct); }\\n.ss-g-btg-badge--correct { background: var(--ss-g-correct); }\\n.ss-g-btg-badge--wrong { background: var(--ss-g-wrong); }\\n.ss-g-btg-rarity { position: absolute; top: 6px; left: 6px; padding: 1px 6px; border-radius: 999px; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] .ss-g-btg-rarity { background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-btg-cell .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-btg-name { width: 100%; padding: 4px 2px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-display); font-weight: 700; font-size: 14px; text-transform: uppercase; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-plus { display: flex; }\\n.ss-g-btg-pin { flex: none; padding: 0 12px 12px; }\\n.ss-g-btg-sheet { padding: 14px; border-radius: 18px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-btg-sheet-hdr { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-btg-sheet-hdr .ss-g-chip { padding: 4px 10px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-sheet-x { color: var(--ss-g-muted); display: flex; flex: none; }\\n.ss-g-btg-sheet-close { margin-left: auto; flex: none; width: 44px; height: 44px; border: 0; border-radius: 10px; background: transparent; color: var(--ss-g-muted); display: grid; place-items: center; cursor: pointer; }\\n.ss-g-btg-sheet-close:hover { background: var(--ss-g-raised); color: var(--ss-g-ink); }\\n.ss-g-btg-sheet .ss-g-search-box { height: 48px; border-radius: 12px; background: var(--ss-g-ground); }\\n.ss-g-btg-sheet-empty { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-btg-sheet .ss-g-opt { background: var(--ss-g-raised); }\\n.ss-g-btg-sheet .ss-g-opts { max-height: 160px; }\\n.ss-g-btg-result-name { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-result-plus { color: var(--ss-w-accent); display: flex; }\\n/* u407: cell avatar replaces Silhouette */\\n.ss-g-btg-av { width: 38px; height: 38px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 12px; font-weight: 700; }\\n.ss-g-btg-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-btg-av .ss-w-av-initials { font-size: 12px; }\\n/* u407: coach photo in row/col header */\\n.ss-g-btg-coach-av { width: 28px; height: 28px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 10px; font-weight: 700; }\\n.ss-g-btg-coach-av img { width: 100%; height: 100%; object-fit: cover; }\\n/* u407: country flag emoji in header — sized to match other header icons */\\n.ss-g-btg-hdr-flag { font-size: 20px; line-height: 1; flex: none; }\\n/* u407: club crest in col/row header */\\n.ss-g-btg-colhdr .ss-g-crest, .ss-g-btg-rowhdr .ss-g-crest { width: 28px; height: 28px; flex: none; }\\n\\n/* ── Starting XI (u393) ── */\\n.ss-g-xi-pitch { position: relative; flex: none; height: 400px; border-radius: 18px; overflow: hidden; background: repeating-linear-gradient(180deg, var(--ss-g-pitch) 0 40px, color-mix(in srgb, var(--ss-g-pitch) 88%, var(--ss-g-pitch-mark)) 40px 80px); border: 1px solid var(--ss-g-pitch-line); }\\n.ss-g-xi-slot { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 48px; border: 0; padding: 0; background: transparent; color: var(--ss-g-pitch-mark); font: inherit; cursor: pointer; }\\n.ss-g-xi-slot:disabled { cursor: default; }\\n.ss-g-xi-ring { width: 48px; height: 48px; box-sizing: border-box; display: grid; place-items: center; border-radius: 50%; border: 1.5px dashed var(--ss-g-pitch-mark); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; }\\n.ss-g-xi-slot[data-state=\\\"filled\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-accent-tint); color: var(--ss-g-ink); }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-xi-tag { max-width: 72px; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-tag { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-xi-picker { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-xi-picker-head { display: flex; align-items: center; gap: 8px; font-size: 14px; }\\n.ss-g-xi-list { list-style: none; display: flex; flex-direction: column; gap: 4px; max-height: 240px; overflow-y: auto; }\\n.ss-g-xi-opt { width: 100%; display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 6px 10px; border: 0; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-xi-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-xi-opt-no { width: 28px; flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; color: var(--ss-w-accent); text-align: center; }\\n.ss-g-xi-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-opt-pos { flex: none; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 10px; font-weight: 700; }\\n.ss-g-xi-lock { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-xi-lock svg { color: var(--ss-w-accent); flex: none; }\\n\\n/* ── Stat Ladder (u393) ── */\\n.ss-g-sl-prompt { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 6px 0 6px; text-align: center; }\\n.ss-g-sl-stat { padding: 4px 10px; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }\\n.ss-g-sl-q { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; line-height: 1.05; text-transform: uppercase; }\\n.ss-g-sl-q em { font-style: normal; color: var(--ss-w-accent); }\\n.ss-g-sl-rungs { list-style: none; display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sl-rung { min-height: 84px; display: flex; align-items: center; gap: 12px; padding: 0 16px 0 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-sl-rung--mystery { min-height: 96px; border: 2px dashed var(--ss-w-accent); background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sl-rung--mystery[data-result=\\\"correct\\\"] { border: 2px solid var(--ss-g-correct); background: var(--ss-g-warm); }\\n.ss-g-sl-rung--mystery[data-result=\\\"wrong\\\"] { border: 2px solid var(--ss-g-wrong-mark); background: var(--ss-g-warm); }\\n.ss-g-sl-rank { width: 32px; height: 32px; flex: none; display: grid; place-items: center; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; }\\n.ss-g-sl-rung:first-child .ss-g-sl-rank { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-sl-rung--mystery .ss-g-sl-rank { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-sl-av { width: 52px; height: 52px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-weight: 700; }\\n.ss-g-sl-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-sl-name { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.1; }\\n.ss-g-sl-name small { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-sl-name b { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-who { flex: 1; min-width: 0; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-sl-val { flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: 1; }\\n.ss-g-sl-val--mystery { font-size: 40px; color: var(--ss-w-accent); }\\n.ss-g-sl-clue { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; line-height: 1.4; color: var(--ss-g-ink-2); }\\n.ss-g-sl-clue svg { flex: none; color: var(--ss-w-accent); }\\n.ss-g-sl-pool { list-style: none; display: flex; flex-direction: column; gap: 4px; }\\n.ss-g-sl-opt { width: 100%; min-height: 48px; display: flex; align-items: center; gap: 12px; padding: 6px 10px; border: 1px solid transparent; border-radius: 12px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] { border-color: var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] svg { color: var(--ss-w-accent); }\\n.ss-g-sl-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-sl-opt-av { width: 36px; height: 36px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 12px; font-weight: 700; }\\n.ss-g-sl-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-guess { display: flex; align-items: flex-end; gap: 8px; }\\n.ss-g-sl-guess .ss-g-search { flex: 1; min-width: 0; }\\n.ss-g-sl-guess .ss-g-btn { min-height: 50px; padding: 0 20px; border-radius: 14px; }\\n\\n/* ── Matchday Predictor (u393) ── */\\n.ss-g-mp-card { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 16px 10px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-mp-team { width: 84px; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }\\n.ss-g-mp-team .ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-mp-team-name { max-width: 100%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 17px; line-height: 1.05; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-mp-team-side { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mp-scores { display: flex; align-items: center; gap: 8px; }\\n.ss-g-mp-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }\\n.ss-g-mp-step { width: 64px; height: 44px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--ss-g-line-warm); background: var(--ss-g-raised); color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-mp-step:disabled { opacity: .4; cursor: default; }\\n.ss-g-mp-digit { width: 64px; height: 76px; display: grid; place-items: center; box-sizing: border-box; border-radius: 12px; background: var(--ss-g-ground); border: 2px solid var(--ss-g-strong-line); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 52px; line-height: 1; }\\n.ss-g-mp-digit[data-active=\\\"true\\\"] { border-color: var(--ss-w-accent); color: var(--ss-w-accent); }\\n.ss-g-mp-dash { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; color: var(--ss-g-faint); }\\n.ss-g-mp-scorer { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-mp-sec-head { display: flex; align-items: baseline; justify-content: space-between; margin-top: 10px; }\\n.ss-g-mp-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-mp-sec-head span { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mp-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-mp-pcard { position: relative; min-width: 0; height: 116px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 6px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; cursor: pointer; }\\n.ss-g-mp-pcard[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-mp-pcard:disabled { cursor: default; opacity: .6; }\\n.ss-g-mp-pcheck { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-mp-pname { max-width: 100%; font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mp-none { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--ss-g-line); background: transparent; color: var(--ss-g-muted); font: 600 14px var(--ss-g-font-body); cursor: pointer; text-align: left; }\\n.ss-g-mp-radio { width: 18px; height: 18px; flex: none; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--ss-g-strong-line); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] { color: var(--ss-g-ink); border-color: var(--ss-g-line-warm); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] .ss-g-mp-radio { border-color: var(--ss-w-accent); background: var(--ss-w-accent); box-shadow: inset 0 0 0 3px var(--ss-g-ground); }\\n.ss-g-mp-closed { padding: 10px 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-muted); font-size: 13px; text-align: center; }\\n.ss-g-mp-fun { font-size: 11px; color: var(--ss-g-faint); text-align: center; }\\n.ss-g-mp-rows { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-mp-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 14px; }\\n.ss-g-mp-row-k { color: var(--ss-g-ink-2); }\\n.ss-g-mp-row-v { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] .ss-g-mp-row-v { color: var(--ss-g-success); }\\n.ss-g-mp-row-d { color: var(--ss-g-ink); }\\n\\n/* ── Fan MOTM (u393) ── */\\n.ss-g-motm-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-motm-row { width: 100%; min-height: 60px; display: flex; align-items: center; gap: 12px; padding: 0 14px 0 10px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-motm-row:not(:disabled):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-motm-row:disabled { cursor: default; }\\n.ss-g-motm-row--voted { border: 1.5px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-motm-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-size: 13px; font-weight: 700; }\\n.ss-g-motm-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-motm-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-motm-pill { flex: none; padding: 3px 8px; font-size: 11px; }\\n.ss-g-motm-foot { font-size: 14px; font-weight: 600; }\\n.ss-g-motm-fun { font-size: 11px; color: var(--ss-g-faint); }\\n\"\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["import_react","import_widget_sdk","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","ReactMarkdown","remarkGfm","import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","directionWord","import_react","import_jsx_runtime","initials","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","Crest","import_react","head","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","initials","import_react","import_jsx_runtime","SHOWN","import_react","import_jsx_runtime","import_jsx_runtime","splitWidths","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","isTerminal","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_react","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","isLocked","React","import_react","import_jsx_runtime","import_jsx_runtime","MAX_GUESSES","parseClientState","import_react","import_jsx_runtime","parseClientState","segments","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_jsx_runtime","parseClientState","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","read","key","isRecord","parse","browserStorage","read","import_widget_sdk","import_react","import_widget_sdk","import_widget_sdk","import_react","import_react","import_react","import_react","TTL_MS","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|