@sensiblestats/widget-react 0.21.0 → 0.22.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/StatsWidget.tsx","../src/kickoff.ts","../src/i18n.ts","../src/config.ts","../src/dashboardTap.ts","../src/theme.ts","../src/useChatStream.ts","../src/reducer.ts","../src/chart.ts","../src/model.ts","../src/assets/logo.ts","../src/components/Icons.tsx","../src/components/GreetingBubble.tsx","../src/components/ChatFab.tsx","../src/components/ChatPanel.tsx","../src/components/ChatHeader.tsx","../src/components/MessageList.tsx","../src/components/Markdown.tsx","../src/components/EntityCardList.tsx","../src/components/BettingInsightList.tsx","../src/components/AddToSlipButton.tsx","../src/slip.ts","../src/components/Toast.tsx","../src/components/OddsMovementBadge.tsx","../src/components/Crest.tsx","../src/components/MarketOddsCardList.tsx","../src/components/OddsMovementCard.tsx","../src/components/ActionButtons.tsx","../src/components/dashboard/DashboardTile.tsx","../src/components/dashboard/GreetingDashboard.tsx","../src/components/club-dashboard/GreetingHeaderBlock.tsx","../src/components/club-dashboard/FixtureHeroBlock.tsx","../src/components/club-dashboard/ResultPills.tsx","../src/components/club-dashboard/FormGuideBlock.tsx","../src/components/club-dashboard/MatchPreviewBlock.tsx","../src/components/club-dashboard/MatchPreviewCardBlock.tsx","../src/components/club-dashboard/TeamDnaBlock.tsx","../src/components/club-dashboard/CountdownBlock.tsx","../src/components/club-dashboard/ClubDashboard.tsx","../src/components/ChatMessage.tsx","../src/components/IntentChips.tsx","../src/scroll.ts","../src/components/ChatInput.tsx","../src/styles/css.generated.ts"],"sourcesContent":["export { StatsWidget } from './StatsWidget'\nexport type { StatsWidgetProps } from './StatsWidget'\nexport type { StatsWidgetConfig } from './config'\nexport { WIDGET_CSS } from './styles/css.generated'\n","import { useEffect, useMemo, useRef, type CSSProperties } from 'react'\nimport { StatsWidgetClient, type Conversation } from '@sensiblestats/widget-sdk'\nimport { normalizeUi, toClientOptions, toUserContext, type StatsWidgetConfig } from './config'\nimport type { SlipHandlerProps } from './slip'\nimport { createDashboardTapSignal } from './dashboardTap'\nimport { themeAttrs } from './theme'\nimport { useChatStream } from './useChatStream'\nimport { ChatFab } from './components/ChatFab'\nimport { ChatPanel } from './components/ChatPanel'\nimport { WIDGET_CSS } from './styles/css.generated'\n\nexport type StatsWidgetProps =\n | { config: StatsWidgetConfig; client?: never }\n | { client: StatsWidgetClient; config?: Omit<StatsWidgetConfig, 'operatorId' | 'publicKey' | 'baseUrl' | 'userContext'> }\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 const ui = useMemo(() => normalizeUi((props.config ?? { operatorId: '', publicKey: '' }) as StatsWidgetConfig), [props.config])\n const rootRef = useRef<HTMLDivElement>(null)\n const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : undefined)\n const slip = useMemo<SlipHandlerProps>(\n () => ({\n onAddToSlip: props.config?.onAddToSlip,\n conversationId: controller.state.conversationId ?? undefined,\n onMarketClicked: (marketName) => {\n // sendSignal throws synchronously with no operatorUserId configured, and its\n // returned promise can reject on a gateway failure. Neither should ever break\n // the add-to-slip flow for a host that never wired signal tracking.\n try {\n void built?.conversation\n .sendSignal({ signalType: 'InsightMarketClicked', entityType: 'Market', entityName: marketName })\n .catch(() => undefined)\n } catch {\n // ignored — see comment above\n }\n },\n }),\n [props.config?.onAddToSlip, controller.state.conversationId, built],\n )\n const onDashboardTap = useMemo(\n () => (built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : undefined),\n [built],\n )\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 <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 controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} />\n ) : (\n <ChatFab\n label={ui.launcherLabel}\n greeting={ui.greeting}\n popupText={controller.state.popupText}\n onOpen={controller.open}\n onDismissPopup={controller.dismissPopup}\n dismissLabel={ui.dismissGreeting}\n />\n )}\n </div>\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\nexport interface LocaleStrings {\n launcherLabel: string\n placeholder: string\n closeChat: 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 showStats: string\n hideStats: 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 clubMatchPreviewHeading: string\n clubTeamDnaHeading: string\n clubFormHeading: string\n clubCountdownLabel: string\n clubKickoff: (ms: number) => string\n clubKickoffAria: (ms: number) => string\n inSlip: string\n slipAdded: (n?: number) => 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}\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 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 showStats: 'Show stats',\n hideStats: 'Hide stats',\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 clubMatchPreviewHeading: 'Match preview',\n clubTeamDnaHeading: 'How they play',\n clubFormHeading: 'Recent form',\n clubCountdownLabel: 'Countdown to kick-off',\n clubKickoff: (ms) =>\n new Intl.DateTimeFormat('en-GB', { weekday: 'short', day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n clubKickoffAria: (ms) =>\n `Kick-off ${new Intl.DateTimeFormat('en-GB', { weekday: 'long', day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit' }).format(new Date(ms))}`,\n inSlip: 'In slip',\n slipAdded: (n) => (n === undefined ? 'Added to slip' : `Added to slip (${n} selection${n === 1 ? '' : 's'})`),\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 },\n tr: {\n launcherLabel: 'SensibleStats ile sohbet et',\n placeholder: 'Bir takım, oyuncu veya maç hakkında sor…',\n closeChat: 'Sohbeti kapat',\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 showStats: 'İstatistikleri göster',\n hideStats: 'İstatistikleri gizle',\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 clubMatchPreviewHeading: 'Maç önizlemesi',\n clubTeamDnaHeading: 'Nasıl oynuyorlar',\n clubFormHeading: 'Son form',\n clubCountdownLabel: 'Başlama vuruşuna kalan',\n clubKickoff: (ms) =>\n new Intl.DateTimeFormat('tr-TR', { weekday: 'short', day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n clubKickoffAria: (ms) =>\n `Başlama vuruşu ${new Intl.DateTimeFormat('tr-TR', { weekday: 'long', day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit' }).format(new Date(ms))}`,\n inSlip: 'Kuponda',\n slipAdded: (n) => (n === undefined ? 'Kupona eklendi' : `Kupona eklendi (${n} seçim)`),\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 },\n}\n\nexport function resolveLocaleStrings(locale?: string): LocaleStrings {\n return STRINGS[locale as Locale] ?? STRINGS.en\n}\n","import type { AddToSlipHandler, StatsWidgetClientOptions, UserContext } from '@sensiblestats/widget-sdk'\nimport { resolveLocaleStrings } 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}\n\ntype UiKeys =\n | 'theme' | 'accent' | 'position' | 'offset' | 'radius' | 'locale'\n | 'launcherLabel' | 'greeting' | 'greetingMessage' | 'placeholder' | 'starters' | 'injectStyles'\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 closeChat: 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 showStats: string\n hideStats: 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 clubMatchPreviewHeading: string\n clubTeamDnaHeading: string\n clubFormHeading: string\n clubCountdownLabel: string\n clubKickoff: (ms: number) => string\n clubKickoffAria: (ms: number) => string\n addToSlip: string\n inSlip: string\n slipAdded: (n?: number) => 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}\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 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 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 showStats: strings.showStats,\n hideStats: strings.hideStats,\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 clubMatchPreviewHeading: strings.clubMatchPreviewHeading,\n clubTeamDnaHeading: strings.clubTeamDnaHeading,\n clubFormHeading: strings.clubFormHeading,\n clubCountdownLabel: strings.clubCountdownLabel,\n clubKickoff: strings.clubKickoff,\n clubKickoffAria: strings.clubKickoffAria,\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 }\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 { ENTITY_TYPE_CODES, type Conversation, type GreetingDashboardLayout, type GreetingDashboardTile, type SignalEntityType } 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/**\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 */\nexport function createDashboardTapSignal(sendSignal: Conversation['sendSignal']): DashboardTapHandler {\n return (tile, index, layout) => {\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 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 { ChatHandle, ChatInput, Conversation } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { reducer, initialState, type WidgetState } from './reducer'\nimport { chipFromText } from './model'\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\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}\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}\n\nexport function useChatStream(conversation: Conversation, starterTexts: string[], greetingMessage?: string): ChatController {\n const seed = useMemo(() => initialState(starterTexts.map(chipFromText)), [])\n const [state, dispatch] = useReducer(reducer, seed)\n const idRef = useRef(0)\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(false)\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 }, 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. No user bubble; its response\n // becomes the launcher popup. Fire-and-forget — failures (including a fallback timeout)\n // are swallowed (STOP only, no visible error) since this is non-critical background chatter.\n useEffect(() => {\n const message = greetingMessage?.trim()\n if (!message || greetedRef.current) return\n greetedRef.current = true\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 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 return { state, open, close, stop, toggle, send, retry, dismissPopup }\n}\n","import type { ChatEvent, ChatInput, ClubDashboardPayload, 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; clubDashboard?: ClubDashboardPayload }\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 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\nconst POPUP_MAX = 160\n\nexport function initialState(starters: ChipVM[]): WidgetState {\n return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, 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 const text = active?.text.trim() ?? ''\n // A completed greeting turn surfaces its answer as the launcher popup (unless already open).\n const popupText = active?.isGreeting && !state.isOpen && text ? text.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 clubDashboard: event.data.clubDashboard ?? 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 '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 }\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; message: string }\nexport interface ChipVM { text: string }\nexport interface InsightScope { key: string; label: string; stats: StatCell[] }\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 scopes?: InsightScope[]\n text: string\n stats: StatCell[]\n disclaimer?: string\n matchId: number\n matchOddsId?: number\n addToSlipEnabled: 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}\n\nexport interface MarketOddsRowVM {\n key: string\n selection: string\n odds: string\n oddsDecimal?: number\n matchOddsId?: number\n quotedAtUtc?: string\n isMain: 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 bookmaker?: string\n updatedAt?: string\n isLive: boolean\n matchId: number\n mainRows: MarketOddsRowVM[]\n moreRows: MarketOddsRowVM[]\n disclaimer?: string\n addToSlipEnabled: boolean\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 message = str(action.actionValue) ?? str(action.message) ?? str(action.query) ?? label\n return { label, actionId, 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\nexport function toInsightVM(insight: BettingInsight): InsightVM {\n const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? ''\n const selection = [str(insight.selectionLabel), str(insight.line)].filter(Boolean).join(' ') || undefined\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 scopes = Array.isArray(insight.scopes)\n ? (insight.scopes as Array<Record<string, unknown>>)\n .map((s) => ({ key: str(s.key), label: str(s.label), stats: readStatCells(s.stats) }))\n .filter((s): s is InsightScope => !!s.key && !!s.label)\n : undefined\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 scopes,\n text: str(insight.text) ?? '',\n stats: readStatCells(insight.stats),\n disclaimer: str(insight.disclaimer),\n matchId: typeof insight.matchId === 'number' ? insight.matchId : 0,\n matchOddsId,\n addToSlipEnabled: insight.addToSlipEnabled === 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 }\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 = [str(r.selectionLabel), str(r.line)].filter(Boolean).join(' ')\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 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 previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n }\n }\n const vms = rows.map(toRow).filter((r) => r.selection && r.odds)\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 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 }\n}\n\nexport interface OddsMovementVM {\n id: string\n market: string\n selection: 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}\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 = [str(card.selectionLabel), str(card.line)].filter(Boolean).join(' ')\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 market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n selection,\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 }\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","// 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}\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","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}>{text}</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 { SsMark } from './Icons'\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.\nexport function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLabel = 'Dismiss' }: { label: string; greeting?: string; popupText?: string | null; onOpen: () => void; onDismissPopup: () => void; dismissLabel?: string }): JSX.Element {\n const bubble = popupText ?? greeting\n return (\n <div className=\"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 <SsMark className=\"ss-w-fab-mark\" />\n </button>\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport { ChatHeader } from './ChatHeader'\nimport { MessageList } from './MessageList'\nimport { ChatInput } from './ChatInput'\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.\nconst 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 }: { controller: ChatController; ui: UiConfig; slip: SlipHandlerProps; onDashboardTap?: DashboardTapHandler }): JSX.Element {\n const { state, close, stop, send } = 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 return (\n <div className=\"ss-w-panel\" role=\"dialog\" aria-modal={isModal} aria-label={ui.chatDialogLabel}>\n <ChatHeader onClose={close} closeLabel={ui.closeChat} />\n <MessageList controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} />\n <ChatInput placeholder={ui.placeholder} streaming={state.isStreaming} onSend={(t) => send(t)} onStop={stop} stopLabel={ui.stopResponse} sendLabel={ui.sendMessage} />\n </div>\n )\n}\n","import { SsMark, CloseIcon } from './Icons'\n\nexport function ChatHeader({ onClose, closeLabel = 'Close chat' }: { onClose: () => void; closeLabel?: string }): JSX.Element {\n return (\n <header className=\"ss-w-header\">\n <SsMark className=\"ss-w-header-mark\" />\n <span className=\"ss-w-header-title\">SensibleStats</span>\n <button type=\"button\" className=\"ss-w-close\" aria-label={closeLabel} onClick={onClose}><CloseIcon /></button>\n </header>\n )\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 { ChatMessage } from './ChatMessage'\nimport { IntentChips } from './IntentChips'\nimport { ActionButtons } from './ActionButtons'\nimport { isPinnedToBottom } from '../scroll'\n\nexport function MessageList({ controller, ui, slip, onDashboardTap }: { controller: ChatController; ui: UiConfig; slip: SlipHandlerProps; onDashboardTap?: DashboardTapHandler }): 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 useEffect(() => {\n if (pinnedRef.current) endRef.current?.scrollIntoView({ block: 'end' })\n }, [state.messages, state.status])\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 or a 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)\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, displayText: a.label })}\n onTap={(tile, index) => {\n send(tile.actionValue, { 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 onClubAction={(label, opts) => send(label, { actionRef: opts.actionRef })}\n ui={ui}\n slip={slip}\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} />\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 }: { image: string }): JSX.Element {\n return <span className=\"ss-w-ecard-crest\" style={{ backgroundImage: `url(${image})` }} aria-hidden=\"true\" />\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 StatRows({ stats }: { stats: StatCell[] }): JSX.Element {\n return (\n <div className=\"ss-w-ecard-stats\">\n {stats.map((s) => {\n const m = RECORD_RE.exec(s.value)\n return (\n <div key={s.label} className=\"ss-w-ecard-row\">\n <span className=\"ss-w-ecard-rlabel\">{s.label}</span>\n {m ? <FormBar w={Number(m[1])} d={Number(m[2])} l={Number(m[3])} /> : <span />}\n <span className=\"ss-w-ecard-rval\">{s.value}</span>\n </div>\n )\n })}\n </div>\n )\n}\n\n// The right-hand panel: competition tabs (2+ scopes) or a static league label\n// (1 scope), the season pill, and the stat rows for the active scope.\nfunction CardBody({ c }: { c: CardVM }): JSX.Element | null {\n const [active, setActive] = useState(0)\n if (c.scopes.length === 0) return null\n const season = c.season ? <span className=\"ss-w-ecard-season\">{shortSeason(c.season)}</span> : null\n\n if (c.scopes.length === 1) {\n const only = c.scopes[0]!\n return (\n <div className=\"ss-w-ecard-body\">\n <div className=\"ss-w-ecard-tabs ss-w-ecard-tabs-static\">\n <span className=\"ss-w-ecard-lead\" title={only.label}>{only.image ? <Crest image={only.image} /> : null}<span className=\"ss-w-ecard-lead-txt\">{only.label}</span></span>\n {season}\n </div>\n <StatRows stats={only.stats} />\n </div>\n )\n }\n\n const current = c.scopes[active] ?? c.scopes[0]!\n return (\n <div className=\"ss-w-ecard-body\">\n <div className=\"ss-w-ecard-tabs\" role=\"tablist\">\n {c.scopes.map((s, i) => (\n <button\n key={String(s.competitionId ?? 'all')}\n type=\"button\"\n role=\"tab\"\n className=\"ss-w-ecard-tab\"\n aria-selected={i === active}\n aria-label={s.label}\n title={s.label}\n onClick={() => setActive(i)}\n >\n {s.image ? <Crest image={s.image} /> : s.label}\n </button>\n ))}\n {season}\n </div>\n <StatRows key={String(current.competitionId ?? 'all')} stats={current.stats} />\n </div>\n )\n}\n\nfunction EntityCardItem({ c }: { c: CardVM }): JSX.Element {\n const hasBody = c.scopes.length > 0\n return (\n <div className={hasBody ? 'ss-w-ecard' : 'ss-w-ecard ss-w-ecard-bare'} data-kind={c.kind}>\n <div className=\"ss-w-ecard-id\">\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 </div>\n <CardBody c={c} />\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 { useState } from 'react'\nimport type { InsightVM, StatCell } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { AddToSlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\n\nfunction StatRows({ stats }: { stats: StatCell[] }): JSX.Element {\n return (\n <div className=\"ss-w-bi-rows\">\n {stats.map((s) => (\n <div key={`${s.label}:${s.value}`} className=\"ss-w-bi-row\">\n <span className=\"ss-w-bi-row-lbl\">{s.label}</span>\n <span className=\"ss-w-bi-row-num\">{s.value}</span>\n </div>\n ))}\n </div>\n )\n}\n\nfunction ScopedStats({ scopes }: { scopes: NonNullable<InsightVM['scopes']> }): JSX.Element {\n const [active, setActive] = useState(0)\n const current = scopes[active] ?? scopes[0] ?? { key: '', label: '', stats: [] }\n return (\n <div className=\"ss-w-bi-scoped\">\n <div className=\"ss-w-bi-scopes\" role=\"group\">\n {scopes.map((s, i) => (\n <button key={s.key} type=\"button\" className=\"ss-w-bi-chip\" aria-pressed={i === active} onClick={() => setActive(i)}>\n {s.label}\n </button>\n ))}\n </div>\n <StatRows key={current.key} stats={current.stats} />\n </div>\n )\n}\n\nfunction hasStatsContent(it: InsightVM): boolean {\n return (!!it.scopes && it.scopes.length >= 2) || it.stats.length > 0\n}\n\n// The reason-to-bet prose is clamped to two lines; one right-chevron expands it to the full text\n// AND the supporting stats together (the mock's single \">\" affordance). Collapsed by default so the\n// card stays scannable. The arrow only appears when there is something more to reveal — stats, or a\n// reason long enough to be clamped.\nfunction ReasonStrip({ it, ui }: { it: InsightVM; ui?: UiConfig }): JSX.Element | null {\n const [open, setOpen] = useState(false)\n const hasScopes = !!it.scopes && it.scopes.length >= 2\n const hasStats = hasStatsContent(it)\n const hasText = !!it.text\n if (!hasText && !hasStats) return null\n const expandable = hasStats || (it.text?.length ?? 0) > 90\n return (\n <div className=\"ss-w-bi-reason\">\n <span className=\"ss-w-bi-chart\" aria-hidden=\"true\" />\n <div className=\"ss-w-bi-reason-body\">\n {hasText ? <p className={`ss-w-bi-text${open ? '' : ' ss-w-bi-text-clamp'}`}>{it.text}</p> : null}\n {open && hasStats ? (hasScopes ? <ScopedStats scopes={it.scopes!} /> : <StatRows stats={it.stats} />) : null}\n </div>\n {expandable ? (\n <button\n type=\"button\"\n className=\"ss-w-bi-expand\"\n aria-expanded={open}\n aria-label={open ? ui?.hideStats ?? 'Hide stats' : ui?.showStats ?? 'Show stats'}\n onClick={() => setOpen((v) => !v)}\n >\n <span className={`ss-w-bi-arrow${open ? ' ss-w-bi-arrow-open' : ''}`} aria-hidden=\"true\" />\n </button>\n ) : null}\n </div>\n )\n}\n\nfunction InsightCard({ it, ui, slip }: { it: InsightVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const live = it.isLive || it.phase === 'live'\n const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : undefined\n const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName\n const showHeader = !!it.competition || live || !!kickoff\n return (\n <div className=\"ss-w-binsight\">\n {showHeader ? (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-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-header-right\">\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.dayLabel} {kickoff.time}</span> : null}\n </span>\n </div>\n ) : null}\n <div className=\"ss-w-bi-body\">\n <div className=\"ss-w-bi-fixture\">\n {hasNamedTeams ? (\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 ) : it.fixture ? (\n <span className=\"ss-w-bi-fixture-txt\">{it.fixture}</span>\n ) : null}\n </div>\n <div className=\"ss-w-bi-action\">\n <span className=\"ss-w-bi-mkt\">\n <span className=\"ss-w-bi-market\">{it.market}</span>\n {it.selection ? <span className=\"ss-w-bi-sel\">{it.selection}</span> : null}\n </span>\n {it.isMarketFloor ? (\n <span className=\"ss-w-bi-floor\">{ui?.marketFloorLabel ?? 'Market price · not a value pick'}</span>\n ) : 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 <AddToSlipButton it={it} slip={slip} ui={ui} />\n </div>\n </div>\n <ReasonStrip it={it} ui={ui} />\n {it.disclaimer ? <p className=\"ss-w-bi-disc\">{it.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function BettingInsightList({ insights, ui, slip }: { insights: InsightVM[]; ui?: UiConfig; slip: SlipHandlerProps }): 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} />)}\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, wasAdded, type SlipHandlerProps, type SlipToast } from '../slip'\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, marketName, slip, ui }:\n { selection: SlipSelection | null; shownOdds: string; marketName: string; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n const [pending, setPending] = useState(false)\n const [settled, setSettled] = useState(false)\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n\n const handler = slip.onAddToSlip\n if (!ui || !handler || !selection) return null\n\n const onClick = async (): Promise<void> => {\n setPending(true)\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 setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui))\n setSettled(isTerminal(result))\n if (wasAdded(result) && slip.onMarketClicked) {\n try {\n slip.onMarketClicked(marketName)\n } catch {\n // Telemetry must never change what the user sees.\n }\n }\n } catch {\n setToast({ kind: 'error', text: ui.slipFailed })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"ss-w-slip\">\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 <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 <SlipButton selection={selection} shownOdds={it.odds ?? ''} marketName={it.market} slip={slip} ui={ui} />\n}\n","import type { AddToSlipHandler, AddToSlipResult } 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 onMarketClicked?: (marketName: string) => void\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\nexport function resultToToast(result: AddToSlipResult | void, shownOdds: string, ui: UiConfig): SlipToast {\n if (!result) return { kind: 'success', text: ui.slipAdded(undefined) }\n switch (result.status) {\n case 'added':\n return { kind: 'success', text: ui.slipAdded(result.slip?.selectionCount) }\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 { 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 { useState } from 'react'\nimport type { MarketOddsVM, MarketOddsRowVM } from '../model'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\n\nfunction OddsRow({ vm, row, ui, slip }: { vm: MarketOddsVM; row: MarketOddsRowVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null\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 <SlipButton selection={selection} shownOdds={row.odds} marketName={vm.market} slip={slip} ui={ui} />\n </div>\n )\n}\n\nfunction MarketOddsCard({ vm, ui, slip }: { vm: MarketOddsVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const [open, setOpen] = useState(false)\n const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName\n const showHeader = !!vm.competition || vm.isLive || !!kickoff\n return (\n <div className=\"ss-w-mocard\">\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.dayLabel} {kickoff.time}</span> : null}\n </span>\n </div>\n ) : null}\n {(hasNamedTeams || vm.fixture || vm.market) ? (\n <div className=\"ss-w-mo-sub\">\n {hasNamedTeams ? (\n <div 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 </div>\n ) : vm.fixture ? <span className=\"ss-w-mo-teams\">{vm.fixture}</span> : null}\n {vm.market ? <span className=\"ss-w-mo-market\">{vm.market}</span> : null}\n </div>\n ) : 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} />)}\n {open ? vm.moreRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} />) : 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({ cards, ui, slip }: { cards: MarketOddsVM[]; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-mocards\">\n {cards.map((vm) => <MarketOddsCard key={vm.id} vm={vm} ui={ui} slip={slip} />)}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\nimport type { OddsMovementVM } from '../model'\nimport { CHART_VIEW_H, CHART_VIEW_W } from '../chart'\nimport { OddsMovementBadge } from './OddsMovementBadge'\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({ vm, ui }: { vm: OddsMovementVM; ui?: UiConfig }): 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\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 </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({ cards, ui }: { cards: OddsMovementVM[]; ui?: UiConfig }): 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} />)}\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\nexport function DashboardTile({ tile, onTap }: { tile: GreetingDashboardTile; onTap: () => void }): JSX.Element {\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 }: { dashboard: GreetingDashboardData; onTap: (tile: GreetingDashboardTileData, index: number) => void }): 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)} />\n ))}\n </div>\n {dashboard.footerTip ? <span className=\"ss-w-dash-foot\">{dashboard.footerTip}</span> : null}\n </div>\n )\n}\n","import type { ClubGreetingHeaderBlock } from '@sensiblestats/widget-sdk'\n\nexport function GreetingHeaderBlock({ block }: { block: ClubGreetingHeaderBlock }): JSX.Element {\n return (\n <div className=\"ss-w-cdash-greeting\">\n <div className=\"ss-w-cdash-greeting-title\">{block.title}</div>\n <div className=\"ss-w-cdash-greeting-subtitle\">{block.subtitle}</div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { ClubFixtureHeroBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nfunction initials(name: string): string {\n return name.split(/\\s+/).filter(Boolean).slice(0, 2).map((w) => w[0]!.toUpperCase()).join('')\n}\n\nfunction Crest({ url, name }: { url?: string | null; name: string }): JSX.Element {\n const [broken, setBroken] = useState(false)\n if (!url || broken) {\n return (\n <span className=\"ss-w-cdash-crest ss-w-cdash-crest--fallback\" aria-hidden=\"true\">\n {initials(name)}\n </span>\n )\n }\n return <img className=\"ss-w-cdash-crest\" src={url} alt=\"\" aria-hidden=\"true\" onError={() => setBroken(true)} />\n}\n\nexport function FixtureHeroBlock({\n block,\n ui,\n onAction,\n}: {\n block: ClubFixtureHeroBlock\n ui: UiConfig\n onAction: (label: string, opts: { actionRef: string }) => void\n}): JSX.Element {\n return (\n <div className=\"ss-w-cdash-fixture\">\n <div className=\"ss-w-cdash-tie\">\n <Crest url={block.homeCrestUrl} name={block.homeName} />\n <span className=\"ss-w-cdash-team\">{block.homeName}</span>\n <span className=\"ss-w-cdash-vs\">v</span>\n <span className=\"ss-w-cdash-team\">{block.awayName}</span>\n <Crest url={block.awayCrestUrl} name={block.awayName} />\n </div>\n <div className=\"ss-w-cdash-fixture-meta\">\n <span className=\"ss-w-cdash-kickoff\">{ui.clubKickoff(block.kickoffUnix * 1000)}</span>\n {block.venue ? <span className=\"ss-w-cdash-venue\">{block.venue}</span> : null}\n {block.competition ? <span className=\"ss-w-cdash-comp\">{block.competition}</span> : null}\n </div>\n {/* The tap sends the opaque actionRef the backend minted for this CTA -- no prose\n command, no grounding metadata. ctaLabel doubles as both the wire `message`\n (the display bubble) and the button text, per the predefined-action-contract\n wire shape: { message: <label>, actionRef, conversationId }. */}\n <button type=\"button\" className=\"ss-w-cdash-cta\" onClick={() => onAction(block.ctaLabel, { actionRef: block.ctaActionRef })}>\n {block.ctaLabel}\n </button>\n </div>\n )\n}\n","export function ResultPills({ results }: { results: string[] }): JSX.Element {\n return (\n <>\n {results.map((r, i) => (\n <span key={i} className={`ss-w-cdash-pill ss-w-cdash-pill--${r.toLowerCase()}`}>\n {r}\n </span>\n ))}\n </>\n )\n}\n","import type { ClubFormGuideBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { ResultPills } from './ResultPills'\n\nexport function FormGuideBlock({ block }: { block: ClubFormGuideBlock; ui: UiConfig }): JSX.Element | null {\n if (block.rows.length === 0) return null\n return (\n <div className=\"ss-w-cdash-form\">\n {block.rows.map((row) => (\n <div className=\"ss-w-cdash-form-row\" key={row.name}>\n <span className=\"ss-w-cdash-form-name\">\n {row.name}\n {row.position != null ? ` #${row.position}` : ''}\n </span>\n <span className=\"ss-w-cdash-form-pills\">\n <ResultPills results={row.last5} />\n </span>\n </div>\n ))}\n </div>\n )\n}\n","import type { ClubMatchPreviewBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nexport function MatchPreviewBlock({\n block,\n ui,\n onAction,\n}: {\n block: ClubMatchPreviewBlock\n ui: UiConfig\n onAction: (label: string, opts: { actionRef: string }) => void\n}): JSX.Element | null {\n if (block.facts.length === 0) return null\n const heading = ui.clubMatchPreviewHeading\n return (\n <div className=\"ss-w-cdash-lines\">\n <span className=\"ss-w-cdash-lines-heading\">{heading}</span>\n {block.facts.map((f, i) =>\n f.actionRef ? (\n <button\n key={i}\n type=\"button\"\n className=\"ss-w-cdash-fact\"\n onClick={() => onAction(f.label ?? f.sentence, { actionRef: f.actionRef! })}\n >\n {f.sentence}\n {f.label ? <span className=\"ss-w-cdash-fact-label\"> {f.label}</span> : null}\n </button>\n ) : (\n <p key={i}>{f.sentence}</p>\n ),\n )}\n </div>\n )\n}\n","import type { ClubMatchPreviewCardBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { ResultPills } from './ResultPills'\n\nfunction position(p?: number): string {\n return p != null ? `#${p}` : '—'\n}\n\nexport function MatchPreviewCardBlock({ block }: { block: ClubMatchPreviewCardBlock; ui: UiConfig }): JSX.Element {\n return (\n <div className=\"ss-w-cdash-preview\">\n <div className=\"ss-w-cdash-preview-header\">\n <span className=\"ss-w-cdash-team\">{block.homeName}</span>\n <span className=\"ss-w-cdash-vs\">v</span>\n <span className=\"ss-w-cdash-team\">{block.awayName}</span>\n </div>\n <div className=\"ss-w-cdash-preview-row\">\n <span className=\"ss-w-cdash-preview-value\">{position(block.homePosition)}</span>\n <span className=\"ss-w-cdash-preview-label\">{block.tableLabel}</span>\n <span className=\"ss-w-cdash-preview-value\">{position(block.awayPosition)}</span>\n </div>\n <div className=\"ss-w-cdash-preview-row\">\n <span className=\"ss-w-cdash-preview-pills\">\n <ResultPills results={block.homeLast5} />\n </span>\n <span className=\"ss-w-cdash-preview-label\">{block.last5Label}</span>\n <span className=\"ss-w-cdash-preview-pills\">\n <ResultPills results={block.awayLast5} />\n </span>\n </div>\n {block.edgeTeamName ? (\n <div className=\"ss-w-cdash-preview-edge\">\n <span aria-hidden=\"true\">▸</span>\n <strong>{block.edgeTeamName}</strong>\n {block.edgeReason ? <span> — {block.edgeReason}</span> : null}\n </div>\n ) : null}\n {block.h2HLines.length > 0 ? (\n <div className=\"ss-w-cdash-preview-h2h\">\n {block.h2HLines.map((line, i) => (\n <p key={i}>{line}</p>\n ))}\n </div>\n ) : null}\n </div>\n )\n}\n","import type { ClubTeamDnaBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nexport function TeamDnaBlock({\n block,\n ui,\n onAction,\n}: {\n block: ClubTeamDnaBlock\n ui: UiConfig\n onAction: (label: string, opts: { actionRef: string }) => void\n}): JSX.Element | null {\n if (block.facts.length === 0) return null\n const heading = ui.clubTeamDnaHeading\n return (\n <div className=\"ss-w-cdash-lines\">\n <span className=\"ss-w-cdash-lines-heading\">{heading}</span>\n {block.facts.map((f, i) =>\n f.actionRef ? (\n <button\n key={i}\n type=\"button\"\n className=\"ss-w-cdash-fact\"\n onClick={() => onAction(f.label ?? f.sentence, { actionRef: f.actionRef! })}\n >\n {f.sentence}\n {f.label ? <span className=\"ss-w-cdash-fact-label\"> {f.label}</span> : null}\n </button>\n ) : (\n <p key={i}>{f.sentence}</p>\n ),\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { ClubCountdownBlock } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nconst DAY_MS = 24 * 3600 * 1000\n\nfunction pad2(n: number): string {\n return String(n).padStart(2, '0')\n}\n\nfunction splitRemaining(remainingMs: number): { h: string; m: string; s: string } {\n const totalSeconds = Math.max(0, Math.floor(remainingMs / 1000))\n const h = Math.floor(totalSeconds / 3600)\n const m = Math.floor((totalSeconds % 3600) / 60)\n const s = totalSeconds % 60\n return { h: pad2(h), m: pad2(m), s: pad2(s) }\n}\n\nexport function CountdownBlock({ block, ui }: { block: ClubCountdownBlock; ui: UiConfig }): JSX.Element | null {\n const [remainingMs, setRemainingMs] = useState(() => block.kickoffUnix * 1000 - Date.now())\n\n useEffect(() => {\n setRemainingMs(block.kickoffUnix * 1000 - Date.now())\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n const id = setInterval(() => {\n setRemainingMs(block.kickoffUnix * 1000 - Date.now())\n }, 1000)\n return () => clearInterval(id)\n }, [block.kickoffUnix])\n\n if (remainingMs <= 0) return null\n if (remainingMs > DAY_MS) return null\n\n const { h, m, s } = splitRemaining(remainingMs)\n\n return (\n <div className=\"ss-w-cdash-cd\" aria-label={ui.clubKickoffAria(block.kickoffUnix * 1000)}>\n <div className=\"ss-w-cdash-cd-clock\" aria-hidden=\"true\">\n <span className=\"ss-w-cdash-cd-h\">{h}</span>h{' '}\n <span className=\"ss-w-cdash-cd-m\">{m}</span>m{' '}\n <span className=\"ss-w-cdash-cd-s\">{s}</span>s\n </div>\n <div className=\"ss-w-cdash-cd-label\">{ui.clubCountdownLabel}</div>\n </div>\n )\n}\n","import type { FC } from 'react'\nimport type { ClubDashboardBlock, ClubDashboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { GreetingHeaderBlock } from './GreetingHeaderBlock'\nimport { FixtureHeroBlock } from './FixtureHeroBlock'\nimport { FormGuideBlock } from './FormGuideBlock'\nimport { MatchPreviewBlock } from './MatchPreviewBlock'\nimport { MatchPreviewCardBlock } from './MatchPreviewCardBlock'\nimport { TeamDnaBlock } from './TeamDnaBlock'\nimport { CountdownBlock } from './CountdownBlock'\n\ntype BlockProps = { block: ClubDashboardBlock; ui: UiConfig; onAction: (label: string, opts: { actionRef: string }) => void }\n\n// Open registry: future block types register here — the container stays club-dashboard-agnostic.\nexport const CLUB_BLOCK_REGISTRY: Partial<Record<ClubDashboardBlock['type'], FC<BlockProps>>> = {\n greetingHeader: ({ block }) => (block.type === 'greetingHeader' ? <GreetingHeaderBlock block={block} /> : null),\n fixtureHero: ({ block, ui, onAction }) => (block.type === 'fixtureHero' ? <FixtureHeroBlock block={block} ui={ui} onAction={onAction} /> : null),\n formGuide: ({ block, ui }) => (block.type === 'formGuide' ? <FormGuideBlock block={block} ui={ui} /> : null),\n matchPreview: ({ block, ui, onAction }) => (block.type === 'matchPreview' ? <MatchPreviewBlock block={block} ui={ui} onAction={onAction} /> : null),\n matchPreviewCard: ({ block, ui }) => (block.type === 'matchPreviewCard' ? <MatchPreviewCardBlock block={block} ui={ui} /> : null),\n teamDna: ({ block, ui, onAction }) => (block.type === 'teamDna' ? <TeamDnaBlock block={block} ui={ui} onAction={onAction} /> : null),\n countdown: ({ block, ui }) => (block.type === 'countdown' ? <CountdownBlock block={block} ui={ui} /> : null),\n}\n\nexport function ClubDashboard({\n dashboard,\n ui,\n onAction,\n}: {\n dashboard: ClubDashboardPayload\n ui: UiConfig\n onAction: (label: string, opts: { actionRef: string }) => void\n}): JSX.Element | null {\n if (!dashboard.blocks.length) return null\n return (\n <div className=\"ss-w-cdash\">\n {dashboard.blocks.map((block, i) => {\n const Comp = Object.prototype.hasOwnProperty.call(CLUB_BLOCK_REGISTRY, block.type)\n ? CLUB_BLOCK_REGISTRY[block.type]\n : undefined\n if (!Comp) {\n // Safe in the browser-injected bundle: there is no `process` global and tsup defines no\n // NODE_ENV, so a `process.env.NODE_ENV` gate would throw ReferenceError at render. An\n // unknown block type is a rare version-skew event, so one console.warn is the Q3\n // observability signal without a telemetry surface (ruling: warn-always over dev-only,\n // since this build has no feasible dev/prod signal).\n console.warn(`[club-dashboard] no renderer for block type \"${block.type}\"`)\n return null\n }\n return (\n <div key={i} className=\"ss-w-cdash-block\">\n <Comp block={block} ui={ui} onAction={onAction} />\n </div>\n )\n })}\n </div>\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 { Markdown } from './Markdown'\nimport { EntityCardList } from './EntityCardList'\nimport { BettingInsightList } from './BettingInsightList'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { ActionButtons } from './ActionButtons'\nimport { GreetingDashboard } from './dashboard/GreetingDashboard'\nimport { ClubDashboard } from './club-dashboard/ClubDashboard'\n\nexport function ChatMessage({ message, disabled, onAct, onTap, onClubAction, ui, slip }: { message: Message; disabled: boolean; onAct: (a: ActionVM) => void; onTap: (tile: GreetingDashboardTile, index: number) => void; onClubAction: (label: string, opts: { actionRef: string }) => void; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n if (message.role === 'user') {\n return <div className=\"ss-w-msg ss-w-user\"><div className=\"ss-w-bubble\">{message.text}</div></div>\n }\n return (\n <div className=\"ss-w-msg ss-w-bot\">\n {/* A greeting dashboard or a club dashboard carries its own title, which is the turn's\n single heading; the streamed line would duplicate it, so it is suppressed whenever\n either is present. Ordinary answers (no dashboard) render their text as before. */}\n {message.text && !message.greetingDashboard && !message.clubDashboard ? <Markdown text={message.text} /> : null}\n {message.greetingDashboard ? <GreetingDashboard dashboard={message.greetingDashboard} onTap={onTap} /> : null}\n {message.clubDashboard && ui ? <ClubDashboard dashboard={message.clubDashboard} ui={ui} onAction={onClubAction} /> : null}\n <EntityCardList cards={message.cards} disabled={disabled} showLessLabel={ui?.showLess} showMoreLabel={ui?.showMore} />\n <BettingInsightList insights={message.insights} ui={ui} slip={slip} />\n <MarketOddsCardList cards={message.marketOdds} ui={ui} slip={slip} />\n <OddsMovementCardList cards={message.oddsMovement} ui={ui} />\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","// 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-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 }\\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}\\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}\\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; }\\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 { 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\\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; }\\n.ss-w-header-title { font-weight: 660; }\\n.ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n\\n/* messages */\\n.ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }\\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/* Identity Hero: crest-led identity block | tabbed stats panel */\\n.ss-w-ecard { display: grid; grid-template-columns: 112px 1fr; align-items: stretch; 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-id { display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; padding: 13px 10px; border-right: 1px solid var(--ss-w-line); background: linear-gradient(158deg, var(--ss-w-bubble), color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-bubble))); }\\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-id { flex-direction: row; text-align: left; gap: 11px; background: none; border-right: none; padding: 10px 12px; }\\n.ss-w-ecard-bare .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }\\n.ss-w-ecard-bare .ss-w-thumb.ss-w-team { border-radius: 10px; }\\n\\n.ss-w-ecard-body { min-width: 0; padding: 9px 12px 12px; display: flex; flex-direction: column; }\\n\\n/* tab strip seated on the stats panel's top edge; active tab underlined in accent */\\n.ss-w-ecard-tabs { display: flex; align-items: stretch; gap: 3px; border-bottom: 1px solid var(--ss-w-line); margin-bottom: 9px; flex-wrap: wrap; }\\n.ss-w-ecard-tab { 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: 5px 8px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }\\n.ss-w-ecard-tab[aria-selected=\\\"true\\\"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-ecard-tabs-static { align-items: center; flex-wrap: nowrap; }\\n.ss-w-ecard-lead { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 640; color: var(--ss-w-ink); padding: 4px 2px 8px; min-width: 0; flex: 1; }\\n.ss-w-ecard-lead-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\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.ss-w-ecard-tabs-static .ss-w-ecard-season { margin-bottom: 4px; }\\n\\n.ss-w-ecard-stats { display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-ecard-row { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; }\\n.ss-w-ecard-rlabel { font-size: 9.5px; text-transform: uppercase; letter-spacing: .045em; color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-ecard-rval { justify-self: end; font-size: 15px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }\\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/* row 1: competition logo + name on the left, live badge + kickoff on the right */\\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; }\\n.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\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/* row 2: crest-flanked fixture on the left, boxed action panel on the right */\\n.ss-w-bi-body { display: flex; align-items: center; gap: 10px; }\\n.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12px; font-weight: 650; color: var(--ss-w-ink); }\\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.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }\\n.ss-w-bi-action .ss-w-slip { width: 100%; }\\n.ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }\\n/* The action column is narrow; let its toast size to its own text and anchor to the card's right edge instead of being clipped to the button width. */\\n.ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }\\n.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }\\n.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }\\n.ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }\\n.ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }\\n.ss-w-bi-odds b { font-size: 23px; 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\\n/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, 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-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }\\n.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\\n.ss-w-bi-expand { flex: none; align-self: center; display: grid; place-items: center; width: 22px; height: 22px; margin: -2px -4px -2px 0; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-bi-expand:hover { color: var(--ss-w-ink); }\\n.ss-w-bi-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); transition: transform .15s ease; }\\n.ss-w-bi-arrow-open { transform: rotate(135deg); }\\n.ss-w-bi-rows { display: flex; flex-direction: column; }\\n.ss-w-bi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-bi-row:first-child { border-top: none; }\\n.ss-w-bi-row-lbl { font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; flex: none; color: var(--ss-w-ink); }\\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n.ss-w-bi-scoped { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-bi-scopes { display: inline-flex; align-items: center; gap: 2px; flex-wrap: wrap; align-self: flex-start; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 2px; }\\n.ss-w-bi-chip { font-size: 11px; font-weight: 600; border: none; border-radius: 7px; padding: 4px 10px; color: var(--ss-w-faint); background: none; cursor: pointer; }\\n.ss-w-bi-chip[aria-pressed=\\\"true\\\"] { color: var(--ss-w-ink); background: var(--ss-w-panel); box-shadow: 0 1px 2px rgba(0,0,0,.08); }\\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.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 { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }\\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.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); }\\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; }\\n.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }\\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.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; }\\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; }\\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.ss-w-toast { position: absolute; top: calc(100% + 6px); left: 0; z-index: 1; max-width: 100%; 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@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.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: #eef8f1; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }\\n\\n/* club match-day dashboard */\\n.ss-w-cdash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }\\n.ss-w-cdash-block { display: flex; flex-direction: column; }\\n\\n.ss-w-cdash-greeting { display: flex; flex-direction: column; gap: 2px; }\\n.ss-w-cdash-greeting-title { font-weight: 700; font-size: 14px; color: var(--ss-w-ink); }\\n.ss-w-cdash-greeting-subtitle { font-size: 11.5px; color: var(--ss-w-faint); }\\n\\n.ss-w-cdash-fixture { display: flex; flex-direction: column; align-items: center; gap: 8px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 12px; text-align: center; }\\n.ss-w-cdash-tie { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }\\n.ss-w-cdash-team { font-weight: 650; font-size: 13px; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }\\n.ss-w-cdash-vs { font-size: 11px; color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-cdash-crest { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--ss-w-bubble); }\\n.ss-w-cdash-crest--fallback { display: grid; place-items: center; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n.ss-w-cdash-fixture-meta { display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-cdash-kickoff { font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-cdash-cta { font: inherit; font-weight: 700; font-size: 12px; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: none; border-radius: 999px; padding: 8px 18px; cursor: pointer; }\\n\\n.ss-w-cdash-form { display: flex; flex-direction: column; gap: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; }\\n.ss-w-cdash-form-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\\n.ss-w-cdash-form-name { font-size: 12px; font-weight: 600; color: var(--ss-w-ink); min-width: 0; overflow-wrap: anywhere; }\\n.ss-w-cdash-form-pills { flex: none; display: flex; align-items: center; gap: 3px; }\\n.ss-w-cdash-pill { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; font-size: 9.5px; font-weight: 700; color: #fff; }\\n.ss-w-cdash-pill--w { background: color-mix(in srgb, var(--ss-w-pos) 88%, black); }\\n.ss-w-cdash-pill--d { background: var(--ss-w-faint); }\\n.ss-w-cdash-pill--l { background: color-mix(in srgb, var(--ss-w-neg) 88%, black); }\\n\\n.ss-w-cdash-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; text-align: left; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; padding: 10px 12px; }\\n.ss-w-cdash-lines-heading { font-size: 12px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-cdash-lines p { font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); margin: 0; }\\n.ss-w-cdash-fact { display: block; width: 100%; text-align: left; font: inherit; font-size: 12px; line-height: 1.4; color: var(--ss-w-ink); background: none; border: none; padding: 0; cursor: pointer; }\\n.ss-w-cdash-fact:hover, .ss-w-cdash-fact:focus-visible { color: var(--ss-w-accent); text-decoration: underline; }\\n.ss-w-cdash-fact-label { font-size: 11px; font-weight: 700; color: var(--ss-w-accent); }\\n\\n.ss-w-cdash-cd { display: flex; flex-direction: column; align-items: center; gap: 4px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; text-align: center; }\\n.ss-w-cdash-cd-clock { display: flex; align-items: baseline; justify-content: center; gap: 2px; font-variant-numeric: tabular-nums; font-family: ui-monospace, \\\"SFMono-Regular\\\", Menlo, monospace; font-weight: 700; font-size: 18px; color: var(--ss-w-ink); }\\n.ss-w-cdash-cd-h, .ss-w-cdash-cd-m, .ss-w-cdash-cd-s { color: var(--ss-w-accent); }\\n.ss-w-cdash-cd-label { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); }\\n\\n.ss-w-cdash-preview { display: flex; flex-direction: column; gap: 8px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 10px 12px; }\\n.ss-w-cdash-preview-header { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 6px; }\\n.ss-w-cdash-preview-header .ss-w-cdash-team:first-child { justify-self: start; text-align: left; }\\n.ss-w-cdash-preview-header .ss-w-cdash-team:last-child { justify-self: end; text-align: right; }\\n.ss-w-cdash-preview-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px; }\\n.ss-w-cdash-preview-label { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); text-align: center; text-transform: uppercase; letter-spacing: 0.03em; }\\n.ss-w-cdash-preview-value { font-size: 12px; font-weight: 700; color: var(--ss-w-ink); text-align: center; }\\n.ss-w-cdash-preview-pills { display: flex; align-items: center; justify-content: center; gap: 3px; }\\n.ss-w-cdash-preview-row:first-of-type .ss-w-cdash-preview-value { justify-self: start; }\\n.ss-w-cdash-preview-row:first-of-type .ss-w-cdash-preview-value:last-child { justify-self: end; }\\n.ss-w-cdash-preview-row:last-of-type .ss-w-cdash-preview-pills:first-child { justify-self: start; }\\n.ss-w-cdash-preview-row:last-of-type .ss-w-cdash-preview-pills:last-child { justify-self: end; }\\n.ss-w-cdash-preview-edge { display: flex; align-items: baseline; gap: 4px; font-size: 12px; line-height: 1.4; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 8px; padding: 6px 8px; }\\n.ss-w-cdash-preview-edge strong { color: var(--ss-w-ink); }\\n.ss-w-cdash-preview-h2h { display: flex; flex-direction: column; gap: 2px; }\\n.ss-w-cdash-preview-h2h p { font-size: 11.5px; line-height: 1.4; color: var(--ss-w-faint); margin: 0; }\\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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","names":["import_react","import_widget_sdk","import_widget_sdk","import_widget_sdk","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","ReactMarkdown","remarkGfm","import_react","import_jsx_runtime","import_react","import_react","import_widget_sdk","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","directionWord","import_react","import_jsx_runtime","initials","Crest","import_jsx_runtime","StatRows","Crest","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","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","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/dashboardTap.ts","../src/theme.ts","../src/useChatStream.ts","../src/reducer.ts","../src/chart.ts","../src/model.ts","../src/assets/logo.ts","../src/components/Icons.tsx","../src/components/GreetingBubble.tsx","../src/components/ChatFab.tsx","../src/components/ChatPanel.tsx","../src/components/ChatHeader.tsx","../src/components/MessageList.tsx","../src/components/Markdown.tsx","../src/components/EntityCardList.tsx","../src/components/BettingInsightList.tsx","../src/components/AddToSlipButton.tsx","../src/slip.ts","../src/components/Toast.tsx","../src/components/OddsMovementBadge.tsx","../src/components/Crest.tsx","../src/components/MarketOddsCardList.tsx","../src/components/OddsMovementCard.tsx","../src/components/ActionButtons.tsx","../src/components/dashboard/DashboardTile.tsx","../src/components/dashboard/GreetingDashboard.tsx","../src/components/ChatMessage.tsx","../src/components/IntentChips.tsx","../src/scroll.ts","../src/components/ChatInput.tsx","../src/styles/css.generated.ts"],"sourcesContent":["export { StatsWidget } from './StatsWidget'\nexport type { StatsWidgetProps } from './StatsWidget'\nexport type { StatsWidgetConfig } from './config'\nexport { WIDGET_CSS } from './styles/css.generated'\n","import { useEffect, useMemo, useRef, type CSSProperties } from 'react'\nimport { StatsWidgetClient, type Conversation } from '@sensiblestats/widget-sdk'\nimport { normalizeUi, toClientOptions, toUserContext, type StatsWidgetConfig } from './config'\nimport type { SlipHandlerProps } from './slip'\nimport { createDashboardTapSignal } from './dashboardTap'\nimport { themeAttrs } from './theme'\nimport { useChatStream } from './useChatStream'\nimport { ChatFab } from './components/ChatFab'\nimport { ChatPanel } from './components/ChatPanel'\nimport { WIDGET_CSS } from './styles/css.generated'\n\nexport type StatsWidgetProps =\n | { config: StatsWidgetConfig; client?: never }\n | { client: StatsWidgetClient; config?: Omit<StatsWidgetConfig, 'operatorId' | 'publicKey' | 'baseUrl' | 'userContext'> }\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 const ui = useMemo(() => normalizeUi((props.config ?? { operatorId: '', publicKey: '' }) as StatsWidgetConfig), [props.config])\n const rootRef = useRef<HTMLDivElement>(null)\n const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : undefined)\n const slip = useMemo<SlipHandlerProps>(\n () => ({\n onAddToSlip: props.config?.onAddToSlip,\n conversationId: controller.state.conversationId ?? undefined,\n onMarketClicked: (marketName) => {\n // sendSignal throws synchronously with no operatorUserId configured, and its\n // returned promise can reject on a gateway failure. Neither should ever break\n // the add-to-slip flow for a host that never wired signal tracking.\n try {\n void built?.conversation\n .sendSignal({ signalType: 'InsightMarketClicked', entityType: 'Market', entityName: marketName })\n .catch(() => undefined)\n } catch {\n // ignored — see comment above\n }\n },\n }),\n [props.config?.onAddToSlip, controller.state.conversationId, built],\n )\n const onDashboardTap = useMemo(\n () => (built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input)) : undefined),\n [built],\n )\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 <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 controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} />\n ) : (\n <ChatFab\n label={ui.launcherLabel}\n greeting={ui.greeting}\n popupText={controller.state.popupText}\n onOpen={controller.open}\n onDismissPopup={controller.dismissPopup}\n dismissLabel={ui.dismissGreeting}\n />\n )}\n </div>\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\nexport interface LocaleStrings {\n launcherLabel: string\n placeholder: string\n closeChat: 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 showStats: string\n hideStats: 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: (n?: number) => 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}\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 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 showStats: 'Show stats',\n hideStats: 'Hide stats',\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: (n) => (n === undefined ? 'Added to slip' : `Added to slip (${n} selection${n === 1 ? '' : 's'})`),\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 },\n tr: {\n launcherLabel: 'SensibleStats ile sohbet et',\n placeholder: 'Bir takım, oyuncu veya maç hakkında sor…',\n closeChat: 'Sohbeti kapat',\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 showStats: 'İstatistikleri göster',\n hideStats: 'İstatistikleri gizle',\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: (n) => (n === undefined ? 'Kupona eklendi' : `Kupona eklendi (${n} seçim)`),\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 },\n}\n\nexport function resolveLocaleStrings(locale?: string): LocaleStrings {\n return STRINGS[locale as Locale] ?? STRINGS.en\n}\n","import type { AddToSlipHandler, StatsWidgetClientOptions, UserContext } from '@sensiblestats/widget-sdk'\nimport { resolveLocaleStrings } 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}\n\ntype UiKeys =\n | 'theme' | 'accent' | 'position' | 'offset' | 'radius' | 'locale'\n | 'launcherLabel' | 'greeting' | 'greetingMessage' | 'placeholder' | 'starters' | 'injectStyles'\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 closeChat: 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 showStats: string\n hideStats: 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: (n?: number) => 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}\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 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 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 showStats: strings.showStats,\n hideStats: strings.hideStats,\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 }\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 { ENTITY_TYPE_CODES, type Conversation, type GreetingDashboardLayout, type GreetingDashboardTile, type SignalEntityType } 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/**\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 */\nexport function createDashboardTapSignal(sendSignal: Conversation['sendSignal']): DashboardTapHandler {\n return (tile, index, layout) => {\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 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 { ChatHandle, ChatInput, Conversation } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { reducer, initialState, type WidgetState } from './reducer'\nimport { chipFromText } from './model'\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\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}\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}\n\nexport function useChatStream(conversation: Conversation, starterTexts: string[], greetingMessage?: string): ChatController {\n const seed = useMemo(() => initialState(starterTexts.map(chipFromText)), [])\n const [state, dispatch] = useReducer(reducer, seed)\n const idRef = useRef(0)\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(false)\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 }, 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. No user bubble; its response\n // becomes the launcher popup. Fire-and-forget — failures (including a fallback timeout)\n // are swallowed (STOP only, no visible error) since this is non-critical background chatter.\n useEffect(() => {\n const message = greetingMessage?.trim()\n if (!message || greetedRef.current) return\n greetedRef.current = true\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 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 return { state, open, close, stop, toggle, send, retry, dismissPopup }\n}\n","import type { ChatEvent, ChatInput, 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 }\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 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\nconst POPUP_MAX = 160\n\nexport function initialState(starters: ChipVM[]): WidgetState {\n return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, 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 const text = active?.text.trim() ?? ''\n // A completed greeting turn surfaces its answer as the launcher popup (unless already open).\n const popupText = active?.isGreeting && !state.isOpen && text ? text.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 })),\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 '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 }\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; message: string }\nexport interface ChipVM { text: string }\nexport interface InsightScope { key: string; label: string; stats: StatCell[] }\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 scopes?: InsightScope[]\n text: string\n stats: StatCell[]\n disclaimer?: string\n matchId: number\n matchOddsId?: number\n addToSlipEnabled: 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}\n\nexport interface MarketOddsRowVM {\n key: string\n selection: string\n odds: string\n oddsDecimal?: number\n matchOddsId?: number\n quotedAtUtc?: string\n isMain: 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 bookmaker?: string\n updatedAt?: string\n isLive: boolean\n matchId: number\n mainRows: MarketOddsRowVM[]\n moreRows: MarketOddsRowVM[]\n disclaimer?: string\n addToSlipEnabled: boolean\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 message = str(action.actionValue) ?? str(action.message) ?? str(action.query) ?? label\n return { label, actionId, 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\nexport function toInsightVM(insight: BettingInsight): InsightVM {\n const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? ''\n const selection = [str(insight.selectionLabel), str(insight.line)].filter(Boolean).join(' ') || undefined\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 scopes = Array.isArray(insight.scopes)\n ? (insight.scopes as Array<Record<string, unknown>>)\n .map((s) => ({ key: str(s.key), label: str(s.label), stats: readStatCells(s.stats) }))\n .filter((s): s is InsightScope => !!s.key && !!s.label)\n : undefined\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 scopes,\n text: str(insight.text) ?? '',\n stats: readStatCells(insight.stats),\n disclaimer: str(insight.disclaimer),\n matchId: typeof insight.matchId === 'number' ? insight.matchId : 0,\n matchOddsId,\n addToSlipEnabled: insight.addToSlipEnabled === 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 }\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 = [str(r.selectionLabel), str(r.line)].filter(Boolean).join(' ')\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 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 previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n }\n }\n const vms = rows.map(toRow).filter((r) => r.selection && r.odds)\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 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 }\n}\n\nexport interface OddsMovementVM {\n id: string\n market: string\n selection: 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}\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 = [str(card.selectionLabel), str(card.line)].filter(Boolean).join(' ')\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 market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n selection,\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 }\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","// 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}\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","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}>{text}</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 { SsMark } from './Icons'\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.\nexport function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLabel = 'Dismiss' }: { label: string; greeting?: string; popupText?: string | null; onOpen: () => void; onDismissPopup: () => void; dismissLabel?: string }): JSX.Element {\n const bubble = popupText ?? greeting\n return (\n <div className=\"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 <SsMark className=\"ss-w-fab-mark\" />\n </button>\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport { ChatHeader } from './ChatHeader'\nimport { MessageList } from './MessageList'\nimport { ChatInput } from './ChatInput'\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.\nconst 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 }: { controller: ChatController; ui: UiConfig; slip: SlipHandlerProps; onDashboardTap?: DashboardTapHandler }): JSX.Element {\n const { state, close, stop, send } = 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 return (\n <div className=\"ss-w-panel\" role=\"dialog\" aria-modal={isModal} aria-label={ui.chatDialogLabel}>\n <ChatHeader onClose={close} closeLabel={ui.closeChat} />\n <MessageList controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} />\n <ChatInput placeholder={ui.placeholder} streaming={state.isStreaming} onSend={(t) => send(t)} onStop={stop} stopLabel={ui.stopResponse} sendLabel={ui.sendMessage} />\n </div>\n )\n}\n","import { SsMark, CloseIcon } from './Icons'\n\nexport function ChatHeader({ onClose, closeLabel = 'Close chat' }: { onClose: () => void; closeLabel?: string }): JSX.Element {\n return (\n <header className=\"ss-w-header\">\n <SsMark className=\"ss-w-header-mark\" />\n <span className=\"ss-w-header-title\">SensibleStats</span>\n <button type=\"button\" className=\"ss-w-close\" aria-label={closeLabel} onClick={onClose}><CloseIcon /></button>\n </header>\n )\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 { ChatMessage } from './ChatMessage'\nimport { IntentChips } from './IntentChips'\nimport { ActionButtons } from './ActionButtons'\nimport { isPinnedToBottom } from '../scroll'\n\nexport function MessageList({ controller, ui, slip, onDashboardTap }: { controller: ChatController; ui: UiConfig; slip: SlipHandlerProps; onDashboardTap?: DashboardTapHandler }): 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 useEffect(() => {\n if (pinnedRef.current) endRef.current?.scrollIntoView({ block: 'end' })\n }, [state.messages, state.status])\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 or a 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)\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, displayText: a.label })}\n onTap={(tile, index) => {\n send(tile.actionValue, { 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 />\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} />\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 }: { image: string }): JSX.Element {\n return <span className=\"ss-w-ecard-crest\" style={{ backgroundImage: `url(${image})` }} aria-hidden=\"true\" />\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 StatRows({ stats }: { stats: StatCell[] }): JSX.Element {\n return (\n <div className=\"ss-w-ecard-stats\">\n {stats.map((s) => {\n const m = RECORD_RE.exec(s.value)\n return (\n <div key={s.label} className=\"ss-w-ecard-row\">\n <span className=\"ss-w-ecard-rlabel\">{s.label}</span>\n {m ? <FormBar w={Number(m[1])} d={Number(m[2])} l={Number(m[3])} /> : <span />}\n <span className=\"ss-w-ecard-rval\">{s.value}</span>\n </div>\n )\n })}\n </div>\n )\n}\n\n// The right-hand panel: competition tabs (2+ scopes) or a static league label\n// (1 scope), the season pill, and the stat rows for the active scope.\nfunction CardBody({ c }: { c: CardVM }): JSX.Element | null {\n const [active, setActive] = useState(0)\n if (c.scopes.length === 0) return null\n const season = c.season ? <span className=\"ss-w-ecard-season\">{shortSeason(c.season)}</span> : null\n\n if (c.scopes.length === 1) {\n const only = c.scopes[0]!\n return (\n <div className=\"ss-w-ecard-body\">\n <div className=\"ss-w-ecard-tabs ss-w-ecard-tabs-static\">\n <span className=\"ss-w-ecard-lead\" title={only.label}>{only.image ? <Crest image={only.image} /> : null}<span className=\"ss-w-ecard-lead-txt\">{only.label}</span></span>\n {season}\n </div>\n <StatRows stats={only.stats} />\n </div>\n )\n }\n\n const current = c.scopes[active] ?? c.scopes[0]!\n return (\n <div className=\"ss-w-ecard-body\">\n <div className=\"ss-w-ecard-tabs\" role=\"tablist\">\n {c.scopes.map((s, i) => (\n <button\n key={String(s.competitionId ?? 'all')}\n type=\"button\"\n role=\"tab\"\n className=\"ss-w-ecard-tab\"\n aria-selected={i === active}\n aria-label={s.label}\n title={s.label}\n onClick={() => setActive(i)}\n >\n {s.image ? <Crest image={s.image} /> : s.label}\n </button>\n ))}\n {season}\n </div>\n <StatRows key={String(current.competitionId ?? 'all')} stats={current.stats} />\n </div>\n )\n}\n\nfunction EntityCardItem({ c }: { c: CardVM }): JSX.Element {\n const hasBody = c.scopes.length > 0\n return (\n <div className={hasBody ? 'ss-w-ecard' : 'ss-w-ecard ss-w-ecard-bare'} data-kind={c.kind}>\n <div className=\"ss-w-ecard-id\">\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 </div>\n <CardBody c={c} />\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 { useState } from 'react'\nimport type { InsightVM, StatCell } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { AddToSlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\n\nfunction StatRows({ stats }: { stats: StatCell[] }): JSX.Element {\n return (\n <div className=\"ss-w-bi-rows\">\n {stats.map((s) => (\n <div key={`${s.label}:${s.value}`} className=\"ss-w-bi-row\">\n <span className=\"ss-w-bi-row-lbl\">{s.label}</span>\n <span className=\"ss-w-bi-row-num\">{s.value}</span>\n </div>\n ))}\n </div>\n )\n}\n\nfunction ScopedStats({ scopes }: { scopes: NonNullable<InsightVM['scopes']> }): JSX.Element {\n const [active, setActive] = useState(0)\n const current = scopes[active] ?? scopes[0] ?? { key: '', label: '', stats: [] }\n return (\n <div className=\"ss-w-bi-scoped\">\n <div className=\"ss-w-bi-scopes\" role=\"group\">\n {scopes.map((s, i) => (\n <button key={s.key} type=\"button\" className=\"ss-w-bi-chip\" aria-pressed={i === active} onClick={() => setActive(i)}>\n {s.label}\n </button>\n ))}\n </div>\n <StatRows key={current.key} stats={current.stats} />\n </div>\n )\n}\n\nfunction hasStatsContent(it: InsightVM): boolean {\n return (!!it.scopes && it.scopes.length >= 2) || it.stats.length > 0\n}\n\n// The reason-to-bet prose is clamped to two lines; one right-chevron expands it to the full text\n// AND the supporting stats together (the mock's single \">\" affordance). Collapsed by default so the\n// card stays scannable. The arrow only appears when there is something more to reveal — stats, or a\n// reason long enough to be clamped.\nfunction ReasonStrip({ it, ui }: { it: InsightVM; ui?: UiConfig }): JSX.Element | null {\n const [open, setOpen] = useState(false)\n const hasScopes = !!it.scopes && it.scopes.length >= 2\n const hasStats = hasStatsContent(it)\n const hasText = !!it.text\n if (!hasText && !hasStats) return null\n const expandable = hasStats || (it.text?.length ?? 0) > 90\n return (\n <div className=\"ss-w-bi-reason\">\n <span className=\"ss-w-bi-chart\" aria-hidden=\"true\" />\n <div className=\"ss-w-bi-reason-body\">\n {hasText ? <p className={`ss-w-bi-text${open ? '' : ' ss-w-bi-text-clamp'}`}>{it.text}</p> : null}\n {open && hasStats ? (hasScopes ? <ScopedStats scopes={it.scopes!} /> : <StatRows stats={it.stats} />) : null}\n </div>\n {expandable ? (\n <button\n type=\"button\"\n className=\"ss-w-bi-expand\"\n aria-expanded={open}\n aria-label={open ? ui?.hideStats ?? 'Hide stats' : ui?.showStats ?? 'Show stats'}\n onClick={() => setOpen((v) => !v)}\n >\n <span className={`ss-w-bi-arrow${open ? ' ss-w-bi-arrow-open' : ''}`} aria-hidden=\"true\" />\n </button>\n ) : null}\n </div>\n )\n}\n\nfunction InsightCard({ it, ui, slip }: { it: InsightVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const live = it.isLive || it.phase === 'live'\n const kickoff = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : undefined\n const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName\n const showHeader = !!it.competition || live || !!kickoff\n return (\n <div className=\"ss-w-binsight\">\n {showHeader ? (\n <div className=\"ss-w-bi-header\">\n <span className=\"ss-w-bi-header-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-header-right\">\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.dayLabel} {kickoff.time}</span> : null}\n </span>\n </div>\n ) : null}\n <div className=\"ss-w-bi-body\">\n <div className=\"ss-w-bi-fixture\">\n {hasNamedTeams ? (\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 ) : it.fixture ? (\n <span className=\"ss-w-bi-fixture-txt\">{it.fixture}</span>\n ) : null}\n </div>\n <div className=\"ss-w-bi-action\">\n <span className=\"ss-w-bi-mkt\">\n <span className=\"ss-w-bi-market\">{it.market}</span>\n {it.selection ? <span className=\"ss-w-bi-sel\">{it.selection}</span> : null}\n </span>\n {it.isMarketFloor ? (\n <span className=\"ss-w-bi-floor\">{ui?.marketFloorLabel ?? 'Market price · not a value pick'}</span>\n ) : 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 <AddToSlipButton it={it} slip={slip} ui={ui} />\n </div>\n </div>\n <ReasonStrip it={it} ui={ui} />\n {it.disclaimer ? <p className=\"ss-w-bi-disc\">{it.disclaimer}</p> : null}\n </div>\n )\n}\n\nexport function BettingInsightList({ insights, ui, slip }: { insights: InsightVM[]; ui?: UiConfig; slip: SlipHandlerProps }): 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} />)}\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, wasAdded, type SlipHandlerProps, type SlipToast } from '../slip'\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, marketName, slip, ui }:\n { selection: SlipSelection | null; shownOdds: string; marketName: string; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n const [pending, setPending] = useState(false)\n const [settled, setSettled] = useState(false)\n const [toast, setToast] = useState<SlipToast | null>(null)\n const dismiss = useCallback(() => setToast(null), [])\n\n const handler = slip.onAddToSlip\n if (!ui || !handler || !selection) return null\n\n const onClick = async (): Promise<void> => {\n setPending(true)\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 setToast(resultToToast(result, shownOdds || selection.oddsDecimal.toFixed(2), ui))\n setSettled(isTerminal(result))\n if (wasAdded(result) && slip.onMarketClicked) {\n try {\n slip.onMarketClicked(marketName)\n } catch {\n // Telemetry must never change what the user sees.\n }\n }\n } catch {\n setToast({ kind: 'error', text: ui.slipFailed })\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"ss-w-slip\">\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 <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 <SlipButton selection={selection} shownOdds={it.odds ?? ''} marketName={it.market} slip={slip} ui={ui} />\n}\n","import type { AddToSlipHandler, AddToSlipResult } 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 onMarketClicked?: (marketName: string) => void\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\nexport function resultToToast(result: AddToSlipResult | void, shownOdds: string, ui: UiConfig): SlipToast {\n if (!result) return { kind: 'success', text: ui.slipAdded(undefined) }\n switch (result.status) {\n case 'added':\n return { kind: 'success', text: ui.slipAdded(result.slip?.selectionCount) }\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 { 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 { useState } from 'react'\nimport type { MarketOddsVM, MarketOddsRowVM } from '../model'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\n\nfunction OddsRow({ vm, row, ui, slip }: { vm: MarketOddsVM; row: MarketOddsRowVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null\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 <SlipButton selection={selection} shownOdds={row.odds} marketName={vm.market} slip={slip} ui={ui} />\n </div>\n )\n}\n\nfunction MarketOddsCard({ vm, ui, slip }: { vm: MarketOddsVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n const [open, setOpen] = useState(false)\n const kickoff = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName\n const showHeader = !!vm.competition || vm.isLive || !!kickoff\n return (\n <div className=\"ss-w-mocard\">\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.dayLabel} {kickoff.time}</span> : null}\n </span>\n </div>\n ) : null}\n {(hasNamedTeams || vm.fixture || vm.market) ? (\n <div className=\"ss-w-mo-sub\">\n {hasNamedTeams ? (\n <div 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 </div>\n ) : vm.fixture ? <span className=\"ss-w-mo-teams\">{vm.fixture}</span> : null}\n {vm.market ? <span className=\"ss-w-mo-market\">{vm.market}</span> : null}\n </div>\n ) : 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} />)}\n {open ? vm.moreRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} />) : 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({ cards, ui, slip }: { cards: MarketOddsVM[]; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element | null {\n if (!cards || cards.length === 0) return null\n return (\n <div className=\"ss-w-mocards\">\n {cards.map((vm) => <MarketOddsCard key={vm.id} vm={vm} ui={ui} slip={slip} />)}\n </div>\n )\n}\n","import type { UiConfig } from '../config'\nimport type { OddsMovementVM } from '../model'\nimport { CHART_VIEW_H, CHART_VIEW_W } from '../chart'\nimport { OddsMovementBadge } from './OddsMovementBadge'\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({ vm, ui }: { vm: OddsMovementVM; ui?: UiConfig }): 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\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 </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({ cards, ui }: { cards: OddsMovementVM[]; ui?: UiConfig }): 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} />)}\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\nexport function DashboardTile({ tile, onTap }: { tile: GreetingDashboardTile; onTap: () => void }): JSX.Element {\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 }: { dashboard: GreetingDashboardData; onTap: (tile: GreetingDashboardTileData, index: number) => void }): 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)} />\n ))}\n </div>\n {dashboard.footerTip ? <span className=\"ss-w-dash-foot\">{dashboard.footerTip}</span> : null}\n </div>\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 { Markdown } from './Markdown'\nimport { EntityCardList } from './EntityCardList'\nimport { BettingInsightList } from './BettingInsightList'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { ActionButtons } from './ActionButtons'\nimport { GreetingDashboard } from './dashboard/GreetingDashboard'\n\nexport function ChatMessage({ message, disabled, onAct, onTap, ui, slip }: { message: Message; disabled: boolean; onAct: (a: ActionVM) => void; onTap: (tile: GreetingDashboardTile, index: number) => void; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n if (message.role === 'user') {\n return <div className=\"ss-w-msg ss-w-user\"><div className=\"ss-w-bubble\">{message.text}</div></div>\n }\n return (\n <div className=\"ss-w-msg ss-w-bot\">\n {message.text && !message.greetingDashboard ? <Markdown text={message.text} /> : null}\n {message.greetingDashboard ? <GreetingDashboard dashboard={message.greetingDashboard} onTap={onTap} /> : null}\n <EntityCardList cards={message.cards} disabled={disabled} showLessLabel={ui?.showLess} showMoreLabel={ui?.showMore} />\n <BettingInsightList insights={message.insights} ui={ui} slip={slip} />\n <MarketOddsCardList cards={message.marketOdds} ui={ui} slip={slip} />\n <OddsMovementCardList cards={message.oddsMovement} ui={ui} />\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","// 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-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 }\\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}\\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}\\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; }\\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 { 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\\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; }\\n.ss-w-header-title { font-weight: 660; }\\n.ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n\\n/* messages */\\n.ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }\\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/* Identity Hero: crest-led identity block | tabbed stats panel */\\n.ss-w-ecard { display: grid; grid-template-columns: 112px 1fr; align-items: stretch; 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-id { display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; padding: 13px 10px; border-right: 1px solid var(--ss-w-line); background: linear-gradient(158deg, var(--ss-w-bubble), color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-bubble))); }\\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-id { flex-direction: row; text-align: left; gap: 11px; background: none; border-right: none; padding: 10px 12px; }\\n.ss-w-ecard-bare .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }\\n.ss-w-ecard-bare .ss-w-thumb.ss-w-team { border-radius: 10px; }\\n\\n.ss-w-ecard-body { min-width: 0; padding: 9px 12px 12px; display: flex; flex-direction: column; }\\n\\n/* tab strip seated on the stats panel's top edge; active tab underlined in accent */\\n.ss-w-ecard-tabs { display: flex; align-items: stretch; gap: 3px; border-bottom: 1px solid var(--ss-w-line); margin-bottom: 9px; flex-wrap: wrap; }\\n.ss-w-ecard-tab { 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: 5px 8px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }\\n.ss-w-ecard-tab[aria-selected=\\\"true\\\"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-ecard-tabs-static { align-items: center; flex-wrap: nowrap; }\\n.ss-w-ecard-lead { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 640; color: var(--ss-w-ink); padding: 4px 2px 8px; min-width: 0; flex: 1; }\\n.ss-w-ecard-lead-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\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.ss-w-ecard-tabs-static .ss-w-ecard-season { margin-bottom: 4px; }\\n\\n.ss-w-ecard-stats { display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-ecard-row { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; }\\n.ss-w-ecard-rlabel { font-size: 9.5px; text-transform: uppercase; letter-spacing: .045em; color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-ecard-rval { justify-self: end; font-size: 15px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }\\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/* row 1: competition logo + name on the left, live badge + kickoff on the right */\\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; }\\n.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\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/* row 2: crest-flanked fixture on the left, boxed action panel on the right */\\n.ss-w-bi-body { display: flex; align-items: center; gap: 10px; }\\n.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12px; font-weight: 650; color: var(--ss-w-ink); }\\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.ss-w-bi-action { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 0; }\\n.ss-w-bi-action .ss-w-slip { width: 100%; }\\n.ss-w-bi-action .ss-w-slip > button { flex: 1; width: 100%; text-align: center; border-radius: 8px; }\\n/* The action column is narrow; let its toast size to its own text and anchor to the card's right edge instead of being clipped to the button width. */\\n.ss-w-bi-action .ss-w-toast { left: auto; right: 0; width: max-content; max-width: 210px; white-space: normal; }\\n.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; align-items: flex-end; text-align: right; }\\n.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.2; color: var(--ss-w-faint); white-space: nowrap; }\\n.ss-w-bi-sel { font-size: 11px; line-height: 1.25; color: var(--ss-w-faint); }\\n.ss-w-bi-odds { flex: none; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }\\n.ss-w-bi-odds b { font-size: 23px; 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\\n/* row 3: bar-chart glyph + reasoning prose + stats-expander chevron, 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-reason-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }\\n.ss-w-bi-text { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-bi-text-clamp { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\\n.ss-w-bi-expand { flex: none; align-self: center; display: grid; place-items: center; width: 22px; height: 22px; margin: -2px -4px -2px 0; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-bi-expand:hover { color: var(--ss-w-ink); }\\n.ss-w-bi-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); transition: transform .15s ease; }\\n.ss-w-bi-arrow-open { transform: rotate(135deg); }\\n.ss-w-bi-rows { display: flex; flex-direction: column; }\\n.ss-w-bi-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-bi-row:first-child { border-top: none; }\\n.ss-w-bi-row-lbl { font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; flex: none; color: var(--ss-w-ink); }\\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n.ss-w-bi-scoped { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-bi-scopes { display: inline-flex; align-items: center; gap: 2px; flex-wrap: wrap; align-self: flex-start; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 2px; }\\n.ss-w-bi-chip { font-size: 11px; font-weight: 600; border: none; border-radius: 7px; padding: 4px 10px; color: var(--ss-w-faint); background: none; cursor: pointer; }\\n.ss-w-bi-chip[aria-pressed=\\\"true\\\"] { color: var(--ss-w-ink); background: var(--ss-w-panel); box-shadow: 0 1px 2px rgba(0,0,0,.08); }\\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.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 { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); }\\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.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); }\\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; }\\n.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }\\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.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; }\\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; }\\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.ss-w-toast { position: absolute; top: calc(100% + 6px); left: 0; z-index: 1; max-width: 100%; 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@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.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: #eef8f1; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: #eef3fb; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: #fdf6ec; }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: #f5eefb; }\\n\"\n"],"mappings":"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","names":["import_react","import_widget_sdk","import_widget_sdk","import_widget_sdk","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","ReactMarkdown","remarkGfm","import_react","import_jsx_runtime","import_react","import_react","import_widget_sdk","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","directionWord","import_react","import_jsx_runtime","initials","Crest","import_jsx_runtime","StatRows","Crest","import_react","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}