{"version":3,"sources":["../src/index.ts","../src/StatsWidget.tsx","../src/kickoff.ts","../src/i18n.ts","../src/config.ts","../src/chart.ts","../src/model.ts","../src/slip.ts","../src/useHostEvents.ts","../src/host.ts","../src/matchViews.ts","../src/slipLedger.ts","../src/dashboardTap.ts","../src/theme.ts","../src/useChatStream.ts","../src/reducer.ts","../src/limit.ts","../src/useLiveDashboardPoll.ts","../src/conversationStore.ts","../src/presets.ts","../src/useLiveMonitor.ts","../src/pinStore.ts","../src/useTabs.ts","../src/useMatchDiscovery.ts","../src/scheduleCache.ts","../src/dueSet.ts","../src/useGames.ts","../src/useLeaderboard.ts","../src/useClubFixtures.ts","../src/useClubStandings.ts","../src/useClubSquad.ts","../src/useClubSquadStats.ts","../src/useClubPlayerDetail.ts","../src/usePresetGrid.ts","../src/presetGrid.ts","../src/liveClock.ts","../src/eventLogContext.ts","../src/popupTelemetry.ts","../src/openTelemetry.ts","../src/components/ChatFab.tsx","../src/components/BrandMark.tsx","../src/assets/logo.ts","../src/components/Icons.tsx","../src/components/GreetingBubble.tsx","../src/components/ChatPanel.tsx","../src/components/ChatHeader.tsx","../src/components/MessageList.tsx","../src/components/Markdown.tsx","../src/components/EntityCardList.tsx","../src/components/AddToSlipButton.tsx","../src/slipAdd.ts","../src/slipStateContext.ts","../src/components/Toast.tsx","../src/components/OddsMovementBadge.tsx","../src/components/Crest.tsx","../src/components/PinToggle.tsx","../src/components/PriceHistoryButton.tsx","../src/components/BettingInsightList.tsx","../src/components/AddAllToSlipButton.tsx","../src/presetToolsContext.ts","../src/components/ComboCardList.tsx","../src/components/MarketOddsCardList.tsx","../src/components/AllMarketsButton.tsx","../src/components/CompactOddsList.tsx","../src/compactList.ts","../src/components/OddsMovementCard.tsx","../src/components/ActionButtons.tsx","../src/components/dashboard/DashboardTile.tsx","../src/components/dashboard/GreetingDashboard.tsx","../src/components/dashboard/FixtureCard.tsx","../src/components/dashboard/CountdownCard.tsx","../src/components/dashboard/InjuriesCard.tsx","../src/components/dashboard/ReasonToBetCard.tsx","../src/components/dashboard/WhereToWatchCard.tsx","../src/components/dashboard/CongestedWeekCard.tsx","../src/components/dashboard/TransfersCard.tsx","../src/components/dashboard/LinksCard.tsx","../src/components/dashboard/PostMatchResultCard.tsx","../src/components/dashboard/PostMatchGoalsCard.tsx","../src/components/dashboard/PostMatchStatsCard.tsx","../src/components/dashboard/PostMatchTopPerformerCard.tsx","../src/components/dashboard/PostMatchNextCard.tsx","../src/components/dashboard/RestingNextCard.tsx","../src/components/dashboard/RestingStandingsCard.tsx","../src/components/dashboard/RestingSeasonCard.tsx","../src/components/dashboard/RestingFormCard.tsx","../src/components/dashboard/LiveScoreCard.tsx","../src/useLiveClock.ts","../src/components/dashboard/LiveTimelineCard.tsx","../src/components/dashboard/MomentumWave.tsx","../src/components/dashboard/LiveStatsCard.tsx","../src/components/dashboard/ClubFanDashboard.tsx","../src/components/ChatMessage.tsx","../src/components/IntentChips.tsx","../src/scroll.ts","../src/components/ChatInput.tsx","../src/components/TabBar.tsx","../src/components/MarketAccordion.tsx","../src/components/LiveFactBlock.tsx","../src/components/MonitorFormH2H.tsx","../src/components/MonitorMatchCard.tsx","../src/components/MonitorTabs.tsx","../src/components/TodayPanel.tsx","../src/placement.ts","../src/search.ts","../src/useStarTap.ts","../src/components/LeagueTile.tsx","../src/components/LeagueDetail.tsx","../src/components/FixtureRow.tsx","../src/components/LeagueRowGroup.tsx","../src/components/games/ui/SearchField.tsx","../src/components/games/ui/icons.tsx","../src/components/GamesPanel.tsx","../src/components/GamesLoginWall.tsx","../src/components/GamesHub.tsx","../src/components/games/ui/gameMeta.ts","../src/components/GameTileArt.tsx","../src/components/games/ui/Chip.tsx","../src/components/GameTile.tsx","../src/components/GameScreenHost.tsx","../src/useGamePlay.ts","../src/components/games/MysteryTigerGame.tsx","../src/components/games/nationFlags.ts","../src/components/games/PlayerAvatar.tsx","../src/components/games/ui/GameHeader.tsx","../src/components/games/ui/SegmentProgress.tsx","../src/components/games/ui/AnswerTray.tsx","../src/components/games/ui/FooterBar.tsx","../src/components/games/ui/Silhouette.tsx","../src/components/games/ui/GameButton.tsx","../src/components/games/ui/ResultCard.tsx","../src/components/games/ui/PointsLadderRow.tsx","../src/components/games/HigherOrLowerGame.tsx","../src/components/games/CareerPathGame.tsx","../src/components/games/ui/CrestShield.tsx","../src/components/games/BeatTheGridGame.tsx","../src/components/games/ui/OptionList.tsx","../src/components/games/GuessTheXiGame.tsx","../src/components/games/ui/PitchSvg.tsx","../src/components/games/ui/formations.ts","../src/components/games/DailyQuizGame.tsx","../src/components/games/MatchdayPredictorGame.tsx","../src/components/games/StartingXiGame.tsx","../src/components/games/StatLadderGame.tsx","../src/components/games/FanMotmGame.tsx","../src/components/Leaderboard.tsx","../src/components/LeaderboardRow.tsx","../src/components/LeaderboardEmpty.tsx","../src/components/LeaderboardPanel.tsx","../src/components/games/ui/fonts.ts","../src/components/Fixtures.tsx","../src/components/Standings.tsx","../src/components/groupByPosition.ts","../src/components/labels.ts","../src/components/SquadStats.tsx","../src/components/Squad.tsx","../src/components/PlayerPhoto.tsx","../src/components/MiniPitch.tsx","../src/components/PerformanceBars.tsx","../src/components/PlayerDetail.tsx","../src/components/PresetSpeedDial.tsx","../src/components/PresetTools.tsx","../src/usePresetDial.ts","../src/presetSeen.ts","../src/components/HostEventsProvider.tsx","../src/styles/css.generated.ts"],"sourcesContent":["export { StatsWidget } from './StatsWidget'\nexport type { StatsWidgetProps } from './StatsWidget'\nexport type { StatsWidgetConfig } from './config'\nexport { createWidgetHost } from './host'\nexport type { WidgetHost } from './host'\nexport { WIDGET_CSS } from './styles/css.generated'\n","import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from 'react'\nimport { StatsWidgetClient, type Conversation } from '@sensiblestats/widget-sdk'\nimport type { MarketOddsLiveBlock } from '@sensiblestats/widget-sdk'\nimport { normalizeUi, toClientOptions, toUserContext, type StatsWidgetConfig } from './config'\nimport { toMarketOddsVM } from './model'\nimport { wasAdded, type SlipHandlerProps } from './slip'\nimport type { WidgetHost } from './host'\nimport { useHostEvents } from './useHostEvents'\nimport { createDashboardTapSignal } from './dashboardTap'\nimport { themeAttrs } from './theme'\nimport { useChatStream } from './useChatStream'\nimport { useLiveMonitor, type WatchRef } from './useLiveMonitor'\nimport { useMatchDiscovery } from './useMatchDiscovery'\nimport { useGames } from './useGames'\nimport { useLeaderboard } from './useLeaderboard'\nimport { useClubFixtures } from './useClubFixtures'\nimport { useClubStandings } from './useClubStandings'\nimport { useClubSquad } from './useClubSquad'\nimport { useClubSquadStats } from './useClubSquadStats'\nimport { useClubPlayerDetail } from './useClubPlayerDetail'\nimport { usePresetGrid } from './usePresetGrid'\nimport { visibleGroupsOf } from './liveClock'\nimport { EventLogContext } from './eventLogContext'\nimport { usePopupTelemetry } from './popupTelemetry'\nimport { useOpenTelemetry } from './openTelemetry'\nimport { bubbleAsks, runBubbleAsk } from './presets'\nimport { ChatFab } from './components/ChatFab'\nimport { ChatPanel } from './components/ChatPanel'\nimport { HostEventsProvider } from './components/HostEventsProvider'\nimport { WIDGET_CSS } from './styles/css.generated'\n\nexport type StatsWidgetProps =\n  | { config: StatsWidgetConfig; client?: never; host?: WidgetHost }\n  | { client: StatsWidgetClient; config?: Omit<StatsWidgetConfig, 'operatorId' | 'publicKey' | 'baseUrl' | 'userContext'>; host?: WidgetHost }\n\nfunction buildClient(props: StatsWidgetProps): { client: StatsWidgetClient; conversation: Conversation } | null {\n  try {\n    if ('client' in props && props.client) {\n      return { client: props.client, conversation: props.client.conversation() }\n    }\n    const cfg = props.config as StatsWidgetConfig\n    const client = new StatsWidgetClient(toClientOptions(cfg))\n    return { client, conversation: client.conversation(toUserContext(cfg)) }\n  } catch (err) {\n    console.error('[StatsWidget] failed to initialize:', err instanceof Error ? err.message : err)\n    return null\n  }\n}\n\nfunction injectStyles(root: Document | ShadowRoot): void {\n  const host: ParentNode = root instanceof ShadowRoot ? root : root.head\n  if (host.querySelector('#ss-w-styles')) return\n  const el = document.createElement('style')\n  el.id = 'ss-w-styles'\n  el.textContent = WIDGET_CSS\n  host.appendChild(el)\n}\n\nexport function StatsWidget(props: StatsWidgetProps): JSX.Element | null {\n  const injectedClient = 'client' in props ? props.client : undefined\n  const cfg = props.config as Partial<StatsWidgetConfig> | undefined\n  const built = useMemo(() => buildClient(props), [injectedClient, cfg?.operatorId, cfg?.publicKey, cfg?.baseUrl])\n  // One logger per mount, keyed on the client identity (not on operatorUserId/anonymousUserId/\n  // conversationId -- those change over the widget's lifetime and are pushed in via setIdentity\n  // below, not by tearing down and recreating the logger).\n  const logger = useMemo(\n    () => (built ? built.client.createEventLogger({\n      operatorUserId: cfg?.userContext?.operatorUserId,\n      anonymousUserId: cfg?.userContext?.anonymousUserId,\n    }) : null),\n    [built?.client],\n  )\n  const ui = useMemo(() => normalizeUi((props.config ?? { operatorId: '', publicKey: '' }) as StatsWidgetConfig), [props.config])\n  const rootRef = useRef<HTMLDivElement>(null)\n  // One-shot launcher attention animation: the FAB nudges then the greeting\n  // types in, exactly once per page load. The ref lives here (not in ChatFab,\n  // which remounts every time the panel closes) so it never replays; a page\n  // refresh remounts the widget and re-arms it.\n  const introDoneRef = useRef(false)\n  const markIntroDone = useCallback(() => { introDoneRef.current = true }, [])\n  const convStorageKey = `ss-w-conv:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`\n  const controller = useChatStream(built?.conversation ?? emptyConversation(), ui.starters, built ? ui.greetingMessage : undefined, convStorageKey)\n  // The two hooks are mutually dependent -- useMatchDiscovery needs monitor.pins, useLiveMonitor\n  // needs to know whether Today has content -- so the cycle is broken with state rather than a\n  // read of discovery's own render. It settles one render later, and unlike a ref it actually\n  // re-renders, which is what lets the fallback effect fire when Today empties under the user.\n  const [hasToday, setHasToday] = useState(false)\n  // Collect a WatchRef for each live card currently on screen so the poll loop keeps them current.\n  // key `live:card:{matchId}` is echoed verbatim by the server; we match on it in the effect below.\n  const liveCardWatches = useMemo<WatchRef[]>(() => {\n    const seen = new Set<number>()\n    const out: WatchRef[] = []\n    for (const msg of controller.state.messages) {\n      if (msg.role !== 'assistant') continue\n      for (const vm of msg.marketOdds) {\n        if (vm.live == null || seen.has(vm.matchId)) continue\n        seen.add(vm.matchId)\n        out.push({ key: `live:card:${vm.matchId}`, kind: 'market', matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName ?? 'FULLTIME_RESULT' })\n      }\n    }\n    return out\n  }, [controller.state.messages])\n  const locale = cfg?.locale\n  const clubFixturesResult = useClubFixtures(built?.conversation ?? null)\n  const monitor = useLiveMonitor({\n    getLiveMonitor: (pins) => (built ? built.conversation.getLiveMonitor(pins, locale) : Promise.resolve(null)),\n    getMarketOdds: (matchId, dev) => (built ? built.conversation.getMarketOdds(matchId, dev) : Promise.resolve(null)),\n    storageKey: `ss-w-pins:${cfg?.operatorId ?? ''}:${cfg?.userContext?.operatorUserId ?? 'anon'}`,\n    isOpen: controller.state.isOpen,\n    hasToday,\n    watches: liveCardWatches,\n    clubEnabled: clubFixturesResult.enabled,\n  })\n  // Stable across renders (deps = [built], itself memoized on the client identity) -- the real\n  // call site useMatchDiscovery.test.tsx's interval-churn test protects: a freshly-constructed\n  // arrow here would defeat that guarantee even with the hook's own getStatesRef defense.\n  const operatorUserId = cfg?.userContext?.operatorUserId\n  const anonymousUserId = cfg?.userContext?.anonymousUserId\n  const getSchedule = useCallback(\n    (localDate: string, utcOffsetMinutes: number) =>\n      built ? built.conversation.getSchedule(localDate, utcOffsetMinutes, operatorUserId, anonymousUserId) : Promise.resolve(null),\n    [built, operatorUserId, anonymousUserId],\n  )\n  const postLeagueStar = useCallback(\n    (competitionId: number, starred: boolean) =>\n      built ? built.conversation.starLeague(competitionId, starred, operatorUserId, anonymousUserId) : Promise.resolve(null),\n    [built, operatorUserId, anonymousUserId],\n  )\n  const getStates = useCallback(\n    (matchIds: number[]) => (built ? built.conversation.getStates(matchIds) : Promise.resolve(null)),\n    [built],\n  )\n  const pinnedMatchIds = useMemo(\n    () => monitor.pins.filter((p) => p.kind === 'match').map((p) => p.matchId),\n    [monitor.pins],\n  )\n  const discovery = useMatchDiscovery({\n    getSchedule,\n    getStates,\n    postLeagueStar,\n    operatorId: cfg?.operatorId ?? '',\n    operatorUserId,\n    anonymousUserId,\n    isOpen: controller.state.isOpen,\n    pinnedMatchIds,\n  })\n  const todayHasContent = visibleGroupsOf(discovery.groups, discovery.states).length > 0\n  useEffect(() => { setHasToday(todayHasContent) }, [todayHasContent])\n\n  // Apply live card snapshot updates back to the chat reducer so live cards show fresh prices,\n  // score, and minute, and stale state clears (D13) once a new snapshot lands.\n  const prevLiveSnapshotRef = useRef(monitor.snapshot)\n  useEffect(() => {\n    const snap = monitor.snapshot\n    if (!snap || snap === prevLiveSnapshotRef.current) return\n    prevLiveSnapshotRef.current = snap\n    for (const market of snap.markets) {\n      if (!market.key.startsWith('live:card:')) continue\n      const matchId = parseInt(market.key.slice('live:card:'.length), 10)\n      if (!Number.isFinite(matchId)) continue\n      let mainRows = [] as ReturnType<typeof toMarketOddsVM>['mainRows']\n      let moreRows = [] as ReturnType<typeof toMarketOddsVM>['moreRows']\n      let addToSlipEnabled = false\n      if (market.card) {\n        const updated = toMarketOddsVM(market.card)\n        mainRows = updated.mainRows\n        moreRows = updated.moreRows\n        addToSlipEnabled = updated.addToSlipEnabled\n      }\n      let closedReason: string | null = null\n      if (market.phase === 'fullTime' || market.phase === 'postponed') closedReason = 'full_time'\n      else if (market.isSuspended) closedReason = 'suspended'\n      else if (!market.card) closedReason = 'no_live_price'\n      const live: MarketOddsLiveBlock = {\n        phase: market.phase,\n        homeScore: market.homeScore ?? null,\n        awayScore: market.awayScore ?? null,\n        minuteLabel: market.minuteLabel ?? null,\n        isSuspended: market.isSuspended,\n        isSettled: market.isSettled,\n        asOfUtc: market.asOfUtc,\n        closedReason,\n      }\n      controller._dispatch?.({ kind: 'UPDATE_LIVE_CARD', matchId, live, mainRows, moreRows, addToSlipEnabled })\n    }\n  }, [monitor.snapshot])\n\n  const gamesResult = useGames(built?.conversation ?? null, { activeTab: monitor.activeTab })\n  const leaderboardResult = useLeaderboard(built?.conversation ?? null, { activeTab: monitor.activeTab })\n  const clubStandingsResult = useClubStandings(built?.conversation ?? null, { activeTab: monitor.activeTab, enabled: clubFixturesResult.enabled })\n  const clubSquadResult = useClubSquad(built?.conversation ?? null, { activeTab: monitor.activeTab, enabled: clubFixturesResult.enabled })\n  const clubSquadStatsResult = useClubSquadStats(built?.conversation ?? null, { activeTab: monitor.activeTab, enabled: clubFixturesResult.enabled })\n  const clubPlayerDetailResult = useClubPlayerDetail(built?.conversation ?? null)\n\n  // Onboarding presets stage 2 (contract §1): asked in the background after the\n  // panel opens; a 200 is kept until it is 10 minutes old, then refetched on the next open (P1).\n  // Stage 3 contract §2: this widget draws legs with no stat, so it asks for the open grid.\n  const getPricePresets = useCallback(\n    (locale: 'en' | 'tr') => (built ? built.conversation.getPricePresets(locale, { pool: 'open' }) : Promise.resolve(null)),\n    [built],\n  )\n  const presetGrid = usePresetGrid({ getPricePresets, isOpen: controller.state.isOpen, locale: ui.presets.lang })\n\n  // The Today dot: the live count rising from zero is the \"something changed you have not seen\"\n  // event for this tab. The hook suppresses it while Today is the active tab, exactly as the\n  // other three dots are suppressed.\n  const markTodayActivity = monitor.markTodayActivity\n  const prevLiveCountRef = useRef(0)\n  useEffect(() => {\n    const rose = prevLiveCountRef.current === 0 && discovery.liveCount > 0\n    prevLiveCountRef.current = discovery.liveCount\n    if (rose) markTodayActivity()\n  }, [discovery.liveCount, markTodayActivity])\n  const hostEvents = useHostEvents({\n    host: props.host,\n    operatorId: cfg?.operatorId ?? '',\n    currentUser: cfg?.userContext?.operatorUserId || undefined,\n    logger,\n    isOpen: controller.state.isOpen,\n    closePanel: controller.close,\n  })\n  const markAdded = hostEvents.markAdded\n  const slip = useMemo<SlipHandlerProps>(\n    () => {\n      const handler = props.config?.onAddToSlip\n      return {\n        // I3: the D5 persistent in-slip badge must arm from ANY add path -- a chat-message\n        // insight/market card, not just the ones rendered inside the Odds tab itself -- so the\n        // wasAdded->markAdded wrap lives here (once), not duplicated per consumer. It awaits the\n        // operator's handler itself, so a result that lands after the button's own timeout still\n        // arms the badge.\n        onAddToSlip: handler && (async (sel) => {\n          const result = await handler(sel)\n          if (wasAdded(result)) markAdded(sel.matchOddsId)\n          return result\n        }),\n        conversationId: controller.state.conversationId ?? undefined,\n      }\n    },\n    [props.config?.onAddToSlip, controller.state.conversationId, markAdded],\n  )\n  const onDashboardTap = useMemo(\n    () => (built ? createDashboardTapSignal((input) => built.conversation.sendSignal(input), logger) : undefined),\n    [built, logger],\n  )\n\n  const dismissPopup = usePopupTelemetry(logger, controller.state.isOpen, controller.state.popupText, controller.dismissPopup)\n  useOpenTelemetry(logger, controller.state.isOpen)\n  const asks = bubbleAsks(controller.state.messages, ui.presets.standoutAsk).map((ask) => ({\n    label: ask.label,\n    onTap: () => runBubbleAsk(ask, {\n      open: controller.open,\n      setActiveTab: monitor.setActiveTab,\n      send: controller.send,\n      onDashboardTap,\n      log: logger,\n    }),\n  }))\n\n  const conversationId = controller.state.conversationId ?? undefined\n  useEffect(() => {\n    if (!logger) return\n    logger.setIdentity({ operatorUserId, anonymousUserId, conversationId })\n  }, [logger, operatorUserId, anonymousUserId, conversationId])\n\n  useEffect(() => {\n    if (!logger) return\n    // React StrictMode runs this cleanup and then this setup again on the same memoized logger.\n    // Without the resume the second pass keeps a disposed logger and every later event is dropped.\n    logger.resume()\n    const onHide = (): void => { logger.flushOnHide() }\n    const onVisibilityHide = (): void => {\n      if (document.visibilityState === 'hidden') logger.flushOnHide()\n    }\n    window.addEventListener('pagehide', onHide)\n    document.addEventListener('visibilitychange', onVisibilityHide)\n    return () => {\n      window.removeEventListener('pagehide', onHide)\n      document.removeEventListener('visibilitychange', onVisibilityHide)\n      // dispose() only clears the internal timer -- it does NOT flush queued events, so an\n      // unflushed dispose on unmount silently drops whatever is still queued.\n      logger.flushOnHide()\n      logger.dispose()\n    }\n  }, [logger])\n\n  useEffect(() => {\n    if (!built || !ui.injectStyles) return\n    const node = rootRef.current?.getRootNode()\n    if (node) injectStyles(node as Document | ShadowRoot)\n  }, [built, ui.injectStyles])\n\n  if (!built) return null\n  const attrs = themeAttrs(ui)\n  return (\n    <EventLogContext.Provider value={logger}>\n      <HostEventsProvider value={hostEvents}>\n        <div ref={rootRef} className=\"ss-w-root\" data-ss-w-theme={attrs['data-ss-w-theme']} data-ss-w-pos={attrs['data-ss-w-pos']} style={attrs.style as CSSProperties}>\n          {controller.state.isOpen ? (\n            <ChatPanel\n              controller={controller}\n              ui={ui}\n              slip={slip}\n              onDashboardTap={onDashboardTap}\n              monitor={monitor.enabled ? monitor : undefined}\n              discovery={discovery}\n              gamesResult={gamesResult}\n              leaderboardResult={leaderboardResult}\n              clubFixturesResult={clubFixturesResult}\n              clubStandingsResult={clubStandingsResult}\n              clubSquadResult={clubSquadResult}\n              clubSquadStatsResult={clubSquadStatsResult}\n              clubPlayerDetailResult={clubPlayerDetailResult}\n              loggedIn={!!operatorUserId}\n              conversation={built?.conversation ?? null}\n              presetGrid={presetGrid}\n            />\n          ) : (\n            <ChatFab\n              label={ui.launcherLabel}\n              greeting={ui.greeting}\n              popupText={controller.state.popupText}\n              logoUrl={ui.logoUrl}\n              onOpen={controller.open}\n              onDismissPopup={dismissPopup}\n              dismissLabel={ui.dismissGreeting}\n              introAllowed={!introDoneRef.current}\n              onIntroStart={markIntroDone}\n              asks={asks}\n            />\n          )}\n        </div>\n      </HostEventsProvider>\n    </EventLogContext.Provider>\n  )\n}\n\n// Hooks must run unconditionally; when the client failed to build we still need a Conversation-shaped stub for the hook.\nfunction emptyConversation(): Conversation {\n  return { send: () => { throw new Error('widget not initialized') } } as unknown as Conversation\n}\n","export function formatBettingKickoff(\n  kickoffUtc: string,\n  ui: { today: string; tomorrow: string },\n  locale: string,\n  now: Date = new Date(),\n): { dayLabel: string; time: string } {\n  const at = new Date(kickoffUtc)\n  const intlLocale = locale === 'tr' ? 'tr-TR' : 'en-GB'\n  const time = new Intl.DateTimeFormat(intlLocale, { hour: '2-digit', minute: '2-digit' }).format(at)\n  const atLocalDate = new Date(at.getFullYear(), at.getMonth(), at.getDate())\n  const nowLocalDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n  const dayDiff = Math.round((atLocalDate.getTime() - nowLocalDate.getTime()) / 86_400_000)\n  const dayLabel =\n    dayDiff === 0\n      ? ui.today\n      : dayDiff === 1\n        ? ui.tomorrow\n        : new Intl.DateTimeFormat(intlLocale, { weekday: 'short', day: 'numeric', month: 'short' }).format(at)\n  return { dayLabel, time }\n}\n","import { formatBettingKickoff } from './kickoff'\n\nexport type Locale = 'en' | 'tr'\n\n// Games-tab copy (u393). Each game task adds its own keys here, in en AND tr.\nexport interface GamesStrings {\n  // BCP-47 tag set on the games roots so CSS text-transform uppercases Turkish i → İ.\n  lang: 'en' | 'tr'\n  dailyChallenge: string\n  playNow: string\n  dailyGames: string\n  newSetAtMidnight: string\n  matchdayGames: string\n  kickoffAt: (dayTime: string) => string\n  statStreak: string\n  statToday: string\n  statRank: string\n  unitDays: string\n  unitPts: string\n  worthNow: (pts: number) => string\n  worthAfterMiss: (pts: number) => string\n  thisWeek: string\n  newToday: string\n  resume: string\n  done: string\n  doneWithScore: (score: number) => string\n  locksAt: (dayTime: string) => string\n  // Points with the locale's digit grouping (\"1,200\" en / \"1.200\" tr). Used by the hub TODAY stat and doneWithScore.\n  formatPts: (n: number) => string\n  // Shared by every game screen (loading branch, result card, primary guess button).\n  loading: string\n  backToGames: string\n  alreadyPlayedTitle: string\n  guess: string\n  // Localised \"Sat 15:00\". A function so each locale owns its Intl locale.\n  formatDayTime: (iso: string) => string\n  // Display names keyed by gameId — locale-specific replacements for the GAME_TITLES map.\n  titles: Record<string, string>\n  taglines: Record<string, string>\n  mysteryTiger: {\n    eyebrow: string\n    labels: Record<'position' | 'nationality' | 'age' | 'shirtNumber' | 'apps', string>\n    yourGuesses: string\n    legendMatch: string\n    legendClose: string\n    legendHigher: string\n    searchLabel: string\n    searchPlaceholder: string\n    optionsLabel: string\n    progress: (used: number, total: number) => string\n    solved: string\n    failed: string\n    detail: (guesses: number) => string\n  }\n  higherOrLower: {\n    eyebrow: (points: number) => string\n    streak: string\n    whoHadMore: string\n    season: (label: string) => string\n    higher: string\n    lower: string\n    vs: string\n    lastAnswer: (name: string, value: number) => string\n    answersSoFar: (answered: number, total: number) => string\n    runOver: string\n    perfectRun: string\n    runDetail: (correct: number) => string\n  }\n  guessTheXi: {\n    pitchLabel: string\n    notThem: string\n    whichClub: (left: number) => string\n    searchPlaceholder: string\n    optionsLabel: string\n    solved: string\n    failed: string\n    detail: (guesses: number) => string\n    theAnswer: string\n  }\n  dailyQuiz: {\n    questionOf: (i: number, n: number) => string\n    results: string\n    next: string\n    previous: string\n    submit: string\n    submitting: string\n    correctOf: (correct: number, n: number) => string\n    progressAria: (i: number, n: number) => string\n  }\n  careerPath: {\n    eyebrow: string\n    mysteryPlayer: string\n    lockPosition: string\n    lockNationality: string\n    firstClub: string\n    loan: string\n    nextClubHidden: string\n    moreClubs: (k: number) => string\n    searchLabel: string\n    searchPlaceholder: string\n    solved: string\n    failed: string\n    guessesLine: (n: number) => string\n  }\n  beatTheGrid: {\n    eyebrow: string\n    filled: (n: number, total: number) => string\n    toGo: (n: number) => string\n    progressAria: (n: number, total: number) => string\n    rowAbbrev: Record<string, string>\n    pickCell: (row: string, col: string) => string\n    cellFilled: (row: string, col: string, name: string, verdict: string) => string\n    correct: string\n    wrong: string\n    closeSearch: string\n    searchLabel: (row: string, col: string) => string\n    searchPlaceholder: string\n    emptyPool: string\n    complete: string\n    summary: (correct: number, filled: number) => string\n  }\n  predictor: {\n    eyebrow: (home: string, away: string) => string\n    home: string\n    away: string\n    goalsUp: (team: string) => string\n    goalsDown: (team: string) => string\n    firstScorer: string\n    optional: string\n    searchLabel: string\n    searchPlaceholder: string\n    noScorer: string\n    save: string\n    saving: string\n    closed: string\n    saved: string\n    savedDetail: (p: { home: string; away: string; h: number; a: number; scorer: string | null }) => string\n    fullTime: (h: number, a: number) => string\n    exactScore: string\n    outcome: string\n    firstScorerRow: string\n    correct: string\n    incorrect: string\n    forFun: string\n  }\n  startingXi: {\n    eyebrow: string\n    perStarter: (n: number) => string\n    picked: (n: number) => string\n    toGo: (n: number) => string\n    pickSlot: (pos: string) => string\n    clearSlot: (pos: string, name: string) => string\n    pickFor: (pos: string) => string\n    allPicked: string\n    searchLabel: string\n    submit: string\n    submitting: string\n    locksAt: (dayTime: string) => string\n    locksSoon: string\n    pending: (n: number) => string\n    gradedLine: (correct: number) => string\n    voided: string\n  }\n  motm: {\n    title: string\n    eyebrow: string\n    voted: string\n    yourVote: string\n    youVoted: (name: string) => string\n    thanks: string\n    tapToVote: string\n    forFun: string\n  }\n  statLadder: {\n    eyebrow: string\n    question: (stat: string) => { pre: string; emph: string; post: string }\n    whoSecond: string\n    clue: (\n      c: { value: number; above: { name: string; diff: number } | null; below: { name: string; diff: number } | null },\n      stat: string,\n    ) => string\n    searchLabel: string\n    searchPlaceholder: string\n    guess: string\n    correct: string\n    wrong: (name: string) => string\n  }\n}\n\n// Onboarding presets stage 2 (contract §5): the speed dial and the two tools. The widget owns only\n// these labels and chrome (G5); every pick, price and multiplication line comes from the grid.\n// Row templates mark the numbers that are selects with {price}, {legs} and {total}; {count} is plain text.\nexport interface PresetStrings {\n  /** Locale tag sent on the grid call (contract §1). */\n  lang: 'en' | 'tr'\n  setNumbers: string\n  buildCombo: string\n  /** The round button's one fixed name: the two labels joined. */\n  dialName: string\n  maxPriceRow: string\n  minPriceRow: string\n  comboRow: string\n  /** Board 1c's second combo ask, starting high (\"Total 50 with 6 matches\"). */\n  bigComboRow: string\n  /** The pill under a singles ask: how many picks the cell holds. */\n  readyCount: (n: number) => string\n  /** The pill under a combo ask: the total the built combo reaches. */\n  readyAt: (total: number) => string\n  maxPriceDisplay: (count: number, price: number) => string\n  maxPriceMessage: (count: number, price: number) => string\n  minPriceDisplay: (count: number, price: number) => string\n  minPriceMessage: (count: number, price: number) => string\n  comboDisplay: (legs: number, total: number) => string\n  comboMessage: (legs: number, total: number) => string\n  unavailable: string\n  send: string\n  close: string\n  totalLabel: string\n  matchesLabel: string\n  fewerMatches: string\n  moreMatches: string\n  /** Accessible names of the row selects (the select announces its own value). */\n  maxPriceName: string\n  minPriceName: string\n  /** Suffix on a select option that has no picks today. */\n  notToday: string\n  /** The combo card's button (spec C5). */\n  changeCombo: string\n  /** Template for the by-market ask row: \"{market} picks today\". {market} is the dropdown. */\n  marketRow: string\n  /** Accessible name for the market dropdown combobox. */\n  marketName: string\n  /** Short market name in the dropdown (\"BTTS\", \"Over 2.5\"); falls back to the grid's labels. */\n  marketShort: (developerName: string, marketLabel: string, selectionLabel: string | null) => string\n  /** Sent-to-chat message when the user taps a market row's Send. */\n  marketMessage: (marketLabel: string, selectionLabel: string | null, count: number) => string\n  /** The greeting bubble's second ask, the Standout matches tile. */\n  standoutAsk: string\n}\n\nconst GROUP_NOUN_EN = { G: 'goalkeepers', D: 'defenders', M: 'midfielders', F: 'forwards' } as const\nconst GROUP_NOUN_TR = { G: 'kalecileri', D: 'defans oyuncuları', M: 'orta saha oyuncuları', F: 'forvetleri' } as const\nconst formatPtsEn = (n: number): string => new Intl.NumberFormat('en-GB').format(n)\nconst formatPtsTr = (n: number): string => new Intl.NumberFormat('tr-TR').format(n)\n// Player-page dates must never wrap mid-date, and ICU 72+ prints en-GB September as \"Sept\".\nconst nbsp = (s: string): string => s.replace(/\\s/g, '\\u00a0')\nconst pdDateEn = (ms: number, opts: Intl.DateTimeFormatOptions): string =>\n  nbsp(new Intl.DateTimeFormat('en-GB', opts).format(new Date(ms)).replace('Sept', 'Sep'))\nconst pdDateTr = (ms: number, opts: Intl.DateTimeFormatOptions): string =>\n  nbsp(new Intl.DateTimeFormat('tr-TR', opts).format(new Date(ms)))\n\nexport interface LocaleStrings {\n  launcherLabel: string\n  placeholder: string\n  closeChat: string\n  newConversation: string\n  moreOptions: string\n  chatDialogLabel: string\n  stopResponse: string\n  sendMessage: string\n  dismissGreeting: string\n  somethingWentWrong: string\n  retry: string\n  limitDailyCap: string\n  limitQuotaExhausted: string\n  limitAssistantPaused: string\n  showLess: string\n  showMore: (n: number) => string\n  allMarkets: (n: number) => string\n  allMarketsAria: (n: number, home: string, away: string) => string\n  oddsLabel: string\n  liveLabel: string\n  liveCard: {\n    /** Shown when no update has arrived for >120s; receives a formatted time string. */\n    stale: (time: string) => string\n    /** Card is suspended. */\n    suspended: string\n    /** Live match but no live price available. */\n    noPrice: string\n    /** Match is over. */\n    fullTime: string\n  }\n  yourMarketTag: string\n  marketFloorLabel: string\n  addToSlip: string\n  marketPrices: string\n  moreLines: string\n  hideLines: string\n  oddsMoved: (was: string, now: string, direction: string) => string\n  oddsShortened: string\n  oddsDrifted: string\n  updatedLabel: string\n  priceMovement: string\n  openingLabel: string\n  currentLabel: string\n  movementWindow: (hours: number) => string\n  notEnoughHistory: string\n  singlePricePoint: string\n  selectionSuspended: string\n  excludedSuspended: (n: number) => string\n  chartTimeLabel: (ms: number) => string\n  chartAria: (opening: string, current: string, direction: string, hours: number) => string\n  inSlip: string\n  slipAdded: string\n  slipDuplicate: string\n  slipPriceChanged: (from: string, to: string) => string\n  slipPriceNotAccepted: (from: string, to: string) => string\n  slipLoginRequired: string\n  slipSuspended: string\n  slipFailed: string\n  addAllToSlip: (n: number) => string\n  addRestToSlip: (n: number) => string\n  allInSlip: string\n  addingAllToSlip: string\n  addAllDone: (n: number) => string\n  addAllPriceMoved: (n: number) => string\n  addAllPartial: (added: number, of: number, notAdded: ReadonlyArray<readonly [string, string]>) => string\n  today: string\n  tomorrow: string\n  bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n  tabChat: string\n  tabFollowing: string\n  tabOdds: string\n  tabToday: string\n  tabFixtures: string\n  tabStandings: string\n  tabSquad: string\n  clubFixturesEmpty: string\n  clubStandingsEmpty: string\n  clubSquadEmpty: string\n  footRight: string\n  footLeft: string\n  footBoth: string\n  positionGoalkeeper: string\n  positionDefender: string\n  positionMidfielder: string\n  positionAttacker: string\n  tabRecords: string\n  clubSquadStatsEmpty: string\n  clubPlayerDetailEmpty: string\n  clubRecordsEmpty: string\n  squadViewRoster: string\n  squadViewStats: string\n  statColApps: string\n  statColGoals: string\n  statColAssists: string\n  statColRating: string\n  statColMinutes: string\n  statColYellow: string\n  statColRed: string\n  statColXg: string\n  statColShots: string\n  detailNationality: string\n  detailAge: string\n  detailHeight: string\n  detailFoot: string\n  detailSeason: string\n  clubPlayerBack: string\n  recordsTopScorers: string\n  recordsMostAppearances: string\n  recordsMostAssists: string\n  recordsSince: string\n  standingsColClub: string\n  statHeadPos: string\n  statHeadMins: string\n  statHeadGoals: string\n  statHeadAssists: string\n  statHeadYellow: string\n  statHeadRed: string\n  statHeadRating: string\n  squadStatsEyebrow: (season: string, competition: string, n: number) => string\n  squadTopScorer: (name: string, n: number) => string\n  squadTopAssists: (name: string, n: number) => string\n  detailStarted: string\n  detailMatches: string\n  detailNatShort: string\n  detailYellows: string\n  detailReds: string\n  availabilityNext: (opponent: string, isHome: boolean, kickoffMs: number | null) => string\n  availabilityAvailable: string\n  availabilityInjured: string\n  availabilitySuspended: string\n  availabilityUnavailable: string\n  availabilityNoConcerns: string\n  availabilityBack: (ms: number) => string\n  perfTitle: string\n  perfTotal: string\n  perfPer90: string\n  perfRankedAgainst: (competition: string, group: string) => string\n  perfUnranked: string\n  perfUnrankedCohort: string\n  perfUnrankedNoLeague: string\n  perfGroupShooting: string\n  perfGroupPassing: string\n  perfGroupPossession: string\n  perfGroupDefending: string\n  perfMetric: Record<string, string>\n  perfGroupNoun: Record<'G' | 'D' | 'M' | 'F', string>\n  matchLogTitle: string\n  matchLogOpponent: (name: string, isHome: boolean) => string\n  resultLetter: Record<'W' | 'D' | 'L', string>\n  logShortDate: (ms: number) => string\n  standingsColPlayed: string\n  standingsColWon: string\n  standingsColDrawn: string\n  standingsColLost: string\n  standingsColGoalDiff: string\n  standingsColPoints: string\n  gamesPlaySegment: string\n  sectionLive: string\n  yourLeagues: string\n  topLeagues: string\n  topLeaguesSub: string\n  allLeagues: string\n  seeAllFixturesLabel: (n: number) => string\n  searchLeaguesPlaceholder: string\n  noLeagueResults: string\n  clearSearchLabel: string\n  starOnLabel: string\n  starOffLabel: string\n  starredToast: string\n  unstarredToast: string\n  leagueDetailPosition: (index: number, total: number) => string\n  prevLeagueLabel: string\n  nextLeagueLabel: string\n  /** Short scoreboard badge for the fixture row's time column. The long-form phase name\n   *  for the monitor card is fullTimeLabel. */\n  halfTime: string\n  staleStates: string\n  pinLabel: string\n  unpinLabel: string\n  matchPinLabel: string\n  matchUnpinLabel: string\n  marketLimitToast: string\n  priceHistoryLabel: string\n  emptyMatchesTab: string\n  emptyOddsTab: string\n  asOf: (time: string) => string\n  graceNote: string\n  suspendedLabel: string\n  fullTimeLabel: string\n  ownGoalLabel: string\n  inSlipLabel: string\n  /** Accessible name of a match link. Both names when the card has them, else the short form. */\n  oddsUnavailable: string\n  momentumLabel: string\n  formAndH2HLabel: string\n  liveFactLabel: string\n  liveFactAsk: string\n  liveFactEarlier: (n: number) => string\n  liveFactHideEarlier: string\n  accordionRetry: string\n  accordionSuspended: string\n  tabGames: string\n  tabLeaderboard: string\n  gamesLoginRequired: string\n  back: string\n  leaderboardOffBoard: string\n  leaderboardThisWeek: string\n  leaderboardAllTime: string\n  leaderboardEmptyFreshTitle: string\n  leaderboardEmptyFreshBody: string\n  leaderboardEmptyColdTitle: string\n  leaderboardEmptyColdBody: string\n  leaderboardEmptyCta: string\n  leaderboardLastWeekLabel: string\n  leaderboardAllTimeEmpty: string\n  gamePlay: string\n  gameLocked: string\n  gameVoided: string\n  games: GamesStrings\n  presets: PresetStrings\n}\n\nconst STRINGS: Record<Locale, LocaleStrings> = {\n  en: {\n    launcherLabel: 'Chat with SensibleStats',\n    placeholder: 'Ask about a team, player or match…',\n    closeChat: 'Close chat',\n    newConversation: 'New conversation',\n    moreOptions: 'More options',\n    chatDialogLabel: 'SensibleStats chat',\n    stopResponse: 'Stop response',\n    sendMessage: 'Send message',\n    dismissGreeting: 'Dismiss',\n    somethingWentWrong: 'Something went wrong.',\n    retry: 'Retry',\n    limitDailyCap: \"You've asked all your questions for today. You can ask again tomorrow.\",\n    limitQuotaExhausted: \"The assistant can't take new questions right now. Please try again later.\",\n    limitAssistantPaused: \"The assistant isn't available right now. Please try again later.\",\n    showLess: 'Show less',\n    showMore: (n) => `Show ${n} more`,\n    allMarkets: (n) => `All markets (${n})`,\n    allMarketsAria: (n, home, away) => `All ${n} markets for ${home} v ${away}`,\n    oddsLabel: 'Odds',\n    liveLabel: 'Live',\n    liveCard: {\n      stale: (time) => `Prices from ${time}`,\n      suspended: 'Market suspended',\n      noPrice: 'No live price available',\n      fullTime: 'Full time',\n    },\n    yourMarketTag: 'Your market',\n    marketFloorLabel: 'Market price · not a value pick',\n    addToSlip: 'Add to slip',\n    marketPrices: 'Market prices',\n    moreLines: 'More lines',\n    hideLines: 'Hide lines',\n    oddsMoved: (was, now, direction) => `was ${was}, now ${now}, ${direction}`,\n    oddsShortened: 'shortened',\n    oddsDrifted: 'drifted',\n    updatedLabel: 'updated',\n    priceMovement: 'Price movement',\n    openingLabel: 'Opening',\n    currentLabel: 'Current',\n    movementWindow: (hours) => (hours % 24 === 0 ? `Last ${hours / 24}d` : `Last ${hours}h`),\n    notEnoughHistory: 'No price history recorded yet for this selection.',\n    singlePricePoint: 'Only one price recorded so far for this selection.',\n    selectionSuspended: 'This selection is not currently available to bet.',\n    excludedSuspended: (n) => `${n} suspended price${n === 1 ? '' : 's'} excluded from this chart.`,\n    chartTimeLabel: (ms) =>\n      new Intl.DateTimeFormat('en-GB', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n    chartAria: (opening, current, direction, hours) => {\n      const span = hours % 24 === 0 ? `${hours / 24} day${hours / 24 === 1 ? '' : 's'}` : `${hours} hour${hours === 1 ? '' : 's'}`\n      // A flat price has no direction word; appending an empty one leaves \", .\" for a screen reader.\n      const drift = direction ? `, ${direction}` : ''\n      return `Price movement over the last ${span}: opened at ${opening}, currently ${current}${drift}.`\n    },\n    inSlip: 'In slip',\n    slipAdded: 'Added to slip',\n    slipDuplicate: 'Already in your slip',\n    slipPriceChanged: (from, to) => `Added at ${to} (was ${from})`,\n    slipPriceNotAccepted: (from, to) => `Price moved to ${to} (was ${from}). Tap to add.`,\n    slipLoginRequired: 'Sign in to add to your slip',\n    slipSuspended: 'Market suspended',\n    slipFailed: \"Couldn't add to slip. Try again.\",\n    addAllToSlip: (n) => `Add all ${n} to slip`,\n    addRestToSlip: (n) => (n === 1 ? 'Add the last pick to slip' : `Add the other ${n} to slip`),\n    allInSlip: 'All in slip',\n    addingAllToSlip: 'Adding…',\n    addAllDone: (n) => `All ${n} added to slip`,\n    addAllPriceMoved: (n) => `All ${n} added. A price changed, so the total changed too.`,\n    addAllPartial: (added, of, notAdded) => `${added} of ${of} added. Not added: ${notAdded.map(([h, a]) => `${h} vs ${a}`).join(', ')}`,\n    today: 'Today',\n    tomorrow: 'Tomorrow',\n    bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.en, 'en', now),\n    tabChat: 'Chat',\n    tabFollowing: 'Following',\n    tabOdds: 'Odds',\n    pinLabel: 'Track odds',\n    unpinLabel: 'Stop tracking odds',\n    matchPinLabel: 'Track match',\n    matchUnpinLabel: 'Stop tracking match',\n    marketLimitToast: 'Odds limit reached — unpin one first',\n    priceHistoryLabel: 'Price history',\n    emptyMatchesTab: 'No pinned matches yet. Pin a match from the conversation to track it live.',\n    emptyOddsTab: 'No odds followed yet. Tap Price history on a price that moved to follow it here.',\n    asOf: (time) => `Prices as of ${time}`,\n    graceNote: 'Unpins on next open · or in 4 h',\n    suspendedLabel: 'Suspended',\n    fullTimeLabel: 'Full time',\n    ownGoalLabel: 'OG',\n    inSlipLabel: 'In slip',\n    oddsUnavailable: 'Odds unavailable right now',\n    momentumLabel: 'Momentum',\n    formAndH2HLabel: 'Form & Head-to-head',\n    liveFactLabel: 'Live fact',\n    liveFactAsk: 'Ask about this',\n    liveFactEarlier: (n: number) => `Earlier facts (${n})`,\n    liveFactHideEarlier: 'Hide earlier facts',\n    accordionRetry: \"Couldn't load odds — tap to retry\",\n    accordionSuspended: 'Suspended',\n    tabToday: 'Today',\n    tabFixtures: 'Fixtures',\n    tabStandings: 'Standings',\n    tabSquad: 'Squad',\n    clubFixturesEmpty: 'No fixtures yet.',\n    clubStandingsEmpty: 'Standings are not available yet.',\n    clubSquadEmpty: 'Squad is not available yet.',\n    footRight: 'Right',\n    footLeft: 'Left',\n    footBoth: 'Both',\n    positionGoalkeeper: 'Goalkeeper',\n    positionDefender: 'Defender',\n    positionMidfielder: 'Midfielder',\n    positionAttacker: 'Attacker',\n    tabRecords: 'Records',\n    clubSquadStatsEmpty: 'Squad stats are not available yet.',\n    clubPlayerDetailEmpty: 'Player details are not available.',\n    clubRecordsEmpty: 'Club records are not available yet.',\n    squadViewRoster: 'Roster',\n    squadViewStats: 'Stats',\n    statColApps: 'Apps',\n    statColGoals: 'Goals',\n    statColAssists: 'Assists',\n    statColRating: 'Rating',\n    statColMinutes: 'Minutes',\n    statColYellow: 'Yellow cards',\n    statColRed: 'Red cards',\n    statColXg: 'xG',\n    statColShots: 'Shots',\n    detailNationality: 'Nationality',\n    detailAge: 'Age',\n    detailHeight: 'Height',\n    detailFoot: 'Foot',\n    detailSeason: 'Season {season}',\n    clubPlayerBack: 'Back',\n    recordsTopScorers: 'Top scorers',\n    recordsMostAppearances: 'Most appearances',\n    recordsMostAssists: 'Most assists',\n    recordsSince: 'Since {season}',\n    standingsColClub: 'Club',\n    statHeadPos: 'Pos',\n    statHeadMins: 'Mins',\n    statHeadGoals: 'G',\n    statHeadAssists: 'A',\n    statHeadYellow: 'Y',\n    statHeadRed: 'R',\n    statHeadRating: 'Rtg',\n    squadStatsEyebrow: (season, competition, n) => `${season} ${competition} · after ${n} game${n === 1 ? '' : 's'}`,\n    squadTopScorer: (name, n) => `Top scorer: ${name} (${n})`,\n    squadTopAssists: (name, n) => `Most assists: ${name} (${n})`,\n    detailStarted: 'Started',\n    detailMatches: 'Matches',\n    detailNatShort: 'Nat.',\n    detailYellows: 'Yellows',\n    detailReds: 'Reds',\n    availabilityNext: (opponent, isHome, kickoffMs) =>\n      `Next: ${isHome ? 'vs' : 'at'} ${opponent} (${isHome ? 'H' : 'A'})` +\n      (kickoffMs !== null && kickoffMs > 0 ? ` · ${pdDateEn(kickoffMs, { weekday: 'short', day: 'numeric', month: 'short' })}` : ''),\n    availabilityAvailable: 'Available',\n    availabilityInjured: 'Injured',\n    availabilitySuspended: 'Suspended',\n    availabilityUnavailable: 'Unavailable',\n    availabilityNoConcerns: 'No fitness concerns reported',\n    availabilityBack: (ms) => `Expected back ${pdDateEn(ms, { day: 'numeric', month: 'short' })}`,\n    perfTitle: 'Season performance',\n    perfTotal: 'Total',\n    perfPer90: 'Per 90',\n    perfRankedAgainst: (competition, group) => `Ranked against ${competition} ${GROUP_NOUN_EN[group as keyof typeof GROUP_NOUN_EN] ?? group}`,\n    perfUnranked: 'Not enough minutes to rank',\n    perfUnrankedCohort: 'Not enough players in this position to rank',\n    perfUnrankedNoLeague: 'Not ranked — no league data',\n    perfGroupShooting: 'Shooting',\n    perfGroupPassing: 'Passing',\n    perfGroupPossession: 'Possession',\n    perfGroupDefending: 'Defending',\n    perfMetric: {\n      goals: 'Goals',\n      xg: 'Expected goals (xG)',\n      shots: 'Shots',\n      shotsOnTarget: 'Shots on target',\n      assists: 'Assists',\n      successfulPasses: 'Successful passes',\n      passAccuracy: 'Pass accuracy',\n      chancesCreated: 'Chances created',\n      successfulDribbles: 'Successful dribbles',\n      dribbleSuccess: 'Dribble success',\n      touches: 'Touches',\n      tacklesWon: 'Tackles won',\n      interceptions: 'Interceptions',\n      duelsWon: 'Duels won',\n    },\n    perfGroupNoun: GROUP_NOUN_EN,\n    matchLogTitle: 'Match log',\n    matchLogOpponent: (name, isHome) => (isHome ? `vs ${name}` : `at ${name}`),\n    resultLetter: { W: 'W', D: 'D', L: 'L' },\n    logShortDate: (ms) => pdDateEn(ms, { day: 'numeric', month: 'short' }),\n    standingsColPlayed: 'P',\n    standingsColWon: 'W',\n    standingsColDrawn: 'D',\n    standingsColLost: 'L',\n    standingsColGoalDiff: 'GD',\n    standingsColPoints: 'Pts',\n    gamesPlaySegment: 'Play',\n    sectionLive: 'Live',\n    yourLeagues: 'Your leagues',\n    topLeagues: 'Top leagues',\n    topLeaguesSub: 'Popular today.',\n    allLeagues: 'All leagues',\n    seeAllFixturesLabel: (n: number) => `All fixtures (${n})`,\n    searchLeaguesPlaceholder: 'Search leagues or teams',\n    noLeagueResults: 'No league or team matches that search.',\n    clearSearchLabel: 'Clear search',\n    starOnLabel: 'Add to Your leagues',\n    starOffLabel: 'Remove from Your leagues',\n    starredToast: 'Added to Your leagues.',\n    unstarredToast: 'Removed from Your leagues.',\n    leagueDetailPosition: (index: number, total: number) => `${index} of ${total}`,\n    prevLeagueLabel: 'Previous league',\n    nextLeagueLabel: 'Next league',\n    halfTime: 'HT',\n    staleStates: \"Live scores can't be updated — showing the last known state.\",\n    tabGames: 'Games',\n    tabLeaderboard: 'Leaderboard',\n    gamesLoginRequired: 'Sign in to play and climb the leaderboard',\n    back: 'Back',\n    leaderboardOffBoard: 'Outside top 50',\n    leaderboardThisWeek: 'This week',\n    leaderboardAllTime: 'All time',\n    leaderboardEmptyFreshTitle: 'New week, blank slate',\n    leaderboardEmptyFreshBody: 'No scores yet. The first fan to play a game takes #1.',\n    leaderboardEmptyColdTitle: 'Be the first up',\n    leaderboardEmptyColdBody: \"Nobody's on the board yet. Play a game and you're #1.\",\n    leaderboardEmptyCta: \"Play today's games\",\n    leaderboardLastWeekLabel: 'Last week',\n    leaderboardAllTimeEmpty: 'The all-time board fills as fans play — nothing here yet.',\n    gamePlay: 'Play',\n    gameLocked: 'Locked',\n    gameVoided: 'Voided',\n    presets: {\n      lang: 'en',\n      setNumbers: 'Set the numbers',\n      buildCombo: 'Build a combo',\n      dialName: 'Set the numbers and Build a combo',\n      maxPriceRow: '{count} picks, max {price}',\n      minPriceRow: 'Picks from {price} up',\n      comboRow: 'Combo of {legs} paying {total}',\n      bigComboRow: 'Total {total} with {legs} matches',\n      readyCount: (n) => `${n} ready`,\n      readyAt: (total) => `ready at ${total.toFixed(2)}`,\n      maxPriceDisplay: (count, price) => `${count} picks, max ${price.toFixed(2)}`,\n      maxPriceMessage: (count, price) => `Show me ${count} picks priced at ${price.toFixed(2)} or less.`,\n      minPriceDisplay: (count, price) => `${count} picks from ${price.toFixed(2)} up`,\n      minPriceMessage: (count, price) => `Show me ${count} picks priced at ${price.toFixed(2)} or more.`,\n      comboDisplay: (legs, total) => `A combo of ${legs} priced at about ${total.toFixed(1)}`,\n      comboMessage: (legs, total) => `Build me a combo of ${legs} priced at about ${total.toFixed(1)}.`,\n      unavailable: 'Not available today.',\n      send: 'Send',\n      close: 'Close',\n      totalLabel: 'Total',\n      matchesLabel: 'Matches',\n      fewerMatches: 'Fewer matches',\n      moreMatches: 'More matches',\n      maxPriceName: 'Max price',\n      minPriceName: 'Lowest price',\n      notToday: ' · not today',\n      changeCombo: 'Change total or matches',\n      marketRow: '{market} picks today',\n      marketName: 'Market',\n      marketShort: (dev, market, sel) => ({ BOTH_TEAMS_TO_SCORE: 'BTTS', DOUBLE_CHANCE: 'Double chance', FULLTIME_RESULT: 'Match winner' } as Record<string, string>)[dev]\n        ?? (dev === 'GOALS_OVER_UNDER' && sel ? sel : sel ? `${market} ${sel}` : market),\n      marketMessage: (market, sel, count) => `Show me ${count} ${sel ? `${market} – ${sel}` : market} picks.`,\n      standoutAsk: 'Standout matches today',\n    },\n    games: {\n      lang: 'en',\n      dailyChallenge: 'Daily challenge',\n      playNow: 'Play now',\n      dailyGames: 'Daily games',\n      newSetAtMidnight: 'New set at midnight',\n      matchdayGames: 'Matchday games',\n      kickoffAt: (t) => `Kick-off ${t}`,\n      statStreak: 'Streak',\n      statToday: 'Today',\n      statRank: 'Rank',\n      unitDays: 'days',\n      unitPts: 'pts',\n      worthNow: pts => `Worth ${pts} pts now`,\n      worthAfterMiss: pts => `${pts} after a miss`,\n      thisWeek: 'this week',\n      newToday: 'New today',\n      resume: 'Resume',\n      done: 'Done',\n      doneWithScore: (s) => `Done · +${formatPtsEn(s)}`,\n      locksAt: (t) => `Locks ${t}`,\n      formatPts: formatPtsEn,\n      loading: 'Loading…',\n      backToGames: 'Back to games',\n      alreadyPlayedTitle: 'Played today',\n      guess: 'Guess',\n      formatDayTime: (iso) =>\n        new Intl.DateTimeFormat('en-GB', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n      titles: {\n        'mystery-tiger': 'Mystery Player',\n        'daily-quiz': 'Daily Quiz',\n        'career-path': 'Career Path',\n        'beat-the-grid': 'Beat the Grid',\n        'guess-the-xi': 'Guess the XI',\n        'higher-or-lower': 'Higher or Lower',\n        'matchday-predictor': 'Matchday Predictor',\n        'starting-xi': 'Starting XI',\n        'stat-ladder': 'Stat Ladder',\n        'fan-motm': 'Fan MOTM',\n      },\n      taglines: {\n        'mystery-tiger': 'One player. Six guesses.',\n        'higher-or-lower': 'Who had more?',\n        'guess-the-xi': 'Name the team',\n        'daily-quiz': 'Test your club knowledge',\n        'career-path': 'Follow the clubs',\n        'beat-the-grid': 'Fill all 9 cells',\n        'matchday-predictor': 'Call the score',\n        'starting-xi': 'Pick the lineup',\n        'stat-ladder': 'Find the missing rung',\n        'fan-motm': 'Vote at full time',\n      },\n      mysteryTiger: {\n        eyebrow: 'Daily · resets 00:00',\n        labels: { position: 'POS', nationality: 'NAT', age: 'AGE', shirtNumber: 'NO.', apps: 'APPS' },\n        yourGuesses: 'Your guesses',\n        legendMatch: 'Match',\n        legendClose: 'Close',\n        legendHigher: 'Mystery is higher',\n        searchLabel: 'Guess a squad player',\n        searchPlaceholder: 'Search by name',\n        optionsLabel: 'Squad players',\n        progress: (used, total) => `${used} of ${total} guesses used`,\n        solved: 'You found them!',\n        failed: 'Out of guesses',\n        detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n      },\n      higherOrLower: {\n        eyebrow: (p) => `+${p} per correct`,\n        streak: 'Streak',\n        whoHadMore: 'Who had more',\n        season: (l) => `${l} season`,\n        higher: 'Higher',\n        lower: 'Lower',\n        vs: 'VS',\n        lastAnswer: (name, value) => `${name} had ${value}`,\n        answersSoFar: (a, total) => `${a} of ${total} answered`,\n        runOver: 'Run over',\n        perfectRun: 'Perfect run!',\n        runDetail: (c) => `${c} correct in a row · back tomorrow`,\n      },\n      guessTheXi: {\n        pitchLabel: 'Starting line-up by nationality',\n        notThem: 'Not them:',\n        whichClub: (left) => `Which club is this? · ${left} left`,\n        searchPlaceholder: 'Search clubs',\n        optionsLabel: 'Clubs',\n        solved: 'Solved!',\n        failed: 'Out of guesses',\n        detail: (n) => `${n} ${n === 1 ? 'guess' : 'guesses'} · back tomorrow`,\n        theAnswer: 'The answer',\n      },\n      dailyQuiz: {\n        questionOf: (i, n) => `Question ${i} of ${n}`,\n        results: 'Results',\n        next: 'Next',\n        previous: 'Previous',\n        submit: 'Submit',\n        submitting: 'Submitting…',\n        correctOf: (c, n) => `${c} of ${n} correct`,\n        progressAria: (i, n) => `Question ${i} of ${n}`,\n      },\n      careerPath: {\n        eyebrow: 'Oldest club first',\n        mysteryPlayer: 'Mystery player',\n        lockPosition: 'Position',\n        lockNationality: 'Nationality',\n        firstClub: 'First club',\n        loan: 'Loan',\n        nextClubHidden: 'Next club — revealed after a wrong guess',\n        moreClubs: (k) => `+ ${k} more club${k === 1 ? '' : 's'}`,\n        searchLabel: 'Who is it?',\n        searchPlaceholder: 'Search any player',\n        solved: 'Career traced!',\n        failed: 'Out of guesses',\n        guessesLine: (n) => `${n} guess${n === 1 ? '' : 'es'} · come back tomorrow`,\n      },\n      beatTheGrid: {\n        eyebrow: 'Fill each cell with a player who fits',\n        filled: (n, t) => `${n} of ${t} filled`,\n        toGo: (n) => `${n} to go`,\n        progressAria: (n, t) => `${n} of ${t} cells filled`,\n        rowAbbrev: { Goalkeeper: 'GK', Defender: 'DEF', Midfielder: 'MID', Forward: 'FWD' },\n        pickCell: (r, c) => `Pick a ${r.toLowerCase()} with ${c}`,\n        cellFilled: (r, c, name, verdict) => `${r} with ${c}: ${name}, ${verdict.toLowerCase()}`,\n        correct: 'Correct',\n        wrong: 'Wrong',\n        closeSearch: 'Close player search',\n        searchLabel: (r, c) => `Search player for ${r} × ${c}`,\n        searchPlaceholder: 'Search players',\n        emptyPool: 'No players available to search yet.',\n        complete: 'Grid complete',\n        summary: (c, f) => `${c}/${f} correct · come back tomorrow`,\n      },\n      predictor: {\n        eyebrow: (home, away) => `${home} v ${away}`,\n        home: 'Home',\n        away: 'Away',\n        goalsUp: (team) => `${team} goals up`,\n        goalsDown: (team) => `${team} goals down`,\n        firstScorer: 'First scorer',\n        optional: 'Optional',\n        searchLabel: 'Search first scorer',\n        searchPlaceholder: 'Search squad',\n        noScorer: 'No first scorer',\n        save: 'Save prediction',\n        saving: 'Saving…',\n        closed: 'Submissions are now closed',\n        saved: 'Prediction saved',\n        savedDetail: (p) =>\n          `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ${p.scorer} first` : ''} · awaiting result`,\n        fullTime: (h, a) => `Full time ${h} – ${a}`,\n        exactScore: 'Exact score',\n        outcome: 'Result (W/D/L)',\n        firstScorerRow: 'First scorer',\n        correct: 'Correct',\n        incorrect: 'Incorrect',\n        forFun: 'For fun — not in the leaderboard',\n      },\n      startingXi: {\n        eyebrow: 'Predict the lineup',\n        perStarter: (n) => `+${n} per starter`,\n        picked: (n) => `${n} of 11 picked`,\n        toGo: (n) => `${n} to go`,\n        pickSlot: (pos) => `Pick ${pos}`,\n        clearSlot: (pos, name) => `Remove ${name} from ${pos}`,\n        pickFor: (pos) => `Pick your ${pos}`,\n        allPicked: 'All 11 picked — tap a player on the pitch to swap',\n        searchLabel: 'Search squad',\n        submit: 'Lock in my XI',\n        submitting: 'Submitting…',\n        locksAt: (t) => `Locks ${t}, about an hour before kick-off`,\n        locksSoon: 'Locks about an hour before kick-off',\n        pending: (n) => `Prediction locked in (${n} players) — awaiting result`,\n        gradedLine: (c) => `${c} of 11 correct`,\n        voided: 'This game has been voided',\n      },\n      motm: {\n        title: 'Man of the Match',\n        eyebrow: 'Fan vote',\n        voted: 'Voted',\n        yourVote: 'Your vote',\n        youVoted: (name) => `You voted ${name}`,\n        thanks: \"Thanks — results aren't shown for this vote\",\n        tapToVote: 'Tap a player to vote',\n        forFun: 'For fun — unranked community vote',\n      },\n      statLadder: {\n        eyebrow: 'Last match',\n        question: (stat) => ({ pre: 'Who made the ', emph: '2nd-most', post: ` ${stat.toLowerCase()}?` }),\n        whoSecond: \"Who's 2nd?\",\n        clue: (c, stat) => {\n          const parts: string[] = []\n          if (c.above) parts.push(c.above.diff === 0 ? `the same as ${c.above.name}` : `${c.above.diff} fewer than ${c.above.name}`)\n          if (c.below) parts.push(c.below.diff === 0 ? `the same as ${c.below.name}` : `${c.below.diff} more than ${c.below.name}`)\n          return `They made ${c.value} ${stat.toLowerCase()}${parts.length ? `, ${parts.join(' and ')}` : ''}.`\n        },\n        searchLabel: 'Guess the 2nd player',\n        searchPlaceholder: 'Search squad',\n        guess: 'Guess',\n        correct: 'Correct!',\n        wrong: (name) => `Wrong — it was ${name}`,\n      },\n    },\n  },\n  tr: {\n    launcherLabel: 'SensibleStats ile sohbet et',\n    placeholder: 'Bir takım, oyuncu veya maç hakkında sor…',\n    closeChat: 'Sohbeti kapat',\n    newConversation: 'Yeni sohbet',\n    moreOptions: 'Diğer seçenekler',\n    chatDialogLabel: 'SensibleStats sohbet',\n    stopResponse: 'Yanıtı durdur',\n    sendMessage: 'Mesaj gönder',\n    dismissGreeting: 'Kapat',\n    somethingWentWrong: 'Bir şeyler ters gitti.',\n    retry: 'Tekrar dene',\n    limitDailyCap: 'Bugünlük sorularını tamamladın. Yarın yeniden sorabilirsin.',\n    limitQuotaExhausted: 'Asistan şu an yeni soru alamıyor. Lütfen daha sonra tekrar dene.',\n    limitAssistantPaused: 'Asistan şu an kullanılamıyor. Lütfen daha sonra tekrar dene.',\n    showLess: 'Daha az göster',\n    showMore: (n) => `${n} tane daha göster`,\n    allMarkets: (n) => `Tüm bahisler (${n})`,\n    allMarketsAria: (n, home, away) => `${home} - ${away}, ${n} bahsin tümü`,\n    oddsLabel: 'Oran',\n    liveLabel: 'Canlı',\n    liveCard: {\n      stale: (time) => `${time} itibarıyla fiyatlar`,\n      suspended: 'Market askıya alındı',\n      noPrice: 'Canlı fiyat mevcut değil',\n      fullTime: 'Maç bitti',\n    },\n    yourMarketTag: 'İlgilendiğin bahis',\n    marketFloorLabel: 'Piyasa oranı · değer bahsi değil',\n    addToSlip: 'Kupona ekle',\n    marketPrices: 'Piyasa fiyatları',\n    moreLines: 'Diğer çizgiler',\n    hideLines: 'Çizgileri gizle',\n    oddsMoved: (was, now, direction) => `önce ${was}, şimdi ${now}, ${direction}`,\n    oddsShortened: 'düştü',\n    oddsDrifted: 'yükseldi',\n    updatedLabel: 'güncellendi',\n    priceMovement: 'Oran hareketi',\n    openingLabel: 'Açılış',\n    currentLabel: 'Güncel',\n    movementWindow: (hours) => (hours % 24 === 0 ? `Son ${hours / 24} gün` : `Son ${hours} saat`),\n    notEnoughHistory: 'Bu seçim için henüz oran geçmişi kaydedilmedi.',\n    singlePricePoint: 'Bu seçim için şimdiye kadar yalnızca bir fiyat kaydedildi.',\n    selectionSuspended: 'Bu seçim şu anda bahse kapalı.',\n    excludedSuspended: (n) => `${n} askıya alınmış fiyat bu grafikten hariç tutuldu.`,\n    chartTimeLabel: (ms) =>\n      new Intl.DateTimeFormat('tr-TR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(ms)),\n    chartAria: (opening, current, direction, hours) => {\n      const span = hours % 24 === 0 ? `${hours / 24} gün` : `${hours} saat`\n      const drift = direction ? `, ${direction}` : ''\n      return `Son ${span} içindeki oran hareketi: ${opening} ile açıldı, şu anda ${current}${drift}.`\n    },\n    inSlip: 'Kuponda',\n    slipAdded: 'Kupona eklendi',\n    slipDuplicate: 'Bu seçim kuponunuzda zaten var',\n    slipPriceChanged: (from, to) => `${to} oranıyla eklendi (önceki ${from})`,\n    slipPriceNotAccepted: (from, to) => `Oran ${to} oldu (önceki ${from}). Eklemek için dokunun.`,\n    slipLoginRequired: 'Kupona eklemek için giriş yapın',\n    slipSuspended: 'Bu market askıya alındı',\n    slipFailed: 'Kupona eklenemedi. Tekrar deneyin.',\n    addAllToSlip: (n) => `${n} seçimi kupona ekle`,\n    addRestToSlip: (n) => (n === 1 ? 'Son seçimi kupona ekle' : `Kalan ${n} seçimi kupona ekle`),\n    allInSlip: 'Hepsi kuponda',\n    addingAllToSlip: 'Ekleniyor…',\n    addAllDone: (n) => `${n} seçim kupona eklendi`,\n    addAllPriceMoved: (n) => `${n} seçim eklendi. Bir oran değişti, toplam oran da değişti.`,\n    addAllPartial: (added, of, notAdded) => `${of} seçimden ${added} tanesi eklendi. Eklenemeyen: ${notAdded.map(([h, a]) => `${h} - ${a}`).join(', ')}`,\n    today: 'Bugün',\n    tomorrow: 'Yarın',\n    bettingKickoff: (kickoffUtc, now) => formatBettingKickoff(kickoffUtc, STRINGS.tr, 'tr', now),\n    tabChat: 'Sohbet',\n    tabFollowing: 'Takip',\n    tabOdds: 'Oranlar',\n    pinLabel: 'Oranı takip et',\n    unpinLabel: 'Oran takibini bırak',\n    matchPinLabel: 'Maçı takip et',\n    matchUnpinLabel: 'Maç takibini bırak',\n    marketLimitToast: 'Oran limiti dolu — önce birini kaldır',\n    priceHistoryLabel: 'Oran geçmişi',\n    emptyMatchesTab: 'Henüz sabitlenmiş maç yok. Canlı takip için sohbetteki bir maçı sabitle.',\n    emptyOddsTab: 'Henüz takip edilen oran yok. Değişen bir oranda Oran geçmişi düğmesine dokunarak burada takip et.',\n    asOf: (time) => `Fiyatlar ${time} itibarıyla`,\n    graceNote: 'Bir sonraki açılışta kaldırılır · en geç 4 saat',\n    suspendedLabel: 'Askıda',\n    fullTimeLabel: 'Maç sonu',\n    ownGoalLabel: 'KK',\n    inSlipLabel: 'Kuponda',\n    oddsUnavailable: 'Oranlar şu anda kullanılamıyor',\n    momentumLabel: 'Momentum',\n    formAndH2HLabel: 'Form ve Karşılıklı Maçlar',\n    liveFactLabel: 'Canlı bilgi',\n    liveFactAsk: 'Bunu sor',\n    liveFactEarlier: (n: number) => `Önceki bilgiler (${n})`,\n    liveFactHideEarlier: 'Önceki bilgileri gizle',\n    accordionRetry: 'Oranlar yüklenemedi — yeniden dene',\n    accordionSuspended: 'Askıda',\n    tabToday: 'Bugün',\n    tabFixtures: 'Fikstür',\n    tabStandings: 'Puan Durumu',\n    tabSquad: 'Kadro',\n    clubFixturesEmpty: 'Henüz fikstür yok.',\n    clubStandingsEmpty: 'Puan durumu henüz mevcut değil.',\n    clubSquadEmpty: 'Kadro henüz mevcut değil.',\n    footRight: 'Sağ',\n    footLeft: 'Sol',\n    footBoth: 'İki ayak',\n    positionGoalkeeper: 'Kaleci',\n    positionDefender: 'Defans',\n    positionMidfielder: 'Orta saha',\n    positionAttacker: 'Forvet',\n    tabRecords: 'Rekorlar',\n    clubSquadStatsEmpty: 'Kadro istatistikleri henüz mevcut değil.',\n    clubPlayerDetailEmpty: 'Oyuncu bilgileri mevcut değil.',\n    clubRecordsEmpty: 'Kulüp rekorları henüz mevcut değil.',\n    squadViewRoster: 'Kadro',\n    squadViewStats: 'İstatistik',\n    statColApps: 'Maç',\n    statColGoals: 'Gol',\n    statColAssists: 'Asist',\n    statColRating: 'Puan',\n    statColMinutes: 'Dakika',\n    statColYellow: 'Sarı kart',\n    statColRed: 'Kırmızı kart',\n    statColXg: 'xG',\n    statColShots: 'Şut',\n    detailNationality: 'Uyruk',\n    detailAge: 'Yaş',\n    detailHeight: 'Boy',\n    detailFoot: 'Ayak',\n    detailSeason: '{season} sezonu',\n    clubPlayerBack: 'Geri',\n    recordsTopScorers: 'En çok gol atanlar',\n    recordsMostAppearances: 'En çok maç yapanlar',\n    recordsMostAssists: 'En çok asist yapanlar',\n    recordsSince: '{season} sezonundan beri',\n    standingsColClub: 'Takım',\n    statHeadPos: 'Mvk',\n    statHeadMins: 'Dk',\n    statHeadGoals: 'G',\n    statHeadAssists: 'A',\n    statHeadYellow: 'S',\n    statHeadRed: 'K',\n    statHeadRating: 'Puan',\n    squadStatsEyebrow: (season, competition, n) => `${season} ${competition} · ${n} maç sonra`,\n    squadTopScorer: (name, n) => `Gol kralı: ${name} (${n})`,\n    squadTopAssists: (name, n) => `Asist lideri: ${name} (${n})`,\n    detailStarted: 'İlk 11',\n    detailMatches: 'Maç',\n    detailNatShort: 'Uyruk',\n    detailYellows: 'Sarı',\n    detailReds: 'Kırmızı',\n    availabilityNext: (opponent, isHome, kickoffMs) =>\n      `Sonraki: ${opponent} (${isHome ? 'İç\\u00a0saha' : 'Deplasman'})` +\n      (kickoffMs !== null && kickoffMs > 0 ? ` · ${pdDateTr(kickoffMs, { day: 'numeric', month: 'short', weekday: 'short' })}` : ''),\n    availabilityAvailable: 'Hazır',\n    availabilityInjured: 'Sakat',\n    availabilitySuspended: 'Cezalı',\n    availabilityUnavailable: 'Hazır değil',\n    availabilityNoConcerns: 'Sakatlık bildirimi yok',\n    availabilityBack: (ms) => `Dönüş: ${pdDateTr(ms, { day: 'numeric', month: 'short' })}`,\n    perfTitle: 'Sezon performansı',\n    perfTotal: 'Toplam',\n    perfPer90: '90 dk',\n    perfRankedAgainst: (competition, group) => `${competition} ${GROUP_NOUN_TR[group as keyof typeof GROUP_NOUN_TR] ?? group} arasında`,\n    perfUnranked: 'Sıralama için yeterli süre yok',\n    perfUnrankedCohort: 'Bu mevkide sıralama için yeterli oyuncu yok',\n    perfUnrankedNoLeague: 'Sıralanmadı — lig verisi yok',\n    perfGroupShooting: 'Şut',\n    perfGroupPassing: 'Pas',\n    perfGroupPossession: 'Top hakimiyeti',\n    perfGroupDefending: 'Savunma',\n    perfMetric: {\n      goals: 'Gol',\n      xg: 'Gol beklentisi (xG)',\n      shots: 'Şut',\n      shotsOnTarget: 'İsabetli şut',\n      assists: 'Asist',\n      successfulPasses: 'Başarılı pas',\n      passAccuracy: 'Pas isabeti',\n      chancesCreated: 'Yaratılan fırsat',\n      successfulDribbles: 'Başarılı çalım',\n      dribbleSuccess: 'Çalım başarısı',\n      touches: 'Topla buluşma',\n      tacklesWon: 'Kazanılan müdahale',\n      interceptions: 'Top kapma',\n      duelsWon: 'Kazanılan ikili mücadele',\n    },\n    perfGroupNoun: GROUP_NOUN_TR,\n    matchLogTitle: 'Maç geçmişi',\n    matchLogOpponent: (name, isHome) => (isHome ? `${name} (İ)` : `${name} (D)`),\n    resultLetter: { W: 'G', D: 'B', L: 'M' },\n    logShortDate: (ms) => pdDateTr(ms, { day: 'numeric', month: 'short' }),\n    standingsColPlayed: 'O',\n    standingsColWon: 'G',\n    standingsColDrawn: 'B',\n    standingsColLost: 'M',\n    standingsColGoalDiff: 'AV',\n    standingsColPoints: 'P',\n    gamesPlaySegment: 'Oyna',\n    sectionLive: 'Canlı',\n    yourLeagues: 'Liglerin',\n    topLeagues: 'Öne çıkan ligler',\n    topLeaguesSub: 'Bugün popüler.',\n    allLeagues: 'Tüm ligler',\n    seeAllFixturesLabel: (n: number) => `Tüm maçlar (${n})`,\n    searchLeaguesPlaceholder: 'Lig veya takım ara',\n    noLeagueResults: 'Aramana uyan lig veya takım yok.',\n    clearSearchLabel: 'Aramayı temizle',\n    starOnLabel: 'Liglerine ekle',\n    starOffLabel: 'Liglerinden çıkar',\n    starredToast: 'Liglerin bölümüne eklendi.',\n    unstarredToast: 'Liglerin bölümünden çıkarıldı.',\n    leagueDetailPosition: (index: number, total: number) => `${index} / ${total}`,\n    prevLeagueLabel: 'Önceki lig',\n    nextLeagueLabel: 'Sonraki lig',\n    halfTime: 'İY',\n    staleStates: 'Canlı skorlar güncellenemiyor — son bilinen durum gösteriliyor.',\n    tabGames: 'Oyunlar',\n    tabLeaderboard: 'Lider Tablosu',\n    gamesLoginRequired: 'Oynamak ve lider tablosuna girmek için giriş yapın',\n    back: 'Geri',\n    leaderboardOffBoard: 'İlk 50 dışında',\n    leaderboardThisWeek: 'Bu hafta',\n    leaderboardAllTime: 'Tüm zamanlar',\n    leaderboardEmptyFreshTitle: 'Yeni hafta, temiz sayfa',\n    leaderboardEmptyFreshBody: 'Henüz skor yok. Oynayan ilk taraftar 1. sıraya geçer.',\n    leaderboardEmptyColdTitle: 'İlk sen ol',\n    leaderboardEmptyColdBody: 'Panoda henüz kimse yok. Bir oyun oyna, 1. sıra senin.',\n    leaderboardEmptyCta: 'Bugünün oyunlarını oyna',\n    leaderboardLastWeekLabel: 'Geçen hafta',\n    leaderboardAllTimeEmpty: 'Tüm zamanlar panosu taraftarlar oynadıkça dolar — henüz bir şey yok.',\n    gamePlay: 'Oyna',\n    gameLocked: 'Kilitli',\n    gameVoided: 'İptal edildi',\n    presets: {\n      lang: 'tr',\n      setNumbers: 'Sayıları belirle',\n      buildCombo: 'Kombin oluştur',\n      dialName: 'Sayıları belirle ve Kombin oluştur',\n      maxPriceRow: '{count} seçim, en fazla {price}',\n      minPriceRow: '{price} ve üzeri seçimler',\n      comboRow: 'Yaklaşık {total} oranlı {legs} maçlık kombin',\n      bigComboRow: '{legs} maçla toplam {total}',\n      readyCount: (n) => `${n} hazır`,\n      readyAt: (total) => `${total.toFixed(2)} ile hazır`,\n      maxPriceDisplay: (count, price) => `${count} seçim, en fazla ${price.toFixed(2)}`,\n      maxPriceMessage: (count, price) => `${price.toFixed(2)} veya altı oranlı ${count} seçim göster.`,\n      minPriceDisplay: (count, price) => `${count} seçim, ${price.toFixed(2)} ve üzeri`,\n      minPriceMessage: (count, price) => `${price.toFixed(2)} veya üzeri oranlı ${count} seçim göster.`,\n      comboDisplay: (legs, total) => `${legs} maçlık kombin, yaklaşık ${total.toFixed(1)}`,\n      comboMessage: (legs, total) => `Yaklaşık ${total.toFixed(1)} oranlı ${legs} maçlık bir kombin hazırla.`,\n      unavailable: 'Bugün mevcut değil.',\n      send: 'Gönder',\n      close: 'Kapat',\n      totalLabel: 'Toplam',\n      matchesLabel: 'Maç sayısı',\n      fewerMatches: 'Daha az maç',\n      moreMatches: 'Daha fazla maç',\n      maxPriceName: 'En yüksek oran',\n      minPriceName: 'En düşük oran',\n      notToday: ' · bugün yok',\n      changeCombo: 'Toplamı veya maçları değiştir',\n      marketRow: 'Bugünkü {market} seçimleri',\n      marketName: 'Bahis türü',\n      marketShort: (dev, market, sel) => ({ BOTH_TEAMS_TO_SCORE: 'KG Var', DOUBLE_CHANCE: 'Çifte şans', FULLTIME_RESULT: 'Maç sonucu' } as Record<string, string>)[dev]\n        ?? (dev === 'GOALS_OVER_UNDER' && sel ? sel : sel ? `${market} ${sel}` : market),\n      marketMessage: (market, sel, count) => `${count} ${sel ? `${market} – ${sel}` : market} seçimi göster.`,\n      standoutAsk: 'Bugünün öne çıkan maçları',\n    },\n    games: {\n      lang: 'tr',\n      dailyChallenge: 'Günün meydan okuması',\n      playNow: 'Hemen oyna',\n      dailyGames: 'Günlük oyunlar',\n      newSetAtMidnight: 'Yeni set gece yarısı',\n      matchdayGames: 'Maç günü oyunları',\n      kickoffAt: (t) => `Başlama ${t}`,\n      statStreak: 'Seri',\n      statToday: 'Bugün',\n      statRank: 'Sıra',\n      unitDays: 'gün',\n      unitPts: 'puan',\n      worthNow: pts => `Şimdi ${pts} puan`,\n      worthAfterMiss: pts => `yanlışta ${pts}`,\n      thisWeek: 'bu hafta',\n      newToday: 'Bugün yeni',\n      resume: 'Devam et',\n      done: 'Tamamlandı',\n      doneWithScore: (s) => `Tamamlandı · +${formatPtsTr(s)}`,\n      locksAt: (t) => `Kilit ${t}`,\n      formatPts: formatPtsTr,\n      loading: 'Yükleniyor…',\n      backToGames: 'Oyunlara dön',\n      alreadyPlayedTitle: 'Bugün oynadın',\n      guess: 'Tahmin',\n      formatDayTime: (iso) =>\n        new Intl.DateTimeFormat('tr-TR', { weekday: 'short', hour: '2-digit', minute: '2-digit' }).format(new Date(iso)),\n      titles: {\n        'mystery-tiger': 'Gizemli Oyuncu',\n        'daily-quiz': 'Günün Testi',\n        'career-path': 'Kariyer Yolu',\n        'beat-the-grid': 'Tabloyu Tamamla',\n        'guess-the-xi': 'Bu 11 Kimin?',\n        'higher-or-lower': 'Fazla mı, Az mı?',\n        'matchday-predictor': 'Skor Tahmini',\n        'starting-xi': 'İlk 11 Tahmini',\n        'stat-ladder': 'İstatistik Merdiveni',\n        'fan-motm': 'Maçın Oyuncusu',\n      },\n      taglines: {\n        'mystery-tiger': 'Bir oyuncu. Altı tahmin.',\n        'higher-or-lower': 'Kimin daha fazlası var?',\n        'guess-the-xi': 'Takımı bil',\n        'daily-quiz': 'Kulüp bilgini sına',\n        'career-path': 'Kulüpleri takip et',\n        'beat-the-grid': '9 hücreyi doldur',\n        'matchday-predictor': 'Skoru tahmin et',\n        'starting-xi': 'İlk 11’i seç',\n        'stat-ladder': 'Eksik basamağı bul',\n        'fan-motm': 'Maç sonunda oy ver',\n      },\n      mysteryTiger: {\n        eyebrow: 'Günlük · 00:00’da yenilenir',\n        labels: { position: 'POZ', nationality: 'UYR', age: 'YAŞ', shirtNumber: 'NO.', apps: 'MAÇ' },\n        yourGuesses: 'Tahminlerin',\n        legendMatch: 'Eşleşme',\n        legendClose: 'Yakın',\n        legendHigher: 'Gizli oyuncu daha yüksek',\n        searchLabel: 'Kadrodan bir oyuncu tahmin et',\n        searchPlaceholder: 'İsimle ara',\n        optionsLabel: 'Kadro oyuncuları',\n        progress: (used, total) => `${total} tahminden ${used} kullanıldı`,\n        solved: 'Buldun!',\n        failed: 'Tahmin hakkın bitti',\n        detail: (n) => `${n} tahmin · yarın yine gel`,\n      },\n      higherOrLower: {\n        eyebrow: (p) => `Doğru başına +${p}`,\n        streak: 'Seri',\n        whoHadMore: 'Kimin daha fazlası var',\n        season: (l) => `${l} sezonu`,\n        higher: 'Daha fazla',\n        lower: 'Daha az',\n        vs: 'VS',\n        lastAnswer: (name, value) => `${name}: ${value}`,\n        answersSoFar: (a, total) => `${total} eşleşmeden ${a} yanıtlandı`,\n        runOver: 'Seri bitti',\n        perfectRun: 'Kusursuz seri!',\n        runDetail: (c) => `Üst üste ${c} doğru · yarın yine gel`,\n      },\n      guessTheXi: {\n        pitchLabel: 'Uyruklara göre ilk 11',\n        notThem: 'Bunlar değil:',\n        whichClub: (left) => `Bu hangi kulüp? · ${left} hak kaldı`,\n        searchPlaceholder: 'Kulüp ara',\n        optionsLabel: 'Kulüpler',\n        solved: 'Bildin!',\n        failed: 'Tahmin hakkın bitti',\n        detail: (n) => `${n} tahmin · yarın yine gel`,\n        theAnswer: 'Doğru cevap',\n      },\n      dailyQuiz: {\n        questionOf: (i, n) => `Soru ${i} / ${n}`,\n        results: 'Sonuçlar',\n        next: 'İleri',\n        previous: 'Önceki',\n        submit: 'Gönder',\n        submitting: 'Gönderiliyor…',\n        correctOf: (c, n) => `${n} soruda ${c} doğru`,\n        progressAria: (i, n) => `Soru ${i} / ${n}`,\n      },\n      careerPath: {\n        eyebrow: 'En eski kulüp önce',\n        mysteryPlayer: 'Gizemli oyuncu',\n        lockPosition: 'Mevki',\n        lockNationality: 'Uyruk',\n        firstClub: 'İlk kulüp',\n        loan: 'Kiralık',\n        nextClubHidden: 'Sıradaki kulüp — yanlış tahminden sonra açılır',\n        moreClubs: (k) => `+ ${k} kulüp daha`,\n        searchLabel: 'Bu kim?',\n        searchPlaceholder: 'Herhangi bir oyuncu ara',\n        solved: 'Kariyer çözüldü!',\n        failed: 'Tahmin hakkın bitti',\n        guessesLine: (n) => `${n} tahmin · yarın tekrar gel`,\n      },\n      beatTheGrid: {\n        eyebrow: 'Her hücreye uyan bir oyuncu yerleştir',\n        filled: (n, t) => `${t} hücreden ${n} dolu`,\n        toGo: (n) => `${n} kaldı`,\n        progressAria: (n, t) => `${t} hücreden ${n} dolu`,\n        rowAbbrev: { Goalkeeper: 'KL', Defender: 'DEF', Midfielder: 'OS', Forward: 'FV' },\n        pickCell: (r, c) => `${r} × ${c} için oyuncu seç`,\n        cellFilled: (r, c, name, verdict) => `${r} × ${c}: ${name}, ${verdict.toLocaleLowerCase('tr')}`,\n        correct: 'Doğru',\n        wrong: 'Yanlış',\n        closeSearch: 'Oyuncu aramayı kapat',\n        searchLabel: (r, c) => `${r} × ${c} için oyuncu ara`,\n        searchPlaceholder: 'Oyuncu ara',\n        emptyPool: 'Henüz aranacak oyuncu yok.',\n        complete: 'Tablo tamamlandı',\n        summary: (c, f) => `${f} hücrede ${c} doğru · yarın tekrar gel`,\n      },\n      predictor: {\n        eyebrow: (home, away) => `${home} - ${away}`,\n        home: 'Ev sahibi',\n        away: 'Deplasman',\n        goalsUp: (team) => `${team} golünü artır`,\n        goalsDown: (team) => `${team} golünü azalt`,\n        firstScorer: 'İlk golü atan',\n        optional: 'İsteğe bağlı',\n        searchLabel: 'İlk golcüyü ara',\n        searchPlaceholder: 'Kadroda ara',\n        noScorer: 'İlk gol yok',\n        save: 'Tahmini kaydet',\n        saving: 'Kaydediliyor…',\n        closed: 'Tahminler kapandı',\n        saved: 'Tahmin kaydedildi',\n        savedDetail: (p) =>\n          `${p.home ? `${p.home} ` : ''}${p.h}–${p.a}${p.away ? ` ${p.away}` : ''}${p.scorer ? ` · ilk gol ${p.scorer}` : ''} · sonuç bekleniyor`,\n        fullTime: (h, a) => `Maç sonu ${h} – ${a}`,\n        exactScore: 'Tam skor',\n        outcome: 'Sonuç (G/B/M)',\n        firstScorerRow: 'İlk golü atan',\n        correct: 'Doğru',\n        incorrect: 'Yanlış',\n        forFun: 'Eğlence için — sıralamaya girmez',\n      },\n      startingXi: {\n        eyebrow: 'Kadroyu tahmin et',\n        perStarter: (n) => `İlk 11 oyuncu başına +${n}`,\n        picked: (n) => `11 oyuncudan ${n} seçildi`,\n        toGo: (n) => `${n} kaldı`,\n        pickSlot: (pos) => `${pos} seç`,\n        clearSlot: (pos, name) => `${name} oyuncusunu ${pos} mevkiinden çıkar`,\n        pickFor: (pos) => `${pos} için oyuncu seç`,\n        allPicked: '11 oyuncu seçildi — değiştirmek için sahadaki oyuncuya dokun',\n        searchLabel: 'Kadroda ara',\n        submit: 'İlk 11’imi kilitle',\n        submitting: 'Gönderiliyor…',\n        locksAt: (t) => `${t} kilitlenir, başlamadan yaklaşık bir saat önce`,\n        locksSoon: 'Başlamadan yaklaşık bir saat önce kilitlenir',\n        pending: (n) => `Tahmin kilitlendi (${n} oyuncu) — sonuç bekleniyor`,\n        gradedLine: (c) => `11 oyuncudan ${c} doğru`,\n        voided: 'Bu oyun iptal edildi',\n      },\n      motm: {\n        title: 'Maçın Oyuncusu',\n        eyebrow: 'Taraftar oylaması',\n        voted: 'Oy verildi',\n        yourVote: 'Oy verdiğin',\n        youVoted: (name) => `${name} için oy verdin`,\n        thanks: 'Teşekkürler — bu oylamanın sonuçları gösterilmiyor',\n        tapToVote: 'Oy vermek için bir oyuncuya dokun',\n        forFun: 'Eğlence için — sıralamaya girmeyen taraftar oylaması',\n      },\n      statLadder: {\n        eyebrow: 'Son maç',\n        question: (stat) => ({ pre: `${stat.toLocaleLowerCase('tr')} sıralamasında `, emph: '2. sırada', post: ' kim var?' }),\n        whoSecond: '2. kim?',\n        clue: (c, stat) => {\n          const parts: string[] = []\n          if (c.above) parts.push(c.above.diff === 0 ? `${c.above.name} ile aynı` : `${c.above.name} oyuncusundan ${c.above.diff} eksik`)\n          if (c.below) parts.push(c.below.diff === 0 ? `${c.below.name} ile aynı` : `${c.below.name} oyuncusundan ${c.below.diff} fazla`)\n          return `${c.value} ${stat.toLocaleLowerCase('tr')}${parts.length ? `: ${parts.join(' ve ')}` : ''}.`\n        },\n        searchLabel: '2. oyuncuyu tahmin et',\n        searchPlaceholder: 'Kadroda ara',\n        guess: 'Tahmin et',\n        correct: 'Doğru!',\n        wrong: (name) => `Yanlış — doğru cevap ${name}`,\n      },\n    },\n  },\n}\n\nexport function resolveLocaleStrings(locale?: string): LocaleStrings {\n  return STRINGS[locale as Locale] ?? STRINGS.en\n}\n\n/** True unless the locale's language is one the widget supports other than English; a missing\n *  or unsupported locale counts as English. Matches on the language subtag, so \"tr-TR\" is Turkish. */\nexport function isEnglishLocale(locale?: string): boolean {\n  const lang = (locale ?? '').trim().toLowerCase().split(/[-_]/)[0] ?? ''\n  return lang === 'en' || !Object.prototype.hasOwnProperty.call(STRINGS, lang)\n}\n","import type { AddToSlipHandler, StatsWidgetClientOptions, UserContext } from '@sensiblestats/widget-sdk'\nimport { isEnglishLocale, resolveLocaleStrings } from './i18n'\nimport type { GamesStrings, PresetStrings } 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  /** @deprecated Ignored since widget-react 0.72.1; the widget no longer opens matches. */\n  onOpenMatch?: (match: { matchId: number }) => void | Promise<void>\n\n  // — Branding —\n  /** Operator logo; replaces the SS mark in the header and the FAB launcher. */\n  logoUrl?: string\n  /** Header title text. Default \"SensibleStats\". */\n  headerTitle?: string\n  /** CTA color → --ss-w-cta. */\n  cta?: string\n  /** Panel/surface color → --ss-w-panel. Pair with `ink`. */\n  surface?: string\n  /** Primary text color → --ss-w-ink. Pair with `surface`. */\n  ink?: string\n  /** Icon used for the pin/save toggle on matches and odds. Default \"pin\". */\n  pinIcon?: 'pin' | 'star' | 'bookmark'\n}\n\ntype UiKeys =\n  | 'theme' | 'accent' | 'position' | 'offset' | 'radius' | 'locale'\n  | 'launcherLabel' | 'greeting' | 'greetingMessage' | 'placeholder' | 'starters' | 'injectStyles'\n  | 'logoUrl' | 'headerTitle' | 'cta' | 'surface' | 'ink' | 'pinIcon'\n\nexport interface UiConfig {\n  theme: 'light' | 'dark' | 'auto'\n  accent?: string\n  position: 'left' | 'right'\n  offset: { x: number; y: number }\n  radius: number\n  /** Raw BCP-47 locale string for runtime formatting (e.g. Intl.DateTimeFormat). */\n  locale: string\n  launcherLabel: string\n  greeting?: string\n  greetingMessage?: string\n  placeholder: string\n  starters: string[]\n  injectStyles: boolean\n  logoUrl?: string\n  headerTitle?: string\n  /** The server localizes betting labels for non-English widgets (\"2.5 Üst\"), so only an English\n   *  widget can report the label it shows as the raw slip selection. */\n  rawBettingLabels: boolean\n  cta?: string\n  surface?: string\n  ink?: string\n  pinIcon: 'pin' | 'star' | 'bookmark'\n  closeChat: string\n  newConversation: string\n  moreOptions: string\n  chatDialogLabel: string\n  stopResponse: string\n  sendMessage: string\n  dismissGreeting: string\n  somethingWentWrong: string\n  retry: string\n  limitDailyCap: string\n  limitQuotaExhausted: string\n  limitAssistantPaused: string\n  showLess: string\n  showMore: (n: number) => string\n  allMarkets: (n: number) => string\n  allMarketsAria: (n: number, home: string, away: string) => string\n  oddsLabel: string\n  liveLabel: string\n  yourMarketTag: string\n  marketFloorLabel: string\n  marketPrices: string\n  moreLines: string\n  hideLines: string\n  oddsMoved: (was: string, now: string, direction: string) => string\n  oddsShortened: string\n  oddsDrifted: string\n  updatedLabel: string\n  priceMovement: string\n  openingLabel: string\n  currentLabel: string\n  movementWindow: (hours: number) => string\n  notEnoughHistory: string\n  singlePricePoint: string\n  selectionSuspended: string\n  excludedSuspended: (n: number) => string\n  chartTimeLabel: (ms: number) => string\n  chartAria: (opening: string, current: string, direction: string, hours: number) => string\n  addToSlip: string\n  inSlip: string\n  slipAdded: string\n  slipDuplicate: string\n  slipPriceChanged: (from: string, to: string) => string\n  slipPriceNotAccepted: (from: string, to: string) => string\n  slipLoginRequired: string\n  slipSuspended: string\n  slipFailed: string\n  addAllToSlip: (n: number) => string\n  addRestToSlip: (n: number) => string\n  allInSlip: string\n  addingAllToSlip: string\n  addAllDone: (n: number) => string\n  addAllPriceMoved: (n: number) => string\n  addAllPartial: (added: number, of: number, notAdded: ReadonlyArray<readonly [string, string]>) => string\n  today: string\n  tomorrow: string\n  bettingKickoff: (kickoffUtc: string, now?: Date) => { dayLabel: string; time: string }\n  tabChat: string\n  tabFollowing: string\n  tabOdds: string\n  tabToday: string\n  tabFixtures: string\n  tabStandings: string\n  tabSquad: string\n  clubFixturesEmpty: string\n  clubStandingsEmpty: string\n  clubSquadEmpty: string\n  footRight: string\n  footLeft: string\n  footBoth: string\n  positionGoalkeeper: string\n  positionDefender: string\n  positionMidfielder: string\n  positionAttacker: string\n  tabRecords: string\n  clubSquadStatsEmpty: string\n  clubPlayerDetailEmpty: string\n  clubRecordsEmpty: string\n  squadViewRoster: string\n  squadViewStats: string\n  statColApps: string\n  statColGoals: string\n  statColAssists: string\n  statColRating: string\n  statColMinutes: string\n  statColYellow: string\n  statColRed: string\n  statColXg: string\n  statColShots: string\n  detailNationality: string\n  detailAge: string\n  detailHeight: string\n  detailFoot: string\n  detailSeason: string\n  clubPlayerBack: string\n  recordsTopScorers: string\n  recordsMostAppearances: string\n  recordsMostAssists: string\n  recordsSince: string\n  standingsColClub: string\n  statHeadPos: string\n  statHeadMins: string\n  statHeadGoals: string\n  statHeadAssists: string\n  statHeadYellow: string\n  statHeadRed: string\n  statHeadRating: string\n  squadStatsEyebrow: (season: string, competition: string, n: number) => string\n  squadTopScorer: (name: string, n: number) => string\n  squadTopAssists: (name: string, n: number) => string\n  detailStarted: string\n  detailMatches: string\n  detailNatShort: string\n  detailYellows: string\n  detailReds: string\n  availabilityNext: (opponent: string, isHome: boolean, kickoffMs: number | null) => string\n  availabilityAvailable: string\n  availabilityInjured: string\n  availabilitySuspended: string\n  availabilityUnavailable: string\n  availabilityNoConcerns: string\n  availabilityBack: (ms: number) => string\n  perfTitle: string\n  perfTotal: string\n  perfPer90: string\n  perfRankedAgainst: (competition: string, group: string) => string\n  perfUnranked: string\n  perfUnrankedCohort: string\n  perfUnrankedNoLeague: string\n  perfGroupShooting: string\n  perfGroupPassing: string\n  perfGroupPossession: string\n  perfGroupDefending: string\n  perfMetric: Record<string, string>\n  perfGroupNoun: Record<'G' | 'D' | 'M' | 'F', string>\n  matchLogTitle: string\n  matchLogOpponent: (name: string, isHome: boolean) => string\n  resultLetter: Record<'W' | 'D' | 'L', string>\n  logShortDate: (ms: number) => string\n  standingsColPlayed: string\n  standingsColWon: string\n  standingsColDrawn: string\n  standingsColLost: string\n  standingsColGoalDiff: string\n  standingsColPoints: string\n  gamesPlaySegment: string\n  sectionLive: string\n  yourLeagues: string\n  topLeagues: string\n  topLeaguesSub: string\n  allLeagues: string\n  seeAllFixturesLabel: (n: number) => string\n  searchLeaguesPlaceholder: string\n  noLeagueResults: string\n  clearSearchLabel: string\n  starOnLabel: string\n  starOffLabel: string\n  starredToast: string\n  unstarredToast: string\n  leagueDetailPosition: (index: number, total: number) => string\n  prevLeagueLabel: string\n  nextLeagueLabel: string\n  halfTime: string\n  staleStates: string\n  pinLabel: string\n  unpinLabel: string\n  matchPinLabel: string\n  matchUnpinLabel: string\n  marketLimitToast: string\n  priceHistoryLabel: string\n  emptyMatchesTab: string\n  emptyOddsTab: string\n  asOf: (time: string) => string\n  graceNote: string\n  suspendedLabel: string\n  fullTimeLabel: string\n  ownGoalLabel: string\n  inSlipLabel: string\n  oddsUnavailable: string\n  momentumLabel: string\n  formAndH2HLabel: string\n  liveFactLabel: string\n  liveFactAsk: string\n  liveFactEarlier: (n: number) => string\n  liveFactHideEarlier: string\n  accordionRetry: string\n  accordionSuspended: string\n  tabGames: string\n  tabLeaderboard: string\n  gamesLoginRequired: string\n  back: string\n  leaderboardOffBoard: string\n  leaderboardThisWeek: string\n  leaderboardAllTime: string\n  leaderboardEmptyFreshTitle: string\n  leaderboardEmptyFreshBody: string\n  leaderboardEmptyColdTitle: string\n  leaderboardEmptyColdBody: string\n  leaderboardEmptyCta: string\n  leaderboardLastWeekLabel: string\n  leaderboardAllTimeEmpty: string\n  gamePlay: string\n  gameLocked: string\n  gameVoided: string\n  games: GamesStrings\n  presets: PresetStrings\n  liveCard: {\n    stale: (time: string) => string\n    suspended: string\n    noPrice: string\n    fullTime: string\n  }\n}\n\nexport function normalizeUi(cfg: Pick<StatsWidgetConfig, UiKeys>): UiConfig {\n  const strings = resolveLocaleStrings(cfg.locale)\n  return {\n    theme: cfg.theme ?? 'auto',\n    accent: cfg.accent,\n    logoUrl: cfg.logoUrl,\n    headerTitle: cfg.headerTitle,\n    locale: cfg.locale ?? 'en',\n    rawBettingLabels: isEnglishLocale(cfg.locale),\n    cta: cfg.cta,\n    surface: cfg.surface,\n    ink: cfg.ink,\n    pinIcon: cfg.pinIcon ?? 'pin',\n    position: cfg.position ?? 'right',\n    offset: { x: cfg.offset?.x ?? 20, y: cfg.offset?.y ?? 20 },\n    radius: cfg.radius ?? 16,\n    launcherLabel: cfg.launcherLabel ?? strings.launcherLabel,\n    greeting: cfg.greeting,\n    greetingMessage: cfg.greetingMessage,\n    placeholder: cfg.placeholder ?? strings.placeholder,\n    starters: cfg.starters ?? [],\n    injectStyles: cfg.injectStyles ?? true,\n    closeChat: strings.closeChat,\n    newConversation: strings.newConversation,\n    moreOptions: strings.moreOptions,\n    chatDialogLabel: strings.chatDialogLabel,\n    stopResponse: strings.stopResponse,\n    sendMessage: strings.sendMessage,\n    dismissGreeting: strings.dismissGreeting,\n    somethingWentWrong: strings.somethingWentWrong,\n    retry: strings.retry,\n    limitDailyCap: strings.limitDailyCap,\n    limitQuotaExhausted: strings.limitQuotaExhausted,\n    limitAssistantPaused: strings.limitAssistantPaused,\n    showLess: strings.showLess,\n    showMore: strings.showMore,\n    allMarkets: strings.allMarkets,\n    allMarketsAria: strings.allMarketsAria,\n    oddsLabel: strings.oddsLabel,\n    liveLabel: strings.liveLabel,\n    yourMarketTag: strings.yourMarketTag,\n    marketFloorLabel: strings.marketFloorLabel,\n    marketPrices: strings.marketPrices,\n    moreLines: strings.moreLines,\n    hideLines: strings.hideLines,\n    oddsMoved: strings.oddsMoved,\n    oddsShortened: strings.oddsShortened,\n    oddsDrifted: strings.oddsDrifted,\n    updatedLabel: strings.updatedLabel,\n    priceMovement: strings.priceMovement,\n    openingLabel: strings.openingLabel,\n    currentLabel: strings.currentLabel,\n    movementWindow: strings.movementWindow,\n    notEnoughHistory: strings.notEnoughHistory,\n    singlePricePoint: strings.singlePricePoint,\n    selectionSuspended: strings.selectionSuspended,\n    excludedSuspended: strings.excludedSuspended,\n    chartTimeLabel: strings.chartTimeLabel,\n    chartAria: strings.chartAria,\n    addToSlip: strings.addToSlip,\n    inSlip: strings.inSlip,\n    slipAdded: strings.slipAdded,\n    slipDuplicate: strings.slipDuplicate,\n    slipPriceChanged: strings.slipPriceChanged,\n    slipPriceNotAccepted: strings.slipPriceNotAccepted,\n    slipLoginRequired: strings.slipLoginRequired,\n    slipSuspended: strings.slipSuspended,\n    slipFailed: strings.slipFailed,\n    addAllToSlip: strings.addAllToSlip,\n    addRestToSlip: strings.addRestToSlip,\n    allInSlip: strings.allInSlip,\n    addingAllToSlip: strings.addingAllToSlip,\n    addAllDone: strings.addAllDone,\n    addAllPriceMoved: strings.addAllPriceMoved,\n    addAllPartial: strings.addAllPartial,\n    today: strings.today,\n    tomorrow: strings.tomorrow,\n    bettingKickoff: strings.bettingKickoff,\n    tabChat: strings.tabChat,\n    tabFollowing: strings.tabFollowing,\n    tabOdds: strings.tabOdds,\n    tabToday: strings.tabToday,\n    tabFixtures: strings.tabFixtures,\n    tabStandings: strings.tabStandings,\n    tabSquad: strings.tabSquad,\n    clubFixturesEmpty: strings.clubFixturesEmpty,\n    clubStandingsEmpty: strings.clubStandingsEmpty,\n    clubSquadEmpty: strings.clubSquadEmpty,\n    footRight: strings.footRight,\n    footLeft: strings.footLeft,\n    footBoth: strings.footBoth,\n    positionGoalkeeper: strings.positionGoalkeeper,\n    positionDefender: strings.positionDefender,\n    positionMidfielder: strings.positionMidfielder,\n    positionAttacker: strings.positionAttacker,\n    tabRecords: strings.tabRecords,\n    clubSquadStatsEmpty: strings.clubSquadStatsEmpty,\n    clubPlayerDetailEmpty: strings.clubPlayerDetailEmpty,\n    clubRecordsEmpty: strings.clubRecordsEmpty,\n    squadViewRoster: strings.squadViewRoster,\n    squadViewStats: strings.squadViewStats,\n    statColApps: strings.statColApps,\n    statColGoals: strings.statColGoals,\n    statColAssists: strings.statColAssists,\n    statColRating: strings.statColRating,\n    statColMinutes: strings.statColMinutes,\n    statColYellow: strings.statColYellow,\n    statColRed: strings.statColRed,\n    statColXg: strings.statColXg,\n    statColShots: strings.statColShots,\n    detailNationality: strings.detailNationality,\n    detailAge: strings.detailAge,\n    detailHeight: strings.detailHeight,\n    detailFoot: strings.detailFoot,\n    detailSeason: strings.detailSeason,\n    clubPlayerBack: strings.clubPlayerBack,\n    recordsTopScorers: strings.recordsTopScorers,\n    recordsMostAppearances: strings.recordsMostAppearances,\n    recordsMostAssists: strings.recordsMostAssists,\n    recordsSince: strings.recordsSince,\n    standingsColClub: strings.standingsColClub,\n    statHeadPos: strings.statHeadPos,\n    statHeadMins: strings.statHeadMins,\n    statHeadGoals: strings.statHeadGoals,\n    statHeadAssists: strings.statHeadAssists,\n    statHeadYellow: strings.statHeadYellow,\n    statHeadRed: strings.statHeadRed,\n    statHeadRating: strings.statHeadRating,\n    squadStatsEyebrow: strings.squadStatsEyebrow,\n    squadTopScorer: strings.squadTopScorer,\n    squadTopAssists: strings.squadTopAssists,\n    detailStarted: strings.detailStarted,\n    detailMatches: strings.detailMatches,\n    detailNatShort: strings.detailNatShort,\n    detailYellows: strings.detailYellows,\n    detailReds: strings.detailReds,\n    availabilityNext: strings.availabilityNext,\n    availabilityAvailable: strings.availabilityAvailable,\n    availabilityInjured: strings.availabilityInjured,\n    availabilitySuspended: strings.availabilitySuspended,\n    availabilityUnavailable: strings.availabilityUnavailable,\n    availabilityNoConcerns: strings.availabilityNoConcerns,\n    availabilityBack: strings.availabilityBack,\n    perfTitle: strings.perfTitle,\n    perfTotal: strings.perfTotal,\n    perfPer90: strings.perfPer90,\n    perfRankedAgainst: strings.perfRankedAgainst,\n    perfUnranked: strings.perfUnranked,\n    perfUnrankedCohort: strings.perfUnrankedCohort,\n    perfUnrankedNoLeague: strings.perfUnrankedNoLeague,\n    perfGroupShooting: strings.perfGroupShooting,\n    perfGroupPassing: strings.perfGroupPassing,\n    perfGroupPossession: strings.perfGroupPossession,\n    perfGroupDefending: strings.perfGroupDefending,\n    perfMetric: strings.perfMetric,\n    perfGroupNoun: strings.perfGroupNoun,\n    matchLogTitle: strings.matchLogTitle,\n    matchLogOpponent: strings.matchLogOpponent,\n    resultLetter: strings.resultLetter,\n    logShortDate: strings.logShortDate,\n    standingsColPlayed: strings.standingsColPlayed,\n    standingsColWon: strings.standingsColWon,\n    standingsColDrawn: strings.standingsColDrawn,\n    standingsColLost: strings.standingsColLost,\n    standingsColGoalDiff: strings.standingsColGoalDiff,\n    standingsColPoints: strings.standingsColPoints,\n    gamesPlaySegment: strings.gamesPlaySegment,\n    sectionLive: strings.sectionLive,\n    yourLeagues: strings.yourLeagues,\n    topLeagues: strings.topLeagues,\n    topLeaguesSub: strings.topLeaguesSub,\n    allLeagues: strings.allLeagues,\n    seeAllFixturesLabel: strings.seeAllFixturesLabel,\n    searchLeaguesPlaceholder: strings.searchLeaguesPlaceholder,\n    noLeagueResults: strings.noLeagueResults,\n    clearSearchLabel: strings.clearSearchLabel,\n    starOnLabel: strings.starOnLabel,\n    starOffLabel: strings.starOffLabel,\n    starredToast: strings.starredToast,\n    unstarredToast: strings.unstarredToast,\n    leagueDetailPosition: strings.leagueDetailPosition,\n    prevLeagueLabel: strings.prevLeagueLabel,\n    nextLeagueLabel: strings.nextLeagueLabel,\n    halfTime: strings.halfTime,\n    staleStates: strings.staleStates,\n    pinLabel: strings.pinLabel,\n    unpinLabel: strings.unpinLabel,\n    matchPinLabel: strings.matchPinLabel,\n    matchUnpinLabel: strings.matchUnpinLabel,\n    marketLimitToast: strings.marketLimitToast,\n    priceHistoryLabel: strings.priceHistoryLabel,\n    emptyMatchesTab: strings.emptyMatchesTab,\n    emptyOddsTab: strings.emptyOddsTab,\n    asOf: strings.asOf,\n    graceNote: strings.graceNote,\n    suspendedLabel: strings.suspendedLabel,\n    fullTimeLabel: strings.fullTimeLabel,\n    ownGoalLabel: strings.ownGoalLabel,\n    inSlipLabel: strings.inSlipLabel,\n    oddsUnavailable: strings.oddsUnavailable,\n    momentumLabel: strings.momentumLabel,\n    formAndH2HLabel: strings.formAndH2HLabel,\n    liveFactLabel: strings.liveFactLabel,\n    liveFactAsk: strings.liveFactAsk,\n    liveFactEarlier: strings.liveFactEarlier,\n    liveFactHideEarlier: strings.liveFactHideEarlier,\n    accordionRetry: strings.accordionRetry,\n    accordionSuspended: strings.accordionSuspended,\n    tabGames: strings.tabGames,\n    tabLeaderboard: strings.tabLeaderboard,\n    gamesLoginRequired: strings.gamesLoginRequired,\n    back: strings.back,\n    leaderboardOffBoard: strings.leaderboardOffBoard,\n    leaderboardThisWeek: strings.leaderboardThisWeek,\n    leaderboardAllTime: strings.leaderboardAllTime,\n    leaderboardEmptyFreshTitle: strings.leaderboardEmptyFreshTitle,\n    leaderboardEmptyFreshBody: strings.leaderboardEmptyFreshBody,\n    leaderboardEmptyColdTitle: strings.leaderboardEmptyColdTitle,\n    leaderboardEmptyColdBody: strings.leaderboardEmptyColdBody,\n    leaderboardEmptyCta: strings.leaderboardEmptyCta,\n    leaderboardLastWeekLabel: strings.leaderboardLastWeekLabel,\n    leaderboardAllTimeEmpty: strings.leaderboardAllTimeEmpty,\n    gamePlay: strings.gamePlay,\n    gameLocked: strings.gameLocked,\n    gameVoided: strings.gameVoided,\n    games: strings.games,\n    presets: strings.presets,\n    liveCard: strings.liveCard,\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","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, ComboCard, ComboLeg, EntityCard, MarketOddsCard, MarketOddsRow, OddsMovementCard, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { ChartGeometry, ChartSample } from './chart'\nimport { projectSeries } from './chart'\n\nexport type CardKind = 'player' | 'team' | 'generic'\nexport interface StatCell { label: string; value: string }\nexport interface CardScope { competitionId: number | null; label: string; image?: string; stats: StatCell[] }\nexport interface CardVM { id: string; kind: CardKind; name: string; image?: string; sub?: string; season?: string; scopes: CardScope[] }\nexport interface ActionVM { label: string; actionId?: string; actionRef?: string; message: string }\nexport interface ChipVM { text: string }\nexport interface InsightVM {\n  id: string\n  market: string\n  selection?: string\n  odds?: string\n  bookmaker?: string\n  isLive: boolean\n  phase?: string\n  fixture?: string\n  competition?: string\n  text: string\n  disclaimer?: string\n  matchId: number\n  matchOddsId?: number\n  marketDeveloperName?: string\n  selectionLabel?: string\n  line?: string\n  addToSlipEnabled: boolean\n  pinEnabled: boolean\n  isMarketFloor: boolean\n  oddsDecimal?: number\n  quotedAtUtc?: string\n  previousOdds?: string\n  movementDirection?: 'shortened' | 'drifted'\n  homeTeamName?: string\n  awayTeamName?: string\n  homeCrest?: string\n  awayCrest?: string\n  competitionCrest?: string\n  kickoffUtc?: string\n  kickoffLabel?: string\n}\n\nexport interface MarketOddsRowVM {\n  key: string\n  selection: string\n  selectionLabel?: string\n  line?: string\n  odds: string\n  oddsDecimal?: number\n  matchOddsId?: number\n  quotedAtUtc?: string\n  isMain: boolean\n  isSuspended: boolean\n  previousOdds?: string\n  movementDirection?: 'shortened' | 'drifted'\n}\nexport interface MarketOddsVM {\n  id: string\n  market: string\n  fixture?: string\n  homeTeamName?: string\n  awayTeamName?: string\n  homeCrest?: string\n  awayCrest?: string\n  competitionCrest?: string\n  competition?: string\n  kickoffUtc?: string\n  kickoffLabel?: string\n  bookmaker?: string\n  updatedAt?: string\n  isLive: boolean\n  matchId: number\n  mainRows: MarketOddsRowVM[]\n  moreRows: MarketOddsRowVM[]\n  disclaimer?: string\n  addToSlipEnabled: boolean\n  marketDeveloperName?: string\n  mainLine?: string\n  pinEnabled: boolean\n  /** The stat drawn inside the card, above the rows. Always statTexts[0] when statTexts is set. */\n  statText?: string\n  /** Up to 2 stats drawn inside the card, above the rows, strongest first. */\n  statTexts?: string[]\n  /** Set when the server sent the card for the market the user bets on. */\n  tag?: 'your_market'\n  /** Present when the card is for a live (in-progress) fixture. Drives the live header. */\n  live?: import('@sensiblestats/widget-sdk').MarketOddsLiveBlock | null\n  /** Open markets Following lists for the match (server count). */\n  marketCount?: number\n  /** Set on a live card restored from storage: its prices predate this page, so no slip until a live update lands. */\n  awaitingLiveUpdate?: 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 actionRef = str(action.actionRef)\n  const message = str(action.actionValue) ?? str(action.message) ?? str(action.query) ?? label\n  return { label, actionId, actionRef, message }\n}\n\nexport function toChipVM(intent: Record<string, unknown>): ChipVM | null {\n  const text = str(intent.text) ?? str(intent.label) ?? str(intent.title)\n  return text ? { text } : null\n}\n\nexport function chipFromText(text: string): ChipVM {\n  return { text }\n}\n\n// A localized label can already embed the line (TR \"2.5 Üst\") -- never append it twice.\n// Shared by every selection/line join site so they can't drift out of sync (u324).\nexport function joinSelection(label?: string, line?: string): string | undefined {\n  if (label && line && label.includes(line)) return label\n  return [label, line].filter(Boolean).join(' ') || undefined\n}\n\nexport function toInsightVM(insight: BettingInsight): InsightVM {\n  const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? ''\n  const selectionLabel = str(insight.selectionLabel)\n  const selectionLine = str(insight.line)\n  const selection = joinSelection(selectionLabel, selectionLine)\n  const value = insight.odds?.value\n  const odds = typeof value === 'number' && Number.isFinite(value) ? value.toFixed(2) : undefined\n  const oddsValue = insight.odds?.value\n  const matchOddsId = typeof insight.odds?.matchOddsId === 'number' ? insight.odds.matchOddsId : undefined\n  const home = str(insight.homeTeamName)\n  const away = str(insight.awayTeamName)\n  const fixture = home && away ? `${home} vs ${away}` : undefined\n  const competition = str(insight.competitionName)\n  const previousValue = insight.odds?.previousValue\n  const previous =\n    typeof previousValue === 'number' && Number.isFinite(previousValue) ? previousValue : undefined\n  const direction =\n    insight.odds?.movementDirection === 'shortened' || insight.odds?.movementDirection === 'drifted'\n      ? insight.odds.movementDirection\n      : undefined\n  return {\n    id: str(insight.insightId) ?? `${str(insight.ruleId) ?? 'insight'}:${num(insight.matchId) ?? ''}`,\n    market,\n    selection,\n    odds,\n    // The wire payload carries bookmakerId (not a name); render a name only if one is present.\n    bookmaker: str(insight.odds?.bookmakerName),\n    isLive: insight.odds?.isLive === true,\n    phase: str(insight.phase),\n    fixture,\n    competition,\n    text: str(insight.text) ?? '',\n    disclaimer: str(insight.disclaimer),\n    matchId: typeof insight.matchId === 'number' ? insight.matchId : 0,\n    matchOddsId,\n    marketDeveloperName: str(insight.marketDeveloperName),\n    selectionLabel: str(insight.selectionLabel),\n    line: str(insight.line),\n    addToSlipEnabled: insight.addToSlipEnabled === true,\n    pinEnabled: insight.pinEnabled === true,\n    isMarketFloor: insight.isMarketFloor === true,\n    oddsDecimal: typeof oddsValue === 'number' && Number.isFinite(oddsValue) ? oddsValue : undefined,\n    quotedAtUtc: str(insight.odds?.quotedAtUtc),\n    previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n    movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n    homeTeamName: home,\n    awayTeamName: away,\n    homeCrest: str(insight.homeTeamImagePath),\n    awayCrest: str(insight.awayTeamImagePath),\n    competitionCrest: str(insight.competitionImagePath),\n    kickoffUtc: str(insight.kickoffUtc),\n    kickoffLabel: str(insight.kickoffLabel),\n  }\n}\n\nexport function toSlipSelection(vm: InsightVM, conversationId?: string): SlipSelection | null {\n  if (vm.matchOddsId === undefined || vm.oddsDecimal === undefined) return null\n  const selection: SlipSelection = {\n    matchOddsId: vm.matchOddsId,\n    matchId: vm.matchId,\n    oddsDecimal: vm.oddsDecimal,\n  }\n  if (vm.quotedAtUtc !== undefined) selection.quotedAtUtc = vm.quotedAtUtc\n  if (vm.id !== undefined) selection.insightId = vm.id\n  if (conversationId !== undefined) selection.conversationId = conversationId\n  return selection\n}\n\nexport function toMarketOddsVM(card: MarketOddsCard): MarketOddsVM {\n  const rows = Array.isArray(card.rows) ? card.rows : []\n  const toRow = (r: MarketOddsRow, i: number): MarketOddsRowVM => {\n    const selection = joinSelection(str(r.selectionLabel), str(r.line)) ?? ''\n    const price = typeof r.price === 'number' && Number.isFinite(r.price) ? r.price : undefined\n    const previous =\n      typeof r.previousPrice === 'number' && Number.isFinite(r.previousPrice) ? r.previousPrice : undefined\n    const direction =\n      r.movementDirection === 'shortened' || r.movementDirection === 'drifted' ? r.movementDirection : undefined\n    return {\n      key: `${selection}:${str(r.line) ?? ''}:${i}`,\n      selection,\n      selectionLabel: str(r.selectionLabel),\n      line: str(r.line),\n      odds: price !== undefined ? price.toFixed(2) : '',\n      oddsDecimal: price,\n      matchOddsId: typeof r.matchOddsId === 'number' ? r.matchOddsId : undefined,\n      quotedAtUtc: str(r.quotedAtUtc),\n      isMain: r.isMainLine !== false,\n      // === true, not !== false: a server that has not shipped the field yet leaves it undefined,\n      // and undefined must read as open rather than hiding every price on the card.\n      isSuspended: r.isSuspended === true,\n      previousOdds: previous !== undefined && direction !== undefined ? previous.toFixed(2) : undefined,\n      movementDirection: previous !== undefined && direction !== undefined ? direction : undefined,\n    }\n  }\n  // A suspended selection leaves the ladder entirely, same rule the live match card follows: we do\n  // not show a price the bookmaker is not taking. If every line is suspended the card has no rows and\n  // MarketOddsCardList renders nothing for it.\n  const vms = rows.map(toRow).filter((r) => r.selection && r.odds && !r.isSuspended)\n  const home = str(card.homeTeamName)\n  const away = str(card.awayTeamName)\n  const updated = rows.map((r) => str(r.quotedAtUtc)).filter((v): v is string => !!v).sort()\n  return {\n    id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}`,\n    market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n    fixture: home && away ? `${home} vs ${away}` : undefined,\n    homeTeamName: home,\n    awayTeamName: away,\n    homeCrest: str(card.homeTeamImagePath),\n    awayCrest: str(card.awayTeamImagePath),\n    competitionCrest: str(card.competitionImagePath),\n    competition: str(card.competitionName),\n    kickoffUtc: str(card.kickoffUtc),\n    kickoffLabel: str(card.kickoffLabel),\n    bookmaker: rows.map((r) => str(r.bookmakerName)).find(Boolean),\n    updatedAt: updated.length > 0 ? updated[updated.length - 1] : undefined,\n    isLive: rows.some((r) => r.isLive === true),\n    matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n    mainRows: vms.filter((r) => r.isMain),\n    moreRows: vms.filter((r) => !r.isMain),\n    disclaimer: str(card.disclaimer),\n    addToSlipEnabled: card.addToSlipEnabled === true,\n    marketDeveloperName: str(card.marketDeveloperName),\n    mainLine: str(card.mainLine),\n    pinEnabled: card.pinEnabled === true,\n    statText: card.insight && typeof card.insight === 'object' ? str(card.insight.text) : undefined,\n    statTexts: Array.isArray(card.insights)\n      ? card.insights.map((i) => str(i?.text)).filter((t): t is string => !!t)\n      : undefined,\n    tag: card.tag === 'your_market' ? 'your_market' : undefined,\n    live: card.live ?? null,\n    marketCount: typeof card.marketCount === 'number' && Number.isFinite(card.marketCount) ? card.marketCount : undefined,\n  }\n}\n\nexport interface OddsMovementVM {\n  id: string\n  matchId: number\n  market: string\n  marketDeveloperName?: string\n  selection: string\n  selectionLabel?: string\n  line?: string\n  fixture?: string\n  competition?: string\n  bookmaker?: string\n  opening: string\n  current: string\n  direction?: 'shortened' | 'drifted'\n  windowHours: number\n  excludedCount: number\n  isSuspended: boolean\n  disclaimer?: string\n  geometry: ChartGeometry | null\n  observationCount: number\n  pinEnabled: boolean\n  matchOddsId?: number\n}\n\nexport function toOddsMovementVM(card: OddsMovementCard): OddsMovementVM {\n  const raw = Array.isArray(card.points) ? card.points : []\n  const samples: ChartSample[] = []\n  for (const p of raw) {\n    const price = typeof p.price === 'number' && Number.isFinite(p.price) ? p.price : undefined\n    const atMs = typeof p.atUtc === 'string' ? Date.parse(p.atUtc) : NaN\n    if (price === undefined || Number.isNaN(atMs)) continue\n    samples.push({ atMs, price })\n  }\n  // projectSeries trusts sample order as the time domain (samples[0]/samples[^1] become tMin/tMax)\n  // without re-checking it; every other field above is already validated, so this is the one\n  // property whose violation is otherwise invisible.\n  samples.sort((a, b) => a.atMs - b.atMs)\n\n  const asNumber = (v: unknown): number | undefined =>\n    typeof v === 'number' && Number.isFinite(v) ? v : undefined\n  const opening = asNumber(card.openingPrice)\n  const current = asNumber(card.currentPrice)\n  const home = str(card.homeTeamName)\n  const away = str(card.awayTeamName)\n  const selection = joinSelection(str(card.selectionLabel), str(card.line)) ?? ''\n  const bookmakerId = typeof card.bookmakerId === 'number' ? card.bookmakerId : ''\n\n  return {\n    id: `${typeof card.matchId === 'number' ? card.matchId : 0}:${str(card.marketDeveloperName) ?? ''}:${selection}:${bookmakerId}`,\n    matchId: typeof card.matchId === 'number' ? card.matchId : 0,\n    market: str(card.marketLabel) ?? str(card.marketDeveloperName) ?? '',\n    marketDeveloperName: str(card.marketDeveloperName),\n    selection,\n    selectionLabel: str(card.selectionLabel),\n    line: str(card.line),\n    fixture: home && away ? `${home} vs ${away}` : undefined,\n    competition: str(card.competitionName),\n    bookmaker: str(card.bookmakerName),\n    opening: opening !== undefined ? opening.toFixed(2) : '',\n    current: current !== undefined ? current.toFixed(2) : '',\n    direction:\n      card.movementDirection === 'shortened' || card.movementDirection === 'drifted'\n        ? card.movementDirection\n        : undefined,\n    windowHours: asNumber(card.windowHours) ?? 0,\n    excludedCount: asNumber(card.excludedSuspendedCount) ?? 0,\n    isSuspended: card.isSuspended === true,\n    disclaimer: str(card.disclaimer),\n    geometry: projectSeries(samples),\n    observationCount: samples.length,\n    pinEnabled: card.pinEnabled === true,\n    matchOddsId: typeof card.matchOddsId === 'number' ? card.matchOddsId : undefined,\n  }\n}\n\nexport function marketOddsRowToSlipSelection(\n  vm: MarketOddsVM, row: MarketOddsRowVM, conversationId?: string,\n): SlipSelection | null {\n  if (row.matchOddsId === undefined || row.oddsDecimal === undefined) return null\n  const selection: SlipSelection = { matchOddsId: row.matchOddsId, matchId: vm.matchId, oddsDecimal: row.oddsDecimal }\n  if (row.quotedAtUtc !== undefined) selection.quotedAtUtc = row.quotedAtUtc\n  if (conversationId !== undefined) selection.conversationId = conversationId\n  return selection\n}\n\nexport interface ComboLegVM {\n  key: string\n  matchId: number\n  homeTeamName: string\n  awayTeamName: string\n  homeCrest?: string\n  awayCrest?: string\n  competition?: string\n  kickoffUtc?: string\n  kickoffLabel?: string\n  market: string\n  marketDeveloperName: string\n  selection: string\n  selectionLabel: string\n  line?: string\n  odds: string\n  oddsDecimal: number\n  matchOddsId: number\n  quotedAtUtc?: string\n  /** Absent when the leg has no stat (stage 3 contract §3). */\n  insightId?: string\n  statText?: string\n  pinEnabled: boolean\n}\nexport interface ComboCardVM {\n  id: string\n  legs: ComboLegVM[]\n  multiplication: string\n  /** The server's note naming swapped-out legs (contract §4), shown as given. */\n  replacedNote?: string\n  addToSlipEnabled: boolean\n  /** The asked total and leg count (contract §4 `target`, `legCount`), for \"Change total or\n   *  matches\" (spec C5). Absent on a card stored before stage 2, which then shows no such button. */\n  target?: number\n  legCount?: number\n}\n\nfunction finite(v: unknown): number | undefined {\n  return typeof v === 'number' && Number.isFinite(v) ? v : undefined\n}\n\nfunction toComboLegVM(leg: ComboLeg | null | undefined): ComboLegVM | null {\n  if (!leg || typeof leg !== 'object') return null\n  const price = finite(leg.price)\n  const matchOddsId = finite(leg.matchOddsId)\n  const matchId = finite(leg.matchId)\n  const home = str(leg.homeTeamName)\n  const away = str(leg.awayTeamName)\n  const selectionLabel = str(leg.selectionLabel)\n  const insight = leg.insight && typeof leg.insight === 'object' ? leg.insight : undefined\n  const insightId = str(insight?.insightId)\n  const statText = str(insight?.text)\n  // A stat needs both its id and its text (contract §3, P1); a leg without one is drawn with no stat line.\n  const hasStat = !!insightId && !!statText\n  // P5: a leg missing any of these cannot be drawn honestly, and a card missing a leg would\n  // show a multiplication line that does not match its legs.\n  if (price === undefined || matchOddsId === undefined || matchId === undefined || !home || !away\n    || !selectionLabel) return null\n  const line = str(leg.line)\n  return {\n    key: `${matchOddsId}`,\n    matchId,\n    homeTeamName: home,\n    awayTeamName: away,\n    homeCrest: str(leg.homeTeamImagePath),\n    awayCrest: str(leg.awayTeamImagePath),\n    competition: str(leg.competitionName),\n    kickoffUtc: str(leg.kickoffUtc),\n    kickoffLabel: str(leg.kickoffLabel),\n    market: str(leg.marketLabel) ?? str(leg.marketDeveloperName) ?? '',\n    marketDeveloperName: str(leg.marketDeveloperName) ?? '',\n    selection: joinSelection(selectionLabel, line) ?? selectionLabel,\n    selectionLabel,\n    line,\n    odds: price.toFixed(2),\n    oddsDecimal: price,\n    matchOddsId,\n    quotedAtUtc: str(leg.quotedAtUtc),\n    ...(hasStat ? { insightId, statText } : {}),\n    pinEnabled: leg.pinEnabled === true,\n  }\n}\n\nexport function toComboCardVM(card: ComboCard): ComboCardVM | null {\n  const rawLegs = Array.isArray(card?.legs) ? card.legs : []\n  const multiplication = str(card?.multiplication)\n  if (rawLegs.length < 2 || !multiplication) return null\n  const legs: ComboLegVM[] = []\n  for (const raw of rawLegs) {\n    const vm = toComboLegVM(raw)\n    if (!vm) return null\n    legs.push(vm)\n  }\n  return {\n    id: str(card.comboId) ?? legs.map((l) => l.matchOddsId).join('-'),\n    legs,\n    multiplication,\n    replacedNote: str(card.replacedNote),\n    addToSlipEnabled: card.addToSlipEnabled === true,\n    target: finite(card.target),\n    legCount: finite(card.legCount),\n  }\n}\n\nexport function comboLegToSlipSelection(leg: ComboLegVM, conversationId?: string): SlipSelection {\n  const selection: SlipSelection = {\n    matchOddsId: leg.matchOddsId,\n    matchId: leg.matchId,\n    oddsDecimal: leg.oddsDecimal,\n  }\n  if (leg.insightId !== undefined) selection.insightId = leg.insightId\n  if (leg.quotedAtUtc !== undefined) selection.quotedAtUtc = leg.quotedAtUtc\n  if (conversationId !== undefined) selection.conversationId = conversationId\n  return selection\n}\n","import type { AddToSlipHandler, AddToSlipResult, LiveMonitorStatPrice, SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from './config'\nimport type { SlipAddOutcome } from './slipAdd'\n\nexport const ADD_TO_SLIP_TIMEOUT_MS = 10_000\n\nexport interface SlipToast { kind: 'success' | 'error'; text: string }\n\nexport interface SlipHandlerProps {\n  onAddToSlip?: AddToSlipHandler\n  conversationId?: string\n}\n\nexport interface SlipPickFields { matchId?: number; selection?: string; line?: string; odds?: number }\n\nexport const MAX_SELECTION = 64\nexport const MAX_LINE = 32\nexport const MAX_ODDS = 10_000\n\n// The gateway rejects the whole batch when one event breaks a length or range rule, so a value\n// that would fail validation is dropped from the pick rather than risking every queued event.\nexport function slipPickFields(selection: SlipSelection, label?: string, line?: string): SlipPickFields {\n  const fields: SlipPickFields = {}\n  if (Number.isSafeInteger(selection.matchId) && selection.matchId > 0) fields.matchId = selection.matchId\n  if (label && label.trim() && label.length <= MAX_SELECTION) fields.selection = label\n  if (line && line.trim() && line.length <= MAX_LINE) fields.line = line\n  const odds = selection.oddsDecimal\n  if (Number.isFinite(odds) && odds > 1 && odds <= MAX_ODDS) fields.odds = odds\n  return fields\n}\n\n// Shared by every market-chip renderer (stat rows, live facts): a chip only becomes a slip\n// selection when it carries a real, addable price -- otherwise there's nothing to submit.\nexport function chipSelection(market: LiveMonitorStatPrice | null | undefined, matchId: number, conversationId?: string): SlipSelection | null {\n  if (!market || !market.addToSlipEnabled || typeof market.matchOddsId !== 'number' || typeof market.price !== 'number') return null\n  const selection: SlipSelection = { matchOddsId: market.matchOddsId, matchId, oddsDecimal: market.price }\n  if (conversationId !== undefined) selection.conversationId = conversationId\n  return selection\n}\n\nexport function wasAdded(result: AddToSlipResult | void): boolean {\n  if (!result) return true\n  if (result.status === 'price_changed') return result.accepted\n  return result.status === 'added'\n}\n\nexport function isTerminal(result: AddToSlipResult | void): boolean {\n  if (!result) return true\n  if (result.status === 'price_changed') return result.accepted\n  return result.status === 'added' || result.status === 'duplicate'\n}\n\n// slip_result's `outcome`: 'added' on success (including the assumed-success void/duplicate/\n// accepted-price-change cases), else the specific reject reason string -- so a downstream\n// consumer can tell \"the user added it\" from \"why it was refused\" without re-deriving toast text.\nexport function slipOutcome(result: AddToSlipResult | void): string {\n  if (!result) return 'added'\n  switch (result.status) {\n    case 'added':\n    case 'duplicate':\n      return result.status\n    case 'price_changed':\n      return result.accepted ? 'added' : 'price_changed'\n    case 'rejected':\n      return result.reason\n  }\n}\n\nexport function resultToToast(result: AddToSlipResult | void, shownOdds: string, ui: UiConfig): SlipToast {\n  if (!result) return { kind: 'success', text: ui.slipAdded }\n  switch (result.status) {\n    case 'added':\n      return { kind: 'success', text: ui.slipAdded }\n    case 'duplicate':\n      return { kind: 'success', text: ui.slipDuplicate }\n    case 'price_changed':\n      return result.accepted\n        ? { kind: 'success', text: ui.slipPriceChanged(shownOdds, result.newOddsDecimal.toFixed(2)) }\n        : { kind: 'error', text: ui.slipPriceNotAccepted(shownOdds, result.newOddsDecimal.toFixed(2)) }\n    case 'rejected':\n      if (result.reason === 'login_required') return { kind: 'error', text: ui.slipLoginRequired }\n      if (result.reason === 'suspended') return { kind: 'error', text: ui.slipSuspended }\n      return { kind: 'error', text: result.message ?? ui.slipFailed }\n  }\n}\n\nexport type AddAllStep = 'added' | 'added_moved' | 'skip' | 'stop_login' | 'stop'\n\n// What one leg's answer does to an \"Add all\" run (plan Global Constraint 6). A refusal that is\n// about this leg goes on; one that will refuse every later leg too stops.\nexport function addAllStep(outcome: SlipAddOutcome): AddAllStep {\n  if (outcome.kind === 'failed') return 'stop'\n  const result = outcome.result\n  if (!result) return 'added'\n  switch (result.status) {\n    case 'added':\n    case 'duplicate':\n      return 'added'\n    case 'price_changed':\n      return result.accepted ? 'added_moved' : 'skip'\n    case 'rejected':\n      if (result.reason === 'login_required') return 'stop_login'\n      if (result.reason === 'limit') return 'stop'\n      return 'skip'\n  }\n}\n\nexport interface AddAllTally {\n  /** Legs the run set out to add: the ones not already in the slip. */\n  attempted: number\n  added: number\n  priceMoved: boolean\n  /** Home and away team of every leg not added, tried or not, in card order. */\n  notAdded: Array<readonly [string, string]>\n  login: boolean\n}\n\n// Never a total or a slip count: the operator owns the slip (memory: never-assume-slip-state).\nexport function addAllToast(t: AddAllTally, ui: UiConfig): SlipToast {\n  if (t.login && t.added === 0) return { kind: 'error', text: ui.slipLoginRequired }\n  if (t.added === 0) return { kind: 'error', text: ui.slipFailed }\n  if (t.notAdded.length === 0) {\n    return { kind: 'success', text: t.priceMoved ? ui.addAllPriceMoved(t.added) : ui.addAllDone(t.added) }\n  }\n  return { kind: 'error', text: ui.addAllPartial(t.added, t.attempted, t.notAdded) }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\nimport { attachHost, type HostSink, type WidgetHost } from './host'\nimport { createMatchViews } from './matchViews'\nimport { BET_REPORT_MAX, createSlipLedger, toSlipEvent } from './slipLedger'\nimport type { SlipAdd, SlipState } from './slipStateContext'\n\nexport interface HostEventsOptions {\n  host: WidgetHost | undefined\n  operatorId: string\n  /** operatorUserId of the visitor; undefined when anonymous. */\n  currentUser: string | undefined\n  logger: EventLogger | null\n  isOpen: boolean\n  closePanel: () => void\n}\n\nexport interface HostEvents {\n  slipState: SlipState\n  /** Arms the Odds tab badge for an odd the widget added to the slip. */\n  markAdded(matchOddsId: number): void\n}\n\n/** The part of the widget the operator's side can change, and what the widget reports about it. */\nexport function useHostEvents(opts: HostEventsOptions): HostEvents {\n  const { host, operatorId, currentUser, logger, isOpen, closePanel } = opts\n\n  // The two marks live here, not in the button or the monitor hook, so a host call can clear\n  // them. `added` arms the Odds tab badge; `settled` flips a button to \"In slip\".\n  const [added, setAdded] = useState<Record<number, true>>({})\n  const [settled, setSettled] = useState<Record<number, true>>({})\n  const markAdded = useCallback((matchOddsId: number) => {\n    setAdded((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n  }, [])\n  const settle = useCallback((matchOddsId: number) => {\n    setSettled((prev) => (prev[matchOddsId] ? prev : { ...prev, [matchOddsId]: true }))\n  }, [])\n  const clearMarks = useCallback((ids: readonly number[]) => {\n    const drop = (prev: Record<number, true>): Record<number, true> => {\n      if (!ids.some((id) => prev[id])) return prev\n      const next = { ...prev }\n      for (const id of ids) delete next[id]\n      return next\n    }\n    setAdded(drop)\n    setSettled(drop)\n  }, [])\n\n  const hasHost = host !== undefined\n  // Only an operator that passed a host can ever read the ledger, so only then is it written.\n  const ledger = useMemo(\n    () => (hasHost ? createSlipLedger(`ss-w-slip:${operatorId}`) : null),\n    [hasHost, operatorId],\n  )\n  const currentUserRef = useRef(currentUser)\n  currentUserRef.current = currentUser // latest-value pattern; recordAdd stays stable across logins\n  const recordAdd = useCallback((add: SlipAdd) => {\n    ledger?.record({ id: add.selection.matchOddsId, market: add.market, ...add.pick, user: currentUserRef.current })\n  }, [ledger])\n  const slipState = useMemo<SlipState>(\n    () => ({ added, settled, settle, recordAdd }),\n    [added, settled, settle, recordAdd],\n  )\n\n  const tracksViews = hasHost\n  // What this tab has already reported about match views. Keyed on the user as well, so a login\n  // or logout starts from the state stored for that visitor.\n  const views = useMemo(\n    () => (tracksViews ? createMatchViews(`ss-w-views:${operatorId}`, { user: currentUser }) : null),\n    [tracksViews, operatorId, currentUser],\n  )\n\n  // What a host call does. It lives in a ref so the attach effect below depends only on the host,\n  // while every call still sees the latest logger, ledger and user (the latest-fn pattern).\n  const sinkRef = useRef<HostSink>(() => {})\n  sinkRef.current = (command) => {\n    if (command.kind === 'matchOpened') {\n      if (views?.view(command.matchId) === 'log') {\n        logger?.log({ name: 'match_view', entityType: 'match', entityId: String(command.matchId) })\n      }\n      return\n    }\n    const name = command.kind === 'slipRemoved' ? 'slip_remove' : 'bet_placed'\n    const ids = command.kind === 'slipRemoved' ? [command.matchOddsId] : command.matchOddsIds\n    // The marks clear for any odd the host names. Only an odd the widget itself added, a ledger\n    // hit, is reported: the host passes every leg without filtering.\n    clearMarks(ids)\n    if (!ledger) return\n    let reported = 0\n    for (const id of ids) {\n      const entry = ledger.take(id, currentUser)\n      if (!entry || reported >= BET_REPORT_MAX) continue\n      reported++\n      logger?.log(toSlipEvent(name, entry))\n    }\n  }\n  useEffect(() => {\n    if (!host) return\n    return attachHost(host, (command) => sinkRef.current(command))\n  }, [host])\n\n  // A view is reported only for a visitor who has opened the panel in this tab. The first open\n  // logs what was held until then and sends it; a view is otherwise deferred and starts no\n  // request of its own. `views` changes with the user, so a login while the panel is open\n  // re-runs this for the new visitor.\n  useEffect(() => {\n    if (!isOpen || !views) return\n    const held = views.markOpened()\n    if (held.length === 0) return\n    for (const matchId of held) {\n      logger?.log({ name: 'match_view', entityType: 'match', entityId: String(matchId) })\n    }\n    void logger?.flushNow()\n  }, [isOpen, views, logger])\n\n  return { slipState, markAdded }\n}\n","export interface WidgetHost {\n  /** The user removed this selection from the operator's slip. */\n  slipRemoved(selection: { matchOddsId: number }): void\n  /** The user placed a bet. Pass every leg; the widget reports only the ones it added. */\n  betPlaced(bet: { selections: ReadonlyArray<{ matchOddsId: number }> }): void\n  /** The user opened this match's page on the operator's site. */\n  matchOpened(match: { matchId: number }): void\n}\n\nexport type HostCommand =\n  | { kind: 'slipRemoved'; matchOddsId: number }\n  | { kind: 'betPlaced'; matchOddsIds: number[] }\n  | { kind: 'matchOpened'; matchId: number }\n\nexport type HostSink = (command: HostCommand) => void\n\nexport const HOST_QUEUE_MAX = 20\n\ninterface HostState {\n  queue: HostCommand[]\n  sink: HostSink | null\n}\n\n// Keyed by the object createWidgetHost() returned. WidgetHost is an exported interface, so an\n// operator can pass an object it built by hand; that object has no entry here and stays inert.\nconst STATES = new WeakMap<WidgetHost, HostState>()\n\nexport function isValidId(value: unknown): value is number {\n  return typeof value === 'number' && Number.isSafeInteger(value) && value > 0\n}\n\n/**\n * The operator's handle for telling the widget what happened on its side. Create it once at\n * module scope and pass it as the `host` prop. Calls made while no widget is mounted are queued\n * and replayed when one attaches. No method ever throws, and creating a host touches no browser\n * API, so a module-scope host is safe under server rendering.\n */\nexport function createWidgetHost(): WidgetHost {\n  const state: HostState = { queue: [], sink: null }\n\n  const dispatch = (command: HostCommand): void => {\n    if (state.sink) {\n      state.sink(command)\n      return\n    }\n    state.queue.push(command)\n    if (state.queue.length > HOST_QUEUE_MAX) state.queue.shift()\n  }\n\n  const host: WidgetHost = {\n    // Every body sits in a try: a missing argument, a malformed one and a widget bug behind the\n    // sink all end the same way, with the call ignored.\n    slipRemoved(selection) {\n      try {\n        const id: unknown = selection.matchOddsId\n        if (isValidId(id)) dispatch({ kind: 'slipRemoved', matchOddsId: id })\n      } catch {\n        // a host method never throws into operator code\n      }\n    },\n    betPlaced(bet) {\n      try {\n        const legs: unknown = bet.selections\n        if (!Array.isArray(legs)) return\n        const ids: number[] = []\n        for (const leg of legs as ReadonlyArray<{ matchOddsId?: unknown } | null | undefined>) {\n          const id = leg?.matchOddsId\n          if (isValidId(id) && !ids.includes(id)) ids.push(id)\n        }\n        if (ids.length > 0) dispatch({ kind: 'betPlaced', matchOddsIds: ids })\n      } catch {\n        // a host method never throws into operator code\n      }\n    },\n    matchOpened(match) {\n      try {\n        const id: unknown = match.matchId\n        if (isValidId(id)) dispatch({ kind: 'matchOpened', matchId: id })\n      } catch {\n        // a host method never throws into operator code\n      }\n    },\n  }\n\n  STATES.set(host, state)\n  return host\n}\n\n/**\n * Internal: connects a mounted widget to a host, replays what was queued, and returns the detach.\n * Not exported from the package.\n */\nexport function attachHost(host: WidgetHost, sink: HostSink): () => void {\n  const state = STATES.get(host)\n  if (!state) return () => {}\n  state.sink = sink\n  const queued = state.queue\n  state.queue = []\n  for (const command of queued) {\n    try {\n      sink(command)\n    } catch {\n      // one failing command must not drop the ones queued behind it\n    }\n  }\n  return () => {\n    // A second widget may have attached since; only the current owner clears the slot.\n    if (state.sink === sink) state.sink = null\n  }\n}\n","import { isValidId } from './host'\n\nexport const VIEW_DEDUPE_MS = 30 * 60 * 1000\nexport const HELD_MAX = 5\n\n/** duplicate: seen inside the window. log: report it now. held: kept until the panel opens. */\nexport type ViewResult = 'duplicate' | 'log' | 'held'\n\nexport interface MatchViews {\n  /** A match page view, or a click on a match link. */\n  view(matchId: number): ViewResult\n  /** The panel opened. Returns the matches held until now, oldest first; empty on later opens. */\n  markOpened(): number[]\n}\n\nexport interface MatchViewsOptions {\n  /** operatorUserId of the current visitor; undefined when anonymous. */\n  user?: string\n  /** Defaults to window.sessionStorage. Pass null for a memory-only state. */\n  storage?: Storage | null\n  now?: () => number\n}\n\ninterface ViewState {\n  opened: boolean\n  seen: Record<string, number>\n  held: number[]\n}\n\nconst empty = (): ViewState => ({ opened: false, seen: {}, held: [] })\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parse(raw: string | null, user: string | undefined): ViewState {\n  if (!raw) return empty()\n  let blob: unknown\n  try {\n    blob = JSON.parse(raw)\n  } catch {\n    return empty()\n  }\n  if (!isRecord(blob) || blob.v !== 1) return empty()\n  // One visitor's panel open and held views must not count for the next visitor of the tab. A\n  // blob with no user was written while logged out and carries over to whoever logs in.\n  if (blob.user !== undefined && blob.user !== user) return empty()\n  const state = empty()\n  state.opened = blob.opened === true\n  if (isRecord(blob.seen)) {\n    for (const [key, at] of Object.entries(blob.seen)) {\n      if (typeof at === 'number' && Number.isFinite(at)) state.seen[key] = at\n    }\n  }\n  // Held ids are logged when the panel opens, so they are re-checked and capped here: a blob\n  // someone edited must not be able to put a bad id, or more events than a batch holds, on the wire.\n  if (Array.isArray(blob.held)) {\n    state.held = blob.held.filter(isValidId).slice(-HELD_MAX)\n  }\n  return state\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n  try {\n    return window.sessionStorage\n  } catch {\n    return null\n  }\n}\n\n/**\n * What this tab has already reported about match views. It lives in sessionStorage because a host\n * can remount the widget on every navigation, and memory would forget that the visitor had opened\n * the panel. After the first storage failure the state lives in memory for the rest of the mount.\n */\nexport function createMatchViews(storageKey: string, options: MatchViewsOptions = {}): MatchViews {\n  const now = options.now ?? (() => Date.now())\n  const user = options.user\n  let storage: Storage | null | undefined = options.storage\n  let memory: ViewState = empty()\n\n  const read = (): ViewState => {\n    if (storage === undefined) storage = browserStorage()\n    if (storage) {\n      try {\n        memory = parse(storage.getItem(storageKey), user)\n      } catch {\n        storage = null\n      }\n    }\n    return memory\n  }\n\n  const write = (state: ViewState): void => {\n    memory = state\n    if (!storage) return\n    try {\n      storage.setItem(storageKey, JSON.stringify({ v: 1, user, ...state }))\n    } catch {\n      storage = null\n    }\n  }\n\n  return {\n    view(matchId) {\n      const at = now()\n      const state = read()\n      for (const key of Object.keys(state.seen)) {\n        if (at - (state.seen[key] ?? 0) >= VIEW_DEDUPE_MS) delete state.seen[key]\n      }\n      const key = String(matchId)\n      if (state.seen[key] !== undefined) return 'duplicate'\n      state.seen[key] = at\n      let result: ViewResult = 'log'\n      if (!state.opened) {\n        state.held = [...state.held.filter((id) => id !== matchId), matchId].slice(-HELD_MAX)\n        result = 'held'\n      }\n      write(state)\n      return result\n    },\n    markOpened() {\n      const state = read()\n      if (state.opened) return []\n      const at = now()\n      const held = state.held\n      // Stamped now, so the dedupe window starts when the row is written, not when it was held.\n      for (const id of held) state.seen[String(id)] = at\n      write({ opened: true, seen: state.seen, held: [] })\n      return held\n    },\n  }\n}\n","import type { WidgetEventInput } from '@sensiblestats/widget-sdk'\nimport { isValidId } from './host'\nimport { MAX_LINE, MAX_ODDS, MAX_SELECTION } from './slip'\n\nexport const LEDGER_TTL_MS = 7 * 24 * 60 * 60 * 1000\nexport const LEDGER_MAX = 100\n// The most ledger hits one host call reports. The server rejects a batch of more than 50 events\n// and the logger sends its whole queue as one batch, so an uncapped bet could fail a batch and\n// lose every event in it.\nexport const BET_REPORT_MAX = 25\nconst MAX_MARKET = 128\n// The server's floor (WidgetEventBatchRequest.Odds). An event below it fails its whole batch.\nconst MIN_ODDS = 1.0001\n\nexport interface LedgerEntry {\n  /** matchOddsId */\n  id: number\n  /** market developer name */\n  market: string\n  matchId?: number\n  selection?: string\n  line?: string\n  odds?: number\n  /** operatorUserId at add time; absent for an anonymous visitor */\n  user?: string\n  /** epoch milliseconds */\n  at: number\n}\n\nexport interface SlipLedger {\n  record(entry: Omit<LedgerEntry, 'at'>): void\n  take(id: number, currentUser: string | undefined): LedgerEntry | null\n}\n\nexport interface SlipLedgerOptions {\n  /** Defaults to window.localStorage. Pass null for a memory-only ledger. */\n  storage?: Storage | null\n  now?: () => number\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction fits(value: unknown, max: number): value is string {\n  return typeof value === 'string' && value.trim().length > 0 && value.length <= max\n}\n\n// Storage is not trusted: someone can edit the blob, and one bad value in a logged event fails\n// the whole batch at the gateway. An entry that cannot be identified is dropped; a bad optional\n// field is left out and the entry kept.\nfunction clean(item: unknown): LedgerEntry | null {\n  if (!isRecord(item)) return null\n  const { id, market, at, user } = item\n  if (!isValidId(id)) return null\n  if (typeof at !== 'number' || !Number.isFinite(at)) return null\n  if (!fits(market, MAX_MARKET)) return null\n  if (user !== undefined && (typeof user !== 'string' || user.length === 0)) return null\n  const entry: LedgerEntry = { id, market, at }\n  if (typeof user === 'string') entry.user = user\n  if (isValidId(item.matchId)) entry.matchId = item.matchId\n  if (fits(item.selection, MAX_SELECTION)) entry.selection = item.selection\n  if (fits(item.line, MAX_LINE)) entry.line = item.line\n  const odds = item.odds\n  if (typeof odds === 'number' && Number.isFinite(odds) && odds >= MIN_ODDS && odds <= MAX_ODDS) entry.odds = odds\n  return entry\n}\n\nfunction parse(raw: string | null): LedgerEntry[] {\n  if (!raw) return []\n  let blob: unknown\n  try {\n    blob = JSON.parse(raw)\n  } catch {\n    return []\n  }\n  if (!isRecord(blob) || blob.v !== 1 || !Array.isArray(blob.entries)) return []\n  const entries: LedgerEntry[] = []\n  for (const item of blob.entries) {\n    const entry = clean(item)\n    if (entry) entries.push(entry)\n  }\n  return entries\n}\n\n// Null where there is no window (server rendering) and where the browser denies storage access:\n// both make this read throw.\nfunction browserStorage(): Storage | null {\n  try {\n    return window.localStorage\n  } catch {\n    return null\n  }\n}\n\n/**\n * The widget's record of its own adds, so a later slipRemoved/betPlaced from the host can be\n * reported with the fields the add logged. Every call reads storage, so two tabs share one\n * ledger. After the first storage failure the ledger keeps working from memory for the rest of\n * the mount and stops touching storage.\n */\nexport function createSlipLedger(storageKey: string, options: SlipLedgerOptions = {}): SlipLedger {\n  const now = options.now ?? (() => Date.now())\n  let storage: Storage | null | undefined = options.storage\n  // The entries last read or written. It becomes the ledger itself once storage has failed.\n  let memory: LedgerEntry[] = []\n\n  const read = (): LedgerEntry[] => {\n    if (storage === undefined) storage = browserStorage()\n    if (storage) {\n      try {\n        memory = parse(storage.getItem(storageKey))\n      } catch {\n        storage = null\n      }\n    }\n    return memory\n  }\n\n  const write = (entries: LedgerEntry[]): void => {\n    memory = entries\n    if (!storage) return\n    try {\n      storage.setItem(storageKey, JSON.stringify({ v: 1, entries }))\n    } catch {\n      storage = null\n    }\n  }\n\n  const live = (entry: LedgerEntry, at: number): boolean => at - entry.at <= LEDGER_TTL_MS\n\n  return {\n    record(entry) {\n      const at = now()\n      const cleaned = clean({ ...entry, at })\n      if (!cleaned) return\n      const kept = read().filter((e) => e.id !== cleaned.id && live(e, at))\n      // Entries are appended in time order, so the last LEDGER_MAX are the newest.\n      kept.push(cleaned)\n      write(kept.slice(-LEDGER_MAX))\n    },\n    take(id, currentUser) {\n      const at = now()\n      const entries = read().filter((e) => live(e, at))\n      const index = entries.findIndex((e) => e.id === id)\n      const entry = entries[index]\n      if (!entry) return null\n      // One user's pick must not count for the next user of a shared browser. An entry with no\n      // user was added while logged out and belongs to whoever is here now.\n      if (entry.user !== undefined && entry.user !== currentUser) return null\n      entries.splice(index, 1)\n      write(entries)\n      return entry\n    },\n  }\n}\n\n/** The wire event for a host call that hit this entry: the same fields the add logged. A field\n *  the entry lacks is undefined here and so absent from the JSON that goes out. */\nexport function toSlipEvent(name: 'slip_remove' | 'bet_placed', entry: LedgerEntry): WidgetEventInput {\n  return {\n    name, entityType: 'market', entityId: entry.market, marketDeveloperName: entry.market,\n    matchId: entry.matchId, selection: entry.selection, line: entry.line, odds: entry.odds,\n  }\n}\n","import { ENTITY_TYPE_CODES, type Conversation, type EventLogger, type GreetingDashboardLayout, type GreetingDashboardTile, type SignalEntityType, type WidgetEntityType } from '@sensiblestats/widget-sdk'\n\nexport type DashboardTapHandler = (tile: GreetingDashboardTile, index: number, layout: GreetingDashboardLayout) => void\n\n// tile.signal.entityType is a plain string on the wire (GreetingDashboardSignalRef), so a value\n// outside the union must be checked, not asserted -- an unchecked cast would let an unrecognised\n// value reach toSignalWireBody, which throws synchronously and is swallowed by the try/catch\n// below, silently dropping the tap the same way an unresolved entityId used to.\nfunction isSignalEntityType(value: string): value is SignalEntityType {\n  return Object.prototype.hasOwnProperty.call(ENTITY_TYPE_CODES, value)\n}\n\n// The server's GreetingDashboardSignalRef.entityType is PascalCase ('Team', 'Market', ...) and\n// carries a couple of values (Article/Session/Query/Conversation) that have no widget-event\n// counterpart -- those, and anything unrecognised, map to null so the caller can skip the emit\n// instead of sending a bogus entityType.\nfunction toWidgetEntityType(value: string): WidgetEntityType | null {\n  switch (value.toLowerCase()) {\n    case 'match': return 'match'\n    case 'team': return 'team'\n    case 'player': return 'player'\n    case 'competition': return 'competition'\n    case 'market': return 'market'\n    default: return null\n  }\n}\n\n/**\n * Builds the tap-to-signal side effect for a greeting dashboard tile.\n * Every tap is a MarketView signal (spec 9.4) regardless of the tile's own entity type --\n * entityType/entityId identify what was tapped, dashboardLayout/tileIndex identify where.\n *\n * `log` is threaded in as a parameter (not read via `useEventLog()`) because this module is a\n * plain factory, not a component or hook -- the caller (a component) owns the logger instance.\n */\nexport function createDashboardTapSignal(sendSignal: Conversation['sendSignal'], log?: EventLogger | null): DashboardTapHandler {\n  return (tile, index, layout) => {\n    const widgetEntityType = toWidgetEntityType(tile.signal.entityType)\n    if (widgetEntityType) {\n      log?.log({ name: 'tile_tap', entityType: widgetEntityType, entityId: tile.signal.entityId })\n    }\n    if (!isSignalEntityType(tile.signal.entityType)) return\n    // sendSignal throws synchronously with no identity configured, and its returned promise\n    // can reject on a gateway failure. Neither may break the tap -- the message this tile sent\n    // still has to reach the model even when the Interest Engine can't be reached.\n    try {\n      void sendSignal({\n        signalType: 'MarketView',\n        entityType: tile.signal.entityType,\n        entityId: tile.signal.entityId,\n        dashboardLayout: layout,\n        tileIndex: index,\n      }).catch(() => undefined)\n    } catch {\n      // ignored -- see comment above\n    }\n  }\n}\n","import type { UiConfig } from './config'\n\nexport interface ThemeAttrs {\n  'data-ss-w-theme': string\n  'data-ss-w-pos': string\n  style: Record<string, string>\n}\n\nexport function themeAttrs(ui: UiConfig): ThemeAttrs {\n  const style: Record<string, string> = {\n    '--ss-w-offset-x': `${ui.offset.x}px`,\n    '--ss-w-offset-y': `${ui.offset.y}px`,\n    '--ss-w-radius': `${ui.radius}px`,\n  }\n  if (ui.accent) style['--ss-w-accent'] = ui.accent\n  if (ui.cta) style['--ss-w-cta'] = ui.cta\n  if (ui.surface) style['--ss-w-panel'] = ui.surface\n  if (ui.ink) style['--ss-w-ink'] = ui.ink\n  if (ui.surface && ui.ink) {\n    style['--ss-w-bubble'] = 'color-mix(in srgb, var(--ss-w-ink) 5%, var(--ss-w-panel))'\n    style['--ss-w-line'] = 'color-mix(in srgb, var(--ss-w-ink) 12%, var(--ss-w-panel))'\n    style['--ss-w-faint'] = 'color-mix(in srgb, var(--ss-w-ink) 55%, var(--ss-w-panel))'\n  }\n  return { 'data-ss-w-theme': ui.theme, 'data-ss-w-pos': ui.position, style }\n}\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'\nimport type { ChatGrounding, ChatHandle, ChatInput, ChatPreset, Conversation } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { reducer, initialState, markAwaitingLiveUpdate, type Action, type WidgetState, type AssistantTurn } from './reducer'\nimport { chipFromText } from './model'\nimport { useLiveDashboardPoll } from './useLiveDashboardPoll'\nimport { readConversation, writeConversation, clearConversation } from './conversationStore'\nimport { CLIENT_CAPABILITIES } from './presets'\nimport { isLimitNotice, isPaused, limitDelayMs } from './limit'\n\n// An assistant turn counts as an answer only if it carries something to show. Deliberately\n// excludes `actions` -- follow-up chips are not answer content, so an errored turn that only\n// has fallback chips must not count as answered.\nfunction hasAnswerContent(t: AssistantTurn): boolean {\n  return !!t.text || t.cards.length > 0 || t.insights.length > 0 ||\n    t.marketOdds.length > 0 || t.oddsMovement.length > 0 || (t.comboCards?.length ?? 0) > 0 ||\n    !!t.greetingDashboard || !!t.clubFanDashboard\n}\n\n// If the server never emits a terminal event (turn_complete/error) within this window, the\n// panel would otherwise spin forever -- an async generator that just ends without yielding a\n// terminal event leaves isStreaming stuck at true, since only turn_complete/error/STOP clear it.\nexport const STREAM_FALLBACK_TIMEOUT_MS = 30_000\n\n// Next id must not collide with restored m{n} ids (React keys + live-dashboard id matching).\nfunction seedIdCounter(messages: { id: string }[]): number {\n  let max = -1\n  for (const m of messages) {\n    const n = Number(m.id.slice(1)) // ids are `m${n}`\n    if (m.id[0] === 'm' && Number.isFinite(n) && n > max) max = n\n  }\n  return max + 1\n}\n\nexport interface SendOptions {\n  actionId?: string\n  /** Opaque predefined-action-contract ref (e.g. a club-dashboard tap) — forwarded on ChatInput.actionRef. */\n  actionRef?: string\n  /** Text shown in the user bubble when it differs from the message sent upstream (e.g. an action's label). */\n  displayText?: string\n  /** Structured context for the turn (a tapped live fact) — forwarded on ChatInput.grounding. */\n  grounding?: ChatGrounding\n  /** Onboarding presets stage 2 (contract §3): set only by a preset tool's Send. */\n  preset?: ChatPreset\n}\n\nexport interface ChatController {\n  state: WidgetState\n  open(): void\n  close(): void\n  stop(): void\n  toggle(): void\n  send(text: string, opts?: SendOptions): void\n  retry(): void\n  dismissPopup(): void\n  reset(): void\n  /** Internal seam: lets the live-card poll loop apply snapshot updates to chat-message cards. */\n  _dispatch?: (action: Action) => void\n}\n\nexport function useChatStream(conversation: Conversation, starterTexts: string[], greetingMessage?: string, storageKey?: string): ChatController {\n  const boot = useMemo(() => {\n    const payload = storageKey ? readConversation(storageKey, Date.now()) : null\n    const restored = payload != null && payload !== 'expired' && payload !== 'corrupt'\n    const base = initialState(starterTexts.map(chipFromText))\n    if (restored) {\n      return { state: { ...base, messages: markAwaitingLiveUpdate(payload.messages), conversationId: payload.conversationId, starters: [] }, restored: true, stale: false }\n    }\n    return { state: base, restored: false, stale: payload === 'expired' || payload === 'corrupt' }\n  }, [])\n  const [state, dispatch] = useReducer(reducer, boot.state)\n  const idRef = useRef(seedIdCounter(boot.state.messages))\n  const handleRef = useRef<ChatHandle | null>(null)\n  const fallbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n  const stateRef = useRef(state)\n  stateRef.current = state\n  const greetedRef = useRef(boot.restored) // restored -> greeting already \"handled\" (suppressed)\n  const hydratedRef = useRef(false) // suppresses the single re-persist a cross-tab sync would echo\n\n  const restoreSeededRef = useRef(false)\n  if (!restoreSeededRef.current) {\n    restoreSeededRef.current = true\n    if (boot.restored && boot.state.conversationId) conversation.conversationId = boot.state.conversationId\n  }\n\n  const nextId = () => `m${idRef.current++}`\n\n  const clearFallbackTimer = useCallback(() => {\n    if (fallbackTimerRef.current != null) {\n      clearTimeout(fallbackTimerRef.current)\n      fallbackTimerRef.current = null\n    }\n  }, [])\n\n  // Arms a watchdog for one in-flight send. clearFallbackTimer() is called on every path that\n  // supersedes this send (a newer run(), stop(), close()) or that sees a terminal event, so a\n  // firing timer always means neither happened in time -- including the case where the async\n  // generator simply ends without ever yielding turn_complete/error: consume()'s own `finally`\n  // nulls handleRef as soon as that happens, so this cannot key off handle identity (it would\n  // already look \"stale\" and the very hang it exists to catch would go unreported).\n  const armFallbackTimer = useCallback((onFire: () => void) => {\n    clearFallbackTimer()\n    fallbackTimerRef.current = setTimeout(() => {\n      fallbackTimerRef.current = null\n      handleRef.current?.cancel()\n      handleRef.current = null\n      onFire()\n    }, STREAM_FALLBACK_TIMEOUT_MS)\n  }, [clearFallbackTimer])\n\n  const consume = useCallback((handle: ChatHandle, onError: (err: WidgetSdkError) => void) => {\n    ;(async () => {\n      try {\n        for await (const event of handle) {\n          dispatch({ kind: 'EVENT', event })\n          // The greeting's limit notice is not the end of the turn: the greeting answers after it, so its watchdog stays armed.\n          if (event.type === 'turn_complete' || (event.type === 'error' && !isLimitNotice(event.data))) 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    if (isPaused(stateRef.current.limit)) return // B4c ruling 13: every send path, Retry included, comes through run\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({\n      message: trimmed, actionId: opts?.actionId, actionRef: opts?.actionRef, grounding: opts?.grounding,\n      clientCapabilities: [...CLIENT_CAPABILITIES],\n      ...(opts?.preset ? { preset: opts.preset } : {}),\n    }, opts?.displayText)\n  }, [run])\n\n  const retry = useCallback(() => {\n    const last = stateRef.current.lastUserInput\n    if (last) run(last, stateRef.current.lastDisplayText ?? undefined)\n  }, [run])\n\n  // Auto-greeting: fire once on mount when configured (and not restored from storage). No\n  // user bubble; its response becomes the launcher popup. Fire-and-forget — failures\n  // (including a fallback timeout) are swallowed (STOP only, no visible error) since this is\n  // non-critical background chatter. Also reused by reset() to re-greet after clearing.\n  const fireGreeting = useCallback(() => {\n    const message = greetingMessage?.trim()\n    if (!message) return\n    try {\n      handleRef.current?.cancel()\n      clearFallbackTimer()\n      dispatch({ kind: 'GREETING_SENT', assistantId: nextId() })\n      const handle = conversation.send({ message, clientCapabilities: [...CLIENT_CAPABILITIES] })\n      handleRef.current = handle\n      armFallbackTimer(() => dispatch({ kind: 'STOP' }))\n      consume(handle, () => dispatch({ kind: 'STOP' }))\n    } catch {\n      dispatch({ kind: 'STOP' })\n    }\n  }, [greetingMessage, conversation, consume, clearFallbackTimer, armFallbackTimer])\n\n  useEffect(() => {\n    if (greetedRef.current) return // restored, or already greeted\n    greetedRef.current = true\n    fireGreeting()\n  }, [fireGreeting])\n\n  // B4c: re-open the composer when the limit resets (capped at LIMIT_TIMER_MAX_MS); the server judges the next turn.\n  useEffect(() => {\n    if (!state.limit) return\n    const delay = limitDelayMs(state.limit, Date.now())\n    if (delay === null) return\n    const timer = setTimeout(() => dispatch({ kind: 'LIMIT_EXPIRED' }), delay)\n    return () => clearTimeout(timer)\n  }, [state.limit])\n\n  // Clear a stale/corrupt blob once, from an effect (never during the render seed).\n  useEffect(() => {\n    if (boot.stale && storageKey) clearConversation(storageKey)\n  }, [])\n\n  // Persist only complete exchanges after each settle (never mid-stream, never the greeting).\n  // A user message is kept only when its paired assistant turn (USER_SENT always pushes\n  // [user, assistant] together) is done, non-greeting, and has real content -- this drops a\n  // trailing unanswered question (panel closed mid-stream) and an empty errored bubble alike.\n  useEffect(() => {\n    if (!storageKey || state.isStreaming) return\n    if (hydratedRef.current) { hydratedRef.current = false; return } // don't echo a sync back out\n    const msgs = state.messages\n    const persistable = msgs.filter((m, i) => {\n      if (m.role === 'user') {\n        const next = msgs[i + 1]\n        return !!next && next.role === 'assistant' && next.done && !next.isGreeting && hasAnswerContent(next)\n      }\n      return m.done && !m.isGreeting && hasAnswerContent(m)\n    })\n    if (persistable.length === 0) return\n    writeConversation(storageKey, state.conversationId, persistable, Date.now())\n  }, [storageKey, state.isStreaming, state.messages, state.conversationId])\n\n  // Live multi-tab sync: mirror another tab's write/clear of the shared conversation.\n  useEffect(() => {\n    if (!storageKey) return\n    const onStorage = (e: StorageEvent) => {\n      if (e.key !== storageKey || e.storageArea !== window.localStorage) return\n      if (stateRef.current.isStreaming) return // never clobber an in-flight turn in this tab\n      if (e.newValue == null) {\n        // cleared elsewhere (New conversation / expiry) -> mirror a fresh conversation\n        idRef.current = 0\n        conversation.conversationId = undefined\n        hydratedRef.current = true\n        dispatch({ kind: 'RESET' })\n        greetedRef.current = true\n        fireGreeting()\n        return\n      }\n      const parsed = readConversation(storageKey, Date.now())\n      if (!parsed || parsed === 'expired' || parsed === 'corrupt') return\n      idRef.current = seedIdCounter(parsed.messages)\n      conversation.conversationId = parsed.conversationId ?? undefined\n      hydratedRef.current = true\n      dispatch({ kind: 'RESTORE', messages: parsed.messages, conversationId: parsed.conversationId })\n    }\n    window.addEventListener('storage', onStorage)\n    return () => window.removeEventListener('storage', onStorage)\n  }, [storageKey, conversation, fireGreeting])\n\n  const open = useCallback(() => dispatch({ kind: 'OPEN' }), [])\n  const close = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'CLOSE' }) }, [clearFallbackTimer])\n  const stop = useCallback(() => { handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer(); dispatch({ kind: 'STOP' }) }, [clearFallbackTimer])\n  const toggle = useCallback(() => { if (stateRef.current.isOpen) close(); else open() }, [close, open])\n  const dismissPopup = useCallback(() => dispatch({ kind: 'DISMISS_POPUP' }), [])\n\n  const reset = useCallback(() => {\n    handleRef.current?.cancel(); handleRef.current = null; clearFallbackTimer()\n    if (storageKey) clearConversation(storageKey)\n    idRef.current = 0\n    conversation.conversationId = undefined\n    dispatch({ kind: 'RESET' })\n    greetedRef.current = true\n    fireGreeting()\n  }, [storageKey, conversation, clearFallbackTimer, fireGreeting])\n\n  const getLiveDashboard = useCallback(() => conversation.getLiveDashboard(), [conversation])\n  useLiveDashboardPoll({ messages: state.messages, dispatch, getLiveDashboard })\n\n  return { state, open, close, stop, toggle, send, retry, dismissPopup, reset, _dispatch: dispatch }\n}\n","import type { ChatEvent, ChatInput, ClubFanDashboardCard, ClubFanDashboardPayload, GreetingDashboard, MarketOddsLiveBlock, StreamErrorEventData } from '@sensiblestats/widget-sdk'\nimport { WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { toActionVM, toCardVM, toChipVM, toComboCardVM, toInsightVM, toMarketOddsVM, toOddsMovementVM, type ActionVM, type CardVM, type ChipVM, type ComboCardVM, type InsightVM, type MarketOddsRowVM, type MarketOddsVM, type OddsMovementVM } from './model'\nimport { limitFromError, limitFromEvent, type LimitState } from './limit'\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[]; comboCards?: ComboCardVM[]; done: boolean; isGreeting?: boolean; greetingDashboard?: GreetingDashboard; clubFanDashboard?: ClubFanDashboardPayload }\nexport type Message = UserMessage | AssistantTurn\n\nexport interface WidgetState {\n  isOpen: boolean\n  messages: Message[]\n  isStreaming: boolean\n  status: string | null\n  actionsLoading: boolean\n  starters: ChipVM[]\n  configuredStarters: ChipVM[]\n  error: StreamErrorEventData | WidgetSdkError | null\n  lastUserInput: ChatInput | null\n  lastDisplayText: string | null\n  // Launcher popup text (the auto-greeting response). Cleared on open/dismiss.\n  popupText: string | null\n  conversationId: string | null\n  // B4c: the brand's limit; kept across RESET, never persisted (ruling 11).\n  limit: LimitState | null\n}\n\nexport type Action =\n  | { kind: 'OPEN' }\n  | { kind: 'CLOSE' }\n  | { kind: 'USER_SENT'; input: ChatInput; userId: string; assistantId: string; displayText?: string }\n  | { kind: 'GREETING_SENT'; assistantId: string }\n  | { kind: 'EVENT'; event: ChatEvent }\n  | { kind: 'STREAM_ERROR'; error: WidgetSdkError }\n  | { kind: 'STOP' }\n  | { kind: 'DISMISS_POPUP' }\n  | { kind: 'LIVE_REFRESH'; messageId: string; cards: ClubFanDashboardCard[]; greeting?: string }\n  | { kind: 'LIVE_TRANSITION'; messageId: string; dashboard: ClubFanDashboardPayload }\n  | { kind: 'UPDATE_LIVE_CARD'; matchId: number; live: MarketOddsLiveBlock; mainRows: MarketOddsRowVM[]; moreRows: MarketOddsRowVM[]; addToSlipEnabled: boolean }\n  | { kind: 'RESET' }\n  | { kind: 'RESTORE'; messages: Message[]; conversationId: string | null }\n  | { kind: 'LIMIT_EXPIRED' }\n\nconst POPUP_MAX = 160\n\n/** Live cards read back from storage carry prices from before this tab saw them, so they wait for\n *  a live update (D13). A card this tab already holds keeps its own flag: another tab's write must\n *  not re-mark a card this tab has updated live. With no `held`, every live card is marked. */\nexport function markAwaitingLiveUpdate(messages: Message[], held: Message[] = []): Message[] {\n  if (!messages.some((m) => m.role === 'assistant' && m.marketOdds.some((vm) => vm.live != null))) return messages\n  const heldFlags = new Map<string, boolean>()\n  for (const m of held) {\n    if (m.role !== 'assistant') continue\n    for (const vm of m.marketOdds) if (vm.live != null) heldFlags.set(`${m.id}|${vm.id}`, vm.awaitingLiveUpdate === true)\n  }\n  return messages.map((m) => {\n    if (m.role !== 'assistant' || !m.marketOdds.some((vm) => vm.live != null)) return m\n    return {\n      ...m,\n      marketOdds: m.marketOdds.map((vm) =>\n        vm.live != null ? { ...vm, awaitingLiveUpdate: heldFlags.get(`${m.id}|${vm.id}`) ?? true } : vm),\n    }\n  })\n}\n\nexport function initialState(starters: ChipVM[]): WidgetState {\n  return { isOpen: false, messages: [], isStreaming: false, status: null, actionsLoading: false, starters, configuredStarters: starters, error: null, lastUserInput: null, lastDisplayText: null, popupText: null, conversationId: null, limit: 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\n// B4c ruling 8: a refused turn ends without the generic error and its Retry button; the panel shows the limit instead.\nfunction settleRefused(state: WidgetState, limit: LimitState): WidgetState {\n  return { ...state, limit, error: null, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n}\n\n// B4c ruling 12: only a completed plain typed turn proves the limit is gone. Under pause_questions a chip, card tap,\n// grounded ask or preset can be admitted while typed questions are still refused.\nfunction isPlainInput(input: ChatInput | null): boolean {\n  return !!input && !input.actionRef && !input.actionId && !input.grounding && !input.preset\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 'combo_card': {\n      const vm = toComboCardVM(event.data.card)\n      if (!vm) return state\n      return { ...state, messages: mapActive(state, (t) => ({ ...t, comboCards: [...(t.comboCards ?? []), vm] })) }\n    }\n    case 'odds_movement':\n      return { ...state, messages: mapActive(state, (t) => ({ ...t, oddsMovement: [...t.oddsMovement, toOddsMovementVM(event.data.card)] })) }\n    case 'intent_chip': {\n      const chip = toChipVM(event.data.intent)\n      return chip ? { ...state, starters: [...state.starters, chip] } : state\n    }\n    case 'actions_loading':\n      return { ...state, actionsLoading: true, status: event.data.message }\n    case 'turn_complete': {\n      const active = activeTurn(state)\n      // A completed greeting turn surfaces its message as the launcher popup (unless already open).\n      // The club fan dashboard carries its greeting line in the payload rather than as answer\n      // text, so prefer that; fall back to any streamed answer text for other greeting shapes.\n      const greetingLine = event.data.clubFanDashboard?.greeting?.trim() || (active?.text.trim() ?? '')\n      const clearsLimit = !active?.isGreeting && isPlainInput(state.lastUserInput)\n      const popupText = active?.isGreeting && !state.isOpen && greetingLine ? greetingLine.slice(0, POPUP_MAX) : state.popupText\n      return {\n        ...state, isStreaming: false, status: null, actionsLoading: false, popupText, limit: clearsLimit ? null : state.limit,\n        conversationId: event.data.conversationId ?? state.conversationId,\n        messages: mapActive(state, (t) => ({\n          ...t,\n          done: true,\n          greetingDashboard: event.data.dashboard ?? undefined,\n          clubFanDashboard: event.data.clubFanDashboard ?? undefined,\n        })),\n      }\n    }\n    case 'error': {\n      const limit = limitFromEvent(event.data)\n      // B4c: the greeting's notice comes first and the greeting still answers, so the turn keeps streaming.\n      if (limit && event.data.terminal === false) return { ...state, limit }\n      // A refusal is never suppressed, not even on the greeting turn: it is how a paused widget learns it is paused.\n      if (limit) return settleRefused(state, limit)\n      // A failed greeting fails silently — it's non-critical background chatter.\n      const suppress = activeTurn(state)?.isGreeting === true\n      return { ...state, error: suppress ? state.error : event.data, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n    }\n  }\n  // Unknown/unmodelled event type: never return undefined — that would corrupt\n  // state and crash the next dispatch. Ignore the event and keep state intact.\n  return state\n}\n\nexport function reducer(state: WidgetState, action: Action): WidgetState {\n  switch (action.kind) {\n    case 'OPEN':\n      return { ...state, isOpen: true, popupText: null }\n    case 'CLOSE':\n      return { ...state, isOpen: false, isStreaming: false, status: null, actionsLoading: false }\n    case 'USER_SENT': {\n      const user: UserMessage = { role: 'user', id: action.userId, text: action.displayText ?? action.input.message }\n      const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false }\n      return { ...state, messages: [...state.messages, user, assistant], isStreaming: true, status: null, actionsLoading: false, starters: [], error: null, lastUserInput: action.input, lastDisplayText: action.displayText ?? null }\n    }\n    case 'GREETING_SENT': {\n      // Auto-greeting: no user bubble; the assistant turn is flagged so its completion sets the popup.\n      const assistant: AssistantTurn = { role: 'assistant', id: action.assistantId, text: '', cards: [], actions: [], insights: [], marketOdds: [], oddsMovement: [], done: false, isGreeting: true }\n      return { ...state, messages: [...state.messages, assistant], isStreaming: true, status: null, error: null }\n    }\n    case 'DISMISS_POPUP':\n      return { ...state, popupText: null }\n    case 'RESET':\n      // Preserve panel open/closed state: \"New conversation\" is an in-panel control, so the\n      // panel must stay open with the fresh greeting rather than snapping shut. Cross-tab\n      // clear-mirroring likewise keeps each tab's panel as it was.\n      return { ...initialState(state.configuredStarters), isOpen: state.isOpen, limit: state.limit }\n    case 'RESTORE':\n      return {\n        ...state,\n        messages: markAwaitingLiveUpdate(action.messages, state.messages),\n        conversationId: action.conversationId,\n        isStreaming: false,\n        status: null,\n        actionsLoading: false,\n        starters: action.messages.length ? [] : state.configuredStarters,\n        error: null,\n      }\n    case 'EVENT':\n      return applyEvent(state, action.event)\n    case 'STREAM_ERROR': {\n      const limit = limitFromError(action.error)\n      if (limit) return settleRefused(state, limit)\n      return { ...state, error: action.error, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n    }\n    case 'LIMIT_EXPIRED':\n      return { ...state, limit: null }\n    case 'STOP':\n      return { ...state, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) }\n    case 'UPDATE_LIVE_CARD': {\n      const { matchId, live, mainRows, moreRows, addToSlipEnabled } = action\n      return {\n        ...state,\n        messages: state.messages.map((m) => {\n          if (m.role !== 'assistant') return m\n          // Short-circuit: return the same object when no live VM for this matchId exists.\n          if (!m.marketOdds.some((vm) => vm.matchId === matchId && vm.live != null)) return m\n          return {\n            ...m,\n            marketOdds: m.marketOdds.map((vm) =>\n              vm.matchId === matchId && vm.live != null\n                ? { ...vm, live, mainRows, moreRows, addToSlipEnabled, awaitingLiveUpdate: false }\n                : vm,\n            ),\n          }\n        }),\n      }\n    }\n    case 'LIVE_REFRESH':\n      return {\n        ...state,\n        messages: state.messages.map((m) =>\n          m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n            ? { ...m, clubFanDashboard: { ...m.clubFanDashboard, cards: action.cards, greeting: action.greeting ?? m.clubFanDashboard.greeting } }\n            : m,\n        ),\n      }\n    case 'LIVE_TRANSITION':\n      return {\n        ...state,\n        messages: state.messages.map((m) =>\n          m.role === 'assistant' && m.id === action.messageId && m.clubFanDashboard\n            ? { ...m, clubFanDashboard: action.dashboard }\n            : m,\n        ),\n      }\n  }\n}\n","// src/limit.ts -- B4c: the brand's limit as the panel shows it.\nimport type { StreamErrorEventData, WidgetSdkError } from '@sensiblestats/widget-sdk'\nimport { LimitError, isLimitCode, type LimitCode } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from './config'\n\nexport interface LimitState {\n  code: LimitCode\n  /** assistant_paused: the message replaces the composer and nothing is sent until the limit resets. */\n  paused: boolean\n  message: string | null\n  resetsAt: string | null\n  retryAfterSeconds: number | null\n}\n\n// The timer only re-opens the composer; the server judges the next turn. A longer quota re-checks hourly, the most the server ever asks for (MaxRetryAfterSeconds).\nexport const LIMIT_TIMER_MAX_MS = 60 * 60 * 1000\n\nconst ZONED = /(?:Z|[+-]\\d{2}:?\\d{2})$/i\n\nfunction build(\n  code: LimitCode, message: string | null | undefined,\n  resetsAt: string | null | undefined, retryAfterSeconds: number | null | undefined,\n): LimitState {\n  return {\n    code,\n    paused: code === 'assistant_paused',\n    message: message?.trim() || null,\n    resetsAt: resetsAt ?? null,\n    retryAfterSeconds: typeof retryAfterSeconds === 'number' && Number.isFinite(retryAfterSeconds) ? retryAfterSeconds : null,\n  }\n}\n\nexport function limitFromEvent(data: StreamErrorEventData): LimitState | null {\n  return isLimitCode(data.code) ? build(data.code, data.message, data.resetsAt, data.retryAfterSeconds) : null\n}\n\nexport function limitFromError(error: WidgetSdkError): LimitState | null {\n  return error instanceof LimitError ? build(error.limitCode, error.limitMessage, error.resetsAt, error.retryAfter) : null\n}\n\n/** The greeting's notice: the greeting still answers after it, so it does not end the turn. */\nexport function isLimitNotice(data: StreamErrorEventData): boolean {\n  return data.terminal === false && isLimitCode(data.code)\n}\n\nexport function isPaused(limit: LimitState | null): boolean {\n  return limit?.paused === true\n}\n\nexport function limitText(limit: LimitState, ui: UiConfig): string {\n  if (limit.message) return limit.message\n  switch (limit.code) {\n    case 'daily_cap': return ui.limitDailyCap\n    case 'quota_exhausted': return ui.limitQuotaExhausted\n    case 'assistant_paused': return ui.limitAssistantPaused\n  }\n}\n\n// The server's retryAfterSeconds is already clamp(resetsAt - its own now, 1, 3600), so it is the clock-skew-free hint and wins.\n// resetsAt is only the fallback (a zone-less one reads as UTC, B4c ruling 7): against a device clock it can be hours off.\nexport function limitDelayMs(limit: LimitState, nowMs: number): number | null {\n  const retry = limit.retryAfterSeconds\n  if (retry != null && Number.isFinite(retry) && retry >= 0) return Math.min(retry * 1000, LIMIT_TIMER_MAX_MS)\n  const at = limit.resetsAt ? Date.parse(ZONED.test(limit.resetsAt) ? limit.resetsAt : `${limit.resetsAt}Z`) : Number.NaN\n  return Number.isNaN(at) ? null : Math.min(Math.max(at - nowMs, 0), LIMIT_TIMER_MAX_MS)\n}\n","import { useEffect, useReducer, useRef } from 'react'\nimport type { ClubFanDashboardPayload, CountdownCard } from '@sensiblestats/widget-sdk'\nimport type { Action, Message } from './reducer'\n\nconst POLL_INTERVAL_MS = 60_000\nconst LEAD_MS = 120_000       // start polling 2 min before kickoff\nconst GIVE_UP_MS = 30 * 60_000  // stop polling 30 min after kickoff if match never went live\n\ntype Anchor =\n  | { messageId: string; kind: 'live' }\n  | { messageId: string; kind: 'preMatch'; kickoffMs: number }\n\nexport interface UseLiveDashboardPollOptions {\n  messages: Message[]\n  dispatch: (action: Action) => void\n  getLiveDashboard: () => Promise<ClubFanDashboardPayload | null>\n}\n\nfunction extractKickoffMs(dashboard: ClubFanDashboardPayload): number | null {\n  const countdown = dashboard.cards.find((c): c is CountdownCard => c.cardType === 'countdown')\n  if (countdown) return countdown.data.kickoffUnix * 1_000\n  // fall back to any card that exposes kickoffUnix in its data\n  for (const c of dashboard.cards) {\n    const d = (c as { data?: { kickoffUnix?: number } }).data\n    if (typeof d?.kickoffUnix === 'number') return d.kickoffUnix * 1_000\n  }\n  return null\n}\n\n// Returns the most recent assistant message that can serve as a polling anchor:\n// — a live dashboard (always valid), or\n// — a preMatch dashboard whose kickoff is within [kickoff − LEAD_MS, kickoff + GIVE_UP_MS].\nfunction findAnchor(messages: Message[]): Anchor | null {\n  const now = Date.now()\n  for (const m of messages.slice().reverse()) {\n    if (m.role !== 'assistant' || !m.clubFanDashboard) continue\n    const { phase } = m.clubFanDashboard\n    if (phase === 'live') return { messageId: m.id, kind: 'live' }\n    if (phase === 'preMatch') {\n      const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n      if (kickoffMs === null) continue\n      if (now >= kickoffMs - LEAD_MS && now <= kickoffMs + GIVE_UP_MS) {\n        return { messageId: m.id, kind: 'preMatch', kickoffMs }\n      }\n    }\n  }\n  return null\n}\n\n// Returns the earliest future wakeup time for a preMatch dashboard that is not yet within the\n// poll window (kickoff − LEAD_MS still in the future). Returns null if none.\nfunction findEarliestWakeupMs(messages: Message[]): number | null {\n  const now = Date.now()\n  let earliest: number | null = null\n  for (const m of messages) {\n    if (m.role !== 'assistant' || m.clubFanDashboard?.phase !== 'preMatch') continue\n    const kickoffMs = extractKickoffMs(m.clubFanDashboard)\n    if (kickoffMs === null) continue\n    const wakeAt = kickoffMs - LEAD_MS\n    if (wakeAt > now && (earliest === null || wakeAt < earliest)) earliest = wakeAt\n  }\n  return earliest\n}\n\n// Polls the live club-fan dashboard every 60s for the chosen anchor:\n//\n// — Live anchor: on a live payload → LIVE_REFRESH (cards + greeting). On a post-match payload →\n//   LIVE_TRANSITION (full swap to the post-match dashboard) and stop polling. On null → stop.\n// — PreMatch anchor: on a live payload → LIVE_TRANSITION (full payload swap). On null → keep\n//   polling (pre-kickoff 204s) but give up if now > kickoff + GIVE_UP_MS.\n//\n// Wake-up: if a preMatch dashboard's window hasn't opened yet (kickoff − 2min still in the\n// future), schedules a setTimeout to trigger a re-render exactly when polling should begin.\nexport function useLiveDashboardPoll({ messages, dispatch, getLiveDashboard }: UseLiveDashboardPollOptions): void {\n  const [, forceUpdate] = useReducer((x: number) => x + 1, 0)\n  const anchor = findAnchor(messages)\n  const anchorRef = useRef<Anchor | null>(anchor)\n  anchorRef.current = anchor\n  const inFlightRef = useRef(false)\n\n  // Polling effect — keyed on the anchor identity so it restarts when anchor changes.\n  const anchorKey = anchor ? `${anchor.messageId}:${anchor.kind}` : null\n\n  useEffect(() => {\n    if (!anchorKey || !anchorRef.current) return\n\n    const tick = async () => {\n      if (inFlightRef.current) return\n      inFlightRef.current = true\n      try {\n        const payload = await getLiveDashboard()\n        const current = anchorRef.current\n        if (!current) return\n\n        if (payload?.phase === 'live') {\n          if (current.kind === 'preMatch') {\n            dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n            window.clearInterval(id)\n          } else {\n            dispatch({ kind: 'LIVE_REFRESH', messageId: current.messageId, cards: payload.cards, greeting: payload.greeting })\n          }\n        } else if (payload?.phase === 'postMatch' && current.kind === 'live') {\n          // Match ended: the poll now returns the post-match dashboard. Swap the live card for it\n          // and stop polling (the anchor is no longer live).\n          dispatch({ kind: 'LIVE_TRANSITION', messageId: current.messageId, dashboard: payload })\n          window.clearInterval(id)\n        } else {\n          // null (204) or non-live phase with no payload\n          if (current.kind === 'live') {\n            window.clearInterval(id)\n          } else if (Date.now() > current.kickoffMs + GIVE_UP_MS) {\n            window.clearInterval(id)\n          }\n          // preMatch within window: keep polling (these are pre-kickoff 204s)\n        }\n      } catch {\n        // A network error must not crash the widget or stop the loop — swallow and retry\n        // on the next tick.\n      } finally {\n        inFlightRef.current = false\n      }\n    }\n\n    const id = window.setInterval(() => { void tick() }, POLL_INTERVAL_MS)\n    return () => window.clearInterval(id)\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [anchorKey, dispatch, getLiveDashboard])\n\n  // Wake-up effect — schedules a re-render when a preMatch window opens in the future.\n  useEffect(() => {\n    if (anchorKey !== null) return  // already polling, no wake-up needed\n    const wakeAt = findEarliestWakeupMs(messages)\n    if (wakeAt === null) return\n    const delay = wakeAt - Date.now()\n    if (delay <= 0) return\n    const id = window.setTimeout(forceUpdate, delay)\n    return () => window.clearTimeout(id)\n  }, [anchorKey, messages, forceUpdate])\n}\n","import type { Message } from './reducer'\n\nexport const TTL_MS = 3_600_000\nexport const MAX_MESSAGES = 30\n\nexport interface StoredPayload {\n  conversationId: string | null\n  messages: Message[]\n}\n\ninterface StoredConversation {\n  v: 1\n  updatedAt: number\n  conversationId: string | null\n  messages: Message[]\n}\n\n// Pure read: returns the payload when a v:1 blob exists and is within TTL; a sentinel the caller\n// clears from an effect (never during render) when stale/unparseable; null when absent.\nexport function readConversation(storageKey: string, now: number): StoredPayload | 'expired' | 'corrupt' | null {\n  let raw: string | null\n  try {\n    raw = window.localStorage.getItem(storageKey)\n  } catch {\n    return null // SSR / storage blocked\n  }\n  if (!raw) return null\n  let parsed: StoredConversation\n  try {\n    parsed = JSON.parse(raw) as StoredConversation\n  } catch {\n    return 'corrupt'\n  }\n  if (parsed?.v !== 1 || !Array.isArray(parsed.messages) || typeof parsed.updatedAt !== 'number') return 'corrupt'\n  if (now - parsed.updatedAt > TTL_MS) return 'expired'\n  return { conversationId: parsed.conversationId ?? null, messages: parsed.messages }\n}\n\nexport function writeConversation(storageKey: string, conversationId: string | null, messages: Message[], now: number): void {\n  let capped = messages.slice(-MAX_MESSAGES)\n  for (let attempt = 0; attempt < 2; attempt++) {\n    try {\n      window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, updatedAt: now, conversationId, messages: capped } satisfies StoredConversation))\n      return\n    } catch {\n      // quota / blocked: drop the oldest half and retry once, then give up (in-memory only)\n      if (capped.length <= 1) return\n      capped = capped.slice(Math.ceil(capped.length / 2))\n    }\n  }\n}\n\nexport function clearConversation(storageKey: string): void {\n  try {\n    window.localStorage.removeItem(storageKey)\n  } catch {\n    // no-op\n  }\n}\n","// The preset rules the widget owns (spec C6, contract §1-3). The server builds every number; the\n// widget only recognises price tiles, picks which ones become bubble asks, and declares what it\n// can draw.\n\nimport type { EventLogger, GreetingDashboardLayout, GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport type { Message } from './reducer'\nimport type { ChatController } from './useChatStream'\nimport type { DashboardTapHandler } from './dashboardTap'\n\n/** Sent on every chat request (G8, stage 3 contract §1). Without \"price_presets\" the server sends today's\n *  greeting and never a combo_card; without \"price_presets_open\" it never sends a leg with no stat. */\nexport const CLIENT_CAPABILITIES: readonly string[] = ['price_presets', 'price_presets_open', 'limit_notice']\n\n/** contract §2: a tile is a price tile when its signal entity id starts with this. */\nexport const PRICE_TILE_PREFIX = 'goal-preset-'\n\nexport function isPriceTile(tile: GreetingDashboardTile): boolean {\n  const id = tile.signal?.entityId\n  return typeof id === 'string' && id.startsWith(PRICE_TILE_PREFIX)\n}\n\n/** D6: a price tile's ask (its subtitle) is what the user's bubble shows; every other tile keeps\n *  today's title. A price tile with no subtitle falls back to the title rather than an empty bubble. */\nexport function tileDisplayText(tile: GreetingDashboardTile): string {\n  const subtitle = tile.subtitle?.trim()\n  return isPriceTile(tile) && subtitle ? subtitle : tile.title\n}\n\n/** contract §2: the singles price tile (\"3 picks, max 1.50\"). */\nexport const MAX_PRICE_TILE_ID = 'goal-preset-max-price'\n/** The Goal dashboard's Standout matches tile, which the server puts after the price tiles. */\nexport const STANDOUT_TILE_ID = 'goal-standout-matches'\n\nexport interface BubbleAsk {\n  tile: GreetingDashboardTile\n  /** The tile's index in the dashboard: the same number the dashboard-tap signal sends as tileIndex. */\n  index: number\n  /** The ask's place under the bubble, 0 or 1: popup_ask_tap's outcome (contract §5). */\n  position: number\n  layout: GreetingDashboardLayout\n  /** The button's text, and the user bubble a tap shows. */\n  label: string\n}\n\n/** The bubble's asks under \"Want to look at one of these?\", only on a greeting with a price tile:\n *  the singles tile (its subtitle), then Standout matches (labelled standoutLabel). The bubble greets\n *  a new visitor, so it never offers a combo; the dashboard behind it still shows every price tile. */\nexport function bubbleAsks(messages: Message[], standoutLabel: string): BubbleAsk[] {\n  for (let i = messages.length - 1; i >= 0; i--) {\n    const m = messages[i]\n    if (!m || m.role !== 'assistant' || !m.isGreeting) continue\n    const dashboard = m.greetingDashboard\n    if (!dashboard || !dashboard.tiles.some(isPriceTile)) return []\n    const asks: BubbleAsk[] = []\n    const add = (entityId: string, labelOf: (tile: GreetingDashboardTile) => string | undefined): void => {\n      const index = dashboard.tiles.findIndex((tile) => tile.signal?.entityId === entityId)\n      const tile = dashboard.tiles[index]\n      const label = tile ? labelOf(tile)?.trim() : undefined\n      if (tile && label) asks.push({ tile, index, position: asks.length, layout: dashboard.layout, label })\n    }\n    add(MAX_PRICE_TILE_ID, (tile) => tile.subtitle ?? undefined)\n    add(STANDOUT_TILE_ID, () => standoutLabel)\n    return asks\n  }\n  return []\n}\n\nexport interface BubbleAskDeps {\n  open(): void\n  setActiveTab(tab: 'chat'): void\n  send: ChatController['send']\n  onDashboardTap?: DashboardTapHandler\n  log?: EventLogger | null\n}\n\n/** C6: a tap opens the panel, switches to Chat before sending (a reply must not stream in behind\n *  another tab), sends as a tile tap does with the ask's label as the user bubble, and reports the tap. */\nexport function runBubbleAsk(ask: BubbleAsk, deps: BubbleAskDeps): void {\n  deps.log?.log({ name: 'popup_ask_tap', outcome: String(ask.position) })\n  deps.open()\n  deps.setActiveTab('chat')\n  const displayText = ask.label\n  deps.send(ask.tile.actionValue, ask.tile.actionRef ? { actionRef: ask.tile.actionRef, displayText } : { displayText })\n  deps.onDashboardTap?.(ask.tile, ask.index, ask.layout)\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LiveMonitorEvent, LiveMonitorSnapshot, MarketOddsBlock, PinRef } from '@sensiblestats/widget-sdk'\nimport { createPinStore, pinKey, type PinAddResult, type PinStore } from './pinStore'\nimport { useTabs, type WidgetTab } from './useTabs'\n\n/** A transient watch: same shape as PinRef but not stored in the pin store. The chat panel\n *  adds a WatchRef for each live-card market currently on screen; the poll loop sends it\n *  alongside the user's pins so the snapshot stays current. */\nexport type WatchRef = PinRef\n\n// Re-exported for back-compat; callers that already import MonitorTab continue to compile.\nexport type MonitorTab = WidgetTab\n\nexport interface LiveMonitorController {\n  /** Starts TRUE (the server-side pinEnabled flag is the real affordance gate); flips to\n   *  false permanently for the session on a 404 (null snapshot) from the monitor endpoint. */\n  enabled: boolean\n  pins: PinRef[]\n  snapshot: LiveMonitorSnapshot | null\n  activeTab: WidgetTab\n  setActiveTab(tab: WidgetTab): void\n  togglePin(pin: PinRef): PinAddResult\n  isPinned(key: string): boolean\n  /** One match at a time: pins (replacing any other match pin) or keeps the match, opens\n   *  `marketDeveloperName` in its accordion (else the first market), and switches to Following. */\n  pinMatch(target: { matchId: number; marketDeveloperName?: string }): 'added' | 'kept'\n  /** Set by ChatPanel when a reply lands off-tab; cleared on chat tab. */\n  chatDot: boolean\n  markChatActivity(): void\n  /** A goal/red event arrived on a pinned match since Maçlar was last viewed. */\n  matchesDot: boolean\n  /** A pinned market's price changed since Oranlar was last viewed. */\n  oddsDot: boolean\n  /** The live count rose from zero while Today was off-screen; suppressed on the active tab. */\n  todayDot: boolean\n  /** Set by the discovery owner when the live count rises from zero (mirrors markChatActivity). */\n  markTodayActivity(): void\n  /** Last-viewed price per pin key, for client-side movement badges. */\n  lastViewedPrices: Record<string, number>\n  /** The currently open accordion market per matchId (null = collapsed). One open at a time per match. */\n  openMarket: Record<number, string | null>\n  /** Lazy per-market odds cache, keyed `${matchId}:${marketDeveloperName}`. */\n  marketOdds: Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n  toggleMarket(matchId: number, marketDeveloperName: string): void\n  /** Refetches a market's odds WITHOUT touching openMarket -- the tap-to-retry affordance for a\n   *  market that is already open and errored. toggleMarket would collapse it instead (it flips\n   *  openMarket unconditionally), which is the wrong move when the row is already showing. */\n  retryMarket(matchId: number, marketDeveloperName: string): void\n  /** Internal seam: applies a freshly-fetched snapshot (or null on a 404). The poll loop calls\n   *  this repeatedly; tests call it directly to drive dot/grace logic without a live timer.\n   *  Not part of the poll cadence/visibility policy itself. */\n  _setSnapshot(next: LiveMonitorSnapshot | null): void\n}\n\nexport interface UseLiveMonitorOptions {\n  /** Called with pins + watches combined; the server de-duplicates by key. */\n  getLiveMonitor: (pins: PinRef[]) => Promise<LiveMonitorSnapshot | null>\n  getMarketOdds?: (matchId: number, marketDeveloperName: string) => Promise<MarketOddsBlock | null>\n  storageKey: string\n  /** false -> true transitions trigger an immediate poll tick (widget open). */\n  isOpen: boolean\n  /** Whether the Today tab currently has content -- picks the fallback target when a pinned tab\n   *  disappears, and sends the user to Chat when Today itself empties under them. */\n  hasToday?: boolean\n  /** Transient watches from the chat panel (live cards on screen). Not stored in the pin store.\n   *  When non-empty, the poll loop fires even when the user has no pins of their own. */\n  watches?: WatchRef[]\n  /** True once the club-tenant probe resolves. The club tab strip never renders\n   *  today/following/odds, so any route onto one of them (a chat-card pin tap, a stale pin from\n   *  before the probe settled) must bounce to Chat rather than strand the fan on a tab with no\n   *  way back. */\n  clubEnabled?: boolean\n}\n\nconst GOAL_OR_RED: ReadonlySet<LiveMonitorEvent['type']> = new Set(['goal', 'red'])\nconst MIN_POLL_MS = 5_000\nconst DEFAULT_POLL_MS = 60_000\n// Live cards are only shown for in-progress matches, which the server polls at 12 s.\nconst LIVE_WATCH_POLL_MS = 12_000\n\nfunction eventIdentity(e: LiveMonitorEvent): string {\n  return `${e.type}:${e.side}:${e.minuteLabel}:${e.player ?? ''}`\n}\n\nfunction priceForPin(snapshot: LiveMonitorSnapshot | null, pin: PinRef): number | undefined {\n  if (!snapshot) return undefined\n  const market = snapshot.markets.find((m) => m.key === pin.key)\n  const rows = market?.card?.rows\n  if (!rows || rows.length === 0) return undefined\n  const row = pin.matchOddsId != null ? rows.find((r) => r.matchOddsId === pin.matchOddsId) : rows[0]\n  return row?.price\n}\n\nfunction phaseForPin(snapshot: LiveMonitorSnapshot, pin: PinRef): string | undefined {\n  if (pin.kind === 'match') return snapshot.matches.find((m) => m.matchId === pin.matchId)?.phase\n  return snapshot.markets.find((mk) => mk.key === pin.key)?.phase\n}\n\nexport function useLiveMonitor(opts: UseLiveMonitorOptions): LiveMonitorController {\n  const sessionIdRef = useRef(crypto.randomUUID())\n\n  const [pins, setPins] = useState<PinRef[]>([])\n  // Lazy initializer: the store fires an initial (no-op-from-the-caller's-view) onChange\n  // synchronously during construction, which is a same-component render-phase state update\n  // React explicitly supports — it must not run in an effect/later render.\n  const [store] = useState<PinStore>(() => createPinStore(opts.storageKey, sessionIdRef.current, setPins))\n\n  const [enabled, setEnabled] = useState(true)\n  const [snapshot, setSnapshotState] = useState<LiveMonitorSnapshot | null>(null)\n  const { activeTab, setActiveTab: setActiveTabState } = useTabs('chat')\n  const [chatDot, setChatDot] = useState(false)\n  const [matchesDot, setMatchesDot] = useState(false)\n  const [oddsDot, setOddsDot] = useState(false)\n  const [todayDot, setTodayDot] = useState(false)\n  const [lastViewedPrices, setLastViewedPrices] = useState<Record<string, number>>({})\n  const [openMarket, setOpenMarket] = useState<Record<number, string | null>>({})\n  const [marketOdds, setMarketOdds] = useState<\n    Record<string, { block?: MarketOddsBlock; loading: boolean; error: boolean }>\n  >({})\n\n  const pinsRef = useRef(pins)\n  pinsRef.current = pins\n  // Watches are not stored in state -- they come from opts on every render; keep in a ref so\n  // tick (which is created once) can read the latest value without needing deps.\n  const watchesRef = useRef<WatchRef[]>(opts.watches ?? [])\n  watchesRef.current = opts.watches ?? []\n  const activeTabRef = useRef(activeTab)\n  activeTabRef.current = activeTab\n  const snapshotRef = useRef(snapshot)\n  snapshotRef.current = snapshot\n  const lastViewedPricesRef = useRef(lastViewedPrices)\n  lastViewedPricesRef.current = lastViewedPrices\n  const openMarketRef = useRef(openMarket)\n  openMarketRef.current = openMarket\n  const marketOddsRef = useRef(marketOdds)\n  marketOddsRef.current = marketOdds\n  const hasToday = opts.hasToday ?? false\n  const clubEnabled = opts.clubEnabled ?? false\n\n  const marketKey = (matchId: number, dev: string): string => `${matchId}:${dev}`\n\n  const getMarketOddsRef = useRef(opts.getMarketOdds)\n  getMarketOddsRef.current = opts.getMarketOdds // latest-fn pattern; fetchMarket reads the ref, deps stay stable\n\n  // Stable identity ([] deps, refs only) so callers (applySnapshot, tick) can invoke it without\n  // needing to sit in a dependency array.\n  const fetchMarket = useCallback((matchId: number, dev: string) => {\n    const key = marketKey(matchId, dev)\n    const existing = marketOddsRef.current[key]\n    if (existing?.loading) return // already in flight -- don't double-fetch\n    const loadingEntry = { ...existing, loading: true, error: false }\n    marketOddsRef.current = { ...marketOddsRef.current, [key]: loadingEntry }\n    setMarketOdds((prev) => ({ ...prev, [key]: loadingEntry }))\n    const fn = getMarketOddsRef.current\n    if (!fn) return\n    void fn(matchId, dev)\n      .then((block) => {\n        const entry = { block: block ?? undefined, loading: false, error: false }\n        marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n        setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n      })\n      .catch(() => {\n        const entry = { ...marketOddsRef.current[key], loading: false, error: true }\n        marketOddsRef.current = { ...marketOddsRef.current, [key]: entry }\n        setMarketOdds((prev) => ({ ...prev, [key]: entry }))\n      })\n  }, [])\n\n  const toggleMarket = useCallback((matchId: number, dev: string) => {\n    const key = marketKey(matchId, dev)\n    const wasOpen = openMarketRef.current[matchId] === dev\n    const nextValue = wasOpen ? null : dev\n    openMarketRef.current = { ...openMarketRef.current, [matchId]: nextValue }\n    setOpenMarket((prev) => ({ ...prev, [matchId]: nextValue }))\n    // Opening a market that isn't cached yet -- fetch it. A successfully-cached reopen is a\n    // no-op fetch, but an entry that previously errored (no block) MUST be retried, not\n    // treated as \"cached\" -- that's what drives the tap-to-retry affordance (Task 9).\n    const existing = marketOddsRef.current[key]\n    if (!wasOpen && !(existing?.loading || existing?.block)) {\n      fetchMarket(matchId, dev)\n    }\n  }, [fetchMarket])\n\n  const retryMarket = useCallback((matchId: number, dev: string) => {\n    fetchMarket(matchId, dev)\n  }, [fetchMarket])\n\n  const applySnapshot = useCallback((next: LiveMonitorSnapshot | null) => {\n    if (next === null) {\n      setEnabled(false)\n      return\n    }\n    const prev = snapshotRef.current\n    const currentPins = pinsRef.current\n\n    const pinnedMatchIds = new Set(currentPins.filter((p) => p.kind === 'match').map((p) => p.matchId))\n    let sawNewGoalOrRed = false\n    for (const m of next.matches) {\n      if (!pinnedMatchIds.has(m.matchId)) continue\n      const prevMatch = prev?.matches.find((pm) => pm.matchId === m.matchId)\n      const prevKeys = new Set((prevMatch?.events ?? []).filter((e) => GOAL_OR_RED.has(e.type)).map(eventIdentity))\n      if (m.events.some((e) => GOAL_OR_RED.has(e.type) && !prevKeys.has(eventIdentity(e)))) {\n        sawNewGoalOrRed = true\n        break\n      }\n    }\n    if (sawNewGoalOrRed && activeTabRef.current !== 'following') setMatchesDot(true)\n\n    // Default-open the first available market per pinned match, once -- an explicit close\n    // (openMarket[matchId] === null) must stick, so the guard is \"no entry at all\" not \"falsy\".\n    for (const m of next.matches) {\n      if (!pinnedMatchIds.has(m.matchId)) continue\n      const first = m.availableMarkets?.[0]\n      if (!first) continue\n      if (m.matchId in openMarketRef.current) continue\n      const dev = first.marketDeveloperName\n      openMarketRef.current = { ...openMarketRef.current, [m.matchId]: dev }\n      setOpenMarket((prevOpen) => ({ ...prevOpen, [m.matchId]: dev }))\n      fetchMarket(m.matchId, dev)\n    }\n\n    const marketPins = currentPins.filter((p) => p.kind !== 'match')\n    if (activeTabRef.current === 'odds') {\n      setLastViewedPrices((prevMap) => {\n        let changed = false\n        const out = { ...prevMap }\n        for (const pin of marketPins) {\n          const price = priceForPin(next, pin)\n          if (price !== undefined && out[pin.key] !== price) {\n            out[pin.key] = price\n            changed = true\n          }\n        }\n        return changed ? out : prevMap\n      })\n    } else {\n      let sawPriceMove = false\n      for (const pin of marketPins) {\n        const price = priceForPin(next, pin)\n        const last = lastViewedPricesRef.current[pin.key]\n        if (price !== undefined && last !== undefined && price !== last) {\n          sawPriceMove = true\n          break\n        }\n      }\n      if (sawPriceMove) setOddsDot(true)\n    }\n\n    const graceKeys = currentPins\n      .filter((p) => {\n        const phase = phaseForPin(next, p)\n        return phase === 'fullTime' || phase === 'postponed' || phase === 'gone'\n      })\n      .map((p) => p.key)\n    if (graceKeys.length > 0) store.markGrace(graceKeys, sessionIdRef.current, Date.now())\n\n    // Sync the ref immediately (state updates are async) -- the poll loop's schedule step reads\n    // this synchronously in the SAME tick, right after this call returns, to size the next\n    // delay off the snapshot that was just received rather than the one from the prior tick.\n    snapshotRef.current = next\n    setSnapshotState(next)\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [store])\n\n  // Poll loop. ALL mutable inputs live in refs so `tick` is created ONCE ([applySnapshot] deps,\n  // and applySnapshot itself is stable across renders): an inline getLiveMonitor lambda handed\n  // in fresh from StatsWidget on every render must not re-arm the visibility listener or\n  // recreate the timer chain.\n  const inFlightRef = useRef(false)\n  const pendingRef = useRef(false)\n  const inFlightKeysRef = useRef('')\n  const timerRef = useRef<number | undefined>(undefined)\n  const disabledRef = useRef(false)\n  const mountedRef = useRef(false)\n  const getLiveMonitorRef = useRef(opts.getLiveMonitor)\n  getLiveMonitorRef.current = opts.getLiveMonitor // latest-fn pattern; tick reads the ref, deps stay stable\n\n  const tick = useCallback(async () => {\n    const allPins = [...pinsRef.current, ...watchesRef.current]\n    if (disabledRef.current || allPins.length === 0) return\n    const keys = allPins.map((p) => p.key).join('|')\n    if (inFlightRef.current) {\n      // Several triggers fire in one burst with the same pins; only a pin set that changed since\n      // the poll in flight was sent needs its own poll right after it lands.\n      if (keys !== inFlightKeysRef.current) pendingRef.current = true\n      return\n    }\n    inFlightKeysRef.current = keys\n    inFlightRef.current = true\n    try {\n      const snap = await getLiveMonitorRef.current(allPins)\n      if (!mountedRef.current) return\n      if (snap === null) {\n        // 404 -> live monitor disabled for this operator: stop for the session, hide affordances.\n        disabledRef.current = true\n        applySnapshot(null)\n        return\n      }\n      applySnapshot(snap)\n      // Live-refresh the open accordion market per match. Bypasses the \"already cached\" skip\n      // (that guard only lives in toggleMarket) -- fetchMarket itself only skips a fetch already\n      // in flight, so this always requests fresh odds for a live match's open market.\n      for (const m of snap.matches) {\n        if (m.phase !== 'live') continue\n        const dev = openMarketRef.current[m.matchId]\n        if (dev) fetchMarket(m.matchId, dev)\n      }\n    } catch {\n      // transient failure: keep the previous snapshot, retry on the next scheduled tick\n    } finally {\n      inFlightRef.current = false\n      if (pendingRef.current && mountedRef.current) {\n        pendingRef.current = false\n        void tick()\n      } else {\n        scheduleRef.current()\n      }\n    }\n  }, [applySnapshot, fetchMarket]) // reads refs only -- both callbacks are themselves stable\n\n  const scheduleRef = useRef<() => void>(() => {})\n  scheduleRef.current = () => {\n    window.clearTimeout(timerRef.current)\n    const hasWork = pinsRef.current.length > 0 || watchesRef.current.length > 0\n    if (!mountedRef.current || disabledRef.current || !hasWork || document.visibilityState === 'hidden') return\n    const fallbackMs = watchesRef.current.length > 0 ? LIVE_WATCH_POLL_MS : DEFAULT_POLL_MS\n    const hinted = snapshotRef.current ? snapshotRef.current.nextPollSeconds * 1000 : fallbackMs\n    timerRef.current = window.setTimeout(() => void tick(), Math.max(MIN_POLL_MS, hinted))\n  }\n\n  // Set before the effects below that tick; cleared on unmount so a tick already awaiting the\n  // network drops its snapshot (no pin-grace write) and arms no timer after the hook is gone.\n  useEffect(() => {\n    mountedRef.current = true\n    return () => { mountedRef.current = false }\n  }, [])\n\n  // Immediate tick: pin list transitions 0 -> 1+ (togglePin add, or pins already present at\n  // mount -- the ref starts at 0 so the first run treats \"already have pins\" the same way).\n  // Dropping to zero pins clears any pending timer so a stray tick never fires with no pins.\n  // It deliberately does NOT move the active tab: PinToggle is reachable from a chat message\n  // card, so unpinning mid-conversation must leave the reader where they are. The per-kind\n  // effect below owns the fallback, and its `activeTab` guard covers zero pins too.\n  const prevPinsLengthRef = useRef(0)\n  useEffect(() => {\n    const wasEmpty = prevPinsLengthRef.current === 0 && watchesRef.current.length === 0\n    prevPinsLengthRef.current = pins.length\n    if (pins.length === 0 && watchesRef.current.length === 0) {\n      window.clearTimeout(timerRef.current)\n      return\n    }\n    if (wasEmpty) void tick()\n  }, [pins.length, tick])\n\n  // Watches are not in state, so they don't trigger the pins effect. When the caller adds the first\n  // watch (live card appears in the chat), fire an immediate tick to populate the snapshot without\n  // waiting for the next timer.  The watches array reference changes on every render so we only\n  // compare length via a ref to avoid re-arming on each re-render.\n  const prevWatchesLengthRef = useRef(0)\n  const watchesLength = opts.watches?.length ?? 0\n  useEffect(() => {\n    const wasEmpty = prevWatchesLengthRef.current === 0 && pinsRef.current.length === 0\n    prevWatchesLengthRef.current = watchesLength\n    if (wasEmpty && watchesLength > 0) void tick()\n  }, [watchesLength, tick])\n\n  // A tab left active after the content backing it disappears strands the user on an empty panel\n  // with no tab in the strip to escape from. Four ways in: a club tenant lands on a sportsbook-only\n  // tab (the club strip never renders one), the last match pin drops while an odds pin remains\n  // (pins.length alone can't see it, the OTHER kind keeps it above zero), the mirror case for odds,\n  // and Today emptying under the user at the local-date rollover.\n  useEffect(() => {\n    if (clubEnabled && (activeTab === 'today' || activeTab === 'following' || activeTab === 'odds')) {\n      setActiveTabState('chat')\n      return\n    }\n    const matchPins = pins.filter((p) => p.kind === 'match').length\n    const marketPins = pins.length - matchPins\n    if (activeTab === 'following' && matchPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n    if (activeTab === 'odds' && marketPins === 0) setActiveTabState(hasToday ? 'today' : 'chat')\n    if (activeTab === 'today' && !hasToday) setActiveTabState('chat')\n  }, [pins, activeTab, hasToday, clubEnabled])\n\n  // Immediate tick: widget open (false -> true transition).\n  const prevIsOpenRef = useRef(false)\n  useEffect(() => {\n    const wasClosed = !prevIsOpenRef.current\n    prevIsOpenRef.current = opts.isOpen\n    if (wasClosed && opts.isOpen) void tick()\n  }, [opts.isOpen, tick])\n\n  // Visibility: hidden clears the pending timer; visible ticks immediately. Mounted exactly\n  // once -- `tick` never changes identity, so this effect never re-fires across re-renders.\n  useEffect(() => {\n    const onVisibility = () => {\n      if (document.visibilityState === 'hidden') window.clearTimeout(timerRef.current)\n      else void tick()\n    }\n    document.addEventListener('visibilitychange', onVisibility)\n    return () => {\n      document.removeEventListener('visibilitychange', onVisibility)\n      window.clearTimeout(timerRef.current)\n    }\n  }, [tick])\n\n  const setActiveTab = useCallback((tab: WidgetTab) => {\n    setActiveTabState(tab)\n    if (tab === 'chat') setChatDot(false)\n    if (tab === 'today') setTodayDot(false)\n    if (tab === 'following') {\n      setMatchesDot(false)\n      void tick()\n    }\n    if (tab === 'odds') {\n      setOddsDot(false)\n      setLastViewedPrices((prevMap) => {\n        const out = { ...prevMap }\n        for (const pin of pinsRef.current.filter((p) => p.kind !== 'match')) {\n          const price = priceForPin(snapshotRef.current, pin)\n          if (price !== undefined) out[pin.key] = price\n        }\n        return out\n      })\n      void tick()\n    }\n  }, [tick])\n\n  // The ref is refreshed here, not only on the next render: a price history tap adds a pin and\n  // opens the Odds tab in one handler, and that tab's immediate fetch must already carry the pin.\n  const togglePin = useCallback((pin: PinRef): PinAddResult => {\n    const result = store.toggle(pin)\n    pinsRef.current = store.pins\n    return result\n  }, [store])\n  const isPinned = useCallback((key: string): boolean => pinsRef.current.some((p) => p.key === key), [])\n  const pinMatch = useCallback((target: { matchId: number; marketDeveloperName?: string }): 'added' | 'kept' => {\n    const { matchId, marketDeveloperName: dev } = target\n    const key = pinKey({ kind: 'match', matchId })\n    const result = store.has(key) ? 'kept' : 'added'\n    if (result === 'added') store.toggle({ key, kind: 'match', matchId })\n    pinsRef.current = store.pins\n    if (dev) {\n      openMarketRef.current = { ...openMarketRef.current, [matchId]: dev }\n      setOpenMarket((prev) => ({ ...prev, [matchId]: dev }))\n      const existing = marketOddsRef.current[marketKey(matchId, dev)]\n      if (!(existing?.loading || existing?.block)) fetchMarket(matchId, dev)\n    } else {\n      const next = { ...openMarketRef.current }\n      delete next[matchId]\n      openMarketRef.current = next\n      setOpenMarket((prev) => {\n        const out = { ...prev }\n        delete out[matchId]\n        return out\n      })\n    }\n    setActiveTab('following')\n    return result\n  }, [store, fetchMarket, setActiveTab])\n  const markChatActivity = useCallback(() => setChatDot(true), [])\n  // Same shape as markChatActivity: the count that drives it lives in useMatchDiscovery, which\n  // cannot be read from here without making the two hooks observe each other's own render.\n  const markTodayActivity = useCallback(() => {\n    if (activeTabRef.current !== 'today') setTodayDot(true)\n  }, [])\n\n  return {\n    enabled,\n    pins,\n    snapshot,\n    activeTab,\n    setActiveTab,\n    togglePin,\n    isPinned,\n    pinMatch,\n    chatDot,\n    markChatActivity,\n    matchesDot,\n    oddsDot,\n    todayDot,\n    markTodayActivity,\n    lastViewedPrices,\n    openMarket,\n    marketOdds,\n    toggleMarket,\n    retryMarket,\n    _setSnapshot: applySnapshot,\n  }\n}\n","import type { PinRef } from '@sensiblestats/widget-sdk'\n\nexport const MAX_MARKET_PINS = 10\nexport type PinAddResult = 'added' | 'removed' | 'market_limit'\n\nexport type StoredPin = PinRef & { graceAt?: number; graceSession?: string }\n\nexport interface PinStore {\n  pins: PinRef[]\n  /** Toggle: same key present -> remove; else add if under the kind's cap. */\n  toggle(pin: PinRef): PinAddResult\n  remove(key: string): void\n  has(key: string): boolean\n  /** D7: stamps graceAt/graceSession on the given keys, only where not already stamped. */\n  markGrace(keys: string[], sessionId: string, now: number): void\n}\n\nexport function pinKey(p: Omit<PinRef, 'key'>): string {\n  return `${p.kind}:${p.matchId}:${p.marketDeveloperName ?? ''}:${p.selectionLabel ?? ''}:${p.line ?? ''}:${p.matchOddsId ?? ''}`\n}\n\nexport const GRACE_MS = 4 * 60 * 60 * 1000\n\n/** D7: drop pins whose grace started in a PREVIOUS session (next widget open) or > 4h ago. */\nexport function pruneExpired(pins: StoredPin[], sessionId: string, now: number): StoredPin[] {\n  return pins.filter((p) => p.graceAt === undefined || (p.graceSession === sessionId && now - p.graceAt <= GRACE_MS))\n}\n\n/** One pinned match at a time: keeps every non-match pin and the last (newest) match pin. */\nexport function oneMatchPin(pins: StoredPin[]): StoredPin[] {\n  const matches = pins.filter((p) => p.kind === 'match')\n  const newest = matches[matches.length - 1]\n  return pins.filter((p) => p.kind !== 'match' || p === newest)\n}\n\ninterface StoredPins {\n  v: 1\n  pins: StoredPin[]\n}\n\nfunction safeRead(storageKey: string): StoredPin[] {\n  try {\n    const raw = window.localStorage.getItem(storageKey)\n    if (!raw) return []\n    const parsed = JSON.parse(raw) as StoredPins\n    return parsed.v === 1 && Array.isArray(parsed.pins) ? parsed.pins : []\n  } catch {\n    return []\n  }\n}\n\nfunction safeWrite(storageKey: string, pins: StoredPin[]): void {\n  try {\n    window.localStorage.setItem(storageKey, JSON.stringify({ v: 1, pins } satisfies StoredPins))\n  } catch {\n    // storage blocked -> in-memory only for the session (spec, degradation rules)\n  }\n}\n\nexport function loadPins(storageKey: string): PinRef[] {\n  return safeRead(storageKey)\n}\n\nexport function createPinStore(storageKey: string, sessionId: string, onChange: (pins: PinRef[]) => void): PinStore {\n  // D7 grace: pins whose subject finished in a previous session (or >4h ago) are dropped on open.\n  let pins = oneMatchPin(pruneExpired(safeRead(storageKey), sessionId, Date.now()))\n\n  const commit = (next: StoredPin[]) => {\n    pins = next\n    safeWrite(storageKey, pins)\n    onChange(pins)\n  }\n  commit(pins)\n\n  return {\n    get pins() {\n      return pins\n    },\n    has: (key) => pins.some((p) => p.key === key),\n    remove: (key) => commit(pins.filter((p) => p.key !== key)),\n    markGrace(keys, session, now) {\n      commit(\n        pins.map((p) => (keys.includes(p.key) && p.graceAt === undefined ? { ...p, graceAt: now, graceSession: session } : p)),\n      )\n    },\n    toggle(pin) {\n      if (pins.some((p) => p.key === pin.key)) {\n        commit(pins.filter((p) => p.key !== pin.key))\n        return 'removed'\n      }\n      if (pin.kind === 'match') {\n        commit([...pins.filter((p) => p.kind !== 'match'), pin])\n        return 'added'\n      }\n      if (pins.length - pins.filter((p) => p.kind === 'match').length >= MAX_MARKET_PINS) return 'market_limit'\n      commit([...pins, pin])\n      return 'added'\n    },\n  }\n}\n","import { useState } from 'react'\n\nexport type WidgetTab = 'chat' | 'today' | 'following' | 'odds' | 'games' | 'fixtures' | 'standings' | 'squad' | 'records'\n\nexport function useTabs(initial: WidgetTab = 'chat'): { activeTab: WidgetTab; setActiveTab: (t: WidgetTab) => void } {\n  const [activeTab, setActiveTab] = useState<WidgetTab>(initial)\n  return { activeTab, setActiveTab }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { LeagueStarResult, MatchState, SchedulePayload, ScheduleGroup, StatesPayload } from '@sensiblestats/widget-sdk'\nimport { patchScheduleStar, readSchedule, readScheduleIgnoringTtl, writeSchedule } from './scheduleCache'\nimport { dueMatchIds } from './dueSet'\n\nconst POLL_MS = 60_000\n// Local re-render so the minute advances between network polls. Costs one render; the alternative\n// is a clock that only moves once a minute.\nconst ROLLOVER_CHECK_MS = 60_000\nconst STALE_AFTER_FAILURES = 2\n\nexport interface MatchDiscoveryController {\n  groups: ScheduleGroup[]\n  states: Record<number, MatchState>\n  /** Advanced locally between polls so the minute ticks. */\n  liveCount: number\n  stale: boolean\n  starLeague(competitionId: number, starred: boolean): Promise<boolean>\n  /** Test seam: run one states poll synchronously. Not part of the cadence policy. */\n  _tick(): Promise<void>\n}\n\nexport interface UseMatchDiscoveryOptions {\n  getSchedule: (localDate: string, utcOffsetMinutes: number) => Promise<SchedulePayload | null>\n  getStates: (matchIds: number[]) => Promise<StatesPayload | null>\n  postLeagueStar: (competitionId: number, starred: boolean) => Promise<LeagueStarResult | null>\n  operatorId: string\n  operatorUserId?: string\n  anonymousUserId?: string\n  isOpen: boolean\n  pinnedMatchIds: number[]\n}\n\nfunction encodedUserKey(operatorUserId?: string, anonymousUserId?: string): string {\n  return encodeURIComponent(operatorUserId || anonymousUserId || 'none')\n}\n\nfunction localDateOf(now: Date): string {\n  const y = now.getFullYear()\n  const m = `${now.getMonth() + 1}`.padStart(2, '0')\n  const d = `${now.getDate()}`.padStart(2, '0')\n  return `${y}-${m}-${d}`\n}\n\nexport function useMatchDiscovery(opts: UseMatchDiscoveryOptions): MatchDiscoveryController {\n  const [groups, setGroups] = useState<ScheduleGroup[]>([])\n  const [states, setStates] = useState<Record<number, MatchState>>({})\n  const [failures, setFailures] = useState(0)\n\n  const groupsRef = useRef(groups)\n  groupsRef.current = groups\n  const statesRef = useRef(states)\n  statesRef.current = states\n  // latest-fn pattern (mirrors useLiveMonitor's getLiveMonitorRef): tick reads the ref, so an\n  // inline getStates lambda handed in fresh on every render cannot tear down and recreate the\n  // poll interval.\n  const getStatesRef = useRef(opts.getStates)\n  getStatesRef.current = opts.getStates\n\n  // A widget left mounted across midnight has to move to the new day, or it holds yesterday's\n  // fixtures forever with an empty due set and no polling. Cheap enough to check on a coarse\n  // interval; the state only ever changes value once a day, so it re-renders once a day.\n  const [localDate, setLocalDate] = useState(() => localDateOf(new Date()))\n  useEffect(() => {\n    const id = setInterval(() => {\n      const next = localDateOf(new Date())\n      setLocalDate((prev) => (prev === next ? prev : next))\n    }, ROLLOVER_CHECK_MS)\n    return () => clearInterval(id)\n  }, [])\n\n  // `states` is deliberately NOT cleared here: a 23:00 fixture still playing at 00:30 belongs to\n  // neither day's window, and dropping its state would blank a score that is still true.\n  useEffect(() => {\n    let cancelled = false\n    // getTimezoneOffset is minutes WEST of UTC, so Istanbul reports -180 for UTC+3.\n    const utcOffsetMinutes = -new Date().getTimezoneOffset()\n    const key = encodedUserKey(opts.operatorUserId, opts.anonymousUserId)\n\n    const cached = readSchedule(opts.operatorId, key, localDate, Date.now())\n    if (cached) {\n      if (!cancelled) setGroups(cached.groups)\n      return () => { cancelled = true }\n    }\n\n    void (async () => {\n      try {\n        const payload = await opts.getSchedule(localDate, utcOffsetMinutes)\n        if (cancelled || !payload) return\n        writeSchedule(opts.operatorId, key, localDate, payload, Date.now())\n        setGroups(payload.groups)\n      } catch {\n        // Fixtures do not move, so an expired day beats an empty tab.\n        const fallback = readScheduleIgnoringTtl(opts.operatorId, key, localDate)\n        if (!cancelled && fallback) setGroups(fallback.groups)\n      }\n    })()\n\n    return () => { cancelled = true }\n  }, [opts.operatorId, opts.operatorUserId, opts.anonymousUserId, localDate])\n\n  const tick = useCallback(async () => {\n    const ids = dueMatchIds(groupsRef.current, statesRef.current, Date.now())\n    if (ids.length === 0) return\n    try {\n      const payload = await getStatesRef.current(ids)\n      if (!payload) return\n      setStates((prev) => {\n        // Retained rather than replaced: a finished match keeps its final score after it leaves\n        // the due set.\n        const next = { ...prev }\n        for (const state of payload.states) next[state.matchId] = state\n        return next\n      })\n      setFailures(0)\n    } catch {\n      setFailures((n) => n + 1)\n    }\n  }, [])\n\n  // `groups` is in the deps (beyond `tick`, which is now stable) so a schedule fetch that\n  // resolves after the mount-time tick above gets an immediate follow-up poll, rather than\n  // stranding the newly-loaded due set until the next 60s tick.\n  useEffect(() => {\n    if (!opts.isOpen) return\n    void tick()\n    const id = setInterval(() => { void tick() }, POLL_MS)\n    return () => clearInterval(id)\n  }, [opts.isOpen, tick, groups])\n\n  const stale = failures >= STALE_AFTER_FAILURES\n\n  const liveCount = useMemo(\n    () => (stale\n      ? 0\n      // A match whose own reading has gone stale stops counting: a stalled window must not hold\n      // the badge up at 1 for the rest of the day.\n      : Object.values(states).filter((s) => s.phase === 'live').length),\n    [states, stale],\n  )\n\n  const starLeague = useCallback(async (competitionId: number, starred: boolean): Promise<boolean> => {\n    let result: LeagueStarResult | null\n    try {\n      result = await opts.postLeagueStar(competitionId, starred)\n    } catch {\n      // A thrown error (429/5xx/network failure) must not become an unhandled rejection on the\n      // operator's host page -- the UI already re-enables the star on any falsy return.\n      return false\n    }\n    if (!result) return false\n    const patch = { isStarred: result.starred, isLearned: false, learnedRank: null }\n    setGroups((prev) => prev.map((g) => (g.competitionId === competitionId ? { ...g, ...patch } : g)))\n    patchScheduleStar(opts.operatorId, encodedUserKey(opts.operatorUserId, opts.anonymousUserId), localDate, competitionId, patch)\n    return true\n  }, [opts.postLeagueStar, opts.operatorId, opts.operatorUserId, opts.anonymousUserId, localDate])\n\n  return { groups, states, liveCount, stale, starLeague, _tick: tick }\n}\n","import type { SchedulePayload } from '@sensiblestats/widget-sdk'\n\nconst PREFIX = 'ss-w-schedule:'\nexport const SCHEMA_VERSION = 2\nconst TTL_MS = 6 * 3600_000\n\ninterface Entry {\n  v: number\n  at: number\n  payload: SchedulePayload\n}\n\nexport function scheduleCacheKey(operatorId: string, encodedUserKey: string, localDate: string): string {\n  return `${PREFIX}${operatorId}:${encodedUserKey}:${localDate}`\n}\n\nfunction read(operatorId: string, encodedUserKey: string, localDate: string): Entry | null {\n  try {\n    const raw = localStorage.getItem(scheduleCacheKey(operatorId, encodedUserKey, localDate))\n    if (!raw) return null\n    const entry = JSON.parse(raw) as Entry\n    // A wire change bumps SCHEMA_VERSION; without this an old entry deserializes into the new\n    // shape and renders fields that are no longer there.\n    if (entry.v !== SCHEMA_VERSION || !entry.payload) return null\n    return entry\n  } catch {\n    return null\n  }\n}\n\nexport function readSchedule(\n  operatorId: string, encodedUserKey: string, localDate: string, nowMs: number,\n): SchedulePayload | null {\n  const entry = read(operatorId, encodedUserKey, localDate)\n  if (!entry) return null\n  return nowMs - entry.at > TTL_MS ? null : entry.payload\n}\n\n/** The /schedule-failed path: fixtures do not move, so a stale day beats an empty tab. */\nexport function readScheduleIgnoringTtl(\n  operatorId: string, encodedUserKey: string, localDate: string,\n): SchedulePayload | null {\n  return read(operatorId, encodedUserKey, localDate)?.payload ?? null\n}\n\n// The cache is skeleton-only by construction, not by convention: a payload is rebuilt\n// field-by-field here so an excess live-state field on the wire can never be persisted.\nfunction skeletonOnly(payload: SchedulePayload): SchedulePayload {\n  return {\n    localDate: payload.localDate,\n    groups: payload.groups.map((g) => ({\n      competitionId: g.competitionId,\n      competitionName: g.competitionName,\n      competitionCountry: g.competitionCountry ?? null,\n      competitionImagePath: g.competitionImagePath ?? null,\n      rank: g.rank,\n      expandedByDefault: g.expandedByDefault,\n      isStarred: g.isStarred,\n      isLearned: g.isLearned,\n      learnedRank: g.learnedRank,\n      matches: g.matches.map((m) => ({\n        matchId: m.matchId,\n        homeTeamName: m.homeTeamName,\n        awayTeamName: m.awayTeamName,\n        homeTeamImagePath: m.homeTeamImagePath ?? null,\n        awayTeamImagePath: m.awayTeamImagePath ?? null,\n        kickoffUnix: m.kickoffUnix,\n      })),\n    })),\n  }\n}\n\nexport function writeSchedule(\n  operatorId: string, encodedUserKey: string, localDate: string, payload: SchedulePayload, nowMs: number,\n): void {\n  const keep = scheduleCacheKey(operatorId, encodedUserKey, localDate)\n  // Scoped to this operator AND user: two users of one operator can share a browser, and pruning\n  // the operator prefix would evict the other user's day on every write.\n  const mine = `${PREFIX}${operatorId}:${encodedUserKey}:`\n  try {\n    for (let i = localStorage.length - 1; i >= 0; i--) {\n      const key = localStorage.key(i)\n      if (key && key.startsWith(mine) && key !== keep) localStorage.removeItem(key)\n    }\n    const entry: Entry = { v: SCHEMA_VERSION, at: nowMs, payload: skeletonOnly(payload) }\n    localStorage.setItem(keep, JSON.stringify(entry))\n  } catch {\n    // A full or blocked localStorage must not break the tab; the schedule refetches next mount.\n  }\n}\n\n/** Patches one group's star flags in place, reusing the entry's ORIGINAL `at` so a star tap\n *  cannot silently extend the cache's TTL. A cache miss (expired/never written) is a no-op --\n *  there is no correct `at` to write under, and the next real fetch will carry the true state. */\nexport function patchScheduleStar(\n  operatorId: string, encodedUserKey: string, localDate: string, competitionId: number,\n  star: { isStarred: boolean; isLearned: boolean; learnedRank: number | null },\n): void {\n  const entry = read(operatorId, encodedUserKey, localDate)\n  if (!entry) return\n  const groups = entry.payload.groups.map((g) => (g.competitionId === competitionId ? { ...g, ...star } : g))\n  writeSchedule(operatorId, encodedUserKey, localDate, { ...entry.payload, groups }, entry.at)\n}\n","import type { ScheduleGroup, MatchState } from '@sensiblestats/widget-sdk'\n\n// Phases that never change again, so one answer is the last answer we need. Everything else --\n// preMatch (the clock passed but the feed has not flipped yet) and live -- is still moving.\nconst TERMINAL_PHASES: ReadonlySet<string> = new Set(['fullTime', 'postponed'])\n\n/**\n * Which of today's matches to ask about. Anything past its kickoff clock that has not yet given us\n * a terminal answer, and nothing else.\n *\n * This replaced a fixed 3.5-hour window after kickoff. The window bounded the REQUEST, but on a\n * cold load it also silently bounded what we could ever KNOW: open the widget at 15:13 and a match\n * that kicked off at 11:00 was already outside it, so it was never asked about, had no state, and\n * rendered as a fixture that had not started -- kickoff time, no score -- four hours after it\n * finished 0-1. Matches inside the window showed FT correctly, which is why only the older half of\n * the day looked wrong.\n *\n * Terminating on the answer rather than on the clock is also strictly cheaper in the steady state:\n * every finished match drops out permanently after one reply, so a late-evening poll carries only\n * what is actually still playing. The schedule is one day, and the endpoint caps at 200 ids.\n */\nexport function dueMatchIds(\n  groups: ScheduleGroup[], states: Record<number, MatchState>, nowMs: number,\n): number[] {\n  const due = new Set<number>()\n\n  for (const group of groups) {\n    for (const match of group.matches) {\n      if (nowMs - match.kickoffUnix * 1000 < 0) continue\n      const phase = states[match.matchId]?.phase\n      if (phase !== undefined && TERMINAL_PHASES.has(phase)) continue\n      due.add(match.matchId)\n    }\n  }\n\n  return [...due]\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { GameListPayload, GameSummary } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nconst GAMES_POLL_MS = 60_000\nconst DEFAULT_TZ = 'Europe/London'\n\nfunction computeGameDay(timezone: string): string {\n  // en-CA uses YYYY-MM-DD format\n  return new Intl.DateTimeFormat('en-CA', { timeZone: timezone }).format(new Date())\n}\n\nexport interface UseGamesResult {\n  enabled: boolean\n  games: GameSummary[]\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useGames(\n  conversation: { getGames: (gameDay?: string) => Promise<GameListPayload | null> } | null | undefined,\n  { activeTab, operatorTimezone }: { activeTab: WidgetTab; operatorTimezone?: string },\n): UseGamesResult {\n  // Games/Leaderboard tabs are hidden until we KNOW this operator has games. Every operator shares\n  // one games backend, so a non-games operator does not 404 — it returns 200 with an empty list.\n  // Gating on games.length (not on the 404 sentinel) is what keeps the tabs off those operators;\n  // defaulting to false avoids flashing the tabs on every operator during the first fetch.\n  const [enabled, setEnabled] = useState(false)\n  const [games, setGames] = useState<GameSummary[]>([])\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  // Set only when the feature is entirely off for this operator (backend 404). Stops all polling —\n  // distinct from \"enabled\", which merely reflects whether today's list has any games.\n  const hardOffRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n  const tzRef = useRef(operatorTimezone ?? DEFAULT_TZ)\n  tzRef.current = operatorTimezone ?? DEFAULT_TZ\n\n  // The conversation is often null on first render and set once the widget finishes initialising.\n  // It is intentionally NOT read through the ref in the effect deps — the effect must re-run when\n  // it becomes available, or the one-shot fetch never fires and the tabs never appear. (Defaulting\n  // `enabled` to true used to paper over this; gating on the games list means we must actually\n  // fetch.)\n  const ready = conversation != null\n\n  useEffect(() => {\n    if (hardOffRef.current) return\n    let active = true\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current || !active) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        const gameDay = computeGameDay(tzRef.current)\n        const result = await conv.getGames(gameDay)\n        if (!active) return\n        if (result === null) {\n          // 404: games feature is not enabled for this operator at all — hide and stop polling.\n          hardOffRef.current = true\n          setEnabled(false)\n          setGames([])\n        } else {\n          // 200: show the tabs only when this operator actually has games today.\n          setGames(result.games)\n          setEnabled(result.games.length > 0)\n        }\n      } catch {\n        // swallow; retry next tick\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    // Always fetch once on mount or refresh\n    void doFetch()\n\n    // Poll while the games tab is active\n    let intervalId: number | undefined\n    if (activeTab === 'games') {\n      intervalId = window.setInterval(() => {\n        if (hardOffRef.current) {\n          window.clearInterval(intervalId)\n          return\n        }\n        void doFetch()\n      }, GAMES_POLL_MS)\n    }\n\n    return () => {\n      active = false\n      // Release the in-flight guard so a remount (React StrictMode double-invokes effects, and any\n      // dependency change re-runs this one) can fetch again. Without this, the first run's request\n      // is still in flight when the second run checks the guard, the second run bails, and the\n      // first run's result is dropped because `active` is now false — so `enabled` is never set.\n      inFlightRef.current = false\n      if (intervalId !== undefined) window.clearInterval(intervalId)\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [activeTab, refreshCount, ready])\n\n  const refresh = useCallback(() => {\n    setRefreshCount((c) => c + 1)\n  }, [])\n\n  return { enabled, games, loading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseLeaderboardResult {\n  data: LeaderboardPayload | null\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useLeaderboard(\n  conversation: { getLeaderboard: () => Promise<LeaderboardPayload | null> } | null | undefined,\n  { activeTab }: { activeTab: WidgetTab },\n): UseLeaderboardResult {\n  const [data, setData] = useState<LeaderboardPayload | null>(null)\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n\n  useEffect(() => {\n    // The Games hub's stat row (rank, streak) reads the same payload.\n    if (activeTab !== 'games') return\n    let active = true\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        const result = await conv.getLeaderboard()\n        if (active) setData(result)\n      } catch {\n        // swallow; keep previous data\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    void doFetch()\n    return () => {\n      active = false\n      // Release the guard so a refresh fired while this fetch is still in flight (a quick tap into a\n      // game and back) runs its own fetch instead of bailing — the same fix useGames carries.\n      inFlightRef.current = false\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [activeTab, refreshCount])\n\n  const refresh = useCallback(() => {\n    setRefreshCount((c) => c + 1)\n  }, [])\n\n  return { data, loading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { ClubFixture, ClubFixturesPayload } from '@sensiblestats/widget-sdk'\n\nconst CLUB_PROBE_RETRY_MS = 15_000\n// A persistent non-404 error (a gateway not yet deployed, a misconfigured key, a sustained 429)\n// must not retry forever: every page view of every tenant would poll indefinitely, and the club\n// probe sharing a rate-limit bucket with chat makes that a chat-throttling risk too.\nconst CLUB_PROBE_MAX_ATTEMPTS = 3\n\nexport interface UseClubFixturesResult {\n  enabled: boolean\n  settled: boolean\n  fixtures: ClubFixture[]\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useClubFixtures(\n  conversation: { getClubFixtures: (competitionId?: number, limit?: number) => Promise<ClubFixturesPayload | null> } | null | undefined,\n): UseClubFixturesResult {\n  const [enabled, setEnabled] = useState(false)\n  const [settled, setSettled] = useState(false)\n  const [fixtures, setFixtures] = useState<ClubFixture[]>([])\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  const hardOffRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n  const ready = conversation != null\n\n  useEffect(() => {\n    if (hardOffRef.current) return\n    let active = true\n    let retryTimeoutId: number | undefined\n    let attempts = 0\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current || !active) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        attempts += 1\n        const result = await conv.getClubFixtures()\n        if (!active) return\n        if (result === null) {\n          hardOffRef.current = true\n          setEnabled(false)\n          setFixtures([])\n        } else {\n          setFixtures(result.fixtures)\n          setEnabled(true)\n        }\n        setSettled(true)\n      } catch {\n        // Not a 404 — must not hard-off on the first failure (Review Focus). A dropped request\n        // must not permanently hide the Club tabs for the rest of the session. But a PERSISTENT\n        // error (gateway not yet deployed, bad key, a sustained 429) must not retry forever either\n        // — cap it and settle disabled, same end state as a 404.\n        if (!active) return\n        if (attempts < CLUB_PROBE_MAX_ATTEMPTS) {\n          retryTimeoutId = window.setTimeout(() => {\n            if (!hardOffRef.current) void doFetch()\n          }, CLUB_PROBE_RETRY_MS)\n        } else {\n          setEnabled(false)\n          setFixtures([])\n          setSettled(true)\n        }\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    void doFetch()\n\n    return () => {\n      active = false\n      inFlightRef.current = false\n      if (retryTimeoutId !== undefined) window.clearTimeout(retryTimeoutId)\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [refreshCount, ready])\n\n  const refresh = useCallback(() => setRefreshCount((c) => c + 1), [])\n\n  return { enabled, settled, fixtures, loading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { ClubStandingRow, ClubStandingsPayload } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseClubStandingsResult {\n  data: ClubStandingRow[] | null\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useClubStandings(\n  conversation: { getClubStandings: (competitionId?: number) => Promise<ClubStandingsPayload | null> } | null | undefined,\n  { activeTab, enabled }: { activeTab: WidgetTab; enabled: boolean },\n): UseClubStandingsResult {\n  const [data, setData] = useState<ClubStandingRow[] | null>(null)\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n\n  useEffect(() => {\n    if (activeTab !== 'standings' || !enabled) return\n    let active = true\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        const result = await conv.getClubStandings()\n        if (active) setData(result?.rows ?? null)\n      } catch {\n        // swallow; keep previous data\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    void doFetch()\n    return () => {\n      active = false\n      inFlightRef.current = false\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [activeTab, enabled, refreshCount])\n\n  const refresh = useCallback(() => {\n    setRefreshCount((c) => c + 1)\n  }, [])\n\n  // The fetch effect's setLoading(true) lands a render cycle after this one — without this,\n  // activating the tab paints the empty message for one frame before the fetch even starts.\n  const effectiveLoading = loading || (activeTab === 'standings' && enabled && data === null)\n\n  return { data, loading: effectiveLoading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { ClubSquadPayload, ClubSquadPlayer } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseClubSquadResult {\n  data: ClubSquadPlayer[] | null\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useClubSquad(\n  conversation: { getClubSquad: () => Promise<ClubSquadPayload | null> } | null | undefined,\n  { activeTab, enabled }: { activeTab: WidgetTab; enabled: boolean },\n): UseClubSquadResult {\n  const [data, setData] = useState<ClubSquadPlayer[] | null>(null)\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n\n  useEffect(() => {\n    if (activeTab !== 'squad' || !enabled) return\n    let active = true\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        const result = await conv.getClubSquad()\n        if (active) setData(result?.players ?? null)\n      } catch {\n        // swallow; keep previous data\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    void doFetch()\n    return () => {\n      active = false\n      inFlightRef.current = false\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [activeTab, enabled, refreshCount])\n\n  const refresh = useCallback(() => {\n    setRefreshCount((c) => c + 1)\n  }, [])\n\n  // The fetch effect's setLoading(true) lands a render cycle after this one — without this,\n  // activating the tab paints the empty message for one frame before the fetch even starts.\n  const effectiveLoading = loading || (activeTab === 'squad' && enabled && data === null)\n\n  return { data, loading: effectiveLoading, refresh }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { ClubPlayerSeasonStats, ClubSquadStatsPayload } from '@sensiblestats/widget-sdk'\nimport type { WidgetTab } from './useTabs'\n\nexport interface UseClubSquadStatsResult {\n  data: ClubPlayerSeasonStats[] | null\n  seasonName: string | null\n  competitionName: string | null\n  matchesPlayed: number | null\n  loading: boolean\n  refresh: () => void\n}\n\nexport function useClubSquadStats(\n  conversation: { getClubSquadStats: () => Promise<ClubSquadStatsPayload | null> } | null | undefined,\n  { activeTab, enabled }: { activeTab: WidgetTab; enabled: boolean },\n): UseClubSquadStatsResult {\n  const [data, setData] = useState<ClubPlayerSeasonStats[] | null>(null)\n  const [seasonName, setSeasonName] = useState<string | null>(null)\n  const [competitionName, setCompetitionName] = useState<string | null>(null)\n  const [matchesPlayed, setMatchesPlayed] = useState<number | null>(null)\n  const [loading, setLoading] = useState(false)\n  const [refreshCount, setRefreshCount] = useState(0)\n\n  const inFlightRef = useRef(false)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n\n  useEffect(() => {\n    if (activeTab !== 'squad' || !enabled) return\n    let active = true\n\n    const doFetch = async (): Promise<void> => {\n      const conv = conversationRef.current\n      if (!conv || inFlightRef.current) return\n      inFlightRef.current = true\n      setLoading(true)\n      try {\n        const result = await conv.getClubSquadStats()\n        if (active) {\n          setData(result?.players ?? null)\n          setSeasonName(result?.seasonName ?? null)\n          setCompetitionName(result?.competitionName ?? null)\n          setMatchesPlayed(result?.clubMatchesPlayed ?? null)\n        }\n      } catch {\n        // swallow; keep previous data\n      } finally {\n        inFlightRef.current = false\n        if (active) setLoading(false)\n      }\n    }\n\n    void doFetch()\n    return () => {\n      active = false\n      inFlightRef.current = false\n    }\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [activeTab, enabled, refreshCount])\n\n  const refresh = useCallback(() => {\n    setRefreshCount((c) => c + 1)\n  }, [])\n\n  // The fetch effect's setLoading(true) lands a render cycle after this one — without this,\n  // activating the tab paints the empty message for one frame before the fetch even starts.\n  const effectiveLoading = loading || (activeTab === 'squad' && enabled && data === null)\n\n  return { data, seasonName, competitionName, matchesPlayed, loading: effectiveLoading, refresh }\n}\n","import { useCallback, useRef, useState } from 'react'\nimport type { ClubPlayerDetailPayload } from '@sensiblestats/widget-sdk'\n\nexport interface UseClubPlayerDetailResult {\n  data: ClubPlayerDetailPayload | null\n  loading: boolean\n  fetch: (playerId: number) => void\n  clear: () => void\n}\n\nexport function useClubPlayerDetail(\n  conversation: { getClubPlayerDetail: (playerId: number) => Promise<ClubPlayerDetailPayload | null> } | null | undefined,\n): UseClubPlayerDetailResult {\n  const [data, setData] = useState<ClubPlayerDetailPayload | null>(null)\n  const [loading, setLoading] = useState(false)\n\n  const requestSeqRef = useRef(0)\n  const conversationRef = useRef(conversation)\n  conversationRef.current = conversation\n\n  const fetch = useCallback((playerId: number) => {\n    const conv = conversationRef.current\n    if (!conv) return\n    const seq = ++requestSeqRef.current\n    setData(null)\n    setLoading(true)\n    void (async () => {\n      try {\n        const result = await conv.getClubPlayerDetail(playerId)\n        if (seq === requestSeqRef.current) setData(result)\n      } catch {\n        // swallow; keep previous data\n      } finally {\n        if (seq === requestSeqRef.current) setLoading(false)\n      }\n    })()\n  }, [])\n\n  const clear = useCallback(() => {\n    requestSeqRef.current++\n    setData(null)\n    setLoading(false)\n  }, [])\n\n  return { data, loading, fetch, clear }\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { PresetGrid } from '@sensiblestats/widget-sdk'\nimport { isPresetGrid } from './presetGrid'\n\n/** R12 / contract §1 (ruling 1f8954432): a preview may show a grid up to 10 minutes old. */\nexport const GRID_MAX_AGE_MS = 600_000\n\n/**\n * Onboarding presets stage 2 (contract §1): the grid behind the two tools, asked for in the\n * background after the panel opens. A panel open asks again when the last call was not a 200 or\n * the kept body's builtAtUtc is more than 10 minutes old (an unparseable one counts as old). A new\n * 200 replaces the kept body, a 404 drops it, and a 503, a network error or a malformed body keeps it.\n * Never asked twice in the same open, never two requests at once. Lives in StatsWidget, which lives\n * for the page (P1).\n */\nexport function usePresetGrid({ getPricePresets, isOpen, locale, now = Date.now }: {\n  getPricePresets: (locale: 'en' | 'tr') => Promise<PresetGrid | null>\n  isOpen: boolean\n  locale: 'en' | 'tr'\n  now?: () => number\n}): PresetGrid | null {\n  const [grid, setGrid] = useState<PresetGrid | null>(null)\n  const keptRef = useRef<PresetGrid | null>(null)\n  const localeRef = useRef(locale)\n  const inFlightRef = useRef(false)\n  const mountedRef = useRef(true)\n  // Read through refs so a caller that passes new functions each render never re-asks.\n  const getRef = useRef(getPricePresets)\n  getRef.current = getPricePresets\n  const nowRef = useRef(now)\n  nowRef.current = now\n\n  useEffect(() => {\n    mountedRef.current = true\n    return () => { mountedRef.current = false }\n  }, [])\n\n  useEffect(() => {\n    if (localeRef.current !== locale) {\n      localeRef.current = locale\n      keptRef.current = null\n      setGrid(null)\n    }\n    if (!isOpen || inFlightRef.current) return\n    const kept = keptRef.current\n    const age = kept ? nowRef.current() - Date.parse(kept.builtAtUtc) : Number.NaN\n    // `age <= max` is false for NaN, so no kept grid, or an unparseable builtAtUtc, counts as old.\n    if (age <= GRID_MAX_AGE_MS) return\n    inFlightRef.current = true\n    // Promise.resolve().then: a client without the method (an older injected client) throws inside\n    // the chain, not in this effect.\n    Promise.resolve()\n      .then(() => getRef.current(locale))\n      .then((body) => {\n        // A 404 drops the kept grid (contract §1, aa45ad6ad): the round button and any open tool go\n        // away, which is how cool-off and a flag turned off reach an open page. A grid with no cell in\n        // any row is dropped too, so a quiet day never shows a tool where every number is unavailable;\n        // the next open asks again.\n        if (body === null || (isPresetGrid(body) && !hasAnyCell(body))) {\n          keptRef.current = null\n          if (mountedRef.current) setGrid(null)\n          return\n        }\n        if (!isPresetGrid(body)) return\n        keptRef.current = body\n        if (mountedRef.current) setGrid(body)\n      })\n      .catch(() => { /* the kept body stays; the next open asks again */ })\n      .finally(() => { inFlightRef.current = false })\n  }, [isOpen, locale])\n\n  return grid\n}\n\nfunction hasAnyCell(grid: PresetGrid): boolean {\n  return grid.singles.length > 0 || grid.singlesFrom.length > 0 || grid.combos.length > 0\n    || (grid.markets !== undefined && grid.markets.length > 0)\n}\n","// Onboarding presets stage 2: the grid rules the widget owns (contract §2-§4). The server builds\n// every pick, total and multiplication line; the widget only offers the numbers, finds the cell a\n// choice names, and words the ask a Send carries.\nimport type { ChatPreset, PresetComboCell, PresetGrid, PresetMarketCell, PresetPick, PresetSinglesCell } from '@sensiblestats/widget-sdk'\nimport type { PresetStrings } from './i18n'\n\nexport const DEFAULT_SINGLES_LIMITS: readonly number[] = [1.3, 1.5, 1.7, 2.0]\nexport const DEFAULT_SINGLES_FLOORS: readonly number[] = [1.5, 2.0, 2.5, 3.0]\nexport const DEFAULT_COMBO_TOTALS: readonly number[] = [3, 5, 10, 20, 50]\n/** contract §4: \"3 picks, max [1.50]\" and \"Picks from [2.00] up\" keep the count at 3. */\nexport const FIXED_SINGLES_COUNT = 3\nconst MIN_COMBO_LEGS = 2\n/** G9: never more than 6 legs, whatever the operator allows. */\nconst MAX_COMBO_LEGS = 6\n/** The numbers each row starts on, as the contract's examples read. */\nexport const START = { maxPrice: 1.5, minPrice: 2, comboTotal: 5, comboLegs: 3 } as const\n\nconst finite = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v)\nconst cents = (n: number): number => Math.round(n * 100)\n\nexport function samePrice(a: number, b: number): boolean {\n  return cents(a) === cents(b)\n}\n\n/** P12: a body without the three arrays and a numeric maxLegs counts as no 200. */\nexport function isPresetGrid(v: unknown): v is PresetGrid {\n  if (!v || typeof v !== 'object') return false\n  const g = v as Record<string, unknown>\n  return Array.isArray(g.singles) && Array.isArray(g.singlesFrom) && Array.isArray(g.combos) && finite(g.maxLegs)\n}\n\nfunction drawable(p: PresetPick | null | undefined): boolean {\n  return !!p && finite(p.price) && finite(p.matchOddsId) && finite(p.matchId) && typeof p.homeTeamName === 'string' && typeof p.awayTeamName === 'string'\n}\n\n/** contract §2: the defaults plus every value some cell has, so a missing value still draws. */\nfunction choices(defaults: readonly number[], present: unknown[]): number[] {\n  const out: number[] = []\n  for (const n of [...defaults, ...present]) {\n    if (finite(n) && n > 0 && !out.some((m) => samePrice(m, n))) out.push(n)\n  }\n  return out.sort((a, b) => a - b)\n}\n\nexport function singlesLimits(grid: PresetGrid): number[] {\n  return choices(DEFAULT_SINGLES_LIMITS, grid.singles.map((c) => c?.price))\n}\n\nexport function singlesFloors(grid: PresetGrid): number[] {\n  return choices(DEFAULT_SINGLES_FLOORS, grid.singlesFrom.map((c) => c?.price))\n}\n\nexport function comboTotals(grid: PresetGrid): number[] {\n  return choices(DEFAULT_COMBO_TOTALS, grid.combos.map((c) => c?.total))\n}\n\nexport function comboLegChoices(grid: PresetGrid): number[] {\n  const max = Math.min(MAX_COMBO_LEGS, Math.floor(grid.maxLegs))\n  const out: number[] = []\n  for (let n = MIN_COMBO_LEGS; n <= max; n++) out.push(n)\n  return out\n}\n\n/** A tap moves to the next value; from the last it wraps to the first. */\nexport function cycle(values: number[], current: number): number {\n  if (values.length === 0) return current\n  const i = values.findIndex((v) => samePrice(v, current))\n  return values[(i + 1) % values.length] ?? current\n}\n\nexport function startValue(values: number[], preferred: number): number {\n  return values.find((v) => samePrice(v, preferred)) ?? values[0] ?? preferred\n}\n\n/** P9: a combo card's target snaps to the closest offered total, by ratio not by difference. */\nexport function nearest(values: number[], target: number): number {\n  const first = values[0]\n  if (first === undefined) return target\n  if (!(target > 0)) return first\n  const distance = (v: number): number => Math.abs(Math.log(v / target))\n  return values.reduce((best, v) => (distance(v) < distance(best) ? v : best), first)\n}\n\nexport function clampLegs(values: number[], legs: number): number {\n  const lo = values[0]\n  const hi = values[values.length - 1]\n  if (lo === undefined || hi === undefined) return legs\n  return Math.min(Math.max(Math.round(legs), lo), hi)\n}\n\nexport function findSingles(cells: PresetSinglesCell[], price: number, count: number): PresetSinglesCell | null {\n  const cell = cells.find((c) => !!c && finite(c.price) && samePrice(c.price, price) && c.count === count)\n  return cell && Array.isArray(cell.picks) && cell.picks.length === count && cell.picks.every(drawable) ? cell : null\n}\n\nexport function findCombo(grid: PresetGrid, total: number, legs: number): PresetComboCell | null {\n  const cell = grid.combos.find((c) => !!c && finite(c.total) && samePrice(c.total, total) && c.legs === legs)\n  const combo = cell?.combo\n  const whole = !!combo && typeof combo.multiplication === 'string' && combo.multiplication !== ''\n    && Array.isArray(combo.legs) && combo.legs.length === legs && combo.legs.every(drawable)\n  return cell && whole ? cell : null\n}\n\n/** A total that exists only at another match count moves the count to the nearest one that has it; a tie takes the smaller. */\nexport function legsForTotal(grid: PresetGrid, total: number, legs: number): number {\n  if (findCombo(grid, total, legs)) return legs\n  let best = legs\n  let bestGap = Infinity\n  for (const n of comboLegChoices(grid)) {\n    if (!findCombo(grid, total, n)) continue\n    const gap = Math.abs(n - legs)\n    if (gap < bestGap) { best = n; bestGap = gap }\n  }\n  return best\n}\n\n/** Opens a singles row on START when its cell exists, else on the closest value that has one (a tie takes the smaller); with no cell anywhere it stays on START. */\nexport function startSingles(cells: PresetSinglesCell[], values: number[], start: number, count: number): number {\n  const home = startValue(values, start)\n  if (findSingles(cells, home, count)) return home\n  let best: number | null = null\n  for (const v of values) {\n    if (!findSingles(cells, v, count)) continue\n    if (best === null || Math.abs(cents(v) - cents(start)) < Math.abs(cents(best) - cents(start))) best = v\n  }\n  return best ?? home\n}\n\n/** Opens a combo on (START total, START legs) when that cell exists, else on the closest total with a cell at any count, at the count nearest START legs. */\nexport function startCombo(grid: PresetGrid, totals: number[], legChoices: number[], startTotal: number, startLegs: number): { total: number; legs: number } {\n  const home = { total: startValue(totals, startTotal), legs: startValue(legChoices, startLegs) }\n  if (findCombo(grid, home.total, home.legs)) return home\n  let best: number | null = null\n  for (const t of totals) {\n    if (!legChoices.some((n) => findCombo(grid, t, n))) continue\n    if (best === null || Math.abs(cents(t) - cents(startTotal)) < Math.abs(cents(best) - cents(startTotal))) best = t\n  }\n  return best === null ? home : { total: best, legs: legsForTotal(grid, best, home.legs) }\n}\n\n/** What a tool's Send puts in the chat (contract §3, §5). */\nexport interface PresetAsk {\n  message: string\n  displayText: string\n  preset: ChatPreset\n}\n\n/** contract §3: the shown picks' ids, in the order shown, with their match ids index for index. */\nfunction idsOf(picks: PresetPick[]): Pick<ChatPreset, 'matchOddsIds' | 'matchIds'> {\n  return { matchOddsIds: picks.map((p) => p.matchOddsId), matchIds: picks.map((p) => p.matchId) }\n}\n\nexport function maxPriceAsk(cell: PresetSinglesCell, s: PresetStrings): PresetAsk {\n  return {\n    message: s.maxPriceMessage(cell.count, cell.price),\n    displayText: s.maxPriceDisplay(cell.count, cell.price),\n    preset: { kind: 'max_price', price: cell.price, count: cell.count, ...idsOf(cell.picks) },\n  }\n}\n\nexport function minPriceAsk(cell: PresetSinglesCell, s: PresetStrings): PresetAsk {\n  return {\n    message: s.minPriceMessage(cell.count, cell.price),\n    displayText: s.minPriceDisplay(cell.count, cell.price),\n    preset: { kind: 'min_price', price: cell.price, count: cell.count, ...idsOf(cell.picks) },\n  }\n}\n\nexport function comboAsk(cell: PresetComboCell, s: PresetStrings): PresetAsk {\n  return {\n    message: s.comboMessage(cell.legs, cell.total),\n    displayText: s.comboDisplay(cell.legs, cell.total),\n    preset: { kind: 'combo', total: cell.total, legs: cell.legs, ...idsOf(cell.combo.legs) },\n  }\n}\n\nexport function marketAsk(cell: PresetMarketCell, s: PresetStrings): PresetAsk {\n  return {\n    message: s.marketMessage(cell.marketLabel, cell.selectionLabel ?? null, cell.count),\n    displayText: marketDisplay(cell, s),\n    preset: { kind: 'market', marketDeveloperName: cell.marketDeveloperName, ...idsOf(cell.picks) },\n  }\n}\n\n/** The row's sentence with the short market name: the bubble text and the Send's name. */\nexport function marketDisplay(cell: PresetMarketCell, s: PresetStrings): string {\n  return s.marketRow.replace('{market}', s.marketShort(cell.marketDeveloperName, cell.marketLabel, cell.selectionLabel ?? null))\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\n\n/**\n * The single question \"is this match being presented as live right now\". Both sides of the seam\n * must ask it the same way: TodayPanel uses it to pick the live band, LeagueDetail uses its\n * negation to decide what stays in its own fixture list. If the two ever disagree a match falls\n * through the gap and renders nowhere — that is a defect this codebase has already shipped once.\n *\n * `pollStale` is OUR fetch failing, which is a real reason to stop trusting every state at once.\n * There is deliberately no per-match staleness test here; see the note in FixtureRow.\n */\nexport function isTreatedLive(state: MatchState | undefined, pollStale: boolean): boolean {\n  return state?.phase === 'live' && !pollStale\n}\n\n/**\n * A match the Today tab has no reason to keep listing. The schedule endpoint already excludes\n * terminal matches server-side (LiveMonitorScheduleComposer filters Match.MatchState), but the\n * client caches a day's schedule in localStorage for six hours — so a match that finishes while\n * the panel is open would linger in a list a fresh load would not show it in. This closes that\n * gap so both paths agree.\n *\n * fullTime only, deliberately. `postponed` arises server-side when a fixture has no kickoff\n * timestamp, which the schedule query already excludes, and hiding a postponed fixture from the\n * day it was scheduled for would be a different decision than the one being made here.\n */\nexport function isFinished(state: MatchState | undefined): boolean {\n  return state?.phase === 'fullTime'\n}\n\n/**\n * What the Today tab actually contains, after the finished matches leave. This is the ONE answer\n * both the panel and the tab strip read: TodayPanel renders it, and `hasToday` decides from its\n * length whether the tab exists at all. Deciding the tab from the raw schedule instead is what\n * shipped a Today tab opening onto a blank panel once every match of the day had ended.\n */\nexport function visibleGroupsOf(\n  groups: readonly ScheduleGroup[],\n  states: Record<number, MatchState>,\n): ScheduleGroup[] {\n  return groups\n    .map((group) => ({ ...group, matches: group.matches.filter((m) => !isFinished(states[m.matchId])) }))\n    .filter((group) => group.matches.length > 0)\n}\n","import { createContext, useContext } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\nexport const EventLogContext = createContext<EventLogger | null>(null)\n\nexport function useEventLog(): EventLogger | null {\n  return useContext(EventLogContext)\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\n// Returns the dismiss handler to hand the launcher. Opening is detected from state rather than\n// by wrapping open(): OPEN clears popupText in the same render, so the text seen while closed is\n// remembered to tell a popup open from a plain launcher open.\nexport function usePopupTelemetry(\n  log: EventLogger | null,\n  isOpen: boolean,\n  popupText: string | null,\n  dismissPopup: () => void,\n): () => void {\n  const shownRef = useRef(new Set<string>())\n  const closedTextRef = useRef<string | null>(null)\n\n  useEffect(() => {\n    if (isOpen) {\n      if (closedTextRef.current) log?.log({ name: 'popup_opened' })\n      closedTextRef.current = null\n      return\n    }\n    closedTextRef.current = popupText\n    if (popupText && !shownRef.current.has(popupText)) {\n      shownRef.current.add(popupText)\n      log?.log({ name: 'popup_shown' })\n    }\n  }, [log, isOpen, popupText])\n\n  return useCallback(() => {\n    log?.log({ name: 'popup_dismissed' })\n    dismissPopup()\n  }, [log, dismissPopup])\n}\n","import { useEffect, useRef } from 'react'\nimport type { EventLogger } from '@sensiblestats/widget-sdk'\n\n// Opening is detected from state, as in usePopupTelemetry, so the launcher, a popup bubble, an ask tap and a\n// programmatic open all count once. The flag resets on close even when there is no logger yet, and is set only\n// once an open has actually been logged, so a logger that arrives mid-open still reports it.\nexport function useOpenTelemetry(log: EventLogger | null, isOpen: boolean): void {\n  const openLoggedRef = useRef(false)\n\n  useEffect(() => {\n    if (!isOpen) {\n      openLoggedRef.current = false\n      return\n    }\n    if (openLoggedRef.current || !log) return\n    openLoggedRef.current = true\n    log.log({ name: 'widget_open' })\n  }, [log, isOpen])\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { BrandMark } from './BrandMark'\nimport { GreetingBubble, type GreetingBubbleAsk } from './GreetingBubble'\n\n// Only rendered while the panel is closed. The dynamic greeting popup takes\n// precedence over the static greeting and is dismissable; both open the panel.\n//\n// introAllowed/onIntroStart drive the one-shot attention animation (the FAB\n// nudges, then the greeting types in). The latch below fires it once, the first\n// time a bubble appears; onIntroStart lets the parent record that so it never\n// replays when the FAB remounts on a later panel close. Refreshing the page\n// remounts the whole widget and re-arms it.\nexport function ChatFab({ label, greeting, popupText, logoUrl, onOpen, onDismissPopup, dismissLabel = 'Dismiss', introAllowed = false, onIntroStart, asks }: { label: string; greeting?: string; popupText?: string | null; logoUrl?: string; onOpen: () => void; onDismissPopup: () => void; dismissLabel?: string; introAllowed?: boolean; onIntroStart?: () => void; asks?: GreetingBubbleAsk[] }): JSX.Element {\n  const bubble = popupText ?? greeting\n  const [intro, setIntro] = useState(false)\n  const armedRef = useRef(introAllowed)\n  useEffect(() => {\n    if (armedRef.current && bubble) {\n      armedRef.current = false\n      setIntro(true)\n      onIntroStart?.()\n    }\n  }, [bubble, onIntroStart])\n  return (\n    <div className={intro ? 'ss-w-fab-wrap ss-w-intro' : 'ss-w-fab-wrap'}>\n      {bubble ? <GreetingBubble text={bubble} onOpen={onOpen} onDismiss={popupText ? onDismissPopup : undefined} dismissLabel={dismissLabel} asks={popupText ? asks : undefined} /> : null}\n      <button type=\"button\" className=\"ss-w-fab\" aria-label={label} onClick={onOpen}>\n        <BrandMark logoUrl={logoUrl} className=\"ss-w-fab-mark\" />\n      </button>\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport { SsMark } from './Icons'\n\n// Operator logo with a hard fallback to the built-in SS mark: a missing or\n// broken logoUrl must never leave a blank in the header or launcher.\nexport function BrandMark({ logoUrl, className }: { logoUrl?: string; className?: string }): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  if (!logoUrl || failed) return <SsMark className={className} />\n  return <img className={className} src={logoUrl} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n}\n","// SensibleStats brand mark, inlined as a data URI so the published widget\n// bundle stays self-contained (no external asset hosting / CORS concerns\n// for third-party embeds).\nexport const SS_LOGO_DATA_URI = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjoAAAI6CAYAAAAuSOLAAAAAAXNSR0IArs4c6QAAAJplWElmTU0AKgAAAAgAAwESAAMAAAABAAEAAAExAAIAAAA9AAAAModpAAQAAAABAAAAcAAAAABBZG9iZSBQaG90b3Nob3AgMjYuMTAgKDIwMjUwNzMwLm0uMzE2NiAwN2IxMjM0KSAgKE1hY2ludG9zaCkAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAI6oAMABAAAAAEAAAI6AAAAACwGtVwAAAQwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6QzBGRTM5NjM5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6QzBGRTM5NjI5NEJEMTFGMEJGNjZEMjUyN0U0MzU5RUM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0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\"\n","// SensibleStats brand mark, rendered from the official logo asset.\nimport { SS_LOGO_DATA_URI } from '../assets/logo'\n\nexport function SsMark({ className }: { className?: string }): JSX.Element {\n  return <img className={className} src={SS_LOGO_DATA_URI} alt=\"\" aria-hidden=\"true\" />\n}\nexport function SendIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M3 20l18-8L3 4v6l12 2-12 2z\" /></svg>\n}\nexport function CloseIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M18 6L6 18M6 6l12 12\" stroke=\"currentColor\" strokeWidth=\"2\" /></svg>\n}\nexport function ChevronIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" /></svg>\n}\nexport function NewChatIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><path fill=\"none\" d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" /></svg>\n}\nexport function KebabIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><g fill=\"currentColor\"><circle cx=\"12\" cy=\"5\" r=\"1.6\" /><circle cx=\"12\" cy=\"12\" r=\"1.6\" /><circle cx=\"12\" cy=\"19\" r=\"1.6\" /></g></svg>\n}\nexport function SlidersIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><g fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\"><path d=\"M4 6h9M17 6h3M4 12h3M11 12h9M4 18h11M19 18h1\" /><circle cx=\"15\" cy=\"6\" r=\"2\" /><circle cx=\"9\" cy=\"12\" r=\"2\" /><circle cx=\"17\" cy=\"18\" r=\"2\" /></g></svg>\n}\nexport function ComboIcon(): JSX.Element {\n  return <svg viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" aria-hidden=\"true\"><g fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"11\" height=\"11\" rx=\"2\" /><rect x=\"10\" y=\"10\" width=\"11\" height=\"11\" rx=\"2\" /></g></svg>\n}\n\n// Dashboard tile icons are emoji (matching the betting widget mockup), not the old monochrome\n// line glyphs: they carry their own colour and read at a larger size. Rendered as text.\nconst DASHBOARD_EMOJI: Record<string, string> = {\n  football: '⚽', 'goal-net': '🥅', btts: '🤝',\n  card: '🟨', 'corner-flag': '🚩', player: '👤',\n  target: '🎯', trophy: '🏆', 'chart-line': '📈',\n  'chart-bar': '📊', chat: '💬', fire: '🔥', sparkle: '✨',\n}\n\nexport function DashboardIcon({ name }: { name: string }): JSX.Element {\n  // hasOwnProperty (not `in`, not `?? fallback`) so a prototype member name like 'toString'\n  // resolves to the fallback emoji rather than an inherited function or a stray property value.\n  const glyph = Object.prototype.hasOwnProperty.call(DASHBOARD_EMOJI, name)\n    ? DASHBOARD_EMOJI[name]\n    : DASHBOARD_EMOJI.target\n  return <span className=\"ss-w-dash-emoji\" aria-hidden=\"true\">{glyph}</span>\n}\n","export interface GreetingBubbleAsk { label: string; onTap: () => void }\n\n// The launcher bubble. With asks (spec C6) it becomes a container: buttons cannot nest, so the line\n// stays its own button that opens the panel, and each ask is a sibling button with its own name.\n// Without asks the markup is exactly today's.\nexport function GreetingBubble(\n  { text, onOpen, onDismiss, dismissLabel = 'Dismiss', asks }:\n  { text: string; onOpen?: () => void; onDismiss?: () => void; dismissLabel?: string; asks?: GreetingBubbleAsk[] },\n): JSX.Element {\n  const body = (\n    <button type=\"button\" className=\"ss-w-greeting-body\" onClick={onOpen}>\n      <span className=\"ss-w-greeting-dots\" aria-hidden=\"true\"><i></i><i></i><i></i></span>\n      <span className=\"ss-w-greeting-text\">{text}</span>\n    </button>\n  )\n  const dismiss = onDismiss ? (\n    <button type=\"button\" className=\"ss-w-greeting-x\" aria-label={dismissLabel} onClick={onDismiss}>×</button>\n  ) : null\n  if (!asks || asks.length === 0) {\n    return <div className=\"ss-w-greeting\" role=\"note\">{body}{dismiss}</div>\n  }\n  return (\n    <div className=\"ss-w-greeting ss-w-greeting--asks\" role=\"note\">\n      <div className=\"ss-w-greeting-top\">{body}{dismiss}</div>\n      <div className=\"ss-w-greeting-asks\">\n        {asks.map((ask, i) => (\n          <button key={`${i}:${ask.label}`} type=\"button\" className=\"ss-w-greeting-ask\" onClick={ask.onTap}>{ask.label}</button>\n        ))}\n      </div>\n    </div>\n  )\n}\n","import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, type CSSProperties } from 'react'\nimport type { ClubFixture, ClubStandingRow, ClubSquadPlayer, ClubPlayerSeasonStats, ClubPlayerDetailPayload, GameSummary, LeaderboardPayload, PresetGrid } from '@sensiblestats/widget-sdk'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport type { PresetAsk } from '../presetGrid'\nimport { ChatHeader } from './ChatHeader'\nimport { MessageList } from './MessageList'\nimport { ChatInput, type ChatInputHandle } from './ChatInput'\nimport { TabBar } from './TabBar'\nimport { MatchesPanel, OddsPanel } from './MonitorTabs'\nimport type { AskHandler } from './LiveFactBlock'\nimport { TodayPanel } from './TodayPanel'\nimport { GamesPanel } from './GamesPanel'\nimport { Fixtures } from './Fixtures'\nimport { Standings } from './Standings'\nimport { Squad } from './Squad'\nimport { PlayerDetail } from './PlayerDetail'\nimport { PresetSpeedDial, type PresetToolKind } from './PresetSpeedDial'\nimport { BuildComboTool, SetNumbersTool } from './PresetTools'\nimport { visibleGroupsOf } from '../liveClock'\nimport { PresetToolsContext, type PresetToolsValue } from '../presetToolsContext'\nimport { usePresetDial } from '../usePresetDial'\nimport { markToolSeen, readToolSeen } from '../presetSeen'\nimport { isPaused, limitText } from '../limit'\n\n// Mirrors the panel's fullscreen breakpoint in widget.css (@media max-width: 639px).\n// The panel only traps the page — and is thus truly modal — when it fills the viewport.\nexport const FULLSCREEN_QUERY = '(max-width: 639px)'\n\nfunction useIsModal(): boolean {\n  const [modal, setModal] = useState(false)\n  useEffect(() => {\n    if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return\n    const mql = window.matchMedia(FULLSCREEN_QUERY)\n    const sync = (): void => setModal(mql.matches)\n    sync()\n    mql.addEventListener('change', sync)\n    return () => mql.removeEventListener('change', sync)\n  }, [])\n  return modal\n}\n\n// The chat layer stays MOUNTED across tab switches so MessageList's scroll-anchoring refs survive.\n// On the Chat tab it is a positioned flex column (.ss-w-chat-layer, flex: 1, min-height: 0) so the\n// speed dial and a preset tool can sit against the message list (P6). Off the Chat tab: absolute +\n// visibility:hidden, so the list keeps its box (and its scroll position) but leaves .ss-w-panel's\n// flex flow and is neither painted nor interactive; `display: none` would zero the list's\n// clientHeight and reset its scrollTop. display:flex is required here: MessageList's root carries\n// `.ss-w-list { flex: 1; ... }`, which only takes effect on a flex-item child; without it the list\n// collapses to its content height, scrollHeight drops to clientHeight, and the browser clamps its\n// scrollTop to 0. `.ss-w-panel` is `position: fixed`, the containing block for this.\nconst HIDDEN_LAYER_STYLE: CSSProperties = { position: 'absolute', inset: 0, visibility: 'hidden', display: 'flex', flexDirection: 'column' }\n\nconst SQUAD_LAYER_STYLE: CSSProperties = { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }\n\ntype OpenTool = { kind: 'numbers' } | { kind: 'combo'; total?: number; legs?: number }\n\nexport function ChatPanel({ controller, ui, slip, onDashboardTap, monitor, discovery, gamesResult, leaderboardResult, clubFixturesResult, clubStandingsResult, clubSquadResult, clubSquadStatsResult, clubPlayerDetailResult, loggedIn, conversation, presetGrid }: {\n  controller: ChatController\n  ui: UiConfig\n  slip: SlipHandlerProps\n  onDashboardTap?: DashboardTapHandler\n  /** Optional -- absent (feature off / not threaded) renders today's DOM byte-identically. */\n  monitor?: LiveMonitorController\n  /** Optional -- absent means the Today tab never qualifies (see hasToday below). */\n  discovery?: MatchDiscoveryController\n  /** Games hook result; absent for non-club operators. */\n  gamesResult?: { enabled: boolean; games: GameSummary[]; loading: boolean; refresh: () => void }\n  /** Leaderboard hook result; absent for non-club operators. */\n  leaderboardResult?: { data: LeaderboardPayload | null; loading: boolean; refresh: () => void }\n  /** Club fixtures hook result; absent for non-club operators. */\n  clubFixturesResult?: { enabled: boolean; settled: boolean; fixtures: ClubFixture[]; loading: boolean; refresh: () => void }\n  /** Club standings hook result; absent for non-club operators. */\n  clubStandingsResult?: { data: ClubStandingRow[] | null; loading: boolean; refresh: () => void }\n  /** Club squad hook result; absent for non-club operators. */\n  clubSquadResult?: { data: ClubSquadPlayer[] | null; loading: boolean; refresh: () => void }\n  /** Club squad season-stats hook result; absent for non-club operators. */\n  clubSquadStatsResult?: { data: ClubPlayerSeasonStats[] | null; seasonName: string | null; competitionName?: string | null; matchesPlayed?: number | null; loading: boolean; refresh: () => void }\n  /** Club player detail hook result; absent for non-club operators. */\n  clubPlayerDetailResult?: { data: ClubPlayerDetailPayload | null; loading: boolean; fetch: (playerId: number) => void; clear: () => void }\n  /** True when the operator user is logged in (operatorUserId is set). */\n  loggedIn?: boolean\n  /** Conversation instance threaded down to GameScreenHost for game config fetching + play submits. */\n  conversation?: GamePlayConversation | null\n  /** Onboarding presets stage 2 (contract §1): the kept 200 grid. Absent or null: no round button. */\n  presetGrid?: PresetGrid | null\n}): JSX.Element {\n  const { state, close, stop, send, reset } = controller\n  const [squadView, setSquadView] = useState<'roster' | 'stats'>('roster')\n  const [selectedPlayerId, setSelectedPlayerId] = useState<number | null>(null)\n  const clearPlayerDetail = clubPlayerDetailResult?.clear\n  const fetchPlayerDetail = clubPlayerDetailResult?.fetch\n  const squadLayerRef = useRef<HTMLDivElement>(null)\n  const squadScrollRef = useRef<number | null>(null)\n  const selectPlayer = (playerId: number) => {\n    squadScrollRef.current = squadLayerRef.current?.querySelector('.ss-w-mon-list')?.scrollTop ?? null\n    setSelectedPlayerId(playerId)\n    fetchPlayerDetail?.(playerId)\n  }\n  const closePlayer = () => {\n    setSelectedPlayerId(null)\n    clearPlayerDetail?.()\n  }\n  // The hidden layer is absolute and taller than the visible one, so the browser clamps the list's scrollTop.\n  useLayoutEffect(() => {\n    if (selectedPlayerId !== null || squadScrollRef.current === null) return\n    const list = squadLayerRef.current?.querySelector('.ss-w-mon-list')\n    if (list) list.scrollTop = squadScrollRef.current\n    squadScrollRef.current = null\n  }, [selectedPlayerId])\n  const activeTab = monitor?.activeTab\n  useEffect(() => {\n    if (activeTab === 'squad' || selectedPlayerId === null) return\n    setSelectedPlayerId(null)\n    clearPlayerDetail?.()\n  }, [activeTab, selectedPlayerId, clearPlayerDetail])\n  const isModal = useIsModal()\n  useEffect(() => {\n    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close() }\n    window.addEventListener('keydown', onKey)\n    return () => window.removeEventListener('keydown', onKey)\n  }, [close])\n\n  // Composer always switches the visible tab to chat BEFORE the message is sent, so a reply\n  // streaming in is never invisible behind the Matches/Odds tab.\n  const handleSend = (text: string) => {\n    typedSendRef.current = true\n    monitor?.setActiveTab('chat')\n    send(text)\n  }\n\n  // \"Ask about this\" on a live fact: same tab-first rule as the composer, plus the grounding the\n  // server turns into [live_facts] context (spec §6).\n  const handleAsk: AskHandler = (text, grounding) => {\n    monitor?.setActiveTab('chat')\n    send(text, { grounding })\n  }\n\n  // A reply landing while the user is on another tab must surface the chat dot -- markChatActivity\n  // is idempotent (setChatDot(true) on an already-true dot is a no-op re-render), so re-running\n  // this on every streaming/message-count change is safe.\n  useEffect(() => {\n    if (monitor && monitor.activeTab !== 'chat' && state.isStreaming) monitor.markChatActivity()\n  }, [monitor, state.isStreaming, state.messages.length])\n\n  // Onboarding presets stage 2: the speed dial and the two tools (spec Stage 2 Behaviour).\n  const onChatTab = !monitor || monitor.activeTab === 'chat'\n  const layerRef = useRef<HTMLDivElement>(null)\n  const dialRef = useRef<HTMLDivElement>(null)\n  const dialButtonRef = useRef<HTMLButtonElement>(null)\n  const inputRef = useRef<ChatInputHandle>(null)\n  const limitRef = useRef<HTMLDivElement>(null)\n  const typedSendRef = useRef(false)\n  const focusAfterCloseRef = useRef<'dial' | 'composer' | null>(null)\n  const [tool, setTool] = useState<OpenTool | null>(null)\n  const [toolSeen, setToolSeen] = useState(readToolSeen)\n  const dial = usePresetDial({\n    layerRef, dialRef, dialButtonRef,\n    messages: state.messages, isStreaming: state.isStreaming, activeTab: monitor?.activeTab ?? 'chat',\n  })\n  const { fold } = dial\n  const paused = isPaused(state.limit)\n  const showDial = !!presetGrid && onChatTab && !tool && !paused\n  useEffect(() => { if (paused) setTool(null) }, [paused])\n  // A refused typed send unmounts the focused composer; keep focus in the panel instead of dropping it to the page.\n  useEffect(() => {\n    if (!paused) return\n    if (typedSendRef.current) limitRef.current?.focus()\n    typedSendRef.current = false\n  }, [paused])\n\n  const openTool = useCallback((next: OpenTool) => {\n    fold()\n    markToolSeen()\n    setToolSeen(true)\n    setTool(next)\n  }, [fold])\n  const onPill = useCallback((kind: PresetToolKind) => openTool(kind === 'numbers' ? { kind: 'numbers' } : { kind: 'combo' }), [openTool])\n  // spec C5: a combo card's \"Change total or matches\" opens the builder preset to that card.\n  const toolsValue = useMemo<PresetToolsValue | null>(\n    () => (presetGrid && !paused ? { openBuilder: (total, legs) => openTool({ kind: 'combo', total, legs }), changeLabel: ui.presets.changeCombo } : null),\n    [presetGrid, paused, openTool, ui.presets.changeCombo],\n  )\n  const closeTool = useCallback(() => {\n    focusAfterCloseRef.current = 'dial'\n    setTool(null)\n  }, [])\n  const sendAsk = useCallback((ask: PresetAsk) => {\n    focusAfterCloseRef.current = 'composer'\n    setTool(null)\n    monitor?.setActiveTab('chat')\n    send(ask.message, { displayText: ask.displayText, preset: ask.preset })\n  }, [monitor, send])\n\n  // contract §2: grid picks carry no kickoffLabel; the preview uses the widget's own kickoff format.\n  const formatKickoff = useCallback((kickoffUtc: string) => {\n    const k = ui.bettingKickoff(kickoffUtc)\n    return `${k.dayLabel} ${k.time}`\n  }, [ui])\n\n  // After a tool closes: focus to the composer after Send, to the round button after ✕ or Escape.\n  useEffect(() => {\n    if (tool) return\n    const target = focusAfterCloseRef.current\n    focusAfterCloseRef.current = null\n    if (target === 'dial') dialButtonRef.current?.focus()\n    else if (target === 'composer') inputRef.current?.focus()\n  }, [tool])\n\n  // P8: a tool lives over the message list; leaving the Chat tab closes it without sending. A 404 on a\n  // refetch drops the grid (contract §1), and the tool goes with it, so the composer comes back.\n  useEffect(() => {\n    if (!tool || (onChatTab && presetGrid)) return\n    focusAfterCloseRef.current = 'composer'\n    setTool(null)\n  }, [tool, onChatTab, presetGrid])\n\n  return (\n    <div className=\"ss-w-panel\" role=\"dialog\" aria-modal={isModal} aria-label={ui.chatDialogLabel}>\n      <ChatHeader\n        onClose={close}\n        closeLabel={ui.closeChat}\n        logoUrl={ui.logoUrl}\n        headerTitle={ui.headerTitle}\n        onNewConversation={reset}\n        canReset={state.messages.length > 0}\n        newConversationLabel={ui.newConversation}\n        moreOptionsLabel={ui.moreOptions}\n      />\n      {monitor && (\n        <TabBar\n          monitor={monitor}\n          ui={ui}\n          matchCount={monitor.pins.filter((p) => p.kind === 'match').length}\n          oddsCount={monitor.pins.filter((p) => p.kind !== 'match').length}\n          todayCount={discovery?.liveCount ?? 0}\n          hasToday={discovery ? visibleGroupsOf(discovery.groups, discovery.states).length > 0 : false}\n          gamesEnabled={gamesResult?.enabled ?? false}\n          clubEnabled={clubFixturesResult?.enabled ?? false}\n        />\n      )}\n      <div ref={layerRef} className=\"ss-w-chat-layer\" data-dial={presetGrid ? '' : undefined} style={onChatTab ? undefined : HIDDEN_LAYER_STYLE}>\n        <PresetToolsContext.Provider value={toolsValue}>\n          <MessageList controller={controller} ui={ui} slip={slip} onDashboardTap={onDashboardTap} monitor={monitor} />\n        </PresetToolsContext.Provider>\n        {showDial ? (\n          <PresetSpeedDial\n            expanded={dial.expanded} showDot={!toolSeen} strings={ui.presets}\n            onToggle={dial.toggle} onOpen={onPill} rootRef={dialRef} buttonRef={dialButtonRef}\n          />\n        ) : null}\n        {tool && presetGrid && onChatTab && !paused ? (\n          tool.kind === 'numbers'\n            ? <SetNumbersTool grid={presetGrid} strings={ui.presets} streaming={state.isStreaming} onSend={sendAsk} onClose={closeTool} />\n            : <BuildComboTool grid={presetGrid} strings={ui.presets} streaming={state.isStreaming} formatKickoff={formatKickoff} initialTotal={tool.total} initialLegs={tool.legs} onSend={sendAsk} onClose={closeTool} />\n        ) : null}\n      </div>\n      {monitor && discovery && monitor.activeTab === 'today' && <TodayPanel discovery={discovery} ui={ui} monitor={monitor} />}\n      {monitor && monitor.activeTab === 'following' && <MatchesPanel monitor={monitor} ui={ui} slip={slip} onAsk={paused ? undefined : handleAsk} />}\n      {monitor && monitor.activeTab === 'odds' && <OddsPanel monitor={monitor} ui={ui} slip={slip} />}\n      {monitor && monitor.activeTab === 'fixtures' && (\n        <Fixtures fixtures={clubFixturesResult?.fixtures ?? []} loading={clubFixturesResult?.loading ?? false} ui={ui} />\n      )}\n      {monitor && monitor.activeTab === 'standings' && (\n        <Standings standings={clubStandingsResult?.data ?? null} loading={clubStandingsResult?.loading ?? false} ui={ui} />\n      )}\n      {monitor && monitor.activeTab === 'squad' && (\n        <>\n          {/* Squad stays mounted under the detail so its list keeps its scroll position on Back. */}\n          <div\n            ref={squadLayerRef}\n            style={selectedPlayerId === null ? SQUAD_LAYER_STYLE : HIDDEN_LAYER_STYLE}\n            aria-hidden={selectedPlayerId !== null ? true : undefined}\n          >\n            <Squad\n              squad={clubSquadResult?.data ?? null} loading={clubSquadResult?.loading ?? false} ui={ui}\n              view={squadView} onToggleView={() => setSquadView((v) => (v === 'roster' ? 'stats' : 'roster'))}\n              stats={clubSquadStatsResult?.data ?? null} statsLoading={clubSquadStatsResult?.loading ?? false}\n              seasonName={clubSquadStatsResult?.seasonName ?? null} competitionName={clubSquadStatsResult?.competitionName ?? null} matchesPlayed={clubSquadStatsResult?.matchesPlayed ?? null}\n              onSelectPlayer={selectPlayer}\n            />\n          </div>\n          {selectedPlayerId !== null && (\n            <PlayerDetail detail={clubPlayerDetailResult?.data ?? null} loading={clubPlayerDetailResult?.loading ?? false} ui={ui} seasonName={clubSquadStatsResult?.seasonName ?? null} onClose={closePlayer} />\n          )}\n        </>\n      )}\n      {monitor && monitor.activeTab === 'games' && gamesResult && (\n        <GamesPanel\n          loggedIn={!!loggedIn}\n          games={gamesResult.games}\n          ui={ui}\n          conversation={conversation}\n          leaderboard={leaderboardResult?.data ?? null}\n          leaderboardLoading={leaderboardResult?.loading ?? false}\n          refreshHub={() => { gamesResult.refresh(); leaderboardResult?.refresh() }}\n        />\n      )}\n      {/* The composer is a chat affordance; hide it on the Games tab where it only confuses. */}\n      {(!monitor || monitor.activeTab !== 'games') && (\n        <>\n          <div ref={limitRef} className=\"ss-w-limit\" role=\"status\" tabIndex={-1}>{state.limit ? limitText(state.limit, ui) : null}</div>\n          {paused ? null : (\n            <ChatInput\n              ref={inputRef} placeholder={ui.placeholder} streaming={state.isStreaming} onSend={handleSend} onStop={stop}\n              stopLabel={ui.stopResponse} sendLabel={ui.sendMessage} disabled={!!tool} onType={fold}\n            />\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { CloseIcon, KebabIcon } from './Icons'\nimport { BrandMark } from './BrandMark'\n\nexport function ChatHeader({\n  onClose,\n  closeLabel = 'Close chat',\n  logoUrl,\n  headerTitle,\n  onNewConversation,\n  canReset,\n  newConversationLabel = 'New conversation',\n  moreOptionsLabel = 'More options',\n}: {\n  onClose: () => void\n  closeLabel?: string\n  logoUrl?: string\n  headerTitle?: string\n  onNewConversation?: () => void\n  canReset?: boolean\n  newConversationLabel?: string\n  moreOptionsLabel?: string\n}): JSX.Element {\n  const [menuOpen, setMenuOpen] = useState(false)\n  const wrapRef = useRef<HTMLDivElement>(null)\n  const kebabRef = useRef<HTMLButtonElement>(null)\n  const firstItemRef = useRef<HTMLButtonElement>(null)\n\n  // Secondary actions (currently just \"New conversation\") live behind the kebab; Close stays a\n  // one-tap control since it is the most frequent action.\n  const hasMenu = !!(canReset && onNewConversation)\n\n  useEffect(() => {\n    if (menuOpen) firstItemRef.current?.focus()\n  }, [menuOpen])\n\n  useEffect(() => {\n    if (!menuOpen) return\n    const onPointer = (e: MouseEvent) => {\n      if (!wrapRef.current?.contains(e.target as Node)) setMenuOpen(false)\n    }\n    const onKey = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        setMenuOpen(false)\n        kebabRef.current?.focus()\n      }\n    }\n    document.addEventListener('mousedown', onPointer)\n    document.addEventListener('keydown', onKey)\n    return () => {\n      document.removeEventListener('mousedown', onPointer)\n      document.removeEventListener('keydown', onKey)\n    }\n  }, [menuOpen])\n\n  const runNewConversation = (): void => {\n    setMenuOpen(false)\n    onNewConversation?.()\n  }\n\n  return (\n    <header className=\"ss-w-header\">\n      <BrandMark logoUrl={logoUrl} className=\"ss-w-header-mark\" />\n      <span className=\"ss-w-header-title\">{headerTitle ?? 'SensibleStats'}</span>\n      {hasMenu ? (\n        <div className=\"ss-w-menu-wrap\" ref={wrapRef}>\n          <button\n            type=\"button\"\n            className=\"ss-w-kebab\"\n            ref={kebabRef}\n            aria-haspopup=\"menu\"\n            aria-expanded={menuOpen}\n            aria-label={moreOptionsLabel}\n            onClick={() => setMenuOpen((open) => !open)}\n          >\n            <KebabIcon />\n          </button>\n          {menuOpen ? (\n            <div className=\"ss-w-menu\" role=\"menu\" aria-label={moreOptionsLabel}>\n              <button\n                type=\"button\"\n                className=\"ss-w-menu-item\"\n                role=\"menuitem\"\n                ref={firstItemRef}\n                onClick={runNewConversation}\n              >\n                <span>{newConversationLabel}</span>\n              </button>\n            </div>\n          ) : null}\n        </div>\n      ) : null}\n      <button type=\"button\" className=\"ss-w-close\" aria-label={closeLabel} onClick={onClose}>\n        <CloseIcon />\n      </button>\n    </header>\n  )\n}\n","import { useEffect, useRef } from 'react'\nimport type { ChatController } from '../useChatStream'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { DashboardTapHandler } from '../dashboardTap'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { tileDisplayText } from '../presets'\nimport { ChatMessage } from './ChatMessage'\nimport { IntentChips } from './IntentChips'\nimport { ActionButtons } from './ActionButtons'\nimport { isPinnedToBottom } from '../scroll'\nimport type { Message } from '../reducer'\nimport { isPaused } from '../limit'\n\n// The element to pin to the top when a new turn begins: the user's question if\n// this turn has one (so the reply reads from just below it), otherwise the\n// assistant turn itself (an auto-greeting or greeting dashboard has no user\n// bubble, and we still want its top in view rather than its bottom).\nfunction turnAnchor(messages: Message[]): { turnId: string; anchorId: string } | null {\n  const last = messages[messages.length - 1]\n  if (!last || last.role !== 'assistant') return null\n  const prev = messages[messages.length - 2]\n  return { turnId: last.id, anchorId: prev && prev.role === 'user' ? prev.id : last.id }\n}\n\nexport function MessageList({ controller, ui, slip, onDashboardTap, monitor }: {\n  controller: ChatController\n  ui: UiConfig\n  slip: SlipHandlerProps\n  onDashboardTap?: DashboardTapHandler\n  monitor?: LiveMonitorController\n}): JSX.Element {\n  const { state, send } = controller\n  const listRef = useRef<HTMLDivElement>(null)\n  const endRef = useRef<HTMLDivElement>(null)\n  // Follow the stream only while the user is at the bottom. pinnedRef is updated\n  // on real scroll events (content growth fires none), so a user who scrolls up\n  // stays put when late content — suggested actions, status — arrives.\n  const pinnedRef = useRef(true)\n  // The turn id we have already anchored to the top. On a new turn we pin its\n  // start to the top so a long reply reads from its beginning instead of the\n  // viewport jumping to the bottom of the answer.\n  const anchoredTurnRef = useRef<string | null>(null)\n  useEffect(() => {\n    const anchor = turnAnchor(state.messages)\n    const list = listRef.current\n    if (anchor && anchor.turnId !== anchoredTurnRef.current) {\n      anchoredTurnRef.current = anchor.turnId\n      // Reserve a viewport of space below the new turn before scrolling, so the\n      // anchor can actually reach the top even while the reply is still empty\n      // (without it the scroll lands at the bottom, onScroll re-pins to bottom,\n      // and the streaming reply then follows the bottom down). The spacer is the\n      // endRef element; it collapses again once the turn stops streaming.\n      //\n      // Only reserve while the turn is actively streaming. A turn first anchored\n      // when it is ALREADY complete -- panel opened after the greeting finished,\n      // or a restored/cross-tab-synced conversation -- has its full height, so it\n      // needs no spacer; reserving one here would never be collapsed (this branch\n      // returns, and the collapse below only runs on a later !isStreaming pass\n      // that never comes), leaving a viewport of dead scroll space below content.\n      if (endRef.current && list) endRef.current.style.height = state.isStreaming ? `${list.clientHeight}px` : ''\n      // Top-anchored, so the list is no longer pinned to the bottom; streaming\n      // updates below won't yank it back down for the rest of this turn.\n      pinnedRef.current = false\n      list?.querySelector(`[data-msg-id=\"${anchor.anchorId}\"]`)?.scrollIntoView({ block: 'start' })\n      return\n    }\n    // Turn finished: drop the reserved space (content above is unaffected, so the\n    // anchored message keeps its position).\n    if (!state.isStreaming && endRef.current) endRef.current.style.height = ''\n    if (pinnedRef.current) endRef.current?.scrollIntoView({ block: 'end' })\n  }, [state.messages, state.status, state.isStreaming])\n\n  // Chips are always emitted by the server; the widget prefers the dashboard and\n  // hides the chips client-side once a greeting dashboard, a club fan dashboard, or a\n  // user message exists.\n  const hasUserMessage = state.messages.some((m) => m.role === 'user')\n  const hasDashboard = state.messages.some((m) => m.role === 'assistant' && (m.greetingDashboard || m.clubFanDashboard))\n  return (\n    <div\n      className=\"ss-w-list\"\n      aria-live=\"polite\"\n      ref={listRef}\n      onScroll={() => { if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current) }}\n    >\n      {state.messages.map((m) => (\n        <ChatMessage\n          key={m.id}\n          message={m}\n          disabled={state.isStreaming || isPaused(state.limit)}\n          onAct={(a) => send(a.message, { actionId: a.actionId, actionRef: a.actionRef, displayText: a.label })}\n          onTap={(tile, index) => {\n            const displayText = tileDisplayText(tile)\n            send(tile.actionValue, tile.actionRef ? { actionRef: tile.actionRef, displayText } : { displayText })\n            // Only fires from within the dashboard this message itself rendered (ChatMessage\n            // renders GreetingDashboard only when message.greetingDashboard is set), so the\n            // dashboard -- and its layout -- is guaranteed present here.\n            if (m.role === 'assistant' && m.greetingDashboard) onDashboardTap?.(tile, index, m.greetingDashboard.layout)\n          }}\n          ui={ui}\n          slip={slip}\n          monitor={monitor}\n        />\n      ))}\n      {state.isStreaming && state.actionsLoading ? <ActionButtons actions={[]} loading onAct={() => {}} /> : null}\n      {state.status ? <div className=\"ss-w-status\">{state.status}</div> : null}\n      {state.error ? (\n        <div className=\"ss-w-error\" role=\"alert\">\n          <span>{'message' in state.error ? state.error.message : ui.somethingWentWrong}</span>\n          <button type=\"button\" className=\"ss-w-retry\" onClick={() => controller.retry()}>{ui.retry}</button>\n        </div>\n      ) : null}\n      {!hasUserMessage && !hasDashboard && !isPaused(state.limit) ? <IntentChips chips={state.starters} onPick={(t) => send(t)} /> : null}\n      <div ref={endRef} className=\"ss-w-turn-spacer\" aria-hidden=\"true\" />\n    </div>\n  )\n}\n","import ReactMarkdown, { type Components } from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nconst components: Components = {\n  a: ({ children, href }) => (\n    <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"ss-w-md-link\">{children}</a>\n  ),\n  table: ({ children }) => (\n    <div className=\"ss-w-table-wrap\"><table className=\"ss-w-md-table\">{children}</table></div>\n  ),\n  ul: ({ children }) => <ul className=\"ss-w-md-ul\">{children}</ul>,\n  ol: ({ children }) => <ol className=\"ss-w-md-ol\">{children}</ol>,\n  code: ({ children }) => <code className=\"ss-w-md-code\">{children}</code>,\n}\n\nexport function Markdown({ text }: { text: string }): JSX.Element {\n  return (\n    <div className=\"ss-w-md\">\n      <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>{text}</ReactMarkdown>\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { CardVM, CardScope, StatCell } from '../model'\n\nconst MAX_VISIBLE = 3\nconst RECORD_RE = /^(\\d+)-(\\d+)-(\\d+)$/\n\nfunction initials(name: string): string {\n  return name.split(/\\s+/).slice(0, 2).map((w) => w[0] ?? '').join('').toUpperCase()\n}\n\n// \"2026/2027\" -> \"26/27\", \"2026\" -> \"26\"; leaves any non-4-digit token untouched.\nfunction shortSeason(season: string): string {\n  return season.replace(/\\d{4}/g, (year) => year.slice(2))\n}\n\nfunction Crest({ image, label }: { image: string; label?: string }): JSX.Element {\n  return (\n    <span\n      className=\"ss-w-ecard-crest\"\n      style={{ backgroundImage: `url(${image})` }}\n      {...(label ? { role: 'img', title: label, 'aria-label': label } : { 'aria-hidden': 'true' as const })}\n    />\n  )\n}\n\n// Proportional win/draw/loss bar. Rendered for any stat value shaped \"w-d-l\".\nfunction FormBar({ w, d, l }: { w: number; d: number; l: number }): JSX.Element | null {\n  if (w + d + l === 0) return null\n  return (\n    <span className=\"ss-w-form\" aria-hidden=\"true\">\n      {w > 0 ? <span className=\"ss-w-form-w\" style={{ flexGrow: w }} /> : null}\n      {d > 0 ? <span className=\"ss-w-form-d\" style={{ flexGrow: d }} /> : null}\n      {l > 0 ? <span className=\"ss-w-form-l\" style={{ flexGrow: l }} /> : null}\n    </span>\n  )\n}\n\nfunction StatCellView({ s }: { s: StatCell }): JSX.Element {\n  const m = RECORD_RE.exec(s.value)\n  if (m) {\n    return (\n      <div className=\"ss-w-ecard-cell\">\n        <span className=\"ss-w-ecard-cval\"><FormBar w={Number(m[1])} d={Number(m[2])} l={Number(m[3])} /></span>\n        <span className=\"ss-w-ecard-clabel\">{s.value}</span>\n      </div>\n    )\n  }\n  return (\n    <div className=\"ss-w-ecard-cell\">\n      <span className=\"ss-w-ecard-cval\">{s.value}</span>\n      <span className=\"ss-w-ecard-clabel\">{s.label}</span>\n    </div>\n  )\n}\n\nfunction StatStrip({ stats }: { stats: StatCell[] }): JSX.Element | null {\n  if (stats.length === 0) return null\n  const cols = Math.min(stats.length, 4)\n  return (\n    <div className=\"ss-w-ecard-strip\" style={{ gridTemplateColumns: `repeat(${cols}, 1fr)` }}>\n      {stats.map((s) => <StatCellView key={s.label + s.value} s={s} />)}\n    </div>\n  )\n}\n\nfunction CardHeader({ c, showScopeCrest }: { c: CardVM; showScopeCrest: boolean }): JSX.Element {\n  const onlyScope = c.scopes.length === 1 ? c.scopes[0]! : null\n  return (\n    <div className=\"ss-w-ecard-hd\">\n      <span\n        className={c.kind === 'team' ? 'ss-w-thumb ss-w-team' : 'ss-w-thumb'}\n        style={c.image ? { backgroundImage: `url(${c.image})` } : undefined}\n      >\n        {c.image ? '' : initials(c.name)}\n      </span>\n      <span className=\"ss-w-ecard-idtext\">\n        <span className=\"ss-w-nm\">{c.name}</span>\n        {c.sub ? <span className=\"ss-w-sub\">{c.sub}</span> : null}\n      </span>\n      <span className=\"ss-w-ecard-meta\">\n        {showScopeCrest && onlyScope?.image ? <Crest image={onlyScope.image} label={onlyScope.label} /> : null}\n        {c.season ? <span className=\"ss-w-ecard-season\">{shortSeason(c.season)}</span> : null}\n      </span>\n    </div>\n  )\n}\n\nfunction ScopeTabs({ scopes, active, onSelect }: { scopes: CardScope[]; active: number; onSelect: (i: number) => void }): JSX.Element {\n  return (\n    <div className=\"ss-w-ecard-scopes\" role=\"tablist\">\n      {scopes.map((s, i) => (\n        <button\n          key={String(s.competitionId ?? 'all')}\n          type=\"button\"\n          role=\"tab\"\n          className=\"ss-w-ecard-scope\"\n          aria-selected={i === active}\n          aria-label={s.label}\n          title={s.label}\n          onClick={() => onSelect(i)}\n        >\n          {s.image ? <Crest image={s.image} /> : s.label}\n        </button>\n      ))}\n    </div>\n  )\n}\n\nfunction EntityCardItem({ c }: { c: CardVM }): JSX.Element {\n  const [active, setActive] = useState(0)\n  const hasBody = c.scopes.length > 0\n  if (!hasBody) {\n    return (\n      <div className=\"ss-w-ecard ss-w-ecard-bare\" data-kind={c.kind}>\n        <CardHeader c={c} showScopeCrest={false} />\n      </div>\n    )\n  }\n  const multi = c.scopes.length > 1\n  const scope = c.scopes[multi ? (c.scopes[active] ? active : 0) : 0]!\n  return (\n    <div className=\"ss-w-ecard\" data-kind={c.kind}>\n      <CardHeader c={c} showScopeCrest={!multi} />\n      {multi ? <ScopeTabs scopes={c.scopes} active={active} onSelect={setActive} /> : null}\n      <StatStrip stats={scope.stats} />\n    </div>\n  )\n}\n\nexport function EntityCardList({ cards, disabled, showLessLabel = 'Show less', showMoreLabel = (n: number) => `Show ${n} more` }: { cards: CardVM[]; disabled?: boolean; showLessLabel?: string; showMoreLabel?: (n: number) => string }): JSX.Element | null {\n  const [expanded, setExpanded] = useState(false)\n  if (cards.length === 0) return null\n  const visible = expanded ? cards : cards.slice(0, MAX_VISIBLE)\n  const overflow = cards.length - MAX_VISIBLE\n  return (\n    <div className=\"ss-w-cards\">\n      {visible.map((c) => <EntityCardItem key={c.id} c={c} />)}\n      {overflow > 0 ? (\n        <button type=\"button\" className=\"ss-w-cards-more\" disabled={disabled} onClick={() => setExpanded((v) => !v)}>\n          {expanded ? showLessLabel : showMoreLabel(overflow)}\n        </button>\n      ) : null}\n    </div>\n  )\n}\n","import { useCallback, useState } from 'react'\nimport type { SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { toSlipSelection, type InsightVM } from '../model'\nimport { isTerminal, resultToToast, type SlipHandlerProps, type SlipToast } from '../slip'\nimport { useSlipAdd } from '../slipAdd'\nimport { useSlipState } from '../slipStateContext'\nimport { Toast } from './Toast'\n\nexport function SlipButton(\n  { selection, shownOdds, marketDeveloperName, selectionLabel, line, slip, ui, price, ariaLabel }:\n  {\n    selection: SlipSelection | null; shownOdds: string; marketDeveloperName?: string\n    /** The raw selection label and line, sent apart (never the joined display string). */\n    selectionLabel?: string; line?: string\n    slip: SlipHandlerProps; ui?: UiConfig\n    /** Draws the price itself as the button, as a compact list row does. */\n    price?: { label?: string; ariaLabel: string }\n    /** Names the plain button apart from its siblings; the slip state is appended. */\n    ariaLabel?: string\n  },\n): JSX.Element | null {\n  const [pending, setPending] = useState(false)\n  const [settledLocal, setSettledLocal] = useState(false)\n  const [toast, setToast] = useState<SlipToast | null>(null)\n  const dismiss = useCallback(() => setToast(null), [])\n  const add = useSlipAdd(slip, ui)\n  const slipState = useSlipState()\n\n  const handler = slip.onAddToSlip\n  if (!ui || !handler || !selection) return null\n  // Inside a widget the mark belongs to the odd and lives at the root, where a host call can\n  // clear it. Rendered on its own, with no provider, the button keeps its own state.\n  const settled = slipState ? !!slipState.settled[selection.matchOddsId] : settledLocal\n\n  const onClick = async (): Promise<void> => {\n    setPending(true)\n    try {\n      const outcome = await add(selection, { marketDeveloperName, selectionLabel, line })\n      if (outcome.kind === 'failed') {\n        setToast({ kind: 'error', text: ui.slipFailed })\n        return\n      }\n      setToast(resultToToast(outcome.result, shownOdds || selection.oddsDecimal.toFixed(2), ui))\n      if (!slipState) setSettledLocal(isTerminal(outcome.result))\n    } finally {\n      setPending(false)\n    }\n  }\n\n  return (\n    <div className=\"ss-w-slip\">\n      {price ? (\n        <button\n          type=\"button\"\n          className=\"ss-w-slip-btn ss-w-slip-btn--price\"\n          data-settled={settled || undefined}\n          aria-label={`${price.ariaLabel}, ${settled ? ui.inSlip : ui.addToSlip}`}\n          disabled={pending || settled}\n          onClick={onClick}\n        >\n          {settled ? <span className=\"ss-w-mol-tick\" aria-hidden=\"true\">✓</span> : null}\n          {price.label ? <span className=\"ss-w-mol-lab\">{price.label}</span> : null}\n          <span>{shownOdds}</span>\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          className=\"ss-w-slip-btn\"\n          aria-label={ariaLabel ? `${ariaLabel}, ${settled ? ui.inSlip : ui.addToSlip}` : undefined}\n          disabled={pending || settled}\n          onClick={onClick}\n        >\n          {settled ? ui.inSlip : ui.addToSlip}\n        </button>\n      )}\n      <Toast toast={toast} onDismiss={dismiss} />\n    </div>\n  )\n}\n\nexport function AddToSlipButton(\n  { it, slip, ui }: { it: InsightVM; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n  const selection = it.addToSlipEnabled ? toSlipSelection(it, slip.conversationId) : null\n  return (\n    <SlipButton\n      selection={selection}\n      shownOdds={it.odds ?? ''}\n      marketDeveloperName={it.marketDeveloperName}\n      selectionLabel={it.selectionLabel}\n      line={it.line}\n      slip={slip}\n      ui={ui}\n    />\n  )\n}\n","import { useCallback } from 'react'\nimport { isAddToSlipResult, type AddToSlipResult, type SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from './config'\nimport { ADD_TO_SLIP_TIMEOUT_MS, isTerminal, slipOutcome, slipPickFields, wasAdded, type SlipHandlerProps } from './slip'\nimport { useEventLog } from './eventLogContext'\nimport { useSlipState } from './slipStateContext'\n\nexport interface SlipAddMeta {\n  marketDeveloperName?: string\n  /** The raw selection label and line, sent apart (never the joined display string). */\n  selectionLabel?: string\n  line?: string\n}\n\n/** `failed`: the handler threw, timed out, or answered outside the contract. */\nexport type SlipAddOutcome =\n  | { kind: 'answered'; result: AddToSlipResult | undefined }\n  | { kind: 'failed' }\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\n// The one path every add takes, from a leg's own button or from a combo's \"Add all\": events,\n// timeout, contract guard, the root's in-slip mark and the slip ledger.\nexport function useSlipAdd(\n  slip: SlipHandlerProps, ui: UiConfig | undefined,\n): (selection: SlipSelection, meta: SlipAddMeta) => Promise<SlipAddOutcome> {\n  const log = useEventLog()\n  const slipState = useSlipState()\n  const handler = slip.onAddToSlip\n  const rawLabels = !!ui?.rawBettingLabels\n  return useCallback(async (selection, { marketDeveloperName, selectionLabel, line }) => {\n    if (!handler) return { kind: 'failed' }\n    const pick = slipPickFields(selection, rawLabels ? selectionLabel : undefined, line)\n    // A market/selection with no marketDeveloperName has no entity to report under entityType\n    // 'market' -- skip the emit rather than log entityId: undefined (mirrors the PinToggle guard).\n    if (marketDeveloperName !== undefined) {\n      log?.log({ name: 'slip_click', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, ...pick })\n    }\n    try {\n      const raw = await withTimeout(Promise.resolve(handler(selection)))\n      // Only a genuine void return means \"assume success\". A non-null value the\n      // guard rejects is a broken contract (e.g. an operator forwarding their own\n      // backend's reason string, which `any` lets past the compiler) — treating it\n      // as void would report a refused bet to the user as added.\n      if (raw != null && !isAddToSlipResult(raw)) throw new Error('malformed add-to-slip result')\n      const result = raw ?? undefined\n      if (marketDeveloperName !== undefined) {\n        log?.log({\n          name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName,\n          outcome: slipOutcome(result), ...pick,\n        })\n      }\n      if (slipState) {\n        if (isTerminal(result)) slipState.settle(selection.matchOddsId)\n        if (wasAdded(result) && marketDeveloperName !== undefined) {\n          slipState.recordAdd({ selection, market: marketDeveloperName, pick })\n        }\n      }\n      return { kind: 'answered', result }\n    } catch {\n      if (marketDeveloperName !== undefined) {\n        log?.log({ name: 'slip_result', entityType: 'market', marketDeveloperName, entityId: marketDeveloperName, outcome: 'timeout', ...pick })\n      }\n      return { kind: 'failed' }\n    }\n  }, [handler, log, slipState, rawLabels])\n}\n","import { createContext, useContext } from 'react'\nimport type { SlipSelection } from '@sensiblestats/widget-sdk'\nimport type { SlipPickFields } from './slip'\n\nexport interface SlipAdd {\n  selection: SlipSelection\n  /** market developer name */\n  market: string\n  pick: SlipPickFields\n}\n\nexport interface SlipState {\n  /** Odds the widget added in this mount. Drives the Odds tab's persistent in-slip badge. */\n  added: Readonly<Record<number, true>>\n  /** Odds whose button got a terminal answer in this mount. Drives the button's \"In slip\" label. */\n  settled: Readonly<Record<number, true>>\n  settle(matchOddsId: number): void\n  /** Remembers an add the widget made, so a later host call for that odd can be reported. */\n  recordAdd(add: SlipAdd): void\n}\n\nexport const SlipStateContext = createContext<SlipState | null>(null)\n\nexport function useSlipState(): SlipState | null {\n  return useContext(SlipStateContext)\n}\n","import { useEffect } from 'react'\nimport type { SlipToast } from '../slip'\n\nconst DISMISS_MS = 4000\n\nexport function Toast({ toast, onDismiss }: { toast: SlipToast | null; onDismiss: () => void }): JSX.Element | null {\n  useEffect(() => {\n    if (!toast) return\n    const timer = setTimeout(onDismiss, DISMISS_MS)\n    return () => clearTimeout(timer)\n  }, [toast, onDismiss])\n\n  if (!toast) return null\n  return (\n    <div className={`ss-w-toast ss-w-toast-${toast.kind}`} role=\"status\" aria-live=\"polite\">\n      {toast.text}\n    </div>\n  )\n}\n","import type { UiConfig } from '../config'\n\n// One component for both card types. The market-odds row and the insight card must not drift into\n// two visual languages for the same signal, so there is exactly one place this markup exists.\nexport function OddsMovementBadge({\n  previous,\n  current,\n  direction,\n  ui,\n}: {\n  previous?: string\n  current: string\n  direction?: 'shortened' | 'drifted'\n  ui?: UiConfig\n}): JSX.Element | null {\n  if (previous === undefined || direction === undefined) return null\n  const directionWord =\n    direction === 'shortened' ? (ui?.oddsShortened ?? 'shortened') : (ui?.oddsDrifted ?? 'drifted')\n  const label =\n    ui?.oddsMoved?.(previous, current, directionWord) ?? `was ${previous}, now ${current}, ${directionWord}`\n  return (\n    // Strikethrough is invisible to screen readers, so the whole was/now/direction sentence rides\n    // on one aria-label and the visual glyphs are hidden from the accessibility tree.\n    <span className=\"ss-w-move\" role=\"img\" aria-label={label}>\n      <span className=\"ss-w-move-prev\" aria-hidden=\"true\">{previous}</span>\n      <span className=\"ss-w-move-arrow\" aria-hidden=\"true\">{direction === 'shortened' ? '▼' : '▲'}</span>\n    </span>\n  )\n}\n","import { useState } from 'react'\n\nexport function initials(name?: string): string {\n  return (name ?? '').trim().slice(0, 1).toUpperCase() || '?'\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a monogram (first initial) -- the design\n// wants the monogram whenever the crest is missing OR fails to load, which a background-image span\n// can't detect. onError flips to the monogram; the fixed sizing keeps the row height stable either way.\nexport function Crest({ url, name, kind }: { url?: string; name?: string; kind: 'team' | 'comp' }): JSX.Element {\n  const cls = kind === 'comp' ? 'ss-w-bi-comp-logo' : 'ss-w-bi-crest'\n  const [failed, setFailed] = useState(false)\n  if (url && !failed) {\n    return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n  }\n  return <span className={`${cls} ss-w-bi-crest-mono`} aria-hidden=\"true\">{initials(name)}</span>\n}\n","import { useCallback, useState, type MouseEvent } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\n// One glyph per pinIcon choice, drawn from a single silhouette path so the\n// pinned state can toggle outline (off) → filled (on) without a second asset.\n// The pin keeps its original thumbtack (scaled into a 24 box) so the default\n// look is unchanged in shape; star and bookmark are standard marks.\nconst PIN_GLYPHS: Record<'pin' | 'star' | 'bookmark', { viewBox: string; d: string; strokeWidth: number; transform?: string }> = {\n  pin: { viewBox: '0 0 24 24', strokeWidth: 1.4, transform: 'scale(1.5)', d: 'M9.5 1.5 14.5 6.5 13 8l-.5-.5-3 3 .3 2.2-1.4 1.4L5.6 11.3l-3.3 3.3-1-1 3.3-3.3L1.9 7.5l1.4-1.4 2.2.3 3-3L8 2.9z' },\n  star: { viewBox: '0 0 24 24', strokeWidth: 2, d: 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z' },\n  bookmark: { viewBox: '0 0 24 24', strokeWidth: 2, d: 'M7 3h10a1.5 1.5 0 0 1 1.5 1.5V21l-6.5-3.6L5.5 21V4.5A1.5 1.5 0 0 1 7 3z' },\n}\n\nexport function PinToggle({ pin, monitor, ui, market }: {\n  pin: Omit<PinRef, 'key'>\n  monitor: LiveMonitorController | undefined\n  ui: UiConfig\n  /** The market the card showed: a tap that pins opens it in Following. */\n  market?: string\n}): JSX.Element | null {\n  const [toast, setToast] = useState<SlipToast | null>(null)\n  const dismiss = useCallback(() => setToast(null), [])\n  const log = useEventLog()\n\n  if (!monitor || !monitor.enabled) return null\n\n  const key = pinKey(pin)\n  const pinned = monitor.isPinned(key)\n  // Match pins and odds pins are separate behaviors (2026-09-06 ruling): each toggle tracks\n  // exactly its own pin, and the labels name which one this is.\n  const labels = pin.kind === 'match'\n    ? { pin: ui.matchPinLabel, unpin: ui.matchUnpinLabel }\n    : { pin: ui.pinLabel, unpin: ui.unpinLabel }\n\n  const onClick = (e: MouseEvent<HTMLButtonElement>): void => {\n    e.stopPropagation()\n    if (pin.kind === 'match' && !monitor.isPinned(key)) {\n      if (monitor.pinMatch({ matchId: pin.matchId, marketDeveloperName: market }) === 'added') {\n        log?.log({ name: 'pin_add', entityType: 'match', entityId: String(pin.matchId), marketDeveloperName: pin.marketDeveloperName })\n      }\n      return\n    }\n    const result = monitor.togglePin({ ...pin, key })\n    // A market/selection pin with no marketDeveloperName has no entity to report under\n    // entityType 'market' -- skip the emit rather than fall back to the match id, which would\n    // mislabel a match under a market entityType.\n    if ((result === 'added' || result === 'removed') && (pin.kind === 'match' || pin.marketDeveloperName !== undefined)) {\n      log?.log({\n        name: result === 'added' ? 'pin_add' : 'pin_remove',\n        entityType: pin.kind === 'match' ? 'match' : 'market',\n        entityId: pin.kind === 'match' ? String(pin.matchId) : pin.marketDeveloperName,\n        marketDeveloperName: pin.marketDeveloperName,\n      })\n    } else if (result === 'market_limit') {\n      setToast({ kind: 'error', text: ui.marketLimitToast })\n    }\n  }\n\n  const glyph = PIN_GLYPHS[ui.pinIcon]\n  return (\n    <div className=\"ss-w-pin-wrap\">\n      <button\n        type=\"button\"\n        className=\"ss-w-pin\"\n        data-on={pinned || undefined}\n        data-icon={ui.pinIcon}\n        aria-pressed={pinned}\n        aria-label={pinned ? labels.unpin : labels.pin}\n        onClick={onClick}\n      >\n        <svg viewBox={glyph.viewBox} aria-hidden=\"true\">\n          <path\n            transform={glyph.transform}\n            d={glyph.d}\n            fill={pinned ? 'currentColor' : 'none'}\n            stroke={pinned ? 'none' : 'currentColor'}\n            strokeWidth={glyph.strokeWidth}\n            strokeLinejoin=\"round\"\n            strokeLinecap=\"round\"\n          />\n        </svg>\n      </button>\n      <Toast toast={toast} onDismiss={dismiss} />\n    </div>\n  )\n}\n","import { useCallback, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { joinSelection } from '../model'\nimport { pinKey } from '../pinStore'\nimport type { SlipToast } from '../slip'\nimport { useEventLog } from '../eventLogContext'\nimport { Toast } from './Toast'\n\ntype HistoryPin = Omit<PinRef, 'key' | 'kind' | 'withHistory'>\n\n// D27: in place of an odds pin, a price that moved opens its history in the Odds tab. The tap adds\n// the selection with its history, or finds it already there, and switches tab. It never removes\n// an entry: unpinning lives in the Odds tab.\nexport function PriceHistoryButton({ selection, monitor, ui }: {\n  selection: HistoryPin\n  monitor: LiveMonitorController | undefined\n  ui: UiConfig\n}): JSX.Element | null {\n  const [toast, setToast] = useState<SlipToast | null>(null)\n  const dismiss = useCallback(() => setToast(null), [])\n  const log = useEventLog()\n\n  if (!monitor || !monitor.enabled) return null\n  // The name carries the selection: two moved rows on one card must not read as two identical buttons.\n  const name = joinSelection(selection.selectionLabel ?? undefined, selection.line ?? undefined)\n  const label = name ? `${ui.priceHistoryLabel}, ${name}` : ui.priceHistoryLabel\n\n  const onClick = (): void => {\n    const pin = { ...selection, kind: 'selection' as const, withHistory: true }\n    const key = pinKey(pin)\n    if (!monitor.isPinned(key)) {\n      const result = monitor.togglePin({ ...pin, key })\n      if (result === 'market_limit') {\n        setToast({ kind: 'error', text: ui.marketLimitToast })\n        return\n      }\n      // Logged as the market pin it is, so the market signal behind \"Your market\" keeps its input.\n      if (result === 'added' && pin.marketDeveloperName !== undefined) {\n        log?.log({ name: 'pin_add', entityType: 'market', entityId: pin.marketDeveloperName, marketDeveloperName: pin.marketDeveloperName })\n      }\n    }\n    monitor.setActiveTab('odds')\n  }\n\n  return (\n    <div className=\"ss-w-pin-wrap\">\n      <button type=\"button\" className=\"ss-w-hist\" aria-label={label} title={label} onClick={onClick}>\n        <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n          <path d=\"M2 13.5h12M3 10.5l3.2-3.4 2.6 2.2L13 4.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n        </svg>\n      </button>\n      <Toast toast={toast} onDismiss={dismiss} />\n    </div>\n  )\n}\n","import type { InsightVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { AddToSlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\n\n// The reason-to-bet fact sentence, shown in full: the card carries no supporting stat rows and\n// nothing to expand.\nfunction ReasonStrip({ it }: { it: InsightVM }): JSX.Element | null {\n  if (!it.text) return null\n  return (\n    <div className=\"ss-w-bi-reason\">\n      <span className=\"ss-w-bi-chart\" aria-hidden=\"true\" />\n      <p className=\"ss-w-bi-text\">{it.text}</p>\n    </div>\n  )\n}\n\n// Renders the fixture as the card's hero: the named team pair when present, else the prose\n// fixture, else the competition (the fallback that becomes the header hero when there is no\n// fixture at all). On a fixture card this fills its own line; the competition rides the meta line\n// above it (u350 two-tier).\nfunction CardFixture({ it }: { it: InsightVM }): JSX.Element | null {\n  if (it.homeTeamName && it.awayTeamName) {\n    return (\n      <>\n        <Crest kind=\"team\" url={it.homeCrest} name={it.homeTeamName} />\n        <span className=\"ss-w-bi-team\">{it.homeTeamName}</span>\n        <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n        <span className=\"ss-w-bi-team\">{it.awayTeamName}</span>\n        <Crest kind=\"team\" url={it.awayCrest} name={it.awayTeamName} />\n      </>\n    )\n  }\n  if (it.fixture) return <span className=\"ss-w-bi-fixture-txt\">{it.fixture}</span>\n  if (it.competition) {\n    return (\n      <>\n        <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n        <span className=\"ss-w-bi-comp\">{it.competition}</span>\n      </>\n    )\n  }\n  return null\n}\n\nfunction InsightCard(\n  { it, ui, slip, monitor }: { it: InsightVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element {\n  const live = it.isLive || it.phase === 'live'\n  // Prefer the server-rendered chip (operator timezone + language); fall back to browser-zone\n  // formatting of the raw instant for older servers that don't send a label.\n  const kickoffFallback = it.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(it.kickoffUtc) : undefined\n  const kickoff = it.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n  const hasNamedTeams = !!it.homeTeamName && !!it.awayTeamName\n  // A fixture (team pair or prose string) is the card's hero and gets its own full-width line so\n  // long club names stop truncating; the competition, kickoff and match pin sit on a quieter meta\n  // line above it. Only when there is no fixture does the competition itself become the hero on a\n  // single header line (u350 two-tier).\n  const leftIsFixture = hasNamedTeams || !!it.fixture\n  const showPin = !!monitor && it.pinEnabled\n  const showHeader = leftIsFixture || !!it.competition || live || !!kickoff || showPin\n  // live badge + kickoff + match pin: shared by the fixture card's meta line and the\n  // competition-hero card's header-right, so the trio renders identically on both. The pin here\n  // pins the MATCH; a moved price opens its history from the pick row below (D27).\n  const headerControls = (\n    <>\n      {live ? (\n        <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n      ) : null}\n      {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n      {showPin && ui ? (\n        <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: it.matchId }} market={it.marketDeveloperName} />\n      ) : null}\n    </>\n  )\n  return (\n    <div className=\"ss-w-binsight\">\n      {showHeader ? (\n        leftIsFixture ? (\n          <div className=\"ss-w-bi-head\">\n            {(it.competition || live || kickoff || showPin) ? (\n              <div className=\"ss-w-bi-meta\">\n                <span className=\"ss-w-bi-meta-left\">\n                  {it.competition ? (\n                    <>\n                      <Crest kind=\"comp\" url={it.competitionCrest} name={it.competition} />\n                      <span className=\"ss-w-bi-comp\">{it.competition}</span>\n                    </>\n                  ) : null}\n                </span>\n                <span className=\"ss-w-bi-meta-right\">{headerControls}</span>\n              </div>\n            ) : null}\n            <div className=\"ss-w-bi-fixture-line\">\n              <CardFixture it={it} />\n            </div>\n          </div>\n        ) : (\n          <div className=\"ss-w-bi-header\">\n            <span className=\"ss-w-bi-header-left\"><CardFixture it={it} /></span>\n            <span className=\"ss-w-bi-header-right\">{headerControls}</span>\n          </div>\n        )\n      ) : null}\n      <div className=\"ss-w-bi-action\">\n        {it.market ? <span className=\"ss-w-bi-market\">{it.market}</span> : null}\n        <div className=\"ss-w-bi-pick-row\">\n          {it.selection ? <span className=\"ss-w-bi-sel\">{it.selection}</span> : null}\n          {it.odds ? (\n            <span className=\"ss-w-bi-odds\">\n              <b>{it.odds}</b>\n              <OddsMovementBadge previous={it.previousOdds} current={it.odds} direction={it.movementDirection} ui={ui} />\n              {it.bookmaker ? <span className=\"ss-w-bi-book\">{it.bookmaker}</span> : null}\n            </span>\n          ) : null}\n          {it.odds && showPin && ui && it.previousOdds ? (\n            <PriceHistoryButton\n              ui={ui}\n              monitor={monitor}\n              selection={{ matchId: it.matchId, marketDeveloperName: it.marketDeveloperName, selectionLabel: it.selectionLabel, line: it.line, matchOddsId: it.matchOddsId }}\n            />\n          ) : null}\n          <AddToSlipButton it={it} slip={slip} ui={ui} />\n        </div>\n      </div>\n      {it.isMarketFloor ? (\n        <span className=\"ss-w-bi-floor\">{ui?.marketFloorLabel ?? 'Market price · not a value pick'}</span>\n      ) : null}\n      <ReasonStrip it={it} />\n      {it.disclaimer ? <p className=\"ss-w-bi-disc\">{it.disclaimer}</p> : null}\n    </div>\n  )\n}\n\nexport function BettingInsightList(\n  { insights, ui, slip, monitor }:\n  { insights: InsightVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element | null {\n  if (!insights || insights.length === 0) return null\n  return (\n    <div className=\"ss-w-binsights\">\n      {insights.map((it) => <InsightCard key={it.id} it={it} ui={ui} slip={slip} monitor={monitor} />)}\n    </div>\n  )\n}\n","import { useCallback, useState } from 'react'\nimport type { UiConfig } from '../config'\nimport { comboLegToSlipSelection, type ComboLegVM } from '../model'\nimport { addAllStep, addAllToast, type AddAllTally, type SlipHandlerProps, type SlipToast } from '../slip'\nimport { useSlipAdd } from '../slipAdd'\nimport { useSlipState } from '../slipStateContext'\nimport { Toast } from './Toast'\n\n// Adds a combo's legs one at a time through the same path as each leg's own button, so every leg\n// logs, settles and is recorded exactly as a single tap would. One at a time because an operator's\n// slip may not take parallel adds, and so a stop (sign-in, a full slip) stops before the next call.\nexport function AddAllToSlipButton(\n  { legs, slip, ui }: { legs: ComboLegVM[]; slip: SlipHandlerProps; ui?: UiConfig },\n): JSX.Element | null {\n  const add = useSlipAdd(slip, ui)\n  const slipState = useSlipState()\n  const [pending, setPending] = useState(false)\n  const [settledLocal, setSettledLocal] = useState<Readonly<Record<number, true>>>({})\n  const [toast, setToast] = useState<SlipToast | null>(null)\n  const dismiss = useCallback(() => setToast(null), [])\n\n  if (!ui || !slip.onAddToSlip || legs.length < 2) return null\n  const settled = slipState ? slipState.settled : settledLocal\n  const open = legs.filter((leg) => !settled[leg.matchOddsId])\n\n  const onClick = async (): Promise<void> => {\n    setPending(true)\n    const tally: AddAllTally = { attempted: open.length, added: 0, priceMoved: false, notAdded: [], login: false }\n    const added: Record<number, true> = {}\n    try {\n      for (let i = 0; i < open.length; i++) {\n        const leg = open[i]!\n        const step = addAllStep(await add(comboLegToSlipSelection(leg, slip.conversationId), {\n          marketDeveloperName: leg.marketDeveloperName || undefined,\n          selectionLabel: leg.selectionLabel,\n          line: leg.line,\n        }))\n        if (step === 'added' || step === 'added_moved') {\n          tally.added++\n          if (step === 'added_moved') tally.priceMoved = true\n          added[leg.matchOddsId] = true\n          continue\n        }\n        tally.notAdded.push([leg.homeTeamName, leg.awayTeamName])\n        if (step === 'skip') continue\n        if (step === 'stop_login') tally.login = true\n        for (const rest of open.slice(i + 1)) tally.notAdded.push([rest.homeTeamName, rest.awayTeamName])\n        break\n      }\n    } finally {\n      if (!slipState) setSettledLocal((s) => ({ ...s, ...added }))\n      setToast(addAllToast(tally, ui))\n      setPending(false)\n    }\n  }\n\n  const label = pending\n    ? ui.addingAllToSlip\n    : open.length === 0\n      ? ui.allInSlip\n      : open.length === legs.length ? ui.addAllToSlip(open.length) : ui.addRestToSlip(open.length)\n\n  return (\n    <div className=\"ss-w-slip ss-w-combo-addall\">\n      <button type=\"button\" className=\"ss-w-slip-btn\" disabled={pending || open.length === 0} onClick={onClick}>{label}</button>\n      <Toast toast={toast} onDismiss={dismiss} />\n    </div>\n  )\n}\n","import { createContext, useContext } from 'react'\n\nexport interface PresetToolsValue {\n  /** Opens \"Build a combo\" preset to a combo card's target and leg count (spec C5, U5). */\n  openBuilder(total: number, legs: number): void\n  /** \"Change total or matches\", in the widget's language. */\n  changeLabel: string\n}\n\n/** Present only once the grid answered 200 (contract §1); without it a combo card shows no\n *  \"Change total or matches\", because the builder would have nothing to show. */\nexport const PresetToolsContext = createContext<PresetToolsValue | null>(null)\n\nexport function usePresetTools(): PresetToolsValue | null {\n  return useContext(PresetToolsContext)\n}\n","import type { ComboCardVM, ComboLegVM } from '../model'\nimport { comboLegToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { AddAllToSlipButton } from './AddAllToSlipButton'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { usePresetTools } from '../presetToolsContext'\n\n// The combo card (spec C5). Every number and word on it comes from the server: the widget draws the\n// legs it was sent, the server's multiplication line and its replaced-leg note verbatim, and never\n// multiplies (spec Approach, R4) or words a note from reason codes (contract §4).\nfunction ComboLegRow(\n  { leg, addToSlipEnabled, ui, slip, monitor }: { leg: ComboLegVM; addToSlipEnabled: boolean; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element {\n  const kickoffFallback = !leg.kickoffLabel && leg.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(leg.kickoffUtc) : undefined\n  const kickoff = leg.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n  const selection = addToSlipEnabled ? comboLegToSlipSelection(leg, slip.conversationId) : null\n  const showPin = !!monitor && leg.pinEnabled && !!ui\n  return (\n    <li className=\"ss-w-combo-leg\">\n      {leg.competition || kickoff || showPin ? (\n        <div className=\"ss-w-combo-leg-meta\">\n          <span className=\"ss-w-bi-comp\">{leg.competition ?? ''}</span>\n          <span className=\"ss-w-bi-meta-right\">\n            {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n            {showPin && ui ? <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: leg.matchId }} market={leg.marketDeveloperName || undefined} /> : null}\n          </span>\n        </div>\n      ) : null}\n      <div className=\"ss-w-bi-fixture-line\">\n        <Crest kind=\"team\" url={leg.homeCrest} name={leg.homeTeamName} />\n        <span className=\"ss-w-bi-team\">{leg.homeTeamName}</span>\n        <span className=\"ss-w-bi-vs\" aria-hidden=\"true\">vs</span>\n        <span className=\"ss-w-bi-team\">{leg.awayTeamName}</span>\n        <Crest kind=\"team\" url={leg.awayCrest} name={leg.awayTeamName} />\n      </div>\n      <div className=\"ss-w-combo-leg-pick\">\n        <span className=\"ss-w-combo-leg-what\">\n          <span className=\"ss-w-combo-leg-market\">{leg.market}</span>\n          <span className=\"ss-w-combo-leg-sel\">{leg.selection}</span>\n        </span>\n        <span className=\"ss-w-combo-leg-price\">{leg.odds}</span>\n        <SlipButton\n          selection={selection}\n          shownOdds={leg.odds}\n          marketDeveloperName={leg.marketDeveloperName || undefined}\n          selectionLabel={leg.selectionLabel}\n          line={leg.line}\n          slip={slip}\n          ui={ui}\n          ariaLabel={`${leg.homeTeamName} ${leg.awayTeamName}, ${leg.selection} ${leg.odds}`}\n        />\n      </div>\n      {leg.statText ? <p className=\"ss-w-combo-leg-stat\">{leg.statText}</p> : null}\n    </li>\n  )\n}\n\nfunction ComboCardView({ vm, ui, slip, monitor }: { vm: ComboCardVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController }): JSX.Element {\n  const tools = usePresetTools()\n  const { target, legCount } = vm\n  return (\n    <div className=\"ss-w-combo\">\n      <ol className=\"ss-w-combo-legs\" role=\"list\">\n        {vm.legs.map((leg) => (\n          <ComboLegRow key={leg.key} leg={leg} addToSlipEnabled={vm.addToSlipEnabled} ui={ui} slip={slip} monitor={monitor} />\n        ))}\n      </ol>\n      <div className=\"ss-w-combo-math\">{vm.multiplication}</div>\n      {vm.replacedNote ? <p className=\"ss-w-combo-note\">{vm.replacedNote}</p> : null}\n      {vm.addToSlipEnabled ? <AddAllToSlipButton legs={vm.legs} slip={slip} ui={ui} /> : null}\n      {tools && target !== undefined && legCount !== undefined ? (\n        <button type=\"button\" className=\"ss-w-combo-change\" onClick={() => tools.openBuilder(target, legCount)}>{tools.changeLabel}</button>\n      ) : null}\n    </div>\n  )\n}\n\nexport function ComboCardList(\n  { cards, ui, slip, monitor }: { cards: ComboCardVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController },\n): JSX.Element | null {\n  if (!cards || cards.length === 0) return null\n  return (\n    <div className=\"ss-w-combos\">\n      {cards.map((vm) => <ComboCardView key={vm.id} vm={vm} ui={ui} slip={slip} monitor={monitor} />)}\n    </div>\n  )\n}\n","import { useEffect, useState } from 'react'\nimport type { PinRef } from '@sensiblestats/widget-sdk'\nimport type { MarketOddsVM, MarketOddsRowVM } from '../model'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { SlipButton } from './AddToSlipButton'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { Crest } from './Crest'\nimport { PinToggle } from './PinToggle'\nimport { PriceHistoryButton } from './PriceHistoryButton'\nimport { AllMarketsButton, allMarketsCount } from './AllMarketsButton'\n\nfunction OddsRow(\n  { vm, row, ui, slip, inSlipIds, history, suppressSlip }:\n  { vm: MarketOddsVM; row: MarketOddsRowVM; ui?: UiConfig; slip: SlipHandlerProps; inSlipIds?: Record<number, true>; history?: LiveMonitorController; suppressSlip?: boolean },\n): JSX.Element {\n  const selection = vm.addToSlipEnabled && !suppressSlip ? marketOddsRowToSlipSelection(vm, row, slip.conversationId) : null\n  // D5 persistent in-slip badge: keyed by matchOddsId in the widget's slip state (`added`, set by\n  // StatsWidget's onAddToSlip wrap), NOT the button's own \"In slip\" mark -- the two follow\n  // different rules (a duplicate answer marks the button and not the badge). Passed as a plain\n  // id map (not the full LiveMonitorController) so callers can surface the badge without also\n  // turning on this list's OWN pin-toggle header (OddsPanel already owns that pin via the\n  // market snapshot's context line -- a second, independently-keyed toggle here could drift out\n  // of sync with it).\n  const inSlip = !!inSlipIds && row.matchOddsId != null && !!inSlipIds[row.matchOddsId]\n  return (\n    <div className=\"ss-w-mo-row\">\n      <span className=\"ss-w-mo-sel\">{row.selection}</span>\n      <OddsMovementBadge previous={row.previousOdds} current={row.odds} direction={row.movementDirection} ui={ui} />\n      <span className=\"ss-w-mo-price\">{row.odds}</span>\n      {history && ui && row.previousOdds ? (\n        <PriceHistoryButton\n          ui={ui}\n          monitor={history}\n          selection={{ matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName, selectionLabel: row.selectionLabel, line: row.line, matchOddsId: row.matchOddsId }}\n        />\n      ) : null}\n      {inSlip && ui ? <span className=\"ss-w-mon-inslip\">✓ {ui.inSlipLabel}</span> : null}\n      {!suppressSlip ? <SlipButton selection={selection} shownOdds={row.odds} marketDeveloperName={vm.marketDeveloperName} selectionLabel={row.selectionLabel} line={row.line} slip={slip} ui={ui} /> : null}\n    </div>\n  )\n}\n\nconst STALE_AFTER_MS = 120_000\n\nfunction fmtHhMm(iso: string, locale: string): string {\n  return new Date(iso).toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit', hour12: false })\n}\n\nfunction MarketOddsCard(\n  { vm, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n  { vm: MarketOddsVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element {\n  const [open, setOpen] = useState(false)\n  const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n  const kickoff = vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n  const hasNamedTeams = !!vm.homeTeamName && !!vm.awayTeamName\n\n  // Live block state (stage 4)\n  const live = vm.live ?? null\n  const closedReason = live?.closedReason ?? null\n  const isClosed = closedReason !== null\n  // D13: stale when >120s since last snapshot update\n  const asOfMs = live ? new Date(live.asOfUtc).getTime() : NaN\n  const isStale = live != null && !isClosed && (vm.awaitingLiveUpdate === true || Date.now() - asOfMs > STALE_AFTER_MS)\n  const staleTime = isStale && live ? fmtHhMm(live.asOfUtc, ui?.locale ?? 'en') : null\n  // No poll may land to re-render the card, so it schedules its own render at the boundary.\n  const [, setStaleTick] = useState(0)\n  const watchStale = live != null && !isClosed && !isStale\n  useEffect(() => {\n    if (!watchStale) return\n    const id = window.setTimeout(() => setStaleTick((n) => n + 1), Math.max(0, asOfMs + STALE_AFTER_MS - Date.now()) + 1)\n    return () => window.clearTimeout(id)\n  }, [watchStale, asOfMs])\n\n  // R22: no pin toggle, no price history on live cards\n  const showPin = !!monitor && vm.pinEnabled && !live && (!!pinRef || !vm.isLive)\n  // Chat path (no pinRef): the header pin is the MATCH pin, and a price that moved opens its\n  // history (D27). The OddsPanel path passes pinRef and keeps its single market pin in the header;\n  // the Live tab accordion (hideHeader) has neither.\n  const history = showPin && !pinRef && !hideHeader ? monitor : undefined\n  // R2/R6: the footer link opens Following; never on a live card, the Odds tab or the accordion.\n  const allMarkets = !hideHeader && !pinRef && !live && !vm.isLive ? allMarketsCount(vm, monitor) : null\n  const showHeader = !!vm.competition || vm.isLive || !!kickoff || showPin || !!live\n  return (\n    <div className={hideHeader ? 'ss-w-mocard ss-w-mocard--bare' : 'ss-w-mocard'}>\n      {!hideHeader && (\n        <>\n          {showHeader ? (\n            <div className=\"ss-w-bi-header\">\n              <span className=\"ss-w-bi-header-left\">\n                {vm.competition ? (\n                  <>\n                    <Crest kind=\"comp\" url={vm.competitionCrest} name={vm.competition} />\n                    <span className=\"ss-w-bi-comp\">{vm.competition}</span>\n                  </>\n                ) : null}\n              </span>\n              <span className=\"ss-w-bi-header-right\">\n                {/* R18: no isLive dot on live cards; show score+minute instead */}\n                {live && !isClosed ? (\n                  <>\n                    <span className=\"ss-w-bi-score\">{live.homeScore}–{live.awayScore}</span>\n                    {live.minuteLabel ? <span className=\"ss-w-bi-min\">{live.minuteLabel}</span> : null}\n                  </>\n                ) : !live && vm.isLive ? (\n                  <span className=\"ss-w-bi-live\"><span className=\"ss-w-bi-live-dot\" aria-hidden=\"true\" />{ui?.liveLabel ?? 'Live'}</span>\n                ) : null}\n                {kickoff ? <span className=\"ss-w-bi-kick\">{kickoff}</span> : null}\n                {showPin && ui ? (\n                  <PinToggle\n                    ui={ui}\n                    monitor={monitor}\n                    pin={pinRef ?? { kind: 'match', matchId: vm.matchId }}\n                    market={pinRef ? undefined : vm.marketDeveloperName}\n                  />\n                ) : null}\n              </span>\n            </div>\n          ) : null}\n          {(hasNamedTeams || vm.fixture || vm.market) ? (\n            <div className=\"ss-w-mo-sub\">\n              {hasNamedTeams ? (\n                <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 ? (\n                <div className=\"ss-w-mo-market-row\">\n                  <span className=\"ss-w-mo-market\">{vm.market}</span>\n                  {vm.tag === 'your_market' ? <span className=\"ss-w-mo-tag\">{ui?.yourMarketTag ?? 'Your market'}</span> : null}\n                </div>\n              ) : null}\n            </div>\n          ) : null}\n        </>\n      )}\n      {!hideHeader && !pinRef\n        ? (vm.statTexts && vm.statTexts.length > 0 ? vm.statTexts : vm.statText ? [vm.statText] : []).map((text, i) => (\n            <div key={i} className=\"ss-w-mo-stat\">{text}</div>\n          ))\n        : null}\n      {/* D12: closed state messages instead of rows */}\n      {isClosed ? (\n        <div className=\"ss-w-mo-closed\">\n          {closedReason === 'suspended' ? <span>{ui?.liveCard.suspended ?? 'Market suspended'}</span>\n            : closedReason === 'no_live_price' ? <span>{ui?.liveCard.noPrice ?? 'No live price available'}</span>\n            : closedReason === 'full_time' ? <span>{ui?.liveCard.fullTime ?? 'Full time'}</span>\n            : null}\n        </div>\n      ) : (\n        <>\n          <div className=\"ss-w-mo-rows\">\n            {vm.mainRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} suppressSlip={isStale} />)}\n            {open ? vm.moreRows.map((row) => <OddsRow key={row.key} vm={vm} row={row} ui={ui} slip={slip} inSlipIds={inSlipIds} history={history} suppressSlip={isStale} />) : 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          {/* D13: stale text after rows when >120s since last update */}\n          {staleTime ? <p className=\"ss-w-mo-stale\">{ui?.liveCard.stale(staleTime) ?? `Prices from ${staleTime}`}</p> : null}\n        </>\n      )}\n      {vm.bookmaker || (allMarkets !== null && monitor && ui) ? (\n        <div className=\"ss-w-mo-foot\">\n          {vm.bookmaker ? <span>{vm.bookmaker}</span> : null}\n          {allMarkets !== null && monitor && ui ? <AllMarketsButton vm={vm} count={allMarkets} monitor={monitor} ui={ui} surface=\"card\" /> : null}\n        </div>\n      ) : null}\n      {vm.disclaimer ? <p className=\"ss-w-bi-disc\">{vm.disclaimer}</p> : null}\n    </div>\n  )\n}\n\nexport function MarketOddsCardList(\n  { cards, ui, slip, monitor, inSlipIds, hideHeader, pinRef }:\n  { cards: MarketOddsVM[]; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController; inSlipIds?: Record<number, true>; hideHeader?: boolean; pinRef?: Omit<PinRef, 'key'> },\n): JSX.Element | null {\n  if (!cards || cards.length === 0) return null\n  return (\n    <div className=\"ss-w-mocards\">\n      {cards.map((vm) => (\n        <MarketOddsCard key={vm.id} vm={vm} ui={ui} slip={slip} monitor={monitor} inSlipIds={inSlipIds} hideHeader={hideHeader} pinRef={pinRef} />\n      ))}\n    </div>\n  )\n}\n","import type { MarketOddsVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { useEventLog } from '../eventLogContext'\n\n/** The count behind \"All markets (N)\", or null when the link must not show (G3). */\nexport function allMarketsCount(vm: MarketOddsVM, monitor: LiveMonitorController | undefined): number | null {\n  if (!monitor?.enabled || !vm.pinEnabled) return null\n  return vm.marketCount !== undefined && vm.marketCount >= 2 ? vm.marketCount : null\n}\n\nexport function AllMarketsButton({ vm, count, monitor, ui, surface }: {\n  vm: MarketOddsVM; count: number; monitor: LiveMonitorController; ui: UiConfig; surface: 'card' | 'list'\n}): JSX.Element {\n  const log = useEventLog()\n  const onClick = (): void => {\n    monitor.pinMatch({ matchId: vm.matchId, marketDeveloperName: vm.marketDeveloperName })\n    log?.log({\n      name: 'match_open',\n      entityType: 'match',\n      entityId: String(vm.matchId),\n      marketDeveloperName: vm.marketDeveloperName,\n      outcome: surface === 'card' ? 'all_markets_card' : 'all_markets_list',\n    })\n  }\n  const label = vm.homeTeamName && vm.awayTeamName ? ui.allMarketsAria(count, vm.homeTeamName, vm.awayTeamName) : undefined\n  return (\n    <button type=\"button\" className={surface === 'card' ? 'ss-w-allmk' : 'ss-w-allmk ss-w-allmk--chip'} aria-label={label ?? ui.allMarkets(count)} onClick={onClick}>\n      <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n        <rect x=\"3\" y=\"5\" width=\"5\" height=\"5\" rx=\"1.2\" /><rect x=\"9.5\" y=\"5\" width=\"5\" height=\"5\" rx=\"1.2\" /><rect x=\"16\" y=\"5\" width=\"5\" height=\"5\" rx=\"1.2\" />\n        <rect x=\"3\" y=\"14\" width=\"5\" height=\"5\" rx=\"1.2\" /><rect x=\"9.5\" y=\"14\" width=\"5\" height=\"5\" rx=\"1.2\" /><rect x=\"16\" y=\"14\" width=\"5\" height=\"5\" rx=\"1.2\" />\n      </svg>\n      {surface === 'card' ? ui.allMarkets(count) : count}\n    </button>\n  )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { Ref } from 'react'\nimport type { CompactCellVM, CompactListVM, CompactRowVM } from '../compactList'\nimport { COMPACT_PAGE } from '../compactList'\nimport { marketOddsRowToSlipSelection } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { AllMarketsButton, allMarketsCount } from './AllMarketsButton'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PinToggle } from './PinToggle'\n\nfunction Cell({ row, cell, ui, slip }: { row: CompactRowVM; cell: CompactCellVM; ui?: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n  const vm = row.card\n  const selection = vm.addToSlipEnabled ? marketOddsRowToSlipSelection(vm, cell.row, slip.conversationId) : null\n  const name = `${vm.homeTeamName ?? ''} ${vm.awayTeamName ?? ''}, ${cell.row.selection} ${cell.row.odds}`\n  const button = (\n    <SlipButton\n      selection={selection}\n      shownOdds={cell.row.odds}\n      marketDeveloperName={vm.marketDeveloperName}\n      selectionLabel={cell.row.selectionLabel}\n      line={cell.row.line}\n      slip={slip}\n      ui={ui}\n      price={{ label: cell.label, ariaLabel: name }}\n    />\n  )\n  return (\n    // A third of the price column fits four characters at the row's size: 13.00 steps down a size\n    // and 101.00 two.\n    <span className={['ss-w-mol-cell', cell.row.odds.length >= 5 && 'ss-w-mol-cell--wide', cell.row.odds.length >= 6 && 'ss-w-mol-cell--wider'].filter(Boolean).join(' ')}>\n      {selection && slip.onAddToSlip && ui ? button : (\n        <span className=\"ss-w-mol-price\">\n          {cell.label ? <span className=\"ss-w-mol-lab\" aria-hidden=\"true\">{cell.label}</span> : null}\n          <span aria-hidden=\"true\">{cell.row.odds}</span>\n          <span className=\"ss-w-vh\">{name}</span>\n        </span>\n      )}\n      <OddsMovementBadge previous={cell.row.previousOdds} current={cell.row.odds} direction={cell.row.movementDirection} ui={ui} />\n    </span>\n  )\n}\n\nfunction Row({ row, columns, ui, slip, monitor, rowRef }: {\n  row: CompactRowVM; columns: number; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n  rowRef?: Ref<HTMLDivElement>\n}): JSX.Element {\n  const vm = row.card\n  const count = allMarketsCount(vm, monitor)\n  const kickoffFallback = vm.kickoffUtc && ui?.bettingKickoff ? ui.bettingKickoff(vm.kickoffUtc) : undefined\n  const when = vm.isLive\n    ? ui?.liveLabel ?? 'Live'\n    : vm.kickoffLabel ?? (kickoffFallback ? `${kickoffFallback.dayLabel} ${kickoffFallback.time}` : undefined)\n  return (\n    <div className=\"ss-w-mol-row\" ref={rowRef} tabIndex={rowRef ? -1 : undefined}>\n      <div className=\"ss-w-mol-fx\">\n        <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.homeCrest} name={vm.homeTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.homeTeamName}</span></span>\n        <span className=\"ss-w-mol-team\"><Crest kind=\"team\" url={vm.awayCrest} name={vm.awayTeamName ?? ''} /><span className=\"ss-w-mol-nm\">{vm.awayTeamName}</span></span>\n        {row.otherMarket ? <span className=\"ss-w-mol-mkt\">{row.otherMarket}</span> : null}\n      </div>\n      <span className=\"ss-w-mol-cells\" style={{ gridTemplateColumns: `repeat(${row.cells.length || columns}, minmax(0, 1fr))` }}>\n        {row.cells.map((cell) => <Cell key={cell.row.key} row={row} cell={cell} ui={ui} slip={slip} />)}\n      </span>\n      <span className={vm.isLive ? 'ss-w-mol-side ss-w-mol-side--live' : 'ss-w-mol-side'}>\n        {when ? <span className=\"ss-w-mol-when\">{when}</span> : null}\n        {count !== null && monitor && ui\n          ? <AllMarketsButton vm={vm} count={count} monitor={monitor} ui={ui} surface=\"list\" />\n          : monitor && vm.pinEnabled && vm.isLive && ui ? <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: vm.matchId }} /> : null}\n      </span>\n    </div>\n  )\n}\n\nexport function CompactOddsList({ list, ui, slip, monitor }: {\n  list: CompactListVM; ui?: UiConfig; slip: SlipHandlerProps; monitor?: LiveMonitorController\n}): JSX.Element {\n  const [shown, setShown] = useState(COMPACT_PAGE)\n  const hidden = list.rowCount - shown\n  // \"Show more\" can unmount itself; focus goes to the first row it revealed, not to the page body.\n  const [focusIndex, setFocusIndex] = useState<number | null>(null)\n  const focusRef = useRef<HTMLDivElement>(null)\n  useEffect(() => {\n    if (focusIndex !== null) focusRef.current?.focus()\n  }, [focusIndex])\n  let left = shown\n  let index = 0\n  return (\n    <div className=\"ss-w-mol\">\n      <div className=\"ss-w-mol-head\">\n        <span className=\"ss-w-mol-market\">{list.market}</span>\n        <span className=\"ss-w-mol-cols\" aria-hidden=\"true\" style={{ gridTemplateColumns: `repeat(${list.columns.length}, minmax(0, 1fr))` }}>\n          {list.columns.map((c, i) => <span key={`${c}:${i}`} className=\"ss-w-mol-col\">{c}</span>)}\n        </span>\n        <span className=\"ss-w-mol-side\" aria-hidden=\"true\" />\n      </div>\n      {list.groups.map((group, gi) => {\n        const rows = group.rows.slice(0, Math.max(0, left))\n        left -= rows.length\n        if (rows.length === 0) return null\n        return (\n          <div className=\"ss-w-mol-group\" key={`${group.competition ?? ''}:${gi}`}>\n            {group.competition ? (\n              <div className=\"ss-w-mol-comp\">\n                <Crest kind=\"comp\" url={group.competitionCrest} name={group.competition} />\n                <span>{group.competition}</span>\n              </div>\n            ) : null}\n            {rows.map((row) => {\n              const at = index++\n              return <Row key={row.card.id} row={row} columns={list.columns.length} ui={ui} slip={slip} monitor={monitor} rowRef={at === focusIndex ? focusRef : undefined} />\n            })}\n          </div>\n        )\n      })}\n      {hidden > 0 ? (\n        <button type=\"button\" className=\"ss-w-mo-more\" onClick={() => { setFocusIndex(shown); setShown((n) => n + COMPACT_PAGE) }}>\n          <span>{ui?.showMore ? ui.showMore(Math.min(COMPACT_PAGE, hidden)) : `Show ${Math.min(COMPACT_PAGE, hidden)} more`}</span>\n          <span className=\"ss-w-mo-more-chev\" aria-hidden=\"true\" />\n        </button>\n      ) : null}\n      {list.bookmaker ? <div className=\"ss-w-mo-foot\"><span>{list.bookmaker}</span></div> : null}\n      {list.disclaimer ? <p className=\"ss-w-bi-disc\">{list.disclaimer}</p> : null}\n    </div>\n  )\n}\n","import type { MarketOddsRowVM, MarketOddsVM } from './model'\n\n/** One price in a compact list row. `label` is set when the column head does not say what it is. */\nexport interface CompactCellVM {\n  row: MarketOddsRowVM\n  label?: string\n}\n\nexport interface CompactRowVM {\n  card: MarketOddsVM\n  /** The row's market name, set when it differs from the list's market. */\n  otherMarket?: string\n  cells: CompactCellVM[]\n}\n\nexport interface CompactGroupVM {\n  competition?: string\n  competitionCrest?: string\n  rows: CompactRowVM[]\n}\n\nexport interface CompactListVM {\n  market: string\n  columns: string[]\n  groups: CompactGroupVM[]\n  rowCount: number\n  bookmaker?: string\n  disclaimer?: string\n}\n\nexport const COMPACT_MIN_CARDS = 3\n\n/** A row holds one to three prices in the price column. A market with more, such as correct score,\n *  or a card with every price suspended, keeps the stack. */\nconst COMPACT_MAX_PRICES = 3\n\n/** Match Result heads are the betting convention, 1 X 2, in every language: \"Beraberlik\" and\n *  \"Deplasman\" do not fit a price column. */\nconst RESULT_MARKET = 'FULLTIME_RESULT'\nconst RESULT_HEADS = ['1', 'X', '2']\nexport const COMPACT_PAGE = 5\n\n/** The list's market: the one most cards carry, the first card's on a tie. */\nfunction referenceMarket(cards: MarketOddsVM[]): string | undefined {\n  const counts = new Map<string | undefined, number>()\n  for (const c of cards) counts.set(c.marketDeveloperName, (counts.get(c.marketDeveloperName) ?? 0) + 1)\n  let best = cards[0]!.marketDeveloperName\n  for (const c of cards) {\n    if ((counts.get(c.marketDeveloperName) ?? 0) > (counts.get(best) ?? 0)) best = c.marketDeveloperName\n  }\n  return best\n}\n\n/**\n * D16: three or more price cards on one turn, one per fixture, draw as one compact list. Returns\n * null for anything else, which keeps the stack: fewer cards, or two cards of the same fixture.\n * A row of another market than the list's names its market and labels its own prices (R19, Ertu\n * 2026-10-03).\n */\nexport function toCompactList(cards: MarketOddsVM[]): CompactListVM | null {\n  if (cards.length < COMPACT_MIN_CARDS) return null\n  if (new Set(cards.map((c) => c.matchId)).size !== cards.length) return null\n  if (cards.some((c) => c.mainRows.length === 0 || c.mainRows.length > COMPACT_MAX_PRICES)) return null\n\n  const market = referenceMarket(cards)\n  // The heads come from the card of the list's market with the most open prices: a suspended price\n  // on the first card must not drop a column for every row.\n  const head = cards\n    .filter((c) => c.marketDeveloperName === market)\n    .reduce((best, c) => (c.mainRows.length > best.mainRows.length ? c : best))\n  const labels = head.mainRows.map((r) => r.selectionLabel ?? r.selection)\n  const columns = market === RESULT_MARKET && labels.length === RESULT_HEADS.length ? RESULT_HEADS : labels\n\n  const toRow = (card: MarketOddsVM): CompactRowVM => {\n    const sameMarket = card.marketDeveloperName === market\n    const own = card.mainRows.map((r) => r.selectionLabel ?? r.selection)\n    const aligned = sameMarket && own.length === labels.length && own.every((l, i) => l === labels[i])\n    return {\n      card,\n      otherMarket: sameMarket ? undefined : card.market,\n      cells: card.mainRows.map((row) => ({\n        row,\n        label: !aligned ? row.selection : row.line !== head.mainLine && row.line ? row.line : undefined,\n      })),\n    }\n  }\n\n  const groups: CompactGroupVM[] = []\n  for (const card of cards) {\n    let group = groups.find((g) => g.competition === card.competition)\n    if (!group) {\n      group = { competition: card.competition, competitionCrest: card.competitionCrest, rows: [] }\n      groups.push(group)\n    }\n    group.rows.push(toRow(card))\n  }\n\n  return {\n    market: head.market,\n    columns,\n    groups,\n    rowCount: cards.length,\n    bookmaker: cards.map((c) => c.bookmaker).find(Boolean),\n    disclaimer: cards.map((c) => c.disclaimer).find(Boolean),\n  }\n}\n","import type { UiConfig } from '../config'\nimport type { OddsMovementVM } from '../model'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { CHART_VIEW_H, CHART_VIEW_W } from '../chart'\nimport { OddsMovementBadge } from './OddsMovementBadge'\nimport { PriceHistoryButton } from './PriceHistoryButton'\n\nfunction directionWord(vm: OddsMovementVM, ui?: UiConfig): string {\n  if (vm.direction === 'shortened') return ui?.oddsShortened ?? 'shortened'\n  if (vm.direction === 'drifted') return ui?.oddsDrifted ?? 'drifted'\n  return ''\n}\n\nfunction OddsMovementCard(\n  { vm, ui, monitor }: { vm: OddsMovementVM; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element {\n  const word = directionWord(vm, ui)\n  const drift = word ? `, ${word}` : ''\n  const aria = ui?.chartAria\n    ? ui.chartAria(vm.opening, vm.current, word, vm.windowHours)\n    : `Price movement over the last ${vm.windowHours} hours: opened at ${vm.opening}, currently ${vm.current}${drift}.`\n  const showPin = !!monitor && vm.pinEnabled\n\n  return (\n    <div className=\"ss-w-omcard\">\n      <div className=\"ss-w-om-head\">\n        <span className=\"ss-w-om-market\">{vm.market}</span>\n        <span className=\"ss-w-om-tag\">{ui?.priceMovement ?? 'Price movement'}</span>\n        {showPin && ui ? (\n          <PriceHistoryButton\n            ui={ui}\n            monitor={monitor}\n            selection={{\n              matchId: vm.matchId,\n              marketDeveloperName: vm.marketDeveloperName,\n              selectionLabel: vm.selectionLabel,\n              line: vm.line,\n              matchOddsId: vm.matchOddsId,\n            }}\n          />\n        ) : null}\n      </div>\n      {vm.fixture ? (\n        <div className=\"ss-w-om-fixture\">\n          <span>{vm.fixture}</span>\n          {vm.competition ? <span className=\"ss-w-om-comp\">{vm.competition}</span> : null}\n        </div>\n      ) : null}\n      <div className=\"ss-w-om-sel\">{vm.selection}</div>\n      <OddsMovementBadge previous={vm.opening} current={vm.current} direction={vm.direction} ui={ui} />\n\n      {vm.geometry === null ? (\n        <div className=\"ss-w-om-empty\">\n          {vm.observationCount === 1\n            ? ui?.singlePricePoint ?? 'Only one price recorded so far for this selection.'\n            : ui?.notEnoughHistory ?? 'No price history recorded yet for this selection.'}\n        </div>\n      ) : (\n        <svg\n          className=\"ss-w-om-chart\"\n          viewBox={vm.geometry.viewBox}\n          width=\"100%\"\n          role=\"img\"\n          aria-label={aria}\n        >\n          {vm.geometry.gridlines.map((g) => (\n            <g key={g.price}>\n              <line className=\"ss-w-om-grid\" x1={40} y1={g.y} x2={CHART_VIEW_W - 8} y2={g.y} />\n              <text className=\"ss-w-om-ylab\" x={34} y={g.y + 3} textAnchor=\"end\">{g.price.toFixed(2)}</text>\n            </g>\n          ))}\n          <path className=\"ss-w-om-line\" d={vm.geometry.path} fill=\"none\" />\n          {vm.geometry.markers.map((m, i) => (\n            <circle key={i} className=\"ss-w-om-dot\" cx={m.x} cy={m.y} r={2.5} />\n          ))}\n          {ui?.chartTimeLabel ? (\n            <>\n              <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8} textAnchor=\"start\">\n                {ui.chartTimeLabel(vm.geometry.startMs)}\n              </text>\n              <text className=\"ss-w-om-xlab\" x={CHART_VIEW_W - 8} y={CHART_VIEW_H - 8} textAnchor=\"end\">\n                {ui.chartTimeLabel(vm.geometry.endMs)}\n              </text>\n            </>\n          ) : (\n            <text className=\"ss-w-om-xlab\" x={40} y={CHART_VIEW_H - 8}>\n              {ui?.movementWindow ? ui.movementWindow(vm.windowHours) : `Last ${vm.windowHours}h`}\n            </text>\n          )}\n        </svg>\n      )}\n\n      <div className=\"ss-w-om-foot\">\n        <span>{ui?.openingLabel ?? 'Opening'} <b>{vm.opening}</b></span>\n        <span>{ui?.currentLabel ?? 'Current'} <b>{vm.current}</b></span>\n      </div>\n      {vm.bookmaker ? (\n        <div className=\"ss-w-om-foot\">\n          <span>{vm.bookmaker}</span>\n        </div>\n      ) : null}\n      {vm.excludedCount > 0 ? (\n        <div className=\"ss-w-om-excl\">\n          {ui?.excludedSuspended ? ui.excludedSuspended(vm.excludedCount) : `${vm.excludedCount} suspended price(s) excluded from this chart.`}\n        </div>\n      ) : null}\n      {vm.isSuspended ? (\n        <div className=\"ss-w-om-susp\">{ui?.selectionSuspended ?? 'This selection is not currently available to bet.'}</div>\n      ) : null}\n      {vm.disclaimer ? <div className=\"ss-w-om-disc\">{vm.disclaimer}</div> : null}\n    </div>\n  )\n}\n\nexport function OddsMovementCardList(\n  { cards, ui, monitor }: { cards: OddsMovementVM[]; ui?: UiConfig; monitor?: LiveMonitorController },\n): JSX.Element | null {\n  if (!cards || cards.length === 0) return null\n  return (\n    <div className=\"ss-w-omcards\">\n      {cards.map((vm) => <OddsMovementCard key={vm.id} vm={vm} ui={ui} monitor={monitor} />)}\n    </div>\n  )\n}\n","import type { ActionVM } from '../model'\n\nexport function ActionButtons({ actions, loading, disabled, onAct }: { actions: ActionVM[]; loading: boolean; disabled?: boolean; onAct: (action: ActionVM) => void }): JSX.Element | null {\n  if (actions.length === 0 && !loading) return null\n  return (\n    <div className=\"ss-w-actions\">\n      {actions.map((a, i) => (\n        <button key={`${a.label}-${i}`} type=\"button\" className=\"ss-w-abtn\" disabled={disabled} onClick={() => onAct(a)}>{a.label}</button>\n      ))}\n      {actions.length === 0 && loading ? (\n        <>\n          <span className=\"ss-w-abtn-shimmer\" />\n          <span className=\"ss-w-abtn-shimmer\" />\n        </>\n      ) : null}\n    </div>\n  )\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport { DashboardIcon, ChevronIcon } from '../Icons'\n\n// The server payload caps crests at 3 (spec D2); slicing here is a defensive floor, not a\n// server-side promise, since a badge + crest row this wide already competes for the same\n// space the title needs.\nconst MAX_CRESTS = 3\n\n// The server appends the price as a last \" · @1.85\" segment; it is lifted out so the hero can show\n// it as a price rather than as the tail of a sentence.\nconst ODDS_TAIL = /\\s*·\\s*@(\\d+(?:\\.\\d+)?)\\s*$/\n\nfunction splitOdds(subtitle: string): { text: string; odds?: string } {\n  const m = ODDS_TAIL.exec(subtitle)\n  return m ? { text: subtitle.slice(0, m.index), odds: m[1] } : { text: subtitle }\n}\n\nfunction HeroTile({ tile, onTap, oddsLabel }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel: string }): JSX.Element {\n  const crests = (tile.imageUrls ?? []).filter(Boolean).slice(0, 2)\n  const sub = tile.subtitle ? splitOdds(tile.subtitle) : null\n  return (\n    <button type=\"button\" className=\"ss-w-dash-tile ss-w-dash-tile--full ss-w-dash-hero\" onClick={onTap}>\n      <span className=\"ss-w-dash-hero-top\">\n        {tile.badgeText ? <span className=\"ss-w-dash-hero-badge\">{tile.badgeText}</span> : null}\n        {sub?.odds ? <span className=\"ss-w-dash-hero-price\"><span className=\"ss-g-sr\">{oddsLabel} </span>{sub.odds}</span> : null}\n        <span className=\"ss-w-dash-hero-chevron\"><ChevronIcon /></span>\n      </span>\n      <span className=\"ss-w-dash-hero-main\">\n        <span className=\"ss-w-dash-hero-visual\" aria-hidden=\"true\">\n          {crests.length > 0\n            ? crests.map((url, i) => (\n                <span key={`${url}-${i}`} className=\"ss-w-dash-hero-crest\" style={{ backgroundImage: `url(${url})` }} />\n              ))\n            : <span className=\"ss-w-dash-hero-icon\"><DashboardIcon name={tile.icon} /></span>}\n        </span>\n        <span className=\"ss-w-dash-hero-body\">\n          <span className=\"ss-w-dash-hero-title\">{tile.title}</span>\n          {sub?.text ? <span className=\"ss-w-dash-hero-subtitle\">{sub.text}</span> : null}\n        </span>\n      </span>\n    </button>\n  )\n}\n\n// 'end' puts the badge in its own column at the row's right edge, in place of the chevron: the\n// goal layout's one-column rows have the width for it, and a badge under the subtitle made each\n// row about 95px tall.\nexport type BadgePlacement = 'meta' | 'end'\n\nexport function DashboardTile({ tile, onTap, oddsLabel = 'Odds', badgePlacement = 'meta' }: { tile: GreetingDashboardTile; onTap: () => void; oddsLabel?: string; badgePlacement?: BadgePlacement }): JSX.Element {\n  if (tile.emphasis === 'hero') return <HeroTile tile={tile} onTap={onTap} oddsLabel={oddsLabel} />\n  const spanClass = tile.span === 'full' ? 'ss-w-dash-tile--full' : 'ss-w-dash-tile--half'\n  const crests = (tile.imageUrls ?? []).slice(0, MAX_CRESTS)\n  const endBadge = badgePlacement === 'end' && tile.badgeText ? tile.badgeText : null\n  const metaBadge = endBadge ? null : tile.badgeText\n  const hasMeta = Boolean(metaBadge) || 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            {metaBadge ? <span className=\"ss-w-dash-tile-badge\">{metaBadge}</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      {endBadge\n        ? <span className=\"ss-w-dash-tile-value\">{endBadge}</span>\n        : <span className=\"ss-w-dash-tile-chevron\"><ChevronIcon /></span>}\n    </button>\n  )\n}\n","import type { GreetingDashboard as GreetingDashboardData, GreetingDashboardLayout, GreetingDashboardTile as GreetingDashboardTileData } from '@sensiblestats/widget-sdk'\nimport { DashboardTile } from './DashboardTile'\n\nconst LAYOUT_CLASSES: Record<GreetingDashboardLayout, string> = {\n  market: 'ss-w-dash--market',\n  goal: 'ss-w-dash--goal',\n  discovery: 'ss-w-dash--discovery',\n}\n\n// The server's layout is a closed set, but a mismatched deploy or a future value\n// could still send something outside it. Falling back to goal (an allowlist check,\n// not a truthiness test) avoids emitting a class with no CSS rule behind it.\n// hasOwnProperty (not `in`) so a prototype member name like 'toString' can't slip\n// through as a layout and get interpolated into the className.\nfunction layoutClass(layout: string): string {\n  return Object.prototype.hasOwnProperty.call(LAYOUT_CLASSES, layout)\n    ? LAYOUT_CLASSES[layout as GreetingDashboardLayout]\n    : LAYOUT_CLASSES.goal\n}\n\nexport function GreetingDashboard({ dashboard, onTap, oddsLabel }: { dashboard: GreetingDashboardData; onTap: (tile: GreetingDashboardTileData, index: number) => void; oddsLabel?: string }): JSX.Element {\n  const layout = layoutClass(dashboard.layout)\n  const badgePlacement = layout === LAYOUT_CLASSES.goal ? 'end' : 'meta'\n  return (\n    <div className={`ss-w-dash ${layout}`}>\n      <div className=\"ss-w-dash-head\">\n        <span className=\"ss-w-dash-title\">{dashboard.title}</span>\n        {dashboard.subtitle ? <span className=\"ss-w-dash-subtitle\">{dashboard.subtitle}</span> : null}\n      </div>\n      <div className=\"ss-w-dash-grid\">\n        {dashboard.tiles.map((t, i) => (\n          <DashboardTile key={`${t.title}-${i}`} tile={t} onTap={() => onTap(t, i)} oddsLabel={oddsLabel} badgePlacement={badgePlacement} />\n        ))}\n      </div>\n      {dashboard.footerTip ? <span className=\"ss-w-dash-foot\">{dashboard.footerTip}</span> : null}\n    </div>\n  )\n}\n","import type { FixtureCard as FixtureCardData, FormMatch } from '@sensiblestats/widget-sdk'\nimport { Crest } from '../Crest'\n\nfunction teamFormResultClass(result: FormMatch['result']): string {\n  if (result === 'W') return 'ss-w-fandash-teamform-cell--win'\n  if (result === 'L') return 'ss-w-fandash-teamform-cell--loss'\n  return 'ss-w-fandash-teamform-cell--draw'\n}\n\n// One historical-match cell: subject crest + score + opponent crest, ordered by which side the\n// subject team played on so the score always reads left-to-right as it happened on the pitch.\nfunction TeamFormCell({ m, subjectCrestUrl, subjectName }: {\n  m: FormMatch\n  subjectCrestUrl?: string | null\n  subjectName: string\n}): JSX.Element {\n  const subjectCrest = <Crest url={subjectCrestUrl ?? undefined} name={subjectName} kind=\"team\" />\n  const opponentCrest = <Crest url={m.opponentCrestUrl ?? undefined} kind=\"team\" />\n  const score = m.teamIsHome ? `${m.teamScore} - ${m.oppScore}` : `${m.oppScore} - ${m.teamScore}`\n  return (\n    <div className={`ss-w-fandash-teamform-cell ${teamFormResultClass(m.result)}`}>\n      {m.teamIsHome ? subjectCrest : opponentCrest}\n      <span className=\"ss-w-fandash-teamform-score\">{score}</span>\n      {m.teamIsHome ? opponentCrest : subjectCrest}\n    </div>\n  )\n}\n\nconst TEAM_FORM_ROWS = 5\n\n// Two-column \"Team form\" card: left = home team's last 5, right = away team's last 5, most-recent\n// first. The rows grid is filled home-cell, away-cell per index (matching the approved two-column\n// mock) so a 2-col CSS grid lays them out in the right pairs without any extra layout wiring. A\n// shorter side just leaves later slots blank rather than shifting the other column's rows.\nfunction teamFormRows(data: FixtureCardData['data']): JSX.Element[] {\n  return Array.from({ length: TEAM_FORM_ROWS }, (_, i) => i).flatMap((i) => [\n    <span key={`h-${i}`} className=\"ss-w-fandash-teamform-slot\">\n      {data.homeForm[i] ? (\n        <TeamFormCell m={data.homeForm[i]} subjectCrestUrl={data.homeCrestUrl} subjectName={data.homeName} />\n      ) : null}\n    </span>,\n    <span key={`a-${i}`} className=\"ss-w-fandash-teamform-slot\">\n      {data.awayForm[i] ? (\n        <TeamFormCell m={data.awayForm[i]} subjectCrestUrl={data.awayCrestUrl} subjectName={data.awayName} />\n      ) : null}\n    </span>,\n  ])\n}\n\n// The fixture payload renders as three stacked [data] cards -- the fixture head (teams, kickoff,\n// venue), the last-five form, and the head-to-head record -- so each block reads as its own unit.\n// None is a tap target: the compare-form action lives in the greeting chips, so the card carries no\n// redundant CTA. (u319: the server now issues FixtureCard as a plain DataCard with no actionRef.)\nexport function FixtureCard({ card }: { card: FixtureCardData }): JSX.Element {\n  const { data } = card\n  const h2h = data.h2H\n  return (\n    <>\n      <div className=\"ss-w-fandash-card ss-w-fandash-fixture\">\n        <span className=\"ss-w-fandash-eyebrow\">{card.title} · {data.competition}</span>\n        <div className=\"ss-w-fandash-fixture-teams\">\n          <span className=\"ss-w-fandash-fixture-team\">\n            <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n            <span className=\"ss-w-fandash-fixture-name\">{data.homeName}</span>\n          </span>\n          <span className=\"ss-w-fandash-fixture-vs\">v</span>\n          <span className=\"ss-w-fandash-fixture-team ss-w-fandash-fixture-team--away\">\n            <span className=\"ss-w-fandash-fixture-name\">{data.awayName}</span>\n            <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n          </span>\n        </div>\n        <div className=\"ss-w-fandash-fixture-meta\">\n          <span className=\"ss-w-fandash-fixture-kickoff\">{data.kickoffLabel}</span>\n          {data.venue ? <span className=\"ss-w-fandash-fixture-venue\"> · {data.venue}</span> : null}\n        </div>\n      </div>\n\n      <div className=\"ss-w-fandash-card ss-w-fandash-lastfive\">\n        <span className=\"ss-w-fandash-eyebrow\">{data.formLabel}</span>\n        <div className=\"ss-w-fandash-teamform-head\">\n          <span className=\"ss-w-fandash-teamform-head-team\">\n            <Crest url={data.homeCrestUrl ?? undefined} name={data.homeName} kind=\"team\" />\n            <span className=\"ss-w-fandash-teamform-head-name\">{data.homeName}</span>\n          </span>\n          <span className=\"ss-w-fandash-teamform-head-team\">\n            <Crest url={data.awayCrestUrl ?? undefined} name={data.awayName} kind=\"team\" />\n            <span className=\"ss-w-fandash-teamform-head-name\">{data.awayName}</span>\n          </span>\n        </div>\n        <div className=\"ss-w-fandash-teamform-rows\">\n          {teamFormRows(data)}\n        </div>\n      </div>\n\n      {h2h || data.fact ? (\n        <div className=\"ss-w-fandash-card ss-w-fandash-h2h\">\n          {h2h ? (\n            <>\n              <span className=\"ss-w-fandash-eyebrow\">{h2h.label}</span>\n              <div className=\"ss-w-fandash-split\">\n                <span className=\"ss-w-fandash-split-cell\">\n                  <span className=\"ss-w-fandash-split-value\">{h2h.wins}</span>\n                  <span className=\"ss-w-fandash-split-label\">{h2h.homeWinsLabel}</span>\n                </span>\n                <span className=\"ss-w-fandash-split-cell\">\n                  <span className=\"ss-w-fandash-split-value\">{h2h.draws}</span>\n                  <span className=\"ss-w-fandash-split-label\">{h2h.drawsLabel}</span>\n                </span>\n                <span className=\"ss-w-fandash-split-cell\">\n                  <span className=\"ss-w-fandash-split-value\">{h2h.losses}</span>\n                  <span className=\"ss-w-fandash-split-label\">{h2h.awayWinsLabel}</span>\n                </span>\n              </div>\n            </>\n          ) : null}\n          {data.fact ? <span className=\"ss-w-fandash-fact\">{data.fact}</span> : null}\n        </div>\n      ) : null}\n    </>\n  )\n}\n","import { Fragment, useEffect, useState } from 'react'\nimport type { CountdownCard as CountdownCardData } from '@sensiblestats/widget-sdk'\n\ntype UnitKind = 'd' | 'h' | 'm' | 's'\ntype Segment = { value: string; unit: UnitKind }\n\nconst DAY_MS = 86_400_000\n\n// The countdown reads day:hour while the match is more than a day out, and switches to a live\n// hour:minute:second clock on match day (under a day to kickoff). `withSeconds` is dropped under\n// reduced motion so the card never shows a seconds figure it will never refresh. Returns null once\n// kickoff has passed.\nfunction remainingSegments(kickoffUnix: number, nowMs: number, withSeconds: boolean): Segment[] | null {\n  const totalSeconds = Math.floor((kickoffUnix * 1000 - nowMs) / 1000)\n  if (totalSeconds <= 0) return null\n  const days = Math.floor(totalSeconds / 86_400)\n  const hours = Math.floor((totalSeconds % 86_400) / 3600)\n  const minutes = Math.floor((totalSeconds % 3600) / 60)\n  const seconds = totalSeconds % 60\n  const pad = (n: number) => String(n).padStart(2, '0')\n  if (days > 0) return [{ value: pad(days), unit: 'd' }, { value: pad(hours), unit: 'h' }]\n  const segs: Segment[] = [{ value: pad(hours), unit: 'h' }, { value: pad(minutes), unit: 'm' }]\n  if (withSeconds) segs.push({ value: pad(seconds), unit: 's' })\n  return segs\n}\n\nexport function CountdownCard({ card }: { card: CountdownCardData }): JSX.Element {\n  const { data } = card\n  // Unit labels are server-localized; the numbers are computed client-side.\n  const unitLabel: Record<UnitKind, string> = { d: data.daysUnit, h: data.hoursUnit, m: data.minutesUnit, s: data.secondsUnit }\n  const [nowMs, setNowMs] = useState(() => Date.now())\n  // Reduced motion is read once at mount: it decides whether the card ticks at all and whether it\n  // shows a (necessarily static, so potentially stale) seconds figure. Ticking is otherwise\n  // additive -- the segments computed at mount keep showing even if no interval ever fires.\n  const [reduced] = useState(\n    () => typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches,\n  )\n  const withinDay = data.kickoffUnix * 1000 - nowMs < DAY_MS\n  useEffect(() => {\n    if (reduced) return\n    const id = window.setInterval(() => setNowMs(Date.now()), withinDay ? 1000 : 60_000)\n    return () => window.clearInterval(id)\n  }, [reduced, withinDay])\n  const segments = remainingSegments(data.kickoffUnix, nowMs, withinDay && !reduced)\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-countdown\">\n      <div className=\"ss-w-fandash-countdown-top\">\n        <span className=\"ss-w-fandash-eyebrow\">{card.title ?? 'Kick-off in'}</span>\n        {segments ? (\n          <span className=\"ss-w-fandash-countdown-clock\">\n            {segments.map((s, i) => (\n              <Fragment key={s.unit}>\n                {i > 0 ? <span className=\"ss-w-fandash-countdown-colon\">:</span> : null}\n                <span className=\"ss-w-fandash-countdown-seg\">\n                  <span className=\"ss-w-fandash-countdown-value\">{s.value}</span>\n                  <span className=\"ss-w-fandash-countdown-unit\">{unitLabel[s.unit]}</span>\n                </span>\n              </Fragment>\n            ))}\n          </span>\n        ) : null}\n      </div>\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { InjuriesCard as InjuriesCardData, InjuryRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { Crest } from '../Crest'\n\nconst SHOWN = 3\n\nfunction ColHead({ name, crestUrl }: { name: string; crestUrl?: string | null }): JSX.Element {\n  return (\n    <span className=\"ss-w-fandash-injuries-col-head\">\n      <Crest url={crestUrl ?? undefined} name={name} kind=\"team\" />\n      <span className=\"ss-w-fandash-injuries-col-head-name\">{name}</span>\n    </span>\n  )\n}\n\nfunction InjuryList({ rows, emptyLabel, limit }: { rows: InjuryRow[]; emptyLabel: string; limit?: number }): JSX.Element {\n  if (rows.length === 0) return <span className=\"ss-w-fandash-injuries-empty\">{emptyLabel}</span>\n  const shown = limit === undefined ? rows : rows.slice(0, limit)\n  return (\n    <ul className=\"ss-w-fandash-injury-list\">\n      {shown.map((r, i) => (\n        <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-injury-row\">\n          <span className=\"ss-w-fandash-injury-name\">{r.playerName}</span>\n          <span className=\"ss-w-fandash-injury-meta\">\n            <span className=\"ss-w-fandash-injury-status\">{r.status}</span>\n            {r.injuryType ? <span className=\"ss-w-fandash-injury-type\">{r.injuryType}</span> : null}\n            {r.expectedReturnLabel ? <span className=\"ss-w-fandash-injury-return\">{r.expectedReturnLabel}</span> : null}\n          </span>\n        </li>\n      ))}\n    </ul>\n  )\n}\n\nexport function InjuriesCard({ card, ui }: { card: InjuriesCardData; ui?: UiConfig }): JSX.Element {\n  const { data } = card\n  const [expanded, setExpanded] = useState(false)\n  // Either side's list can be long; a shared toggle collapses both to SHOWN and reveals the rest,\n  // so the card doesn't push the input off-screen. The count is how many are hidden across both sides.\n  const hidden = Math.max(0, data.ours.length - SHOWN) + Math.max(0, data.theirs.length - SHOWN)\n  const limit = expanded ? undefined : SHOWN\n  const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n  const showLess = ui?.showLess ?? 'Show less'\n  // \"Ours\" is club-vs-opponent, not home-vs-away — reorder into home/away columns so the card\n  // reads left-to-right like the rest of the dashboard regardless of which side the club is on.\n  const homeCol = data.oursIsHome\n    ? { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n    : { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n  const awayCol = data.oursIsHome\n    ? { name: data.theirsName, crest: data.theirsCrestUrl, rows: data.theirs }\n    : { name: data.oursName, crest: data.oursCrestUrl, rows: data.ours }\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-injuries\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-injuries-cols\">\n        <div className=\"ss-w-fandash-injuries-col\">\n          <ColHead name={homeCol.name} crestUrl={homeCol.crest} />\n          <InjuryList rows={homeCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n        </div>\n        <div className=\"ss-w-fandash-injuries-divider\" />\n        <div className=\"ss-w-fandash-injuries-col\">\n          <ColHead name={awayCol.name} crestUrl={awayCol.crest} />\n          <InjuryList rows={awayCol.rows} emptyLabel={data.emptyLabel} limit={limit} />\n        </div>\n      </div>\n      {hidden > 0 ? (\n        <button\n          type=\"button\"\n          className=\"ss-w-fandash-injuries-more\"\n          aria-expanded={expanded}\n          onClick={() => setExpanded((v) => !v)}\n        >\n          {expanded ? showLess : showMore(hidden)}\n        </button>\n      ) : null}\n    </div>\n  )\n}\n","import type { ReasonToBetCard as ReasonToBetCardData } from '@sensiblestats/widget-sdk'\n\nexport function ReasonToBetCard({ card }: { card: ReasonToBetCardData }): JSX.Element {\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-reasons\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <ul className=\"ss-w-fandash-reason-list\">\n        {card.data.angles.map((angle, i) => (\n          <li key={`${angle}-${i}`} className=\"ss-w-fandash-reason-item\">{angle}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n","import type { WhereToWatchCard as WhereToWatchCardData } from '@sensiblestats/widget-sdk'\n\nexport function WhereToWatchCard({ card }: { card: WhereToWatchCardData }): JSX.Element {\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-watch\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <span className=\"ss-w-fandash-stations\">\n        {card.data.stations.map((station, i) => (\n          <span key={`${station}-${i}`} className=\"ss-w-fandash-station-chip\">{station}</span>\n        ))}\n      </span>\n    </div>\n  )\n}\n","import type { CongestedWeekCard as CongestedWeekCardData } from '@sensiblestats/widget-sdk'\n\nexport function CongestedWeekCard({ card, onTap }: { card: CongestedWeekCardData; onTap: (card: CongestedWeekCardData) => void }): JSX.Element {\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-congested\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-congested-grid\">\n        {card.data.entries.map((entry, i) => (\n          <span key={`${entry.opponent}-${i}`} className=\"ss-w-fandash-congested-cell\">\n            <span className=\"ss-w-fandash-congested-day\">{entry.dayLabel}</span>\n            <span className=\"ss-w-fandash-congested-opponent\">{entry.opponent}</span>\n            <span className=\"ss-w-fandash-congested-comp\">{entry.competition}</span>\n            <span className=\"ss-w-fandash-congested-time\">{entry.timeLabel}</span>\n          </span>\n        ))}\n      </div>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { TransfersCard as TransfersCardData, TransferRow } from '@sensiblestats/widget-sdk'\n\nfunction TransferList({ rows }: { rows: TransferRow[] }): JSX.Element {\n  if (rows.length === 0) return <span className=\"ss-w-fandash-transfers-empty\">None</span>\n  return (\n    <ul className=\"ss-w-fandash-transfer-list\">\n      {rows.map((r, i) => (\n        <li key={`${r.playerName}-${i}`} className=\"ss-w-fandash-transfer-row\">\n          <span className=\"ss-w-fandash-transfer-name\">{r.playerName}</span>\n          <span className=\"ss-w-fandash-transfer-club\">{r.otherClub}</span>\n          {r.type ? <span className=\"ss-w-fandash-transfer-type\">{r.type}</span> : null}\n        </li>\n      ))}\n    </ul>\n  )\n}\n\nexport function TransfersCard({ card }: { card: TransfersCardData }): JSX.Element {\n  const { data } = card\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-transfers\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-transfers-cols\">\n        <div className=\"ss-w-fandash-transfers-col\">\n          <span className=\"ss-w-fandash-transfers-col-head\">In</span>\n          <TransferList rows={data.in} />\n        </div>\n        <div className=\"ss-w-fandash-transfers-col\">\n          <span className=\"ss-w-fandash-transfers-col-head\">Out</span>\n          <TransferList rows={data.out} />\n        </div>\n      </div>\n    </div>\n  )\n}\n","import type { LinksCard as LinksCardData } from '@sensiblestats/widget-sdk'\nimport { ChevronIcon } from '../Icons'\n\nexport function LinksCard({ card }: { card: LinksCardData }): JSX.Element {\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-links\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-link-grid\">\n        {card.data.links.map((link, i) => (\n          <a key={`${link.url}-${i}`} className=\"ss-w-fandash-link-tile\" href={link.url} target=\"_blank\" rel=\"noopener noreferrer\">\n            <span className=\"ss-w-fandash-link-label\">{link.label}</span>\n            <span className=\"ss-w-fandash-link-chevron\"><ChevronIcon /></span>\n          </a>\n        ))}\n      </div>\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { PostMatchResultCard as PostMatchResultCardData } from '@sensiblestats/widget-sdk'\n\nfunction initials(name: string): string {\n  return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Same img-with-fallback treatment as LiveScoreCard's LiveCrest -- a broken/absent URL falls back\n// to a coloured initials chip, which a background-image span can't detect on its own.\nfunction PostMatchCrest({\n  url,\n  name,\n  side,\n}: {\n  url?: string | null\n  name: string\n  side: 'home' | 'away'\n}): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  const cls = `ss-w-fandash-postmatch-crest ss-w-fandash-postmatch-crest--${side}`\n  if (url && !failed) {\n    return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n  }\n  return (\n    <span className={`${cls} ss-w-fandash-postmatch-crest--fallback`} aria-hidden=\"true\">\n      {initials(name)}\n    </span>\n  )\n}\n\n// [data] card -- the full-time scoreboard. No tap target: the score itself is the payload, and\n// the goals/stats/top-performer cards below carry the actionRef taps for this match.\nexport function PostMatchResultCard({ card }: { card: PostMatchResultCardData }): JSX.Element {\n  const { data } = card\n  const homeWon = data.homeScore >= data.awayScore\n  const awayWon = data.awayScore >= data.homeScore\n\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-result\">\n      <div className=\"ss-w-fandash-postmatch-top\">\n        {/* card.title carries the server-localized \"Full time\" label -- reused as the pill text\n            rather than a hardcoded English literal. */}\n        {card.title ? <span className=\"ss-w-fandash-postmatch-pill\">{card.title}</span> : null}\n        <span className={`ss-w-fandash-postmatch-tag ss-w-fandash-postmatch-tag--${data.outcome}`}>\n          {data.resultLabel}\n        </span>\n      </div>\n      <div className=\"ss-w-fandash-postmatch-main\">\n        <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--home\">\n          <PostMatchCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n          <span className=\"ss-w-fandash-postmatch-team-name\">{data.homeName}</span>\n        </div>\n        <div className=\"ss-w-fandash-postmatch-score-main\">\n          <span\n            className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${homeWon ? 'win' : 'lose'}`}\n          >\n            {data.homeScore}\n          </span>\n          <span className=\"ss-w-fandash-postmatch-score-sep\">–</span>\n          <span\n            className={`ss-w-fandash-postmatch-score-value ss-w-fandash-postmatch-score-value--${awayWon ? 'win' : 'lose'}`}\n          >\n            {data.awayScore}\n          </span>\n        </div>\n        <div className=\"ss-w-fandash-postmatch-side ss-w-fandash-postmatch-side--away\">\n          <PostMatchCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n          <span className=\"ss-w-fandash-postmatch-team-name\">{data.awayName}</span>\n        </div>\n      </div>\n      <div className=\"ss-w-fandash-postmatch-meta\">\n        {data.kickoffLabel}\n        {data.competition ? ` · ${data.competition}` : ''}\n      </div>\n    </div>\n  )\n}\n","import type { PostMatchGoalsCard as PostMatchGoalsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see FixtureCard/CongestedWeekCard).\nexport function PostMatchGoalsCard({ card, onTap }: {\n  card: PostMatchGoalsCardData\n  onTap: (card: PostMatchGoalsCardData) => void\n}): JSX.Element {\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-goals\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <ul className=\"ss-w-fandash-postmatch-goal-list\">\n        {card.data.goals.map((g, i) => (\n          <li key={`${g.text}-${i}`} className={g.scoredByClub ? 'ss-w-fandash-postmatch-goal ss-w-fandash-postmatch-goal--club' : 'ss-w-fandash-postmatch-goal'}>\n            <span className=\"ss-w-fandash-postmatch-goal-ball\" />\n            <span>{g.text}</span>\n          </li>\n        ))}\n      </ul>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { PostMatchStatsCard as PostMatchStatsCardData } from '@sensiblestats/widget-sdk'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width. Mirrors LiveStatsCard's splitWidths.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n  const total = homeNum + awayNum\n  if (total <= 0) return { home: '50%', away: '50%' }\n  const homePct = Math.round((homeNum / total) * 1000) / 10\n  return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function PostMatchStatsCard({ card, onTap }: {\n  card: PostMatchStatsCardData\n  onTap: (card: PostMatchStatsCardData) => void\n}): JSX.Element {\n  const { data } = card\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-stats\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-postmatch-stat-rows\">\n        {data.rows.map((r, i) => {\n          // Row values are club-first, but the result card above renders home-left/away-right, so\n          // orient by venue: the home team's value on the left, the away team's on the right. When\n          // the club is the away side, that means the club's value is the RIGHT column.\n          const leftValue = data.clubIsHome ? r.clubValue : r.oppValue\n          const rightValue = data.clubIsHome ? r.oppValue : r.clubValue\n          const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n          const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n          const { home, away } = splitWidths(homeNum, awayNum)\n          return (\n            <div key={`${r.label}-${i}`} className=\"ss-w-fandash-postmatch-stat\">\n              <div className=\"ss-w-fandash-postmatch-stat-row\">\n                <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--home\">{leftValue}</span>\n                <span className=\"ss-w-fandash-postmatch-stat-label\">{r.label}</span>\n                <span className=\"ss-w-fandash-postmatch-stat-value ss-w-fandash-postmatch-stat-value--away\">{rightValue}</span>\n              </div>\n              <div className=\"ss-w-fandash-postmatch-stat-bar\">\n                <span className=\"ss-w-fandash-postmatch-stat-bar-home\" style={{ width: home }} />\n                <span className=\"ss-w-fandash-postmatch-stat-bar-away\" style={{ width: away }} />\n              </div>\n            </div>\n          )\n        })}\n      </div>\n      {data.rows.length > 0 ? (\n        <div className=\"ss-w-fandash-postmatch-legend\">\n          <span className=\"ss-w-fandash-postmatch-legend-item\">\n            <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--home\" />\n            {data.homeName}\n          </span>\n          <span className=\"ss-w-fandash-postmatch-legend-item\">\n            <i className=\"ss-w-fandash-postmatch-legend-swatch ss-w-fandash-postmatch-legend-swatch--away\" />\n            {data.awayName}\n          </span>\n        </div>\n      ) : null}\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { PostMatchTopPerformerCard as PostMatchTopPerformerCardData } from '@sensiblestats/widget-sdk'\n\n// First letter of the first and last word (a single-word name yields just that one letter, since\n// first === last); whitespace/empty falls back to \"?\" rather than rendering a blank avatar.\nfunction initials(playerName: string): string {\n  const words = playerName.trim().split(/\\s+/).filter(Boolean)\n  if (words.length === 0) return '?'\n  const first = words[0]!.charAt(0)\n  const last = words[words.length - 1]!.charAt(0)\n  return (words.length > 1 ? `${first}${last}` : first).toUpperCase()\n}\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard. Full mockup treatment:\n// gradient initials avatar + name + a prominent rating chip. No \"2 goals\" sub-line -- there's no\n// data for it.\nexport function PostMatchTopPerformerCard({ card, onTap }: {\n  card: PostMatchTopPerformerCardData\n  onTap: (card: PostMatchTopPerformerCardData) => void\n}): JSX.Element {\n  const { data } = card\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-postmatch-performer\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-postmatch-perf-row\">\n        <span className=\"ss-w-fandash-postmatch-perf-avatar\" aria-hidden=\"true\">{initials(data.playerName)}</span>\n        <span className=\"ss-w-fandash-postmatch-perf-name\">{data.playerName}</span>\n        <span className=\"ss-w-fandash-postmatch-perf-rating\">{data.ratingLabel}</span>\n      </div>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { PostMatchNextCard as PostMatchNextCardData } from '@sensiblestats/widget-sdk'\n\n// [data] card -- the upcoming fixture teaser that follows a post-match dashboard. No tap target.\n// v1 (modest): whenLabel is already a complete localized phrase composed server-side -- it\n// includes the opponent, venue and kickoff time (EN \"vs Bournemouth (H) · Sat 12 Sep · 15:00\",\n// TR \"İç sahada Bournemouth · ...\"). Rendering opponentName alongside it would duplicate the\n// opponent, so this card shows only whenLabel, dressed up with an accent rule rather than a second\n// line. The richer opponent-headline + venue chip + crest layout needs a server field split\n// (opponent vs venue vs time as separate fields) and is deferred.\nexport function PostMatchNextCard({ card }: { card: PostMatchNextCardData }): JSX.Element {\n  const { data } = card\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-postmatch-next\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-postmatch-next-row\">\n        <span className=\"ss-w-fandash-postmatch-next-when\">{data.whenLabel}</span>\n      </div>\n    </div>\n  )\n}\n","import type { RestingNextCard as RestingNextCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- tapping sends actionLabel as a follow-up message, carrying the opaque\n// actionRef so the server resolves the pre-issued binding (see PostMatchGoalsCard/FixtureCard).\nexport function RestingNextCard({ card, onTap }: {\n  card: RestingNextCardData\n  onTap: (card: RestingNextCardData) => void\n}): JSX.Element {\n  const { data } = card\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-next\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-resting-next-row\">\n        <span className=\"ss-w-fandash-resting-next-when\">{data.whenLabel}</span>\n        {data.competition ? <span className=\"ss-w-fandash-resting-next-competition\">{data.competition}</span> : null}\n      </div>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { RestingStandingsCard as RestingStandingsCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingStandingsCard({ card, onTap }: {\n  card: RestingStandingsCardData\n  onTap: (card: RestingStandingsCardData) => void\n}): JSX.Element {\n  const { data } = card\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-standings\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-resting-standings-row\">\n        <span className=\"ss-w-fandash-resting-standings-position\">{data.positionLabel}</span>\n        <span className=\"ss-w-fandash-resting-standings-record\">{data.recordLabel}</span>\n      </div>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { RestingSeasonCard as RestingSeasonCardData } from '@sensiblestats/widget-sdk'\n\n// [prefill] card -- same tap wiring as PostMatchGoalsCard/FixtureCard.\nexport function RestingSeasonCard({ card, onTap }: {\n  card: RestingSeasonCardData\n  onTap: (card: RestingSeasonCardData) => void\n}): JSX.Element {\n  const { data } = card\n  return (\n    <button type=\"button\" className=\"ss-w-fandash-card ss-w-fandash-card--tap ss-w-fandash-resting-season\" onClick={() => onTap(card)}>\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-resting-season-rows\">\n        {data.scorerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.scorerLabel}</span> : null}\n        {data.playerLabel ? <span className=\"ss-w-fandash-resting-season-row\">{data.playerLabel}</span> : null}\n        <span className=\"ss-w-fandash-resting-season-row\">{data.tallyLabel}</span>\n      </div>\n      <span className=\"ss-w-fandash-card-cta\">{card.actionLabel}</span>\n    </button>\n  )\n}\n","import type { RestingFormCard as RestingFormCardData } from '@sensiblestats/widget-sdk'\n\nfunction resultClass(result: string): string {\n  const upper = result.toUpperCase()\n  if (upper === 'W') return 'ss-w-fandash-form-pill--win'\n  if (upper === 'L') return 'ss-w-fandash-form-pill--loss'\n  return 'ss-w-fandash-form-pill--draw'\n}\n\n// [data] card -- recent form as one styled W/D/L pill per letter (same pill classes as the\n// fixture card's last-five strip). No tap target.\nexport function RestingFormCard({ card }: { card: RestingFormCardData }): JSX.Element {\n  const { data } = card\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-resting-form\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <span className=\"ss-w-fandash-form\">\n        {data.letters.map((r, i) => (\n          <span key={`${r}-${i}`} className={`ss-w-fandash-form-pill ${resultClass(r)}`}>{r}</span>\n        ))}\n      </span>\n    </div>\n  )\n}\n","import { useRef, useState } from 'react'\nimport type { LiveScoreCard as LiveScoreCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport { useLiveClock } from '../../useLiveClock'\n\nfunction initials(name: string): string {\n  return name.trim().slice(0, 3).toUpperCase()\n}\n\n// Crest is an <img> so a broken/absent URL falls back to a coloured initials chip -- the design\n// wants the chip whenever the crest is missing OR fails to load, which a background-image span\n// can't detect on its own.\nfunction LiveCrest({ url, name, side }: { url?: string | null; name: string; side: 'home' | 'away' }): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  const cls = `ss-w-fandash-live-crest ss-w-fandash-live-crest--${side}`\n  if (url && !failed) {\n    return <img className={cls} src={url} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n  }\n  return (\n    <span className={`${cls} ss-w-fandash-live-crest--fallback`} aria-hidden=\"true\">\n      {initials(name)}\n    </span>\n  )\n}\n\n// Splits the goal events the parent filtered out of the live timeline into \"Salah 6', Núñez 9'\"\n// lines per side, oldest first, so each scorer renders under the team that actually scored\n// rather than always on one fixed side. Events with no player name are dropped rather than\n// rendered blank; a side with nothing to show gets null.\nfunction scorersBySide(goalEvents: LiveEventLine[] | undefined): { home: string | null; away: string | null } {\n  if (!goalEvents || goalEvents.length === 0) return { home: null, away: null }\n  // Defensive: only ever render actual goals, even if a caller passes an unfiltered event list.\n  const named = goalEvents.filter((e) => e.type === 'goal' && e.player)\n  const line = (side: 'home' | 'away'): string | null => {\n    const scorers = named\n      .filter((e) => e.side === side)\n      .slice()\n      .sort((a, b) => a.minute - b.minute)\n      .map((e) => `${e.player} ${e.minuteLabel}`)\n    return scorers.length === 0 ? null : scorers.join(', ')\n  }\n  return { home: line('home'), away: line('away') }\n}\n\n// [data] card -- the in-play scoreboard. No tap target: the live score itself is the payload,\n// and the timeline/stats cards below carry the rest of the in-play picture.\nexport function LiveScoreCard({\n  card,\n  goalEvents,\n}: {\n  card: LiveScoreCardData\n  goalEvents?: LiveEventLine[]\n}): JSX.Element {\n  const { data } = card\n\n  // The reducer replaces the card object on every ~60s poll, so seeding the live-clock hook with\n  // `Date.now()` on every render would restart its elapsed-time math each time and the minute\n  // would never tick between polls. Reseed only when the server minute or score actually changes.\n  const seedKey = `${data.minute}:${data.homeScore}:${data.awayScore}`\n  const seedRef = useRef<{ key: string; receivedAtMs: number } | null>(null)\n  if (!seedRef.current || seedRef.current.key !== seedKey) {\n    seedRef.current = { key: seedKey, receivedAtMs: Date.now() }\n  }\n\n  const displayMinute = useLiveClock(data.minute, data.clockRunning, seedRef.current.receivedAtMs)\n  const minuteSuffix = data.minuteLabel.replace(/^\\d+/, '')\n  const { home: homeScorers, away: awayScorers } = scorersBySide(goalEvents)\n\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-live-score\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-live-top\">\n        <span className=\"ss-w-fandash-live-pill\">\n          <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n          {data.statusLabel}\n        </span>\n        <span className=\"ss-w-fandash-live-minute\">{`${displayMinute}${minuteSuffix}`}</span>\n        {data.competition ? <span className=\"ss-w-fandash-live-competition\">{data.competition}</span> : null}\n      </div>\n      <div className=\"ss-w-fandash-live-main\">\n        <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--home\">\n          <LiveCrest url={data.homeCrestUrl} name={data.homeName} side=\"home\" />\n          <span className=\"ss-w-fandash-live-team-name\">{data.homeName}</span>\n        </div>\n        <div className=\"ss-w-fandash-live-score-main\">\n          <span className=\"ss-w-fandash-live-score-value\">{data.homeScore}</span>\n          <span className=\"ss-w-fandash-live-score-sep\">–</span>\n          <span className=\"ss-w-fandash-live-score-value\">{data.awayScore}</span>\n        </div>\n        <div className=\"ss-w-fandash-live-side ss-w-fandash-live-side--away\">\n          <LiveCrest url={data.awayCrestUrl} name={data.awayName} side=\"away\" />\n          <span className=\"ss-w-fandash-live-team-name\">{data.awayName}</span>\n        </div>\n      </div>\n      {homeScorers || awayScorers ? (\n        <div className=\"ss-w-fandash-live-scorers-row\">\n          <div className=\"ss-w-fandash-live-scorers ss-w-fandash-live-scorers--home\">\n            {homeScorers ? (\n              <>\n                <span className=\"ss-w-fandash-live-scorers-icon\" aria-hidden=\"true\">\n                  ⚽\n                </span>\n                {homeScorers}\n              </>\n            ) : null}\n          </div>\n          <div className=\"ss-w-fandash-live-scorers ss-w-fandash-live-scorers--away\">\n            {awayScorers ? (\n              <>\n                {awayScorers}\n                <span className=\"ss-w-fandash-live-scorers-icon\" aria-hidden=\"true\">\n                  ⚽\n                </span>\n              </>\n            ) : null}\n          </div>\n        </div>\n      ) : null}\n    </div>\n  )\n}\n","import { useEffect, useState } from 'react'\n\nconst TICK_MS = 60_000\n// Generous stoppage-time headroom. The server clamps 2H to 105; if a live poll never\n// delivers a \"Finished\" transition (resolver drops the match before that lands), a stuck\n// clockRunning:true must hold here instead of climbing forever.\nconst MAX_LIVE_TICK_MINUTES = 15\n\nfunction computeDisplayMinute(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n  if (!clockRunning) return minute\n  const elapsedMinutes = Math.floor((Date.now() - receivedAtMs) / TICK_MS)\n  return minute + Math.min(Math.max(0, elapsedMinutes), MAX_LIVE_TICK_MINUTES)\n}\n\n// Ticks a live match minute forward once per real minute between server polls, so the\n// clock doesn't look frozen during the 60s gap. Reseeds immediately whenever `minute` or\n// `receivedAtMs` changes (a fresh poll), rather than waiting for the next interval tick.\nexport function useLiveClock(minute: number, clockRunning: boolean, receivedAtMs: number): number {\n  const [displayMinute, setDisplayMinute] = useState(() =>\n    computeDisplayMinute(minute, clockRunning, receivedAtMs),\n  )\n\n  useEffect(() => {\n    setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n\n    if (!clockRunning) return\n\n    const id = window.setInterval(() => {\n      setDisplayMinute(computeDisplayMinute(minute, clockRunning, receivedAtMs))\n    }, TICK_MS)\n\n    return () => window.clearInterval(id)\n  }, [minute, clockRunning, receivedAtMs])\n\n  return displayMinute\n}\n","import { useState } from 'react'\nimport type { LiveTimelineCard as LiveTimelineCardData, LiveEventLine } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\n\nconst SHOWN = 3\n\n// Per-type icon: a ball mark for goals, a coloured card rectangle for yellow/red, up/down\n// arrows for a substitution. An unrecognised type (forward-compat with the server's union)\n// renders a neutral dot rather than nothing, so a new event type never looks broken.\nfunction EventIcon({ type }: { type: LiveEventLine['type'] }): JSX.Element {\n  if (type === 'goal') {\n    return (\n      <span className=\"ss-w-fandash-live-tl-ico ss-w-fandash-live-tl-ico--goal\" aria-hidden=\"true\">\n        <span className=\"ss-w-fandash-live-tl-ball\" />\n      </span>\n    )\n  }\n  if (type === 'yellow' || type === 'red') {\n    return (\n      <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n        <span className={`ss-w-fandash-live-tl-card ss-w-fandash-live-tl-card--${type}`} />\n      </span>\n    )\n  }\n  if (type === 'sub') {\n    return (\n      <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\">\n        <span className=\"ss-w-fandash-live-tl-subarrows\">⇅</span>\n      </span>\n    )\n  }\n  return <span className=\"ss-w-fandash-live-tl-ico\" aria-hidden=\"true\"><span className=\"ss-w-fandash-live-tl-dot\" /></span>\n}\n\n// Sub events name both players; the \"for {playerOff}\" half only renders when the server sent\n// it, and everything falls back to the server's plain text if a name field is missing.\nfunction EventLabel({ e }: { e: LiveEventLine }): JSX.Element {\n  if (e.type === 'sub') {\n    return (\n      <span className=\"ss-w-fandash-live-tl-who\">\n        {e.player ?? e.text}\n        {e.playerOff ? <span className=\"ss-w-fandash-live-tl-off\"> for {e.playerOff}</span> : null}\n      </span>\n    )\n  }\n  return <span className=\"ss-w-fandash-live-tl-who\">{e.player ?? e.text}</span>\n}\n\nfunction EventRow({ e }: { e: LiveEventLine }): JSX.Element {\n  const cls = [\n    'ss-w-fandash-live-tl-ev',\n    e.side === 'home' ? 'ss-w-fandash-live-tl-ev--home' : 'ss-w-fandash-live-tl-ev--away',\n    e.type === 'goal' ? 'ss-w-fandash-live-tl-ev--goal' : '',\n  ]\n    .filter(Boolean)\n    .join(' ')\n  return (\n    <div className={cls}>\n      <span className=\"ss-w-fandash-live-tl-txt\">\n        <EventLabel e={e} />\n        <EventIcon type={e.type} />\n      </span>\n      <span className=\"ss-w-fandash-live-tl-badge\">{e.minuteLabel}</span>\n    </div>\n  )\n}\n\n// [data] card -- the in-play event feed as a compact two-sided timeline down a centre spine:\n// each club's events sit on its own side, most-recent 3 shown with a \"See more\" toggle for the\n// rest. No tap target.\nexport function LiveTimelineCard({ card, ui }: { card: LiveTimelineCardData; ui?: UiConfig }): JSX.Element | null {\n  const [expanded, setExpanded] = useState(false)\n  const events = card.data.events\n  if (!events || events.length === 0) return null\n\n  const sorted = [...events].sort((a, b) => b.minute - a.minute)\n  const rest = sorted.length - SHOWN\n  const shown = expanded ? sorted : sorted.slice(0, SHOWN)\n\n  const showMore = ui?.showMore ?? ((n: number) => `Show ${n} more`)\n  const showLess = ui?.showLess ?? 'Show less'\n\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-live-timeline\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-live-tl\">\n        {shown.map((e, i) => (\n          <EventRow key={`${e.minute}-${e.side}-${e.type}-${i}`} e={e} />\n        ))}\n      </div>\n      {rest > 0 ? (\n        <button\n          type=\"button\"\n          className=\"ss-w-fandash-live-tl-more\"\n          aria-expanded={expanded}\n          onClick={() => setExpanded((v) => !v)}\n        >\n          {expanded ? showLess : showMore(rest)}\n        </button>\n      ) : null}\n    </div>\n  )\n}\n","import { useId } from 'react'\nimport type { LiveStatsData } from '@sensiblestats/widget-sdk'\n\n// widget-sdk's events.ts defines `MomentumPoint` but its barrel (index.ts) never re-exports it on\n// its own -- only as the element type of `LiveStatsData.momentum`. Indexing off that field avoids\n// widening this task's scope to a widget-sdk barrel edit for a type alias.\ntype MomentumPoint = LiveStatsData['momentum'][number]\n\nconst WIDTH = 270\nconst HEIGHT = 56\nconst BASELINE = HEIGHT / 2 // mid-height, matches the mockup's BASE=28 for H=56\nconst SCALE = 0.26 // value ±100 -> ±26px around the baseline, same as the mockup\n\nfunction buildPaths(\n  points: MomentumPoint[],\n): { area: string; line: string; lastLeftPct: number; lastTopPx: number } {\n  const lastIndex = points.length - 1\n  const px = (i: number): number => (lastIndex === 0 ? 0 : (i / lastIndex) * WIDTH)\n  const py = (v: number): number => BASELINE - v * SCALE\n  const linePts = points.map((p, i) => `${px(i).toFixed(1)},${py(p.value).toFixed(1)}`)\n  const area = `M0,${BASELINE} L${linePts.join(' L')} L${WIDTH},${BASELINE} Z`\n  const line = `M${linePts.join(' L')}`\n  // The caller (MomentumWave) already returns null for an empty series, so lastIndex is always a\n  // valid index here -- the `?? 0` only satisfies noUncheckedIndexedAccess, it never triggers.\n  const lastValue = points[lastIndex]?.value ?? 0\n  // The marker is an HTML overlay positioned by PERCENT of width (so it survives the SVG's\n  // preserveAspectRatio=\"none\" scaling undistorted) -- always 0 for a single point, always 100 for\n  // the last of more than one, matching px()'s own 0..WIDTH mapping.\n  const lastLeftPct = lastIndex === 0 ? 0 : 100\n  return { area, line, lastLeftPct, lastTopPx: py(lastValue) }\n}\n\n// [data] momentum wave -- no tap target. `value` is club-positive (clubPressure - oppPressure),\n// but colour follows VENUE, not club, to stay consistent with the score/timeline cards: the club's\n// own colour is --ss-w-home when `clubIsHome`, --ss-w-away otherwise. So a club-positive swing (up,\n// above the baseline) is filled with the club's venue colour, and an opponent-positive swing (down)\n// with the opponent's venue colour -- top/bottom are NOT fixed to home/away, they flip with\n// `clubIsHome` so the same team is always the same colour across every live card.\nexport function MomentumWave({\n  points,\n  caption,\n  clubIsHome,\n}: {\n  points: MomentumPoint[]\n  caption?: string | null\n  clubIsHome: boolean\n}): JSX.Element | null {\n  if (points.length === 0) return null\n\n  const { area, line, lastLeftPct, lastTopPx } = buildPaths(points)\n  const clipId = useId()\n  const topClipId = `${clipId}-top`\n  const bottomClipId = `${clipId}-bottom`\n  const topClass = clubIsHome ? 'ss-w-fandash-live-mom-home' : 'ss-w-fandash-live-mom-away'\n  const bottomClass = clubIsHome ? 'ss-w-fandash-live-mom-away' : 'ss-w-fandash-live-mom-home'\n\n  return (\n    <div className=\"ss-w-fandash-live-mom\">\n      {caption ? <span className=\"ss-w-fandash-live-mom-caption\">{caption}</span> : null}\n      <div className=\"ss-w-fandash-live-mom-plot\">\n        <svg\n          className=\"ss-w-fandash-live-mom-svg\"\n          viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n          preserveAspectRatio=\"none\"\n          role=\"img\"\n          aria-label={caption ?? 'Momentum'}\n        >\n          <defs>\n            <clipPath id={topClipId}>\n              <rect x={0} y={0} width={WIDTH} height={BASELINE} />\n            </clipPath>\n            <clipPath id={bottomClipId}>\n              <rect x={0} y={BASELINE} width={WIDTH} height={HEIGHT - BASELINE} />\n            </clipPath>\n          </defs>\n          <path d={area} className={topClass} clipPath={`url(#${topClipId})`} />\n          <path d={area} className={bottomClass} clipPath={`url(#${bottomClipId})`} />\n          <line x1={0} y1={BASELINE} x2={WIDTH} y2={BASELINE} className=\"ss-w-fandash-live-mom-base\" />\n          <path d={line} className=\"ss-w-fandash-live-mom-line\" vectorEffect=\"non-scaling-stroke\" />\n        </svg>\n        {/* HTML overlay dot, not an SVG <circle> -- the SVG's preserveAspectRatio=\"none\" stretches\n            non-uniform scaling into an oval, and at x=WIDTH half of a circle hangs off the edge.\n            An HTML element can't be deformed by the SVG's viewBox scaling, and clamp() keeps it\n            fully inside the plot at both ends. */}\n        <span\n          className=\"ss-w-fandash-live-mom-now\"\n          style={{ left: `clamp(4px, ${lastLeftPct}%, calc(100% - 4px))`, top: `${lastTopPx}px` }}\n          aria-hidden=\"true\"\n        />\n      </div>\n    </div>\n  )\n}\n","import type { LiveStatsCard as LiveStatsCardData } from '@sensiblestats/widget-sdk'\nimport { MomentumWave } from './MomentumWave'\n\n// Split-bar widths as percentages, rounded to 1dp so the rendered width string stays short and\n// stable in tests. Guarded for the 0/0 case (or any non-positive total) -- an even 50/50 split\n// rather than a NaN width, since a stat can legitimately be 0-0 early in a match.\nfunction splitWidths(homeNum: number, awayNum: number): { home: string; away: string } {\n  const total = homeNum + awayNum\n  if (total <= 0) return { home: '50%', away: '50%' }\n  const homePct = Math.round((homeNum / total) * 1000) / 10\n  return { home: `${homePct}%`, away: `${Math.round((100 - homePct) * 10) / 10}%` }\n}\n\n// [data] card -- in-play match stats, home value / stat label / away value per row, each backed\n// by a home/away split bar, plus an optional momentum wave (or its text fallback). No tap target.\n//\n// LiveStatRow itself only carries clubNum/oppNum (club vs opponent), but LiveStatsData now also\n// carries `clubIsHome`/`homeName`/`awayName` (mirroring the venue signal LiveScoreCard already\n// has and the ClubIsHome pattern on RestingNextData/PostMatchNextData) -- so this card orients by\n// VENUE, not by club, to stay colour-consistent with the score and timeline cards: home is always\n// --ss-w-home on the left, away is always --ss-w-away on the right, and clubNum/oppNum are placed\n// on whichever side `clubIsHome` says the club actually occupies this match.\nexport function LiveStatsCard({ card }: { card: LiveStatsCardData }): JSX.Element {\n  const { data } = card\n  return (\n    <div className=\"ss-w-fandash-card ss-w-fandash-live-stats\">\n      {card.title ? <span className=\"ss-w-fandash-eyebrow\">{card.title}</span> : null}\n      <div className=\"ss-w-fandash-live-stat-rows\">\n        {data.rows.map((r, i) => {\n          const homeValue = data.clubIsHome ? r.clubValue : r.oppValue\n          const awayValue = data.clubIsHome ? r.oppValue : r.clubValue\n          const homeNum = data.clubIsHome ? r.clubNum : r.oppNum\n          const awayNum = data.clubIsHome ? r.oppNum : r.clubNum\n          const { home, away } = splitWidths(homeNum, awayNum)\n          return (\n            <div key={`${r.label}-${i}`} className=\"ss-w-fandash-live-stat\">\n              <div className=\"ss-w-fandash-live-stat-row\">\n                <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--home\">{homeValue}</span>\n                <span className=\"ss-w-fandash-live-stat-label\">{r.label}</span>\n                <span className=\"ss-w-fandash-live-stat-value ss-w-fandash-live-stat-value--away\">{awayValue}</span>\n              </div>\n              <div className=\"ss-w-fandash-live-bar\">\n                <span className=\"ss-w-fandash-live-bar-home\" style={{ width: home }} />\n                <span className=\"ss-w-fandash-live-bar-away\" style={{ width: away }} />\n              </div>\n            </div>\n          )\n        })}\n      </div>\n      {data.momentum.length > 0 ? (\n        <MomentumWave points={data.momentum} caption={data.momentumLabel} clubIsHome={data.clubIsHome} />\n      ) : data.momentumLabel ? (\n        <span className=\"ss-w-fandash-live-momentum\">{data.momentumLabel}</span>\n      ) : null}\n      {data.rows.length > 0 ? (\n        <div className=\"ss-w-fandash-live-legend\">\n          <span className=\"ss-w-fandash-live-legend-item\">\n            <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--home\" />\n            {data.homeName}\n          </span>\n          <span className=\"ss-w-fandash-live-legend-item\">\n            <i className=\"ss-w-fandash-live-legend-swatch ss-w-fandash-live-legend-swatch--away\" />\n            {data.awayName}\n          </span>\n        </div>\n      ) : null}\n    </div>\n  )\n}\n","import type {\n  ClubFanDashboardCard,\n  ClubFanDashboardPayload,\n  CongestedWeekCard as CongestedWeekCardData,\n  LiveEventLine,\n  LiveTimelineCard as LiveTimelineCardData,\n  PostMatchGoalsCard as PostMatchGoalsCardData,\n  PostMatchStatsCard as PostMatchStatsCardData,\n  PostMatchTopPerformerCard as PostMatchTopPerformerCardData,\n  RestingNextCard as RestingNextCardData,\n  RestingStandingsCard as RestingStandingsCardData,\n  RestingSeasonCard as RestingSeasonCardData,\n} from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../../config'\nimport { FixtureCard } from './FixtureCard'\nimport { CountdownCard } from './CountdownCard'\nimport { InjuriesCard } from './InjuriesCard'\nimport { ReasonToBetCard } from './ReasonToBetCard'\nimport { WhereToWatchCard } from './WhereToWatchCard'\nimport { CongestedWeekCard } from './CongestedWeekCard'\nimport { TransfersCard } from './TransfersCard'\nimport { LinksCard } from './LinksCard'\nimport { PostMatchResultCard } from './PostMatchResultCard'\nimport { PostMatchGoalsCard } from './PostMatchGoalsCard'\nimport { PostMatchStatsCard } from './PostMatchStatsCard'\nimport { PostMatchTopPerformerCard } from './PostMatchTopPerformerCard'\nimport { PostMatchNextCard } from './PostMatchNextCard'\nimport { RestingNextCard } from './RestingNextCard'\nimport { RestingStandingsCard } from './RestingStandingsCard'\nimport { RestingSeasonCard } from './RestingSeasonCard'\nimport { RestingFormCard } from './RestingFormCard'\nimport { LiveScoreCard } from './LiveScoreCard'\nimport { LiveTimelineCard } from './LiveTimelineCard'\nimport { LiveStatsCard } from './LiveStatsCard'\n\n// The [prefill] card types (see ClubFanDashboardPayload.cs) -- tapping any of them sends its\n// actionLabel as a follow-up message, carrying the opaque actionRef so the server resolves the\n// pre-issued binding. Every other card type is a [data] card with no tap target. FixtureCard is a\n// DataCard now (u319): its tap moved to the greeting chips, so it's not in this union any more.\nexport type ClubFanDashboardTapCard =\n  | CongestedWeekCardData\n  | PostMatchGoalsCardData\n  | PostMatchStatsCardData\n  | PostMatchTopPerformerCardData\n  | RestingNextCardData\n  | RestingStandingsCardData\n  | RestingSeasonCardData\n\nexport function ClubFanDashboard({ dashboard, onTap, ui }: {\n  dashboard: ClubFanDashboardPayload\n  onTap: (card: ClubFanDashboardTapCard) => void\n  ui?: UiConfig\n}): JSX.Element {\n  // The clock leads the dashboard, so any countdown card is floated to the top; the rest keep\n  // their server order.\n  const orderedCards = [\n    ...dashboard.cards.filter((c) => c.cardType === 'countdown'),\n    ...dashboard.cards.filter((c) => c.cardType !== 'countdown'),\n  ]\n  // The score card's scorers line is derived from the sibling timeline card's goal events, so it\n  // needs pulling out here where the full card list is in scope. Null-safe: no timeline card (or\n  // no goals in it) means no scorers line, not a crash.\n  const timelineCard = dashboard.cards.find(\n    (c): c is LiveTimelineCardData => c.cardType === 'liveTimeline',\n  )\n  const goalEvents = timelineCard?.data.events.filter((e) => e.type === 'goal')\n  return (\n    <div className=\"ss-w-fandash\">\n      {dashboard.greeting ? <span className={dashboard.greetingIsLead ? 'ss-w-fandash-greeting ss-w-fandash-greeting--lead' : 'ss-w-fandash-greeting'}>{dashboard.greeting}</span> : null}\n      <div className=\"ss-w-fandash-cards\">\n        {orderedCards.map((card, i) => (\n          <FanDashboardCard key={`${card.cardType}-${i}`} card={card} onTap={onTap} ui={ui} goalEvents={goalEvents} />\n        ))}\n      </div>\n    </div>\n  )\n}\n\nfunction FanDashboardCard({ card, onTap, ui, goalEvents }: {\n  card: ClubFanDashboardCard\n  onTap: (card: ClubFanDashboardTapCard) => void\n  ui?: UiConfig\n  goalEvents?: LiveEventLine[]\n}): JSX.Element | null {\n  switch (card.cardType) {\n    case 'fixture':\n      return <FixtureCard card={card} />\n    case 'countdown':\n      return <CountdownCard card={card} />\n    case 'injuries':\n      return <InjuriesCard card={card} ui={ui} />\n    case 'reasonToBet':\n      return <ReasonToBetCard card={card} />\n    case 'whereToWatch':\n      return <WhereToWatchCard card={card} />\n    case 'congestedWeek':\n      return <CongestedWeekCard card={card} onTap={onTap} />\n    case 'transfers':\n      return <TransfersCard card={card} />\n    case 'links':\n      return <LinksCard card={card} />\n    case 'postMatchResult':\n      return <PostMatchResultCard card={card} />\n    case 'postMatchGoals':\n      return <PostMatchGoalsCard card={card} onTap={onTap} />\n    case 'postMatchStats':\n      return <PostMatchStatsCard card={card} onTap={onTap} />\n    case 'postMatchTopPerformer':\n      return <PostMatchTopPerformerCard card={card} onTap={onTap} />\n    case 'postMatchNext':\n      return <PostMatchNextCard card={card} />\n    case 'restingNext':\n      return <RestingNextCard card={card} onTap={onTap} />\n    case 'restingStandings':\n      return <RestingStandingsCard card={card} onTap={onTap} />\n    case 'restingSeason':\n      return <RestingSeasonCard card={card} onTap={onTap} />\n    case 'restingForm':\n      return <RestingFormCard card={card} />\n    case 'liveScore':\n      return <LiveScoreCard card={card} goalEvents={goalEvents} />\n    case 'liveTimeline':\n      return <LiveTimelineCard card={card} ui={ui} />\n    case 'liveStats':\n      return <LiveStatsCard card={card} />\n    default:\n      // The server's cardType is a closed set, but a mismatched deploy could still send an\n      // unrecognised discriminator -- render nothing for it rather than crash the whole turn.\n      return null\n  }\n}\n","import type { GreetingDashboardTile } from '@sensiblestats/widget-sdk'\nimport type { Message } from '../reducer'\nimport type { ActionVM } from '../model'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { Markdown } from './Markdown'\nimport { EntityCardList } from './EntityCardList'\nimport { BettingInsightList } from './BettingInsightList'\nimport { ComboCardList } from './ComboCardList'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { CompactOddsList } from './CompactOddsList'\nimport { toCompactList } from '../compactList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { ActionButtons } from './ActionButtons'\nimport { GreetingDashboard } from './dashboard/GreetingDashboard'\nimport { ClubFanDashboard, type ClubFanDashboardTapCard } from './dashboard/ClubFanDashboard'\n\nexport function ChatMessage({ message, disabled, onAct, onTap, ui, slip, monitor }: {\n  message: Message\n  disabled: boolean\n  onAct: (a: ActionVM) => void\n  onTap: (tile: GreetingDashboardTile, index: number) => void\n  ui?: UiConfig\n  slip: SlipHandlerProps\n  monitor?: LiveMonitorController\n}): JSX.Element {\n  if (message.role === 'user') {\n    return <div className=\"ss-w-msg ss-w-user\" data-msg-id={message.id}><div className=\"ss-w-bubble\">{message.text}</div></div>\n  }\n  // A [prefill] club-fan-dashboard card tap reuses the same send path as an action button --\n  // actionLabel becomes both the message and the display text, and the opaque actionRef rides\n  // along so the server resolves the card's pre-issued action binding rather than re-planning\n  // a prose command -- rather than threading a second tap handler through MessageList.\n  const onFanDashboardTap = (card: ClubFanDashboardTapCard): void => {\n    onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || '' })\n  }\n  const compact = toCompactList(message.marketOdds)\n  return (\n    <div className=\"ss-w-msg ss-w-bot\" data-msg-id={message.id}>\n      {message.text && !message.greetingDashboard && !message.clubFanDashboard ? <Markdown text={message.text} /> : null}\n      {message.greetingDashboard && !message.clubFanDashboard ? <GreetingDashboard dashboard={message.greetingDashboard} onTap={onTap} oddsLabel={ui?.oddsLabel} /> : null}\n      {message.clubFanDashboard ? <ClubFanDashboard dashboard={message.clubFanDashboard} onTap={onFanDashboardTap} ui={ui} /> : null}\n      <EntityCardList cards={message.cards} disabled={disabled} showLessLabel={ui?.showLess} showMoreLabel={ui?.showMore} />\n      <BettingInsightList insights={message.insights} ui={ui} slip={slip} monitor={monitor} />\n      <ComboCardList cards={message.comboCards ?? []} ui={ui} slip={slip} monitor={monitor} />\n      {compact\n        ? <CompactOddsList list={compact} ui={ui} slip={slip} monitor={monitor} />\n        : <MarketOddsCardList cards={message.marketOdds} ui={ui} slip={slip} monitor={monitor} />}\n      <OddsMovementCardList cards={message.oddsMovement} ui={ui} monitor={monitor} />\n      <ActionButtons actions={message.actions} loading={false} disabled={disabled} onAct={onAct} />\n    </div>\n  )\n}\n","import type { ChipVM } from '../model'\n\nexport function IntentChips({ chips, onPick }: { chips: ChipVM[]; onPick: (text: string) => void }): JSX.Element | null {\n  if (chips.length === 0) return null\n  return (\n    <div className=\"ss-w-chips\">\n      {chips.map((c, i) => (\n        <button key={`${c.text}-${i}`} type=\"button\" className=\"ss-w-chip\" onClick={() => onPick(c.text)}>{c.text}</button>\n      ))}\n    </div>\n  )\n}\n","// Distance (px) from the bottom within which the list is still considered\n// \"pinned\" — small enough that a user reading earlier content isn't counted\n// as pinned, large enough to absorb sub-pixel/rounding drift while streaming.\nexport const PIN_THRESHOLD = 48\n\n/**\n * True when the scroll container is at (or within PIN_THRESHOLD of) its bottom.\n * Used to decide whether new content should auto-scroll: we follow the stream\n * only while the user is already at the bottom, so late arrivals (e.g. suggested\n * actions) never yank a user who has scrolled up to read.\n */\nexport function isPinnedToBottom(el: Pick<HTMLElement, 'scrollHeight' | 'scrollTop' | 'clientHeight'>, threshold = PIN_THRESHOLD): boolean {\n  return el.scrollHeight - el.scrollTop - el.clientHeight <= threshold\n}\n","import { forwardRef, useEffect, useImperativeHandle, useRef, useState, type KeyboardEvent } from 'react'\nimport { SendIcon } from './Icons'\n\nexport interface ChatInputHandle {\n  /** Puts focus in the composer: the text box, or, while a reply streams and the text box is\n   *  disabled, the Stop button, with the text box taking focus back when the reply ends (P5). */\n  focus(): void\n}\n\nexport interface ChatInputProps {\n  placeholder: string\n  streaming: boolean\n  onSend: (t: string) => void\n  onStop: () => void\n  stopLabel?: string\n  sendLabel?: string\n  /** A preset tool is open over the chat (spec Stage 2): nothing in the composer can be used. */\n  disabled?: boolean\n  /** Called on each change to the typed text (an input event), never on Tab or the arrow keys. */\n  onType?: () => void\n}\n\nexport const ChatInput = forwardRef<ChatInputHandle, ChatInputProps>(function ChatInput(\n  { placeholder, streaming, onSend, onStop, stopLabel = 'Stop response', sendLabel = 'Send message', disabled = false, onType },\n  ref,\n) {\n  const [value, setValue] = useState('')\n  const textareaRef = useRef<HTMLTextAreaElement>(null)\n  const stopRef = useRef<HTMLButtonElement>(null)\n  const textBoxWantsFocusRef = useRef(false)\n  const submit = () => { if (disabled) return; 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\n  useImperativeHandle(ref, () => ({\n    focus() {\n      const box = textareaRef.current\n      if (box && !box.disabled) { textBoxWantsFocusRef.current = false; box.focus(); return }\n      textBoxWantsFocusRef.current = true\n      stopRef.current?.focus()\n    },\n  }), [])\n\n  // The reply ended (Stop unmounted, focus fell to the page): hand focus to the text box, unless\n  // the visitor has put it somewhere else meanwhile.\n  useEffect(() => {\n    if (streaming || disabled || !textBoxWantsFocusRef.current) return\n    textBoxWantsFocusRef.current = false\n    const box = textareaRef.current\n    if (!box) return\n    const active = (box.getRootNode() as Document | ShadowRoot).activeElement\n    const input = box.closest('.ss-w-input')\n    const isWithinComponent = input?.contains(active as Node)\n    if (!active || active === box.ownerDocument.body || isWithinComponent) box.focus()\n  }, [streaming, disabled])\n\n  return (\n    <div className=\"ss-w-input\">\n      <textarea\n        ref={textareaRef} className=\"ss-w-textarea\" rows={1} placeholder={placeholder} value={value}\n        disabled={streaming || disabled}\n        onChange={(e) => { setValue(e.target.value); onType?.() }}\n        onKeyDown={onKeyDown}\n      />\n      {streaming ? (\n        <button ref={stopRef} type=\"button\" className=\"ss-w-send ss-w-stop\" aria-label={stopLabel} disabled={disabled} onClick={onStop}><span className=\"ss-w-stop-glyph\" /></button>\n      ) : (\n        <button type=\"button\" className=\"ss-w-send\" aria-label={sendLabel} disabled={disabled} onClick={submit}><SendIcon /></button>\n      )}\n    </div>\n  )\n})\n","import { useEffect, useRef } from 'react'\nimport type { LiveMonitorController, MonitorTab } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\n\nexport function TabBar({ monitor, ui, matchCount, oddsCount, todayCount, hasToday, gamesEnabled, clubEnabled }: {\n  monitor: LiveMonitorController\n  ui: UiConfig\n  matchCount: number\n  oddsCount: number\n  /** Live match count. NEVER the fixture count -- a Saturday would badge 41. */\n  todayCount: number\n  hasToday: boolean\n  /** Enabled when getGames resolves non-null; false for betting operators (404 sentinel). */\n  gamesEnabled?: boolean\n  clubEnabled?: boolean\n}): JSX.Element | null {\n  const tabs: { tab: MonitorTab; label: string; count: number; dot: boolean }[] = [\n    { tab: 'chat', label: ui.tabChat, count: 0, dot: monitor.chatDot },\n    ...(clubEnabled\n      ? [\n          { tab: 'fixtures' as MonitorTab, label: ui.tabFixtures, count: 0, dot: false },\n          { tab: 'standings' as MonitorTab, label: ui.tabStandings, count: 0, dot: false },\n          { tab: 'squad' as MonitorTab, label: ui.tabSquad, count: 0, dot: false },\n        ]\n      : [\n          ...(hasToday ? [{ tab: 'today' as MonitorTab, label: ui.tabToday, count: todayCount, dot: monitor.todayDot }] : []),\n          ...(matchCount > 0 ? [{ tab: 'following' as MonitorTab, label: ui.tabFollowing, count: matchCount, dot: monitor.matchesDot }] : []),\n          ...(oddsCount > 0 ? [{ tab: 'odds' as MonitorTab, label: ui.tabOdds, count: oddsCount, dot: monitor.oddsDot }] : []),\n        ]),\n    ...(gamesEnabled ? [{ tab: 'games' as MonitorTab, label: ui.tabGames, count: 0, dot: false }] : []),\n  ]\n\n  const listRef = useRef<HTMLDivElement>(null)\n  const activeTab = monitor.activeTab\n  useEffect(() => {\n    const el = listRef.current?.querySelector<HTMLElement>('[data-on]')\n    if (!el || typeof el.scrollIntoView !== 'function') return\n    const reduce = typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches\n    el.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: reduce ? 'auto' : 'smooth' })\n  }, [activeTab])\n\n  // A lone Chat tab is chrome that selects nothing -- the strip stays hidden, as it does today\n  // when nothing is pinned.\n  if (tabs.length < 2) return null\n\n  return (\n    <div className=\"ss-w-tabs\" role=\"tablist\" ref={listRef}>\n      {tabs.map(({ tab, label, count, dot }) => {\n        const active = monitor.activeTab === tab\n        return (\n          <button\n            key={tab}\n            type=\"button\"\n            role=\"tab\"\n            aria-selected={active}\n            data-on={active ? '' : undefined}\n            className=\"ss-w-tab\"\n            onClick={() => monitor.setActiveTab(tab)}\n          >\n            {label}\n            {count > 0 && <span className=\"ss-w-tab-count\">{count}</span>}\n            {dot && !active && <span className=\"ss-w-tab-dot\" aria-hidden=\"true\" />}\n          </button>\n        )\n      })}\n    </div>\n  )\n}\n","import type { LiveMonitorMatch } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { toMarketOddsVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\n\nexport function MarketAccordion({ match, monitor, ui, slip }: {\n  match: LiveMonitorMatch\n  monitor: LiveMonitorController\n  ui: UiConfig\n  slip: SlipHandlerProps\n}): JSX.Element | null {\n  const slipState = useSlipState()\n  const markets = match.availableMarkets ?? []\n  if (markets.length === 0) return null\n  const open = monitor.openMarket[match.matchId] ?? null\n\n  return (\n    <div className=\"ss-w-acc\">\n      {markets.map((m) => {\n        // A suspended market has no servable card: the odds lookup drops every suspended/stopped\n        // row, so /live-monitor/market answers 404 MarketNotPriced and the panel lands on the\n        // tap-to-retry affordance, which can never succeed. Don't offer the tap. `&& !m.suspended`\n        // also collapses a market that suspends WHILE open, instead of leaving stale rows up.\n        const isOpen = open === m.marketDeveloperName && !m.suspended\n        const key = `${match.matchId}:${m.marketDeveloperName}`\n        const entry = monitor.marketOdds[key]\n        return (\n          <div key={m.marketDeveloperName} className={isOpen ? 'ss-w-acc-row ss-w-acc-row-open' : 'ss-w-acc-row'}>\n            <div className=\"ss-w-acc-head\">\n              <button\n                type=\"button\"\n                className={m.suspended ? 'ss-w-acc-toggle ss-w-acc-toggle--susp' : 'ss-w-acc-toggle'}\n                aria-expanded={isOpen}\n                disabled={m.suspended}\n                onClick={() => monitor.toggleMarket(match.matchId, m.marketDeveloperName)}\n              >\n                <span className=\"ss-w-acc-chevron\">{m.suspended ? '' : isOpen ? '▾' : '▸'}</span>\n                <span className=\"ss-w-acc-label\">{m.marketLabel}</span>\n                {m.hasInsight && <span className=\"ss-w-acc-badge\">★</span>}\n                {m.suspended && <span className=\"ss-w-acc-susp\">{ui.accordionSuspended}</span>}\n              </button>\n            </div>\n            {isOpen && (\n              <div className=\"ss-w-acc-panel\">\n                {entry?.error && (\n                  <div\n                    className=\"ss-w-acc-retry\"\n                    onClick={() => monitor.retryMarket(match.matchId, m.marketDeveloperName)}\n                  >\n                    {ui.accordionRetry}\n                  </div>\n                )}\n                {entry?.block?.insight?.text && (\n                  <div className=\"ss-w-acc-insight\">{entry.block.insight.text}</div>\n                )}\n                {entry?.block?.card && (\n                  <MarketOddsCardList\n                    cards={[toMarketOddsVM(entry.block.card)]}\n                    ui={ui}\n                    slip={slip}\n                    monitor={monitor}\n                    inSlipIds={slipState?.added}\n                    hideHeader\n                  />\n                )}\n              </div>\n            )}\n          </div>\n        )\n      })}\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { ChatGrounding, LiveMonitorFact } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\n\nexport type AskHandler = (text: string, grounding: ChatGrounding) => void\n\n// Spec §6: the newest fact under the score, one at a time; earlier ones expand below it. A fact\n// with no market (unpriced, suspended, or a record) renders without the chip row at all.\nexport function LiveFactBlock({ facts, matchId, ui, slip, onAsk }: {\n  facts: LiveMonitorFact[]\n  matchId: number\n  ui: UiConfig\n  slip: SlipHandlerProps\n  onAsk?: AskHandler\n}): JSX.Element | null {\n  const [expanded, setExpanded] = useState(false)\n  const [current, ...earlier] = facts\n  if (!current) return null\n  const m = current.market\n  return (\n    <section className=\"ss-w-fact\" aria-label={ui.liveFactLabel}>\n      <div className=\"ss-w-fact-k\">\n        <span>{ui.liveFactLabel}</span>\n        <span className=\"ss-w-fact-min\">· {current.minuteLabel}</span>\n        <span className=\"ss-w-fact-subj\">{current.subjectLabel}</span>\n      </div>\n      <p className=\"ss-w-fact-text\">{current.text}</p>\n      <div className=\"ss-w-fact-basis\">{current.basis}</div>\n      {m && !m.isSuspended && (\n        <div className=\"ss-w-fact-mkt\">\n          <span>{m.marketLabel} · {m.selectionLabel}</span>\n          <span className=\"ss-w-mon-stat-mkt-right\">\n            {typeof m.price === 'number' && <span className=\"ss-w-mon-price\">{m.price.toFixed(2)}</span>}\n            <SlipButton\n              selection={chipSelection(m, matchId, slip.conversationId)}\n              shownOdds={typeof m.price === 'number' ? m.price.toFixed(2) : ''}\n              marketDeveloperName={m.marketDeveloperName}\n              selectionLabel={m.selectionLabel}\n              slip={slip}\n              ui={ui}\n            />\n          </span>\n        </div>\n      )}\n      {expanded && earlier.length > 0 && (\n        <ul className=\"ss-w-fact-hist\">\n          {earlier.map((f) => (\n            <li key={f.id}>\n              <span className=\"ss-w-fact-hmin\">{f.minuteLabel}</span>\n              <div>\n                <p className=\"ss-w-fact-htext\">{f.text}</p>\n                <div className=\"ss-w-fact-basis\">{f.basis}</div>\n              </div>\n            </li>\n          ))}\n        </ul>\n      )}\n      <div className=\"ss-w-fact-foot\">\n        {onAsk && (\n          <button type=\"button\" className=\"ss-w-fact-link\"\n            onClick={() => onAsk(current.text, { kind: 'liveFact', matchId, subject: current.text.slice(0, 400) })}>\n            {ui.liveFactAsk}\n          </button>\n        )}\n        {earlier.length > 0 && (\n          <button type=\"button\" className=\"ss-w-fact-link ss-w-fact-link--muted\" aria-expanded={expanded}\n            onClick={() => setExpanded((v) => !v)}>\n            {expanded ? ui.liveFactHideEarlier : ui.liveFactEarlier(earlier.length)}\n          </button>\n        )}\n      </div>\n    </section>\n  )\n}\n","import { useState } from 'react'\nimport type { FormAndH2H, FormMatch } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\n\nfunction resultClass(result: FormMatch['result']): string {\n  if (result === 'W') return 'ss-w-h2h-result--win'\n  if (result === 'L') return 'ss-w-h2h-result--loss'\n  return 'ss-w-h2h-result--draw'\n}\n\nfunction resultLabel(result: FormMatch['result'], ui: UiConfig): string {\n  if (result === 'W') return ui.standingsColWon\n  if (result === 'L') return ui.standingsColLost\n  return ui.standingsColDrawn\n}\n\nfunction FormDots({ form, ui }: { form: FormMatch[]; ui: UiConfig }): JSX.Element {\n  return (\n    <div className=\"ss-w-h2h-dots\">\n      {form.map((m, i) => (\n        <span key={i} className={`ss-w-h2h-result ${resultClass(m.result)}`}>{resultLabel(m.result, ui)}</span>\n      ))}\n    </div>\n  )\n}\n\nexport function MonitorFormH2H({ formAndH2H, homeTeamName, awayTeamName, ui }: {\n  formAndH2H: FormAndH2H\n  homeTeamName?: string | null\n  awayTeamName?: string | null\n  ui: UiConfig\n}): JSX.Element {\n  const [expanded, setExpanded] = useState(false)\n  const { homeForm, awayForm, h2h, homeShortCode, awayShortCode } = formAndH2H\n  if (homeForm.length === 0 && awayForm.length === 0 && !h2h) {\n    return <></>\n  }\n  const homeLabel = homeShortCode || homeTeamName\n  const awayLabel = awayShortCode || awayTeamName\n  const total = h2h ? h2h.wins + h2h.draws + h2h.losses : 0\n  const winsPct = total > 0 && h2h ? (h2h.wins / total) * 100 : 0\n  const drawsPct = total > 0 && h2h ? (h2h.draws / total) * 100 : 0\n  const lossesPct = total > 0 && h2h ? (h2h.losses / total) * 100 : 0\n\n  return (\n    <div className=\"ss-w-h2h\">\n      <button type=\"button\" className=\"ss-w-h2h-head\" aria-expanded={expanded} onClick={() => setExpanded((v) => !v)}>\n        <span className=\"ss-w-h2h-head-l\">\n          <span className=\"ss-w-h2h-dot\" aria-hidden=\"true\" />\n          <span className=\"ss-w-h2h-title\">{ui.formAndH2HLabel}</span>\n        </span>\n        <svg\n          className={expanded ? 'ss-w-h2h-chevron ss-w-h2h-chevron--open' : 'ss-w-h2h-chevron'}\n          width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n          strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"\n        >\n          <path d=\"M6 9l6 6 6-6\" />\n        </svg>\n      </button>\n\n      {expanded && (\n        <div className=\"ss-w-h2h-body\">\n          <div className=\"ss-w-h2h-forms\">\n            <div className=\"ss-w-h2h-form-col\">\n              <span className=\"ss-w-h2h-form-team\">{homeLabel}</span>\n              <FormDots form={homeForm} ui={ui} />\n            </div>\n            <div className=\"ss-w-h2h-form-col ss-w-h2h-form-col--away\">\n              <span className=\"ss-w-h2h-form-team\">{awayLabel}</span>\n              <FormDots form={awayForm} ui={ui} />\n            </div>\n          </div>\n\n          {h2h && (\n            <div className=\"ss-w-h2h-record\">\n              <span className=\"ss-w-h2h-meta\">{h2h.label}</span>\n              <div className=\"ss-w-h2h-bar\">\n                <span className=\"ss-w-h2h-bar-seg ss-w-h2h-bar-seg--win\" style={{ width: `${winsPct}%` }} />\n                <span className=\"ss-w-h2h-bar-seg ss-w-h2h-bar-seg--draw\" style={{ width: `${drawsPct}%` }} />\n                <span className=\"ss-w-h2h-bar-seg ss-w-h2h-bar-seg--loss\" style={{ width: `${lossesPct}%` }} />\n              </div>\n              <div className=\"ss-w-h2h-legend\">\n                <span className=\"ss-w-h2h-legend-item\">\n                  <span className=\"ss-w-h2h-legend-dot ss-w-h2h-legend-dot--win\" aria-hidden=\"true\" />\n                  {h2h.wins} {h2h.homeWinsLabel}\n                </span>\n                <span className=\"ss-w-h2h-legend-item\">\n                  <span className=\"ss-w-h2h-legend-dot ss-w-h2h-legend-dot--draw\" aria-hidden=\"true\" />\n                  {h2h.draws} {h2h.drawsLabel}\n                </span>\n                <span className=\"ss-w-h2h-legend-item\">\n                  <span className=\"ss-w-h2h-legend-dot ss-w-h2h-legend-dot--loss\" aria-hidden=\"true\" />\n                  {h2h.losses} {h2h.awayWinsLabel}\n                </span>\n              </div>\n            </div>\n          )}\n        </div>\n      )}\n    </div>\n  )\n}\n","import type { LiveMonitorEvent, LiveMonitorMatch, LiveMonitorStatRow, PinRef } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport { chipSelection, type SlipHandlerProps } from '../slip'\nimport { SlipButton } from './AddToSlipButton'\nimport { Crest } from './Crest'\nimport { MomentumWave } from './dashboard/MomentumWave'\nimport { LiveFactBlock, type AskHandler } from './LiveFactBlock'\nimport { MonitorFormH2H } from './MonitorFormH2H'\nimport { PinToggle } from './PinToggle'\n\n// A stat row's market chip promotes to the top when the user has pinned that market -- matched by\n// FIELD, never by a reconstructed pin key. LiveMonitorStatPrice carries no `line`, and its\n// selectionLabel is server-localized (TR \"2.5 Üst\" vs the stored pin's raw \"Over\"), so any key\n// string built from the chip would never equal the stored pin's key. marketDeveloperName is the\n// one field both sides always share in its raw, unlocalized form; matchOddsId is an unambiguous\n// same-selection identifier when both sides carry it.\nfunction isPromoted(row: LiveMonitorStatRow, promotedPins: readonly PinRef[]): boolean {\n  const chip = row.market\n  if (!chip) return false\n  return promotedPins.some((pin) =>\n    pin.marketDeveloperName === chip.marketDeveloperName ||\n    (chip.matchOddsId != null && pin.matchOddsId === chip.matchOddsId))\n}\n\nfunction formatTime(iso: string): string {\n  return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface ScorerLine { player: string; label: string }\n\n// One line per scorer for a single side, in the order goals were scored, with a brace collapsed\n// onto that scorer's line (\"Powell 87', 90+6'\"). An own goal carries an \"(OG)\" marker on its\n// minute. Goals arrive already ascending from the server; grouping by name preserves that order\n// via the first appearance of each scorer.\nfunction groupScorers(goals: LiveMonitorEvent[], ownGoalLabel: string): ScorerLine[] {\n  const order: string[] = []\n  const minutesByPlayer = new Map<string, string[]>()\n  for (const g of goals) {\n    const name = g.player ?? ''\n    const minute = g.ownGoal ? `${g.minuteLabel} (${ownGoalLabel})` : g.minuteLabel\n    if (!minutesByPlayer.has(name)) {\n      minutesByPlayer.set(name, [])\n      order.push(name)\n    }\n    minutesByPlayer.get(name)!.push(minute)\n  }\n  return order.map((name) => {\n    const minutes = minutesByPlayer.get(name)!.join(', ')\n    return { player: name, label: name ? `${name} ${minutes}` : minutes }\n  })\n}\n\nexport function MonitorMatchCard({ match, promotedPins, monitor, ui, slip, onAsk }: {\n  match: LiveMonitorMatch\n  /** the user's non-match pins on this match — their stat rows promote to the top strip */\n  promotedPins: PinRef[]\n  monitor: LiveMonitorController\n  ui: UiConfig\n  slip: SlipHandlerProps\n  onAsk?: AskHandler\n}): JSX.Element {\n  const live = match.phase === 'live'\n  const goals = match.events.filter((e) => e.type === 'goal')\n  const homeScorers = groupScorers(goals.filter((e) => e.side === 'home'), ui.ownGoalLabel)\n  const awayScorers = groupScorers(goals.filter((e) => e.side === 'away'), ui.ownGoalLabel)\n  const promotedRows = match.statRows.filter((row) => isPromoted(row, promotedPins))\n  const otherRows = match.statRows.filter((row) => !isPromoted(row, promotedPins))\n  const orderedRows = [...promotedRows, ...otherRows]\n  const kickoff = match.phase === 'preMatch' && match.kickoffUtc ? ui.bettingKickoff(match.kickoffUtc) : undefined\n\n  return (\n    <div className=\"ss-w-mon\">\n      <div className=\"ss-w-mon-top\">\n        {live && (\n          <span className=\"ss-w-fandash-live-pill\">\n            <span className=\"ss-w-fandash-live-dot\" aria-hidden=\"true\" />\n            {ui.liveLabel}\n          </span>\n        )}\n        {match.phase === 'fullTime' && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n        {kickoff && <span className=\"ss-w-mon-pill\">{kickoff.dayLabel} · {kickoff.time}</span>}\n        {live && match.minuteLabel && <span className=\"ss-w-mon-min\">{match.minuteLabel}</span>}\n        {match.competitionName && <span className=\"ss-w-mon-comp\">{match.competitionName}</span>}\n        <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n      </div>\n      <div className=\"ss-w-mon-main\">\n        <span className=\"ss-w-mon-side\">\n          <Crest kind=\"team\" url={match.homeCrestUrl ?? undefined} name={match.homeTeamName ?? undefined} />\n          <span className=\"ss-w-mon-name\">{match.homeTeamName}</span>\n        </span>\n        {match.phase === 'preMatch' ? (\n          <span className=\"ss-w-mon-vs\">vs</span>\n        ) : (\n          <span className=\"ss-w-mon-score\">{match.homeScore}<i>–</i>{match.awayScore}</span>\n        )}\n        <span className=\"ss-w-mon-side ss-w-mon-side--away\">\n          <Crest kind=\"team\" url={match.awayCrestUrl ?? undefined} name={match.awayTeamName ?? undefined} />\n          <span className=\"ss-w-mon-name\">{match.awayTeamName}</span>\n        </span>\n      </div>\n      {match.phase === 'preMatch' && match.formAndH2H && (\n        <MonitorFormH2H\n          formAndH2H={match.formAndH2H}\n          homeTeamName={match.homeTeamName}\n          awayTeamName={match.awayTeamName}\n          ui={ui}\n        />\n      )}\n      {(homeScorers.length > 0 || awayScorers.length > 0) && (\n        <div className=\"ss-w-mon-scorers\">\n          <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-home\">\n            {homeScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n          </ul>\n          <span className=\"ss-w-mon-scorers-ball\" aria-hidden=\"true\">⚽</span>\n          <ul className=\"ss-w-mon-scorers-col ss-w-mon-scorers-away\">\n            {awayScorers.map((s, i) => <li key={`${s.player}-${i}`}>{s.label}</li>)}\n          </ul>\n        </div>\n      )}\n      {live && match.facts && match.facts.length > 0 && (\n        <LiveFactBlock facts={match.facts} matchId={match.matchId} ui={ui} slip={slip} onAsk={onAsk} />\n      )}\n      <div className=\"ss-w-mon-stats\">\n        {orderedRows.map((row) => {\n          const total = row.homeNum + row.awayNum\n          const homePct = total > 0 ? (row.homeNum / total) * 75 : 0\n          const awayPct = total > 0 ? (row.awayNum / total) * 75 : 0\n          const promoted = isPromoted(row, promotedPins)\n          const selection = chipSelection(row.market, match.matchId, slip.conversationId)\n          return (\n            <div className={promoted ? 'ss-w-mon-stat ss-w-mon-pstrip' : 'ss-w-mon-stat'} key={row.label}>\n              <div className=\"ss-w-mon-stat-row\">\n                <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--home\">{row.homeValue}</span>\n                <span className=\"ss-w-mon-stat-l\">{row.label}</span>\n                <span className=\"ss-w-mon-stat-v ss-w-mon-stat-v--away\">{row.awayValue}</span>\n              </div>\n              <div className=\"ss-w-mon-bar\">\n                <b className=\"ss-w-mon-bar-home\" style={{ width: `${homePct}%` }} />\n                <i className=\"ss-w-mon-bar-away\" style={{ width: `${awayPct}%` }} />\n              </div>\n              {/* A suspended market drops its whole betting line -- label, price and button -- and\n                  the stat row keeps its bar, exactly like a row with no market at all. Showing it\n                  offered a price the bookmaker was not taking next to a live Add to slip whose\n                  only possible outcome was the slipSuspended error toast. bet365 suspends\n                  derivative in-play markets constantly: measured across 20 live matches, 61% of\n                  Goals Over/Under rows and 69% of 1st Half Goals rows were suspended against 9%\n                  of Fulltime Result. */}\n              {row.market && !row.market.isSuspended && (\n                <div className={promoted ? 'ss-w-mon-stat-mkt ss-w-mon-mkt' : 'ss-w-mon-stat-mkt'}>\n                  <span>{row.market.marketLabel} · {row.market.selectionLabel}</span>\n                  <span className=\"ss-w-mon-stat-mkt-right\">\n                    {typeof row.market.price === 'number' && <span className=\"ss-w-mon-price\">{row.market.price.toFixed(2)}</span>}\n                    <SlipButton\n                      selection={selection}\n                      shownOdds={typeof row.market.price === 'number' ? row.market.price.toFixed(2) : ''}\n                      marketDeveloperName={row.market.marketDeveloperName}\n                      selectionLabel={row.market.selectionLabel}\n                      slip={slip}\n                      ui={ui}\n                    />\n                  </span>\n                </div>\n              )}\n            </div>\n          )\n        })}\n      </div>\n      {match.status === 'stale' && <span className=\"ss-w-mon-asof\">{ui.asOf(formatTime(match.asOfUtc))}</span>}\n      {match.momentum.length > 0 && (\n        <div className=\"ss-w-mon-mom\">\n          {/* Label only -- no percentage split. momentumHomePct is a share of the WHOLE match's\n              accumulated pressure, so it reads as a verdict on the match (\"99% - 1%\") when the\n              wave beneath it is showing minute-by-minute swing. The two disagree on sight, and\n              the share is the one that misleads. */}\n          <span className=\"ss-w-mon-stat-l\">{ui.momentumLabel}</span>\n          <MomentumWave points={match.momentum} clubIsHome={true} />\n        </div>\n      )}\n      {match.phase === 'fullTime' && <div className=\"ss-w-mon-grace\">{ui.graceNote}</div>}\n    </div>\n  )\n}\n","import type { LiveMonitorMarket } from '@sensiblestats/widget-sdk'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { UiConfig } from '../config'\nimport type { SlipHandlerProps } from '../slip'\nimport type { MarketOddsRowVM, MarketOddsVM } from '../model'\nimport { MarketOddsCardList } from './MarketOddsCardList'\nimport { OddsMovementCardList } from './OddsMovementCard'\nimport { MarketAccordion } from './MarketAccordion'\nimport { MonitorMatchCard } from './MonitorMatchCard'\nimport { toMarketOddsVM, toOddsMovementVM } from '../model'\nimport { useSlipState } from '../slipStateContext'\nimport type { AskHandler } from './LiveFactBlock'\n\n// Slim live-only strip above an Odds-tab market card. The card itself already shows the\n// competition, fixture, market, kickoff and the unpin — so this renders ONLY the match-live\n// context the card lacks (score, minute, suspended/settled, stale as-of), and nothing at all for\n// a pre-match market (avoids duplicating the card's fixture/kickoff). (u342)\nfunction OddsLiveStrip({ m, ui }: { m: LiveMonitorMarket; ui: UiConfig }): JSX.Element | null {\n  const showScore = m.phase !== 'preMatch' && typeof m.homeScore === 'number'\n  const stale = m.status === 'stale'\n  if (!showScore && !m.minuteLabel && !(m.isSuspended && !m.isSettled) && !m.isSettled && !stale) return null\n  return (\n    <div className=\"ss-w-mk-live\">\n      {showScore && (\n        <b className=\"ss-w-mk-live-score\">{m.homeTeamName} {m.homeScore}–{m.awayScore} {m.awayTeamName}</b>\n      )}\n      {m.minuteLabel && <span className=\"ss-w-mon-min\">{m.minuteLabel}</span>}\n      {m.isSuspended && !m.isSettled && <span className=\"ss-w-mon-susp\">{ui.suspendedLabel}</span>}\n      {m.isSettled && <span className=\"ss-w-mon-pill\">{ui.fullTimeLabel}</span>}\n      {stale && (\n        <span className=\"ss-w-mon-asof\">{ui.asOf(new Date(m.asOfUtc).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }))}</span>\n      )}\n    </div>\n  )\n}\n\nexport function MatchesPanel({ monitor, ui, slip, onAsk }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps; onAsk?: AskHandler }): JSX.Element {\n  // Only EXPLICIT match pins surface here (2026-09-06 ruling: an odds pin tracks odds, a match\n  // pin tracks the match -- never combined). Filtering against current pins, not just the\n  // snapshot, also makes an unpin drop the card immediately.\n  const matches = (monitor.snapshot?.matches ?? []).filter((m) =>\n    monitor.pins.some((p) => p.kind === 'match' && p.matchId === m.matchId))\n  if (matches.length === 0) {\n    // A pin just made is not in the snapshot until the next poll; stay blank rather than flash the empty text.\n    return monitor.pins.some((p) => p.kind === 'match') ? <div className=\"ss-w-mon-list\" /> : <div className=\"ss-w-mon-empty\">{ui.emptyMatchesTab}</div>\n  }\n  return (\n    <div className=\"ss-w-mon-list\">\n      {matches.map((m) => (\n        <div key={m.matchId} className=\"ss-w-mon-item\">\n          <MonitorMatchCard\n            match={m}\n            // promotion is PER MATCH: only odds pins on THIS match promote their stat row\n            promotedPins={monitor.pins.filter((p) => p.kind !== 'match' && p.matchId === m.matchId)}\n            monitor={monitor}\n            ui={ui}\n            slip={slip}\n            onAsk={onAsk}\n          />\n          <MarketAccordion match={m} monitor={monitor} ui={ui} slip={slip} />\n        </div>\n      ))}\n    </div>\n  )\n}\n\n// I2 (since-view movement): the badge on a pin's PRIMARY row must reflect what THIS operator's\n// client last saw (monitor.lastViewedPrices, keyed by the market snapshot's own key), never the\n// server's own previousPrice/movementDirection window -- those two clocks are unrelated. Only the\n// first main row carries this override; other rows/lines keep whatever (if anything) the server\n// sent.\nfunction withSinceViewMovement(vm: MarketOddsVM, prev: number | undefined): MarketOddsVM {\n  const primary = vm.mainRows[0]\n  if (prev === undefined || !primary || primary.oddsDecimal === undefined || primary.oddsDecimal === prev) return vm\n  const updatedPrimary: MarketOddsRowVM = {\n    ...primary,\n    previousOdds: prev.toFixed(2),\n    movementDirection: primary.oddsDecimal < prev ? 'shortened' : 'drifted',\n  }\n  return { ...vm, mainRows: [updatedPrimary, ...vm.mainRows.slice(1)] }\n}\n\nexport function OddsPanel({ monitor, ui, slip }: { monitor: LiveMonitorController; ui: UiConfig; slip: SlipHandlerProps }): JSX.Element {\n  const slipState = useSlipState()\n  // Same current-pins filter as MatchesPanel: only markets a stored pin still claims render, so\n  // every card carries its unpin affordance and vanishes the moment that pin is removed.\n  const markets = (monitor.snapshot?.markets ?? []).filter((m) =>\n    monitor.pins.some((p) => p.key === m.key))\n  if (markets.length === 0) return <div className=\"ss-w-mon-empty\">{ui.emptyOddsTab}</div>\n  return (\n    <div className=\"ss-w-mon-list\">\n      {markets.map((m) => {\n        // The unpin lives in the card's own header now; pass the ORIGINAL stored pin ref (found by\n        // key) so its pinKey matches exactly -- the card would otherwise reconstruct a market pin\n        // with line=mainLine, which never matches an accordion pin stored without a line.\n        const pin = monitor.pins.find((p) => p.key === m.key)\n        return (\n        <div className=\"ss-w-mon-oddspin\" key={m.key} data-settled={m.isSettled || undefined}>\n          <OddsLiveStrip m={m} ui={ui} />\n          {/* D5 persistent in-slip badge: the wasAdded->markAdded wrapping lives in StatsWidget's\n              own slip memo (so a conversation-path add also arms the badge) -- this panel only\n              reads the widget's slip state to render it. */}\n          {m.card && (\n            <MarketOddsCardList\n              cards={[withSinceViewMovement(toMarketOddsVM(m.card), monitor.lastViewedPrices[m.key])]}\n              ui={ui}\n              slip={slip}\n              monitor={monitor}\n              pinRef={pin ?? undefined}\n              inSlipIds={slipState?.added}\n            />\n          )}\n          {m.history && <OddsMovementCardList cards={[toOddsMovementVM(m.history)]} ui={ui} />}\n          {!m.card && !m.history && <div className=\"ss-w-mon-empty-card\">{ui.oddsUnavailable}</div>}\n        </div>\n        )\n      })}\n    </div>\n  )\n}\n","import { useEffect, useId, useMemo, useState } from 'react'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { MatchDiscoveryController } from '../useMatchDiscovery'\nimport { placeLeagues, starClickable } from '../placement'\nimport { matchesQuery, matchingFixtures } from '../search'\nimport { useStarTap } from '../useStarTap'\nimport { LeagueTile } from './LeagueTile'\nimport { LeagueDetail } from './LeagueDetail'\nimport { LeagueRowGroup, ROW_CAP_PER_LEAGUE, SECTION_ROW_BUDGET, rowsFor } from './LeagueRowGroup'\nimport { FixtureRow } from './FixtureRow'\nimport { Crest } from './Crest'\nimport { SearchField } from './games/ui/SearchField'\nimport { isTreatedLive, visibleGroupsOf } from '../liveClock'\n\nexport function TodayPanel({ discovery, ui, monitor }: {\n  discovery: MatchDiscoveryController\n  ui: UiConfig\n  monitor: LiveMonitorController\n}): JSX.Element {\n  const { groups, states, stale, starLeague } = discovery\n\n  const searchId = useId()\n  const [query, setQuery] = useState('')\n  const [selectedCompetitionId, setSelectedCompetitionId] = useState<number | null>(null)\n  const [toast, setToast] = useState<'starred' | 'unstarred' | null>(null)\n\n  // Mirrors LeagueDetail's own toast timer (Task 6): a toast that never clears would outlive the\n  // tap that caused it.\n  useEffect(() => {\n    if (toast === null) return\n    const id = setTimeout(() => setToast(null), 4000)\n    return () => clearTimeout(id)\n  }, [toast])\n\n  // Finished matches leave the day. Everything below reads visibleGroups, never groups: the live\n  // band, the name-collision count, the group list and the tab strip that decides whether this\n  // panel is reachable at all have to agree on what the day contains, and filtering in one place\n  // is what guarantees that.\n  const visibleGroups = visibleGroupsOf(groups, states)\n\n  // Only a 'match' pin is a pin candidate (Global Constraint) -- a market/selection pin on a\n  // league with no match pin of its own must not promote that league into Your/Top leagues.\n  const pinnedMatchIds = useMemo(\n    () => monitor.pins.filter((p) => p.kind === 'match').map((p) => p.matchId),\n    [monitor.pins],\n  )\n\n  const placement = useMemo(() => placeLeagues(visibleGroups, pinnedMatchIds), [visibleGroups, pinnedMatchIds])\n\n  // Single shared in-flight guard (Task 5's requirement): exactly one useStarTap instance feeds\n  // both the grid (wrapped below, for our own toast) and LeagueDetail (handed raw, since it shows\n  // its own toast for its own taps -- see the Task 7 ruling on the brief's onToggleStar text).\n  const starTap = useStarTap(starLeague)\n\n  const gridStarTap = useMemo(() => ({\n    pendingId: starTap.pendingId,\n    tap: async (competitionId: number, next: boolean): Promise<boolean> => {\n      const ok = await starTap.tap(competitionId, next)\n      if (ok) setToast(next ? 'starred' : 'unstarred')\n      return ok\n    },\n  }), [starTap, starTap.pendingId])\n\n  // competitionName is not an identity: a real Saturday returns four groups named \"Premier\n  // League\". Only collide-on-screen names pay the horizontal cost of a country suffix.\n  const nameCounts = visibleGroups.reduce<Record<string, number>>((acc, g) => {\n    acc[g.competitionName] = (acc[g.competitionName] ?? 0) + 1\n    return acc\n  }, {})\n\n  // A league with zero non-live rows (every match just kicked off) never enters the row budget --\n  // it falls back to a tile, same as today, rather than disappearing. Everything after the first\n  // group that doesn't fit also falls back, so the tile grid keeps placement order instead of\n  // letting a later, smaller league jump ahead of a bigger one that didn't make the cut.\n  const rowedCandidates: typeof placement.candidates = []\n  const tiledCandidates: typeof placement.candidates = []\n  {\n    let budget = SECTION_ROW_BUDGET\n    let overBudget = false\n    for (const group of placement.candidates) {\n      const rows = rowsFor(group, states, stale)\n      if (rows === 0) { tiledCandidates.push(group); continue }\n      if (!overBudget && rows <= budget) { rowedCandidates.push(group); budget -= rows } else { overBudget = true; tiledCandidates.push(group) }\n    }\n  }\n\n  const openIndex = selectedCompetitionId === null\n    ? -1\n    : placement.order.findIndex((g) => g.competitionId === selectedCompetitionId)\n  const openGroup = openIndex === -1 ? undefined : placement.order[openIndex]\n\n  // The previously-selected league's last match can finish between renders (visibleGroupsOf then\n  // drops it from placement.order). The render above already falls back to the grid for that\n  // frame; this just drops the stale id so a later re-open of the same competition starts fresh.\n  useEffect(() => {\n    if (selectedCompetitionId !== null && openGroup === undefined) setSelectedCompetitionId(null)\n  }, [selectedCompetitionId, openGroup])\n\n  // Flat across competitions but ordered by the competition's rank, then by the fixture's position\n  // inside its group -- no ranking field of the client's own. Array.sort is stable, so ties within\n  // a rank keep the flatMap's group-then-match order.\n  // The sort is NOT dead code: `rank` is the contract, the array order is not. That the composer\n  // currently emits groups already in rank order is incidental -- nothing in the wire format\n  // promises it, and a server-side reordering would silently scramble the live band without this.\n  const liveRows = stale\n    ? []\n    : visibleGroups\n        .flatMap((group) =>\n          group.matches\n            .filter((m) => isTreatedLive(states[m.matchId], stale))\n            .map((match) => ({ match, rank: group.rank })))\n        .sort((a, b) => a.rank - b.rank)\n\n  // LeagueDetail's own fixture list excludes whatever this band hoists (Task 6's `!isTreatedLive`\n  // filter) -- it assumes the band is showing them. The band has to render above LeagueDetail too,\n  // not just above the grid, or an opened league's live match renders nowhere. See liveClock.ts's\n  // header comment: that gap is a defect this codebase has already shipped once.\n  const liveBand = liveRows.length > 0 && (\n    <>\n      <div className=\"ss-w-sec-head\">\n        <span className=\"ss-w-sec-dot\" aria-hidden=\"true\" />\n        {ui.sectionLive}\n      </div>\n      <div className=\"ss-w-today-live\">\n        {liveRows.map(({ match }) => (\n          <FixtureRow key={match.matchId} match={match} state={states[match.matchId]}\n            stale={stale} ui={ui} monitor={monitor} />\n        ))}\n      </div>\n    </>\n  )\n\n  if (openGroup !== undefined) {\n    return (\n      <div className=\"ss-w-today-root\">\n        <div className=\"ss-w-mon-list\">\n          {stale && <div className=\"ss-w-stale\">{ui.staleStates}</div>}\n          {liveBand}\n          <LeagueDetail\n            group={openGroup}\n            position={{ index: openIndex + 1, total: placement.order.length }}\n            states={states}\n            stale={stale}\n            ui={ui}\n            monitor={monitor}\n            starTap={starTap}\n            onBack={() => setSelectedCompetitionId(null)}\n            onPrev={() => setSelectedCompetitionId(placement.order[Math.max(0, openIndex - 1)]!.competitionId)}\n            onNext={() => setSelectedCompetitionId(\n              placement.order[Math.min(placement.order.length - 1, openIndex + 1)]!.competitionId,\n            )}\n          />\n        </div>\n      </div>\n    )\n  }\n\n  const searching = query.trim().length > 0\n  const searchResults = searching ? placement.order.filter((g) => matchesQuery(g, query)) : []\n\n  return (\n    <div className=\"ss-w-today-root\">\n      <div className=\"ss-w-mon-list\">\n        {stale && <div className=\"ss-w-stale\">{ui.staleStates}</div>}\n\n        {!searching && liveBand}\n\n        <SearchField\n          id={searchId}\n          label={ui.searchLeaguesPlaceholder}\n          labelHidden\n          placeholder={ui.searchLeaguesPlaceholder}\n          value={query}\n          onChange={setQuery}\n          clearLabel={ui.clearSearchLabel}\n        />\n\n        {searching ? (\n          searchResults.length === 0 ? (\n            <div className=\"ss-w-today-empty\">{ui.noLeagueResults}</div>\n          ) : (\n            <>\n              {searchResults.map((group) => (\n                <div key={group.competitionId} className=\"ss-w-today-search-block\">\n                  <div className=\"ss-w-today-search-group\">\n                    <Crest url={group.competitionImagePath ?? undefined} name={group.competitionName} kind=\"comp\" />\n                    <span className=\"ss-w-today-search-group-name\">\n                      {group.competitionName}\n                      {(nameCounts[group.competitionName] ?? 0) > 1 && group.competitionCountry\n                        ? <span className=\"ss-w-today-tile-country\"> ({group.competitionCountry})</span>\n                        : null}\n                    </span>\n                  </div>\n                  {matchingFixtures(group, query).map((match) => (\n                    <div\n                      key={match.matchId}\n                      role=\"button\"\n                      tabIndex={0}\n                      className=\"ss-w-today-search-row\"\n                      onClick={() => setSelectedCompetitionId(group.competitionId)}\n                      onKeyDown={(e) => {\n                        if (e.target !== e.currentTarget) return\n                        if (e.key === 'Enter' || e.key === ' ') {\n                          e.preventDefault()\n                          setSelectedCompetitionId(group.competitionId)\n                        }\n                      }}\n                    >\n                      <FixtureRow match={match} state={states[match.matchId]} stale={stale} ui={ui} monitor={monitor} />\n                    </div>\n                  ))}\n                </div>\n              ))}\n            </>\n          )\n        ) : (\n          <>\n            <div className=\"ss-w-today-sec\">\n              {placement.personal ? ui.yourLeagues : ui.topLeagues}\n              {!placement.personal && <span className=\"ss-w-today-sec-sub\">{ui.topLeaguesSub}</span>}\n            </div>\n            <div className=\"ss-w-today-rowsection\">\n              {rowedCandidates.map((group) => (\n                <LeagueRowGroup\n                  key={group.competitionId}\n                  group={group}\n                  states={states}\n                  stale={stale}\n                  cap={ROW_CAP_PER_LEAGUE}\n                  starClickable={starClickable(group, placement.pinnedCompetitionId)}\n                  disambiguate={(nameCounts[group.competitionName] ?? 0) > 1}\n                  onOpen={() => setSelectedCompetitionId(group.competitionId)}\n                  starTap={gridStarTap}\n                  ui={ui}\n                  monitor={monitor}\n                />\n              ))}\n              {tiledCandidates.length > 0 && (\n                <div className=\"ss-w-today-tiles\">\n                  {tiledCandidates.map((group) => (\n                    <LeagueTile\n                      key={group.competitionId}\n                      group={group}\n                      starClickable={starClickable(group, placement.pinnedCompetitionId)}\n                      disambiguate={(nameCounts[group.competitionName] ?? 0) > 1}\n                      onOpen={() => setSelectedCompetitionId(group.competitionId)}\n                      starTap={gridStarTap}\n                      ui={ui}\n                    />\n                  ))}\n                </div>\n              )}\n            </div>\n\n            <div className=\"ss-w-today-sec\">{ui.allLeagues}</div>\n            <div className=\"ss-w-today-tiles\">\n              {placement.others.map((group) => (\n                <LeagueTile\n                  key={group.competitionId}\n                  group={group}\n                  starClickable={starClickable(group, placement.pinnedCompetitionId)}\n                  disambiguate={(nameCounts[group.competitionName] ?? 0) > 1}\n                  onOpen={() => setSelectedCompetitionId(group.competitionId)}\n                  starTap={gridStarTap}\n                  ui={ui}\n                />\n              ))}\n            </div>\n          </>\n        )}\n      </div>\n\n      {toast !== null && (\n        <p className=\"ss-w-today-toast\" role=\"status\" aria-live=\"polite\">\n          {toast === 'starred' ? ui.starredToast : ui.unstarredToast}\n        </p>\n      )}\n    </div>\n  )\n}\n","import type { ScheduleGroup } from '@sensiblestats/widget-sdk'\n\nexport interface PlacementResult {\n  personal: boolean\n  candidates: ScheduleGroup[]\n  others: ScheduleGroup[]\n  order: ScheduleGroup[]\n  pinnedCompetitionId: number | null\n}\n\nexport function placeLeagues(visible: readonly ScheduleGroup[], pinnedMatchIds: readonly number[]): PlacementResult {\n  const candidates: ScheduleGroup[] = []\n  const candidateIds = new Set<number>()\n\n  for (const g of visible) {\n    if (g.isStarred) { candidates.push(g); candidateIds.add(g.competitionId) }\n  }\n\n  let budget = 4\n  const pinned = visible.find(\n    (g) => !candidateIds.has(g.competitionId) && g.matches.some((m) => pinnedMatchIds.includes(m.matchId)),\n  ) ?? null\n  if (pinned && budget > 0) {\n    candidates.push(pinned); candidateIds.add(pinned.competitionId); budget -= 1\n  }\n\n  const learned = visible\n    .filter((g) => g.isLearned && !candidateIds.has(g.competitionId))\n    .sort((a, b) => (a.learnedRank ?? Number.MAX_SAFE_INTEGER) - (b.learnedRank ?? Number.MAX_SAFE_INTEGER))\n  for (const g of learned) {\n    if (budget <= 0) break\n    candidates.push(g); candidateIds.add(g.competitionId); budget -= 1\n  }\n\n  const personal = candidates.length > 0\n  const pool = personal ? candidates : visible.slice(0, 4)\n  const poolIds = personal ? candidateIds : new Set(pool.map((g) => g.competitionId))\n  const others = visible.filter((g) => !poolIds.has(g.competitionId))\n\n  return { personal, candidates: pool, others, order: [...pool, ...others], pinnedCompetitionId: pinned?.competitionId ?? null }\n}\n\n/** Whether a tile's star is tappable (spec §3): always true unless this is the one pin-sourced,\n *  not-otherwise-starred tile -- unpinning (not the tile star) is its removal path. */\nexport function starClickable(group: ScheduleGroup, pinnedCompetitionId: number | null): boolean {\n  return group.isStarred || group.competitionId !== pinnedCompetitionId\n}\n","import type { ScheduleGroup } from '@sensiblestats/widget-sdk'\n\n/** Turkish-aware fold: dotted/dotless I first (NOT canonically equivalent under NFD), then strip\n *  combining diacritics, then lowercase -- so \"besiktas\" matches \"Beşiktaş\" and \"istanbul\"\n *  matches \"İstanbul\". */\nexport function foldSearchText(s: string): string {\n  return s.replace(/İ/g, 'I').replace(/ı/g, 'i').normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase()\n}\n\nfunction competitionMatchesQuery(group: ScheduleGroup, q: string): boolean {\n  if (foldSearchText(group.competitionName).includes(q)) return true\n  return !!group.competitionCountry && foldSearchText(group.competitionCountry).includes(q)\n}\n\nexport function matchesQuery(group: ScheduleGroup, query: string): boolean {\n  const q = foldSearchText(query.trim())\n  if (!q) return true\n  if (competitionMatchesQuery(group, q)) return true\n  return group.matches.some(\n    (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q),\n  )\n}\n\n/** Fixtures from `group` to render for `query`: every fixture when the query matched the\n *  competition's own name/country, otherwise only the fixtures whose team names matched. */\nexport function matchingFixtures(group: ScheduleGroup, query: string): ScheduleGroup['matches'] {\n  const q = foldSearchText(query.trim())\n  if (!q || competitionMatchesQuery(group, q)) return group.matches\n  return group.matches.filter(\n    (m) => foldSearchText(m.homeTeamName).includes(q) || foldSearchText(m.awayTeamName).includes(q),\n  )\n}\n","import { useCallback, useRef, useState } from 'react'\n\n/** The in-flight-disable guard shared by LeagueTile (Task 5) and LeagueDetail (Task 6): a second\n *  tap while a star request is in flight is dropped rather than queued or fired again, and the\n *  pending id always clears -- success, rejection, or anything else -- so a failed call cannot\n *  leave the star permanently disabled. */\nexport function useStarTap(starLeague: (competitionId: number, starred: boolean) => Promise<boolean>): {\n  pendingId: number | null\n  tap: (competitionId: number, next: boolean) => Promise<boolean>\n} {\n  const [pendingId, setPendingId] = useState<number | null>(null)\n  // A ref, not just the state above: two taps fired in the same tick (no render between them)\n  // would both read the same stale `pendingId` closure value and both pass the guard. The ref is\n  // written synchronously, so the second tap's guard check always sees the first tap's claim.\n  const pendingRef = useRef<number | null>(null)\n\n  const tap = useCallback(async (competitionId: number, next: boolean): Promise<boolean> => {\n    if (pendingRef.current !== null) return false\n    pendingRef.current = competitionId\n    setPendingId(competitionId)\n    try {\n      return await starLeague(competitionId, next)\n    } finally {\n      pendingRef.current = null\n      setPendingId(null)\n    }\n  }, [starLeague])\n\n  return { pendingId, tap }\n}\n","import type { ScheduleGroup } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { useStarTap } from '../useStarTap'\nimport { Crest } from './Crest'\n\n// Same silhouette PinToggle uses for its 'star' glyph choice -- one path, outline (not starred)\n// vs filled (starred) via fill/stroke, so the two surfaces read as the same mark.\nconst STAR_PATH = 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z'\n\nexport function LeagueTile({ group, starClickable, disambiguate, onOpen, starTap, ui }: {\n  group: ScheduleGroup\n  starClickable: boolean\n  disambiguate: boolean\n  onOpen(): void\n  starTap: ReturnType<typeof useStarTap>\n  ui: UiConfig\n}): JSX.Element {\n  const onStarClick = (): void => {\n    void starTap.tap(group.competitionId, !group.isStarred)\n  }\n\n  return (\n    <div className=\"ss-w-today-tile\">\n      <button type=\"button\" className=\"ss-w-today-tile-body\" onClick={onOpen}>\n        <Crest url={group.competitionImagePath ?? undefined} name={group.competitionName} kind=\"comp\" />\n        <span className=\"ss-w-today-tile-name\">\n          {group.competitionName}\n          {disambiguate && group.competitionCountry\n            ? <span className=\"ss-w-today-tile-country\"> ({group.competitionCountry})</span>\n            : null}\n        </span>\n      </button>\n      <button\n        type=\"button\"\n        className=\"ss-w-today-tile-star\"\n        aria-pressed={group.isStarred}\n        aria-label={group.isStarred ? ui.starOffLabel : ui.starOnLabel}\n        disabled={!starClickable || starTap.pendingId !== null}\n        onClick={onStarClick}\n      >\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n          <path\n            d={STAR_PATH}\n            fill={group.isStarred ? 'currentColor' : 'none'}\n            stroke={group.isStarred ? 'none' : 'currentColor'}\n            strokeWidth={2}\n            strokeLinejoin=\"round\"\n            strokeLinecap=\"round\"\n          />\n        </svg>\n      </button>\n    </div>\n  )\n}\n","import { useEffect, useState } from 'react'\nimport type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { useStarTap } from '../useStarTap'\nimport { isTreatedLive } from '../liveClock'\nimport { FixtureRow } from './FixtureRow'\nimport { Crest } from './Crest'\nimport { ChevronIcon } from './Icons'\n\n// Same silhouette LeagueTile uses for its star glyph -- one path, outline (not starred) vs\n// filled (starred) via fill/stroke, so the two surfaces read as the same mark.\nconst STAR_PATH = 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z'\n\nexport function LeagueDetail({ group, position, states, stale, ui, monitor, starTap, onBack, onPrev, onNext }: {\n  group: ScheduleGroup\n  position: { index: number; total: number }\n  states: Record<number, MatchState>\n  stale: boolean\n  ui: UiConfig\n  monitor: LiveMonitorController\n  starTap: ReturnType<typeof useStarTap>\n  onBack(): void\n  onPrev(): void\n  onNext(): void\n}): JSX.Element {\n  const [toast, setToast] = useState<string | null>(null)\n\n  // Mirrors Toast.tsx's own DISMISS_MS: a toast that never clears stops being a toast, and would\n  // otherwise follow the user onto whichever league prev/next lands on next. Reset on the\n  // competition changing too -- the same mounted instance is reused across prev/next (Task 7),\n  // so a stale \"Added to Your leagues.\" must not survive onto a league the user never starred.\n  useEffect(() => {\n    setToast(null)\n  }, [group.competitionId])\n  useEffect(() => {\n    if (toast === null) return\n    const id = setTimeout(() => setToast(null), 4000)\n    return () => clearTimeout(id)\n  }, [toast])\n\n  // Same invariant CompetitionGroup held (Task 6 ports it verbatim): a live fixture is rendered\n  // in the live band TodayPanel owns, so it is absent here AND absent from the count -- the badge\n  // has to agree with what is under the header. Once the poll goes stale the live band hides\n  // itself, so a cached phase:'live' match must fall back into this list rather than vanish.\n  const own = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale))\n\n  // Unlike LeagueTile's star, this one is NEVER gated by starClickable (spec §3/§7's one named\n  // exception to the tile rule) -- a pin-sourced league's only way off this screen's star is the\n  // same tap that would be disabled on its tile.\n  const onStarClick = (): void => {\n    const next = !group.isStarred\n    void starTap.tap(group.competitionId, next).then((ok) => {\n      if (ok) setToast(next ? ui.starredToast : ui.unstarredToast)\n    })\n  }\n\n  return (\n    <div className=\"ss-w-today-detail\">\n      <div className=\"ss-w-today-detail-head\">\n        <button type=\"button\" className=\"ss-w-today-detail-back\" aria-label={ui.back} onClick={onBack}>\n          <ChevronIcon />\n        </button>\n        <Crest url={group.competitionImagePath ?? undefined} name={group.competitionName} kind=\"comp\" />\n        <span className=\"ss-w-today-detail-name\">{group.competitionName}</span>\n        <button\n          type=\"button\"\n          className=\"ss-w-today-detail-star\"\n          aria-pressed={group.isStarred}\n          aria-label={group.isStarred ? ui.starOffLabel : ui.starOnLabel}\n          disabled={starTap.pendingId !== null}\n          onClick={onStarClick}\n        >\n          <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n            <path\n              d={STAR_PATH}\n              fill={group.isStarred ? 'currentColor' : 'none'}\n              stroke={group.isStarred ? 'none' : 'currentColor'}\n              strokeWidth={2}\n              strokeLinejoin=\"round\"\n              strokeLinecap=\"round\"\n            />\n          </svg>\n        </button>\n      </div>\n\n      <div className=\"ss-w-today-detail-nav\">\n        <button type=\"button\" className=\"ss-w-today-detail-prev\" aria-label={ui.prevLeagueLabel}\n          disabled={position.index <= 1} onClick={onPrev}>\n          <ChevronIcon />\n        </button>\n        <span className=\"ss-w-today-detail-pos\">{ui.leagueDetailPosition(position.index, position.total)}</span>\n        <button type=\"button\" className=\"ss-w-today-detail-next\" aria-label={ui.nextLeagueLabel}\n          disabled={position.index >= position.total} onClick={onNext}>\n          <ChevronIcon />\n        </button>\n      </div>\n\n      <div className=\"ss-w-today-detail-body\">\n        <span className=\"ss-w-today-detail-count\">{own.length}</span>\n        {own.map((m) => (\n          <FixtureRow key={m.matchId} match={m} state={states[m.matchId]} stale={stale} ui={ui} monitor={monitor} />\n        ))}\n      </div>\n\n      {/* Layered status region, not a modal: an aria-live announcement that never intercepts a\n          pointer event, so the back/nav/star buttons above stay clickable while it is showing. */}\n      {toast !== null && (\n        <p className=\"ss-w-today-toast\" role=\"status\" aria-live=\"polite\">{toast}</p>\n      )}\n    </div>\n  )\n}\n","import type { MatchState, ScheduleMatch } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport { PinToggle } from './PinToggle'\n\nfunction kickoffLabel(kickoffUnix: number): string {\n  const d = new Date(kickoffUnix * 1000)\n  return `${`${d.getHours()}`.padStart(2, '0')}:${`${d.getMinutes()}`.padStart(2, '0')}`\n}\n\n// The away side mirrors the home side around the score: crest on the far (right)\n// edge, name aligned inward toward the score. Reversing the flow in CSS keeps the\n// DOM order crest→name identical to home, matching the away pattern used by the\n// fandash fixture/live cards.\nfunction Side({ name, crest, away = false }: { name: string; crest?: string | null; away?: boolean }): JSX.Element {\n  return (\n    <span className={away ? 'ss-w-drow-side ss-w-drow-side--away' : 'ss-w-drow-side'}>\n      {crest ? <img className=\"ss-w-drow-crest\" src={crest} alt=\"\" /> : null}\n      <span className=\"ss-w-drow-nm\">{name}</span>\n    </span>\n  )\n}\n\nexport function FixtureRow({ match, state, stale, ui, monitor }: {\n  match: ScheduleMatch\n  state?: MatchState\n  stale: boolean\n  ui: UiConfig\n  monitor: LiveMonitorController\n}): JSX.Element {\n  // Deliberately no per-match staleness test. u357 added one, reading Match.UpdatedAt through\n  // stateAsOfUtc — but that column advances only when the DATA CHANGES, not when we poll. Measured\n  // on sandbox1: every live match had a poll age of 31-48s while UpdatedAt ages ran 32-1451s, so\n  // the guard suppressed the clock on 9 of 17 healthy matches, Levante v Barcelona among them. The\n  // stalled window it was built for does not exist; `stale` (our own fetch failing) is the only\n  // real signal we have, and it already covers the whole payload.\n  const isLive = state?.phase === 'live' && !stale\n  // Gated on phase, never on the presence of a number: /states counts goal rows, so it reports 0\n  // for a fixture with none whatever its phase, and the due set polls anything whose kickoff clock\n  // has passed. A \"NotStarted\" fixture between the clock passing and the live feed flipping would\n  // otherwise read 0-0. The typeof pair only narrows the template below.\n  const hasScore = (state?.phase === 'live' || state?.phase === 'fullTime')\n    && typeof state.homeScore === 'number' && typeof state.awayScore === 'number'\n  const score = hasScore ? `${state!.homeScore}–${state!.awayScore}` : undefined\n\n  // Rendered verbatim. The minute runs ~2 min behind wall clock because the provider's own\n  // `minutes` field is a snapshot we freeze until the next poll -- that is being corrected at the\n  // source in the hub (deriving from the ticking period's start), NOT compensated for here. Two\n  // layers each adding elapsed to the same number is how you get a 139th minute.\n  const ticked = state?.phase === 'live' ? (state.minuteLabel ?? null) : null\n  const when = state?.isHalfTime && !stale\n    ? ui.halfTime\n    : isLive\n      ? (ticked ?? '\\u2014')\n      : state?.phase === 'live'\n        ? '\\u2014'\n        : kickoffLabel(match.kickoffUnix)\n\n  return (\n    <div className={isLive || state?.isHalfTime ? 'ss-w-drow ss-w-drow--live' : 'ss-w-drow'}>\n      <span className={isLive || state?.isHalfTime ? 'ss-w-drow-when ss-w-drow-when--live' : 'ss-w-drow-when'}>{when}</span>\n      <span className=\"ss-w-drow-fx\">\n        <Side name={match.homeTeamName} crest={match.homeTeamImagePath} />\n        {/* The score sits between the two sides, where a scoreboard puts it. With no score yet it\n            is the separating dash, so the row keeps one shape before and after kickoff. */}\n        <span className={hasScore ? 'ss-w-drow-sc' : 'ss-w-drow-sc ss-w-drow-sc--idle'}>\n          {score ?? '–'}\n        </span>\n        <Side name={match.awayTeamName} crest={match.awayTeamImagePath} away />\n      </span>\n      <PinToggle ui={ui} monitor={monitor} pin={{ kind: 'match', matchId: match.matchId }} />\n    </div>\n  )\n}\n","import type { MatchState, ScheduleGroup } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { LiveMonitorController } from '../useLiveMonitor'\nimport type { useStarTap } from '../useStarTap'\nimport { isTreatedLive } from '../liveClock'\nimport { FixtureRow } from './FixtureRow'\nimport { Crest } from './Crest'\n\nexport const ROW_CAP_PER_LEAGUE = 3\nexport const SECTION_ROW_BUDGET = 12\n\n/** Rows this group would consume in the section budget -- same live-hoisting invariant as\n *  LeagueDetail's `own` (liveClock.ts): a live fixture renders in the band above, never counted\n *  here too. */\nexport function rowsFor(group: ScheduleGroup, states: Record<number, MatchState>, stale: boolean): number {\n  const nonLive = group.matches.filter((m) => !isTreatedLive(states[m.matchId], stale)).length\n  return Math.min(nonLive, ROW_CAP_PER_LEAGUE)\n}\n\n// Same silhouette LeagueTile/LeagueDetail use for the star glyph -- one path, outline (not\n// starred) vs filled (starred) via fill/stroke, so all three surfaces read as the same mark.\nconst STAR_PATH = 'M12 2.5l2.9 5.9 6.5.95-4.7 4.58 1.1 6.47L12 17.35 6.1 20.4l1.1-6.47L2.5 9.35l6.5-.95z'\n\nexport function LeagueRowGroup({ group, states, stale, cap, starClickable, disambiguate, onOpen, starTap, ui, monitor }: {\n  group: ScheduleGroup\n  states: Record<number, MatchState>\n  stale: boolean\n  cap: number\n  starClickable: boolean\n  disambiguate: boolean\n  onOpen(): void\n  starTap: ReturnType<typeof useStarTap>\n  ui: UiConfig\n  monitor: LiveMonitorController\n}): JSX.Element | null {\n  const sorted = group.matches\n    .filter((m) => !isTreatedLive(states[m.matchId], stale))\n    .sort((a, b) => a.kickoffUnix - b.kickoffUnix)\n  // A league whose only match(es) just went live loses its row entirely rather than rendering an\n  // empty header -- callers fall back to a tile for this case (today's behavior), same as a group\n  // that never made it into placement.\n  if (sorted.length === 0) return null\n\n  const shown = sorted.slice(0, cap)\n  const overflow = sorted.length - shown.length\n\n  const onStarClick = (): void => {\n    void starTap.tap(group.competitionId, !group.isStarred)\n  }\n\n  return (\n    <div className=\"ss-w-today-rowgroup\">\n      <div className=\"ss-w-today-rowgroup-head\">\n        <button type=\"button\" className=\"ss-w-today-rowgroup-head-body\" onClick={onOpen}>\n          <Crest url={group.competitionImagePath ?? undefined} name={group.competitionName} kind=\"comp\" />\n          <span className=\"ss-w-today-rowgroup-name\">\n            {group.competitionName}\n            {disambiguate && group.competitionCountry\n              ? <span className=\"ss-w-today-tile-country\"> ({group.competitionCountry})</span>\n              : null}\n          </span>\n        </button>\n        <button\n          type=\"button\"\n          className=\"ss-w-today-rowgroup-star\"\n          aria-pressed={group.isStarred}\n          aria-label={group.isStarred ? ui.starOffLabel : ui.starOnLabel}\n          disabled={!starClickable || starTap.pendingId !== null}\n          onClick={onStarClick}\n        >\n          <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n            <path\n              d={STAR_PATH}\n              fill={group.isStarred ? 'currentColor' : 'none'}\n              stroke={group.isStarred ? 'none' : 'currentColor'}\n              strokeWidth={2}\n              strokeLinejoin=\"round\"\n              strokeLinecap=\"round\"\n            />\n          </svg>\n        </button>\n      </div>\n      <div className=\"ss-w-today-rowgroup-rows\">\n        {shown.map((m) => (\n          <FixtureRow key={m.matchId} match={m} state={states[m.matchId]} stale={stale} ui={ui} monitor={monitor} />\n        ))}\n      </div>\n      {overflow > 0 && (\n        <button type=\"button\" className=\"ss-w-today-rowgroup-seeall\" onClick={onOpen}>\n          {ui.seeAllFixturesLabel(sorted.length)}\n        </button>\n      )}\n    </div>\n  )\n}\n","import { useCallback, useRef } from 'react'\nimport type { KeyboardEvent, MutableRefObject, Ref } from 'react'\nimport { IconClose, IconSearch } from './icons'\n\nexport function SearchField({ id, label, labelHidden = false, placeholder, value, onChange, disabled, inputRef, onKeyDown, clearLabel }: {\n  id: string; label: string; labelHidden?: boolean; placeholder: string; value: string\n  onChange: (v: string) => void; disabled?: boolean; inputRef?: Ref<HTMLInputElement>\n  onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void; clearLabel?: string\n}): JSX.Element {\n  const localRef = useRef<HTMLInputElement | null>(null)\n  const setInputRef = useCallback((node: HTMLInputElement | null) => {\n    localRef.current = node\n    if (typeof inputRef === 'function') inputRef(node)\n    else if (inputRef) (inputRef as MutableRefObject<HTMLInputElement | null>).current = node\n  }, [inputRef])\n  return (\n    <div className=\"ss-g-search\">\n      <label htmlFor={id} className={labelHidden ? 'ss-g-sr' : 'ss-g-search-label'}>{label}</label>\n      <div className=\"ss-g-search-box\">\n        <IconSearch />\n        <input id={id} ref={setInputRef} type=\"text\" autoComplete=\"off\" placeholder={placeholder} value={value}\n          disabled={disabled} onKeyDown={onKeyDown} onChange={e => onChange(e.target.value)} />\n        {clearLabel && value.length > 0 ? (\n          <button type=\"button\" className=\"ss-g-search-clear\" aria-label={clearLabel}\n            onClick={() => { onChange(''); localRef.current?.focus() }}>\n            <IconClose size={11} />\n          </button>\n        ) : null}\n      </div>\n    </div>\n  )\n}\n","type P = { size?: number }\nconst svg = (size: number, children: JSX.Element | JSX.Element[], fill = false): JSX.Element => (\n  <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={fill ? 'currentColor' : 'none'} stroke={fill ? 'none' : 'currentColor'}\n    strokeWidth={2.2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">{children}</svg>\n)\nexport const IconChevronLeft = ({ size = 20 }: P) => svg(size, <path d=\"M15 18l-6-6 6-6\" />)\nexport const IconLock = ({ size = 14 }: P) => svg(size, [<rect key=\"a\" x=\"5\" y=\"11\" width=\"14\" height=\"10\" rx=\"2\" />, <path key=\"b\" d=\"M8 11V7a4 4 0 0 1 8 0v4\" />])\nexport const IconCheck = ({ size = 14 }: P) => svg(size, <path d=\"M5 12l5 5 9-10\" />)\nexport const IconClose = ({ size = 16 }: P) => svg(size, <path d=\"M6 6l12 12M18 6L6 18\" />)\nexport const IconSearch = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"11\" cy=\"11\" r=\"7\" />, <path key=\"b\" d=\"M20 20l-3.5-3.5\" />])\nexport const IconPlus = ({ size = 20 }: P) => svg(size, <path d=\"M12 5v14M5 12h14\" />)\nexport const IconStar = ({ size = 14 }: P) => svg(size, <path d=\"M12 2.5l2.9 6 6.6.8-4.9 4.5 1.3 6.5L12 17l-5.9 3.3 1.3-6.5L2.5 9.3l6.6-.8z\" />, true)\nexport const IconBulb = ({ size = 16 }: P) => svg(size, [<path key=\"a\" d=\"M9 18h6M10 21h4\" />, <path key=\"b\" d=\"M12 3a6 6 0 0 0-3.5 10.9V16h7v-2.1A6 6 0 0 0 12 3z\" />])\nexport const IconArrowUp = ({ size = 12 }: P) => svg(size, <path d=\"M12 19V5M5 12l7-7 7 7\" />)\nexport const IconArrowDown = ({ size = 12 }: P) => svg(size, <path d=\"M12 5v14M19 12l-7 7-7-7\" />)\nexport const IconCalendar = ({ size = 18 }: P) => svg(size, [<rect key=\"a\" x=\"4\" y=\"5\" width=\"16\" height=\"15\" rx=\"2\" />, <path key=\"b\" d=\"M4 10h16M9 3v4M15 3v4\" />])\nexport const IconShield = ({ size = 18 }: P) => svg(size, <path d=\"M12 3l7 3v6c0 5-3 8-7 9-4-1-7-4-7-9V6z\" />)\nexport const IconFlag = ({ size = 18 }: P) => svg(size, <path d=\"M5 21V4M5 4h12l-2 4 2 4H5\" />)\nexport const IconBall = ({ size = 18 }: P) => svg(size, [<circle key=\"a\" cx=\"12\" cy=\"12\" r=\"9\" />, <path key=\"b\" d=\"M12 7l4 3-1.5 4.5h-5L8 10z\" />])\nexport const IconBoot = ({ size = 18 }: P) => svg(size, <path d=\"M4 6h6l1 6 8 3v3H4z\" />)\nexport const IconGloves = ({ size = 18 }: P) => svg(size, <path d=\"M7 21v-8l-2-3V6a1.5 1.5 0 0 1 3 0v3V4a1.5 1.5 0 0 1 3 0v5V3.5a1.5 1.5 0 0 1 3 0V9V5a1.5 1.5 0 0 1 3 0v9l-2 3v4z\" />)\nexport const IconFlame = ({ size = 16 }: P) => svg(size, <path d=\"M12 3c1 4 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-7 1.5 1 2 2 2 3 1-2 1-4 1-6z\" />, true)\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { GamesHub } from './GamesHub'\nimport { GameScreenHost } from './GameScreenHost'\nimport { LeaderboardPanel } from './LeaderboardPanel'\nimport { ensureGamesFonts } from './games/ui/fonts'\n\nexport function GamesPanel({\n  loggedIn,\n  games,\n  ui,\n  conversation,\n  leaderboard,\n  leaderboardLoading,\n  refreshHub,\n}: {\n  loggedIn: boolean\n  games: GameSummary[]\n  ui: UiConfig\n  conversation?: GamePlayConversation | null\n  leaderboard?: LeaderboardPayload | null\n  leaderboardLoading?: boolean\n  /** Called when a play is saved and when the fan leaves a game screen, so the hub's tiles and stat row reflect the play. */\n  refreshHub?: () => void\n}): JSX.Element {\n  const [selected, setSelected] = useState<{ gameId: string; fixtureId: number; gameDay: string; lockAtUtc: string | null } | null>(null)\n  const [segment, setSegment] = useState<'play' | 'leaderboard'>('play')\n\n  useEffect(() => { ensureGamesFonts() }, [])\n\n  if (!loggedIn) return <GamesLoginWall ui={ui} />\n\n  if (selected !== null) {\n    return (\n      <div className=\"ss-w-gscreen-wrap\" lang={ui.games.lang}>\n        <GameScreenHost\n          selected={selected}\n          onBack={() => { setSelected(null); refreshHub?.() }}\n          onPlayed={refreshHub}\n          conversation={conversation ?? null}\n          ui={ui}\n        />\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"ss-g-hub-wrap\" lang={ui.games.lang}>\n      <div className=\"ss-w-seg\">\n        <button\n          type=\"button\"\n          className=\"ss-w-seg-btn\"\n          {...(segment === 'play' ? { 'data-on': '' } : {})}\n          onClick={() => setSegment('play')}\n        >\n          {ui.gamesPlaySegment}\n        </button>\n        <button\n          type=\"button\"\n          className=\"ss-w-seg-btn\"\n          {...(segment === 'leaderboard' ? { 'data-on': '' } : {})}\n          onClick={() => setSegment('leaderboard')}\n        >\n          {ui.tabLeaderboard}\n        </button>\n      </div>\n      {segment === 'play' ? (\n        <div data-testid=\"games-hub\" lang={ui.games.lang}>\n          <GamesHub\n            games={games}\n            onOpen={(g: GameSummary) => setSelected({ gameId: g.gameId, fixtureId: g.fixtureId, gameDay: g.gameDay, lockAtUtc: g.lockAtUtc ?? null })}\n            myWeeklyRow={leaderboard?.myWeeklyRow ?? null}\n            ui={ui}\n          />\n        </div>\n      ) : (\n        <LeaderboardPanel\n          loggedIn={loggedIn}\n          data={leaderboard ?? null}\n          loading={leaderboardLoading ?? false}\n          onPlay={() => setSegment('play')}\n          ui={ui}\n        />\n      )}\n    </div>\n  )\n}\n","import type { UiConfig } from '../config'\n\nexport function GamesLoginWall({ ui }: { ui: UiConfig }): JSX.Element {\n  return (\n    <div className=\"ss-w-mon-list\">\n      <div className=\"ss-w-games-wall\">\n        <p>{ui.gamesLoginRequired}</p>\n      </div>\n    </div>\n  )\n}\n","import { useEffect, useState } from 'react'\nimport type { GameSummary, LeaderboardRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GameTile } from './GameTile'\nimport { Chip } from './games/ui/Chip'\nimport { IconFlame } from './games/ui/icons'\n\nconst PLAYABLE = new Set<GameSummary['status']>(['available', 'in_progress'])\nconst DONE = new Set<GameSummary['status']>(['played', 'graded'])\n\nexport function pickHeroGame(games: GameSummary[]): GameSummary | null {\n  const daily = games.filter(g => g.kind === 'daily')\n  const tiger = daily.find(g => g.gameId === 'mystery-tiger')\n  if (tiger && PLAYABLE.has(tiger.status)) return tiger\n  const firstPlayable = daily.find(g => PLAYABLE.has(g.status))\n  if (firstPlayable) return firstPlayable\n  return tiger ?? daily[0] ?? null\n}\n\n// Two fixtures of one game on one day must not share a key.\nexport const tileKey = (g: GameSummary): string => `${g.gameId}-${g.gameDay}-${g.fixtureId}`\n\nexport function GamesHub({ games, myWeeklyRow, weeklyPrize, onOpen, ui }: {\n  games: GameSummary[]\n  myWeeklyRow?: LeaderboardRow | null\n  weeklyPrize?: string\n  onOpen: (g: GameSummary) => void\n  ui: UiConfig\n}): JSX.Element {\n  const [, setTick] = useState(0)\n  useEffect(() => {\n    const id = setInterval(() => setTick(t => t + 1), 60_000)\n    return () => clearInterval(id)\n  }, [])\n\n  const hero = pickHeroGame(games)\n  const daily = games.filter(g => g.kind === 'daily' && g !== hero)\n  const grid = daily.filter(g => g.gameId !== 'beat-the-grid')\n  const wide = daily.find(g => g.gameId === 'beat-the-grid')\n  const fixtures = games.filter(g => g.kind === 'fixture')\n  const kickoffs = fixtures.map(g => g.kickoffUtc).filter((k): k is string => !!k).sort()\n  const todayPts = games.filter(g => DONE.has(g.status)).reduce((s, g) => s + (g.score ?? 0), 0)\n  const dash = '—'\n\n  return (\n    <div className=\"ss-g-hub\">\n      <div className=\"ss-g-stats\">\n        <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statStreak}</span>\n          <span className=\"ss-g-stat-v\" data-testid=\"stat-streak\">\n            {myWeeklyRow ? <><IconFlame />{myWeeklyRow.currentStreak}</> : dash}\n            {myWeeklyRow && <small>{ui.games.unitDays}</small>}\n          </span></div>\n        <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statToday}</span>\n          <span className=\"ss-g-stat-v ss-g-stat-v--accent\" data-testid=\"stat-today\">{ui.games.formatPts(todayPts)}<small>{ui.games.unitPts}</small></span></div>\n        <div className=\"ss-g-stat\"><span className=\"ss-g-stat-l\">{ui.games.statRank}</span>\n          <span className=\"ss-g-stat-v\" data-testid=\"stat-rank\">{myWeeklyRow ? `#${myWeeklyRow.rank}` : dash}\n            {myWeeklyRow && <small>{ui.games.thisWeek}</small>}</span></div>\n      </div>\n\n      {weeklyPrize && <Chip variant=\"accent\" className=\"ss-g-prize\">{weeklyPrize}</Chip>}\n\n      {hero && <GameTile game={hero} onOpen={onOpen} ui={ui} variant=\"hero\" />}\n\n      {(grid.length > 0 || wide) && (\n        <section className=\"ss-g-sec\">\n          <div className=\"ss-g-sec-head\"><h3>{ui.games.dailyGames}</h3><span>{ui.games.newSetAtMidnight}</span></div>\n          {grid.length > 0 && <div className=\"ss-g-grid\">{grid.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>}\n          {wide && <GameTile game={wide} onOpen={onOpen} ui={ui} variant=\"wide\" />}\n        </section>\n      )}\n\n      {fixtures.length > 0 && (\n        <section className=\"ss-g-sec\">\n          <div className=\"ss-g-sec-head\"><h3>{ui.games.matchdayGames}</h3>\n            {kickoffs[0] && <span>{ui.games.kickoffAt(ui.games.formatDayTime(kickoffs[0]))}</span>}</div>\n          <div className=\"ss-g-grid\">{fixtures.map(g => <GameTile key={tileKey(g)} game={g} onOpen={onOpen} ui={ui} />)}</div>\n        </section>\n      )}\n    </div>\n  )\n}\n","function prettifyGameId(gameId: string): string {\n  return gameId.split('-').map(w => (w ? w[0]!.toUpperCase() + w.slice(1) : w)).join(' ')\n}\n\n// `title` is nullable because GameSummary.title is `string | null` (widget-sdk events.ts).\n// `titles` is the locale-specific map from GamesStrings — caller passes `ui.games.titles`.\nexport function gameTitle(g: { gameId: string; title?: string | null }, titles: Record<string, string>): string {\n  return g.title ?? titles[g.gameId] ?? prettifyGameId(g.gameId)\n}\n\n// Design renders \"first name\" small over \"SURNAME\" big. Surname = last token.\nexport function splitName(full: string): { first: string; last: string } {\n  const parts = full.trim().split(/\\s+/).filter(Boolean)\n  if (parts.length <= 1) return { first: '', last: parts[0] ?? '' }\n  return { first: parts.slice(0, -1).join(' '), last: parts[parts.length - 1]! }\n}\n","export function GameTileArt({ gameId }: { gameId: string }): JSX.Element {\n  return (\n    <svg className=\"ss-g-art\" viewBox=\"0 0 120 74\" aria-hidden=\"true\">{ART[gameId] ?? ART.default}</svg>\n  )\n}\n\nconst head = (cx: number, cy: number, r: number, cls = 'ss-g-art-fg') => (\n  <g className={cls}><circle cx={cx} cy={cy - r * 0.3} r={r * 0.45} /><path d={`M${cx - r} ${cy + r}c0-${r * 0.8} ${r * 0.45}-${r * 1.1} ${r}-${r * 1.1}s${r} ${r * 0.3} ${r} ${r * 1.1}z`} /></g>\n)\n\nconst ART: Record<string, JSX.Element> = {\n  'mystery-tiger': <>{head(60, 38, 26, 'ss-g-art-fg')}<text x=\"60\" y=\"36\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n  'higher-or-lower': <>{head(32, 38, 20)}{head(88, 38, 20)}<circle cx=\"60\" cy=\"37\" r=\"11\" className=\"ss-g-art-accent\" /><path d=\"M57 33l3-3 3 3M57 41l3 3 3-3\" className=\"ss-g-art-ink\" /></>,\n  'guess-the-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60, 'a'], [24, 46], [48, 46], [72, 46], [96, 46], [36, 30], [60, 30], [84, 30], [40, 14], [60, 14], [80, 14]].map(([x, y, a], i) => <circle key={i} cx={x as number} cy={y as number} r=\"4\" className={a ? 'ss-g-art-accent' : 'ss-g-art-dot'} />)}</>,\n  'daily-quiz': <>{[[14, 8], [62, 8], [14, 40], [62, 40]].map(([x, y], i) => <rect key={i} x={x} y={y} width=\"44\" height=\"26\" rx=\"5\" className={i === 1 ? 'ss-g-art-correct' : 'ss-g-art-block'} />)}</>,\n  'career-path': <><path d=\"M18 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><path d=\"M48 37h8M84 37h8\" className=\"ss-g-art-line\" /><path d=\"M60 22h24v10c0 7-5 11-12 13-7-2-12-6-12-13z\" className=\"ss-g-art-fg\" /><rect x=\"96\" y=\"22\" width=\"18\" height=\"26\" rx=\"4\" className=\"ss-g-art-dash\" /><text x=\"105\" y=\"40\" className=\"ss-g-art-q\" textAnchor=\"middle\">?</text></>,\n  'beat-the-grid': <>{[0, 1, 2].flatMap(r => [0, 1, 2].map(c => <rect key={`${r}${c}`} x={33 + c * 19} y={10 + r * 19} width=\"16\" height=\"16\" rx=\"3\" className={(r + c) % 3 === 0 ? 'ss-g-art-accent' : 'ss-g-art-block'} />))}</>,\n  'matchday-predictor': <><path d=\"M10 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /><rect x=\"38\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-accent-stroke\" /><rect x=\"64\" y=\"22\" width=\"18\" height=\"24\" rx=\"4\" className=\"ss-g-art-dash\" /><path d=\"M90 20h20v9c0 6-4 9-10 11-6-2-10-5-10-11z\" className=\"ss-g-art-fg\" /></>,\n  'starting-xi': <><rect x=\"8\" y=\"4\" width=\"104\" height=\"66\" rx=\"6\" className=\"ss-g-art-pitch\" />{[[60, 60], [30, 46], [50, 46], [70, 46], [90, 46], [45, 30], [75, 30], [30, 16], [60, 16], [90, 16]].map(([x, y], i) => <circle key={i} cx={x} cy={y} r=\"5\" className={i < 7 ? 'ss-g-art-accent' : 'ss-g-art-dash'} />)}</>,\n  'stat-ladder': <>{[[20, 70], [34, 52], [48, 34]].map(([y, w], i) => <rect key={i} x=\"24\" y={y} width={w} height=\"12\" rx=\"3\" className={i === 1 ? 'ss-g-art-accent' : 'ss-g-art-block'} />)}</>,\n  'fan-motm': <><circle cx=\"60\" cy=\"37\" r=\"26\" className=\"ss-g-art-accent-stroke\" />{head(60, 40, 18)}<path d=\"M84 8l2.4 5 5.4.6-4 3.7 1.1 5.4-4.9-2.7-4.9 2.7 1.1-5.4-4-3.7 5.4-.6z\" className=\"ss-g-art-accent\" /></>,\n  default: <circle cx=\"60\" cy=\"37\" r=\"22\" className=\"ss-g-art-fg\" />,\n}\n","import type { ReactNode } from 'react'\n\nexport type ChipVariant = 'neutral' | 'accent' | 'success' | 'badge' | 'lock'\n\nexport function Chip({ variant = 'neutral', icon, children, className }: {\n  variant?: ChipVariant; icon?: ReactNode; children: ReactNode; className?: string\n}): JSX.Element {\n  return (\n    <span className={`ss-g-chip ss-g-chip--${variant}${className ? ` ${className}` : ''}`}>\n      {icon}{children}\n    </span>\n  )\n}\n\nexport function StatStack({ value, label }: { value: ReactNode; label: string }): JSX.Element {\n  return (\n    <span className=\"ss-g-statstack\">\n      <span className=\"ss-g-statstack-v\">{value}</span>\n      <span className=\"ss-g-statstack-l\">{label}</span>\n    </span>\n  )\n}\n","import type { GameSummary } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { gameTitle } from './games/ui/gameMeta'\nimport { GameTileArt } from './GameTileArt'\nimport { Chip } from './games/ui/Chip'\nimport { IconChevronLeft } from './games/ui/icons'\n\nexport type TileTone = 'new' | 'accent' | 'success' | 'muted'\n\n/** Pure: the tile's status line and tone, from the existing GameSummary fields only. */\nexport function tileStatus(game: GameSummary, ui: UiConfig): { text: string; tone: TileTone } {\n  switch (game.status) {\n    case 'locked': return { text: ui.gameLocked, tone: 'muted' }\n    case 'voided': return { text: ui.gameVoided, tone: 'muted' }\n    case 'in_progress': return { text: ui.games.resume, tone: 'accent' }\n    case 'played':\n    case 'graded':\n      return game.ranked\n        ? { text: ui.games.doneWithScore(game.score ?? 0), tone: 'success' }\n        : { text: ui.games.done, tone: 'success' }\n    default:\n      if (game.kind === 'fixture' && game.lockAtUtc && new Date(game.lockAtUtc).getTime() > Date.now()) {\n        return { text: ui.games.locksAt(ui.games.formatDayTime(game.lockAtUtc)), tone: 'accent' }\n      }\n      return { text: ui.games.taglines[game.gameId] ?? ui.gamePlay, tone: 'new' }\n  }\n}\n\nconst DISABLED = new Set<GameSummary['status']>(['locked', 'voided'])\n\nexport function GameTile({ game, onOpen, ui, variant = 'tile' }: {\n  game: GameSummary; onOpen: (g: GameSummary) => void; ui: UiConfig; variant?: 'tile' | 'wide' | 'hero'\n}): JSX.Element {\n  const status = tileStatus(game, ui)\n  const disabled = DISABLED.has(game.status)\n  const title = gameTitle(game, ui.games.titles)\n\n  const body = variant === 'hero' ? (\n    <>\n      <span className=\"ss-g-hero-text\">\n        <span className=\"ss-g-hero-eyebrow\">{ui.games.dailyChallenge}</span>\n        {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n        <span className=\"ss-g-hero-title\">{title}</span>\n        <span className=\"ss-g-hero-sub\">{ui.games.taglines[game.gameId] ?? ''}</span>\n        {status.tone === 'success'\n          ? <span className=\"ss-g-tile-status\" data-tone=\"success\">{status.text}</span>\n          : <span className=\"ss-g-hero-cta\">{status.tone === 'accent' ? ui.games.resume : ui.games.playNow} →</span>}\n      </span>\n      <span className=\"ss-g-hero-art\"><GameTileArt gameId={game.gameId} /></span>\n    </>\n  ) : variant === 'wide' ? (\n    <>\n      <span className=\"ss-g-wide-art\"><GameTileArt gameId={game.gameId} /></span>\n      <span className=\"ss-g-wide-text\">\n        <span className=\"ss-g-tile-title\">{title}</span>\n        <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n        {status.tone === 'new' && <Chip variant=\"badge\">{ui.games.newToday}</Chip>}\n      </span>\n      <span className=\"ss-g-wide-chev\"><IconChevronLeft size={18} /></span>\n    </>\n  ) : (\n    <>\n      <span className=\"ss-g-tile-art\"><GameTileArt gameId={game.gameId} /></span>\n      <span className=\"ss-g-tile-title\">{title}</span>\n      <span className=\"ss-g-tile-status\" data-tone={status.tone}>{status.text}</span>\n    </>\n  )\n\n  const cls = `ss-g-tile ss-g-tile--${variant}`\n  if (disabled) return <div className={cls} data-disabled aria-disabled=\"true\">{body}</div>\n  return <button type=\"button\" className={cls} aria-label={`${title} — ${status.text}`} onClick={() => onOpen(game)}>{body}</button>\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { UiConfig } from '../config'\nimport type { GamePlayConversation } from '../useGamePlay'\nimport { useGamePlay } from '../useGamePlay'\nimport { MysteryTigerGame } from './games/MysteryTigerGame'\nimport { HigherOrLowerGame } from './games/HigherOrLowerGame'\nimport { CareerPathGame } from './games/CareerPathGame'\nimport { BeatTheGridGame } from './games/BeatTheGridGame'\nimport { GuessTheXiGame } from './games/GuessTheXiGame'\nimport { DailyQuizGame } from './games/DailyQuizGame'\nimport { MatchdayPredictorGame } from './games/MatchdayPredictorGame'\nimport { StartingXiGame } from './games/StartingXiGame'\nimport { StatLadderGame } from './games/StatLadderGame'\nimport { FanMotmGame } from './games/FanMotmGame'\nimport { GameHeader } from './games/ui/GameHeader'\nimport { gameTitle } from './games/ui/gameMeta'\nimport type {\n  MysteryTigerConfig,\n  HolConfig,\n  CareerPathConfig,\n  BeatTheGridConfig,\n  GuessTheXiConfig,\n  DailyQuizConfig,\n  MatchdayPredictorConfig,\n  StartingXiConfig,\n  StatLadderConfig,\n  FanMotmConfig,\n} from './games/types'\n\n// Fixture games need a pending-result poll: they submit once before kickoff,\n// then remain in \"pending\" until resolved at full time.\nconst FIXTURE_GAME_IDS = new Set([\n  'matchday-predictor',\n  'starting-xi',\n  'stat-ladder',\n  'fan-motm',\n])\n\n// Poll cadence while a fixture game result is pending (30 seconds).\nconst PENDING_POLL_INTERVAL_MS = 30_000\n\nfunction safeParseConfig<T>(json: string | null | undefined): T | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as T\n  } catch {\n    return null\n  }\n}\n\nexport function GameScreenHost({\n  selected,\n  onBack,\n  onPlayed,\n  conversation,\n  ui,\n}: {\n  selected: { gameId: string; fixtureId: number; gameDay?: string; lockAtUtc?: string | null }\n  onBack: () => void\n  /** Called once a submitted play has been saved, so the hub can refetch points and status. */\n  onPlayed?: () => void\n  conversation: GamePlayConversation | null | undefined\n  ui: UiConfig\n}): JSX.Element {\n  const { gameId, fixtureId, gameDay = '', lockAtUtc = null } = selected\n\n  // Fetch config on open\n  const [configJson, setConfigJson] = useState<string | null>(null)\n\n  useEffect(() => {\n    setConfigJson(null)\n    if (!conversation) return\n    let cancelled = false\n    void (async () => {\n      try {\n        const payload = await conversation.getGameConfig(gameId, fixtureId, gameDay || undefined, ui.games.lang)\n        if (!cancelled && payload?.configJson) {\n          setConfigJson(payload.configJson)\n        }\n      } catch {\n        // best-effort\n      }\n    })()\n    return () => { cancelled = true }\n  }, [conversation, gameId, fixtureId, gameDay, ui.games.lang])\n\n  // Shared submit lifecycle\n  const { result, submitting, submit, hydrate, rawStatus } = useGamePlay(conversation, {\n    gameId,\n    gameDay: gameDay,\n    fixtureId: fixtureId || undefined,\n    locale: ui.games.lang,\n  })\n\n  // Hydrate on open for a returning fan\n  useEffect(() => {\n    if (conversation) hydrate()\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [conversation, gameId])\n\n  // Pending-result poll: while a fixture game result is pending (submitted but not yet\n  // resolved at full time), poll getGameResult at a low cadence until graded or voided.\n  const hydrateRef = useRef(hydrate)\n  hydrateRef.current = hydrate\n\n  useEffect(() => {\n    if (!FIXTURE_GAME_IDS.has(gameId)) return\n    if (rawStatus !== 'pending') return\n\n    const timerId = setInterval(() => {\n      hydrateRef.current()\n    }, PENDING_POLL_INTERVAL_MS)\n\n    return () => clearInterval(timerId)\n  }, [gameId, rawStatus])\n\n  const sharedProps = {\n    result,\n    submitting,\n    // Refresh only after the play is saved: a fan can tap Back while a submit is still in flight,\n    // and a refetch fired from Back alone would read the hub's pre-play state.\n    onSubmit: (answerJson: string) => { void submit(answerJson).then(() => onPlayed?.()) },\n    ui,\n    onBack,\n    lockAtUtc,\n  }\n\n  function renderScreen(): JSX.Element {\n    switch (gameId) {\n      case 'mystery-tiger':\n        return (\n          <MysteryTigerGame\n            {...sharedProps}\n            config={safeParseConfig<MysteryTigerConfig>(configJson)}\n          />\n        )\n      case 'higher-or-lower':\n        return (\n          <HigherOrLowerGame\n            {...sharedProps}\n            config={safeParseConfig<HolConfig>(configJson)}\n          />\n        )\n      case 'career-path':\n        return (\n          <CareerPathGame\n            {...sharedProps}\n            config={safeParseConfig<CareerPathConfig>(configJson)}\n          />\n        )\n      case 'beat-the-grid': {\n        const btgConfig = safeParseConfig<BeatTheGridConfig>(configJson)\n        return (\n          <BeatTheGridGame\n            {...sharedProps}\n            config={btgConfig}\n            playerPool={btgConfig?.playerPool ?? []}\n          />\n        )\n      }\n      case 'guess-the-xi':\n        return (\n          <GuessTheXiGame\n            {...sharedProps}\n            config={safeParseConfig<GuessTheXiConfig>(configJson)}\n          />\n        )\n      case 'daily-quiz':\n        return (\n          <DailyQuizGame\n            {...sharedProps}\n            config={safeParseConfig<DailyQuizConfig>(configJson)}\n          />\n        )\n      case 'matchday-predictor':\n        return (\n          <MatchdayPredictorGame\n            {...sharedProps}\n            config={safeParseConfig<MatchdayPredictorConfig>(configJson)}\n          />\n        )\n      case 'starting-xi':\n        return (\n          <StartingXiGame\n            {...sharedProps}\n            config={safeParseConfig<StartingXiConfig>(configJson)}\n          />\n        )\n      case 'stat-ladder':\n        return (\n          <StatLadderGame\n            {...sharedProps}\n            config={safeParseConfig<StatLadderConfig>(configJson)}\n          />\n        )\n      case 'fan-motm':\n        return (\n          <FanMotmGame\n            {...sharedProps}\n            config={safeParseConfig<FanMotmConfig>(configJson)}\n          />\n        )\n      default:\n        return (\n          <div className=\"ss-g-screen\" data-testid={`game-screen-${gameId}`}>\n            <GameHeader title={gameTitle({ gameId }, ui.games.titles)} onBack={onBack} backLabel={ui.back} />\n          </div>\n        )\n    }\n  }\n\n  return (\n    <div className=\"ss-w-gscreen\" data-testid=\"gscreen\" data-lock-at={lockAtUtc ?? undefined}>\n      {renderScreen()}\n    </div>\n  )\n}\n","import { useCallback, useRef, useState } from 'react'\nimport type { GameResultPayload, GameStatePayload, SubmitPlayResult } from '@sensiblestats/widget-sdk'\n\nexport interface UseGamePlayOptions {\n  gameId: string\n  gameDay: string\n  fixtureId?: number\n  locale?: string\n  /** Called after a ranked play completes (pointsDelta present). */\n  refresh?: () => void\n}\n\nexport interface UseGamePlayResult {\n  result: SubmitPlayResult | null\n  submitting: boolean\n  submit: (answerJson: string) => Promise<void>\n  hydrate: () => void\n  /** Raw status string from the last getGameResult call (null until hydrated). */\n  rawStatus: string | null\n}\n\nexport type GamePlayConversation = {\n  postPlay: (gameId: string, answerJson: string, gameDay: string, fixtureId?: number, locale?: string) => Promise<SubmitPlayResult | null>\n  getGameResult: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameResultPayload | null>\n  getGameConfig: (gameId: string, fixtureId?: number, gameDay?: string, locale?: string) => Promise<GameStatePayload | null>\n}\n\nfunction toSubmitResult(payload: GameResultPayload): SubmitPlayResult {\n  return {\n    // 'pending' means the play is recorded but awaiting resolution (fixture games)\n    alreadyPlayed: payload.status === 'played' || payload.status === 'graded' || payload.status === 'pending',\n    score: payload.score,\n    isCorrect: payload.isCorrect,\n    clientStateJson: payload.clientStateJson,\n    attemptsUsed: payload.attemptsUsed,\n  }\n}\n\nexport function useGamePlay(\n  conversation: GamePlayConversation | null | undefined,\n  { gameId, gameDay, fixtureId, locale, refresh }: UseGamePlayOptions,\n): UseGamePlayResult {\n  const [result, setResult] = useState<SubmitPlayResult | null>(null)\n  const [submitting, setSubmitting] = useState(false)\n  const [rawStatus, setRawStatus] = useState<string | null>(null)\n\n  const inFlightRef = useRef(false)\n  const convRef = useRef(conversation)\n  convRef.current = conversation\n  const optsRef = useRef({ gameId, gameDay, fixtureId, locale, refresh })\n  optsRef.current = { gameId, gameDay, fixtureId, locale, refresh }\n  // Mirror the latest result so submit() (a stable [] callback) can tell whether we\n  // already hold in-progress state without wiping it.\n  const resultRef = useRef<SubmitPlayResult | null>(null)\n  resultRef.current = result\n\n  const refetch = useCallback(async (): Promise<void> => {\n    const conv = convRef.current\n    if (!conv) return\n    const opts = optsRef.current\n    try {\n      const payload = await conv.getGameResult(opts.gameId, opts.fixtureId, opts.gameDay, opts.locale)\n      if (payload === null) return\n      // Never let a null-clientState payload blank a board we already hold (e.g. a rescore that\n      // couldn't reconstruct state). A first hydrate holds nothing, so a legitimately terminal\n      // null-state play (voided / already-played) still renders; the status always updates.\n      if (payload.clientStateJson == null && resultRef.current?.clientStateJson != null) {\n        setRawStatus(payload.status)\n        return\n      }\n      setResult(toSubmitResult(payload))\n      setRawStatus(payload.status)\n    } catch {\n      // best-effort\n    }\n  }, [])\n\n  const submit = useCallback(async (answerJson: string): Promise<void> => {\n    const conv = convRef.current\n    if (!conv || inFlightRef.current) return\n    inFlightRef.current = true\n    setSubmitting(true)\n    try {\n      const opts = optsRef.current\n      const playResult = await conv.postPlay(opts.gameId, answerJson, opts.gameDay, opts.fixtureId, opts.locale)\n      if (playResult !== null) {\n        // Guard against a state-losing response: a still-in-progress submit that carries no\n        // ClientStateJson (e.g. a server-side concurrency retry) must NOT overwrite the board\n        // we already hold. Reconcile from the server instead of rendering an empty state.\n        const hasFreshState = playResult.clientStateJson != null\n        const isTerminal = playResult.alreadyPlayed === true\n        const holdsState = resultRef.current?.clientStateJson != null\n        if (!hasFreshState && !isTerminal && holdsState) {\n          await refetch()\n        } else {\n          setResult(playResult)\n        }\n        if (playResult.pointsDelta != null) {\n          opts.refresh?.()\n        }\n      }\n    } catch {\n      // best-effort; leave result unchanged\n    } finally {\n      inFlightRef.current = false\n      setSubmitting(false)\n    }\n  }, [refetch])\n\n  const hydrate = useCallback((): void => {\n    void refetch()\n  }, [refetch])\n\n  return { result, submitting, submit, hydrate, rawStatus }\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, MysteryTigerConfig, MysteryTigerClientState, MysteryTigerGuessResult, MysteryTigerAttributeVerdict } from './types'\nimport { nationalityFlag } from './nationFlags'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress, type SegmentState } from './ui/SegmentProgress'\nimport { AnswerTray } from './ui/AnswerTray'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { PointsLadderRow } from './ui/PointsLadderRow'\nimport { IconBulb } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\nfunction parseClientState(json: string | null | undefined): MysteryTigerClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as MysteryTigerClientState\n  } catch {\n    return null\n  }\n}\n\nexport type MtAttrKey = keyof Omit<MysteryTigerGuessResult, 'playerId'>\nconst ATTR_KEYS: MtAttrKey[] = ['position', 'nationality', 'age', 'shirtNumber', 'apps']\nconst NUMERIC_KEYS: ReadonlySet<MtAttrKey> = new Set<MtAttrKey>(['age', 'shirtNumber', 'apps'])\n\nconst MAX_GUESSES = 6\n\nfunction verdictGlyph(v: MysteryTigerAttributeVerdict): string {\n  if (v.verdict === 'exact') return '✓'\n  if (v.verdict === 'miss') return '✗'\n  if (v.direction === 'up') return '↑'\n  if (v.direction === 'down') return '↓'\n  return '≈'\n}\n\n// Direction arrow shown under a numeric value (\"22 ▲\" = mystery player is older/higher/more).\nfunction directionArrow(v: MysteryTigerAttributeVerdict): string {\n  if (v.direction === 'up') return '▲'\n  if (v.direction === 'down') return '▼'\n  return ''\n}\n\n// Full position names (Sportmonks \"Centre Forward\", \"Goalkeeper\", …) overflow the small square\n// tile, so map them to a short code for display. Anything unmapped falls back to its initials.\nconst POSITION_SHORT: Record<string, string> = {\n  goalkeeper: 'GK', keeper: 'GK',\n  defender: 'DEF', 'centre back': 'CB', 'center back': 'CB', 'centre-back': 'CB', 'center-back': 'CB',\n  'left back': 'LB', 'right back': 'RB', 'left wing-back': 'LWB', 'right wing-back': 'RWB', sweeper: 'SW',\n  midfielder: 'MID', 'defensive midfield': 'DM', 'central midfield': 'CM', 'centre midfield': 'CM',\n  'attacking midfield': 'AM', 'left midfield': 'LM', 'right midfield': 'RM',\n  'left wing': 'LW', 'right wing': 'RW', 'left winger': 'LW', 'right winger': 'RW',\n  forward: 'FWD', attacker: 'FWD', striker: 'ST', 'second striker': 'SS',\n  'centre forward': 'CF', 'center forward': 'CF', 'centre-forward': 'CF',\n}\n\nfunction shortPosition(value: string): string {\n  const mapped = POSITION_SHORT[value.trim().toLowerCase()]\n  if (mapped) return mapped\n  if (value.length <= 3) return value.toUpperCase() // already a code (GK, ST, CB, …)\n  return value.split(/[\\s-]+/).filter(Boolean).map(w => (w[0] ?? '').toUpperCase()).join('').slice(0, 3)\n}\n\n// The display face of a tile: the guessed player's own value (a flag for nationality, a short\n// code for position), falling back to the verdict glyph when the backend sent no value.\nfunction tileFace(key: MtAttrKey, v: MysteryTigerAttributeVerdict): string {\n  if (!v.value) return verdictGlyph(v)\n  if (key === 'nationality') return nationalityFlag(v.value)\n  if (key === 'position') return shortPosition(v.value)\n  return v.value\n}\n\nexport interface KnownAttribute { key: MtAttrKey; state: 'known' | 'range' | 'unknown'; text: string }\n\n// What the fan has pinned down so far, per attribute. An exact verdict reveals the value. For the\n// numeric attributes each ▲ (\"mystery is higher than v\") raises the floor and each ▼ lowers the\n// ceiling, so 23▲ + 26▼ reads \"24–25\", only ▼9 reads \"< 9\", only ▲31 reads \"> 31\".\nexport function deriveKnownAttributes(guesses: MysteryTigerGuessResult[], keys: MtAttrKey[]): KnownAttribute[] {\n  return keys.map((key): KnownAttribute => {\n    const exact = guesses.find(g => g[key].verdict === 'exact')\n    if (exact) return { key, state: 'known', text: tileFace(key, exact[key]) }\n    if (!NUMERIC_KEYS.has(key)) return { key, state: 'unknown', text: '?' }\n    let maxUp: number | null = null\n    let minDown: number | null = null\n    for (const g of guesses) {\n      const v = g[key]\n      if (!v.value || !v.direction) continue\n      const n = Number(v.value)\n      if (!Number.isFinite(n)) continue\n      if (v.direction === 'up') maxUp = maxUp === null ? n : Math.max(maxUp, n)\n      else minDown = minDown === null ? n : Math.min(minDown, n)\n    }\n    if (maxUp !== null && minDown !== null) {\n      const lo = maxUp + 1\n      const hi = minDown - 1\n      return { key, state: 'range', text: lo >= hi ? String(lo) : `${lo}–${hi}` }\n    }\n    if (minDown !== null) return { key, state: 'range', text: `< ${minDown}` }\n    if (maxUp !== null) return { key, state: 'range', text: `> ${maxUp}` }\n    return { key, state: 'unknown', text: '?' }\n  })\n}\n\nexport function MysteryTigerGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<MysteryTigerConfig>): JSX.Element {\n  const t = ui.games.mysteryTiger\n  const [query, setQuery] = useState('')\n  const inputId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const guessResults = clientState?.guessResults ?? []\n  const alreadyGuessedIds = new Set<number>(guessResults.map(g => g.playerId))\n  const shirtEnabled = config?.shirtTileEnabled ?? clientState?.shirtTileEnabled ?? false\n  const keys = ATTR_KEYS.filter(k => k !== 'shirtNumber' || shirtEnabled)\n\n  const isOver =\n    result?.alreadyPlayed === true ||\n    clientState?.solved === true ||\n    clientState?.failed === true\n\n  const guessesUsed = clientState?.guessesUsed ?? guessResults.length\n  const totalGuesses = clientState ? clientState.guessesUsed + clientState.guessesRemaining : MAX_GUESSES\n  const score = result?.score ?? 0\n  const revealName = isOver ? clientState?.revealedPlayerName : undefined\n\n  const pool = config && !isOver ? config.squadPlayers.filter(p => !alreadyGuessedIds.has(p.id)) : []\n\n  function handleSelect(playerId: number) {\n    if (!config || isOver || submitting) return\n    const prevGuesses = guessResults.map(g => g.playerId)\n    const newGuesses = [...prevGuesses, playerId]\n    setQuery('')\n    onSubmit(JSON.stringify({ guesses: newGuesses }))\n  }\n\n  const headerRight = !config ? undefined : isOver ? (\n    <Chip variant=\"accent\">{score} {ui.games.unitPts}</Chip>\n  ) : (\n    <span data-testid=\"mt-chip\">\n      <Chip>{ui.games.guess} <span className=\"ss-g-num\">{guessesUsed + 1}</span> / {totalGuesses}</Chip>\n    </span>\n  )\n\n  const segments: SegmentState[] = Array.from({ length: totalGuesses }, (_, i) =>\n    i < guessesUsed ? 'done' : i === guessesUsed ? 'current' : 'todo')\n  const cols = { gridTemplateColumns: `minmax(0, 1fr) repeat(${keys.length}, 42px)` }\n  const known = deriveKnownAttributes(guessResults, keys)\n\n  return (\n    <div className=\"ss-g-screen ss-g-mt\" data-game=\"mystery-tiger\" data-testid=\"game-screen-mystery-tiger\">\n      <GameHeader title={gameTitle({ gameId: 'mystery-tiger' }, ui.games.titles)} eyebrow={t.eyebrow} right={headerRight}\n        onBack={onBack} backLabel={ui.back} />\n\n      {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n      {config && (\n        <>\n          <div className=\"ss-g-body\">\n            {!isOver && <PointsLadderRow ladder={config.pointsLadder} guessesUsed={guessesUsed} ui={ui} />}\n            <div className={`ss-g-mt-card${isOver ? ' ss-g-mt-card--reveal' : ''}`}>\n              <div className=\"ss-g-mt-portrait\">\n                {revealName ? (\n                  <PlayerAvatar className=\"ss-g-mt-photo\" name={revealName} imagePath={clientState?.revealedPlayerImagePath} />\n                ) : (\n                  <Silhouette size={150} variant=\"mystery\" />\n                )}\n                {revealName && <span className=\"ss-g-mt-reveal-name\">{revealName}</span>}\n              </div>\n              <div className=\"ss-g-mt-known\" style={{ gridTemplateColumns: `repeat(${keys.length}, minmax(0, 1fr))` }}>\n                {known.map(k => (\n                  <div key={k.key} className=\"ss-g-mt-known-cell\">\n                    <span className=\"ss-g-mt-lab\">{t.labels[k.key]}</span>\n                    <span className=\"ss-g-mt-known-v\" data-state={k.state} data-testid={`known-${k.key}`}>{k.text}</span>\n                  </div>\n                ))}\n              </div>\n            </div>\n\n            {!isOver && <SegmentProgress segments={segments} ariaLabel={t.progress(guessesUsed, totalGuesses)} />}\n\n            {guessResults.length > 0 && (\n              <div className=\"ss-g-mt-table\">\n                <div className=\"ss-g-mt-thead\" style={cols}>\n                  <span>{t.yourGuesses}</span>\n                  {keys.map(k => <span key={k}>{t.labels[k]}</span>)}\n                </div>\n                {guessResults.map((gr, i) => {\n                  const name = config.squadPlayers.find(p => p.id === gr.playerId)?.name ?? `#${gr.playerId}`\n                  const { first, last } = splitName(name)\n                  return (\n                    <div key={gr.playerId} className=\"ss-g-mt-row\" style={cols}>\n                      <div className=\"ss-g-mt-who\">\n                        <PlayerAvatar className=\"ss-g-mt-av\" name={name} />\n                        <span className=\"ss-g-mt-names\">\n                          {first && <span className=\"ss-g-mt-first\">{first}</span>}\n                          <span className=\"ss-g-mt-last\">{last}</span>\n                        </span>\n                      </div>\n                      {keys.map(key => {\n                        const v = gr[key]\n                        const arrow = directionArrow(v)\n                        return (\n                          <div\n                            key={key}\n                            className=\"ss-g-mt-cell\"\n                            data-testid={`verdict-${key}-${i}`}\n                            data-verdict={v.verdict}\n                            aria-label={`${t.labels[key]}: ${v.value ?? v.verdict}${v.direction ? ` ${v.direction}` : ''}`}\n                          >\n                            <span className=\"ss-g-mt-cell-v\" aria-hidden=\"true\">{tileFace(key, v)}</span>\n                            {arrow && <span className=\"ss-g-mt-cell-dir\" aria-hidden=\"true\">{arrow}</span>}\n                          </div>\n                        )\n                      })}\n                    </div>\n                  )\n                })}\n              </div>\n            )}\n\n            {!isOver && (\n              <div className=\"ss-g-mt-legend\">\n                <span><i className=\"ss-g-mt-sw\" data-verdict=\"exact\" />{t.legendMatch}</span>\n                <span><i className=\"ss-g-mt-sw\" data-verdict=\"near\" />{t.legendClose}</span>\n                <span>▲ {t.legendHigher}</span>\n              </div>\n            )}\n\n            {clientState?.hintLine && !isOver && (\n              <div className=\"ss-g-mt-hint\"><IconBulb /><span>{clientState.hintLine}</span></div>\n            )}\n\n            {isOver && (\n              <ResultCard\n                tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n                title={clientState?.solved ? t.solved : clientState?.failed ? t.failed : ui.games.alreadyPlayedTitle}\n                score={score}\n                detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n                onBack={onBack}\n                ui={ui}\n              />\n            )}\n          </div>\n\n          {!isOver && (\n            <FooterBar>\n              <AnswerTray id={inputId} label={t.searchLabel} placeholder={t.searchPlaceholder}\n                optionsLabel={t.optionsLabel} options={pool} query={query} onQuery={setQuery}\n                onPick={handleSelect} disabled={submitting} />\n            </FooterBar>\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n","// Maps a nationality country-name string (as the games backend emits it) to a flag emoji.\n// UK home nations use subdivision flag emoji; everything else uses regional-indicator pairs.\n// Unmapped nationalities fall back to a short uppercased code so a slot is never blank.\n\nconst FLAGS: Record<string, string> = {\n  // UK home nations (subdivision flags)\n  england: '🏴\\u{E0067}\\u{E0062}\\u{E0065}\\u{E006E}\\u{E0067}\\u{E007F}',\n  scotland: '🏴\\u{E0067}\\u{E0062}\\u{E0073}\\u{E0063}\\u{E0074}\\u{E007F}',\n  wales: '🏴\\u{E0067}\\u{E0062}\\u{E0077}\\u{E006C}\\u{E0073}\\u{E007F}',\n  'northern ireland': '🇬🇧',\n  'republic of ireland': '🇮🇪',\n  ireland: '🇮🇪',\n  'united kingdom': '🇬🇧',\n\n  // Western & Southern Europe\n  france: '🇫🇷', spain: '🇪🇸', portugal: '🇵🇹', germany: '🇩🇪', italy: '🇮🇹',\n  netherlands: '🇳🇱', belgium: '🇧🇪', switzerland: '🇨🇭', austria: '🇦🇹',\n  luxembourg: '🇱🇺', malta: '🇲🇹', cyprus: '🇨🇾',\n  andorra: '🇦🇩', liechtenstein: '🇱🇮', 'san marino': '🇸🇲', monaco: '🇲🇨',\n\n  // Northern Europe\n  denmark: '🇩🇰', sweden: '🇸🇪', norway: '🇳🇴', finland: '🇫🇮', iceland: '🇮🇸',\n\n  // Central & Eastern Europe\n  poland: '🇵🇱', czechia: '🇨🇿', 'czech republic': '🇨🇿', croatia: '🇭🇷',\n  serbia: '🇷🇸', 'bosnia and herzegovina': '🇧🇦', bosnia: '🇧🇦',\n  greece: '🇬🇷', romania: '🇷🇴', ukraine: '🇺🇦', russia: '🇷🇺',\n  hungary: '🇭🇺', slovakia: '🇸🇰', slovenia: '🇸🇮', bulgaria: '🇧🇬',\n  lithuania: '🇱🇹', latvia: '🇱🇻', estonia: '🇪🇪', moldova: '🇲🇩', belarus: '🇧🇾',\n\n  // South-East Europe / Balkans\n  turkey: '🇹🇷', türkiye: '🇹🇷', albania: '🇦🇱', 'north macedonia': '🇲🇰',\n  kosovo: '🇽🇰', montenegro: '🇲🇪',\n\n  // Caucasus & Central Asia\n  armenia: '🇦🇲', georgia: '🇬🇪', azerbaijan: '🇦🇿',\n  kazakhstan: '🇰🇿', uzbekistan: '🇺🇿', kyrgyzstan: '🇰🇬',\n  tajikistan: '🇹🇯', turkmenistan: '🇹🇲',\n\n  // South America\n  brazil: '🇧🇷', argentina: '🇦🇷', uruguay: '🇺🇾', colombia: '🇨🇴', chile: '🇨🇱',\n  peru: '🇵🇪', ecuador: '🇪🇨', paraguay: '🇵🇾', venezuela: '🇻🇪', bolivia: '🇧🇴',\n  guyana: '🇬🇾', suriname: '🇸🇷',\n\n  // North & Central America\n  mexico: '🇲🇽', 'united states': '🇺🇸', usa: '🇺🇸', canada: '🇨🇦',\n  'costa rica': '🇨🇷', panama: '🇵🇦', honduras: '🇭🇳', 'el salvador': '🇸🇻',\n  guatemala: '🇬🇹', nicaragua: '🇳🇮',\n\n  // Caribbean\n  jamaica: '🇯🇲', cuba: '🇨🇺', haiti: '🇭🇹', 'dominican republic': '🇩🇴',\n  'trinidad and tobago': '🇹🇹', trinidad: '🇹🇹',\n  'curaçao': '🇨🇼', curacao: '🇨🇼',\n  barbados: '🇧🇧',\n\n  // West Africa\n  nigeria: '🇳🇬', ghana: '🇬🇭', senegal: '🇸🇳',\n  ivorycoast: '🇨🇮', \"cote d'ivoire\": '🇨🇮', \"côte d'ivoire\": '🇨🇮', 'ivory coast': '🇨🇮',\n  cameroon: '🇨🇲', mali: '🇲🇱', guinea: '🇬🇳', 'guinea-bissau': '🇬🇼',\n  'sierra leone': '🇸🇱', liberia: '🇱🇷', 'cape verde': '🇨🇻', 'gambia': '🇬🇲',\n  mauritania: '🇲🇷', togo: '🇹🇬', benin: '🇧🇯', 'burkina faso': '🇧🇫', niger: '🇳🇪',\n\n  // Central & East Africa\n  'dr congo': '🇨🇩', 'democratic republic of the congo': '🇨🇩', 'congo dr': '🇨🇩',\n  'republic of the congo': '🇨🇬', congo: '🇨🇬', 'congo republic': '🇨🇬', 'congo-brazzaville': '🇨🇬',\n  'central african republic': '🇨🇫', gabon: '🇬🇦', 'equatorial guinea': '🇬🇶',\n  'south africa': '🇿🇦', angola: '🇦🇴', namibia: '🇳🇦', botswana: '🇧🇼',\n  zimbabwe: '🇿🇼', zambia: '🇿🇲', malawi: '🇲🇼', mozambique: '🇲🇿',\n  tanzania: '🇹🇿', kenya: '🇰🇪', uganda: '🇺🇬', rwanda: '🇷🇼',\n  ethiopia: '🇪🇹', eritrea: '🇪🇷', djibouti: '🇩🇯', somalia: '🇸🇴',\n  sudan: '🇸🇩', 'south sudan': '🇸🇸', chad: '🇹🇩',\n  lesotho: '🇱🇸', eswatini: '🇸🇿', swaziland: '🇸🇿',\n  madagascar: '🇲🇬', mauritius: '🇲🇺', comoros: '🇰🇲', seychelles: '🇸🇨',\n\n  // North Africa\n  egypt: '🇪🇬', morocco: '🇲🇦', algeria: '🇩🇿', tunisia: '🇹🇳',\n\n  // Middle East\n  'saudi arabia': '🇸🇦', iran: '🇮🇷', iraq: '🇮🇶', lebanon: '🇱🇧',\n  syria: '🇸🇾', jordan: '🇯🇴', qatar: '🇶🇦', 'united arab emirates': '🇦🇪', uae: '🇦🇪',\n  kuwait: '🇰🇼', bahrain: '🇧🇭', oman: '🇴🇲', yemen: '🇾🇪',\n  israel: '🇮🇱', palestine: '🇵🇸',\n\n  // East & South-East Asia\n  japan: '🇯🇵', 'south korea': '🇰🇷', korea: '🇰🇷', china: '🇨🇳',\n  india: '🇮🇳', thailand: '🇹🇭', indonesia: '🇮🇩', malaysia: '🇲🇾',\n  philippines: '🇵🇭', vietnam: '🇻🇳',\n\n  // Oceania\n  australia: '🇦🇺', 'new zealand': '🇳🇿', fiji: '🇫🇯',\n}\n\nexport function nationalityFlag(nationality: string | null | undefined): string {\n  if (!nationality) return '🏳️'\n  const key = nationality.trim().toLowerCase()\n  return FLAGS[key] ?? nationality.slice(0, 3).toUpperCase()\n}\n\n// A nationality without a flag falls back to its first three letters (\"BEN\"); callers size that\n// text down so it fits the disc a flag emoji would fill.\nexport function isNationCode(flag: string): boolean {\n  return /^[A-Z]{1,3}$/.test(flag)\n}\n","import { useState } from 'react'\n\n// Two-letter initials from a display name: first + last token, or the first two letters\n// of a single-token name. Used as the photo fallback so an avatar circle is never a bare ball.\nexport function initialsOf(name: string): string {\n  const parts = name.trim().split(/\\s+/).filter(Boolean)\n  const first = parts[0]\n  if (!first) return '?'\n  const last = parts[parts.length - 1]\n  if (parts.length === 1 || !last) return first.slice(0, 2).toUpperCase()\n  return ((first[0] ?? '') + (last[0] ?? '')).toUpperCase()\n}\n\n// The data provider (Sportmonks) serves a generic grey silhouette at .../placeholder.png for\n// people it has no photo of. Treat it as no photo so the fallback (initials, shield) shows.\nexport function isPlaceholderImage(url: string | null | undefined): boolean {\n  return !!url && /\\/placeholder\\.(png|jpe?g|svg|webp)(\\?|$)/i.test(url)\n}\n\n// Circular player avatar. Shows the photo when an imagePath is present and loads; otherwise\n// (missing URL or a broken image) falls back to the player's initials on the same circle.\nexport function PlayerAvatar({\n  name,\n  imagePath,\n  className,\n}: {\n  name: string\n  imagePath?: string\n  className: string\n}): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  const showImage = Boolean(imagePath) && !isPlaceholderImage(imagePath) && !failed\n\n  return (\n    <div className={className} aria-hidden=\"true\">\n      {showImage ? (\n        <img src={imagePath} alt=\"\" loading=\"lazy\" onError={() => setFailed(true)} />\n      ) : (\n        <span className=\"ss-w-av-initials\">{initialsOf(name)}</span>\n      )}\n    </div>\n  )\n}\n","import type { ReactNode } from 'react'\nimport { IconChevronLeft } from './icons'\n\nexport function GameHeader({ title, eyebrow, right, onBack, backLabel }: {\n  title: string; eyebrow?: string; right?: ReactNode; onBack?: () => void; backLabel: string\n}): JSX.Element {\n  return (\n    <div className=\"ss-g-head\">\n      {onBack && (\n        <button type=\"button\" className=\"ss-g-back\" aria-label={backLabel} onClick={onBack}>\n          <IconChevronLeft />\n        </button>\n      )}\n      <div className=\"ss-g-head-text\">\n        {eyebrow && <span className=\"ss-g-eyebrow\">{eyebrow}</span>}\n        <h2 className=\"ss-g-title\">{title}</h2>\n      </div>\n      {right && <div className=\"ss-g-head-right\">{right}</div>}\n    </div>\n  )\n}\n","import type { ReactNode } from 'react'\n\nexport type SegmentState = 'done' | 'current' | 'todo' | 'correct' | 'wrong'\n\nexport function SegmentProgress({ segments, ariaLabel, leftLabel, rightLabel, right }: {\n  segments: SegmentState[]; ariaLabel: string; leftLabel?: string; rightLabel?: string; right?: ReactNode\n}): JSX.Element {\n  return (\n    <div className=\"ss-g-progress\">\n      <div className=\"ss-g-progress-main\">\n        {(leftLabel || rightLabel) && (\n          <div className=\"ss-g-progress-labels\">\n            <span>{leftLabel}</span><span className=\"ss-g-progress-rl\">{rightLabel}</span>\n          </div>\n        )}\n        <div className=\"ss-g-segs\" role=\"img\" aria-label={ariaLabel}\n          style={{ gridTemplateColumns: `repeat(${segments.length}, minmax(0, 1fr))` }}>\n          {segments.map((s, i) => <span key={i} className=\"ss-g-seg\" data-state={s} />)}\n        </div>\n      </div>\n      {right}\n    </div>\n  )\n}\n","import { PlayerAvatar } from '../PlayerAvatar'\nimport { SearchField } from './SearchField'\nimport { splitName } from './gameMeta'\n\nexport interface TrayOption { id: number; name: string; imagePath?: string }\n\n// Tap-to-answer tray: the whole candidate pool as photo chips, filtered by the search box.\n// The pool is whatever the puzzle already ships, so the guess rules are unchanged.\nexport function AnswerTray({ id, label, placeholder, optionsLabel, options, query, onQuery, onPick, disabled, minQuery = 0 }: {\n  id: string; label: string; placeholder: string; optionsLabel: string\n  options: TrayOption[]; query: string; onQuery: (v: string) => void\n  onPick: (id: number) => void; disabled?: boolean\n  // Pools too big to browse (Career Path pulls in every past transfer) list only once the fan types.\n  minQuery?: number\n}): JSX.Element {\n  const needle = query.trim().toLowerCase()\n  const shown = needle.length < minQuery ? [] : needle ? options.filter(o => o.name.toLowerCase().includes(needle)) : options\n  return (\n    <>\n      <SearchField id={id} label={label} labelHidden placeholder={placeholder} value={query}\n        onChange={onQuery} disabled={disabled} />\n      {shown.length > 0 && <div className=\"ss-g-tray\" role=\"listbox\" aria-label={optionsLabel}>\n        {shown.map(o => {\n          const { first, last } = splitName(o.name)\n          return (\n            <button key={o.id} type=\"button\" role=\"option\" aria-selected={false} aria-label={o.name}\n              className=\"ss-g-tray-chip\" disabled={disabled} onClick={() => onPick(o.id)}>\n              <PlayerAvatar className=\"ss-g-tray-av\" name={o.name} imagePath={o.imagePath} />\n              <span className=\"ss-g-tray-name\" aria-hidden=\"true\">\n                {first && <span className=\"ss-g-tray-first\">{first}</span>}\n                <span className=\"ss-g-tray-last\">{last}</span>\n              </span>\n            </button>\n          )\n        })}\n      </div>}\n    </>\n  )\n}\n","import type { ReactNode } from 'react'\nexport function FooterBar({ children }: { children: ReactNode }): JSX.Element {\n  return <div className=\"ss-g-footer\">{children}</div>\n}\n","export function Silhouette({ size, variant = 'default' }: { size: number; variant?: 'default' | 'selected' | 'mystery' }): JSX.Element {\n  return (\n    <span className={`ss-g-sil ss-g-sil--${variant}`} style={{ width: size, height: size }} aria-hidden=\"true\">\n      <svg width={size * 0.86} height={size * 0.86} viewBox=\"0 0 100 100\">\n        <circle cx=\"50\" cy=\"40\" r=\"19\" fill=\"currentColor\" />\n        <path d=\"M12 100c0-23 17-38 38-38s38 15 38 38z\" fill=\"currentColor\" />\n      </svg>\n      {variant === 'mystery' && <span className=\"ss-g-sil-q\">?</span>}\n    </span>\n  )\n}\n","import type { ButtonHTMLAttributes } from 'react'\n\nexport type GameButtonVariant = 'primary' | 'outline' | 'accent-outline' | 'surface'\n\nexport function GameButton({ variant = 'primary', block = false, className, type = 'button', ...rest }:\n  ButtonHTMLAttributes<HTMLButtonElement> & { variant?: GameButtonVariant; block?: boolean }): JSX.Element {\n  const cls = `ss-g-btn ss-g-btn--${variant}${block ? ' ss-g-btn--block' : ''}${className ? ` ${className}` : ''}`\n  return <button type={type} className={cls} {...rest} />\n}\n","import type { UiConfig } from '../../../config'\nimport { GameButton } from './GameButton'\n\nexport type ResultTone = 'win' | 'lose' | 'neutral'\n\n// Spec §6: every game's solved / lost / already-played state uses this one card.\nexport function ResultCard({ tone, title, score, detail, onBack, ui }: {\n  tone: ResultTone; title: string; score?: number; detail?: string; onBack?: () => void; ui: UiConfig\n}): JSX.Element {\n  return (\n    <div className=\"ss-g-result\" data-tone={tone} role=\"status\">\n      <span className=\"ss-g-result-title\">{title}</span>\n      {score !== undefined && (\n        <span className=\"ss-g-result-score\"><span className=\"ss-g-result-num\">{score}</span>{ui.games.unitPts}</span>\n      )}\n      {detail && <span className=\"ss-g-result-detail\">{detail}</span>}\n      {onBack && <GameButton variant=\"outline\" onClick={onBack}>{ui.games.backToGames}</GameButton>}\n    </div>\n  )\n}\n","import type { UiConfig } from '../../../config'\n\n// What a solve is worth right now and after one more miss, from the scorer's own ladder.\nexport function PointsLadderRow({ ladder, guessesUsed, ui }: {\n  ladder: number[] | undefined; guessesUsed: number; ui: UiConfig\n}): JSX.Element | null {\n  if (!ladder || ladder.length === 0) return null\n  const now = ladder[Math.min(guessesUsed, ladder.length - 1)]\n  const next = ladder[guessesUsed + 1]\n  if (now === undefined) return null\n  return (\n    <div className=\"ss-g-worth\" data-testid=\"points-ladder\">\n      <span className=\"ss-g-worth-now\">{ui.games.worthNow(now)}</span>\n      {next !== undefined && next !== now && <span className=\"ss-g-worth-next\">{ui.games.worthAfterMiss(next)}</span>}\n    </div>\n  )\n}\n","import type { ReactNode } from 'react'\nimport type { GameScreenProps, HolConfig, HolClientState } from './types'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { GameHeader } from './ui/GameHeader'\nimport { StatStack } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconArrowUp, IconArrowDown, IconCheck, IconClose } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Points awarded per correct pick — mirrors HigherOrLowerContentGenerator.PointsPerCorrect.\nconst POINTS_PER_CORRECT = 10\n\nfunction parseClientState(json: string | null | undefined): HolClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as HolClientState\n  } catch {\n    return null\n  }\n}\n\nfunction PlayerCard({ name, imagePath, highlight, children }: {\n  name: string; imagePath?: string; highlight?: boolean; children: ReactNode\n}): JSX.Element {\n  const { first, last } = splitName(name)\n  return (\n    <div className={`ss-g-hl-card${highlight ? ' ss-g-hl-card--b' : ''}`}>\n      <div className=\"ss-g-hl-photo-wrap\">\n        {imagePath\n          ? <PlayerAvatar className=\"ss-g-hl-photo\" name={name} imagePath={imagePath} />\n          : <Silhouette size={150} />}\n      </div>\n      <div className=\"ss-g-hl-info\">\n        {first && <span className=\"ss-g-hl-first\">{first}</span>}\n        <span className=\"ss-g-hl-surname\">{last}</span>\n        {children}\n      </div>\n    </div>\n  )\n}\n\nexport function HigherOrLowerGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<HolConfig>): JSX.Element {\n  const t = ui.games.higherOrLower\n  const clientState = parseClientState(result?.clientStateJson)\n\n  const answeredPairs = clientState?.answeredPairs ?? []\n  const answeredCount = answeredPairs.length\n  const runEndedWrong = answeredPairs.some(p => !p.wasCorrect)\n  const allPairsAnswered = config != null && answeredCount >= config.pairs.length\n  const isOver = result?.alreadyPlayed === true || runEndedWrong || allPairsAnswered\n\n  const currentPair = config && !isOver ? config.pairs[answeredCount] ?? null : null\n\n  const correctCount = answeredPairs.filter(p => p.wasCorrect).length\n  // A returning fan may come back with no client state: show the stored play score then.\n  const score = clientState?.score ?? result?.score ?? 0\n  const runLength = clientState?.runLength ?? 0\n\n  const lastAnswer = answeredPairs[answeredPairs.length - 1]\n  const lastAnswerPair = lastAnswer ? config?.pairs.find(p => p.pairIndex === lastAnswer.pairIndex) : undefined\n\n  function handlePick(pick: 'higher' | 'lower') {\n    if (!config || isOver || submitting || !currentPair) return\n    const prevAnswers = answeredPairs.map(p => ({ pairIndex: p.pairIndex, pick: p.pick }))\n    const newAnswers = [...prevAnswers, { pairIndex: currentPair.pairIndex, pick }]\n    onSubmit(JSON.stringify({ answers: newAnswers }))\n  }\n\n  return (\n    <div className=\"ss-g-screen ss-g-hl\" data-game=\"higher-or-lower\" data-testid=\"game-screen-higher-or-lower\">\n      <GameHeader\n        title={gameTitle({ gameId: 'higher-or-lower' }, ui.games.titles)}\n        eyebrow={t.eyebrow(POINTS_PER_CORRECT)}\n        right={config ? <StatStack value={runLength} label={t.streak} /> : undefined}\n        onBack={onBack}\n        backLabel={ui.back}\n      />\n\n      {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n      {config && (\n        <>\n          <div className=\"ss-g-body\">\n            <div className=\"ss-g-hl-prompt\" data-testid=\"hol-prompt\">\n              <span className=\"ss-g-hl-prompt-q\">{t.whoHadMore}</span>\n              <span className=\"ss-g-hl-prompt-stat\">{config.statLabel}</span>\n              <span className=\"ss-g-hl-prompt-season\">{t.season(config.seasonLabel)}</span>\n            </div>\n\n            {currentPair && (\n              <div className=\"ss-g-hl-pair\">\n                <PlayerCard name={currentPair.playerAName} imagePath={currentPair.playerAImagePath}>\n                  <span className=\"ss-g-hl-value\">{currentPair.playerAValue}</span>\n                  <span className=\"ss-g-hl-stat\">{config.statLabel}</span>\n                </PlayerCard>\n                <span className=\"ss-g-hl-vs\" aria-hidden=\"true\">{t.vs}</span>\n                <PlayerCard name={currentPair.playerBName} imagePath={currentPair.playerBImagePath} highlight>\n                  <div className=\"ss-g-hl-btns\">\n                    <GameButton variant=\"primary\" disabled={submitting} onClick={() => handlePick('higher')}>\n                      <IconArrowUp size={16} />{t.higher}\n                    </GameButton>\n                    <GameButton variant=\"outline\" disabled={submitting} onClick={() => handlePick('lower')}>\n                      <IconArrowDown size={16} />{t.lower}\n                    </GameButton>\n                  </div>\n                </PlayerCard>\n              </div>\n            )}\n\n            {lastAnswer && lastAnswerPair && (\n              <p className=\"ss-g-hl-feedback\" data-testid=\"hol-last\" data-correct={lastAnswer.wasCorrect ? 'true' : 'false'}>\n                {lastAnswer.wasCorrect ? <IconCheck /> : <IconClose />}\n                {t.lastAnswer(splitName(lastAnswerPair.playerBName).last, lastAnswer.playerBValue)}\n              </p>\n            )}\n\n            {isOver && (\n              <ResultCard\n                tone={runEndedWrong ? 'lose' : allPairsAnswered ? 'win' : 'neutral'}\n                title={runEndedWrong ? t.runOver : allPairsAnswered ? t.perfectRun : ui.games.alreadyPlayedTitle}\n                score={score}\n                detail={clientState ? t.runDetail(correctCount) : undefined}\n                onBack={onBack}\n                ui={ui}\n              />\n            )}\n          </div>\n\n          {!isOver && (\n            <FooterBar>\n              <div className=\"ss-g-hl-foot\">\n                <div className=\"ss-g-hl-dots\" role=\"img\" aria-label={t.answersSoFar(answeredCount, config.pairs.length)}>\n                  {config.pairs.map((p, i) => {\n                    const a = answeredPairs[i]\n                    return <span key={p.pairIndex} className=\"ss-g-hl-dot\" data-state={a ? (a.wasCorrect ? 'correct' : 'wrong') : 'todo'} />\n                  })}\n                </div>\n                <span className=\"ss-g-hl-pts\">\n                  <span data-testid=\"hol-score\">{score}</span> <span className=\"ss-g-hl-pts-unit\">{ui.games.unitPts}</span>\n                </span>\n              </div>\n            </FooterBar>\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, CareerPathConfig, CareerPathClientState, CareerPathClubSpell } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { AnswerTray } from './ui/AnswerTray'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconLock } from './ui/icons'\nimport { PointsLadderRow } from './ui/PointsLadderRow'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): CareerPathClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as CareerPathClientState\n  } catch {\n    return null\n  }\n}\n\n// \"2012–2015\", \"2012\" when single-season or open-ended, '' when the generator had no start year.\nexport function spellYears(spell: CareerPathClubSpell): string {\n  if (!spell.startYear) return ''\n  if (spell.endYear && spell.endYear !== spell.startYear) return `${spell.startYear}–${spell.endYear}`\n  return String(spell.startYear)\n}\n\nexport function CareerPathGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  onBack,\n  ui,\n}: GameScreenProps<CareerPathConfig>): JSX.Element {\n  const s = ui.games.careerPath\n  const title = gameTitle({ gameId: 'career-path' }, ui.games.titles)\n  const [query, setQuery] = useState('')\n  const inputId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const alreadyGuessedIds = new Set<number>(clientState?.guessResults.map(g => g.playerId) ?? [])\n\n  const isOver =\n    result?.alreadyPlayed === true ||\n    clientState?.solved === true ||\n    clientState?.failed === true\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"career-path\" data-testid=\"game-screen-career-path\">\n        <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const visiblePath = clientState?.visiblePath ?? config.initialPath\n  const totalClubs = clientState?.totalClubs ?? config.totalClubs\n  const hidden = isOver ? 0 : Math.max(0, totalClubs - visiblePath.length)\n\n  const pool = !isOver ? config.typeaheadPool.filter(p => !alreadyGuessedIds.has(p.id)) : []\n\n  function handleSelect(playerId: number): void {\n    if (!config || isOver || submitting) return\n    const prevGuesses = clientState?.guessResults.map(g => g.playerId) ?? []\n    const newGuesses = [...prevGuesses, playerId]\n    setQuery('')\n    onSubmit(JSON.stringify({ guesses: newGuesses }))\n  }\n\n  const right = !isOver && clientState\n    ? (\n        <span data-testid=\"cp-guess-chip\">\n          <Chip variant=\"neutral\">\n            {ui.games.guess} <span className=\"ss-g-num\">{clientState.guessesUsed + 1}</span> / {clientState.guessesUsed + clientState.guessesRemaining}\n          </Chip>\n        </span>\n      )\n    : undefined\n\n  const outcome = clientState?.solved ? s.solved : clientState?.failed ? s.failed : ui.games.done\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"career-path\" data-testid=\"game-screen-career-path\">\n      <GameHeader title={title} eyebrow={s.eyebrow} right={right} onBack={onBack} backLabel={ui.back} />\n\n      <div className=\"ss-g-body\">\n        {!isOver && <PointsLadderRow ladder={config.pointsLadder} guessesUsed={clientState?.guessesUsed ?? 0} ui={ui} />}\n        <div className=\"ss-g-cp-card\">\n          {isOver && clientState?.revealedPlayerName ? (\n            <PlayerAvatar className=\"ss-g-cp-photo\" name={clientState.revealedPlayerName} imagePath={clientState.revealedPlayerImagePath} />\n          ) : (\n            <Silhouette size={64} variant={isOver ? 'default' : 'mystery'} />\n          )}\n          <div className=\"ss-g-cp-card-text\">\n            <span className=\"ss-g-cp-card-title\">\n              {isOver && clientState?.revealedPlayerName ? clientState.revealedPlayerName : s.mysteryPlayer}\n            </span>\n            {clientState?.hintLine ? (\n              <span className=\"ss-g-cp-hint\">{clientState.hintLine}</span>\n            ) : !isOver ? (\n              <span className=\"ss-g-cp-locks\">\n                <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockPosition}</Chip>\n                <Chip variant=\"lock\" icon={<IconLock size={11} />}>{s.lockNationality}</Chip>\n              </span>\n            ) : null}\n          </div>\n        </div>\n\n        <ol className=\"ss-g-cp-line\">\n          {visiblePath.map((spell, i) => {\n            const years = i === 0 ? s.firstClub : spellYears(spell)\n            return (\n              <li key={`${spell.clubName}-${i}`} className=\"ss-g-cp-step\">\n                <span className=\"ss-g-cp-rail\">\n                  <span className=\"ss-g-cp-tile\"><CrestShield src={spell.crestUrl} name={spell.clubName} size={30} /></span>\n                  <span className=\"ss-g-cp-conn\" aria-hidden=\"true\" />\n                </span>\n                <span className=\"ss-g-cp-step-text\">\n                  <span className=\"ss-g-cp-club\">{spell.clubName}</span>\n                  <span className=\"ss-g-cp-sub\">\n                    <span className=\"ss-g-cp-years\">{years}</span>\n                    {spell.isLoan && (\n                      <>\n                        {years ? ' · ' : ''}\n                        <span className=\"ss-g-cp-loan\">{s.loan}</span>\n                      </>\n                    )}\n                  </span>\n                </span>\n              </li>\n            )\n          })}\n          {hidden > 0 && (\n            <li className=\"ss-g-cp-step ss-g-cp-step--hidden\">\n              <span className=\"ss-g-cp-rail\">\n                <span className=\"ss-g-cp-tile ss-g-cp-tile--locked\"><IconLock size={18} /></span>\n                {hidden > 1 && <span className=\"ss-g-cp-conn ss-g-cp-conn--faint\" aria-hidden=\"true\" />}\n              </span>\n              <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.nextClubHidden}</span></span>\n            </li>\n          )}\n          {hidden > 1 && (\n            <li className=\"ss-g-cp-step ss-g-cp-step--more\">\n              <span className=\"ss-g-cp-rail\">\n                <span className=\"ss-g-cp-tile ss-g-cp-tile--faint\"><IconLock size={18} /></span>\n              </span>\n              <span className=\"ss-g-cp-step-text\"><span className=\"ss-g-cp-sub\">{s.moreClubs(hidden - 1)}</span></span>\n            </li>\n          )}\n        </ol>\n\n        {isOver && (\n          <ResultCard\n            tone={clientState?.solved ? 'win' : clientState?.failed ? 'lose' : 'neutral'}\n            title={outcome}\n            score={result?.score}\n            detail={clientState ? s.guessesLine(clientState.guessesUsed) : undefined}\n            onBack={onBack}\n            ui={ui}\n          />\n        )}\n      </div>\n\n      {!isOver && (\n        <FooterBar>\n          <AnswerTray id={inputId} label={s.searchLabel} placeholder={s.searchPlaceholder}\n            optionsLabel={s.searchLabel} options={pool} query={query} onQuery={setQuery}\n            onPick={handleSelect} disabled={submitting} minQuery={1} />\n        </FooterBar>\n      )}\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport { isPlaceholderImage } from '../PlayerAvatar'\n\nexport function CrestShield({ src, name, size = 28 }: { src?: string | null; name: string; size?: number }): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  if (src && !isPlaceholderImage(src) && !failed) {\n    return <img className=\"ss-g-crest\" src={src} alt={name} width={size} height={size} loading=\"lazy\" onError={() => setFailed(true)} />\n  }\n  return (\n    <svg className=\"ss-g-crest ss-g-crest--ph\" width={size} height={size * 32 / 28} viewBox=\"0 0 28 32\" role=\"img\" aria-label={name}>\n      <path d=\"M2 3h24v12c0 9-6 14-12 17C8 29 2 24 2 15z\" fill=\"currentColor\" />\n    </svg>\n  )\n}\n","import React, { useEffect, useId, useRef, useState } from 'react'\nimport type { GameScreenProps, BeatTheGridConfig, BtgClientState, BtgCellResult, BtgCriterionMeta } from './types'\nimport type { UiConfig } from '../../config'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { SearchField } from './ui/SearchField'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport {\n  IconCalendar, IconBall, IconBoot, IconGloves, IconShield, IconFlag, IconCheck, IconClose, IconPlus,\n} from './ui/icons'\nimport { gameTitle } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\nimport { CrestShield } from './ui/CrestShield'\nimport { nationalityFlag } from './nationFlags'\n\nexport interface PlayerEntry {\n  id: number\n  name: string\n  imagePath?: string\n}\n\n// playerPool comes from config.playerPool, threaded through by GameScreenHost.\nexport interface BeatTheGridGameProps extends GameScreenProps<BeatTheGridConfig> {\n  playerPool: PlayerEntry[]\n}\n\ninterface ActiveCell {\n  row: number\n  col: number\n}\n\nexport type CriterionIconKind = 'calendar' | 'ball' | 'boot' | 'gloves' | 'shield' | 'flag'\n\n// Header icon from the criterion key when present (stable across languages), else the English\n// label text of a pre-u400 game; unknown criteria (nationality groups, yellow cards) get the flag.\nexport function criterionIconKind(label: string, key?: string): CriterionIconKind {\n  const l = (key ?? label).toLowerCase()\n  if (l.includes('app')) return 'calendar'\n  if (l.includes('goal')) return 'ball'\n  if (l.includes('assist')) return 'boot'\n  if (l.includes('clean')) return 'gloves'\n  if (l.includes('tackle')) return 'shield'\n  return 'flag'\n}\n\n// The abbreviation map is keyed by the English position; a key like \"games.grid.row.forward\"\n// names it even when the label arrives translated (\"Forvet\").\nexport function rowAbbrev(label: string, map: Record<string, string>, key?: string): string {\n  const suffix = key?.split('.').pop()\n  const english = suffix ? suffix.charAt(0).toUpperCase() + suffix.slice(1) : label\n  return map[english] ?? map[label] ?? label\n}\n\nfunction CriterionIcon({ kind }: { kind: CriterionIconKind }): JSX.Element {\n  switch (kind) {\n    case 'calendar': return <IconCalendar />\n    case 'ball': return <IconBall />\n    case 'boot': return <IconBoot />\n    case 'gloves': return <IconGloves />\n    case 'shield': return <IconShield />\n    default: return <IconFlag />\n  }\n}\n\n// Renders the visual prefix of a header cell based on BtgCriterionMeta when present.\n// Without meta, falls back to the stat/nationality icon (today's behaviour).\nfunction HeaderVisual({ label, textKey: iKey, meta }: { label: string; textKey?: string; meta?: BtgCriterionMeta }): JSX.Element {\n  if (!meta) {\n    return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n  }\n  switch (meta.kind) {\n    case 'club':\n      return <CrestShield src={meta.imageUrl} name={label} size={24} />\n    case 'coach':\n      return <PlayerAvatar name={label} imagePath={meta.imageUrl} className=\"ss-g-btg-coach-av\" />\n    case 'country':\n      return <span className=\"ss-g-btg-hdr-flag\" aria-hidden=\"true\">{nationalityFlag(meta.country ?? label)}</span>\n    case 'position':\n      // Full localized label only (no icon, no abbreviation); the caller omits the icon slot.\n      return <></>\n    default:\n      return <CriterionIcon kind={criterionIconKind(label, iKey)} />\n  }\n}\n\nfunction parseClientState(json: string | null | undefined): BtgClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as BtgClientState\n  } catch {\n    return null\n  }\n}\n\nfunction findCellResult(cells: BtgCellResult[], row: number, col: number): BtgCellResult | undefined {\n  return cells.find(c => c.row === row && c.col === col)\n}\n\n// Compact initials for a placed player, e.g. \"Andrew Robertson\" → \"A. Robertson\".\n// Falls back to an empty string when the name is unknown.\nfunction shortName(name: string | undefined): string {\n  if (!name) return ''\n  const parts = name.trim().split(/\\s+/).filter(Boolean)\n  if (parts.length === 0) return ''\n  const first = parts[0]!\n  if (parts.length === 1) return first\n  const last = parts[parts.length - 1]!\n  return `${first.charAt(0)}. ${last}`\n}\n\nfunction SearchSheet({\n  row,\n  col,\n  rowLabel,\n  colLabel,\n  playerPool,\n  alreadyFilledIds,\n  onPick,\n  onDismiss,\n  ui,\n}: {\n  row: number\n  col: number\n  rowLabel: string\n  colLabel: string\n  playerPool: PlayerEntry[]\n  alreadyFilledIds: Set<number>\n  onPick: (row: number, col: number, playerId: number) => void\n  onDismiss: () => void\n  ui: UiConfig\n}): JSX.Element {\n  const s = ui.games.beatTheGrid\n  const [query, setQuery] = useState('')\n  const inputId = useId()\n  const inputRef = useRef<HTMLInputElement>(null)\n\n  useEffect(() => { inputRef.current?.focus() }, [row, col])\n\n  const filtered = playerPool.filter(\n    p => !alreadyFilledIds.has(p.id) && p.name.toLowerCase().includes(query.toLowerCase()),\n  )\n\n  return (\n    <div className=\"ss-g-btg-sheet\" data-testid=\"btg-search-sheet\">\n      <div className=\"ss-g-btg-sheet-hdr\">\n        <Chip variant=\"neutral\">{rowLabel}</Chip>\n        <span className=\"ss-g-btg-sheet-x\" aria-hidden=\"true\"><IconClose size={12} /></span>\n        <Chip variant=\"accent\">{colLabel}</Chip>\n        <button\n          type=\"button\"\n          className=\"ss-g-btg-sheet-close\"\n          data-testid=\"btg-sheet-dismiss\"\n          aria-label={s.closeSearch}\n          onClick={onDismiss}\n        >\n          <IconClose />\n        </button>\n      </div>\n      {playerPool.length === 0 ? (\n        <div className=\"ss-g-btg-sheet-empty\">{s.emptyPool}</div>\n      ) : (\n        <>\n          <SearchField\n            id={inputId}\n            label={s.searchLabel(rowLabel, colLabel)}\n            labelHidden\n            placeholder={s.searchPlaceholder}\n            value={query}\n            onChange={setQuery}\n            inputRef={inputRef}\n          />\n          {query.length > 0 && filtered.length > 0 && (\n            <OptionList\n              label={s.searchLabel(rowLabel, colLabel)}\n              options={filtered.map(p => ({\n                key: p.id,\n                content: (\n                  <>\n                    <PlayerAvatar name={p.name} imagePath={p.imagePath} className=\"ss-g-opt-av\" />\n                    <span className=\"ss-g-btg-result-name\">{p.name}</span>\n                    <span className=\"ss-g-btg-result-plus\" aria-hidden=\"true\"><IconPlus size={18} /></span>\n                  </>\n                ),\n              }))}\n              onPick={k => onPick(row, col, Number(k))}\n            />\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n\nexport function BeatTheGridGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  onBack,\n  ui,\n  playerPool,\n}: BeatTheGridGameProps): JSX.Element {\n  const s = ui.games.beatTheGrid\n  const title = gameTitle({ gameId: 'beat-the-grid' }, ui.games.titles)\n  const [activeCell, setActiveCell] = useState<ActiveCell | null>(null)\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const filledCells = clientState?.cells ?? []\n\n  const isLocked =\n    result?.alreadyPlayed === true ||\n    clientState?.isComplete === true\n\n  const alreadyFilledIds = new Set<number>(filledCells.map(c => c.playerId))\n\n  function handleCellClick(row: number, col: number): void {\n    if (isLocked || submitting) return\n    const alreadyFilled = findCellResult(filledCells, row, col)\n    if (alreadyFilled) return\n    setActiveCell({ row, col })\n  }\n\n  function handlePick(row: number, col: number, playerId: number): void {\n    setActiveCell(null)\n    const prevCells = filledCells.map(c => ({ row: c.row, col: c.col, playerId: c.playerId }))\n    const newCells = [...prevCells, { row, col, playerId }]\n    onSubmit(JSON.stringify({ cells: newCells }))\n  }\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"beat-the-grid\" data-testid=\"game-screen-beat-the-grid\">\n        <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const rows = config.rows\n  const cols = config.cols\n  const total = rows.length * cols.length\n  const correctCount = filledCells.filter(c => c.isCorrect).length\n  const wrongCount = filledCells.length - correctCount\n  const segments: SegmentState[] = Array.from({ length: total }, (_, i) =>\n    i < correctCount ? 'correct' : i < correctCount + wrongCount ? 'wrong' : 'todo',\n  )\n  // A returning fan may come back with no client state: show the stored play score then.\n  const totalScore = clientState?.totalScore ?? result?.score ?? 0\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"beat-the-grid\" data-testid=\"game-screen-beat-the-grid\">\n      <GameHeader title={title} eyebrow={s.eyebrow} onBack={onBack} backLabel={ui.back} />\n      <SegmentProgress\n        segments={segments}\n        ariaLabel={s.progressAria(filledCells.length, total)}\n        leftLabel={s.filled(filledCells.length, total)}\n        rightLabel={s.toGo(Math.max(0, total - filledCells.length))}\n        right={<Chip variant=\"accent\">{`${totalScore} ${ui.games.unitPts}`}</Chip>}\n      />\n\n      <div className=\"ss-g-body\">\n        <div\n          className={activeCell !== null ? 'ss-g-btg-grid ss-g-btg-grid--fit' : 'ss-g-btg-grid'}\n          style={{\n            gridTemplateColumns: `64px repeat(${cols.length}, minmax(0, 1fr))`,\n            gridTemplateRows: `minmax(44px, 60px) repeat(${rows.length}, minmax(44px, 98px))`,\n          } as React.CSSProperties}\n          role=\"grid\"\n        >\n          <div className=\"ss-g-btg-corner\" />\n          {cols.map((col, colIdx) => {\n            const colMeta = config.colsMeta?.[colIdx]\n            return (\n              <div key={col} className=\"ss-g-btg-colhdr\" data-meta={colMeta ? 'true' : undefined}>\n                <HeaderVisual label={col} textKey={config.colsI18n?.[colIdx]?.key} meta={colMeta} />\n                <span>{col}</span>\n              </div>\n            )\n          })}\n          {rows.map((rowLabel, rowIdx) => {\n            const rowMeta = config.rowsMeta?.[rowIdx]\n            const abbr = rowAbbrev(rowLabel, s.rowAbbrev, config.rowsI18n?.[rowIdx]?.key)\n            // With meta, render using HeaderVisual (empty for position) + the full label.\n            // Without meta, use the abbreviation pattern (existing behaviour).\n            const rowHeaderContent = rowMeta ? (\n              <>\n                <HeaderVisual label={rowLabel} textKey={config.rowsI18n?.[rowIdx]?.key} meta={rowMeta} />\n                <span>{rowLabel}</span>\n              </>\n            ) : abbr === rowLabel ? (\n              <span>{rowLabel}</span>\n            ) : (\n              <>\n                <span aria-hidden=\"true\">{abbr}</span>\n                <span className=\"ss-g-sr\">{rowLabel}</span>\n              </>\n            )\n            return (\n              <React.Fragment key={rowIdx}>\n                <div className=\"ss-g-btg-rowhdr\" data-meta={rowMeta ? 'true' : undefined}>\n                  {rowHeaderContent}\n                </div>\n                {cols.map((colLabel, colIdx) => {\n                  const filled = findCellResult(filledCells, rowIdx, colIdx)\n                  const isActive = activeCell?.row === rowIdx && activeCell?.col === colIdx\n                  const state = filled ? (filled.isCorrect ? 'correct' : 'wrong') : isActive ? 'active' : 'empty'\n                  return (\n                    <button\n                      key={`cell-${rowIdx}-${colIdx}`}\n                      type=\"button\"\n                      data-testid={`btg-cell-${rowIdx}-${colIdx}`}\n                      data-state={state}\n                      aria-label={\n                        filled\n                          ? s.cellFilled(rowLabel, colLabel, playerPool.find(p => p.id === filled.playerId)?.name ?? '', filled.isCorrect ? s.correct : s.wrong)\n                          : s.pickCell(rowLabel, colLabel)\n                      }\n                      aria-pressed={isActive}\n                      className=\"ss-g-btg-cell\"\n                      disabled={isLocked || submitting}\n                      onClick={() => handleCellClick(rowIdx, colIdx)}\n                    >\n                      {filled ? (\n                        <>\n                          <span\n                            className={`ss-g-btg-badge ss-g-btg-badge--${filled.isCorrect ? 'correct' : 'wrong'}`}\n                            role=\"img\"\n                            aria-label={filled.isCorrect ? s.correct : s.wrong}\n                          >\n                            {filled.isCorrect ? <IconCheck size={11} /> : <IconClose size={11} />}\n                          </span>\n                          <span className=\"ss-g-btg-rarity\">{filled.rarityScore}</span>\n                          {(() => {\n                            const entry = playerPool.find(p => p.id === filled.playerId)\n                            return (\n                              <PlayerAvatar\n                                name={entry?.name ?? ''}\n                                imagePath={entry?.imagePath}\n                                className=\"ss-g-btg-av\"\n                              />\n                            )\n                          })()}\n                          <span className=\"ss-g-btg-name\">\n                            {shortName(playerPool.find(p => p.id === filled.playerId)?.name)}\n                          </span>\n                        </>\n                      ) : (\n                        <span className=\"ss-g-btg-plus\" aria-hidden=\"true\"><IconPlus size={22} /></span>\n                      )}\n                    </button>\n                  )\n                })}\n              </React.Fragment>\n            )\n          })}\n        </div>\n\n        {isLocked && (\n          <ResultCard\n            tone=\"neutral\"\n            title={s.complete}\n            score={totalScore}\n            detail={s.summary(correctCount, filledCells.length)}\n            onBack={onBack}\n            ui={ui}\n          />\n        )}\n      </div>\n\n      {activeCell !== null && (\n        <div className=\"ss-g-btg-pin\">\n          <SearchSheet\n            key={`${activeCell.row}-${activeCell.col}`}\n            row={activeCell.row}\n            col={activeCell.col}\n            rowLabel={rows[activeCell.row] ?? ''}\n            colLabel={cols[activeCell.col] ?? ''}\n            playerPool={playerPool}\n            alreadyFilledIds={alreadyFilledIds}\n            onPick={handlePick}\n            onDismiss={() => setActiveCell(null)}\n            ui={ui}\n          />\n        </div>\n      )}\n    </div>\n  )\n}\n","import type { ReactNode } from 'react'\n\nexport interface OptionItem { key: string | number; content: ReactNode }\n\n// Typeahead results. Real <button>s (keyboard reachable) carrying role=option inside a listbox.\nexport function OptionList({ label, options, onPick }: {\n  label: string; options: OptionItem[]; onPick: (key: string | number) => void\n}): JSX.Element {\n  return (\n    <div className=\"ss-g-opts\" role=\"listbox\" aria-label={label}>\n      {options.map(o => (\n        <button key={o.key} type=\"button\" role=\"option\" aria-selected={false} className=\"ss-g-opt\" onClick={() => onPick(o.key)}>\n          {o.content}\n        </button>\n      ))}\n    </div>\n  )\n}\n","import { useState, useId } from 'react'\nimport type { GameScreenProps, GuessTheXiConfig, XiClientState } from './types'\nimport { isNationCode, nationalityFlag } from './nationFlags'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { PointsLadderRow } from './ui/PointsLadderRow'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { CrestShield } from './ui/CrestShield'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { OptionList } from './ui/OptionList'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { toRows, formationLabel, positionsBySlot } from './ui/formations'\nimport { PlayerAvatar } from './PlayerAvatar'\n\n// Total guesses allowed per day. Kept in sync with GuessTheXiScorer.MaxGuesses on the backend.\nconst MAX_GUESSES = 3\n\nfunction parseClientState(json: string | null | undefined): XiClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as XiClientState\n  } catch {\n    return null\n  }\n}\n\nexport function GuessTheXiGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<GuessTheXiConfig>): JSX.Element {\n  const t = ui.games.guessTheXi\n  const [query, setQuery] = useState('')\n  const inputId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n\n  const isOver =\n    result?.alreadyPlayed === true ||\n    clientState?.status === 'solved' ||\n    clientState?.status === 'failed'\n  const solved = clientState?.status === 'solved'\n  const failed = clientState?.status === 'failed'\n\n  const guessedTeamIds = new Set<number>(clientState?.guessHistory.map(g => g.teamId) ?? [])\n  const rows = config ? toRows(config.positions) : []\n  // Only name the shape when the data is a real formation; a neutral fallback grid has no shape.\n  const formation = config?.hasRealFormation ? formationLabel(rows) : ''\n  // Position label under every node (GK/CB/CM/ST…), derived from the formation coordinates only.\n  const posBySlot = config?.hasRealFormation ? positionsBySlot(formation, rows) : new Map<string, string>()\n\n  // A wrong guess can earn a player-name reveal; pin each to its slot so the surname replaces that\n  // node's position tag. Position-type reveals are redundant now that every position is shown.\n  const nameBySlot = new Map<string, string>()\n  ;(clientState?.earnedReveals ?? []).forEach(r => { if (r.slot && r.type !== 'position') nameBySlot.set(r.slot, r.value) })\n\n  // When the game ends and a lineup is present, map slot → lineup entry for photo + name display.\n  const lineupBySlot = new Map<string, { name: string; imagePath?: string }>()\n  ;(clientState?.lineup ?? []).forEach(e => { lineupBySlot.set(e.slot, { name: e.name, imagePath: e.imagePath }) })\n\n  const filtered =\n    config && !isOver\n      ? config.teamPool.filter(\n          tm => !guessedTeamIds.has(tm.teamId) && tm.teamName.toLowerCase().includes(query.toLowerCase()),\n        )\n      : []\n\n  function handlePick(teamId: number): void {\n    if (!config || isOver || submitting) return\n    const prevGuesses = clientState?.guessHistory.map(g => ({ teamId: g.teamId })) ?? []\n    const newGuesses = [...prevGuesses, { teamId }]\n    setQuery('')\n    onSubmit(JSON.stringify({ guesses: newGuesses }))\n  }\n\n  const wrongGuesses = (clientState?.guessHistory ?? []).filter(g => !g.wasCorrect)\n  const guessesLeft = Math.max(0, MAX_GUESSES - (clientState?.guessesUsed ?? 0))\n  const teamName = (id: number): string => config?.teamPool.find(tm => tm.teamId === id)?.teamName ?? `#${id}`\n\n  return (\n    <div className=\"ss-g-screen ss-g-gxi\" data-game=\"guess-the-xi\" data-testid=\"game-screen-guess-the-xi\">\n      <GameHeader\n        title={gameTitle({ gameId: 'guess-the-xi' }, ui.games.titles)}\n        eyebrow={config?.poolLabel}\n        right={formation ? <Chip variant=\"accent\">{formation}</Chip> : undefined}\n        onBack={onBack}\n        backLabel={ui.back}\n      />\n\n      {!config && <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>}\n\n      {config && (\n        <>\n          <div className=\"ss-g-body\">\n            {!isOver && <PointsLadderRow ladder={config.pointsLadder} guessesUsed={clientState?.guessHistory.length ?? 0} ui={ui} />}\n            {rows.length > 0 && (\n              <div className=\"ss-g-gxi-pitch\" role=\"group\" aria-label={t.pitchLabel}>\n                <PitchSvg variant=\"full\" />\n                <div className=\"ss-g-gxi-rows\">\n                  {rows.map((row, r) => (\n                    <div key={r} className=\"ss-g-gxi-row\">\n                      {row.map((pos, c) => {\n                        const posLabel = pos.slot ? posBySlot.get(pos.slot) ?? '' : ''\n                        const name = pos.slot ? nameBySlot.get(pos.slot) : undefined\n                        const lineupEntry = pos.slot ? lineupBySlot.get(pos.slot) : undefined\n                        const flag = nationalityFlag(pos.nationality)\n                        // When lineup is present (terminal state), discs show photo + surname.\n                        if (lineupEntry) {\n                          return (\n                            <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed=\"true\">\n                              <PlayerAvatar\n                                name={lineupEntry.name}\n                                imagePath={lineupEntry.imagePath}\n                                className=\"ss-g-gxi-disc ss-g-gxi-disc--photo\"\n                              />\n                              <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(lineupEntry.name).last}</span>\n                            </div>\n                          )\n                        }\n                        return (\n                          <div key={`${pos.slot}-${c}`} className=\"ss-g-gxi-node\" data-revealed={name ? 'true' : undefined}>\n                            <span\n                              className=\"ss-g-gxi-disc\"\n                              data-code={isNationCode(flag) ? 'true' : undefined}\n                              role=\"img\"\n                              title={pos.nationality}\n                              aria-label={`${posLabel ? posLabel + ' — ' : ''}${pos.nationality}${name ? ' — ' + name : ''}`}\n                            >\n                              {flag}\n                            </span>\n                            {name\n                              ? <span className=\"ss-g-gxi-pos ss-g-gxi-pos--name\">{splitName(name).last}</span>\n                              : posLabel && <span className=\"ss-g-gxi-pos\">{posLabel}</span>}\n                          </div>\n                        )\n                      })}\n                    </div>\n                  ))}\n                </div>\n              </div>\n            )}\n\n            {!isOver && wrongGuesses.length > 0 && (\n              <div className=\"ss-g-gxi-wrong\">\n                <span className=\"ss-g-gxi-wrong-l\">{t.notThem}</span>\n                {wrongGuesses.map(g => {\n                  const crestUrl = config?.teamPool.find(tm => tm.teamId === g.teamId)?.crestUrl\n                  return (\n                    <span key={g.teamId} className=\"ss-g-gxi-wrong-chip\">\n                      <CrestShield src={crestUrl} name={teamName(g.teamId)} size={18} />\n                      <s>{teamName(g.teamId)}</s>\n                    </span>\n                  )\n                })}\n              </div>\n            )}\n\n            {isOver && (\n              <>\n                <ResultCard\n                  tone={solved ? 'win' : failed ? 'lose' : 'neutral'}\n                  title={solved ? t.solved : failed ? t.failed : ui.games.alreadyPlayedTitle}\n                  score={clientState?.score ?? result?.score ?? 0}\n                  detail={clientState ? t.detail(clientState.guessesUsed) : undefined}\n                  onBack={onBack}\n                  ui={ui}\n                />\n                {(solved || failed) && clientState?.answer && (\n                  <div className=\"ss-g-gxi-answer\" data-testid=\"gxi-answer-reveal\">\n                    <span className=\"ss-g-gxi-answer-label\">{t.theAnswer}</span>\n                    <CrestShield src={clientState.answer.crestUrl} name={clientState.answer.teamName} size={32} />\n                    <span className=\"ss-g-gxi-answer-name\">{clientState.answer.teamName}</span>\n                  </div>\n                )}\n              </>\n            )}\n          </div>\n\n          {!isOver && (\n            <FooterBar>\n              {query.length > 0 && filtered.length > 0 && (\n                <OptionList\n                  label={t.optionsLabel}\n                  options={filtered.map(tm => ({\n                    key: tm.teamId,\n                    content: <><CrestShield src={tm.crestUrl} name={tm.teamName} size={28} /><span>{tm.teamName}</span></>,\n                  }))}\n                  onPick={k => handlePick(Number(k))}\n                />\n              )}\n              <SearchField id={inputId} label={t.whichClub(guessesLeft)} placeholder={t.searchPlaceholder}\n                value={query} onChange={setQuery} disabled={submitting} />\n            </FooterBar>\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n","export function PitchSvg({ variant }: { variant: 'full' | 'half' }): JSX.Element {\n  return (\n    <svg className=\"ss-g-pitch-svg\" viewBox={variant === 'full' ? '0 0 100 150' : '0 0 100 100'} preserveAspectRatio=\"none\" aria-hidden=\"true\">\n      <rect x=\"4\" y=\"4\" width=\"92\" height={variant === 'full' ? 142 : 92} fill=\"none\" />\n      {variant === 'full' ? (\n        <>\n          <line x1=\"4\" y1=\"75\" x2=\"96\" y2=\"75\" /><circle cx=\"50\" cy=\"75\" r=\"12\" fill=\"none\" />\n          <rect x=\"26\" y=\"4\" width=\"48\" height=\"20\" fill=\"none\" /><rect x=\"26\" y=\"126\" width=\"48\" height=\"20\" fill=\"none\" />\n        </>\n      ) : (\n        <>\n          <path d=\"M38 4a12 12 0 0 0 24 0\" fill=\"none\" />\n          <rect x=\"26\" y=\"76\" width=\"48\" height=\"20\" fill=\"none\" />\n        </>\n      )}\n    </svg>\n  )\n}\n","import type { XiSlotEntry } from '../types'\n\n/**\n * Groups the flat position list into formation rows keyed by the \"row:col\" slot's row part, then\n * orders the rows so the GOALKEEPER LINE (row 1) sits at the BOTTOM — the football convention: a\n * team defends the bottom goal and attacks upward (GK → defence → midfield → attack).\n *\n * Within a line the provider numbers positions from the team's RIGHT (Sportmonks formation_field:\n * \"2:1\" is the right-back, \"2:4\" the left-back). Drawn attacking upward, the right side is on the\n * screen's right, so each line is returned highest column first (left → right on screen).\n */\nexport function toRows(positions: XiSlotEntry[]): XiSlotEntry[][] {\n  const byRow = new Map<number, XiSlotEntry[]>()\n  positions.forEach((p, i) => {\n    const rowKey = Number(p.slot?.split(':')[0]) || i + 1\n    const bucket = byRow.get(rowKey) ?? []\n    bucket.push(p)\n    byRow.set(rowKey, bucket)\n  })\n  const col = (p: XiSlotEntry): number => Number(p.slot?.split(':')[1]) || 0\n  // Descending: highest row number (forwards) at the top, row 1 (GK) at the bottom.\n  return [...byRow.keys()].sort((a, b) => b - a).map(k => [...byRow.get(k)!].sort((a, b) => col(b) - col(a)))\n}\n\n// Football formation notation from the grouped rows — the outfield lines from defence to attack,\n// goalkeeper excluded (e.g. GK/4/2/3/1 → \"4-2-3-1\"). `rows` arrive attack-first (descending), so\n// read them bottom-up and drop the goalkeeper line.\nexport function formationLabel(rowsAttackFirst: XiSlotEntry[][]): string {\n  if (rowsAttackFirst.length < 2) return ''\n  const gkFirst = [...rowsAttackFirst].reverse()\n  return gkFirst.slice(1).map(r => r.length).join('-')\n}\n\n// Canonical position labels per formation, goalkeeper first then each outfield line, left→right.\n// Lets us print a real position (GK, RB, CDM, ST…) under every node so the fan can read the shape\n// and see at a glance which end is the goalkeeper — without the config having to carry positions.\nexport const FORMATION_POSITIONS: Record<string, string[][]> = {\n  '4-4-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['ST', 'ST']],\n  '4-3-3': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CM', 'CM', 'CM'], ['LW', 'ST', 'RW']],\n  '4-2-3-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM', 'CDM'], ['LW', 'CAM', 'RW'], ['ST']],\n  '4-1-4-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n  '4-5-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'CM', 'RM'], ['ST']],\n  '4-4-1-1': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['LM', 'CM', 'CM', 'RM'], ['CAM'], ['ST']],\n  '4-1-2-1-2': [['GK'], ['LB', 'CB', 'CB', 'RB'], ['CDM'], ['LM', 'RM'], ['CAM'], ['ST', 'ST']],\n  '3-5-2': [['GK'], ['CB', 'CB', 'CB'], ['LWB', 'CM', 'CM', 'CM', 'RWB'], ['ST', 'ST']],\n  '3-4-3': [['GK'], ['CB', 'CB', 'CB'], ['LM', 'CM', 'CM', 'RM'], ['LW', 'ST', 'RW']],\n  '5-3-2': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['CM', 'CM', 'CM'], ['ST', 'ST']],\n  '5-4-1': [['GK'], ['LWB', 'CB', 'CB', 'CB', 'RWB'], ['LM', 'CM', 'CM', 'RM'], ['ST']],\n}\n\n// Line-level fallback when the exact formation is not in the table above: the goalkeeper line, the\n// forward line, then defence/midfield by depth. Always correct at the line grain even when the\n// specific role is not — enough to read the shape and spot the keeper.\nexport function lineFallback(lineIdx: number, totalLines: number): string {\n  if (lineIdx === 0) return 'GK'\n  if (lineIdx === totalLines - 1) return 'FWD'\n  if (lineIdx === 1) return 'DEF'\n  return 'MID'\n}\n\n// Map each slot (\"row:col\") to a position label, reading the rows goalkeeper-first.\nexport function positionsBySlot(formation: string, rowsAttackFirst: XiSlotEntry[][]): Map<string, string> {\n  const gkFirst = [...rowsAttackFirst].reverse()\n  const template = FORMATION_POSITIONS[formation]\n  const map = new Map<string, string>()\n  gkFirst.forEach((line, li) => {\n    line.forEach((entry, ci) => {\n      if (!entry.slot) return\n      const label = template?.[li]?.[ci] ?? lineFallback(li, gkFirst.length)\n      map.set(entry.slot, label)\n    })\n  })\n  return map\n}\n","import { useState } from 'react'\nimport type { GameScreenProps, DailyQuizConfig, DailyQuizClientState, DailyQuizResult } from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): DailyQuizClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as DailyQuizClientState\n  } catch {\n    return null\n  }\n}\n\nfunction findResult(results: DailyQuizResult[], index: number): DailyQuizResult | undefined {\n  return results.find(r => r.index === index)\n}\n\nconst TRAILING_PAREN = /\\s*\\(([^)]*)\\)$/\nconst NAME_TOKEN = /^[\\p{L}\\p{M}.'’-]+$/u\n\nfunction OptionName({ text }: { text: string }): JSX.Element {\n  const match = TRAILING_PAREN.exec(text)\n  const base = match ? text.slice(0, match.index).trim() : text.trim()\n  const suffix = match?.[1]?.trim() ?? ''\n  const tokens = base.split(/\\s+/).filter(Boolean)\n  const isPlainName = tokens.length >= 1 && tokens.length <= 4 && tokens.every(t => NAME_TOKEN.test(t))\n  if (!isPlainName || base === '') {\n    return (\n      <span className=\"ss-g-dq-opt-name\">\n        <span className=\"ss-g-dq-opt-full\">{text}</span>\n      </span>\n    )\n  }\n  const { first, last } = splitName(base)\n  return (\n    <span className=\"ss-g-dq-opt-name\">\n      {first && <span className=\"ss-g-dq-opt-first\">{first}</span>}\n      <span className=\"ss-g-dq-opt-last\">{last}</span>\n      {suffix && <span className=\"ss-g-dq-opt-suffix\">{suffix}</span>}\n    </span>\n  )\n}\n\nexport function DailyQuizGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  onBack,\n  ui,\n}: GameScreenProps<DailyQuizConfig>): JSX.Element {\n  const s = ui.games.dailyQuiz\n  const title = gameTitle({ gameId: 'daily-quiz' }, ui.games.titles)\n  // Local selection state: map from question index → selected option index\n  const [selections, setSelections] = useState<Map<number, number>>(new Map())\n  const [page, setPage] = useState(0)\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const results = clientState?.results ?? []\n  const isRevealed = results.length > 0 || result?.alreadyPlayed === true\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"daily-quiz\" data-testid=\"game-screen-daily-quiz\">\n        <GameHeader title={title} onBack={onBack} backLabel={ui.back} />\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const questions = config.questions\n  const total = questions.length\n  const current = questions[Math.min(page, total - 1)]\n  const isLast = page >= total - 1\n  const currentAnswered = current !== undefined && selections.has(current.index)\n  const allAnswered = selections.size === total\n\n  function handleSelect(questionIndex: number, optionIndex: number): void {\n    if (isRevealed || submitting) return\n    setSelections(prev => new Map(prev).set(questionIndex, optionIndex))\n  }\n\n  function goNext(): void {\n    if (!currentAnswered || isLast) return\n    setPage(p => p + 1)\n  }\n\n  function goPrev(): void {\n    setPage(p => Math.max(0, p - 1))\n  }\n\n  function handleSubmit(): void {\n    if (!config || !allAnswered || isRevealed || submitting) return\n    const answers = config.questions.map(q => ({\n      index: q.index,\n      selectedOptionIndex: selections.get(q.index) ?? 0,\n    }))\n    onSubmit(JSON.stringify({ answers }))\n  }\n\n  if (isRevealed) {\n    const segments: SegmentState[] = questions.map(q => {\n      const r = findResult(results, q.index)\n      if (!r) return 'done'\n      return r.isCorrect ? 'correct' : 'wrong'\n    })\n    const correctCount = results.filter(r => r.isCorrect).length\n    return (\n      <div className=\"ss-g-screen\" data-game=\"daily-quiz\" data-testid=\"game-screen-daily-quiz\">\n        <GameHeader title={title} eyebrow={s.results} onBack={onBack} backLabel={ui.back} />\n        <SegmentProgress segments={segments} ariaLabel={s.results} />\n        <div className=\"ss-g-body\">\n          <ResultCard\n            tone=\"neutral\"\n            title={results.length > 0 ? s.correctOf(correctCount, total) : ui.games.alreadyPlayedTitle}\n            score={result?.score}\n            onBack={onBack}\n            ui={ui}\n          />\n          {questions.map(q => {\n            const r = findResult(results, q.index)\n            const picked = selections.get(q.index)\n            return (\n              <div key={q.index} className=\"ss-g-dq-rq\">\n                <div className=\"ss-g-dq-rq-stem\">{q.stem}</div>\n                {r && (\n                  <div className=\"ss-g-dq-rq-opts\">\n                    {q.options.map((opt, optIdx) => {\n                      let cls = 'ss-g-dq-rq-opt'\n                      if (optIdx === r.correctOptionIndex) cls += ' ss-g-dq-rq-opt--correct'\n                      else if (optIdx === picked && !r.isCorrect) cls += ' ss-g-dq-rq-opt--wrong'\n                      return <span key={optIdx} className={cls}>{opt}</span>\n                    })}\n                  </div>\n                )}\n                {r?.revealText && <div className=\"ss-g-dq-why\">{r.revealText}</div>}\n              </div>\n            )\n          })}\n        </div>\n      </div>\n    )\n  }\n\n  const segments: SegmentState[] = questions.map((_, i) => (i < page ? 'done' : i === page ? 'current' : 'todo'))\n  const selectedIdx = current ? selections.get(current.index) : undefined\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"daily-quiz\" data-testid=\"game-screen-daily-quiz\">\n      <GameHeader title={title} eyebrow={s.questionOf(page + 1, total)} onBack={onBack} backLabel={ui.back} />\n      <SegmentProgress segments={segments} ariaLabel={s.progressAria(page + 1, total)} />\n      <div className=\"ss-g-body\">\n        {current && (\n          <>\n            <h3 className=\"ss-g-dq-stem\">{current.stem}</h3>\n            <div className=\"ss-g-dq-opts\">\n              {current.options.map((opt, optIdx) => {\n                const selected = optIdx === selectedIdx\n                const imagePath = current.optionImagePaths?.[optIdx] ?? undefined\n                const playerName = opt\n                return (\n                  <button\n                    key={optIdx}\n                    type=\"button\"\n                    className=\"ss-g-dq-opt\"\n                    aria-pressed={selected}\n                    disabled={submitting}\n                    onClick={() => handleSelect(current.index, optIdx)}\n                  >\n                    {current.optionImagePaths && (\n                      <PlayerAvatar name={playerName} imagePath={imagePath} className=\"ss-g-dq-opt-av\" />\n                    )}\n                    <span className=\"ss-g-dq-badge\" aria-hidden=\"true\">\n                      {selected ? <IconCheck /> : String.fromCharCode(65 + optIdx)}\n                    </span>\n                    <OptionName text={opt} />\n                  </button>\n                )\n              })}\n            </div>\n          </>\n        )}\n      </div>\n      <FooterBar>\n        <div className=\"ss-g-dq-nav\">\n          {page > 0 && (\n            <GameButton variant=\"outline\" onClick={goPrev} disabled={submitting}>{s.previous}</GameButton>\n          )}\n          {isLast ? (\n            <GameButton variant=\"primary\" block onClick={handleSubmit} disabled={!currentAnswered || !allAnswered || submitting}>\n              {submitting ? s.submitting : s.submit}\n            </GameButton>\n          ) : (\n            <GameButton variant=\"primary\" block onClick={goNext} disabled={!currentAnswered || submitting}>\n              {s.next}\n            </GameButton>\n          )}\n        </div>\n      </FooterBar>\n    </div>\n  )\n}\n","import { useId, useState } from 'react'\nimport type {\n  GameScreenProps,\n  MatchdayPredictorConfig,\n  MatchdayPredictorClientState,\n  MatchdayPredictorTeam,\n} from './types'\nimport type { GamesStrings } from '../../i18n'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { CrestShield } from './ui/CrestShield'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck, IconClose, IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Above this many scorers the card grid gets a search filter (spec §5.7).\nconst SCORER_SEARCH_THRESHOLD = 9\n\ntype Side = 'home' | 'away'\ntype PredictorStrings = GamesStrings['predictor']\n\nfunction parseClientState(json: string | null | undefined): MatchdayPredictorClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as MatchdayPredictorClientState\n  } catch {\n    return null\n  }\n}\n\nfunction isLocked(kickoffUtc: string): boolean {\n  try {\n    return new Date(kickoffUtc).getTime() <= Date.now()\n  } catch {\n    return true\n  }\n}\n\nfunction IconMinus(): JSX.Element {\n  return (\n    <svg width={18} height={18} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.2}\n      strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M5 12h14\" /></svg>\n  )\n}\n\nfunction TeamBadge({ team, label }: { team: MatchdayPredictorTeam; label: string }): JSX.Element {\n  return (\n    <div className=\"ss-g-mp-team\">\n      <CrestShield name={team.name} size={44} />\n      <span className=\"ss-g-mp-team-name\">{team.name}</span>\n      <span className=\"ss-g-mp-team-side\">{label}</span>\n    </div>\n  )\n}\n\nfunction ScoreCard({ home, away, h, a, t, edit }: {\n  home: MatchdayPredictorTeam\n  away: MatchdayPredictorTeam\n  h: number\n  a: number\n  t: PredictorStrings\n  edit?: { disabled: boolean; active: Side; onStep: (side: Side, delta: 1 | -1) => void }\n}): JSX.Element {\n  const col = (side: Side, team: MatchdayPredictorTeam, value: number): JSX.Element => (\n    <div className=\"ss-g-mp-col\">\n      {edit && (\n        <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsUp(team.name)}\n          disabled={edit.disabled} onClick={() => edit.onStep(side, 1)}>\n          <IconPlus size={18} />\n        </button>\n      )}\n      <span className=\"ss-g-mp-digit\" data-testid=\"mp-digit\" data-active={edit ? String(edit.active === side) : 'false'}>\n        {value}\n      </span>\n      {edit && (\n        <button type=\"button\" className=\"ss-g-mp-step\" aria-label={t.goalsDown(team.name)}\n          disabled={edit.disabled || value <= 0} onClick={() => edit.onStep(side, -1)}>\n          <IconMinus />\n        </button>\n      )}\n    </div>\n  )\n  return (\n    <div className=\"ss-g-mp-card\">\n      <TeamBadge team={home} label={t.home} />\n      <div className=\"ss-g-mp-scores\">\n        {col('home', home, h)}\n        <span className=\"ss-g-mp-dash\" aria-hidden=\"true\">–</span>\n        {col('away', away, a)}\n      </div>\n      <TeamBadge team={away} label={t.away} />\n    </div>\n  )\n}\n\nfunction OutcomeRow({ label, ok, detail, t }: { label: string; ok: boolean; detail?: string | null; t: PredictorStrings }): JSX.Element {\n  return (\n    <li className=\"ss-g-mp-row\" data-testid=\"mp-row\" data-ok={String(ok)}>\n      <span className=\"ss-g-mp-row-k\">{label}</span>\n      <span className=\"ss-g-mp-row-v\">\n        {ok ? <IconCheck /> : <IconClose size={14} />}\n        <span className=\"ss-g-sr\">{ok ? t.correct : t.incorrect}</span>\n        {detail ? <span className=\"ss-g-mp-row-d\">{detail}</span> : null}\n      </span>\n    </li>\n  )\n}\n\nexport function MatchdayPredictorGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<MatchdayPredictorConfig>): JSX.Element {\n  const t = ui.games.predictor\n  const [homeScore, setHomeScore] = useState(0)\n  const [awayScore, setAwayScore] = useState(0)\n  const [firstScorerPlayerId, setFirstScorerPlayerId] = useState<number | null>(null)\n  const [lastEdited, setLastEdited] = useState<Side>('home')\n  const [query, setQuery] = useState('')\n  const searchId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const alreadyPlayed = result?.alreadyPlayed === true\n\n  const header = (\n    <GameHeader\n      title={gameTitle({ gameId: 'matchday-predictor' }, ui.games.titles)}\n      eyebrow={config ? t.eyebrow(config.homeTeam.name, config.awayTeam.name) : undefined}\n      right={config ? <Chip icon={<IconLock />}>{ui.games.formatDayTime(config.kickoffUtc)}</Chip> : undefined}\n      onBack={onBack}\n      backLabel={ui.back}\n    />\n  )\n\n  // Played states (pending or graded) when the fan has already submitted\n  if (alreadyPlayed && clientState) {\n    if (!clientState.graded) {\n      const scorer = config?.scorerPool.find(p => p.playerId === clientState.predictedFirstScorerPlayerId) ?? null\n      return (\n        <div className=\"ss-g-screen\" data-game=\"matchday-predictor\" data-testid=\"game-screen-matchday-predictor\">\n          {header}\n          <div className=\"ss-g-body\">\n            {config && (\n              <ScoreCard home={config.homeTeam} away={config.awayTeam}\n                h={clientState.predictedHomeScore} a={clientState.predictedAwayScore} t={t} />\n            )}\n            <ResultCard\n              tone=\"neutral\"\n              title={t.saved}\n              detail={t.savedDetail({\n                home: config?.homeTeam.name ?? '',\n                away: config?.awayTeam.name ?? '',\n                h: clientState.predictedHomeScore,\n                a: clientState.predictedAwayScore,\n                scorer: scorer ? splitName(scorer.playerName).last : null,\n              })}\n              onBack={onBack}\n              ui={ui}\n            />\n          </div>\n          <FooterBar>\n            <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n          </FooterBar>\n        </div>\n      )\n    }\n\n    const r = clientState.result\n    return (\n      <div className=\"ss-g-screen\" data-game=\"matchday-predictor\" data-testid=\"game-screen-matchday-predictor\">\n        {header}\n        <div className=\"ss-g-body\">\n          {config && <ScoreCard home={config.homeTeam} away={config.awayTeam} h={r.homeScore} a={r.awayScore} t={t} />}\n          <ResultCard tone=\"neutral\" title={t.fullTime(r.homeScore, r.awayScore)} onBack={onBack} ui={ui} />\n          <ul className=\"ss-g-mp-rows\">\n            <OutcomeRow label={t.exactScore} ok={clientState.exactScoreCorrect} t={t} />\n            <OutcomeRow label={t.outcome} ok={clientState.outcomeCorrect} t={t} />\n            {!clientState.firstScorerVoid && (\n              <OutcomeRow label={t.firstScorerRow} ok={clientState.firstScorerCorrect} detail={r.firstScorerName} t={t} />\n            )}\n          </ul>\n        </div>\n        <FooterBar>\n          <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n        </FooterBar>\n      </div>\n    )\n  }\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"matchday-predictor\" data-testid=\"game-screen-matchday-predictor\">\n        {header}\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const locked = isLocked(config.kickoffUtc)\n  const disabled = locked || submitting\n\n  function step(side: Side, delta: 1 | -1): void {\n    setLastEdited(side)\n    if (side === 'home') setHomeScore(s => Math.max(0, s + delta))\n    else setAwayScore(s => Math.max(0, s + delta))\n  }\n\n  function handleSubmit(): void {\n    if (disabled || !config) return\n    onSubmit(\n      JSON.stringify({\n        homeScore,\n        awayScore,\n        ...(firstScorerPlayerId !== null ? { firstScorerPlayerId } : {}),\n      }),\n    )\n  }\n\n  const pool = config.scorerPool\n  const showSearch = pool.length > SCORER_SEARCH_THRESHOLD\n  const q = query.trim().toLowerCase()\n  const visible = showSearch && q ? pool.filter(p => p.playerName.toLowerCase().includes(q)) : pool\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"matchday-predictor\" data-testid=\"game-screen-matchday-predictor\">\n      {header}\n      <div className=\"ss-g-body\">\n        <ScoreCard\n          home={config.homeTeam}\n          away={config.awayTeam}\n          h={homeScore}\n          a={awayScore}\n          t={t}\n          edit={{ disabled, active: lastEdited, onStep: step }}\n        />\n\n        {pool.length > 0 && (\n          <section className=\"ss-g-mp-scorer\">\n            <div className=\"ss-g-mp-sec-head\">\n              <h3>{t.firstScorer}</h3>\n              <span>{t.optional}</span>\n            </div>\n            {showSearch && (\n              <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchPlaceholder}\n                value={query} onChange={setQuery} disabled={disabled} />\n            )}\n            <div className=\"ss-g-mp-grid\">\n              {visible.map(p => {\n                const selected = firstScorerPlayerId === p.playerId\n                return (\n                  <button\n                    key={p.playerId}\n                    type=\"button\"\n                    className=\"ss-g-mp-pcard\"\n                    aria-pressed={selected}\n                    aria-label={p.playerName}\n                    disabled={disabled}\n                    onClick={() => setFirstScorerPlayerId(id => (id === p.playerId ? null : p.playerId))}\n                  >\n                    {selected && <span className=\"ss-g-mp-pcheck\"><IconCheck size={12} /></span>}\n                    <Silhouette size={52} variant={selected ? 'selected' : 'default'} />\n                    <span className=\"ss-g-mp-pname\">{splitName(p.playerName).last}</span>\n                  </button>\n                )\n              })}\n            </div>\n            <button\n              type=\"button\"\n              className=\"ss-g-mp-none\"\n              aria-pressed={firstScorerPlayerId === null}\n              disabled={disabled}\n              onClick={() => setFirstScorerPlayerId(null)}\n            >\n              <span className=\"ss-g-mp-radio\" aria-hidden=\"true\" />\n              {t.noScorer}\n            </button>\n          </section>\n        )}\n\n        {locked && <p className=\"ss-g-mp-closed\">{t.closed}</p>}\n      </div>\n\n      <FooterBar>\n        <GameButton variant=\"primary\" block disabled={disabled} onClick={handleSubmit}>\n          {submitting ? t.saving : t.save}\n        </GameButton>\n        <p className=\"ss-g-mp-fun\">{t.forFun}</p>\n      </FooterBar>\n    </div>\n  )\n}\n","import { useId, useState } from 'react'\nimport type {\n  GameScreenProps,\n  StartingXiConfig,\n  StartingXiClientState,\n  StartingXiSquadEntry,\n} from './types'\nimport { FORMATION_POSITIONS, lineFallback } from './ui/formations'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { SegmentProgress } from './ui/SegmentProgress'\nimport type { SegmentState } from './ui/SegmentProgress'\nimport { GameButton } from './ui/GameButton'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { PitchSvg } from './ui/PitchSvg'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconLock, IconPlus } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\n\n// Display only — mirrors StartingXiScorer.PointsPerCorrectStarter (StartingXiScorer.cs:47).\nconst POINTS_PER_STARTER = 8\nconst XI_SIZE = 11\nconst DEFAULT_FORMATION = '4-3-3'\n\nexport interface XiSlot {\n  index: number\n  label: string\n  left: number\n  top: number\n}\n\nfunction parseClientState(json: string | null | undefined): StartingXiClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as StartingXiClientState\n  } catch {\n    return null\n  }\n}\n\n/**\n * Pitch slots for a formation, goalkeeper first then each outfield line left→right. Positions are\n * percentages of an attacking-half pitch: the keeper sits lowest (top 88%), the front line highest.\n * A formation that does not add up to 10 outfield players falls back to 4-3-3 so there are always 11.\n */\nexport function formationSlots(formation: string): { formation: string; slots: XiSlot[] } {\n  const parts = formation.split('-').map(Number).filter(n => n > 0)\n  const valid = parts.reduce((s, n) => s + n, 0) === XI_SIZE - 1\n  const used = valid ? formation : DEFAULT_FORMATION\n  const outfield = valid ? parts : DEFAULT_FORMATION.split('-').map(Number)\n  const lines = [1, ...outfield]\n  const template = FORMATION_POSITIONS[used]\n  const slots: XiSlot[] = []\n  lines.forEach((count, li) => {\n    const top = 88 - li * (77 / (lines.length - 1))\n    for (let ci = 0; ci < count; ci++) {\n      const left = count === 1 ? 50 : 12 + ci * (76 / (count - 1))\n      slots.push({ index: slots.length, label: template?.[li]?.[ci] ?? lineFallback(li, lines.length), left, top })\n    }\n  })\n  return { formation: used, slots }\n}\n\nfunction firstEmpty(slotPlayers: (number | null)[]): number | null {\n  const i = slotPlayers.findIndex(p => p === null)\n  return i === -1 ? null : i\n}\n\nexport function StartingXiGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n  lockAtUtc,\n}: GameScreenProps<StartingXiConfig>): JSX.Element {\n  const t = ui.games.startingXi\n  const [slotPlayers, setSlotPlayers] = useState<(number | null)[]>(() => Array<number | null>(XI_SIZE).fill(null))\n  const [active, setActive] = useState<number | null>(0)\n  const [query, setQuery] = useState('')\n  const searchId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const alreadyPlayed = result?.alreadyPlayed === true\n\n  const header = (\n    <GameHeader\n      title={gameTitle({ gameId: 'starting-xi' }, ui.games.titles)}\n      eyebrow={t.eyebrow}\n      right={<Chip variant=\"accent\">{t.perStarter(POINTS_PER_STARTER)}</Chip>}\n      onBack={onBack}\n      backLabel={ui.back}\n    />\n  )\n\n  // Pending, graded and voided all render the spec §6 result card with a way back to the hub.\n  function statusScreen(title: string, score?: number): JSX.Element {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"starting-xi\" data-testid=\"game-screen-starting-xi\">\n        {header}\n        <div className=\"ss-g-body\">\n          <ResultCard tone=\"neutral\" title={title} score={score} onBack={onBack} ui={ui} />\n        </div>\n      </div>\n    )\n  }\n\n  if (alreadyPlayed) {\n    if (!clientState) return statusScreen(t.voided)\n    if (clientState.status === 'pending') return statusScreen(t.pending(clientState.predictedCount))\n    if (clientState.status === 'graded') return statusScreen(t.gradedLine(clientState.correctCount), clientState.score)\n  }\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"starting-xi\" data-testid=\"game-screen-starting-xi\">\n        {header}\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const { formation, slots } = formationSlots(config.formation)\n  const byId = new Map<number, StartingXiSquadEntry>(config.squadSheet.map(p => [p.playerId, p]))\n  const pickedCount = slotPlayers.filter(p => p !== null).length\n  const canSubmit = pickedCount === XI_SIZE && !submitting\n  const pickedSet = new Set(slotPlayers.filter((p): p is number => p !== null))\n  const q = query.trim().toLowerCase()\n  const available = config.squadSheet.filter(\n    p => !pickedSet.has(p.playerId) && (!q || (p.playerName ?? '').toLowerCase().includes(q)),\n  )\n  const activeSlot = active !== null ? slots[active] ?? null : null\n\n  function pick(playerId: number): void {\n    if (submitting || active === null) return\n    const next = [...slotPlayers]\n    next[active] = playerId\n    setSlotPlayers(next)\n    setActive(firstEmpty(next))\n    setQuery('')\n  }\n\n  function tapSlot(index: number): void {\n    if (submitting) return\n    if (slotPlayers[index] !== null) {\n      const next = [...slotPlayers]\n      next[index] = null\n      setSlotPlayers(next)\n    }\n    setActive(index)\n  }\n\n  function handleSubmit(): void {\n    if (!canSubmit) return\n    onSubmit(JSON.stringify({ predictedPlayerIds: slotPlayers }))\n  }\n\n  const segments: SegmentState[] = slotPlayers.map(p => (p !== null ? 'current' : 'todo'))\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"starting-xi\" data-testid=\"game-screen-starting-xi\">\n      {header}\n      <SegmentProgress\n        segments={segments}\n        ariaLabel={t.picked(pickedCount)}\n        leftLabel={t.picked(pickedCount)}\n        rightLabel={t.toGo(XI_SIZE - pickedCount)}\n        right={<Chip>{formation}</Chip>}\n      />\n      <div className=\"ss-g-body\">\n        <div className=\"ss-g-xi-pitch\">\n          <PitchSvg variant=\"half\" />\n          {slots.map(s => {\n            const playerId = slotPlayers[s.index] ?? null\n            const player = playerId !== null ? byId.get(playerId) ?? null : null\n            const name = player?.playerName ?? ''\n            const state = player ? 'filled' : active === s.index ? 'active' : 'empty'\n            return (\n              <button\n                key={s.index}\n                type=\"button\"\n                className=\"ss-g-xi-slot\"\n                data-state={state}\n                style={{ left: `${s.left}%`, top: `${s.top}%` }}\n                aria-pressed={active === s.index}\n                aria-label={player ? t.clearSlot(s.label, name) : t.pickSlot(s.label)}\n                disabled={submitting}\n                onClick={() => tapSlot(s.index)}\n              >\n                <span className=\"ss-g-xi-ring\" aria-hidden=\"true\">\n                  {player ? (player.jerseyNumber ?? '') : <IconPlus size={18} />}\n                </span>\n                <span className=\"ss-g-xi-tag\" aria-hidden=\"true\">{player ? splitName(name).last : s.label}</span>\n              </button>\n            )\n          })}\n        </div>\n\n        <div className=\"ss-g-xi-picker\">\n          <div className=\"ss-g-xi-picker-head\">\n            {activeSlot ? (\n              <>\n                <Chip variant=\"badge\">{activeSlot.label}</Chip>\n                <strong>{t.pickFor(activeSlot.label)}</strong>\n              </>\n            ) : (\n              <strong>{t.allPicked}</strong>\n            )}\n          </div>\n          {activeSlot && (\n            <>\n              <SearchField id={searchId} label={t.searchLabel} labelHidden placeholder={t.searchLabel}\n                value={query} onChange={setQuery} disabled={submitting} />\n              <ul className=\"ss-g-xi-list\">\n                {available.map(p => (\n                  <li key={p.playerId}>\n                    <button type=\"button\" className=\"ss-g-xi-opt\" disabled={submitting} onClick={() => pick(p.playerId)}>\n                      <span className=\"ss-g-xi-opt-no\" aria-hidden=\"true\">{p.jerseyNumber ?? ''}</span>\n                      <span className=\"ss-g-xi-opt-name\">{p.playerName}</span>\n                      <span className=\"ss-g-xi-opt-pos\">{p.positionName}</span>\n                    </button>\n                  </li>\n                ))}\n              </ul>\n            </>\n          )}\n        </div>\n      </div>\n      <FooterBar>\n        <GameButton variant=\"primary\" block disabled={!canSubmit} onClick={handleSubmit}>\n          {submitting ? t.submitting : t.submit}\n        </GameButton>\n        <p className=\"ss-g-xi-lock\">\n          <IconLock />\n          {lockAtUtc ? t.locksAt(ui.games.formatDayTime(lockAtUtc)) : t.locksSoon}\n        </p>\n      </FooterBar>\n    </div>\n  )\n}\n","import { useId, useState } from 'react'\nimport type {\n  GameScreenProps,\n  StatLadderConfig,\n  StatLadderClientState,\n  StatLadderRung,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { GameButton } from './ui/GameButton'\nimport { PointsLadderRow } from './ui/PointsLadderRow'\nimport { SearchField } from './ui/SearchField'\nimport { FooterBar } from './ui/FooterBar'\nimport { Silhouette } from './ui/Silhouette'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconBulb, IconCheck, IconShield } from './ui/icons'\nimport { gameTitle, splitName } from './ui/gameMeta'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nexport interface LadderClue {\n  value: number\n  above: { name: string; diff: number } | null\n  below: { name: string; diff: number } | null\n}\n\n/** Pure: the mystery rung's value plus its gaps to the named rungs directly above (rank 1) and below (rank 3). */\nexport function ladderClue(ladder: StatLadderRung[]): LadderClue | null {\n  const mystery = ladder.find(r => r.rank === 2)\n  if (!mystery) return null\n  const above = ladder.find(r => r.rank === 1)\n  const below = ladder.find(r => r.rank === 3)\n  return {\n    value: mystery.statValue,\n    above: above?.playerName ? { name: above.playerName, diff: above.statValue - mystery.statValue } : null,\n    below: below?.playerName ? { name: below.playerName, diff: mystery.statValue - below.statValue } : null,\n  }\n}\n\nfunction parseClientState(json: string | null | undefined): StatLadderClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as StatLadderClientState\n  } catch {\n    return null\n  }\n}\n\nfunction NameStack({ name }: { name: string }): JSX.Element {\n  const { first, last } = splitName(name)\n  return (\n    <span className=\"ss-g-sl-name\">\n      {first && <small>{`${first[0]}.`}</small>}\n      <b>{last}</b>\n    </span>\n  )\n}\n\nexport function StatLadderGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<StatLadderConfig>): JSX.Element {\n  const t = ui.games.statLadder\n  const [query, setQuery] = useState('')\n  const [selectedId, setSelectedId] = useState<number | null>(null)\n  const searchId = useId()\n\n  const clientState = parseClientState(result?.clientStateJson)\n  const revealed = clientState != null\n\n  const header = (\n    <GameHeader title={gameTitle({ gameId: 'stat-ladder' }, ui.games.titles)} eyebrow={t.eyebrow} onBack={onBack} backLabel={ui.back} />\n  )\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"stat-ladder\" data-testid=\"game-screen-stat-ladder\">\n        {header}\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const question = t.question(config.statLabel)\n  const clue = revealed ? null : ladderClue(config.ladder)\n  const rungs = [...config.ladder].sort((a, b) => a.rank - b.rank)\n  const q = query.trim().toLowerCase()\n  const pool = q ? config.playerPool.filter(p => p.playerName.toLowerCase().includes(q)) : config.playerPool\n\n  function guess(): void {\n    if (selectedId === null || submitting || revealed) return\n    onSubmit(JSON.stringify({ guessedPlayerId: selectedId }))\n  }\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"stat-ladder\" data-testid=\"game-screen-stat-ladder\">\n      {header}\n      <div className=\"ss-g-body\">\n        {!revealed && <PointsLadderRow ladder={config.pointsLadder} guessesUsed={0} ui={ui} />}\n        <div className=\"ss-g-sl-prompt\">\n          <Chip variant=\"accent\" icon={<IconShield size={14} />} className=\"ss-g-sl-stat\">{config.statLabel}</Chip>\n          <h3 className=\"ss-g-sl-q\">\n            {question.pre}<em>{question.emph}</em>{question.post}\n          </h3>\n        </div>\n\n        <ol className=\"ss-g-sl-rungs\">\n          {rungs.map(rung =>\n            rung.rank === 2 ? (\n              <li\n                key={rung.rank}\n                className=\"ss-g-sl-rung ss-g-sl-rung--mystery\"\n                data-testid=\"sl-mystery-rung\"\n                data-result={revealed ? (clientState!.isCorrect ? 'correct' : 'wrong') : undefined}\n              >\n                <span className=\"ss-g-sl-rank\">2</span>\n                {revealed\n                  ? <PlayerAvatar name={clientState!.revealedRank2.playerName} className=\"ss-g-sl-av\" />\n                  : <Silhouette size={52} variant=\"mystery\" />}\n                {revealed\n                  ? <NameStack name={clientState!.revealedRank2.playerName} />\n                  : <span className=\"ss-g-sl-who\">{t.whoSecond}</span>}\n                <span className=\"ss-g-sl-val ss-g-sl-val--mystery\">{rung.statValue}</span>\n              </li>\n            ) : (\n              <li key={rung.rank} className=\"ss-g-sl-rung\">\n                <span className=\"ss-g-sl-rank\">{rung.rank}</span>\n                <PlayerAvatar name={rung.playerName ?? '?'} className=\"ss-g-sl-av\" />\n                <NameStack name={rung.playerName ?? '?'} />\n                <span className=\"ss-g-sl-val\">{rung.statValue}</span>\n              </li>\n            ),\n          )}\n        </ol>\n\n        {clue && (\n          <p className=\"ss-g-sl-clue\">\n            <IconBulb />\n            <span>{t.clue(clue, config.statLabel)}</span>\n          </p>\n        )}\n\n        {!revealed && (\n          <ul className=\"ss-g-sl-pool\">\n            {pool.map(p => (\n              <li key={p.playerId}>\n                <button\n                  type=\"button\"\n                  className=\"ss-g-sl-opt\"\n                  aria-label={p.playerName}\n                  aria-pressed={selectedId === p.playerId}\n                  disabled={submitting}\n                  onClick={() => { setSelectedId(p.playerId); setQuery(p.playerName) }}\n                >\n                  <PlayerAvatar name={p.playerName} className=\"ss-g-sl-opt-av\" />\n                  <span className=\"ss-g-sl-opt-name\">{p.playerName}</span>\n                  {selectedId === p.playerId && <IconCheck />}\n                </button>\n              </li>\n            ))}\n          </ul>\n        )}\n\n        {revealed && (\n          <ResultCard\n            tone={clientState!.isCorrect ? 'win' : 'lose'}\n            title={clientState!.isCorrect ? t.correct : t.wrong(clientState!.revealedRank2.playerName)}\n            score={result?.score}\n            onBack={onBack}\n            ui={ui}\n          />\n        )}\n      </div>\n\n      {!revealed && (\n        <FooterBar>\n          <div className=\"ss-g-sl-guess\">\n            <SearchField\n              id={searchId}\n              label={t.searchLabel}\n              labelHidden\n              placeholder={t.searchPlaceholder}\n              value={query}\n              onChange={v => { setQuery(v); setSelectedId(null) }}\n              disabled={submitting}\n            />\n            <GameButton variant=\"primary\" disabled={selectedId === null || submitting} onClick={guess}>\n              {t.guess}\n            </GameButton>\n          </div>\n        </FooterBar>\n      )}\n    </div>\n  )\n}\n","import type {\n  GameScreenProps,\n  FanMotmConfig,\n  FanMotmClientState,\n} from './types'\nimport { GameHeader } from './ui/GameHeader'\nimport { Chip } from './ui/Chip'\nimport { FooterBar } from './ui/FooterBar'\nimport { ResultCard } from './ui/ResultCard'\nimport { IconCheck } from './ui/icons'\nimport { PlayerAvatar } from './PlayerAvatar'\n\nfunction parseClientState(json: string | null | undefined): FanMotmClientState | null {\n  if (!json) return null\n  try {\n    return JSON.parse(json) as FanMotmClientState\n  } catch {\n    return null\n  }\n}\n\nexport function FanMotmGame({\n  config,\n  result,\n  submitting,\n  onSubmit,\n  ui,\n  onBack,\n}: GameScreenProps<FanMotmConfig>): JSX.Element {\n  const t = ui.games.motm\n  const clientState = parseClientState(result?.clientStateJson)\n  const alreadyVoted = result?.alreadyPlayed === true\n  const pickedId = clientState?.pickedPlayerId ?? null\n\n  const header = (\n    <GameHeader\n      title={t.title}\n      eyebrow={t.eyebrow}\n      right={alreadyVoted ? <Chip variant=\"success\" icon={<IconCheck />}>{t.voted}</Chip> : undefined}\n      onBack={onBack}\n      backLabel={ui.back}\n    />\n  )\n\n  if (!config) {\n    return (\n      <div className=\"ss-g-screen\" data-game=\"fan-motm\" data-testid=\"game-screen-fan-motm\">\n        {header}\n        <div className=\"ss-g-body ss-g-loading\">{ui.games.loading}</div>\n      </div>\n    )\n  }\n\n  const picked = config.candidates.find(c => c.playerId === pickedId) ?? null\n\n  function handleVote(candidateId: number): void {\n    if (alreadyVoted || submitting) return\n    onSubmit(JSON.stringify({ pickedPlayerId: candidateId }))\n  }\n\n  return (\n    <div className=\"ss-g-screen\" data-game=\"fan-motm\" data-testid=\"game-screen-fan-motm\">\n      {header}\n      <div className=\"ss-g-body\">\n        <ul className=\"ss-g-motm-list\">\n          {config.candidates.map(c => {\n            const isVoted = alreadyVoted && pickedId === c.playerId\n            return (\n              <li key={c.playerId}>\n                <button\n                  type=\"button\"\n                  className={`ss-g-motm-row${isVoted ? ' ss-g-motm-row--voted' : ''}`}\n                  data-testid={`motm-candidate-${c.playerId}`}\n                  disabled={alreadyVoted || submitting}\n                  onClick={() => handleVote(c.playerId)}\n                >\n                  <PlayerAvatar name={c.playerName} className=\"ss-g-motm-av\" />\n                  <span className=\"ss-g-motm-name\">{c.playerName}</span>\n                  {isVoted && <Chip variant=\"accent\" className=\"ss-g-motm-pill\">{t.yourVote}</Chip>}\n                </button>\n              </li>\n            )\n          })}\n        </ul>\n        {alreadyVoted && picked && (\n          <ResultCard tone=\"neutral\" title={t.youVoted(picked.playerName)} detail={t.thanks} onBack={onBack} ui={ui} />\n        )}\n      </div>\n      <FooterBar>\n        {!alreadyVoted && <p className=\"ss-g-motm-foot\">{t.tapToVote}</p>}\n        <p className=\"ss-g-motm-fun\">{t.forFun}</p>\n      </FooterBar>\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { LeaderboardWeeklyRow, LeaderboardAllTimeRow, formatPoints } from './LeaderboardRow'\nimport { LeaderboardEmpty } from './LeaderboardEmpty'\n\ntype Segment = 'weekly' | 'alltime'\n\nexport function Leaderboard({\n  data,\n  ui,\n  onPlay,\n}: {\n  data: LeaderboardPayload\n  ui: UiConfig\n  /** Jumps to the Games tab from the empty-state CTA. */\n  onPlay?: () => void\n}): JSX.Element {\n  const [segment, setSegment] = useState<Segment>('weekly')\n\n  const myRow = segment === 'weekly' ? data.myWeeklyRow : data.myAllTimeRow\n  const offBoard = myRow !== null && myRow !== undefined && myRow.rank === -1\n  const isEmpty = segment === 'weekly'\n    ? data.weeklyTop.length === 0\n    : data.allTimeTop.length === 0\n\n  return (\n    <div className=\"ss-w-lb2\">\n      <div className=\"ss-w-seg\">\n        <button\n          type=\"button\"\n          className=\"ss-w-seg-btn\"\n          {...(segment === 'weekly' ? { 'data-on': '' } : {})}\n          onClick={() => setSegment('weekly')}\n        >\n          {ui.leaderboardThisWeek}\n        </button>\n        <button\n          type=\"button\"\n          className=\"ss-w-seg-btn\"\n          {...(segment === 'alltime' ? { 'data-on': '' } : {})}\n          onClick={() => setSegment('alltime')}\n        >\n          {ui.leaderboardAllTime}\n        </button>\n      </div>\n\n      {isEmpty ? (\n        <LeaderboardEmpty\n          segment={segment}\n          lastWeek={data.lastWeek}\n          weeklyPrize={data.weeklyPrize}\n          onPlay={onPlay}\n          ui={ui}\n        />\n      ) : (\n        <>\n          <div className=\"ss-w-lb2-rows\">\n            {segment === 'weekly'\n              ? data.weeklyTop.map((row) => (\n                  <LeaderboardWeeklyRow\n                    key={row.operatorUserId}\n                    row={row}\n                    isMe={row.operatorUserId === data.myWeeklyRow?.operatorUserId}\n                  />\n                ))\n              : data.allTimeTop.map((row) => (\n                  <LeaderboardAllTimeRow\n                    key={row.operatorUserId}\n                    row={row}\n                    isMe={row.operatorUserId === data.myAllTimeRow?.operatorUserId}\n                  />\n                ))}\n          </div>\n\n          {/* Kit-prize separator */}\n          <div className=\"ss-w-kitline\">🎽</div>\n\n          {/* Pinned \"you\" row or off-board treatment */}\n          {myRow != null && (\n            offBoard ? (\n              <div className=\"ss-w-lbgap\">{ui.leaderboardOffBoard}</div>\n            ) : (\n              <div className=\"ss-w-lb2-rows\">\n                {segment === 'weekly' && data.myWeeklyRow && (\n                  <LeaderboardWeeklyRow row={data.myWeeklyRow} isMe />\n                )}\n                {segment === 'alltime' && data.myAllTimeRow && (\n                  <LeaderboardAllTimeRow row={data.myAllTimeRow} isMe />\n                )}\n              </div>\n            )\n          )}\n\n          {/* All-time footer: show rank + total when available */}\n          {segment === 'alltime' && data.myAllTimeRow && !offBoard && (\n            <div className=\"ss-w-lb2-rows\">\n              <div className=\"ss-w-lb2-row\">\n                <span className=\"ss-w-lb2-handle\">\n                  {formatPoints(data.allTimeTop.reduce((s, r) => s + r.allTimePoints, 0))}\n                </span>\n              </div>\n            </div>\n          )}\n        </>\n      )}\n    </div>\n  )\n}\n","import type { LeaderboardRow as SDKRow, AllTimeRow } from '@sensiblestats/widget-sdk'\n\n/** Formats a points integer with thousands separators. */\nexport function formatPoints(n: number): string {\n  return n.toLocaleString('en')\n}\n\nexport function LeaderboardWeeklyRow({\n  row,\n  isMe,\n}: {\n  row: SDKRow\n  isMe: boolean\n}): JSX.Element {\n  const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n  return (\n    <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n      <span className={rankClass}>#{row.rank}</span>\n      <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n      <span className=\"ss-w-lb2-points\">{formatPoints(row.points)}</span>\n      {row.currentStreak > 0 && (\n        <span className=\"ss-w-lb2-streak\">🔥 {row.currentStreak}</span>\n      )}\n    </div>\n  )\n}\n\nexport function LeaderboardAllTimeRow({\n  row,\n  isMe,\n}: {\n  row: AllTimeRow\n  isMe: boolean\n}): JSX.Element {\n  const rankClass = `ss-w-lb2-rank${row.rank <= 3 ? ' ss-w-lb2-rank--top3' : ''}`\n  return (\n    <div className={`ss-w-lb2-row${isMe ? ' ss-w-lb2-row--you' : ''}`}>\n      <span className={rankClass}>#{row.rank}</span>\n      <span className=\"ss-w-lb2-handle\">{row.handle}</span>\n      <span className=\"ss-w-lb2-points\">{formatPoints(row.allTimePoints)}</span>\n    </div>\n  )\n}\n","import type { LeaderboardChampion } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { formatPoints } from './LeaderboardRow'\n\ntype Segment = 'weekly' | 'alltime'\n\n/**\n * Default state for the leaderboard when the active segment has no ranked rows.\n * Weekly boards reset every week, so this is what most fans see at the start of a week.\n *  - weekly + a prior champion  -> \"fresh week\" copy plus a last-week continuity strip\n *  - weekly + no history        -> \"cold start\" copy (club's first-ever week)\n *  - all-time                   -> a quiet single line; it fills as fans play\n */\nexport function LeaderboardEmpty({\n  segment,\n  lastWeek,\n  weeklyPrize,\n  onPlay,\n  ui,\n}: {\n  segment: Segment\n  lastWeek?: LeaderboardChampion | null\n  weeklyPrize?: string | null\n  onPlay?: () => void\n  ui: UiConfig\n}): JSX.Element {\n  if (segment === 'alltime') {\n    return (\n      <div className=\"ss-w-lb-empty ss-w-lb-empty--alltime\">\n        <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">📊</div>\n        <p className=\"ss-w-lb-empty-body\">{ui.leaderboardAllTimeEmpty}</p>\n      </div>\n    )\n  }\n\n  const fresh = lastWeek != null\n  const title = fresh ? ui.leaderboardEmptyFreshTitle : ui.leaderboardEmptyColdTitle\n  const body = fresh ? ui.leaderboardEmptyFreshBody : ui.leaderboardEmptyColdBody\n\n  return (\n    <div className=\"ss-w-lb-empty\">\n      {weeklyPrize && (\n        <div className=\"ss-w-prize\">\n          <span className=\"ss-w-prize-icon\" aria-hidden=\"true\">🏆</span>\n          <div className=\"ss-w-prize-body\">\n            <span className=\"ss-w-prize-text\">{weeklyPrize}</span>\n          </div>\n        </div>\n      )}\n\n      <div className=\"ss-w-lb-empty-hero\">\n        <div className=\"ss-w-lb-empty-icon\" aria-hidden=\"true\">{fresh ? '🏆' : '🎮'}</div>\n        <h4 className=\"ss-w-lb-empty-title\">{title}</h4>\n        <p className=\"ss-w-lb-empty-body\">{body}</p>\n        {onPlay && (\n          <button type=\"button\" className=\"ss-w-lb-empty-cta\" onClick={onPlay}>\n            {ui.leaderboardEmptyCta}\n          </button>\n        )}\n      </div>\n\n      {fresh && lastWeek && (\n        <div className=\"ss-w-lb-last\">\n          <span className=\"ss-w-lb-last-label\">{ui.leaderboardLastWeekLabel}</span>\n          <span className=\"ss-w-lb-last-champ\" aria-hidden=\"true\">🥇</span>\n          <span className=\"ss-w-lb-last-handle\">{lastWeek.handle}</span>\n          <span className=\"ss-w-lb-last-points\">{formatPoints(lastWeek.points)}</span>\n        </div>\n      )}\n    </div>\n  )\n}\n","import type { LeaderboardPayload } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { GamesLoginWall } from './GamesLoginWall'\nimport { Leaderboard } from './Leaderboard'\n\n/** Settled empty board (no rows yet) — a fetch that returned null once loading is done. */\nconst EMPTY_PAYLOAD: LeaderboardPayload = {\n  week: '',\n  weeklyTop: [],\n  myWeeklyRow: null,\n  allTimeTop: [],\n  myAllTimeRow: null,\n  weeklyPrize: null,\n  lastWeek: null,\n}\n\nexport function LeaderboardPanel({ loggedIn, data, loading, onPlay, ui }: {\n  loggedIn: boolean\n  data: LeaderboardPayload | null\n  loading?: boolean\n  onPlay?: () => void\n  ui: UiConfig\n}): JSX.Element {\n  if (!loggedIn) return <GamesLoginWall ui={ui} />\n  // Still fetching with nothing to show yet: keep the panel blank (skeleton-free).\n  if (data === null && loading) return <div className=\"ss-w-mon-list\" />\n  return (\n    <div className=\"ss-w-mon-list\">\n      <Leaderboard data={data ?? EMPTY_PAYLOAD} ui={ui} onPlay={onPlay} />\n    </div>\n  )\n}\n","const FONTS_LINK_ID = 'ss-w-games-fonts'\nconst FONTS_HREF =\n  'https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@600;700;800&family=Barlow:wght@400;500;600;700&display=swap'\n\n// Registered at document level: @font-face inside a shadow root is ignored by browsers, but\n// document fonts resolve inside the embed's shadow tree. If CSP blocks it the fallback stack renders.\nexport function ensureGamesFonts(doc: Document = document): void {\n  if (!doc.head) return\n  if (doc.getElementById(FONTS_LINK_ID)) return\n  const link = doc.createElement('link')\n  link.id = FONTS_LINK_ID\n  link.rel = 'stylesheet'\n  link.href = FONTS_HREF\n  doc.head.appendChild(link)\n}\n","import type { ClubFixture } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\n\nfunction groupByRound(fixtures: ClubFixture[]): { round: string | null; items: ClubFixture[] }[] {\n  const groups: { round: string | null; items: ClubFixture[] }[] = []\n  for (const fx of fixtures) {\n    const last = groups[groups.length - 1]\n    if (last && last.round === fx.round) last.items.push(fx)\n    else groups.push({ round: fx.round, items: [fx] })\n  }\n  return groups\n}\n\nexport function Fixtures({ fixtures, loading, ui }: {\n  fixtures: ClubFixture[]\n  loading: boolean\n  ui: UiConfig\n}): JSX.Element {\n  if (fixtures.length === 0) {\n    // First fetch still in flight: stay blank rather than flashing the empty message.\n    if (loading) return <div className=\"ss-w-mon-list\" />\n    return <div className=\"ss-w-mon-empty\">{ui.clubFixturesEmpty}</div>\n  }\n\n  return (\n    <div className=\"ss-w-mon-list\">\n      {groupByRound(fixtures).map((group, gi) => (\n        <div key={`${gi}-${group.round ?? 'none'}`}>\n          {group.round && <div className=\"ss-w-club-eyebrow\">{group.round}</div>}\n          {group.items.map((fx) => {\n            const played = fx.homeScore !== null && fx.awayScore !== null\n            const kickoff = fx.matchDateTime ? ui.bettingKickoff(fx.matchDateTime) : null\n            return (\n              <div className=\"ss-w-mon\" key={fx.id}>\n                <div className=\"ss-w-mon-top\">\n                  {fx.competitionName && <span className=\"ss-w-mon-comp\">{fx.competitionName}</span>}\n                  {!played && kickoff && <span className=\"ss-w-mon-pill\">{kickoff.dayLabel} · {kickoff.time}</span>}\n                </div>\n                <div className=\"ss-w-mon-main\">\n                  <span className=\"ss-w-mon-side\">\n                    <span className=\"ss-w-mon-name\">{fx.homeTeamName}</span>\n                  </span>\n                  {played ? (\n                    <span className=\"ss-w-mon-score\">{fx.homeScore}<i>-</i>{fx.awayScore}</span>\n                  ) : (\n                    <span className=\"ss-w-mon-vs\">vs</span>\n                  )}\n                  <span className=\"ss-w-mon-side ss-w-mon-side--away\">\n                    <span className=\"ss-w-mon-name\">{fx.awayTeamName}</span>\n                  </span>\n                </div>\n              </div>\n            )\n          })}\n        </div>\n      ))}\n    </div>\n  )\n}\n","import type { ClubStandingRow } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\n\nfunction groupByTable(rows: ClubStandingRow[]): { table: string | null; items: ClubStandingRow[] }[] {\n  const groups: { table: string | null; items: ClubStandingRow[] }[] = []\n  for (const row of rows) {\n    const last = groups[groups.length - 1]\n    if (last && last.table === row.table) last.items.push(row)\n    else groups.push({ table: row.table, items: [row] })\n  }\n  return groups\n}\n\nexport function Standings({ standings, loading, ui }: {\n  standings: ClubStandingRow[] | null\n  loading: boolean\n  ui: UiConfig\n}): JSX.Element {\n  // First fetch still in flight: stay blank rather than flashing the empty message.\n  if (standings === null && loading) return <div className=\"ss-w-mon-list\" />\n  if (standings === null || standings.length === 0) return <div className=\"ss-w-mon-empty\">{ui.clubStandingsEmpty}</div>\n\n  return (\n    <div className=\"ss-w-mon-list\">\n      {groupByTable(standings).map((group, gi) => (\n        <div className=\"ss-w-table-wrap\" key={`${gi}-${group.table ?? 'none'}`}>\n          {group.table && <div className=\"ss-w-club-eyebrow\">{group.table}</div>}\n          <table className=\"ss-w-md-table\">\n            <thead>\n              <tr>\n                <th>#</th>\n                <th>{ui.standingsColClub}</th>\n                <th>{ui.standingsColPlayed}</th>\n                <th>{ui.standingsColWon}</th>\n                <th>{ui.standingsColDrawn}</th>\n                <th>{ui.standingsColLost}</th>\n                <th>{ui.standingsColGoalDiff}</th>\n                <th>{ui.standingsColPoints}</th>\n              </tr>\n            </thead>\n            <tbody>\n              {group.items.map((row) => (\n                <tr key={row.teamId}>\n                  <td>{row.position}</td>\n                  <td>{row.teamName}</td>\n                  <td>{row.playedGames}</td>\n                  <td>{row.wins}</td>\n                  <td>{row.draws}</td>\n                  <td>{row.losses}</td>\n                  <td>{row.goalDifference}</td>\n                  <td>{row.points}</td>\n                </tr>\n              ))}\n            </tbody>\n          </table>\n        </div>\n      ))}\n    </div>\n  )\n}\n","export function groupByPosition<T extends { positionName: string | null }>(players: T[]): { positionName: string | null; items: T[] }[] {\n  const groups: { positionName: string | null; items: T[] }[] = []\n  for (const p of players) {\n    const last = groups[groups.length - 1]\n    if (last && last.positionName === p.positionName) last.items.push(p)\n    else groups.push({ positionName: p.positionName, items: [p] })\n  }\n  return groups\n}\n","import type { UiConfig } from '../config'\n\nexport function positionLabel(ui: UiConfig, name: string | null): string | null {\n  switch (name) {\n    case 'Goalkeeper': return ui.positionGoalkeeper\n    case 'Defender': return ui.positionDefender\n    case 'Midfielder': return ui.positionMidfielder\n    case 'Attacker': return ui.positionAttacker\n    default: return name\n  }\n}\n\nexport function footLabel(ui: UiConfig, foot: string | null): string | null {\n  const v = foot?.trim() ?? ''\n  if (v === '' || v.toUpperCase() === 'N/A') return null\n  switch (v.toLowerCase()) {\n    case 'right': return ui.footRight\n    case 'left': return ui.footLeft\n    case 'both': return ui.footBoth\n    default: return v\n  }\n}\n\nconst GROUP_CODE: Record<string, string> = { Goalkeeper: 'GK', Defender: 'DF', Midfielder: 'MF', Attacker: 'FW' }\n\nexport function positionShort(code: string | null | undefined, positionName: string | null): string {\n  const c = code?.trim().toUpperCase() ?? ''\n  if (c !== '') return c === 'CF' || c === 'SS' ? 'ST' : c\n  return (positionName !== null && GROUP_CODE[positionName]) || '–'\n}\n\nexport function statsEyebrow(ui: UiConfig, season: string | null, competition: string | null, matches: number | null): string | null {\n  if (season === null || competition === null || matches === null || matches <= 0) return null\n  return ui.squadStatsEyebrow(season, competition, matches)\n}\n","import type { ClubPlayerSeasonStats } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { positionShort } from './labels'\n\nfunction leader(stats: ClubPlayerSeasonStats[], pick: (p: ClubPlayerSeasonStats) => number): ClubPlayerSeasonStats | null {\n  let best: ClubPlayerSeasonStats | null = null\n  for (const p of stats) {\n    if (pick(p) <= 0) continue\n    if (best === null || pick(p) > pick(best) || (pick(p) === pick(best) && p.minutesPlayed < best.minutesPlayed)) best = p\n  }\n  return best\n}\n\nfunction ratingClass(rating: number | null): string {\n  if (rating === null) return 'ss-w-sq-c36 ss-w-sq-rtg-none'\n  return Number(rating.toFixed(1)) >= 7 ? 'ss-w-sq-c36 ss-w-sq-rtg ss-w-pos-ink' : 'ss-w-sq-c36 ss-w-sq-rtg'\n}\n\nexport function SquadStats({ stats, loading, ui, onSelectPlayer }: {\n  stats: ClubPlayerSeasonStats[] | null\n  loading: boolean\n  ui: UiConfig\n  onSelectPlayer: (playerId: number) => void\n}): JSX.Element {\n  if (stats === null && loading) return <div className=\"ss-w-mon-list\" />\n  if (stats === null || stats.length === 0) return <div className=\"ss-w-mon-empty\">{ui.clubSquadStatsEmpty}</div>\n\n  const scorer = leader(stats, (p) => p.goals)\n  const assister = leader(stats, (p) => p.assists)\n  const footer = [\n    scorer && ui.squadTopScorer(scorer.playerName, scorer.goals),\n    assister && ui.squadTopAssists(assister.playerName, assister.assists),\n  ].filter((part): part is string => !!part).join(' · ')\n\n  return (\n    <div className=\"ss-w-mon-list ss-w-sq-stats\">\n      <div className=\"ss-w-sq-card\">\n      <div className=\"ss-w-sq-row ss-w-sq-head\" aria-hidden=\"true\">\n        <span className=\"ss-w-sq-name\" />\n        <span className=\"ss-w-sq-pos\">{ui.statHeadPos}</span>\n        <span className=\"ss-w-sq-c30\">{ui.statColApps}</span>\n        <span className=\"ss-w-sq-c36\">{ui.statHeadMins}</span>\n        <span className=\"ss-w-sq-c20\">{ui.statHeadGoals}</span>\n        <span className=\"ss-w-sq-c20\">{ui.statHeadAssists}</span>\n        <span className=\"ss-w-sq-c20 ss-w-sq-yr\">{ui.statHeadYellow}</span>\n        <span className=\"ss-w-sq-c20 ss-w-sq-yr\">{ui.statHeadRed}</span>\n        <span className=\"ss-w-sq-c36\">{ui.statHeadRating}</span>\n      </div>\n      {stats.map((p) => (\n        <button type=\"button\" className=\"ss-w-sq-row ss-w-sq-tap\" key={p.playerId} onClick={() => onSelectPlayer(p.playerId)}>\n          <span className=\"ss-w-sq-player\">\n            {p.jerseyNumber !== null && <span className=\"ss-w-sq-badge\">{p.jerseyNumber}</span>}\n            <span className=\"ss-w-sq-name ss-w-sq-name-1\">{p.playerName}</span>\n          </span>\n          <span className=\"ss-w-sq-pos\">{positionShort(p.positionCode, p.positionName)}</span>\n          <span className=\"ss-w-sq-c30\">{p.appearances}</span>\n          <span className=\"ss-w-sq-c36\">{p.minutesPlayed}</span>\n          <span className=\"ss-w-sq-c20\">{p.goals}</span>\n          <span className=\"ss-w-sq-c20\">{p.assists}</span>\n          <span className=\"ss-w-sq-c20 ss-w-sq-yr\">{p.yellowCards}</span>\n          <span className=\"ss-w-sq-c20 ss-w-sq-yr\">{p.redCards}</span>\n          <span className={ratingClass(p.averageRating)}>\n            {p.averageRating === null ? '–' : p.averageRating.toFixed(1)}\n          </span>\n        </button>\n      ))}\n      </div>\n      {footer !== '' && <div className=\"ss-w-sq-foot\">{footer}</div>}\n    </div>\n  )\n}\n","import type { ClubPlayerSeasonStats, ClubSquadPlayer } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { groupByPosition } from './groupByPosition'\nimport { positionLabel, statsEyebrow } from './labels'\nimport { SquadStats } from './SquadStats'\n\nexport function Squad({ squad, loading, ui, view, onToggleView, stats, statsLoading, seasonName = null, competitionName = null, matchesPlayed = null, onSelectPlayer }: {\n  squad: ClubSquadPlayer[] | null\n  loading: boolean\n  ui: UiConfig\n  view: 'roster' | 'stats'\n  onToggleView: () => void\n  stats: ClubPlayerSeasonStats[] | null\n  statsLoading: boolean\n  seasonName?: string | null\n  competitionName?: string | null\n  matchesPlayed?: number | null\n  onSelectPlayer: (playerId: number) => void\n}): JSX.Element {\n  const eyebrow = view === 'stats' ? statsEyebrow(ui, seasonName, competitionName, matchesPlayed) : null\n  const toggle = (\n    <div className=\"ss-w-sq-bar\">\n      {eyebrow !== null && <div className=\"ss-w-sq-eyebrow\">{eyebrow}</div>}\n    <div className=\"ss-w-sq-seg\" role=\"group\">\n      {(['roster', 'stats'] as const).map((v) => (\n        <button\n          key={v}\n          type=\"button\"\n          className=\"ss-w-sq-seg-btn\"\n          aria-pressed={view === v}\n          onClick={() => { if (view !== v) onToggleView() }}\n        >\n          {v === 'roster' ? ui.squadViewRoster : ui.squadViewStats}\n        </button>\n      ))}\n    </div>\n    </div>\n  )\n\n  if (view === 'stats') {\n    return (\n      <>\n        {toggle}\n        <SquadStats stats={stats} loading={statsLoading} ui={ui} onSelectPlayer={onSelectPlayer} />\n      </>\n    )\n  }\n\n  // First fetch still in flight: stay blank rather than flashing the empty message.\n  if (squad === null && loading) return <>{toggle}<div className=\"ss-w-mon-list\" /></>\n  if (squad === null || squad.length === 0) return <>{toggle}<div className=\"ss-w-mon-empty\">{ui.clubSquadEmpty}</div></>\n\n  return (\n    <>\n      {toggle}\n      <div className=\"ss-w-mon-list\">\n        {groupByPosition(squad).map((group, gi) => (\n          <div key={`${gi}-${group.positionName ?? 'none'}`}>\n            {group.positionName && <div className=\"ss-w-club-eyebrow\">{positionLabel(ui, group.positionName)}</div>}\n            {group.items.map((p) => (\n              <button type=\"button\" className=\"ss-w-sq-row ss-w-sq-tap\" key={p.playerId} onClick={() => onSelectPlayer(p.playerId)}>\n                <span className=\"ss-w-sq-num\">{p.jerseyNumber ?? ''}</span>\n                <span className=\"ss-w-sq-name\">{p.playerName}</span>\n              </button>\n            ))}\n          </div>\n        ))}\n      </div>\n    </>\n  )\n}\n","import { useState } from 'react'\n\nexport function PlayerPhoto({ photoUrl, jerseyNumber, size }: {\n  photoUrl: string | null | undefined\n  jerseyNumber: number | null\n  size: number\n}): JSX.Element {\n  const [failed, setFailed] = useState(false)\n  const box = { width: size, height: size }\n  if (photoUrl && !failed) {\n    return <img className=\"ss-w-pd-photo\" style={box} src={photoUrl} alt=\"\" aria-hidden=\"true\" onError={() => setFailed(true)} />\n  }\n  return (\n    <span className=\"ss-w-pd-photo ss-w-pd-avatar\" style={{ ...box, fontSize: Math.round(size * 0.35) }} aria-hidden=\"true\">\n      {jerseyNumber ?? ''}\n    </span>\n  )\n}\n","const SPOT: Record<string, readonly [number, number]> = {\n  GK: [50, 90],\n  CB: [50, 75],\n  LB: [18, 70],\n  RB: [82, 70],\n  LWB: [15, 58],\n  RWB: [85, 58],\n  DM: [50, 60],\n  CM: [50, 48],\n  LM: [18, 45],\n  RM: [82, 45],\n  AM: [50, 32],\n  LW: [20, 25],\n  RW: [80, 25],\n  CF: [50, 14],\n  SS: [50, 14],\n  ST: [50, 14],\n}\n\nexport function MiniPitch({ positionCode }: { positionCode: string | null | undefined }): JSX.Element | null {\n  const spot = SPOT[positionCode?.trim().toUpperCase() ?? '']\n  if (spot === undefined) return null\n  return (\n    <div className=\"ss-w-pd-pitch\" aria-hidden=\"true\">\n      <div className=\"ss-w-pd-pitch-dot\" style={{ left: `${spot[0]}%`, top: `${spot[1]}%` }} />\n    </div>\n  )\n}\n","import { useState } from 'react'\nimport type { ClubPerformanceMetric, ClubPlayerPerformance } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\n\ntype Mode = 'total' | 'per90'\ntype Group = ClubPerformanceMetric['group']\n\nconst GROUPS: readonly Group[] = ['shooting', 'passing', 'possession', 'defending']\n\nfunction finite(v: number | null | undefined): number | null {\n  return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n\nfunction valueOf(m: ClubPerformanceMetric, mode: Mode): number | null {\n  return finite(mode === 'total' ? m.total : m.per90)\n}\n\nfunction rankOf(m: ClubPerformanceMetric, mode: Mode): number | null {\n  const r = finite(mode === 'total' ? m.totalRank : m.per90Rank)\n  return r === null ? null : Math.min(100, Math.max(0, Math.round(r)))\n}\n\nfunction format(m: ClubPerformanceMetric, v: number, mode: Mode): string {\n  if (m.isPercent) return `${v.toFixed(1)}%`\n  if (mode === 'per90' || m.key === 'xg') return v.toFixed(2)\n  return String(Math.round(v))\n}\n\nfunction band(rank: number): 'pos' | 'warn' | 'neg' {\n  if (rank >= 67) return 'pos'\n  if (rank >= 34) return 'warn'\n  return 'neg'\n}\n\nfunction groupTitle(ui: UiConfig, g: Group): string {\n  switch (g) {\n    case 'shooting': return ui.perfGroupShooting\n    case 'passing': return ui.perfGroupPassing\n    case 'possession': return ui.perfGroupPossession\n    case 'defending': return ui.perfGroupDefending\n  }\n}\n\nfunction unrankedLine(ui: UiConfig, reason: ClubPlayerPerformance['unrankedReason']): string {\n  switch (reason) {\n    case 'cohort': return ui.perfUnrankedCohort\n    case 'noLeague': return ui.perfUnrankedNoLeague\n    default: return ui.perfUnranked\n  }\n}\n\nexport function PerformanceBars({ performance, competitionName, strings }: {\n  performance: ClubPlayerPerformance\n  competitionName: string | null\n  strings: UiConfig\n}): JSX.Element | null {\n  const [mode, setMode] = useState<Mode>('total')\n  const labelled = performance.metrics.filter((m) => Object.prototype.hasOwnProperty.call(strings.perfMetric, m.key))\n  if (!labelled.some((m) => valueOf(m, 'total') !== null || valueOf(m, 'per90') !== null)) return null\n\n  const subtitle = !performance.ranked\n    ? unrankedLine(strings, performance.unrankedReason)\n    : competitionName\n      ? strings.perfRankedAgainst(competitionName, performance.positionGroup)\n      : null\n\n  const cards = GROUPS.map((g) => {\n    const rows = labelled.filter((m) => m.group === g && valueOf(m, mode) !== null)\n    if (rows.length === 0) return null\n    return (\n      <div key={g} className=\"ss-w-pd-card ss-w-pd-perf-card\">\n        <div className=\"ss-w-pd-perf-group\">{groupTitle(strings, g)}</div>\n        {rows.map((m) => {\n          const v = valueOf(m, mode) as number\n          const rank = performance.ranked ? rankOf(m, mode) : null\n          return (\n            <div key={m.key} className=\"ss-w-pd-bar-row\">\n              <div className=\"ss-w-pd-bar-top\">\n                <span className=\"ss-w-pd-bar-label\">{strings.perfMetric[m.key]}</span>\n                <span className=\"ss-w-pd-bar-value\">{format(m, v, mode)}</span>\n              </div>\n              {rank !== null && (\n                <div className=\"ss-w-pd-track\">\n                  <div className={`ss-w-pd-fill ss-w-pd-fill--${band(rank)}`} style={{ width: `${rank}%` }} />\n                </div>\n              )}\n            </div>\n          )\n        })}\n      </div>\n    )\n  })\n\n  return (\n    <div>\n      <div className=\"ss-w-pd-perf-head\">\n        <div className=\"ss-w-pd-eyebrow\">{strings.perfTitle}</div>\n        <div className=\"ss-w-pd-seg\" role=\"group\">\n          {(['total', 'per90'] as const).map((m) => (\n            <button key={m} type=\"button\" className=\"ss-w-pd-seg-btn\" aria-pressed={mode === m} onClick={() => setMode(m)}>\n              {m === 'total' ? strings.perfTotal : strings.perfPer90}\n            </button>\n          ))}\n        </div>\n      </div>\n      {subtitle !== null && <div className=\"ss-w-pd-perf-sub\">{subtitle}</div>}\n      <div className=\"ss-w-pd-perf-cards\">{cards}</div>\n    </div>\n  )\n}\n","import type { ClubMatchLogRow, ClubPlayerAvailability, ClubPlayerDetailPayload, ClubNextFixture } from '@sensiblestats/widget-sdk'\nimport type { UiConfig } from '../config'\nimport { footLabel, positionLabel } from './labels'\nimport { PlayerPhoto } from './PlayerPhoto'\nimport { MiniPitch } from './MiniPitch'\nimport { PerformanceBars } from './PerformanceBars'\n\nconst DASH = '—'\n\nfunction ageFrom(dobMs: number | null): string {\n  if (dobMs === null) return DASH\n  const dob = new Date(dobMs)\n  const now = new Date()\n  let age = now.getUTCFullYear() - dob.getUTCFullYear()\n  const beforeBirthday =\n    now.getUTCMonth() < dob.getUTCMonth() ||\n    (now.getUTCMonth() === dob.getUTCMonth() && now.getUTCDate() < dob.getUTCDate())\n  if (beforeBirthday) age--\n  return String(age)\n}\n\nfunction validMs(ms: number | null | undefined): number | null {\n  return typeof ms === 'number' && Number.isFinite(ms) && ms > 0 ? ms : null\n}\n\nfunction ratingTone(rounded: number): 'pos' | 'warn' | 'neg' {\n  if (rounded >= 7) return 'pos'\n  if (rounded >= 6) return 'warn'\n  return 'neg'\n}\n\nfunction Bio({ label, value }: { label: string; value: string }): JSX.Element {\n  return (\n    <div className=\"ss-w-pd-bio-item\">\n      <span className=\"ss-w-pd-faint\">{label}</span> <span>{value}</span>\n    </div>\n  )\n}\n\nfunction Tile({ label, value, pos }: { label: string; value: string; pos?: boolean }): JSX.Element {\n  return (\n    <div className=\"ss-w-pd-tile\">\n      <div className=\"ss-w-pd-tile-label\">{label}</div>\n      <div className={pos ? 'ss-w-pd-tile-value ss-w-pd-pos-ink' : 'ss-w-pd-tile-value'}>{value}</div>\n    </div>\n  )\n}\n\nfunction AvailabilityCard({ ui, next, availability }: {\n  ui: UiConfig\n  next: ClubNextFixture | null\n  availability: ClubPlayerAvailability | null\n}): JSX.Element {\n  let note: string | null = null\n  let pill: { text: string; tone: 'pos' | 'warn' | 'neg' } | null = null\n  if (availability !== null) {\n    if (availability.status === 'available') {\n      note = ui.availabilityNoConcerns\n      pill = { text: ui.availabilityAvailable, tone: 'pos' }\n    } else {\n      const back = validMs(availability.expectedReturnUnixMs)\n      note = [availability.detail?.trim() || null, back === null ? null : ui.availabilityBack(back)].filter(Boolean).join(' · ') || null\n      pill = availability.status === 'injured'\n        ? { text: ui.availabilityInjured, tone: 'neg' }\n        : availability.status === 'suspended'\n          ? { text: ui.availabilitySuspended, tone: 'warn' }\n          : { text: ui.availabilityUnavailable, tone: 'warn' }\n    }\n  }\n  return (\n    <div className=\"ss-w-pd-card ss-w-pd-avail\">\n      <div className=\"ss-w-pd-avail-text\">\n        {next !== null && <div className=\"ss-w-pd-avail-next\">{ui.availabilityNext(next.opponentName, next.isHome, validMs(next.kickoffUnixMs))}</div>}\n        {note !== null && <div className=\"ss-w-pd-avail-note\">{note}</div>}\n      </div>\n      {pill !== null && <div className={`ss-w-pd-pill ss-w-pd-pill--${pill.tone}`}>{pill.text}</div>}\n    </div>\n  )\n}\n\nfunction MatchRow({ ui, row }: { ui: UiConfig; row: ClubMatchLogRow }): JSX.Element {\n  const date = validMs(row.kickoffUnixMs)\n  const extras = [\n    row.goals > 0 ? `${row.goals}${ui.statHeadGoals}` : null,\n    row.assists > 0 ? `${row.assists}${ui.statHeadAssists}` : null,\n    row.yellowCards > 0 ? `${row.yellowCards}${ui.statHeadYellow}` : null,\n    row.sentOff ? ui.statHeadRed : null,\n  ].filter((x): x is string => x !== null)\n  const sub = [`${ui.resultLetter[row.result]} ${row.goalsFor}–${row.goalsAgainst}`, `${row.minutes}′`, ...extras].join(' · ')\n  const rating = typeof row.rating === 'number' && Number.isFinite(row.rating) ? Math.round(row.rating * 10) / 10 : null\n  const pillTone = row.result === 'W' ? 'pos' : row.result === 'L' ? 'neg' : 'draw'\n  return (\n    <div className=\"ss-w-pd-match\">\n      <div className=\"ss-w-pd-match-date\">{date === null ? '' : ui.logShortDate(date)}</div>\n      <div className=\"ss-w-pd-match-main\">\n        <div className=\"ss-w-pd-match-opp\">{ui.matchLogOpponent(row.opponentName, row.isHome)}</div>\n        <div className=\"ss-w-pd-match-sub\">{sub}</div>\n      </div>\n      <div className={`ss-w-pd-pill ss-w-pd-pill--${pillTone}`}>{ui.resultLetter[row.result]}</div>\n      {rating === null\n        ? <div className=\"ss-w-pd-chip-empty\" />\n        : <div className={`ss-w-pd-chip ss-w-pd-chip--${ratingTone(rating)}`}>{rating.toFixed(1)}</div>}\n    </div>\n  )\n}\n\nexport function PlayerDetail({ detail, loading, ui, seasonName, onClose }: {\n  detail: ClubPlayerDetailPayload | null\n  loading: boolean\n  ui: UiConfig\n  seasonName: string | null\n  onClose: () => void\n}): JSX.Element {\n  const back = (\n    <button type=\"button\" className=\"ss-w-pd-back\" onClick={onClose}>\n      <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M15 18l-6-6 6-6\" /></svg>\n      {ui.clubPlayerBack}\n    </button>\n  )\n\n  if (detail === null) {\n    return loading\n      ? <><div className=\"ss-w-pd-bar\">{back}</div><div className=\"ss-w-mon-list\" /></>\n      : <><div className=\"ss-w-pd-bar\">{back}</div><div className=\"ss-w-mon-empty\">{ui.clubPlayerDetailEmpty}</div></>\n  }\n\n  const s = detail.seasonStats\n  const foot = footLabel(ui, detail.foot)\n  const position = positionLabel(ui, detail.positionName)\n  const subLine = [detail.teamName?.trim() || null, position].filter(Boolean).join(' · ')\n  const competition = detail.competitionName?.trim() || null\n  const eyebrow = seasonName === null\n    ? null\n    : competition === null ? ui.detailSeason.replace('{season}', seasonName) : `${seasonName} ${competition}`\n  const rating = typeof s.averageRating === 'number' && Number.isFinite(s.averageRating) ? s.averageRating : null\n  const next = detail.nextFixture ?? null\n  const availability = detail.availability ?? null\n  const log = detail.matchLog ?? []\n\n  return (\n    <>\n      <div className=\"ss-w-pd-bar\">{back}</div>\n      <div className=\"ss-w-mon-list ss-w-pd-list\">\n        <div className=\"ss-w-pd-card ss-w-pd-profile\">\n          <PlayerPhoto key={detail.photoUrl ?? ''} photoUrl={detail.photoUrl} jerseyNumber={detail.jerseyNumber} size={52} />\n          <div className=\"ss-w-pd-profile-main\">\n            <div className=\"ss-w-pd-name\">{detail.playerName}</div>\n            {subLine !== '' && <div className=\"ss-w-pd-sub\">{subLine}</div>}\n            <div className=\"ss-w-pd-bio\">\n              <Bio label={ui.detailAge} value={ageFrom(detail.dateOfBirthUnixMs)} />\n              <Bio label={ui.detailHeight} value={detail.heightCm === null ? DASH : `${detail.heightCm} cm`} />\n              {foot !== null && <Bio label={ui.detailFoot} value={foot} />}\n              <Bio label={ui.detailNatShort} value={detail.nationality ?? DASH} />\n            </div>\n          </div>\n          <MiniPitch positionCode={detail.positionCode} />\n        </div>\n\n        {(next !== null || availability !== null) && <AvailabilityCard ui={ui} next={next} availability={availability} />}\n\n        <div>\n          {eyebrow !== null && <div className=\"ss-w-pd-eyebrow ss-w-pd-eyebrow--block\">{eyebrow}</div>}\n          <div className=\"ss-w-pd-tiles\">\n            <Tile label={ui.statColGoals} value={String(s.goals)} />\n            <Tile label={ui.statColAssists} value={String(s.assists)} />\n            {typeof s.starts === 'number' && <Tile label={ui.detailStarted} value={String(s.starts)} />}\n            <Tile label={ui.detailMatches} value={String(s.appearances)} />\n            <Tile label={ui.statColMinutes} value={String(s.minutesPlayed)} />\n            {rating !== null && <Tile label={ui.statColRating} value={rating.toFixed(2)} pos={Math.round(rating * 100) / 100 >= 7} />}\n            <Tile label={ui.detailYellows} value={String(s.yellowCards)} />\n            <Tile label={ui.detailReds} value={String(s.redCards)} />\n          </div>\n        </div>\n\n        {detail.performance != null && (\n          <PerformanceBars performance={detail.performance} competitionName={competition} strings={ui} />\n        )}\n\n        {log.length > 0 && (\n          <div>\n            <div className=\"ss-w-pd-eyebrow ss-w-pd-eyebrow--block\">{ui.matchLogTitle}</div>\n            <div className=\"ss-w-pd-card ss-w-pd-log\">\n              {log.map((row) => <MatchRow key={row.matchId} ui={ui} row={row} />)}\n            </div>\n          </div>\n        )}\n      </div>\n    </>\n  )\n}\n","import { useId, type RefObject } from 'react'\nimport type { PresetStrings } from '../i18n'\nimport { CloseIcon, ComboIcon, SlidersIcon } from './Icons'\n\nexport type PresetToolKind = 'numbers' | 'combo'\n\n/**\n * Onboarding presets stage 2 speed dial (R13, board ShowDial). The round button comes first in the\n * DOM so Tab goes from it into the pills; CSS stacks the pills above it. Folded pills stay mounted\n * for aria-controls and the reverse animation (P10), hidden and out of the tab order.\n */\nexport function PresetSpeedDial({ expanded, showDot, strings, onToggle, onOpen, rootRef, buttonRef }: {\n  expanded: boolean\n  showDot: boolean\n  strings: PresetStrings\n  onToggle: () => void\n  onOpen: (kind: PresetToolKind) => void\n  rootRef: RefObject<HTMLDivElement>\n  buttonRef: RefObject<HTMLButtonElement>\n}): JSX.Element {\n  const pillsId = useId()\n  const tabIndex = expanded ? 0 : -1\n  return (\n    <div ref={rootRef} className=\"ss-w-dial\">\n      <button\n        ref={buttonRef} type=\"button\" className=\"ss-w-dial-btn\"\n        aria-expanded={expanded} aria-controls={pillsId} aria-label={strings.dialName} onClick={onToggle}\n      >\n        <span className=\"ss-w-dial-icon ss-w-dial-icon--open\"><SlidersIcon /></span>\n        <span className=\"ss-w-dial-icon ss-w-dial-icon--close\"><CloseIcon /></span>\n        {showDot && !expanded ? <span className=\"ss-w-dial-dot\" aria-hidden=\"true\" /> : null}\n      </button>\n      <div id={pillsId} className=\"ss-w-dial-pills\" data-open={expanded ? '' : undefined}>\n        <button type=\"button\" className=\"ss-w-dial-pill\" tabIndex={tabIndex} onClick={() => onOpen('numbers')}>\n          <SlidersIcon /><span className=\"ss-w-dial-pill-label\">{strings.setNumbers}</span>\n        </button>\n        <button type=\"button\" className=\"ss-w-dial-pill\" tabIndex={tabIndex} onClick={() => onOpen('combo')}>\n          <ComboIcon /><span className=\"ss-w-dial-pill-label\">{strings.buildCombo}</span>\n        </button>\n      </div>\n    </div>\n  )\n}\n","import { Fragment, useEffect, useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react'\nimport type { PresetComboCell, PresetGrid, PresetPick, PresetSinglesCell } from '@sensiblestats/widget-sdk'\nimport type { PresetStrings } from '../i18n'\nimport {\n  FIXED_SINGLES_COUNT, START, clampLegs, comboAsk, comboLegChoices, comboTotals, findCombo, findSingles,\n  legsForTotal, marketAsk, marketDisplay, maxPriceAsk, minPriceAsk, nearest, samePrice, singlesFloors, singlesLimits, startCombo, startSingles, startValue, type PresetAsk,\n} from '../presetGrid'\nimport { CloseIcon, SendIcon } from './Icons'\n\n// Onboarding presets stage 2: the two tools (spec Stage 2 Behaviour, boards 1c and 2c). Every pick,\n// price and multiplication line is the grid's; the widget only offers numbers and finds the cell.\n\nconst FOCUSABLE = 'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\n/** A modal dialog over the message list with a focus trap. Escape closes it before ChatPanel's\n *  window listener closes the panel: two bubble-phase window listeners have no order guarantee, so\n *  this one runs in the capture phase and stops the event. */\nexport function PresetToolModal({ title, closeLabel, onClose, children, footer }: {\n  title: string\n  closeLabel: string\n  onClose: () => void\n  children: ReactNode\n  footer?: ReactNode\n}): JSX.Element {\n  const dialogRef = useRef<HTMLDivElement>(null)\n  const titleId = useId()\n\n  useEffect(() => { dialogRef.current?.focus() }, [])\n\n  useEffect(() => {\n    const onKey = (e: globalThis.KeyboardEvent): void => {\n      if (e.key !== 'Escape') return\n      e.stopPropagation()\n      e.preventDefault()\n      onClose()\n    }\n    window.addEventListener('keydown', onKey, true)\n    return () => window.removeEventListener('keydown', onKey, true)\n  }, [onClose])\n\n  const trapTab = (e: KeyboardEvent<HTMLDivElement>): void => {\n    if (e.key !== 'Tab') return\n    const dialog = dialogRef.current\n    if (!dialog) return\n    const items = Array.from(dialog.querySelectorAll<HTMLElement>(FOCUSABLE))\n    const first = items[0]\n    const last = items[items.length - 1]\n    if (!first || !last) { e.preventDefault(); return }\n    const active = (dialog.getRootNode() as Document | ShadowRoot).activeElement\n    if (e.shiftKey && (active === first || active === dialog)) { e.preventDefault(); last.focus() }\n    else if (!e.shiftKey && active === last) { e.preventDefault(); first.focus() }\n  }\n\n  return (\n    <div className=\"ss-w-tool-backdrop\">\n      <div ref={dialogRef} className=\"ss-w-tool\" role=\"dialog\" aria-modal=\"true\" aria-labelledby={titleId} tabIndex={-1} onKeyDown={trapTab}>\n        <div className=\"ss-w-tool-head\">\n          <h2 id={titleId} className=\"ss-w-tool-title\">{title}</h2>\n          <button type=\"button\" className=\"ss-w-tool-close\" aria-label={closeLabel} onClick={onClose}><CloseIcon /></button>\n        </div>\n        <div className=\"ss-w-tool-body\">{children}</div>\n        {footer ? <div className=\"ss-w-tool-foot\">{footer}</div> : null}\n      </div>\n    </div>\n  )\n}\n\n/** Fills a row template (\"{count} picks, max {price}\") with text and numbers in a select. */\nfunction fillTemplate(template: string, slots: Record<string, ReactNode>): ReactNode[] {\n  return template.split(/(\\{[a-z]+\\})/).filter((part) => part !== '').map((part, i) => {\n    const key = /^\\{([a-z]+)\\}$/.exec(part)?.[1]\n    return <Fragment key={i}>{key !== undefined && key in slots ? slots[key] : part}</Fragment>\n  })\n}\n\ninterface NumberChoice { value: number; text: string; available: boolean }\n\n/** A native select that sits inside the sentence. The hidden span carries the selected text so the\n *  control is as wide as the number, not as wide as the longest \"not today\" option. */\nfunction NumberSelect({ current, choices, label, notToday, lockEmpty = true, onChoose }: {\n  current: string\n  choices: NumberChoice[]\n  label: string\n  notToday: string\n  /** Disable options with no picks; the legs select leaves them selectable so a choice never jumps the total. */\n  lockEmpty?: boolean\n  onChoose: (value: number) => void\n}): JSX.Element {\n  const selected = Math.max(0, choices.findIndex((c) => c.text === current))\n  return (\n    <span className=\"ss-w-tool-num\">\n      <span className=\"ss-w-tool-num-size\" aria-hidden=\"true\">{current}</span>\n      <select className=\"ss-w-tool-num-select\" aria-label={label} value={String(selected)} onChange={(e) => { const c = choices[Number(e.target.value)]; if (c) onChoose(c.value) }}>\n        {choices.map((c, i) => (\n          <option key={i} value={String(i)} disabled={lockEmpty && !c.available && i !== selected}>{c.available ? c.text : `${c.text}${notToday}`}</option>\n        ))}\n      </select>\n    </span>\n  )\n}\n\n/** A native select for string-keyed choices (e.g., market cells). Same CSS pattern as NumberSelect.\n *  sizeLabels drive the hidden span that sizes the container; optionLabels fill the native dropdown.\n *  Keep sizeLabels short (selectionLabel or a compact variant) so the control fits at narrow viewports. */\nfunction ChoiceSelect({ currentIdx, sizeLabels, optionLabels, label, onChoose }: {\n  currentIdx: number\n  /** Short text shown in the hidden size span; controls the container width. */\n  sizeLabels: string[]\n  /** Full text shown in the native select options. */\n  optionLabels: string[]\n  label: string\n  onChoose: (idx: number) => void\n}): JSX.Element {\n  const sizeText = sizeLabels[currentIdx] ?? ''\n  return (\n    <span className=\"ss-w-tool-num\">\n      <span className=\"ss-w-tool-num-size\" aria-hidden=\"true\">{sizeText}</span>\n      <select className=\"ss-w-tool-num-select\" aria-label={label} value={String(currentIdx)} onChange={(e) => onChoose(Number(e.target.value))}>\n        {optionLabels.map((opt, i) => <option key={i} value={String(i)}>{opt}</option>)}\n      </select>\n    </span>\n  )\n}\n\nfunction SendButton({ label, display, disabled, onClick }: { label: string; display: string; disabled: boolean; onClick: () => void }): JSX.Element {\n  return <button type=\"button\" className=\"ss-w-tool-send\" aria-label={`${label}: ${display}`} disabled={disabled} onClick={onClick}>{label}</button>\n}\n\n// contract §2: a grid pick has no kickoffLabel, so the time comes from kickoffUtc through the\n// widget's own formatter (ChatPanel passes ui.bettingKickoff).\nfunction PickList({ picks, formatKickoff }: { picks: PresetPick[]; formatKickoff: (kickoffUtc: string) => string }): JSX.Element {\n  return (\n    <ul className=\"ss-w-tool-picks\" role=\"list\">\n      {picks.map((p) => (\n        <li key={p.matchOddsId} className=\"ss-w-tool-pick\">\n          <span className=\"ss-w-tool-pick-match\">{p.homeTeamName} – {p.awayTeamName}</span>\n          <span className=\"ss-w-tool-pick-sel\">{p.marketLabel}: {p.selectionLabel}{p.line ? ` ${p.line}` : ''}</span>\n          <span className=\"ss-w-tool-pick-kick\">{formatKickoff(p.kickoffUtc)}</span>\n          <span className=\"ss-w-tool-pick-price\">{p.price.toFixed(2)}</span>\n        </li>\n      ))}\n    </ul>\n  )\n}\n\nfunction ComboPreview({ cell, formatKickoff }: { cell: PresetComboCell; formatKickoff: (kickoffUtc: string) => string }): JSX.Element {\n  return (\n    <>\n      <PickList picks={cell.combo.legs} formatKickoff={formatKickoff} />\n      <div className=\"ss-w-tool-math\">{cell.combo.multiplication}</div>\n    </>\n  )\n}\n\nfunction Unavailable({ text }: { text: string }): JSX.Element {\n  return <p className=\"ss-w-tool-unavailable\">{text}</p>\n}\n\n/** One ask in \"Set the numbers\" (board 1c): the sentence with its numbers, how many picks are ready,\n *  and a round send button. The picks themselves show up in the chat after the send. */\nfunction AskRow({ icon, ask, ready, send }: { icon: string; ask: ReactNode; ready: string | null; send: ReactNode }): JSX.Element {\n  return (\n    <section className=\"ss-w-tool-row ss-w-tool-row--ask\">\n      <span className=\"ss-w-tool-icon\" aria-hidden=\"true\">{icon}</span>\n      <div className=\"ss-w-tool-main\">\n        <p className=\"ss-w-tool-ask\">{ask}</p>\n        {ready ? <span className=\"ss-w-tool-ready\">{ready}</span> : null}\n      </div>\n      {send}\n    </section>\n  )\n}\n\nfunction RoundSend({ label, display, disabled, onClick }: { label: string; display: string; disabled: boolean; onClick: () => void }): JSX.Element {\n  return <button type=\"button\" className=\"ss-w-tool-go\" aria-label={`${label}: ${display}`} disabled={disabled} onClick={onClick}><SendIcon /></button>\n}\n\n/** Where the second combo row starts, as board 1c reads (\"Total 50 with 6 matches\"). */\nconst BIG_COMBO = { total: 50, legs: 6 } as const\n\nexport function SetNumbersTool({ grid, strings, streaming, onSend, onClose }: {\n  grid: PresetGrid\n  strings: PresetStrings\n  streaming: boolean\n  onSend: (ask: PresetAsk) => void\n  onClose: () => void\n}): JSX.Element {\n  const limits = singlesLimits(grid)\n  const floors = singlesFloors(grid)\n  const totals = comboTotals(grid)\n  const legChoices = comboLegChoices(grid)\n  const count = FIXED_SINGLES_COUNT\n  const [maxPrice, setMaxPrice] = useState(() => startSingles(grid.singles, limits, START.maxPrice, count))\n  const [minPrice, setMinPrice] = useState(() => startSingles(grid.singlesFrom, floors, START.minPrice, count))\n  const [start] = useState(() => startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs))\n  const [total, setTotal] = useState(start.total)\n  const [legs, setLegs] = useState(start.legs)\n  const [bigStart] = useState(() => startCombo(grid, totals, legChoices, BIG_COMBO.total, BIG_COMBO.legs))\n  const [bigTotal, setBigTotal] = useState(bigStart.total)\n  const [bigLegs, setBigLegs] = useState(bigStart.legs)\n  const [announcement, setAnnouncement] = useState('')\n  const maxCell = findSingles(grid.singles, maxPrice, count)\n  const minCell = findSingles(grid.singlesFrom, minPrice, count)\n  const comboCell = findCombo(grid, total, legs)\n  const bigCell = findCombo(grid, bigTotal, bigLegs)\n  const announce = (display: string, available: boolean): void => setAnnouncement(available ? display : `${display}. ${strings.unavailable}`)\n\n  const chooseMarket = (idx: number): void => {\n    setMarketIdx(idx)\n    const cell = markets[idx]\n    if (cell) announce(marketDisplay(cell, strings), cell.count > 0)\n  }\n  const chooseMax = (v: number): void => { setMaxPrice(v); announce(strings.maxPriceDisplay(count, v), !!findSingles(grid.singles, v, count)) }\n  const chooseMin = (v: number): void => { setMinPrice(v); announce(strings.minPriceDisplay(count, v), !!findSingles(grid.singlesFrom, v, count)) }\n  const chooseLegs = (v: number): void => { setLegs(v); announce(strings.comboDisplay(v, total), !!findCombo(grid, total, v)) }\n  const chooseTotal = (v: number): void => { const l = legsForTotal(grid, v, legs); setTotal(v); setLegs(l); announce(strings.comboDisplay(l, v), !!findCombo(grid, v, l)) }\n  const chooseBigLegs = (v: number): void => { setBigLegs(v); announce(strings.comboDisplay(v, bigTotal), !!findCombo(grid, bigTotal, v)) }\n  const chooseBigTotal = (v: number): void => { const l = legsForTotal(grid, v, bigLegs); setBigTotal(v); setBigLegs(l); announce(strings.comboDisplay(l, v), !!findCombo(grid, v, l)) }\n  const maxChoices = limits.map((v) => ({ value: v, text: v.toFixed(2), available: !!findSingles(grid.singles, v, count) }))\n  const minChoices = floors.map((v) => ({ value: v, text: v.toFixed(2), available: !!findSingles(grid.singlesFrom, v, count) }))\n  const totalChoices = totals.map((v) => ({ value: v, text: v.toFixed(1), available: legChoices.some((n) => !!findCombo(grid, v, n)) }))\n  const legChoicesFor = (t: number): NumberChoice[] => legChoices.map((n) => ({ value: n, text: String(n), available: !!findCombo(grid, t, n) }))\n  const markets = grid.markets ?? []\n  const [marketIdx, setMarketIdx] = useState(0)\n  const marketCell = markets[marketIdx] ?? null\n  // The select shows the same short name it is sized to, so the sentence never cuts it.\n  const marketLabels = markets.map((c) => strings.marketShort(c.marketDeveloperName, c.marketLabel, c.selectionLabel ?? null))\n  const singlesReady = (cell: PresetSinglesCell | null): string => (cell ? strings.readyCount(cell.picks.length) : strings.unavailable)\n  const comboReady = (cell: PresetComboCell | null): string => (cell ? strings.readyAt(cell.combo.total) : strings.unavailable)\n\n  return (\n    <PresetToolModal title={strings.setNumbers} closeLabel={strings.close} onClose={onClose}>\n      <AskRow\n        icon=\"🎯\"\n        ask={fillTemplate(strings.maxPriceRow, {\n          count: String(count),\n          price: <NumberSelect current={maxPrice.toFixed(2)} choices={maxChoices} label={strings.maxPriceName} notToday={strings.notToday} onChoose={chooseMax} />,\n        })}\n        ready={singlesReady(maxCell)}\n        send={<RoundSend label={strings.send} display={strings.maxPriceDisplay(count, maxPrice)} disabled={!maxCell || streaming} onClick={() => { if (maxCell) onSend(maxPriceAsk(maxCell, strings)) }} />}\n      />\n      <AskRow\n        icon=\"📈\"\n        ask={fillTemplate(strings.minPriceRow, {\n          count: String(count),\n          price: <NumberSelect current={minPrice.toFixed(2)} choices={minChoices} label={strings.minPriceName} notToday={strings.notToday} onChoose={chooseMin} />,\n        })}\n        ready={singlesReady(minCell)}\n        send={<RoundSend label={strings.send} display={strings.minPriceDisplay(count, minPrice)} disabled={!minCell || streaming} onClick={() => { if (minCell) onSend(minPriceAsk(minCell, strings)) }} />}\n      />\n      <AskRow\n        icon=\"✨\"\n        ask={fillTemplate(strings.comboRow, {\n          legs: <NumberSelect current={String(legs)} choices={legChoicesFor(total)} label={strings.matchesLabel} notToday={strings.notToday} lockEmpty={false} onChoose={chooseLegs} />,\n          total: <NumberSelect current={total.toFixed(1)} choices={totalChoices} label={strings.totalLabel} notToday={strings.notToday} onChoose={chooseTotal} />,\n        })}\n        ready={comboReady(comboCell)}\n        send={<RoundSend label={strings.send} display={strings.comboDisplay(legs, total)} disabled={!comboCell || streaming} onClick={() => { if (comboCell) onSend(comboAsk(comboCell, strings)) }} />}\n      />\n      <AskRow\n        icon=\"🏆\"\n        ask={fillTemplate(strings.bigComboRow, {\n          legs: <NumberSelect current={String(bigLegs)} choices={legChoicesFor(bigTotal)} label={strings.matchesLabel} notToday={strings.notToday} lockEmpty={false} onChoose={chooseBigLegs} />,\n          total: <NumberSelect current={bigTotal.toFixed(1)} choices={totalChoices} label={strings.totalLabel} notToday={strings.notToday} onChoose={chooseBigTotal} />,\n        })}\n        ready={comboReady(bigCell)}\n        send={<RoundSend label={strings.send} display={strings.comboDisplay(bigLegs, bigTotal)} disabled={!bigCell || streaming} onClick={() => { if (bigCell) onSend(comboAsk(bigCell, strings)) }} />}\n      />\n      {markets.length > 0 && (\n        <AskRow\n          icon=\"⚽\"\n          ask={fillTemplate(strings.marketRow, {\n            market: <ChoiceSelect currentIdx={marketIdx} sizeLabels={marketLabels} optionLabels={marketLabels} label={strings.marketName} onChoose={chooseMarket} />,\n          })}\n          ready={marketCell ? strings.readyCount(marketCell.count) : null}\n          send={<RoundSend label={strings.send} display={marketCell ? marketDisplay(marketCell, strings) : ''} disabled={!marketCell || streaming} onClick={() => { if (marketCell) onSend(marketAsk(marketCell, strings)) }} />}\n        />\n      )}\n      <p className=\"ss-w-vh\" aria-live=\"polite\">{announcement}</p>\n    </PresetToolModal>\n  )\n}\n\nexport function BuildComboTool({ grid, strings, streaming, formatKickoff, initialTotal, initialLegs, onSend, onClose }: {\n  grid: PresetGrid\n  strings: PresetStrings\n  streaming: boolean\n  formatKickoff: (kickoffUtc: string) => string\n  /** From a combo card's \"Change total or matches\" (spec C5); absent from the round button. */\n  initialTotal?: number\n  initialLegs?: number\n  onSend: (ask: PresetAsk) => void\n  onClose: () => void\n}): JSX.Element {\n  const totals = comboTotals(grid)\n  const legChoices = comboLegChoices(grid)\n  const [start] = useState(() => (initialTotal === undefined ? startCombo(grid, totals, legChoices, START.comboTotal, START.comboLegs) : null))\n  const [total, setTotal] = useState(() => (initialTotal !== undefined ? nearest(totals, initialTotal) : start!.total))\n  const [legs, setLegs] = useState(() => {\n    if (initialTotal === undefined) return initialLegs !== undefined ? clampLegs(legChoices, initialLegs) : start!.legs\n    const from = initialLegs !== undefined ? clampLegs(legChoices, initialLegs) : startValue(legChoices, START.comboLegs)\n    return legsForTotal(grid, nearest(totals, initialTotal), from)\n  })\n  const [announcement, setAnnouncement] = useState('')\n  const cell = findCombo(grid, total, legs)\n  const minLegs = legChoices[0] ?? legs\n  const maxLegs = legChoices[legChoices.length - 1] ?? legs\n  const display = strings.comboDisplay(legs, total)\n\n  const choose = (nextTotal: number, nextLegs: number): void => {\n    setTotal(nextTotal)\n    setLegs(nextLegs)\n    const d = strings.comboDisplay(nextLegs, nextTotal)\n    setAnnouncement(findCombo(grid, nextTotal, nextLegs) ? d : `${d}. ${strings.unavailable}`)\n  }\n\n  const footer = (\n    <SendButton label={strings.send} display={display} disabled={!cell || streaming} onClick={() => { if (cell) onSend(comboAsk(cell, strings)) }} />\n  )\n\n  return (\n    <PresetToolModal title={strings.buildCombo} closeLabel={strings.close} onClose={onClose} footer={footer}>\n      <div className=\"ss-w-tool-section\" role=\"group\" aria-label={strings.totalLabel}>\n        <span className=\"ss-w-tool-label\" aria-hidden=\"true\">{strings.totalLabel}</span>\n        <div className=\"ss-w-tool-chips\">\n          {totals.map((t) => (\n            <button key={t} type=\"button\" className=\"ss-w-tool-chip\" aria-pressed={samePrice(t, total)} onClick={() => choose(t, samePrice(t, total) ? legs : legsForTotal(grid, t, legs))}>{t.toFixed(1)}</button>\n          ))}\n        </div>\n      </div>\n      <div className=\"ss-w-tool-section\" role=\"group\" aria-label={strings.matchesLabel}>\n        <span className=\"ss-w-tool-label\" aria-hidden=\"true\">{strings.matchesLabel}</span>\n        <div className=\"ss-w-tool-stepper\">\n          <button type=\"button\" className=\"ss-w-tool-step\" aria-label={strings.fewerMatches} disabled={legs <= minLegs} onClick={() => choose(total, legs - 1)}>−</button>\n          <span className=\"ss-w-tool-count\">{legs}</span>\n          <button type=\"button\" className=\"ss-w-tool-step\" aria-label={strings.moreMatches} disabled={legs >= maxLegs} onClick={() => choose(total, legs + 1)}>+</button>\n        </div>\n      </div>\n      {cell ? <ComboPreview cell={cell} formatKickoff={formatKickoff} /> : <Unavailable text={strings.unavailable} />}\n      <p className=\"ss-w-vh\" aria-live=\"polite\">{announcement}</p>\n    </PresetToolModal>\n  )\n}\n","import { useCallback, useEffect, useRef, useState, type RefObject } from 'react'\nimport type { Message } from './reducer'\n\n/** P3: a non-greeting turn streaming at mount can only be a send that came with the open (a bubble\n *  ask): CLOSE clears isStreaming (reducer.ts:123-124). */\nexport function sendInFlight(messages: Message[], isStreaming: boolean): boolean {\n  const last = messages[messages.length - 1]\n  return isStreaming && !!last && last.role === 'assistant' && !last.done && !last.isGreeting\n}\n\nexport function lastUserId(messages: Message[]): string | null {\n  for (let i = messages.length - 1; i >= 0; i--) {\n    const m = messages[i]\n    if (m && m.role === 'user') return m.id\n  }\n  return null\n}\n\n// P2: keys that scroll a focused list. Tab is not here: it never folds the pills.\nconst SCROLL_KEYS = new Set(['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown', 'Home', 'End', ' '])\n\nexport interface PresetDial {\n  expanded: boolean\n  toggle(): void\n  fold(): void\n}\n\n/**\n * The speed dial's open state (R13). Out on every panel open (this hook mounts with ChatPanel),\n * folded by the first press outside the dial, a user scroll of the message list, a tab change or a\n * send; typing folds through ChatInput's onType. No timer. Escape with focus in the dial never\n * reaches ChatPanel's window listener: it folds the pills when out and otherwise does nothing (P4).\n */\nexport function usePresetDial({ layerRef, dialRef, dialButtonRef, messages, isStreaming, activeTab }: {\n  layerRef: RefObject<HTMLElement>\n  dialRef: RefObject<HTMLElement>\n  dialButtonRef: RefObject<HTMLButtonElement>\n  messages: Message[]\n  isStreaming: boolean\n  activeTab: string\n}): PresetDial {\n  const [expanded, setExpanded] = useState(() => !sendInFlight(messages, isStreaming))\n  const fold = useCallback(() => setExpanded(false), [])\n  const toggle = useCallback(() => setExpanded((e) => !e), [])\n\n  const currentUserId = lastUserId(messages)\n  const userIdRef = useRef(currentUserId)\n  useEffect(() => {\n    if (currentUserId === userIdRef.current) return\n    userIdRef.current = currentUserId\n    setExpanded(false)\n  }, [currentUserId])\n\n  const tabRef = useRef(activeTab)\n  useEffect(() => {\n    if (activeTab === tabRef.current) return\n    tabRef.current = activeTab\n    setExpanded(false)\n  }, [activeTab])\n\n  const expandedRef = useRef(expanded)\n  expandedRef.current = expanded\n  // Escape with focus on the round button or a pill never reaches ChatPanel's panel handler (P4):\n  // capture phase, stopped; it folds the pills when they are out and otherwise does nothing.\n  useEffect(() => {\n    const onEscape = (e: KeyboardEvent): void => {\n      const dial = dialRef.current\n      if (e.key !== 'Escape' || !dial || !e.composedPath().includes(dial)) return\n      e.stopPropagation()\n      e.preventDefault()\n      if (!expandedRef.current) return\n      setExpanded(false)\n      dialButtonRef.current?.focus()\n    }\n    window.addEventListener('keydown', onEscape, true)\n    return () => window.removeEventListener('keydown', onEscape, true)\n  }, [dialRef, dialButtonRef])\n\n  useEffect(() => {\n    if (!expanded) return\n    const layer = layerRef.current\n    const inDial = (e: Event): boolean => {\n      const dial = dialRef.current\n      return !!dial && e.composedPath().includes(dial)\n    }\n    const inList = (e: Event): boolean =>\n      e.composedPath().some((n) => n instanceof Element && n.classList.contains('ss-w-list'))\n    const onPress = (e: Event): void => { if (!inDial(e)) setExpanded(false) }\n    const onScrollGesture = (e: Event): void => { if (inList(e) && !inDial(e)) setExpanded(false) }\n    const onKey = (e: KeyboardEvent): void => {\n      if (SCROLL_KEYS.has(e.key) && inList(e)) setExpanded(false)\n    }\n    // composedPath() sees through the embed's open shadow root, so a document listener works there too.\n    const doc = layer?.ownerDocument ?? document\n    doc.addEventListener('pointerdown', onPress, true)\n    layer?.addEventListener('wheel', onScrollGesture, { passive: true })\n    layer?.addEventListener('touchmove', onScrollGesture, { passive: true })\n    window.addEventListener('keydown', onKey, true)\n    return () => {\n      doc.removeEventListener('pointerdown', onPress, true)\n      layer?.removeEventListener('wheel', onScrollGesture)\n      layer?.removeEventListener('touchmove', onScrollGesture)\n      window.removeEventListener('keydown', onKey, true)\n    }\n  }, [expanded, layerRef, dialRef])\n\n  return { expanded, toggle, fold }\n}\n","// spec Stage 2 \"The dot\": shown until the visitor has opened a tool once. Kept in localStorage,\n// read and written inside try/catch as slipLedger.ts does; with no storage, this module's memory\n// carries it for the page.\nconst KEY = 'ss-w-presets-tool-opened'\nlet openedThisPage = false\n\nexport function readToolSeen(): boolean {\n  if (openedThisPage) return true\n  try {\n    return window.localStorage.getItem(KEY) === '1'\n  } catch {\n    return false\n  }\n}\n\nexport function markToolSeen(): void {\n  openedThisPage = true\n  try {\n    window.localStorage.setItem(KEY, '1')\n  } catch {\n    /* storage denied: the memory above carries it for this page */\n  }\n}\n\n/** Test seam: a new page load starts with no memory. */\nexport function resetToolSeenMemory(): void {\n  openedThisPage = false\n}\n","import type { ReactNode } from 'react'\nimport { SlipStateContext } from '../slipStateContext'\nimport type { HostEvents } from '../useHostEvents'\n\n/** Hands what useHostEvents returns to the components that read it. */\nexport function HostEventsProvider({ value, children }: { value: HostEvents; children: ReactNode }): JSX.Element {\n  return <SlipStateContext.Provider value={value.slipState}>{children}</SlipStateContext.Provider>\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; --ss-w-warn: #c07a00;\\n  --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n  --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n  --ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;\\n  font-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, Helvetica, Arial, sans-serif;\\n  font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);\\n}\\n@media (prefers-color-scheme: dark) {\\n  .ss-w-root[data-ss-w-theme=\\\"auto\\\"] {\\n    --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n    --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n    --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n    --ss-w-pos: #37c891; --ss-w-neg: #f0655d; --ss-w-warn: #e0a030;\\n    --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n    --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n  }\\n}\\n.ss-w-root[data-ss-w-theme=\\\"dark\\\"] {\\n  --ss-w-accent: #37c891; --ss-w-cta: #ffb638; --ss-w-cta-ink: #1b1300;\\n  --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\\n  --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\\n  --ss-w-pos: #37c891; --ss-w-neg: #f0655d; --ss-w-warn: #e0a030;\\n  --ss-w-home: #5b83c8; --ss-w-away: #e8384f; --ss-w-track: #232d3a;\\n  --ss-w-correct: #37c86b; --ss-w-wrong: #3a3a41;\\n}\\n.ss-w-root[data-ss-w-theme=\\\"light\\\"] {\\n  --ss-w-accent: #17936a; --ss-w-cta: #f5a623; --ss-w-cta-ink: #1b1300;\\n  --ss-w-ink: #14181d; --ss-w-faint: #6b7580;\\n  --ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\\n  --ss-w-home: #3a63a8; --ss-w-away: #c8102e; --ss-w-track: #e9edf1;\\n  --ss-w-correct: #1f9d55; --ss-w-wrong: #b9bbc2;\\n}\\n\\n/* ── games design tokens (u393) ── derived from operator tokens so every tenant theme works.\\n   Targets (Hull #F5A800/#0B0B0B/#F5F5F5): ground #0D0C0A, surface #17150F, warm #1C1810,\\n   raised #211E17, line #26221A, line-warm #3A2F18, accent-tint #3A2C10, strong-line #4A4131. */\\n.ss-w-root {\\n  --ss-g-ground: color-mix(in srgb, var(--ss-w-accent) 2%, var(--ss-w-panel));\\n  --ss-g-surface: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n  --ss-g-warm: color-mix(in srgb, var(--ss-w-accent) 6%, color-mix(in srgb, var(--ss-w-ink) 2%, var(--ss-w-panel)));\\n  --ss-g-raised: color-mix(in srgb, var(--ss-w-accent) 3%, color-mix(in srgb, var(--ss-w-ink) 6%, var(--ss-w-panel)));\\n  --ss-g-line: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 8%, var(--ss-w-panel)));\\n  --ss-g-line-warm: color-mix(in srgb, var(--ss-w-accent) 18%, color-mix(in srgb, var(--ss-w-ink) 3%, var(--ss-w-panel)));\\n  --ss-g-accent-tint: color-mix(in srgb, var(--ss-w-accent) 20%, var(--ss-w-panel));\\n  --ss-g-strong-line: color-mix(in srgb, var(--ss-w-accent) 8%, color-mix(in srgb, var(--ss-w-ink) 18%, var(--ss-w-panel)));\\n  --ss-g-ink: color-mix(in srgb, var(--ss-w-accent) 4%, var(--ss-w-ink));\\n  --ss-g-ink-2: color-mix(in srgb, var(--ss-w-accent) 4%, color-mix(in srgb, var(--ss-w-ink) 72%, var(--ss-w-panel)));\\n  --ss-g-muted: color-mix(in srgb, var(--ss-w-accent) 5%, color-mix(in srgb, var(--ss-w-ink) 60%, var(--ss-w-panel)));\\n  --ss-g-faint: color-mix(in srgb, var(--ss-w-ink) 45%, var(--ss-w-panel));\\n  --ss-g-on-accent: #1a1206;\\n  --ss-g-on-correct: #fff;\\n  --ss-g-correct: color-mix(in srgb, var(--ss-w-correct) 55%, #000);\\n  --ss-g-wrong: color-mix(in srgb, var(--ss-w-neg) 55%, #000);\\n  /* Brighter wrong for thin marks (borders, icons, segments) that must read on dark surfaces; --ss-g-wrong stays for fills. */\\n  --ss-g-wrong-mark: var(--ss-w-neg);\\n  --ss-g-success: color-mix(in srgb, var(--ss-w-pos) 80%, var(--ss-w-ink));\\n  --ss-g-success-tint: color-mix(in srgb, var(--ss-w-pos) 18%, var(--ss-w-panel));\\n  --ss-g-close: #e3b341;\\n  --ss-g-flame: #ff6a1a;\\n  /* Pitch colours are fixed in both themes: the pitch is always a dark green. */\\n  --ss-g-pitch: #123524;\\n  --ss-g-pitch-line: #3e7055;\\n  --ss-g-pitch-chip: #0d0c0a;\\n  --ss-g-pitch-ink: #f4efe6;\\n  --ss-g-pitch-mark: #c9d6cd;\\n  --ss-g-font-display: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;\\n  --ss-g-font-body: 'Barlow', system-ui, -apple-system, 'Segoe UI', sans-serif;\\n}\\n\\n\\n/* ── games ui kit (u393) ── */\\n.ss-g-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\\n.ss-g-head { display: flex; align-items: center; gap: 6px; padding: 8px 16px 8px 6px; font-family: var(--ss-g-font-body); }\\n.ss-g-back { width: 44px; height: 44px; flex: none; display: grid; place-items: center; border: 0; border-radius: 12px; background: transparent; color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-back:hover { background: var(--ss-g-surface); }\\n.ss-g-head-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.05; }\\n.ss-g-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; color: var(--ss-g-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-head-right { flex: none; }\\n.ss-g-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600; white-space: nowrap; }\\n.ss-g-chip--neutral { background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); }\\n.ss-g-chip--neutral .ss-g-num, .ss-g-chip--neutral svg { color: var(--ss-w-accent); }\\n.ss-g-chip--accent { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-weight: 700; }\\n.ss-g-chip--success { background: var(--ss-g-success-tint); color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-chip--badge { padding: 3px 8px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-chip--lock { padding: 3px 8px; border-radius: 6px; font-size: 12px; font-weight: 500; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-statstack { display: flex; flex-direction: column; align-items: flex-end; line-height: 1; }\\n.ss-g-statstack-v { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; color: var(--ss-w-accent); }\\n.ss-g-statstack-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-progress { display: flex; align-items: center; gap: 12px; padding: 0 16px 8px; }\\n.ss-g-progress-main { flex: 1; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-progress-labels { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--ss-g-ink); }\\n.ss-g-progress-rl { color: var(--ss-g-muted); }\\n.ss-g-segs { display: grid; gap: 4px; }\\n.ss-g-seg { height: 5px; border-radius: 3px; background: var(--ss-g-line); }\\n.ss-g-seg[data-state=\\\"done\\\"] { background: var(--ss-g-strong-line); }\\n.ss-g-seg[data-state=\\\"current\\\"] { background: var(--ss-w-accent); }\\n.ss-g-seg[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); }\\n.ss-g-seg[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); }\\n.ss-g-btn { min-height: 48px; padding: 0 16px; border-radius: 12px; font-family: var(--ss-g-font-body); font-size: 14px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }\\n.ss-g-btn:disabled { opacity: .45; cursor: default; }\\n.ss-g-btn--block { width: 100%; min-height: 54px; border-radius: 14px; font-size: 16px; font-weight: 800; }\\n.ss-g-btn--primary { border: 0; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-btn--outline { border: 1.5px solid var(--ss-g-strong-line); background: transparent; color: var(--ss-g-ink); }\\n.ss-g-btn--accent-outline { border: 1.5px solid var(--ss-w-accent); background: transparent; color: var(--ss-w-accent); }\\n.ss-g-btn--surface { border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font-weight: 600; font-size: 13px; }\\n.ss-g-search { display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-search-label { font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-search-box { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1.5px solid var(--ss-g-line); color: var(--ss-g-muted); }\\n.ss-g-search-box:focus-within { border-color: var(--ss-w-accent); }\\n.ss-g-search-box input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: var(--ss-g-ink); font: 500 15px var(--ss-g-font-body); }\\n.ss-g-search-clear { flex: none; width: 20px; height: 20px; padding: 0; border: none; border-radius: 50%; background: var(--ss-g-line); color: var(--ss-g-muted); display: flex; align-items: center; justify-content: center; cursor: pointer; }\\n.ss-g-search-clear:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-g-footer { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--ss-g-line); display: flex; flex-direction: column; gap: 10px; background: var(--ss-g-ground); }\\n.ss-g-sil { position: relative; flex: none; display: inline-flex; align-items: flex-end; justify-content: center; overflow: hidden; border-radius: 50%; background: var(--ss-g-raised); color: var(--ss-g-strong-line); }\\n.ss-g-sil--selected { background: var(--ss-g-accent-tint); color: color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-g-raised)); }\\n.ss-g-sil--mystery { background: var(--ss-g-accent-tint); color: var(--ss-g-ground); }\\n.ss-g-sil-q { position: absolute; top: 22%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 1.1em; color: var(--ss-w-accent); }\\n.ss-g-crest { flex: none; object-fit: contain; }\\n.ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-pitch-svg { position: absolute; inset: 0; width: 100%; height: 100%; stroke: var(--ss-g-pitch-line); stroke-width: .6; }\\n/* ── games screen scaffold (u393) — shared by every game screen ── */\\n.ss-w-gscreen > .ss-g-screen { flex: 1; min-height: 0; }\\n.ss-g-screen { display: flex; flex-direction: column; min-height: 0; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-body); }\\n.ss-g-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 14px; padding: 4px 16px 16px; }\\n.ss-g-body .ss-g-progress { padding: 0; }\\n.ss-g-loading { align-items: center; justify-content: center; color: var(--ss-g-muted); font-size: 13px; }\\n.ss-g-opts { display: flex; flex-direction: column; gap: 4px; max-height: 232px; overflow-y: auto; }\\n.ss-g-opt { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 6px 8px; border: 0; border-radius: 12px; background: var(--ss-g-surface); color: var(--ss-g-ink); font: 600 15px var(--ss-g-font-body); text-align: left; cursor: pointer; }\\n.ss-g-opt:hover, .ss-g-opt:focus-visible { background: var(--ss-g-raised); outline: none; }\\n.ss-g-opt-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 13px; font-weight: 700; }\\n.ss-g-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-result { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 16px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-result[data-tone=\\\"win\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-result[data-tone=\\\"lose\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-result-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 26px; text-transform: uppercase; line-height: 1; }\\n.ss-g-result-score { font-size: 13px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-result-num { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 40px; color: var(--ss-w-accent); margin-right: 4px; }\\n.ss-g-result-detail { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-result .ss-g-btn { margin-top: 6px; }\\n\\n/* launcher */\\n.ss-w-fab-wrap { position: fixed; bottom: var(--ss-w-offset-y); z-index: 2147483000; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-fab-wrap { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-fab-wrap { left: var(--ss-w-offset-x); align-items: flex-start; }\\n.ss-w-fab { width: 56px; height: 56px; border: none; border-radius: 50%; background: var(--ss-w-nav); color: #fff; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 20px rgba(0,0,0,.28); }\\n.ss-w-fab-mark { width: 30px; height: 30px; display: block; object-fit: contain; }\\n.ss-w-greeting { max-width: 240px; display: flex; align-items: flex-start; background: var(--ss-w-panel); color: var(--ss-w-ink); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-greeting-body { position: relative; flex: 1; min-width: 0; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 9px 4px 9px 12px; }\\n.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }\\n.ss-w-greeting-text { display: block; }\\n/* Bubble asks (onboarding presets, spec C6): the line stays one button, the asks stack under it as\\n   sibling buttons. 240 px bubble: 196 px of text room per ask; widest contract ask 167 px (EN),\\n   153 px (TR) at 12px/600, measured 2026-10-04. A longer label wraps, never an ellipsis. */\\n.ss-w-greeting--asks { flex-direction: column; align-items: stretch; }\\n.ss-w-greeting-top { display: flex; align-items: flex-start; }\\n.ss-w-greeting-asks { display: flex; flex-direction: column; gap: 6px; padding: 0 10px 10px; }\\n.ss-w-greeting-ask { min-height: 44px; width: 100%; text-align: left; font: inherit; font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 8%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 35%, var(--ss-w-line)); border-radius: 10px; padding: 6px 10px; cursor: pointer; white-space: normal; overflow-wrap: anywhere; }\\n.ss-w-greeting-ask:hover { border-color: var(--ss-w-accent); }\\n.ss-w-greeting-ask:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n/* Typing indicator: overlays the text area so bubble height stays put; hidden at\\n   rest, revealed only during the one-shot intro (see prefers-reduced-motion block). */\\n.ss-w-greeting-dots { position: absolute; top: 0; bottom: 0; left: 12px; display: flex; align-items: center; gap: 4px; opacity: 0; pointer-events: none; }\\n.ss-w-greeting-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-faint); display: block; }\\n/* One-shot launcher attention intro: FAB nudges, then the greeting types in.\\n   Gated behind no-preference so reduce-motion users get the greeting shown\\n   statically (text visible, no nudge, no typing). ChatFab adds .ss-w-intro once\\n   per page load; every animation runs a single time and settles at rest. */\\n@media (prefers-reduced-motion: no-preference) {\\n  .ss-w-intro .ss-w-fab { animation: ss-w-nudge .8s ease both; }\\n  .ss-w-intro .ss-w-greeting { animation: ss-w-greet-in .45s cubic-bezier(.2,.8,.3,1.15) .8s both; }\\n  .ss-w-intro .ss-w-greeting-text { animation: ss-w-greet-textin .4s ease 1.65s both; }\\n  .ss-w-intro .ss-w-greeting-asks { animation: ss-w-greet-textin .4s ease 1.65s both; }\\n  .ss-w-intro .ss-w-greeting-dots { animation: ss-w-greet-dots .95s ease .85s both; }\\n  .ss-w-intro .ss-w-greeting-dots i { animation: ss-w-greet-dotbounce .5s ease .85s 2; }\\n  .ss-w-intro .ss-w-greeting-dots i:nth-child(2) { animation-delay: 1s; }\\n  .ss-w-intro .ss-w-greeting-dots i:nth-child(3) { animation-delay: 1.15s; }\\n}\\n@keyframes ss-w-nudge {\\n  0%, 100% { transform: none; }\\n  22% { transform: translateY(-9px) rotate(-9deg); }\\n  44% { transform: translateY(0) rotate(7deg); }\\n  64% { transform: translateY(-4px) rotate(-4deg); }\\n  82% { transform: rotate(2deg); }\\n}\\n@keyframes ss-w-greet-in {\\n  from { opacity: 0; transform: translateY(8px) scale(.92); }\\n  to { opacity: 1; transform: none; }\\n}\\n@keyframes ss-w-greet-textin { from { opacity: 0; } to { opacity: 1; } }\\n@keyframes ss-w-greet-dots { 0% { opacity: 0; } 14% { opacity: 1; } 78% { opacity: 1; } 100% { opacity: 0; } }\\n@keyframes ss-w-greet-dotbounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }\\n\\n/* panel */\\n.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(460px, calc(100vw - 40px)); height: min(640px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }\\n.ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel { right: var(--ss-w-offset-x); }\\n.ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { left: var(--ss-w-offset-x); }\\n@media (max-width: 639px) {\\n  /* Fill via inset with no explicit height (like the site's working panel) so the\\n     input stays visible when the mobile keyboard/URL-bar shrinks the viewport. The\\n     position-specific selectors override the right/left offsets set above. */\\n  .ss-w-root[data-ss-w-pos=\\\"right\\\"] .ss-w-panel,\\n  .ss-w-root[data-ss-w-pos=\\\"left\\\"] .ss-w-panel { inset: 0; width: auto; height: auto; border: none; border-radius: 0; }\\n}\\n.ss-w-header { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-header-mark { width: 18px; height: 18px; display: block; object-fit: contain; }\\n.ss-w-header-title { font-weight: 660; flex: 1; }\\n.ss-w-close { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu-wrap { position: relative; display: grid; place-items: center; }\\n.ss-w-kebab { background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\\n.ss-w-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 5; min-width: 184px; padding: 6px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.18); }\\n.ss-w-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; background: none; border: none; border-radius: 8px; color: var(--ss-w-ink); font: inherit; font-size: 13px; text-align: left; cursor: pointer; }\\n.ss-w-menu-item:hover, .ss-w-menu-item:focus-visible { background: var(--ss-w-bubble); }\\n.ss-w-menu-item svg { color: var(--ss-w-faint); font-size: 15px; flex: none; }\\n\\n/* messages */\\n/* .ss-w-mon-list (Matches/Odds tab scrollers) shares .ss-w-list's box/scroll rules by design --\\n   same visual rhythm as the chat message list -- but gets its own class so it isn't the same DOM\\n   landmark as the chat list when both exist in the panel at once (Task 16 fix round, M4). */\\n/* Children of this scrolling column flex container must NOT shrink. The default flex-shrink:1\\n   compresses every child to fit the panel instead of letting the container scroll, and\\n   .ss-w-grp's own overflow:hidden then clips the compressed content away entirely — 27\\n   competition groups rendered as blank bars on a phone. Applies to the pinned cards too. */\\n.ss-w-mon-list > * { flex: none; }\\n.ss-w-list, .ss-w-mon-list { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }\\n/* Transient bottom spacer: reserves a viewport of room below a new turn so its\\n   top can be scrolled into view while the reply is still streaming in. Height is\\n   set imperatively and flex must not shrink it away. */\\n.ss-w-turn-spacer { flex: none; }\\n.ss-w-msg { display: flex; }\\n.ss-w-user { justify-content: flex-end; }\\n.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }\\n.ss-w-bot { flex-direction: column; gap: 8px; }\\n.ss-w-status { font-size: 11px; color: var(--ss-w-faint); font-style: italic; }\\n.ss-w-error { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c0392b; }\\n.ss-w-retry { background: none; border: 1px solid currentColor; border-radius: 10px; padding: 2px 8px; cursor: pointer; color: inherit; }\\n\\n/* markdown */\\n.ss-w-md { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-md :where(p, ul, ol, table, pre, blockquote, h1, h2, h3, h4) { margin: 0; }\\n.ss-w-md > *:first-child { margin-top: 0; }\\n.ss-w-md > *:last-child { margin-bottom: 0; }\\n.ss-w-md-ul { list-style: disc outside; padding-left: 18px; }\\n.ss-w-md-ol { list-style: decimal outside; padding-left: 18px; }\\n.ss-w-md-ul li::marker, .ss-w-md-ol li::marker { color: var(--ss-w-accent); }\\n.ss-w-md-link { color: var(--ss-w-accent); text-decoration: underline; }\\n.ss-w-table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }\\n.ss-w-md-table { border-collapse: collapse; width: max-content; min-width: 100%; font-variant-numeric: tabular-nums; }\\n.ss-w-md-table td, .ss-w-md-table th { border: 1px solid var(--ss-w-line); padding: 4px 8px; text-align: left; white-space: nowrap; }\\n.ss-w-md-table th { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); font-weight: 700; }\\n.ss-w-md-table tbody tr:nth-child(even) { background: var(--ss-w-bubble); }\\n.ss-w-md-code { background: var(--ss-w-bubble); border-radius: 5px; padding: 1px 5px; font-family: ui-monospace, monospace; }\\n\\n/* entity cards */\\n.ss-w-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Entity card: identity header row over a horizontal stat strip */\\n.ss-w-ecard { display: flex; flex-direction: column; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; text-align: left; }\\n\\n.ss-w-ecard-idtext { display: flex; flex-direction: column; gap: 1px; min-width: 0; max-width: 100%; }\\n.ss-w-thumb { width: 54px; height: 54px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 16px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; box-shadow: 0 1px 3px rgba(0,0,0,.14); }\\n.ss-w-thumb.ss-w-team { border-radius: 12px; }\\n.ss-w-ecard[data-kind=\\\"player\\\"] .ss-w-thumb { background-color: var(--ss-w-accent); }\\n.ss-w-nm { font-weight: 680; line-height: 1.15; overflow-wrap: anywhere; }\\n.ss-w-sub { font-size: 11px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* bare card (no stat scopes): simple avatar + name row */\\n.ss-w-ecard-bare { display: flex; align-items: center; }\\n.ss-w-ecard-bare .ss-w-ecard-hd { padding: 10px 12px; }\\n\\n.ss-w-ecard-hd { display: flex; align-items: center; gap: 11px; padding: 11px 13px; }\\n.ss-w-ecard-hd .ss-w-thumb { width: 40px; height: 40px; font-size: 13px; box-shadow: none; }\\n.ss-w-ecard-hd .ss-w-thumb.ss-w-team { border-radius: 10px; }\\n.ss-w-ecard-meta { display: inline-flex; align-items: center; gap: 7px; flex: none; align-self: flex-start; margin-left: auto; }\\n.ss-w-ecard-meta .ss-w-ecard-season { margin: 0; }\\n\\n/* scope tabs: reuse the underline pattern, relocated above the strip */\\n.ss-w-ecard-scopes { display: flex; align-items: stretch; gap: 2px; padding: 0 11px; border-top: 1px solid var(--ss-w-line); flex-wrap: wrap; }\\n.ss-w-ecard-scope { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 7px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; }\\n.ss-w-ecard-scope[aria-selected=\\\"true\\\"] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-ecard-scope .ss-w-ecard-crest { width: 14px; height: 14px; }\\n.ss-w-ecard-scopes + .ss-w-ecard-strip { border-top: none; }\\n\\n.ss-w-ecard-crest { width: 15px; height: 15px; flex: none; display: block; border-radius: 4px; background-size: cover; background-position: center; }\\n.ss-w-ecard-season { flex: none; margin-left: auto; align-self: center; margin-bottom: 5px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n/* stat strip: 1px gap over a line-colored ground paints hairlines between cells, wrap-safe */\\n.ss-w-ecard-strip { display: grid; gap: 1px; background: var(--ss-w-line); border-top: 1px solid var(--ss-w-line); }\\n.ss-w-ecard-cell { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 4px; padding: 10px 4px 11px; background: var(--ss-w-panel); }\\n.ss-w-ecard-cval { height: 20px; display: flex; align-items: center; font-size: 17px; font-weight: 720; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }\\n.ss-w-ecard-cval .ss-w-form { width: 42px; }\\n.ss-w-ecard-clabel { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); font-weight: 600; font-variant-numeric: tabular-nums; }\\n\\n.ss-w-form { justify-self: end; display: flex; height: 6px; width: 48px; border-radius: 4px; overflow: hidden; gap: 2px; }\\n.ss-w-form span { display: block; border-radius: 2px; }\\n.ss-w-form-w { background: var(--ss-w-pos); }\\n.ss-w-form-d { background: var(--ss-w-faint); }\\n.ss-w-form-l { background: var(--ss-w-neg); }\\n\\n.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }\\n.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }\\n.ss-w-cards-more:disabled { opacity: .5; cursor: default; }\\n\\n/* betting insights */\\n.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 8px; }\\n\\n/* header, competition-hero fallback: comp on the left, live badge + kickoff + pin on the right,\\n   all on one line (used when there is no fixture, and by MarketOddsCardList) */\\n.ss-w-bi-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-bi-header-left { display: inline-flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); }\\n.ss-w-bi-header-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n/* two-tier header: a quiet meta line (competition + kickoff + match pin) stacked above the\\n   fixture, so long club names get the whole width to themselves and stop truncating (u350) */\\n.ss-w-bi-head { display: flex; flex-direction: column; gap: 6px; padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-bi-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-bi-meta-left { display: inline-flex; align-items: center; gap: 5px; min-width: 0; flex: 1; }\\n.ss-w-bi-meta-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }\\n.ss-w-bi-fixture-line { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-bi-comp { font-size: 10.5px; color: var(--ss-w-faint); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-kick { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); white-space: nowrap; flex: none; }\\n.ss-w-bi-live { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: #c0392b; border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; gap: 4px; flex: none; }\\n.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }\\n.ss-w-bi-floor { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; align-self: flex-start; flex: none; }\\n\\n/* crests -- CSS background-image on a span, never <img> (matches .ss-w-ecard-crest precedent) */\\n.ss-w-bi-comp-logo { width: 16px; height: 16px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest { width: 24px; height: 24px; flex: none; display: block; border-radius: 50%; object-fit: contain; }\\n.ss-w-bi-crest-mono { display: grid; place-items: center; font-size: 10px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n\\n/* fixture atoms -- crest-flanked team pair; shared by the insight fixture line and MarketOddsCardList */\\n.ss-w-bi-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-bi-vs { font-size: 10px; font-weight: 600; color: var(--ss-w-faint); flex: none; }\\n.ss-w-bi-fixture-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* shared crest-flanked team row (MarketOddsCardList); matches .ss-w-bi-fixture-line's hero weight\\n   so the fixture reads the same on both card types (u350) */\\n.ss-w-bi-fixture { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n\\n/* row 2, two-tier: the market label owns a full-width line above the pick row (selection grows\\n   left, odds + slip + pin sit right), so neither the market name nor the fixture clips (u350) */\\n.ss-w-bi-action { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-bi-market { font-size: 12px; font-weight: 600; line-height: 1.25; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-bi-pick-row { display: flex; align-items: center; gap: 9px; }\\n.ss-w-bi-sel { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; line-height: 1.2; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-bi-odds { flex: none; margin-left: auto; display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }\\n.ss-w-bi-odds b { font-size: 20px; font-family: ui-monospace, monospace; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.05; }\\n.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }\\n.ss-w-bi-pick-row .ss-w-slip { flex: none; }\\n\\n/* row 3: bar-chart glyph + reasoning prose, in a subtle strip */\\n.ss-w-bi-reason { display: flex; align-items: flex-start; gap: 8px; background: var(--ss-w-bubble); border-radius: 10px; padding: 8px 10px; }\\n.ss-w-bi-chart { flex: none; width: 13px; height: 12px; margin-top: 2px; opacity: .55;\\n  background:\\n    linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) left / 3px 55% no-repeat,\\n    linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) center / 3px 100% no-repeat,\\n    linear-gradient(var(--ss-w-accent), var(--ss-w-accent)) right / 3px 75% no-repeat;\\n  background-position: left bottom, center bottom, right bottom;\\n}\\n.ss-w-bi-text { flex: 1; min-width: 0; font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* market odds card */\\n.ss-w-mocards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-mocard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n/* Embedded inside the market accordion, which already provides the card frame + accent rail --\\n   drop the inner frame so odds rows aren't double-bordered. */\\n.ss-w-mocard--bare { border: none; border-radius: 0; padding: 0; background: none; }\\n.ss-w-mo-sub { display: flex; flex-direction: column; gap: 5px; min-width: 0; }\\n.ss-w-mo-teams { font-size: 13px; font-weight: 650; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-market-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-mo-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mo-tag { flex: none; font-size: 10.5px; font-weight: 700; line-height: 1.4; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, transparent); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }\\n.ss-w-mo-more { align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11.5px; font-weight: 600; padding: 2px 0; cursor: pointer; }\\n.ss-w-mo-more:hover { text-decoration: underline; }\\n.ss-w-mo-more-chev { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s ease; }\\n.ss-w-mo-more-chev-up { transform: translateY(1px) rotate(-135deg); }\\n.ss-w-mo-rows { display: flex; flex-direction: column; gap: 4px; }\\n/* Stage 4: live card score+minute in header (R18). */\\n.ss-w-bi-score { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); white-space: nowrap; }\\n.ss-w-bi-min { font-size: 11px; font-weight: 600; color: var(--ss-w-faint); white-space: nowrap; }\\n/* D12: closed state message row; D13: stale-price notice. */\\n.ss-w-mo-closed { padding: 6px 0; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-mo-stale { margin: 0; font-size: 11px; color: var(--ss-w-faint); }\\n/* The card's stat, in the Live tab accordion's insight style. No row below it is marked (R17). */\\n.ss-w-mo-stat { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-mo-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--ss-w-line); }\\n.ss-w-mo-row:last-child { border-bottom: none; }\\n.ss-w-mo-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); flex: 1; min-width: 0; }\\n.ss-w-mo-price { margin-left: auto; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--ss-w-accent); }\\n/* Movement: BOTH directions share --ss-w-faint on purpose. Green-good/red-bad would frame a\\n   shortening price as a discount, which inverts what it actually means for the bettor. */\\n.ss-w-move { display: inline-flex; align-items: baseline; gap: 4px; color: var(--ss-w-faint); }\\n.ss-w-move-prev { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 12px; text-decoration: line-through; }\\n.ss-w-move-arrow { font-size: 9px; line-height: 1; }\\n/* margin-left:auto is row layout, not badge styling -- it belongs to the market-odds row, which is\\n   a flex row, and must NOT follow the badge into the insight card's odds column. */\\n.ss-w-mo-row .ss-w-move { margin-left: auto; }\\n.ss-w-mo-row .ss-w-move + .ss-w-mo-price { margin-left: 0; }\\n.ss-w-mo-row .ss-w-slip { margin: 0; flex: none; }\\n.ss-w-mo-foot { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-allmk { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; padding: 6px 0; background: none; border: 0; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); white-space: nowrap; cursor: pointer; }\\n.ss-w-allmk svg { width: 13px; height: 13px; flex: none; }\\n.ss-w-allmk:hover { text-decoration: underline; }\\n.ss-w-allmk--chip { margin-left: 0; gap: 3px; height: 22px; padding: 0 6px; border: 1px solid var(--ss-w-line); border-radius: 11px; font-size: 11px; font-variant-numeric: tabular-nums; }\\n.ss-w-allmk--chip:hover { text-decoration: none; border-color: var(--ss-w-accent); }\\n\\n/* combo card (onboarding presets, spec C5): legs in kickoff order, then the server's\\n   multiplication line. Same card family as .ss-w-mocard / .ss-w-binsight. */\\n.ss-w-combos { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-combo { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 4px 11px 10px; display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-combo-legs { list-style: none; display: flex; flex-direction: column; }\\n.ss-w-combo-leg { display: flex; flex-direction: column; gap: 5px; padding: 8px 0; border-bottom: 1px dashed var(--ss-w-line); }\\n.ss-w-combo-leg:last-child { border-bottom: none; padding-bottom: 2px; }\\n.ss-w-combo-leg-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\\n.ss-w-combo-leg-pick { display: flex; align-items: center; gap: 9px; min-width: 0; }\\n.ss-w-combo-leg-what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\\n.ss-w-combo-leg-market { font-size: 11.5px; font-weight: 600; line-height: 1.25; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-combo-leg-sel { font-size: 13px; font-weight: 700; line-height: 1.2; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-combo-leg-price { flex: none; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 17px; font-weight: 800; line-height: 1.05; color: var(--ss-w-accent); }\\n.ss-w-combo-leg-pick .ss-w-slip { flex: none; }\\n.ss-w-combo-leg-stat { font-size: 12px; line-height: 1.45; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 9px; }\\n.ss-w-combo-math { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ss-w-ink); text-align: right; background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 8px 10px; overflow-wrap: anywhere; }\\n.ss-w-combo-note { font-size: 11px; line-height: 1.4; color: var(--ss-w-faint); }\\n.ss-w-combo-change { align-self: flex-start; min-height: 36px; padding: 6px 12px; font: inherit; font-size: 12px; font-weight: 650; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; cursor: pointer; }\\n.ss-w-combo-addall { flex-direction: column; align-items: stretch; gap: 6px; }\\n.ss-w-combo-addall .ss-w-slip-btn { min-height: 44px; padding: 10px 16px; font-size: 14px; font-weight: 650; border-radius: 22px; white-space: normal; }\\n.ss-w-combo-addall .ss-w-toast { position: static; width: auto; max-width: none; font-size: 12px; box-shadow: none; }\\n\\n/* onboarding presets stage 2: the two tools (spec Stage 2 Behaviour, boards 1c and 2c). A sheet\\n   over the message list, inside .ss-w-chat-layer; the body scrolls and the builder's Send sits in\\n   the footer, so it stays visible on a phone. Colours come from the theme tokens. */\\n.ss-w-tool-backdrop { position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column; justify-content: flex-end; background: rgba(0,0,0,.35); }\\n.ss-w-tool { display: flex; flex-direction: column; min-height: 0; max-height: 100%; background: var(--ss-w-panel); color: var(--ss-w-ink); border-top: 1px solid var(--ss-w-line); border-radius: 16px 16px 0 0; box-shadow: 0 -8px 24px rgba(0,0,0,.18); outline: none; }\\n.ss-w-tool-head { flex: none; display: flex; align-items: center; gap: 8px; padding: 12px 14px 8px; }\\n.ss-w-tool-title { flex: 1; font-size: 15px; font-weight: 700; line-height: 1.3; }\\n.ss-w-tool-close { flex: none; width: 36px; height: 36px; display: grid; place-items: center; font-size: 16px; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: none; border-radius: 50%; cursor: pointer; }\\n.ss-w-tool-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 12px; padding: 4px 14px 14px; }\\n.ss-w-tool-body > * { flex: none; }\\n.ss-w-tool-foot { flex: none; padding: 10px 14px 12px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-tool-row { display: flex; flex-direction: column; gap: 8px; padding: 10px 11px; border: 1px solid var(--ss-w-line); border-left: 3px solid var(--ss-w-accent); border-radius: 12px; }\\n.ss-w-tool-ask { font-size: 14px; font-weight: 650; line-height: 1.7; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-tool-num { position: relative; display: inline-block; vertical-align: middle; margin: 0 2px; font-variant-numeric: tabular-nums; font-weight: 800; color: var(--ss-w-accent); }\\n.ss-w-tool-num-size { display: block; font-size: max(16px, 1em); user-select: none; -webkit-user-select: none; visibility: hidden; box-sizing: border-box; min-width: 44px; min-height: 32px; padding: 6px 26px 6px 10px; line-height: 1.3; white-space: pre; }\\n.ss-w-tool-num-select { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0 22px 0 10px; font: inherit; font-size: max(16px, 1em); font-variant-numeric: tabular-nums; font-weight: 800; color: var(--ss-w-accent); background-color: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); border: 1.5px solid color-mix(in srgb, var(--ss-w-accent) 65%, var(--ss-w-line)); border-radius: 8px; cursor: pointer; appearance: none; -webkit-appearance: none; }\\n.ss-w-tool-num::after { content: \\\"\\\"; position: absolute; right: 9px; top: 50%; width: 5px; height: 5px; margin-top: -4px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); pointer-events: none; }\\n.ss-w-tool-num-select:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-tool-num-select option { font-weight: 600; color: var(--ss-w-ink); background: var(--ss-w-panel); }\\n.ss-w-tool-num-select option:disabled { color: var(--ss-w-faint); }\\n.ss-w-tool-picks { list-style: none; display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-tool-pick { display: grid; grid-template-columns: 1fr auto; column-gap: 8px; padding: 5px 8px; font-size: 12px; line-height: 1.35; background: var(--ss-w-bubble); border-radius: 8px; }\\n.ss-w-tool-pick-match { grid-column: 1; font-weight: 650; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-tool-pick-sel { grid-column: 1; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-tool-pick-kick { grid-column: 1; font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-tool-pick-price { grid-column: 2; grid-row: 1 / span 3; align-self: center; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 800; color: var(--ss-w-accent); }\\n.ss-w-tool-math { padding: 6px 8px; font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; text-align: right; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; overflow-wrap: anywhere; }\\n.ss-w-tool-unavailable { padding: 6px 8px; font-size: 12px; color: var(--ss-w-faint); border: 1px dashed var(--ss-w-line); border-radius: 8px; }\\n.ss-w-tool-row--ask { flex-direction: row; align-items: center; gap: 10px; border-left-width: 1px; }\\n.ss-w-tool-icon { flex: none; font-size: 20px; line-height: 1; }\\n.ss-w-tool-main { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }\\n.ss-w-tool-ready { padding: 2px 8px; font-size: 11.5px; font-weight: 650; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 12%, transparent); border-radius: 10px; }\\n.ss-w-tool-go { flex: none; width: 44px; height: 44px; display: grid; place-items: center; font-size: 17px; color: #fff; background: var(--ss-w-accent); border: none; border-radius: 50%; cursor: pointer; }\\n.ss-w-tool-go:disabled { color: var(--ss-w-faint); background: var(--ss-w-bubble); cursor: not-allowed; }\\n.ss-w-tool-go:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-tool-send { align-self: flex-end; min-height: 40px; padding: 8px 18px; font: inherit; font-size: 13px; font-weight: 700; color: #fff; background: var(--ss-w-accent); border: none; border-radius: 20px; cursor: pointer; }\\n.ss-w-tool-send:disabled { color: var(--ss-w-faint); background: var(--ss-w-bubble); cursor: not-allowed; }\\n.ss-w-tool-foot .ss-w-tool-send { width: 100%; }\\n.ss-w-tool-section { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-tool-label { font-size: 11.5px; font-weight: 650; color: var(--ss-w-faint); }\\n.ss-w-tool-chips { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-tool-chip { min-width: 52px; min-height: 36px; padding: 6px 10px; font: inherit; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ss-w-ink); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 18px; cursor: pointer; }\\n.ss-w-tool-chip[aria-pressed=\\\"true\\\"] { color: #fff; background: var(--ss-w-accent); border-color: var(--ss-w-accent); }\\n.ss-w-tool-stepper { display: inline-flex; align-items: center; gap: 10px; }\\n.ss-w-tool-step { width: 40px; height: 40px; display: grid; place-items: center; font: inherit; font-size: 18px; font-weight: 700; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 50%; cursor: pointer; }\\n.ss-w-tool-step:disabled { opacity: .5; cursor: not-allowed; }\\n.ss-w-tool-count { min-width: 24px; text-align: center; font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }\\n\\n/* onboarding presets stage 2: the chat layer and the speed dial (spec Stage 2 Behaviour). The\\n   layer is the message list's positioned box (P6), so the dial sits against the list's bottom\\n   right and rises with the composer: right 8px puts the 44px button's centre on Send's (12px\\n   padding + 18px), bottom 10px is above the composer's top border. While the button shows the list\\n   gets 54px more bottom padding so its last message can scroll clear. */\\n.ss-w-chat-layer { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }\\n.ss-w-chat-layer[data-dial] .ss-w-list { padding-bottom: 68px; }\\n.ss-w-dial { position: absolute; left: 12px; right: 8px; bottom: 10px; z-index: 2; display: flex; flex-direction: column-reverse; align-items: flex-end; gap: 8px; pointer-events: none; }\\n.ss-w-dial-btn, .ss-w-dial-pill { pointer-events: auto; }\\n.ss-w-dial-btn { position: relative; flex: none; width: 44px; height: 44px; display: grid; place-items: center; padding: 0; font-size: 20px; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 40%, var(--ss-w-line)); border-radius: 50%; box-shadow: 0 4px 14px rgba(0,0,0,.18); cursor: pointer; }\\n.ss-w-dial-btn[aria-expanded=\\\"true\\\"] { color: var(--ss-w-panel); background: var(--ss-w-accent); border-color: var(--ss-w-accent); }\\n.ss-w-dial-btn:focus-visible, .ss-w-dial-pill:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-dial-icon { grid-area: 1 / 1; display: grid; place-items: center; transition: transform 200ms ease, opacity 200ms ease; }\\n.ss-w-dial-icon--close { opacity: 0; transform: rotate(-90deg); }\\n.ss-w-dial-btn[aria-expanded=\\\"true\\\"] .ss-w-dial-icon--open { opacity: 0; transform: rotate(90deg); }\\n.ss-w-dial-btn[aria-expanded=\\\"true\\\"] .ss-w-dial-icon--close { opacity: 1; transform: none; }\\n.ss-w-dial-dot { position: absolute; top: 3px; right: 3px; width: 10px; height: 10px; background: var(--ss-w-accent); border: 2px solid var(--ss-w-panel); border-radius: 50%; }\\n.ss-w-dial-pills { max-width: 100%; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }\\n.ss-w-dial-pill { max-width: 100%; min-height: 44px; display: inline-flex; align-items: center; gap: 8px; padding: 6px 16px 6px 12px; font: inherit; font-size: 12.5px; font-weight: 650; line-height: 1.25; text-align: left; white-space: normal; overflow-wrap: anywhere; color: var(--ss-w-ink); background: var(--ss-w-panel); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 35%, var(--ss-w-line)); border-radius: 22px; box-shadow: 0 4px 14px rgba(0,0,0,.16); cursor: pointer; opacity: 0; visibility: hidden; transform: translateY(14px) scale(.5); transform-origin: bottom right; transition: opacity 200ms ease, transform 200ms ease, visibility 0s linear 200ms; }\\n.ss-w-dial-pill svg { flex: none; font-size: 18px; color: var(--ss-w-accent); }\\n.ss-w-dial-pill-label { min-width: 0; }\\n.ss-w-dial-pills[data-open] .ss-w-dial-pill { opacity: 1; visibility: visible; transform: none; transition: opacity 200ms ease, transform 200ms ease, visibility 0s; }\\n@media (prefers-reduced-motion: reduce) {\\n  .ss-w-dial-pill { transform: none; transition: opacity 200ms ease, visibility 0s linear 200ms; }\\n  .ss-w-dial-pills[data-open] .ss-w-dial-pill { transition: opacity 200ms ease, visibility 0s; }\\n  .ss-w-dial-icon { transition: opacity 200ms ease; }\\n  .ss-w-dial-icon--close, .ss-w-dial-btn[aria-expanded=\\\"true\\\"] .ss-w-dial-icon--open { transform: none; }\\n}\\n\\n/* Compact price list (D16): three or more cards of one turn, one row per fixture. Team names wrap\\n   to a second line and are never cut; the time sits above the match pin, with no column of its own. */\\n.ss-w-mol { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-mol-head, .ss-w-mol-row { display: grid; grid-template-columns: minmax(0, 1fr) 126px 46px; align-items: center; gap: 4px; }\\n.ss-w-mol-market { font-size: 11.5px; font-weight: 600; color: var(--ss-w-faint); min-width: 0; overflow-wrap: anywhere; }\\n.ss-w-mol-cols, .ss-w-mol-cells { display: grid; gap: 4px; }\\n.ss-w-mol-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); text-align: center; overflow-wrap: break-word; min-width: 0; }\\n.ss-w-mol-comp { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding-top: 4px; }\\n.ss-w-mol-row { padding: 6px 0; border-bottom: 1px dashed var(--ss-w-line); min-height: 48px; box-sizing: border-box; }\\n.ss-w-mol-row:focus { outline: none; }\\n.ss-w-mol-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; border-radius: 6px; }\\n.ss-w-mol-tick { font-family: inherit; font-size: 9.5px; font-weight: 700; line-height: 1.1; }\\n.ss-w-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }\\n.ss-w-mol-group .ss-w-mol-row:last-child { border-bottom: none; }\\n.ss-w-mol-fx { display: flex; flex-direction: column; gap: 3px; min-width: 0; background: none; border: none; padding: 0; text-align: left; font: inherit; color: inherit; }\\n.ss-w-mol-team { display: flex; align-items: center; gap: 5px; min-width: 0; }\\n.ss-w-mol-team > * { flex: none; }\\n.ss-w-mol-team > .ss-w-mol-nm { flex: 1 1 auto; }\\n.ss-w-mol-nm { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); overflow-wrap: break-word; hyphens: manual; line-height: 1.2; min-width: 0; }\\n.ss-w-mol-mkt { font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-mol-cells { align-items: start; }\\n.ss-w-mol-cell { display: flex; flex-direction: column; align-items: stretch; gap: 2px; min-width: 0; }\\n.ss-w-mol-cell > .ss-w-mol-price { flex: none; }\\n.ss-w-mol-cell .ss-w-move { justify-content: center; gap: 2px; }\\n.ss-w-mol-cell .ss-w-move-prev { font-family: inherit; font-variant-numeric: tabular-nums; font-size: 10px; }\\n/* A 39 px cell fits four characters at 13 px: five step down to 11.5 px and six to 10.5 px. */\\n.ss-w-mol-cell--wide .ss-w-mol-price, .ss-w-mol-cell--wide .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 11.5px; }\\n.ss-w-mol-cell--wider .ss-w-mol-price, .ss-w-mol-cell--wider .ss-w-slip-btn.ss-w-slip-btn--price { font-size: 10.5px; }\\n.ss-w-mol-cell .ss-w-slip { margin: 0; flex: none; min-width: 0; }\\n.ss-w-mol-price, .ss-w-slip-btn--price { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 5px 0; border-radius: 8px; border: 1px solid var(--ss-w-line); background: var(--ss-w-panel); font-family: inherit; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-slip-btn.ss-w-slip-btn--price { width: 100%; cursor: pointer; background: var(--ss-w-panel); color: var(--ss-w-accent); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 5px 0; font-size: 13px; font-weight: 700; box-shadow: none; }\\n.ss-w-slip-btn--price:hover:not(:disabled) { border-color: var(--ss-w-accent); }\\n.ss-w-slip-btn--price[data-settled] { color: var(--ss-w-faint); }\\n.ss-w-mol-lab { font-family: inherit; font-size: 9.5px; font-weight: 600; color: var(--ss-w-faint); line-height: 1.1; text-align: center; overflow-wrap: anywhere; }\\n.ss-w-mol-side { display: flex; flex-direction: column; align-items: center; gap: 4px; }\\n.ss-w-mol-when { font-size: 9.5px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; text-align: center; line-height: 1.15; }\\n.ss-w-mol-side--live .ss-w-mol-when { color: var(--ss-w-neg); }\\n\\n/* odds movement card */\\n.ss-w-omcards { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-omcard { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-om-head { display: flex; align-items: center; gap: 8px; }\\n.ss-w-om-market { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-om-tag { margin-left: auto; flex: none; font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 2px 7px; }\\n.ss-w-om-fixture { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ss-w-faint); min-width: 0; }\\n.ss-w-om-comp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-om-sel { font-size: 12.5px; font-weight: 600; color: var(--ss-w-ink); }\\n.ss-w-om-chart { display: block; width: 100%; height: auto; }\\n/* Single neutral accent in BOTH directions, deliberately. Colouring a shortening price green\\n   frames it as a discount, which inverts what it means for the bettor -- the same reason\\n   .ss-w-move keeps both directions on --ss-w-faint. */\\n.ss-w-om-line { stroke: var(--ss-w-accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }\\n.ss-w-om-dot { fill: var(--ss-w-accent); }\\n.ss-w-om-grid { stroke: var(--ss-w-line); stroke-width: 1; }\\n.ss-w-om-ylab, .ss-w-om-xlab { fill: var(--ss-w-faint); font-size: 9px; font-family: ui-monospace, monospace; }\\n.ss-w-om-empty { font-size: 11.5px; color: var(--ss-w-faint); padding: 6px 0; }\\n.ss-w-om-foot { display: flex; align-items: center; gap: 14px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-om-foot b { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; color: var(--ss-w-ink); }\\n.ss-w-om-excl { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-om-susp { font-size: 11px; font-weight: 600; color: #c0392b; }\\n.ss-w-om-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\\n\\n/* action buttons */\\n.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\\n/* text-align is explicit because a <button> defaults to center, and a follow-up question long\\n   enough to wrap then sets its second line ragged on both sides. */\\n.ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; text-align: left; }\\n.ss-w-abtn:disabled { opacity: .5; cursor: default; }\\n.ss-w-abtn-shimmer { width: 140px; height: 30px; border-radius: 16px; background: linear-gradient(90deg, var(--ss-w-bubble), var(--ss-w-line), var(--ss-w-bubble)); background-size: 200% 100%; animation: ss-w-shimmer 1.2s infinite; }\\n@keyframes ss-w-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }\\n\\n/* intent chips */\\n.ss-w-chips { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-chip { font-size: 11.5px; font-weight: 550; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 5px 11px; cursor: pointer; }\\n\\n/* input */\\n.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-limit { padding: 10px 12px; border-top: 1px solid var(--ss-w-line); font-size: 13px; line-height: 1.4; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-limit:empty { padding: 0; border-top: 0; }\\n.ss-w-limit:focus { outline: none; }\\n.ss-w-limit:not(:empty) + .ss-w-input { border-top: none; }\\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-send:disabled { opacity: .45; cursor: not-allowed; }\\n.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }\\n\\n/* add to slip */\\n.ss-w-slip { position: relative; display: flex; }\\n.ss-w-slip-btn { font-size: 11.5px; font-weight: 620; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); border: 1px solid var(--ss-w-cta); border-radius: 14px; padding: 5px 12px; cursor: pointer; white-space: nowrap; }\\n.ss-w-slip-btn:disabled { opacity: .6; cursor: default; background: var(--ss-w-bubble); color: var(--ss-w-faint); border-color: var(--ss-w-line); }\\n/* Anchored to the RIGHT of its (narrow) button wrapper and sized by content, growing leftward\\n   into the card -- inheriting the wrapper's width squeezes the text to one character per line.\\n   Every toast site (slip buttons, pin toggles) sits at the right edge of its row. */\\n.ss-w-toast { position: absolute; top: calc(100% + 6px); right: 0; z-index: 1; width: max-content; max-width: 210px; font-size: 11px; font-weight: 560; border-radius: 10px; padding: 5px 10px; overflow-wrap: anywhere; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n.ss-w-toast-success { color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); }\\n.ss-w-toast-error { color: #c0392b; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); }\\n\\n/* pin affordance */\\n.ss-w-pin-wrap { position: relative; display: inline-flex; flex: none; }\\n.ss-w-pin { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-pin svg { width: 12px; height: 12px; }\\n.ss-w-pin:hover { color: var(--ss-w-ink); border-color: var(--ss-w-faint); }\\n.ss-w-pin[data-on] { background: var(--ss-w-accent); border-color: var(--ss-w-accent); color: #fff; }\\n.ss-w-pin[data-on]:hover { background: var(--ss-w-accent); color: #fff; }\\n.ss-w-hist { flex: none; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border-radius: 50%; background: none; border: 1px solid var(--ss-w-line); color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-hist svg { width: 12px; height: 12px; }\\n.ss-w-hist:hover { color: var(--ss-w-accent); border-color: var(--ss-w-accent); }\\n\\n@media (prefers-reduced-motion: reduce) {\\n  .ss-w-abtn-shimmer { animation: none; }\\n}\\n\\n/* greeting dashboard */\\n.ss-w-dash { display: flex; flex-direction: column; gap: 12px; padding: 4px 0; }\\n.ss-w-dash-head { display: flex; flex-direction: column; }\\n.ss-w-dash-title { font-size: 18px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); }\\n.ss-w-dash-subtitle { font-size: 13px; color: var(--ss-w-faint); margin-top: 4px; }\\n.ss-w-dash-foot { font-size: 11px; color: var(--ss-w-faint); margin-top: 2px; }\\n\\n.ss-w-dash-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-dash-tile--half { grid-column: span 1; }\\n.ss-w-dash-tile--full { grid-column: 1 / -1; }\\n\\n.ss-w-dash-tile {\\n  display: flex; align-items: center; gap: 10px;\\n  padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n  background: var(--ss-w-panel); text-align: left; cursor: pointer; width: 100%;\\n  color: inherit; font: inherit;\\n  min-width: 0;                      /* the panel is min(400px, 100vw - 40px): without this,\\n                                        a long Turkish title blows the column out */\\n}\\n.ss-w-dash-tile-icon { flex: none; display: grid; place-items: center; width: 28px; height: 28px; font-size: 22px; }\\n.ss-w-dash-emoji { line-height: 1; }\\n.ss-w-dash-tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; }\\n.ss-w-dash-tile-title { min-width: 0; font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }\\n.ss-w-dash-tile-subtitle { min-width: 0; font-size: 11.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-tile-chevron { flex: none; margin-left: auto; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n\\n/* Badge + crests share their own row, below the title -- NOT the icon/chevron row. A\\n   nowrap badge (~70px) sitting beside icon+chevron in a ~180px half-span tile left the\\n   title column at ~22px wide, wrapping every title character-by-character. Here the row\\n   gets the body's full width, so a badge this size is comfortably inside it. */\\n.ss-w-dash-tile-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }\\n.ss-w-dash-tile-badge { flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 9px; white-space: nowrap; }\\n\\n.ss-w-dash-tile-crests { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-tile-crest {\\n  width: 18px; height: 18px; border-radius: 50%;\\n  background-size: cover; background-position: center; background-color: var(--ss-w-bubble);\\n  margin-left: -6px; border: 2px solid var(--ss-w-panel);    /* overlapping stack, capped at 3 in DashboardTile */\\n}\\n.ss-w-dash-tile-crest:first-child { margin-left: 0; }\\n\\n/* Market: default 2-column grid, tiles get the same accent rail as the other card\\n   families (.ss-w-binsight, .ss-w-mocard, .ss-w-omcard) so a market tile reads as\\n   part of that visual language rather than a plain unstyled button. */\\n.ss-w-dash--market .ss-w-dash-tile { border-left: 3px solid var(--ss-w-accent); }\\n\\n/* Goal: one column of compact cards, 60px tall with the badge as a price column on the right.\\n   The value ink is accent mixed toward ink (as on the hero price): plain light accent on the\\n   panel is 3.9:1, under the 4.5:1 small text needs. */\\n.ss-w-dash--goal .ss-w-dash-grid { grid-template-columns: 1fr; }\\n.ss-w-dash--goal .ss-w-dash-tile { gap: 12px; min-height: 60px; padding: 8px 12px 8px 14px; border-radius: 8px; }\\n.ss-w-dash--goal .ss-w-dash-tile:hover { background: var(--ss-w-bubble); }\\n.ss-w-dash--goal .ss-w-dash-tile-icon { width: 24px; height: 24px; font-size: 20px; }\\n.ss-w-dash--goal .ss-w-dash-tile-body { gap: 1px; }\\n.ss-w-dash--goal .ss-w-dash-tile-title { font-size: 15px; line-height: 1.25; }\\n.ss-w-dash--goal .ss-w-dash-tile-subtitle { font-size: 13px; line-height: 1.3; overflow-wrap: break-word; }\\n.ss-w-dash-tile-value {\\n  flex: none; margin-left: auto; max-width: 40%; text-align: right;\\n  font-size: 16px; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums;\\n  color: color-mix(in srgb, var(--ss-w-accent) 70%, var(--ss-w-ink));\\n}\\n\\n/* Discovery: tinted bento cards. Stacked (icon over text) so a two- or three-word title gets\\n   the tile's full width instead of the ~100px left of a horizontal icon+chevron -- that narrow\\n   column was wrapping \\\"Most interesting angles\\\" onto three lines. The chevron is dropped (the\\n   whole card is the tap target) and the badge + crest row is forced onto one line. */\\n.ss-w-dash--discovery .ss-w-dash-tile { flex-direction: column; align-items: stretch; gap: 8px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-icon { align-self: flex-start; width: 32px; height: 32px; font-size: 26px; }\\n.ss-w-dash--discovery .ss-w-dash-tile-chevron { display: none; }\\n/* The full-span trends tile has the whole panel width, so its icon and title sit on one row\\n   (horizontal, centre-aligned) rather than stacking like the narrow half tiles. */\\n.ss-w-dash--discovery .ss-w-dash-tile--full { flex-direction: row; align-items: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile--full .ss-w-dash-tile-icon { align-self: center; }\\n.ss-w-dash--discovery .ss-w-dash-tile-meta { flex-wrap: nowrap; }\\n.ss-w-dash--discovery .ss-w-dash-tile-crest { width: 22px; height: 22px; }\\n/* Tints mix a hue into the live panel rather than hardcoding a light pastel, so a dark\\n   operator surface (e.g. --ss-w-panel set from a navy `surface` brand color) yields a\\n   readable tinted-dark card instead of near-white ink on a fixed light pastel. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n/* A hero tile would take the first tint position; count only regular tiles where `of S` parses. */\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(1 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #34c759 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(2 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #3a82f6 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(3 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #f5a623 10%, var(--ss-w-panel)); }\\n.ss-w-dash--discovery .ss-w-dash-tile:nth-child(4 of :not(.ss-w-dash-hero)) { background: color-mix(in srgb, #a855f7 10%, var(--ss-w-panel)); }\\n\\n/* Hero: the personalized lead tile. Declared after the layout rules and at three-class\\n   specificity so it keeps one look in every layout -- no market rail, no goal pill, no\\n   discovery tint or stacking. Colours derive from accent/panel/ink so an operator surface\\n   and dark mode both work without their own rules. */\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero {\\n  display: flex; flex-direction: column; align-items: stretch; gap: 10px;\\n  padding: 12px 14px 14px; border-radius: 16px;\\n  border: 1px solid color-mix(in srgb, var(--ss-w-accent) 38%, var(--ss-w-line));\\n  background:\\n    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--ss-w-accent) 18%, transparent) 0%, transparent 60%),\\n    var(--ss-w-panel);\\n  box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--ss-w-accent) 80%, transparent);\\n}\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:hover { border-color: var(--ss-w-accent); }\\n.ss-w-dash .ss-w-dash-grid .ss-w-dash-hero:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-dash-hero-top { display: flex; align-items: center; gap: 8px; min-height: 20px; }\\n.ss-w-dash-hero-badge {\\n  font-size: 10.5px; font-weight: 750; letter-spacing: .06em; text-transform: uppercase;\\n  color: var(--ss-w-panel); background: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); border-radius: 999px; padding: 3px 10px;\\n  white-space: nowrap;\\n}\\n.ss-w-dash-hero-chevron { flex: none; width: 14px; height: 14px; color: var(--ss-w-faint); }\\n.ss-w-dash-hero-badge { margin-right: auto; }\\n.ss-w-dash-hero-chevron:only-child { margin-left: auto; }\\n.ss-w-dash-hero-main { display: flex; align-items: center; gap: 12px; min-width: 0; }\\n.ss-w-dash-hero-visual { flex: none; display: flex; align-items: center; }\\n.ss-w-dash-hero-crest {\\n  width: 40px; height: 40px; border-radius: 50%;\\n  background-color: color-mix(in srgb, var(--ss-w-ink) 4%, var(--ss-w-panel));\\n  background-size: 72%; background-position: center; background-repeat: no-repeat;\\n  box-shadow: 0 0 0 2px var(--ss-w-panel), 0 0 0 3px color-mix(in srgb, var(--ss-w-ink) 10%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-crest + .ss-w-dash-hero-crest { margin-left: -8px; }\\n.ss-w-dash-hero-icon {\\n  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; font-size: 22px;\\n  background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel));\\n}\\n.ss-w-dash-hero-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }\\n.ss-w-dash-hero-title { font-size: 15.5px; font-weight: 700; line-height: 1.25; color: var(--ss-w-ink); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-subtitle { font-size: 12px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-dash-hero-price {\\n  flex: none; margin-left: auto;\\n  font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 15px; font-weight: 750; line-height: 1;\\n  color: color-mix(in srgb, var(--ss-w-accent) 45%, var(--ss-w-ink)); padding: 5px 9px; border-radius: 8px;\\n  background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel));\\n  border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-panel));\\n}\\n\\n/* club fan pre-match dashboard */\\n.ss-w-fandash { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }\\n.ss-w-fandash-greeting { font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ss-w-ink); }\\n.ss-w-fandash-greeting--lead { font-weight: 400; }\\n.ss-w-fandash-cards { display: flex; flex-direction: column; gap: 8px; }\\n\\n/* Shared card chrome -- a plain <div> for [data] cards, a <button> for [prefill] cards. Both\\n   share the same box so the two families read as one system, not two ad hoc layouts. */\\n.ss-w-fandash-card {\\n  display: flex; flex-direction: column; gap: 8px;\\n  padding: 12px; border-radius: 14px; border: 1px solid var(--ss-w-line);\\n  background: var(--ss-w-panel); text-align: left;\\n  color: inherit; font: inherit; width: 100%; min-width: 0;\\n}\\n.ss-w-fandash-card--tap { cursor: pointer; border-left: 3px solid var(--ss-w-accent); }\\n.ss-w-fandash-card--tap:hover { background: var(--ss-w-bubble); }\\n.ss-w-fandash-card-cta { align-self: flex-start; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); }\\n\\n/* Shared alignment primitives: a small letterspaced section eyebrow, and a 3-column value/label\\n   split reused by the fixture head-to-head (and any future stat-row card). */\\n.ss-w-fandash-eyebrow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); }\\n.ss-w-fandash-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-split-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; min-width: 0; }\\n.ss-w-fandash-split-value { font-size: 20px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); line-height: 1; }\\n.ss-w-fandash-split-label { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n\\n/* fixture card */\\n.ss-w-fandash-fixture-teams { display: flex; align-items: center; gap: 10px; }\\n.ss-w-fandash-fixture-team { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }\\n.ss-w-fandash-fixture-team--away { justify-content: flex-end; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest { width: 30px; height: 30px; }\\n.ss-w-fandash-fixture-team .ss-w-bi-crest-mono { font-size: 12px; }\\n.ss-w-fandash-fixture-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-fixture-team--away .ss-w-fandash-fixture-name { text-align: right; }\\n.ss-w-fandash-fixture-vs { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n/* date + venue as labelled rows, so a long stadium name gets its own line to ellipsis in */\\n.ss-w-fandash-fixture-meta { border-top: 1px solid var(--ss-w-line); padding-top: 10px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-fixture-kickoff { font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-fixture-venue { font-weight: 600; }\\n.ss-w-fandash-fact { font-size: 12px; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 8px; padding: 6px 8px; }\\n/* each head-to-head figure sits on its own shaded tile, so the grid gap separates wins/draws/losses */\\n.ss-w-fandash-h2h .ss-w-fandash-split-cell { background: var(--ss-w-bubble); border-radius: 10px; padding: 12px 6px; }\\n/* extra breathing room between the tally row and the fact beyond the card's own gap */\\n.ss-w-fandash-h2h .ss-w-fandash-fact { margin-top: 4px; }\\n\\n/* Team form: a two-column result-card grid, left = home team's last 5, right = away team's last 5,\\n   most-recent first. The head row carries each column's crest + name; the rows grid is filled\\n   home-cell/away-cell per index so the 2-col grid lays out pairs without extra JS bookkeeping. */\\n.ss-w-fandash-teamform-head { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }\\n.ss-w-fandash-teamform-head-team { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11.5px; font-weight: 750; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-teamform-head-team .ss-w-bi-crest-mono { font-size: 8px; }\\n.ss-w-fandash-teamform-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-teamform-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 6px; }\\n.ss-w-fandash-teamform-slot { display: block; min-width: 0; }\\n.ss-w-fandash-teamform-cell {\\n  display: flex; align-items: center; gap: 4px; border-radius: 7px; padding: 4px 5px; color: #fff;\\n}\\n.ss-w-fandash-teamform-cell--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-teamform-cell--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-teamform-cell--draw { background: var(--ss-w-faint); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest { width: 16px; height: 16px; flex: none; background: rgba(255, 255, 255, .22); }\\n.ss-w-fandash-teamform-cell .ss-w-bi-crest-mono { font-size: 7px; color: #fff; }\\n.ss-w-fandash-teamform-score { flex: 1; text-align: center; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; }\\n.ss-w-fandash-injuries-more { margin-top: 10px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-injuries-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n.ss-w-fandash-form { display: inline-flex; gap: 3px; flex: none; }\\n.ss-w-fandash-form-pill {\\n  display: inline-grid; place-items: center; width: 16px; height: 16px;\\n  border-radius: 4px; font-size: 9.5px; font-weight: 700; color: #fff;\\n}\\n.ss-w-fandash-form-pill--win { background: var(--ss-w-pos); }\\n.ss-w-fandash-form-pill--loss { background: var(--ss-w-neg); }\\n.ss-w-fandash-form-pill--draw { background: var(--ss-w-faint); }\\n\\n/* countdown card: a compact top card -- section eyebrow left, colon-separated clock right. Each\\n   segment stacks its figure over a small unit label (d/h/m/s). The exact kickoff date is not\\n   repeated here; the fixture card below carries it. */\\n.ss-w-fandash-countdown-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-countdown-clock { display: inline-flex; align-items: flex-start; gap: 6px; color: var(--ss-w-accent); }\\n.ss-w-fandash-countdown-seg { display: inline-flex; flex-direction: column; align-items: center; }\\n.ss-w-fandash-countdown-value { font-size: 26px; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -.01em; }\\n.ss-w-fandash-countdown-unit { font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ss-w-faint); margin-top: 3px; }\\n.ss-w-fandash-countdown-colon { font-size: 22px; font-weight: 750; line-height: 1; color: var(--ss-w-faint); }\\n\\n/* injuries + transfers: two-column ours/theirs, in/out */\\n.ss-w-fandash-transfers-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n/* injuries: a 1px divider column sits between the two team sections, each headed by crest + name */\\n.ss-w-fandash-injuries-cols { display: grid; grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1fr); gap: 12px; }\\n.ss-w-fandash-injuries-divider { background: var(--ss-w-line); }\\n.ss-w-fandash-injuries-col, .ss-w-fandash-transfers-col { min-width: 0; display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-transfers-col-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n.ss-w-fandash-injuries-col-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest { width: 18px; height: 18px; }\\n.ss-w-fandash-injuries-col-head .ss-w-bi-crest-mono { font-size: 9px; }\\n.ss-w-fandash-injuries-col-head-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-injuries-empty, .ss-w-fandash-transfers-empty { font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-list, .ss-w-fandash-transfer-list { list-style: none; display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-fandash-injury-row, .ss-w-fandash-transfer-row { display: flex; flex-direction: column; gap: 1px; }\\n.ss-w-fandash-injury-name, .ss-w-fandash-transfer-name { font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }\\n.ss-w-fandash-injury-meta { display: flex; flex-wrap: wrap; gap: 4px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-injury-status { font-weight: 700; color: var(--ss-w-neg); }\\n.ss-w-fandash-transfer-club { font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-transfer-type { align-self: flex-start; font-size: 9.5px; font-weight: 700; text-transform: uppercase; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 13%, var(--ss-w-panel)); border-radius: 999px; padding: 1px 7px; margin-top: 2px; }\\n\\n/* reason-to-bet */\\n.ss-w-fandash-reason-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-reason-item { font-size: 12.5px; padding-left: 14px; position: relative; }\\n.ss-w-fandash-reason-item::before { content: \\\"•\\\"; position: absolute; left: 0; color: var(--ss-w-accent); font-weight: 700; }\\n\\n/* where-to-watch */\\n.ss-w-fandash-stations { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-w-fandash-station-chip { font-size: 11.5px; font-weight: 600; color: var(--ss-w-ink); background: var(--ss-w-bubble); border-radius: 999px; padding: 4px 10px; }\\n\\n/* congested week: a fixed 3-column grid of upcoming fixtures (day / opponent / comp / time) */\\n.ss-w-fandash-congested-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-congested-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 8px; border-radius: 10px; background: var(--ss-w-bubble); }\\n.ss-w-fandash-congested-day { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ss-w-faint); }\\n.ss-w-fandash-congested-opponent { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-comp { font-size: 10px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-congested-time { font-size: 10.5px; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n\\n/* links: 2-column grid of tappable tiles */\\n.ss-w-fandash-link-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-fandash-link-tile { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 11px 13px; border-radius: 10px; border: 1px solid transparent; text-decoration: none; color: inherit; background: color-mix(in srgb, var(--ss-w-accent) 10%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-tile:hover { background: color-mix(in srgb, var(--ss-w-accent) 16%, var(--ss-w-panel)); }\\n.ss-w-fandash-link-label { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }\\n.ss-w-fandash-link-chevron { flex: none; width: 12px; height: 12px; color: var(--ss-w-accent); }\\n\\n/* post-match result: full-time scoreboard, mirroring the live card's crest + big-score treatment.\\n   A neutral \\\"Full time\\\" pill sits left of a coloured Win/Draw/Loss tag; the 3-column main row\\n   (home crest+name | score | away crest+name, away reversed) puts the winner's score in full ink\\n   and the loser's dimmed; a centered meta line sits under a divider. */\\n.ss-w-fandash-postmatch-top { display: flex; align-items: center; gap: 8px; margin-bottom: 15px; }\\n.ss-w-fandash-postmatch-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-postmatch-tag { margin-left: auto; flex: none; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-postmatch-tag--win { color: var(--ss-w-pos); }\\n.ss-w-fandash-postmatch-tag--loss { color: var(--ss-w-neg); }\\n.ss-w-fandash-postmatch-tag--draw { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-postmatch-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-postmatch-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-postmatch-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-crest--fallback.ss-w-fandash-postmatch-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-postmatch-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; }\\n.ss-w-fandash-postmatch-score-value--win { color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-score-value--lose { color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-postmatch-meta { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--ss-w-line); font-size: 12px; color: var(--ss-w-faint); text-align: center; }\\n\\n/* post-match goals: a football-ball icon per goal (mirrors the live timeline ball, duplicated here\\n   under the postmatch prefix), text dimmed for opponent goals and picked out in full ink + bold\\n   for the club's own goals */\\n.ss-w-fandash-postmatch-goal-list { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-postmatch-goal { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-goal-ball { width: 11px; height: 11px; flex: none; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-goal--club { color: var(--ss-w-ink); font-weight: 650; }\\n\\n/* post-match stats: home value / stat label / away value, oriented by venue (u316), each row now\\n   backed by a home/away split bar -- the big upgrade from plain text -- plus a legend. Mirrors\\n   LiveStatsCard's split-bar treatment under the postmatch-prefixed classes; the shared\\n   --ss-w-home/--ss-w-away/--ss-w-track tokens are defined above. */\\n.ss-w-fandash-postmatch-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-postmatch-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-postmatch-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-postmatch-stat-value { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-postmatch-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-postmatch-stat-label { font-size: 10.5px; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-fandash-postmatch-stat-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-postmatch-stat-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-stat-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-fandash-postmatch-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-postmatch-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-postmatch-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-postmatch-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-postmatch-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* post-match top performer (full mockup treatment): gradient initials avatar + name + a\\n   prominent rating chip. Avatar gradient reuses the --ss-w-away token, same pairing as the live\\n   crest fallback; \\\"?\\\" renders through the same avatar span when the name is blank. */\\n.ss-w-fandash-postmatch-perf-row { display: flex; align-items: center; gap: 12px; }\\n.ss-w-fandash-postmatch-perf-avatar {\\n  flex: none; width: 42px; height: 42px; border-radius: 50%;\\n  display: grid; place-items: center;\\n  font-size: 14px; font-weight: 800; color: #fff;\\n  background: linear-gradient(135deg, var(--ss-w-away), color-mix(in srgb, var(--ss-w-away) 55%, #000));\\n}\\n.ss-w-fandash-postmatch-perf-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; }\\n.ss-w-fandash-postmatch-perf-rating { margin-left: auto; flex: none; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border-radius: 999px; padding: 3px 11px; }\\n\\n/* post-match next (v1, modest): whenLabel is already a complete localized phrase (opponent +\\n   venue + kickoff) composed server-side, so this card renders just that one line -- dressed up\\n   with an accent rule rather than a duplicated opponent line. The richer opponent-headline/venue-\\n   chip/crest layout from the mockup needs a server field split and is deferred. */\\n.ss-w-fandash-postmatch-next-row { display: flex; align-items: center; gap: 10px; border-left: 3px solid var(--ss-w-accent); padding-left: 10px; }\\n.ss-w-fandash-postmatch-next-when { font-size: 13.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.3; }\\n\\n/* resting next: the between-matches fixture teaser -- when-label left, competition badge right */\\n.ss-w-fandash-resting-next-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-next-when { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }\\n.ss-w-fandash-resting-next-competition { flex: none; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ss-w-faint); }\\n\\n/* resting standings: position figure left, W-D-L/points record right */\\n.ss-w-fandash-resting-standings-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-resting-standings-position { font-size: 15px; font-weight: 750; color: var(--ss-w-ink); }\\n.ss-w-fandash-resting-standings-record { font-size: 11.5px; color: var(--ss-w-faint); text-align: right; }\\n\\n/* resting season: top scorer / key player / season tally as stacked rows */\\n.ss-w-fandash-resting-season-rows { display: flex; flex-direction: column; gap: 4px; }\\n.ss-w-fandash-resting-season-row { font-size: 12.5px; color: var(--ss-w-ink); }\\n\\n/* resting form: reuses the fixture last-five pill classes (ss-w-fandash-form / -form-pill) */\\n.ss-w-fandash-resting-form .ss-w-fandash-form { margin-top: 2px; }\\n\\n/* live score: pulsing Live pill, crests (real image or a coloured initials fallback), a big\\n   tabular score, and an optional scorers line. Also where the shared home/away venue-colour\\n   tokens (--ss-w-home / --ss-w-away / --ss-w-track) are defined above -- the timeline and stats\\n   cards reuse them. */\\n.ss-w-fandash-live-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-fandash-live-pill { display: inline-flex; flex: none; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: #fff; background: var(--ss-w-neg); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-fandash-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; animation: ss-w-fandash-live-pulse 1.3s ease-in-out infinite; }\\n@keyframes ss-w-fandash-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }\\n@media (prefers-reduced-motion: reduce) {\\n  .ss-w-fandash-live-dot { animation: none; }\\n}\\n.ss-w-fandash-live-minute { flex: none; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-competition { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-fandash-live-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-fandash-live-side { display: flex; align-items: center; gap: 10px; min-width: 0; }\\n.ss-w-fandash-live-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-fandash-live-crest { width: 38px; height: 38px; border-radius: 10px; flex: none; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 12.5px; object-fit: cover; box-shadow: 0 2px 6px rgba(0, 0, 0, .18); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-crest--fallback.ss-w-fandash-live-crest--away { background: var(--ss-w-away); }\\n.ss-w-fandash-live-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 700; line-height: 1.15; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-main { display: flex; align-items: baseline; justify-content: center; font-size: 36px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-score-sep { color: var(--ss-w-faint); font-weight: 500; margin: 0 5px; }\\n.ss-w-fandash-live-scorers-row { margin-top: 12px; display: flex; justify-content: space-between; gap: 10px; }\\n.ss-w-fandash-live-scorers { display: flex; align-items: center; gap: 7px; min-width: 0; font-size: 12.5px; color: var(--ss-w-faint); overflow-wrap: anywhere; }\\n.ss-w-fandash-live-scorers--home { justify-content: flex-start; }\\n.ss-w-fandash-live-scorers--away { justify-content: flex-end; }\\n.ss-w-fandash-live-scorers--home .ss-w-fandash-live-scorers-icon { color: var(--ss-w-home); }\\n.ss-w-fandash-live-scorers--away .ss-w-fandash-live-scorers-icon { color: var(--ss-w-away); }\\n.ss-w-fandash-live-scorers-icon { flex: none; }\\n\\n/* live timeline: a compact two-sided event list down a centre spine -- each club's events sit on\\n   its own side (home left, away right), most-recent 3 shown with a \\\"See more\\\" toggle for the\\n   rest. A 3-column grid (txt | badge | txt) per row; the spine itself is a ::before on the list. */\\n.ss-w-fandash-live-tl { position: relative; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-fandash-live-tl::before { content: \\\"\\\"; position: absolute; left: 50%; top: 1px; bottom: 1px; width: 2px; background: var(--ss-w-line); transform: translateX(-1px); }\\n.ss-w-fandash-live-tl-ev { display: grid; grid-template-columns: 1fr 32px 1fr; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-tl-txt { display: flex; align-items: center; gap: 7px; font-size: 13px; min-width: 0; }\\n.ss-w-fandash-live-tl-ev--home .ss-w-fandash-live-tl-txt { grid-column: 1; justify-content: flex-end; }\\n.ss-w-fandash-live-tl-ev--away .ss-w-fandash-live-tl-txt { grid-column: 3; justify-content: flex-start; flex-direction: row-reverse; }\\n.ss-w-fandash-live-tl-who { font-weight: 650; color: var(--ss-w-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-fandash-live-tl-off { font-weight: 500; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-who { font-weight: 800; }\\n.ss-w-fandash-live-tl-badge { grid-column: 2; justify-self: center; min-width: 29px; height: 19px; padding: 0 4px; border-radius: 6px; display: grid; place-items: center; font-size: 11px; font-weight: 800; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); font-variant-numeric: tabular-nums; z-index: 1; }\\n.ss-w-fandash-live-tl-ev--goal .ss-w-fandash-live-tl-badge { background: var(--ss-w-accent); color: #fff; border-color: transparent; }\\n.ss-w-fandash-live-tl-ico { width: 17px; height: 17px; flex: none; display: grid; place-items: center; }\\n.ss-w-fandash-live-tl-ico--goal { border-radius: 50%; background: color-mix(in srgb, var(--ss-w-away) 16%, transparent); }\\n.ss-w-fandash-live-tl-ball { width: 12px; height: 12px; border-radius: 50%; background: radial-gradient(circle at 50% 42%, #fff 0 34%, transparent 36%), var(--ss-w-ink); border: 1px solid var(--ss-w-ink); }\\n.ss-w-fandash-live-tl-card { width: 9px; height: 12px; border-radius: 2px; display: block; }\\n.ss-w-fandash-live-tl-card--yellow { background: var(--ss-w-cta); }\\n.ss-w-fandash-live-tl-card--red { background: var(--ss-w-away); }\\n.ss-w-fandash-live-tl-subarrows { font-size: 11px; font-weight: 900; line-height: 1; letter-spacing: -1px; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-tl-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ss-w-faint); }\\n.ss-w-fandash-live-tl-more { margin-top: 4px; width: 100%; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 7px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); cursor: pointer; }\\n.ss-w-fandash-live-tl-more:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 2px; }\\n\\n/* live stats: club value / stat label / opponent value, each row backed by a home/away split\\n   bar, plus an optional momentum wave (or its text fallback) and a club/opponent colour legend.\\n   No side signal reaches this card, so the club is always the home token and the opponent is\\n   always the away token -- see LiveStatsCard.tsx. */\\n.ss-w-fandash-live-stat-rows { display: flex; flex-direction: column; gap: 15px; }\\n.ss-w-fandash-live-stat { display: flex; flex-direction: column; gap: 7px; }\\n.ss-w-fandash-live-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-fandash-live-stat-value { font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-fandash-live-stat-value--home { color: var(--ss-w-home); }\\n.ss-w-fandash-live-stat-value--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-fandash-live-stat-label { font-size: 10.5px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .04em; }\\n.ss-w-fandash-live-bar { position: relative; height: 8px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-fandash-live-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-fandash-live-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n\\n.ss-w-fandash-live-momentum { font-size: 11.5px; font-weight: 650; color: var(--ss-w-accent); }\\n.ss-w-fandash-live-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fandash-live-mom-caption { display: block; margin-bottom: 5px; font-size: 10.5px; font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-mom-svg { width: 100%; height: 56px; display: block; overflow: visible; }\\n.ss-w-fandash-live-mom-home { fill: var(--ss-w-home); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-away { fill: var(--ss-w-away); fill-opacity: .85; }\\n.ss-w-fandash-live-mom-line { fill: none; stroke: color-mix(in srgb, var(--ss-w-ink) 55%, transparent); stroke-width: 1.5; }\\n.ss-w-fandash-live-mom-base { stroke: var(--ss-w-line); stroke-width: 1; stroke-dasharray: 3 3; }\\n.ss-w-fandash-live-mom-plot { position: relative; }\\n.ss-w-fandash-live-mom-now {\\n  position: absolute; width: 7px; height: 7px; border-radius: 50%;\\n  transform: translate(-50%, -50%);\\n  background: var(--ss-w-panel); border: 1.5px solid var(--ss-w-ink);\\n  pointer-events: none;\\n}\\n.ss-w-mon-mom { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); text-align: center; }\\n.ss-w-mon-mom .ss-w-fandash-live-mom { margin-top: 6px; padding-top: 0; border-top: none; }\\n\\n.ss-w-fandash-live-legend { display: flex; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ss-w-line); font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-fandash-live-legend-item { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-w-fandash-live-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }\\n.ss-w-fandash-live-legend-swatch--home { background: var(--ss-w-home); }\\n.ss-w-fandash-live-legend-swatch--away { background: var(--ss-w-away); }\\n\\n/* live monitor tab bar: underline pattern mirrors .ss-w-ecard-scope; the unread dot uses --ss-w-neg */\\n.ss-w-tabs { display: flex; align-items: stretch; gap: 2px; border-bottom: 1px solid var(--ss-w-line); overflow-x: auto; scrollbar-width: none; }\\n.ss-w-tabs::-webkit-scrollbar { display: none; }\\n.ss-w-tab { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 620; color: var(--ss-w-faint); background: none; border: none; cursor: pointer; padding: 9px 8px; margin-bottom: -1px; border-bottom: 2px solid transparent; flex: none; white-space: nowrap; }\\n.ss-w-tab[data-on] { color: var(--ss-w-ink); border-bottom-color: var(--ss-w-accent); }\\n.ss-w-tab-count { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 999px; padding: 1px 6px; }\\n.ss-w-tab[data-on] .ss-w-tab-count { color: var(--ss-w-accent); }\\n.ss-w-tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n\\n/* Matches tab match card (MonitorMatchCard): pill row, crest/score main row, per-stat split\\n   bars (venue-oriented -- home always left/blue, away always right/red, never club-oriented,\\n   the u316 bug class), a promoted-market strip for the user's pinned stat chips, and a grace\\n   note once the match has gone full time. Reuses the --ss-w-home/--ss-w-away/--ss-w-track venue\\n   tokens and .ss-w-fandash-live-pill for the Live pill so all live surfaces share one look. */\\n.ss-w-mon { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--ss-w-line); border-radius: 12px; background: var(--ss-w-panel); }\\n.ss-w-mon-top { display: flex; align-items: center; gap: 8px; }\\n.ss-w-mon-pill { display: inline-flex; flex: none; align-items: center; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 3px 8px; }\\n.ss-w-mon-min { flex: none; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-comp { margin-left: auto; font-size: 11px; font-weight: 650; color: var(--ss-w-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-mon-main { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }\\n.ss-w-mon-side { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-w-mon-side--away { flex-direction: row-reverse; text-align: right; }\\n/* long club names (Wolverhampton Wanderers) wrap to two lines instead of truncating mid-word */\\n.ss-w-mon-name { min-width: 0; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-mon-vs { font-size: 12px; font-weight: 700; color: var(--ss-w-faint); text-transform: uppercase; }\\n.ss-w-mon-score { display: flex; align-items: baseline; justify-content: center; font-size: 26px; font-weight: 850; font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; color: var(--ss-w-ink); }\\n.ss-w-mon-score i { font-style: normal; color: var(--ss-w-faint); font-weight: 500; margin: 0 4px; }\\n.ss-w-mon-scorers { display: grid; grid-template-columns: 1fr auto 1fr; align-items: start; column-gap: 10px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mon-scorers-col { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\\n.ss-w-mon-scorers-col li { overflow-wrap: anywhere; }\\n.ss-w-mon-scorers-home { text-align: right; }\\n.ss-w-mon-scorers-away { text-align: left; }\\n.ss-w-mon-scorers-ball { flex: none; align-self: start; line-height: 1.35; }\\n\\n/* Pinned pre-match form + head-to-head (MonitorFormH2H): collapsed by default, a real <button>\\n   header toggles it. W/D/L dots and the H2H bar/legend keep fixed, theme-independent colors\\n   (same convention as the dashboard tile accents above) since they're self-contained badges\\n   carrying their own ink color, not page-background-dependent text. */\\n.ss-w-h2h { border-left: 3px solid #16A34A; padding-left: 12px; }\\n.ss-w-h2h-head { display: flex; align-items: center; justify-content: space-between; width: 100%; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: inherit; padding: 0; }\\n.ss-w-h2h-head-l { display: flex; align-items: center; gap: 6px; }\\n.ss-w-h2h-dot { width: 4px; height: 4px; border-radius: 999px; background: var(--ss-w-faint); flex: none; }\\n.ss-w-h2h-title { font-size: 13px; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-h2h-chevron { flex: none; color: var(--ss-w-faint); transition: transform .15s ease; }\\n.ss-w-h2h-chevron--open { transform: rotate(180deg); }\\n.ss-w-h2h-body { padding-top: 12px; display: flex; flex-direction: column; gap: 12px; }\\n.ss-w-h2h-forms { display: flex; align-items: flex-start; justify-content: space-between; }\\n.ss-w-h2h-form-col { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\\n.ss-w-h2h-form-col--away { align-items: flex-end; }\\n.ss-w-h2h-form-team { font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-h2h-dots { display: flex; gap: 4px; }\\n.ss-w-h2h-result { width: 20px; height: 20px; border-radius: 999px; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex: none; }\\n.ss-w-h2h-result--win { background: #16A34A; color: #FFFFFF; }\\n.ss-w-h2h-result--draw { background: #E5E7EB; color: #4B5563; }\\n.ss-w-h2h-result--loss { background: #F5A623; color: #1F2937; }\\n.ss-w-h2h-record { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-h2h-meta { font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-h2h-bar { display: flex; width: 100%; height: 8px; border-radius: 999px; overflow: hidden; }\\n.ss-w-h2h-bar-seg--win { background: #16A34A; }\\n.ss-w-h2h-bar-seg--draw { background: #D1D5DB; }\\n.ss-w-h2h-bar-seg--loss { background: #2563EB; }\\n.ss-w-h2h-legend { display: flex; align-items: center; justify-content: space-between; margin-top: 2px; }\\n.ss-w-h2h-legend-item { font-size: 11px; color: var(--ss-w-ink); display: flex; align-items: center; gap: 5px; }\\n.ss-w-h2h-legend-dot { width: 7px; height: 7px; border-radius: 999px; display: inline-block; flex: none; }\\n.ss-w-h2h-legend-dot--win { background: #16A34A; }\\n.ss-w-h2h-legend-dot--draw { background: #D1D5DB; }\\n.ss-w-h2h-legend-dot--loss { background: #2563EB; }\\n\\n.ss-w-fact { display: flex; flex-direction: column; gap: 7px; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--ss-w-accent) 9%, transparent); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 22%, transparent); }\\n.ss-w-fact-k { display: flex; align-items: center; gap: 6px; font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-w-fact-min { color: var(--ss-w-ink); letter-spacing: 0; }\\n.ss-w-fact-subj { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 650; color: var(--ss-w-faint); }\\n.ss-w-fact-text { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--ss-w-ink); }\\n.ss-w-fact-basis { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-fact-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; border: 1px solid var(--ss-w-line); border-radius: 8px; padding: 6px 8px; }\\n.ss-w-fact-foot { display: flex; align-items: center; gap: 14px; }\\n.ss-w-fact-link { font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ss-w-accent); background: none; border: none; padding: 4px 0; min-height: 32px; cursor: pointer; }\\n.ss-w-fact-link--muted { color: var(--ss-w-faint); margin-left: auto; }\\n.ss-w-fact-hist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li { display: grid; grid-template-columns: 34px 1fr; gap: 8px; padding: 9px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-fact-hist li:last-child { border-bottom: none; }\\n.ss-w-fact-hmin { font-size: 11px; font-weight: 800; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-fact-htext { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-ink); }\\n.ss-w-mon-stats { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-mon-stat { display: flex; flex-direction: column; gap: 5px; }\\n.ss-w-mon-pstrip { padding: 6px 8px; border-radius: 8px; background: color-mix(in srgb, var(--ss-w-accent) 8%, transparent); }\\n.ss-w-mon-stat-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline; gap: 8px; }\\n.ss-w-mon-stat-v { font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-v--home { color: var(--ss-w-home); }\\n.ss-w-mon-stat-v--away { color: var(--ss-w-away); text-align: right; }\\n.ss-w-mon-stat-l { font-size: 10px; font-weight: 700; text-align: center; color: var(--ss-w-faint); text-transform: uppercase; letter-spacing: .03em; }\\n.ss-w-mon-bar { position: relative; height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; display: flex; }\\n.ss-w-mon-bar-home { height: 100%; background: var(--ss-w-home); }\\n.ss-w-mon-bar-away { height: 100%; background: var(--ss-w-away); margin-left: auto; }\\n.ss-w-mon-stat-mkt { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mon-mkt { background: color-mix(in srgb, var(--ss-w-accent) 10%, transparent); border-radius: 6px; padding: 3px 6px; color: var(--ss-w-ink); }\\n.ss-w-mon-stat-mkt-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }\\n.ss-w-mon-price { font-family: ui-monospace, monospace; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 700; color: var(--ss-w-accent); }\\n.ss-w-mon-susp { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-bubble); border-radius: 6px; padding: 2px 6px; }\\n.ss-w-mon-asof { display: block; font-size: 10.5px; font-weight: 600; color: var(--ss-w-cta); }\\n.ss-w-mon-grace { font-size: 11px; color: var(--ss-w-faint); border-top: 1px solid var(--ss-w-line); padding-top: 8px; }\\n\\n/* Matches/Odds tab panels (MonitorTabs): the shared per-market-pin context line, the empty\\n   state shown when the snapshot carries no matches/markets yet, the persistent D5 in-slip badge,\\n   and the per-market-pin wrapper card (struck price on settlement is a pure CSS hook off its\\n   [data-settled] attribute -- no separate class on the price element itself). */\\n.ss-w-mk-ctx { display: flex; align-items: center; gap: 6px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--ss-w-line); }\\n/* the score and the trailing badges/pin never shrink or wrap -- only the fixture name truncates */\\n.ss-w-mk-ctx b { flex: none; white-space: nowrap; }\\n/* the context line's fixture name stays single-line (the two-line clamp is for the match card) */\\n.ss-w-mk-ctx .ss-w-mon-name { display: block; white-space: nowrap; text-overflow: ellipsis; }\\n.ss-w-mk-ctx-side { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-mk-ctx-right { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }\\n/* flex:1 keeps the composer pinned to the panel bottom when a tab is empty */\\n.ss-w-mon-empty { flex: 1; padding: 24px 16px; text-align: center; font-size: 12.5px; color: var(--ss-w-faint); }\\n/* shared group-header label for Club Fixtures (round) and Squad (position) list groups */\\n.ss-w-club-eyebrow { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding: 10px 2px 4px; }\\n.ss-w-sq-row { display: flex; align-items: center; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-sq-num { flex: none; width: 20px; text-align: right; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-faint); }\\n.ss-w-sq-name { font-size: 13px; font-weight: 600; color: var(--ss-w-ink); }\\n.ss-w-sq-name { flex: 1; min-width: 0; }\\n.ss-w-sq-name-1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-sq-seg { display: flex; gap: 2px; padding: 2px; border-radius: var(--ss-w-radius); background: var(--ss-w-track); }\\n.ss-w-sq-seg-btn { flex: 1; padding: 5px 8px; border: 0; border-radius: calc(var(--ss-w-radius) - 2px); background: transparent; font: inherit; font-size: 12px; font-weight: 600; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-sq-seg-btn[aria-pressed=\\\"true\\\"] { background: var(--ss-w-panel); color: var(--ss-w-ink); }\\n.ss-w-sq-seg-btn:focus-visible, .ss-w-sq-tap:focus-visible, .ss-w-pd-back:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 1px; }\\n.ss-w-sq-tap { width: 100%; border: 0; border-bottom: 1px solid var(--ss-w-line); background: transparent; font: inherit; text-align: left; cursor: pointer; }\\n.ss-w-sq-col { flex: none; width: 40px; text-align: center; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-sq-head { border-bottom: 0; padding-bottom: 0; }\\n.ss-w-sq-head .ss-w-sq-col { font-size: 10px; font-weight: 700; color: var(--ss-w-faint); }\\n.ss-w-sq-stats { padding-top: 10px; gap: 10px; }\\n.ss-w-sq-card { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; }\\n.ss-w-sq-stats .ss-w-sq-row { display: grid; grid-template-columns: 1fr 26px 30px 36px 20px 20px 20px 20px 36px; gap: 0; padding: 7px 10px; font-size: 11px; }\\n.ss-w-sq-card > :last-child { border-bottom: 0; }\\n.ss-w-sq-pos, .ss-w-sq-c20, .ss-w-sq-c30, .ss-w-sq-c36 { text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 11px; font-weight: 400; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-sq-stats .ss-w-sq-head { padding-bottom: 7px; border-bottom: 1px solid var(--ss-w-line); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--ss-w-faint); }\\n.ss-w-sq-stats .ss-w-sq-head > span { font-size: 9px; font-weight: 700; color: var(--ss-w-faint); }\\n.ss-w-sq-player { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-sq-badge { flex: none; width: 18px; height: 18px; border-radius: 6px; background: var(--ss-w-track); color: var(--ss-w-faint); font-size: 9px; font-weight: 700; display: flex; align-items: center; justify-content: center; }\\n.ss-w-sq-stats .ss-w-sq-name { font-size: 11px; }\\n.ss-w-sq-rtg { font-weight: 700; }\\n.ss-w-sq-rtg-none { color: var(--ss-w-faint); font-weight: 400; }\\n.ss-w-sq-stats .ss-w-pos-ink { color: var(--ss-w-pos); font-weight: 700; }\\n.ss-w-sq-foot { padding: 0 2px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-sq-bar { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 10px 14px 0; }\\n.ss-w-sq-bar .ss-w-sq-seg { margin: 0; }\\n.ss-w-sq-bar .ss-w-sq-seg:only-child { flex: 1; }\\n.ss-w-sq-bar .ss-w-sq-seg:not(:only-child) { flex: none; }\\n.ss-w-sq-eyebrow { flex: 1; min-width: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); }\\n@media (max-width: 429px) { .ss-w-sq-badge { display: none; } }\\n@media (max-width: 359px) {\\n  .ss-w-sq-yr { display: none; }\\n  .ss-w-sq-stats .ss-w-sq-row { grid-template-columns: 1fr 26px 30px 36px 20px 20px 36px; }\\n}\\n.ss-w-pd-bar { flex: none; display: flex; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--ss-w-line); line-height: normal; }\\n.ss-w-pd-back { display: flex; align-items: center; gap: 2px; min-height: 32px; padding: 8px 8px 8px 0; margin: -8px 0; border: 0; background: transparent; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-pd-back:hover { color: var(--ss-w-ink); }\\n.ss-w-mon-list.ss-w-pd-list { padding: 16px; gap: 14px; line-height: normal; }\\n.ss-w-pd-card { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; }\\n.ss-w-pd-faint { color: var(--ss-w-faint); }\\n.ss-w-pd-profile { display: flex; gap: 12px; padding: 14px; }\\n.ss-w-pd-photo { flex: none; border-radius: 50%; border: 1px solid var(--ss-w-line); background: var(--ss-w-bubble); object-fit: cover; }\\n.ss-w-pd-avatar { display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--ss-w-ink); }\\n.ss-w-pd-profile-main { flex: 1; min-width: 0; }\\n.ss-w-pd-name { font-size: 16px; font-weight: 800; color: var(--ss-w-ink); overflow-wrap: break-word; }\\n.ss-w-pd-sub { margin-top: 1px; font-size: 12px; color: var(--ss-w-faint); }\\n/* Two columns as on the board, collapsing to one when a column would drop under 80px (narrow phones). */\\n.ss-w-pd-bio { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(80px, calc((100% - 10px) / 2)), 1fr)); gap: 4px 10px; margin-top: 10px; font-size: 11.5px; }\\n.ss-w-pd-bio-item { min-width: 0; overflow-wrap: break-word; }\\n.ss-w-pd-pitch { position: relative; flex: none; width: 56px; height: 76px; border: 1px solid var(--ss-w-line); border-radius: 6px; background: var(--ss-w-track); }\\n.ss-w-pd-pitch-dot { position: absolute; width: 11px; height: 11px; border-radius: 50%; background: var(--ss-w-accent); border: 2px solid var(--ss-w-nav); transform: translate(-50%, -50%); }\\n.ss-w-pd-avail { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 14px; }\\n.ss-w-pd-avail-text { min-width: 0; }\\n.ss-w-pd-avail-next { font-size: 12.5px; font-weight: 700; }\\n.ss-w-pd-avail-note { margin-top: 1px; font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-pd-pill { flex: none; padding: 4px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; white-space: nowrap; }\\n.ss-w-pd-pill--pos, .ss-w-pd-chip--pos { background: color-mix(in srgb, var(--ss-w-pos) 14%, transparent); color: var(--ss-w-pos); }\\n.ss-w-pd-pill--warn, .ss-w-pd-chip--warn { background: color-mix(in srgb, var(--ss-w-warn) 14%, transparent); color: var(--ss-w-warn); }\\n.ss-w-pd-pill--neg, .ss-w-pd-chip--neg { background: color-mix(in srgb, var(--ss-w-neg) 14%, transparent); color: var(--ss-w-neg); }\\n.ss-w-pd-pill--draw { background: var(--ss-w-track); color: var(--ss-w-faint); }\\n.ss-w-pd-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-w-faint); padding: 0 2px; }\\n.ss-w-pd-eyebrow--block { margin-bottom: 8px; }\\n.ss-w-pd-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }\\n.ss-w-pd-tile { min-width: 0; padding: 10px; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; }\\n.ss-w-pd-tile-label { font-size: 10.5px; color: var(--ss-w-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-w-pd-tile-value { margin-top: 2px; font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }\\n.ss-w-pd-pos-ink { color: var(--ss-w-pos); }\\n/* Below 360px the board's 10px tile padding clips \\\"Matches\\\"/\\\"Minutes\\\" (43px) in a ~34px label box. */\\n@media (max-width: 359px) {\\n  .ss-w-pd-tiles { gap: 6px; }\\n  .ss-w-pd-tile { padding: 10px 6px; }\\n}\\n.ss-w-pd-perf-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 2px; }\\n.ss-w-pd-perf-head .ss-w-pd-eyebrow { flex: 1; min-width: 0; }\\n.ss-w-pd-seg { flex: none; display: flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--ss-w-track); }\\n.ss-w-pd-seg-btn { padding: 5px 12px; border: 0; border-radius: 999px; background: transparent; font: inherit; font-size: 11.5px; font-weight: 700; line-height: normal; white-space: nowrap; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-pd-seg-btn[aria-pressed=\\\"true\\\"] { background: var(--ss-w-nav); color: #fff; }\\n.ss-w-pd-seg-btn:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: 1px; }\\n.ss-w-pd-perf-sub { margin-bottom: 10px; font-size: 11px; color: var(--ss-w-faint); }\\n.ss-w-pd-perf-head + .ss-w-pd-perf-cards { margin-top: 10px; }\\n.ss-w-pd-perf-cards { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-pd-perf-card { padding: 14px; }\\n.ss-w-pd-perf-group { margin-bottom: 10px; font-size: 12.5px; font-weight: 700; }\\n.ss-w-pd-bar-row + .ss-w-pd-bar-row { margin-top: 12px; }\\n.ss-w-pd-bar-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 5px; font-size: 12.5px; }\\n.ss-w-pd-bar-label { min-width: 0; overflow-wrap: break-word; }\\n.ss-w-pd-bar-value { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-w-pd-track { height: 6px; border-radius: 999px; background: var(--ss-w-track); overflow: hidden; }\\n.ss-w-pd-fill { height: 100%; border-radius: 999px; }\\n.ss-w-pd-fill--pos { background: var(--ss-w-pos); }\\n.ss-w-pd-fill--warn { background: var(--ss-w-warn); }\\n.ss-w-pd-fill--neg { background: var(--ss-w-neg); }\\n.ss-w-pd-match { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto auto; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-pd-match:last-child { border-bottom: none; }\\n.ss-w-pd-match-date { font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-pd-match-opp { font-size: 12.5px; font-weight: 600; overflow-wrap: break-word; }\\n.ss-w-pd-match-sub { margin-top: 1px; font-size: 10.5px; color: var(--ss-w-faint); }\\n.ss-w-pd-chip-empty { min-width: 30px; }\\n.ss-w-pd-chip { min-width: 30px; padding: 3px 0; border-radius: 6px; text-align: center; font-size: 11.5px; font-weight: 800; font-variant-numeric: tabular-nums; }\\n.ss-w-rec-list { margin: 0; padding: 0; list-style: none; }\\n.ss-w-rec-value { flex: none; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-rec-since { font-size: 12px; color: var(--ss-w-faint); }\\n/* Per-pin unavailable state: the pin's context line still rendered above (score, name, unpin), but\\n   the pin has neither a card nor history (compose-time rescue failed) -- a small inline note beats\\n   a bare context line with nothing under it. */\\n.ss-w-mon-empty-card { padding: 8px 0 2px; font-size: 12px; color: var(--ss-w-faint); }\\n.ss-w-mon-inslip { display: inline-flex; flex: none; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 700; color: var(--ss-w-pos); }\\n/* Odds-tab item is bare: the visible card is the market-odds card itself (no outer wrapper card),\\n   with an optional slim live strip above it. */\\n.ss-w-mon-oddspin { display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-mk-live { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0 2px; font-size: 11.5px; color: var(--ss-w-faint); }\\n.ss-w-mk-live-score { color: var(--ss-w-ink); font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-w-mon-oddspin[data-settled] .ss-w-mo-price,\\n.ss-w-mon-oddspin[data-settled] .ss-w-mon-price { text-decoration: line-through; color: var(--ss-w-faint); }\\n\\n/* market accordion (Task 9): one collapsed row per available market, expanding into a reused\\n   MarketOddsCardList ladder (hideHeader -- the row header already carries the market label). */\\n/* Pinned-match tile: the match card + its odds accordion, spaced apart. */\\n.ss-w-mon-item { display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-acc { display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-acc-row { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); overflow: hidden; }\\n/* Row header: expand toggle (flex:1) + the market PinToggle as a sibling (no nested buttons). */\\n.ss-w-acc-head { display: flex; align-items: center; gap: 8px; padding: 6px 9px 6px 11px; }\\n.ss-w-acc-toggle { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: var(--ss-w-ink); padding: 5px 0; }\\n/* Suspended: the row stays listed (knowing a market is off is useful) but is not tappable --\\n   its card is unservable, so a pointer cursor would promise something that cannot load. */\\n.ss-w-acc-toggle--susp { cursor: default; color: var(--ss-w-faint); }\\n.ss-w-acc-chevron { color: var(--ss-w-faint); font-size: 11px; flex: none; }\\n.ss-w-acc-label { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-acc-badge { font-size: 10.5px; font-weight: 700; color: var(--ss-w-accent); flex: none; }\\n.ss-w-acc-susp { margin-left: auto; font-size: 10.5px; color: var(--ss-w-faint); flex: none; }\\n.ss-w-acc-panel { padding: 0 11px 10px; display: flex; flex-direction: column; gap: 8px; }\\n.ss-w-acc-insight { font-size: 12px; color: var(--ss-w-ink); background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); border-radius: 8px; padding: 7px 9px; }\\n.ss-w-acc-retry { font-size: 12px; color: var(--ss-w-neg); cursor: pointer; padding: 6px 0; }\\n\\n/* ---- Today tab (u355) ---- */\\n.ss-w-sec-head { display: flex; align-items: center; gap: 7px; padding: 2px 2px 0; font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }\\n.ss-w-sec-head::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n.ss-w-sec-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ss-w-neg); flex: none; }\\n.ss-w-today-live { display: flex; flex-direction: column; gap: 2px; }\\n\\n/* Today tab root (Task 7): position: relative so the grid's own star/unstar toast (absolute,\\n   top-centre) anchors here rather than to some unrelated positioned ancestor. */\\n/* Non-scrolling anchor for .ss-w-today-toast (position: absolute; top: 0): .ss-w-mon-list below is\\n   the overflow-y: auto scroller, so a toast parented to IT would scroll out of view with the\\n   content that moved it. This wrapper sits outside that scroller, inside .ss-w-panel's fixed-size\\n   flex column, so top: 0 always lands at the visible top of the Today tab. min-height: 0 is\\n   required: without it this flex item defaults to min-height: auto (its content height), .ss-w-panel's\\n   overflow: hidden then clips it, and .ss-w-mon-list inside never gets a bounded height to scroll within. */\\n.ss-w-today-root { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }\\n\\n/* Section header for \\\"Your leagues\\\"/\\\"Top leagues\\\"/\\\"All leagues\\\" (Task 7) -- same visual\\n   treatment as .ss-w-sec-head (the live-band header), kept as a separate class so a kept test\\n   asserting .ss-w-sec-head is absent when nothing is live cannot see this header too. */\\n.ss-w-today-sec { display: flex; align-items: center; gap: 7px; padding: 2px 2px 0; font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); }\\n.ss-w-today-sec::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n.ss-w-today-sec-sub { text-transform: none; letter-spacing: normal; font-weight: 600; }\\n.ss-w-today-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\\n.ss-w-today-empty { font-size: 12px; color: var(--ss-w-faint); padding: 10px 2px; }\\n.ss-w-today-search-block { display: flex; flex-direction: column; }\\n.ss-w-today-search-group { display: flex; align-items: center; gap: 7px; padding: 2px 2px 6px; }\\n.ss-w-today-search-group::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n.ss-w-today-search-group .ss-w-bi-comp-logo { width: 16px; height: 16px; }\\n.ss-w-today-search-group-name { font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ss-w-faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-today-search-row { cursor: pointer; border-radius: 10px; }\\n.ss-w-today-search-row:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n\\n/* League tile (Task 5): a flat row (crest + name as the open target, star as a separate sibling\\n   button) rather than a disclosure header -- opening is Task 6's LeagueDetail, not an inline\\n   expansion. Same border/radius language .ss-w-grp used to carry, before Task 7 deleted it. */\\n.ss-w-today-tile { display: flex; align-items: center; gap: 6px; border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; background: var(--ss-w-bubble); }\\n.ss-w-today-tile-body { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 8px 9px; background: none; border: none; font: inherit; color: var(--ss-w-ink); cursor: pointer; text-align: left; }\\n.ss-w-today-tile-body:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-tile-name { font-size: 12px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-today-tile-country { font-weight: 600; color: var(--ss-w-faint); }\\n.ss-w-today-tile-star { flex: none; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: 0 6px; background: none; border: none; border-radius: 8px; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-today-tile-star:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-tile-star[aria-pressed=\\\"true\\\"] { color: var(--ss-w-accent); }\\n.ss-w-today-tile-star:disabled { cursor: default; opacity: .4; }\\n.ss-w-today-tile-star svg { width: 18px; height: 18px; }\\n\\n/* Capped row groups (variant B of u521): one league's section-header plus up to\\n   ROW_CAP_PER_LEAGUE inline fixture rows, used in place of a tile when the section row budget\\n   allows it. Mirrors LeagueTile's button-body + sibling-star-button shape. */\\n.ss-w-today-rowsection { display: flex; flex-direction: column; gap: 12px; }\\n.ss-w-today-rowgroup { display: flex; flex-direction: column; }\\n.ss-w-today-rowgroup-head { display: flex; align-items: center; gap: 4px; }\\n.ss-w-today-rowgroup-head-body { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 2px; background: none; border: none; font: inherit; color: var(--ss-w-ink); cursor: pointer; text-align: left; }\\n.ss-w-today-rowgroup-head-body:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-rowgroup-name { font-size: 11px; font-weight: 800; letter-spacing: .02em; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-today-rowgroup-star { flex: none; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: none; border: none; border-radius: 8px; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-today-rowgroup-star:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-rowgroup-star[aria-pressed=\\\"true\\\"] { color: var(--ss-w-accent); }\\n.ss-w-today-rowgroup-star:disabled { cursor: default; opacity: .4; }\\n.ss-w-today-rowgroup-star svg { width: 16px; height: 16px; }\\n.ss-w-today-rowgroup-rows { display: flex; flex-direction: column; }\\n.ss-w-today-rowgroup-seeall { align-self: flex-start; background: none; border: none; font: inherit; font-size: 11px; font-weight: 700; color: var(--ss-w-faint); cursor: pointer; padding: 4px 2px 0; }\\n.ss-w-today-rowgroup-seeall:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n\\n/* League detail (Task 6): the drill-in view opened from a tile. Its header star is always\\n   enabled (spec §3/§7's one exception to the tile rule), so it carries no :disabled styling. */\\n.ss-w-today-detail { position: relative; display: flex; flex-direction: column; gap: 10px; }\\n.ss-w-today-detail-head { display: flex; align-items: center; gap: 8px; }\\n.ss-w-today-detail-back { flex: none; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: none; border: none; border-radius: 8px; color: var(--ss-w-ink); cursor: pointer; transform: scaleX(-1); }\\n.ss-w-today-detail-back:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-detail-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-today-detail-star { flex: none; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; background: none; border: none; border-radius: 8px; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-today-detail-star:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-detail-star[aria-pressed=\\\"true\\\"] { color: var(--ss-w-accent); }\\n.ss-w-today-detail-star svg { width: 18px; height: 18px; }\\n.ss-w-today-detail-nav { display: flex; align-items: center; justify-content: center; gap: 10px; }\\n.ss-w-today-detail-prev, .ss-w-today-detail-next { flex: none; display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; background: none; border: none; border-radius: 8px; color: var(--ss-w-faint); cursor: pointer; }\\n.ss-w-today-detail-prev:focus-visible, .ss-w-today-detail-next:focus-visible { outline: 2px solid var(--ss-w-accent); outline-offset: -2px; }\\n.ss-w-today-detail-prev { transform: scaleX(-1); }\\n.ss-w-today-detail-pos { font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-today-detail-body { display: flex; flex-direction: column; }\\n.ss-w-today-detail-count { align-self: flex-end; flex: none; font-size: 10.5px; font-weight: 700; color: var(--ss-w-faint); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; margin-bottom: 4px; }\\n/* aria-live status region, not a modal -- pointer-events: none so the header/nav above stay\\n   clickable while it is showing. */\\n.ss-w-today-toast { position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 1; pointer-events: none; width: max-content; max-width: 220px; font-size: 11px; font-weight: 560; 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)); border-radius: 10px; padding: 5px 10px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\\n\\n.ss-w-drow { display: grid; grid-template-columns: 42px minmax(0,1fr) 22px; align-items: center; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-drow:last-child { border-bottom: none; }\\n.ss-w-drow-when { font-size: 11px; font-weight: 700; color: var(--ss-w-faint); font-variant-numeric: tabular-nums; }\\n.ss-w-drow-when--live { color: var(--ss-w-neg); }\\n/* Each side ellipsises independently: a single joined string truncates the away team off the end,\\n   which is the u350 betting-card truncation one layer down. */\\n.ss-w-drow-fx { display: flex; align-items: center; gap: 6px; min-width: 0; }\\n.ss-w-drow-side { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1 1 0; }\\n/* Away side mirrors home around the score: crest to the far edge, name aligned inward. */\\n.ss-w-drow-side--away { flex-direction: row-reverse; text-align: right; }\\n.ss-w-drow-nm { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n/* Centre slot of .ss-w-drow-fx, between the two sides: flex:none so a widening score never\\n   steals width the team names need to avoid ellipsis. min-width holds the slot at the width of a\\n   one-digit scoreline so an unscored row's bare dash does not pull the column out of line -- the\\n   scores read as a column down the list, not a jitter. */\\n.ss-w-drow-sc { flex: none; min-width: 26px; text-align: center; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-drow-sc--idle { color: var(--ss-w-faint); font-weight: 600; }\\n.ss-w-drow--live { background: color-mix(in srgb, var(--ss-w-neg) 5%, transparent); border-radius: 8px; padding: 7px 6px; margin: 0 -6px; border-bottom: none; }\\n.ss-w-drow-crest { width: 16px; height: 16px; flex: none; border-radius: 50%; object-fit: contain; background: var(--ss-w-bubble); }\\n\\n.ss-w-stale { font-size: 11px; font-weight: 600; color: var(--ss-w-cta); background: color-mix(in srgb, var(--ss-w-cta) 12%, var(--ss-w-panel)); border-radius: 8px; padding: 6px 9px; }\\n\\n/* Prize banner: CTA-tinted card with icon + body column (label + chips) — still used by\\n   LeaderboardEmpty.tsx's weekly-prize callout. */\\n.ss-w-prize { display: flex; align-items: flex-start; gap: 10px; padding: 11px 13px; border-radius: 12px; background: color-mix(in srgb, var(--ss-w-cta) 10%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-cta) 22%, var(--ss-w-line)); }\\n.ss-w-prize-icon { flex: none; font-size: 20px; line-height: 1; padding-top: 1px; }\\n.ss-w-prize-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }\\n.ss-w-prize-text { font-size: 12.5px; font-weight: 650; color: var(--ss-w-ink); line-height: 1.35; overflow-wrap: anywhere; }\\n\\n/* ── games hub (u393) ── */\\n.ss-g-hub-wrap { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; background: var(--ss-g-ground); font-family: var(--ss-g-font-body); color: var(--ss-g-ink); }\\n.ss-g-hub { display: flex; flex-direction: column; gap: 14px; padding: 14px 16px 20px; }\\n.ss-g-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-stat { display: flex; flex-direction: column; gap: 2px; padding: 9px 12px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); min-width: 0; }\\n.ss-g-stat-l { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-stat-v { display: flex; align-items: baseline; gap: 4px; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 24px; line-height: 1; white-space: nowrap; }\\n.ss-g-stat-v svg { color: var(--ss-g-flame); align-self: center; }\\n.ss-g-stat-v small { font-family: var(--ss-g-font-body); font-size: 12px; font-weight: 600; color: var(--ss-g-muted); overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-stat-v--accent { color: var(--ss-w-accent); }\\n.ss-g-prize { align-self: flex-start; }\\n.ss-g-tile { position: relative; display: flex; flex-direction: column; gap: 4px; padding: 10px; min-width: 0; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; }\\n.ss-g-tile:not([data-disabled]):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-tile[data-disabled] { opacity: .55; cursor: default; }\\n.ss-g-tile--tile { height: 148px; }\\n.ss-g-tile-art { height: 74px; border-radius: 10px; background: var(--ss-g-raised); display: flex; align-items: center; justify-content: center; margin-bottom: 4px; }\\n.ss-g-art { width: 100%; height: 100%; }\\n.ss-g-art-fg { fill: var(--ss-g-strong-line); }\\n.ss-g-art-accent { fill: var(--ss-w-accent); }\\n.ss-g-art-accent-stroke { fill: none; stroke: var(--ss-w-accent); stroke-width: 2; }\\n.ss-g-art-dot { fill: var(--ss-g-pitch-mark); }\\n.ss-g-art-pitch { fill: var(--ss-g-pitch); stroke: var(--ss-g-pitch-line); }\\n.ss-g-art-block { fill: var(--ss-g-line); }\\n.ss-g-art-correct { fill: var(--ss-g-correct); }\\n.ss-g-art-dash { fill: none; stroke: var(--ss-g-strong-line); stroke-dasharray: 3 2; stroke-width: 1.5; }\\n.ss-g-art-line { stroke: var(--ss-g-line-warm); stroke-width: 2; }\\n.ss-g-art-ink { fill: none; stroke: var(--ss-g-on-accent); stroke-width: 2; }\\n.ss-g-art-q { fill: var(--ss-w-accent); font: 800 20px var(--ss-g-font-display); }\\n.ss-g-tile-title { font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tile-status[data-tone=\\\"accent\\\"] { color: var(--ss-w-accent); font-weight: 600; }\\n.ss-g-tile-status[data-tone=\\\"success\\\"] { color: var(--ss-g-success); font-weight: 700; }\\n.ss-g-tile--hero { flex-direction: row; min-height: 184px; padding: 0; overflow: hidden; border-radius: 18px; background: var(--ss-g-warm); border-color: var(--ss-g-line-warm); }\\n.ss-g-hero-text { flex: 0 0 60%; display: flex; flex-direction: column; justify-content: center; gap: 6px; padding: 18px; min-width: 0; }\\n.ss-g-hero-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-hero-title { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: .95; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-hero-sub { font-size: 14px; color: var(--ss-g-ink-2); }\\n.ss-g-hero-cta { align-self: flex-start; margin-top: 6px; padding: 9px 16px; border-radius: 999px; background: var(--ss-w-accent); color: var(--ss-g-on-accent); font-size: 14px; font-weight: 700; }\\n.ss-g-hero-art { flex: 1; display: flex; align-items: center; justify-content: center; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sec { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 6px; }\\n.ss-g-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-sec-head span { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-tile--wide { flex-direction: row; align-items: center; gap: 14px; min-height: 104px; }\\n.ss-g-wide-art { width: 84px; height: 84px; flex: none; border-radius: 10px; background: var(--ss-g-raised); }\\n.ss-g-wide-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }\\n.ss-g-wide-chev { color: var(--ss-g-muted); transform: rotate(180deg); display: flex; }\\n\\n/* ── Mystery Tiger (u393) ── */\\n.ss-g-mt-card { flex: none; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); overflow: hidden; display: flex; flex-direction: column; }\\n.ss-g-mt-portrait { position: relative; height: 178px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 16px, var(--ss-g-warm) 16px 36px); }\\n.ss-g-mt-portrait .ss-g-sil { font-size: 46px; }\\n.ss-g-mt-photo { width: 132px; height: 132px; margin-bottom: 30px; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 40px var(--ss-g-font-display); }\\n.ss-g-mt-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-cp-photo { width: 64px; height: 64px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font: 800 22px var(--ss-g-font-display); }\\n.ss-g-cp-photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-mt-reveal-name { position: absolute; bottom: 6px; left: 12px; right: 12px; text-align: center; font: 800 20px var(--ss-g-font-display); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-known { display: grid; gap: 6px; padding: 12px; }\\n.ss-g-mt-known-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }\\n.ss-g-mt-lab { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-known-v { width: 100%; height: 38px; border-radius: 8px; display: grid; place-items: center; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); color: var(--ss-g-muted); white-space: nowrap; }\\n.ss-g-mt-known-v[data-state=\\\"known\\\"] { background: var(--ss-g-correct); color: var(--ss-g-on-correct); font-size: 18px; }\\n.ss-g-mt-known-v[data-state=\\\"range\\\"] { border: 1px dashed var(--ss-g-strong-line); }\\n.ss-g-mt-table { display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-mt-thead, .ss-g-mt-row { display: grid; gap: 5px; align-items: center; }\\n.ss-g-mt-thead { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mt-thead span:not(:first-child) { text-align: center; }\\n.ss-g-mt-who { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-mt-av { width: 38px; height: 38px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 12px; font-weight: 700; overflow: hidden; }\\n.ss-g-mt-names { display: flex; flex-direction: column; min-width: 0; line-height: 1.1; }\\n.ss-g-mt-first { font-size: 11px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-last { font-size: 14px; font-weight: 700; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mt-cell { height: 42px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; font: 700 16px var(--ss-g-font-display); background: var(--ss-g-raised); border: 1px solid var(--ss-g-line); color: var(--ss-g-ink); overflow: hidden; }\\n.ss-g-mt-cell[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); border-color: transparent; color: var(--ss-g-on-correct); }\\n.ss-g-mt-cell[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); border-color: transparent; color: var(--ss-g-on-accent); }\\n.ss-g-mt-cell-dir { font-size: 10px; margin-top: 2px; }\\n.ss-g-mt-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mt-legend span { display: inline-flex; align-items: center; gap: 6px; }\\n.ss-g-mt-sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }\\n.ss-g-mt-sw[data-verdict=\\\"exact\\\"] { background: var(--ss-g-correct); }\\n.ss-g-mt-sw[data-verdict=\\\"near\\\"] { background: var(--ss-g-close); }\\n.ss-g-mt-hint { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-mt-hint svg { color: var(--ss-w-accent); flex: none; margin-top: 1px; }\\n\\n/* ── Higher or Lower (u393) ── */\\n.ss-g-hl-prompt { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; }\\n.ss-g-hl-prompt-q { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-hl-prompt-stat { font: 800 30px var(--ss-g-font-display); text-transform: uppercase; letter-spacing: .02em; line-height: 1.05; }\\n.ss-g-hl-prompt-season { font-size: 12px; color: var(--ss-g-muted); }\\n/* The pair fills whatever height the panel leaves (a laptop demo panel is ~670px, the design 860px):\\n   both cards share it and the photos scale with them, so Higher/Lower never fall below the fold. */\\n.ss-g-hl .ss-g-body { overflow-y: auto; container: hl / size; }\\n.ss-g-hl-pair { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-hl-card { flex: 1 1 0; min-height: min-content; max-height: 240px; display: flex; border-radius: 18px; overflow: hidden; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-hl-card--b { border-color: var(--ss-g-line-warm); }\\n.ss-g-hl-photo-wrap { width: 38%; max-width: 160px; flex: none; align-self: stretch; display: flex; align-items: flex-end; justify-content: center; background: var(--ss-g-raised); overflow: hidden; }\\n.ss-g-hl-photo-wrap .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-hl-photo { width: 100%; height: 100%; display: grid; place-items: center; color: var(--ss-g-muted); font: 800 36px var(--ss-g-font-display); }\\n.ss-g-hl-photo img { width: 100%; height: 100%; object-fit: cover; object-position: top; }\\n.ss-g-hl-info { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 12px 14px; }\\n.ss-g-hl-first { font-size: 13px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-surname { font: 800 26px var(--ss-g-font-display); text-transform: uppercase; line-height: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-hl-value { font: 800 56px var(--ss-g-font-display); line-height: .95; color: var(--ss-w-accent); margin-top: 6px; }\\n.ss-g-hl-stat { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-hl-btns { display: flex; flex-direction: row; gap: 8px; margin-top: 12px; }\\n.ss-g-hl-btns .ss-g-btn { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0 6px; gap: 4px; }\\n/* Labels stay on one line: Turkish \\\"DAHA FAZLA\\\" wrapped to two in a ~115px button. */\\n.ss-g-hl-btns .ss-g-btn { font-weight: 800; font-size: 13px; letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }\\n.ss-g-hl-btns .ss-g-btn svg { flex: none; }\\n/* Phone-width cards: the info column is ~230px, too narrow for \\\"DAHA FAZLA\\\" + icon side by side.\\n   Drop the icons and tighten the type first; stack the buttons only when even that cannot fit. */\\n.ss-g-hl-info { container: hlinfo / inline-size; }\\n@container hlinfo (max-width: 280px) {\\n  .ss-g-hl-btns .ss-g-btn svg { display: none; }\\n  .ss-g-hl-btns .ss-g-btn { font-size: 12px; letter-spacing: 0; padding: 0 4px; }\\n}\\n@container hlinfo (max-width: 180px) {\\n  .ss-g-hl-btns { flex-direction: column; }\\n}\\n.ss-g-hl-vs { position: relative; z-index: 1; flex: none; align-self: center; width: 44px; height: 44px; margin: -28px 0; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-ground); border: 2px solid var(--ss-g-line-warm); color: var(--ss-w-accent); font: 800 18px var(--ss-g-font-display); }\\n/* Clear the VS badge that straddles the seam between the two cards. */\\n.ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 24px; }\\n.ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 24px; }\\n/* Short panels (a ~580px widget on a small laptop): tighten the type so both cards and the\\n   Higher/Lower buttons stay on screen; below this the body scrolls rather than clipping names. */\\n@container hl (max-height: 420px) {\\n  .ss-g-hl-prompt-stat { font-size: 24px; }\\n  .ss-g-hl-prompt-season { display: none; }\\n  .ss-g-hl-info { padding: 8px 12px; }\\n  .ss-g-hl-surname { font-size: 22px; }\\n  .ss-g-hl-value { font-size: 42px; margin-top: 2px; }\\n  .ss-g-hl-btns { margin-top: 8px; }\\n  .ss-g-hl-vs { width: 38px; height: 38px; margin: -22px 0; font-size: 15px; }\\n  .ss-g-hl-pair > .ss-g-hl-card:first-child .ss-g-hl-info { padding-bottom: 18px; }\\n  .ss-g-hl-vs + .ss-g-hl-card .ss-g-hl-info { padding-top: 18px; }\\n}\\n.ss-g-hl-feedback { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--ss-g-ink-2); }\\n.ss-g-hl-feedback[data-correct=\\\"true\\\"] svg { color: var(--ss-g-success); }\\n.ss-g-hl-feedback[data-correct=\\\"false\\\"] svg { color: var(--ss-g-wrong-mark); }\\n.ss-g-hl-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\\n.ss-g-hl-dots { display: flex; gap: 5px; }\\n.ss-g-hl-dot { width: 22px; height: 22px; border-radius: 50%; border: 1.5px dashed var(--ss-g-strong-line); }\\n.ss-g-hl-dot[data-state=\\\"correct\\\"] { background: var(--ss-g-correct); border: 0; }\\n.ss-g-hl-dot[data-state=\\\"wrong\\\"] { background: var(--ss-g-wrong-mark); border: 0; }\\n.ss-g-hl-pts { font: 700 22px var(--ss-g-font-display); white-space: nowrap; }\\n.ss-g-hl-pts-unit { font-size: 13px; color: var(--ss-g-muted); }\\n\\n/* ── Guess the XI (u393) ── pitch colours are the fixed --ss-g-pitch* tokens (Task 1) */\\n.ss-g-gxi-pitch { position: relative; flex: none; height: 380px; border-radius: 18px; overflow: hidden; border: 1px solid var(--ss-g-pitch-line);\\n  background: repeating-linear-gradient(180deg, color-mix(in srgb, var(--ss-g-pitch) 92%, var(--ss-g-pitch-mark)) 0 12.5%, var(--ss-g-pitch) 12.5% 25%); }\\n.ss-g-gxi-rows { position: absolute; inset: 14px 6px; display: flex; flex-direction: column; justify-content: space-between; }\\n.ss-g-gxi-row { display: flex; justify-content: space-evenly; align-items: flex-start; }\\n.ss-g-gxi-node { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; max-width: 72px; }\\n.ss-g-gxi-disc { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--ss-g-pitch-chip); border: 2px solid var(--ss-g-pitch-ink); font-size: 22px; line-height: 1; }\\n.ss-g-gxi-node[data-revealed] .ss-g-gxi-disc { border-color: var(--ss-w-accent); }\\n.ss-g-gxi-disc[data-code] { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; letter-spacing: .02em; color: var(--ss-g-pitch-ink); }\\n.ss-g-gxi-pos { max-width: 100%; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-pitch-chip); color: var(--ss-g-pitch-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-gxi-pos--name { color: var(--ss-w-accent); text-transform: uppercase; }\\n.ss-g-gxi-wrong { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }\\n.ss-g-gxi-wrong-l { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-gxi-wrong-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 6px; border-radius: 999px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; color: var(--ss-g-muted); }\\n/* u407: lineup photo — fills the 44px disc like the flag does */\\n.ss-g-gxi-disc--photo { overflow: hidden; border: 2px solid var(--ss-w-accent); }\\n.ss-g-gxi-disc--photo img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-gxi-disc--photo .ss-w-av-initials { font-family: var(--ss-g-font-body); font-size: 11px; font-weight: 800; color: var(--ss-g-pitch-ink); }\\n/* u407: answer reveal — prominent row using theme tokens, works on dark/navy/light surfaces */\\n.ss-g-gxi-answer { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 12px 16px; border-radius: 14px; background: var(--ss-g-warm); border: 1.5px solid var(--ss-g-line-warm); }\\n.ss-g-gxi-answer-label { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ss-g-muted); flex: none; }\\n.ss-g-gxi-answer-name { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; text-transform: uppercase; color: var(--ss-g-ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n\\n/* ---- Daily Quiz (u393) ---- */\\n.ss-g-dq-stem { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 30px; line-height: 1.05; overflow-wrap: anywhere; }\\n.ss-g-dq-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }\\n.ss-g-dq-opt { position: relative; min-height: 96px; padding: 44px 12px 12px; border-radius: 16px; border: 1.5px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); text-align: left; font: inherit; cursor: pointer; display: flex; align-items: flex-end; min-width: 0; }\\n.ss-g-dq-opt:hover:not(:disabled) { border-color: var(--ss-g-line-warm); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-dq-opt:disabled { cursor: default; }\\n.ss-g-dq-badge { position: absolute; top: 10px; left: 10px; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; background: var(--ss-g-raised); font-weight: 700; font-size: 13px; color: var(--ss-g-ink); }\\n.ss-g-dq-opt[aria-pressed=\\\"true\\\"] .ss-g-dq-badge { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-dq-opt-name { display: flex; flex-direction: column; min-width: 0; line-height: 1.05; }\\n.ss-g-dq-opt-first { font-size: 12px; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-dq-opt-last { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-dq-opt-suffix { margin-top: 2px; font-size: 12px; font-weight: 600; color: var(--ss-g-muted); }\\n.ss-g-dq-opt-full { font-size: 15px; font-weight: 600; line-height: 1.25; overflow-wrap: anywhere; }\\n.ss-g-dq-nav { display: flex; gap: 10px; }\\n.ss-g-dq-nav .ss-g-btn--block { flex: 1; }\\n.ss-g-dq-rq { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-dq-rq-stem { font-weight: 700; font-size: 14px; }\\n.ss-g-dq-rq-opts { display: flex; flex-wrap: wrap; gap: 6px; }\\n.ss-g-dq-rq-opt { padding: 4px 10px; border-radius: 999px; font-size: 13px; font-weight: 600; background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-dq-rq-opt--correct { background: var(--ss-g-correct); color: var(--ss-g-on-correct); }\\n.ss-g-dq-rq-opt--wrong { background: var(--ss-g-wrong); color: var(--ss-g-on-correct); }\\n.ss-g-dq-why { font-size: 13px; color: var(--ss-g-ink-2); }\\n/* u407: player avatar in quiz option — centered in top half, badge at top-left unaffected */\\n.ss-g-dq-opt-av { position: absolute; top: 7px; right: 10px; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 13px; font-weight: 700; flex: none; }\\n.ss-g-dq-opt-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-dq-opt-av .ss-w-av-initials { font-size: 11px; }\\n\\n/* ---- Career Path (u393) ---- */\\n.ss-g-cp-card { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: 16px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-cp-card-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1; }\\n.ss-g-cp-card-title { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 20px; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-cp-hint { font-size: 13px; color: var(--ss-g-ink-2); }\\n.ss-g-cp-locks { display: flex; gap: 6px; flex-wrap: wrap; }\\n.ss-g-cp-line { list-style: none; display: flex; flex-direction: column; }\\n.ss-g-cp-step { display: flex; gap: 14px; align-items: stretch; }\\n.ss-g-cp-rail { display: flex; flex-direction: column; align-items: center; width: 52px; flex: none; }\\n.ss-g-cp-tile { width: 52px; height: 52px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; }\\n.ss-g-cp-tile--locked { border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); }\\n.ss-g-cp-tile--faint { border: 1.5px dashed var(--ss-g-line); background: transparent; color: var(--ss-g-faint); }\\n.ss-g-cp-conn { width: 2px; flex: 1; min-height: 14px; background: var(--ss-g-line-warm); }\\n.ss-g-cp-conn--faint { background: var(--ss-g-line); }\\n.ss-g-cp-step:last-child .ss-g-cp-conn { display: none; }\\n.ss-g-cp-step-text { display: flex; flex-direction: column; justify-content: center; min-height: 52px; padding-bottom: 14px; min-width: 0; }\\n.ss-g-cp-club { font-weight: 700; font-size: 16px; overflow-wrap: anywhere; }\\n.ss-g-cp-sub { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-cp-loan { color: var(--ss-w-accent); font-weight: 600; }\\n\\n/* Game screen host: fills the panel; each screen owns its header, gutters and scrolling. */\\n.ss-w-gscreen-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 0; overflow: hidden; background: var(--ss-g-ground); }\\n.ss-w-gscreen { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0; }\\n.ss-w-gscreen-body { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 16px; color: var(--ss-w-faint); font-size: 13px; text-align: center; }\\n\\n/* ---- Leaderboard (D2) ---- */\\n/* Outer shell */\\n.ss-w-lb2 { display: flex; flex-direction: column; gap: 12px; }\\n\\n/* Segmented control: This week / All time */\\n.ss-w-seg { display: inline-flex; gap: 2px; align-self: flex-start; background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 9px; padding: 2px; }\\n.ss-w-seg-btn { font-size: 12px; font-weight: 600; border: none; border-radius: 7px; padding: 5px 12px; color: var(--ss-w-faint); background: none; cursor: pointer; font: inherit; white-space: nowrap; }\\n.ss-w-seg-btn[data-on] { color: var(--ss-w-ink); background: var(--ss-w-panel); box-shadow: 0 1px 3px rgba(0,0,0,.09); }\\n\\n/* Row list */\\n.ss-w-lb2-rows { display: flex; flex-direction: column; border: 1px solid var(--ss-w-line); border-radius: 12px; overflow: hidden; background: var(--ss-w-panel); }\\n.ss-w-lb2-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--ss-w-line); }\\n.ss-w-lb2-row:last-child { border-bottom: none; }\\n/* Highlighted \\\"you\\\" row: full-width tint via negative margin trick, contained by border-radius above */\\n.ss-w-lb2-row--you { background: color-mix(in srgb, var(--ss-w-accent) 9%, var(--ss-w-panel)); }\\n.ss-w-lb2-rank { flex: none; min-width: 30px; font-size: 12.5px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-faint); }\\n.ss-w-lb2-rank--top3 { color: var(--ss-w-cta); }\\n.ss-w-lb2-handle { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ss-w-ink); }\\n.ss-w-lb2-points { flex: none; font-size: 13px; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n.ss-w-lb2-streak { flex: none; font-size: 11px; font-weight: 700; color: var(--ss-w-accent); padding-left: 4px; }\\n\\n/* Kit-prize separator: a labelled hairline (eyebrow + two growing lines) */\\n.ss-w-kitline { display: flex; align-items: center; gap: 8px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ss-w-faint); }\\n.ss-w-kitline::before, .ss-w-kitline::after { content: \\\"\\\"; flex: 1; height: 1px; background: var(--ss-w-line); }\\n\\n/* Off-board treatment: dashed pill indicating rank is outside top N */\\n.ss-w-lbgap { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 12px; font-size: 11.5px; color: var(--ss-w-faint); border: 1px dashed var(--ss-w-line); border-radius: 10px; }\\n\\n/* ---- Leaderboard empty / weekly-reset default state ---- */\\n.ss-w-lb-empty { display: flex; flex-direction: column; gap: 12px; flex: 1; }\\n.ss-w-lb-empty-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 20px 16px; border: 1px dashed color-mix(in srgb, var(--ss-w-cta) 30%, var(--ss-w-line)); border-radius: 14px; background: color-mix(in srgb, var(--ss-w-cta) 6%, var(--ss-w-panel)); }\\n.ss-w-lb-empty--alltime { align-items: center; justify-content: center; text-align: center; padding: 24px 16px; }\\n.ss-w-lb-empty-icon { font-size: 30px; line-height: 1; }\\n.ss-w-lb-empty-title { margin: 2px 0 0; font-size: 16px; font-weight: 800; color: var(--ss-w-ink); }\\n.ss-w-lb-empty-body { margin: 0; max-width: 30ch; font-size: 12.5px; line-height: 1.4; color: var(--ss-w-faint); }\\n.ss-w-lb-empty-cta { margin-top: 6px; border: none; border-radius: 10px; padding: 9px 18px; font: inherit; font-size: 13px; font-weight: 700; color: var(--ss-w-cta-ink); background: var(--ss-w-cta); cursor: pointer; }\\n.ss-w-lb-empty-cta:hover { filter: brightness(1.04); }\\n.ss-w-lb-last { display: flex; align-items: center; gap: 7px; padding-top: 10px; border-top: 1px solid var(--ss-w-line); font-size: 11px; }\\n.ss-w-lb-last-label { text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--ss-w-faint); }\\n.ss-w-lb-last-handle { flex: 1; min-width: 0; font-weight: 600; color: var(--ss-w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\\n.ss-w-lb-last-points { flex: none; font-weight: 750; font-variant-numeric: tabular-nums; color: var(--ss-w-ink); }\\n\\n/* PlayerAvatar initials fallback (PlayerAvatar.tsx) — size/colour inherit from the avatar class. */\\n.ss-w-av-initials { font-weight: 800; line-height: 1; text-transform: uppercase; letter-spacing: .02em; }\\n\\n/* ---- Beat the Grid (u393) ---- */\\n.ss-g-btg-grid { display: grid; gap: 6px; }\\n/* While the search sheet is pinned below, the grid shrinks its rows to share the body with it\\n   instead of pushing the bottom row under the sheet. */\\n.ss-g-btg-grid--fit { flex: 0 1 auto; min-height: 0; }\\n.ss-g-btg-colhdr { min-height: 0; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; text-align: center; padding: 0 4px; font-size: 12px; font-weight: 700; line-height: 1.1; min-width: 0; overflow-wrap: anywhere; overflow: hidden; }\\n.ss-g-btg-colhdr[data-meta] { overflow-wrap: normal; word-break: normal; hyphens: none; font-size: 11px; letter-spacing: 0; }\\n.ss-g-btg-colhdr svg { color: var(--ss-w-accent); flex: none; }\\n.ss-g-btg-rowhdr { border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); display: grid; place-items: center; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; letter-spacing: .04em; text-transform: uppercase; overflow-wrap: anywhere; text-align: center; overflow: hidden; }\\n.ss-g-btg-rowhdr[data-meta] { font-size: 10px; font-family: var(--ss-g-font-body); font-weight: 700; letter-spacing: -0.01em; text-transform: none; word-break: normal; overflow-wrap: normal; hyphens: none; line-height: 1.25; padding: 0 2px; }\\n.ss-g-btg-cell { position: relative; min-height: 0; min-width: 0; border-radius: 12px; border: 1.5px dashed var(--ss-g-strong-line); background: transparent; color: var(--ss-g-muted); display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; cursor: pointer; font: inherit; padding: 0; }\\n.ss-g-btg-cell:disabled { cursor: default; }\\n.ss-g-btg-cell[data-state=\\\"active\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"], .ss-g-btg-cell[data-state=\\\"wrong\\\"] { justify-content: flex-end; background: var(--ss-g-surface); border-style: solid; }\\n.ss-g-btg-cell[data-state=\\\"correct\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] { border-color: var(--ss-g-wrong-mark); }\\n.ss-g-btg-badge { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center; color: var(--ss-g-on-correct); }\\n.ss-g-btg-badge--correct { background: var(--ss-g-correct); }\\n.ss-g-btg-badge--wrong { background: var(--ss-g-wrong); }\\n.ss-g-btg-rarity { position: absolute; top: 6px; left: 6px; padding: 1px 6px; border-radius: 999px; background: var(--ss-g-accent-tint); color: var(--ss-w-accent); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }\\n.ss-g-btg-cell[data-state=\\\"wrong\\\"] .ss-g-btg-rarity { background: var(--ss-g-raised); color: var(--ss-g-muted); }\\n.ss-g-btg-cell .ss-g-sil { border-radius: 0; background: transparent; }\\n.ss-g-btg-name { width: 100%; padding: 4px 2px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-family: var(--ss-g-font-display); font-weight: 700; font-size: 14px; text-transform: uppercase; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-plus { display: flex; }\\n.ss-g-btg-pin { flex: none; padding: 0 12px 12px; }\\n.ss-g-btg-sheet { padding: 14px; border-radius: 18px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); display: flex; flex-direction: column; gap: 12px; }\\n.ss-g-btg-sheet-hdr { display: flex; align-items: center; gap: 8px; min-width: 0; }\\n.ss-g-btg-sheet-hdr .ss-g-chip { padding: 4px 10px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-sheet-x { color: var(--ss-g-muted); display: flex; flex: none; }\\n.ss-g-btg-sheet-close { margin-left: auto; flex: none; width: 44px; height: 44px; border: 0; border-radius: 10px; background: transparent; color: var(--ss-g-muted); display: grid; place-items: center; cursor: pointer; }\\n.ss-g-btg-sheet-close:hover { background: var(--ss-g-raised); color: var(--ss-g-ink); }\\n.ss-g-btg-sheet .ss-g-search-box { height: 48px; border-radius: 12px; background: var(--ss-g-ground); }\\n.ss-g-btg-sheet-empty { font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-btg-sheet .ss-g-opt { background: var(--ss-g-raised); }\\n.ss-g-btg-sheet .ss-g-opts { max-height: 160px; }\\n.ss-g-btg-result-name { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-btg-result-plus { color: var(--ss-w-accent); display: flex; }\\n/* u407: cell avatar replaces Silhouette */\\n.ss-g-btg-av { width: 38px; height: 38px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 12px; font-weight: 700; }\\n.ss-g-btg-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-btg-av .ss-w-av-initials { font-size: 12px; }\\n/* u407: coach photo in row/col header */\\n.ss-g-btg-coach-av { width: 28px; height: 28px; flex: none; border-radius: 50%; overflow: hidden; background: var(--ss-g-raised); display: grid; place-items: center; color: var(--ss-g-muted); font-size: 10px; font-weight: 700; }\\n.ss-g-btg-coach-av img { width: 100%; height: 100%; object-fit: cover; }\\n/* u407: country flag emoji in header — sized to match other header icons */\\n.ss-g-btg-hdr-flag { font-size: 20px; line-height: 1; flex: none; }\\n/* u407: club crest in col/row header */\\n.ss-g-btg-colhdr .ss-g-crest, .ss-g-btg-rowhdr .ss-g-crest { width: 28px; height: 28px; flex: none; }\\n\\n/* ── Starting XI (u393) ── */\\n.ss-g-xi-pitch { position: relative; flex: none; height: 400px; border-radius: 18px; overflow: hidden; background: repeating-linear-gradient(180deg, var(--ss-g-pitch) 0 40px, color-mix(in srgb, var(--ss-g-pitch) 88%, var(--ss-g-pitch-mark)) 40px 80px); border: 1px solid var(--ss-g-pitch-line); }\\n.ss-g-xi-slot { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 48px; border: 0; padding: 0; background: transparent; color: var(--ss-g-pitch-mark); font: inherit; cursor: pointer; }\\n.ss-g-xi-slot:disabled { cursor: default; }\\n.ss-g-xi-ring { width: 48px; height: 48px; box-sizing: border-box; display: grid; place-items: center; border-radius: 50%; border: 1.5px dashed var(--ss-g-pitch-mark); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 20px; }\\n.ss-g-xi-slot[data-state=\\\"filled\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-accent-tint); color: var(--ss-g-ink); }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-ring { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); color: var(--ss-w-accent); }\\n.ss-g-xi-tag { max-width: 72px; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-ground); color: var(--ss-g-ink); font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-slot[data-state=\\\"active\\\"] .ss-g-xi-tag { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-xi-picker { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-xi-picker-head { display: flex; align-items: center; gap: 8px; font-size: 14px; }\\n.ss-g-xi-list { list-style: none; display: flex; flex-direction: column; gap: 4px; max-height: 240px; overflow-y: auto; }\\n.ss-g-xi-opt { width: 100%; display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 6px 10px; border: 0; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-xi-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-xi-opt-no { width: 28px; flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; color: var(--ss-w-accent); text-align: center; }\\n.ss-g-xi-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-xi-opt-pos { flex: none; padding: 1px 6px; border-radius: 4px; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 10px; font-weight: 700; }\\n.ss-g-xi-lock { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-xi-lock svg { color: var(--ss-w-accent); flex: none; }\\n\\n/* ── Stat Ladder (u393) ── */\\n.ss-g-sl-prompt { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 6px 0 6px; text-align: center; }\\n.ss-g-sl-stat { padding: 4px 10px; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }\\n.ss-g-sl-q { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; line-height: 1.05; text-transform: uppercase; }\\n.ss-g-sl-q em { font-style: normal; color: var(--ss-w-accent); }\\n.ss-g-sl-rungs { list-style: none; display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-sl-rung { min-height: 84px; display: flex; align-items: center; gap: 12px; padding: 0 16px 0 12px; border-radius: 16px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); }\\n.ss-g-sl-rung--mystery { min-height: 96px; border: 2px dashed var(--ss-w-accent); background: repeating-linear-gradient(-58deg, var(--ss-g-accent-tint) 0 14px, var(--ss-g-warm) 14px 32px); }\\n.ss-g-sl-rung--mystery[data-result=\\\"correct\\\"] { border: 2px solid var(--ss-g-correct); background: var(--ss-g-warm); }\\n.ss-g-sl-rung--mystery[data-result=\\\"wrong\\\"] { border: 2px solid var(--ss-g-wrong-mark); background: var(--ss-g-warm); }\\n.ss-g-sl-rank { width: 32px; height: 32px; flex: none; display: grid; place-items: center; border-radius: 10px; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; }\\n.ss-g-sl-rung:first-child .ss-g-sl-rank { background: var(--ss-g-accent-tint); color: var(--ss-w-accent); }\\n.ss-g-sl-rung--mystery .ss-g-sl-rank { background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-sl-av { width: 52px; height: 52px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-weight: 700; }\\n.ss-g-sl-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-sl-name { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.1; }\\n.ss-g-sl-name small { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-sl-name b { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-who { flex: 1; min-width: 0; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 22px; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-sl-val { flex: none; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 34px; line-height: 1; }\\n.ss-g-sl-val--mystery { font-size: 40px; color: var(--ss-w-accent); }\\n.ss-g-sl-clue { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border-radius: 14px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 13px; line-height: 1.4; color: var(--ss-g-ink-2); }\\n.ss-g-sl-clue svg { flex: none; color: var(--ss-w-accent); }\\n.ss-g-sl-pool { list-style: none; display: flex; flex-direction: column; gap: 4px; }\\n.ss-g-sl-opt { width: 100%; min-height: 48px; display: flex; align-items: center; gap: 12px; padding: 6px 10px; border: 1px solid transparent; border-radius: 12px; background: var(--ss-g-raised); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] { border-color: var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-sl-opt[aria-pressed=\\\"true\\\"] svg { color: var(--ss-w-accent); }\\n.ss-g-sl-opt:disabled { opacity: .5; cursor: default; }\\n.ss-g-sl-opt-av { width: 36px; height: 36px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-line); color: var(--ss-g-ink-2); font-size: 12px; font-weight: 700; }\\n.ss-g-sl-opt-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-sl-guess { display: flex; align-items: flex-end; gap: 8px; }\\n.ss-g-sl-guess .ss-g-search { flex: 1; min-width: 0; }\\n.ss-g-sl-guess .ss-g-btn { min-height: 50px; padding: 0 20px; border-radius: 14px; }\\n\\n/* ── Matchday Predictor (u393) ── */\\n.ss-g-mp-card { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 16px 10px; border-radius: 18px; background: var(--ss-g-warm); border: 1px solid var(--ss-g-line-warm); }\\n.ss-g-mp-team { width: 84px; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }\\n.ss-g-mp-team .ss-g-crest--ph { color: var(--ss-g-strong-line); }\\n.ss-g-mp-team-name { max-width: 100%; font-family: var(--ss-g-font-display); font-weight: 800; font-size: 17px; line-height: 1.05; text-transform: uppercase; overflow-wrap: anywhere; }\\n.ss-g-mp-team-side { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ss-g-muted); }\\n.ss-g-mp-scores { display: flex; align-items: center; gap: 8px; }\\n.ss-g-mp-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }\\n.ss-g-mp-step { width: 64px; height: 44px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--ss-g-line-warm); background: var(--ss-g-raised); color: var(--ss-g-ink); cursor: pointer; }\\n.ss-g-mp-step:disabled { opacity: .4; cursor: default; }\\n.ss-g-mp-digit { width: 64px; height: 76px; display: grid; place-items: center; box-sizing: border-box; border-radius: 12px; background: var(--ss-g-ground); border: 2px solid var(--ss-g-strong-line); font-family: var(--ss-g-font-display); font-weight: 800; font-size: 52px; line-height: 1; }\\n.ss-g-mp-digit[data-active=\\\"true\\\"] { border-color: var(--ss-w-accent); color: var(--ss-w-accent); }\\n.ss-g-mp-dash { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 30px; color: var(--ss-g-faint); }\\n.ss-g-mp-scorer { display: flex; flex-direction: column; gap: 10px; }\\n.ss-g-mp-sec-head { display: flex; align-items: baseline; justify-content: space-between; margin-top: 10px; }\\n.ss-g-mp-sec-head h3 { font-family: var(--ss-g-font-display); font-weight: 700; font-size: 18px; letter-spacing: .06em; text-transform: uppercase; }\\n.ss-g-mp-sec-head span { font-size: 12px; color: var(--ss-g-muted); }\\n.ss-g-mp-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }\\n.ss-g-mp-pcard { position: relative; min-width: 0; height: 116px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 6px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; cursor: pointer; }\\n.ss-g-mp-pcard[aria-pressed=\\\"true\\\"] { border: 2px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-mp-pcard:disabled { cursor: default; opacity: .6; }\\n.ss-g-mp-pcheck { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; background: var(--ss-w-accent); color: var(--ss-g-on-accent); }\\n.ss-g-mp-pname { max-width: 100%; font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-mp-none { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--ss-g-line); background: transparent; color: var(--ss-g-muted); font: 600 14px var(--ss-g-font-body); cursor: pointer; text-align: left; }\\n.ss-g-mp-radio { width: 18px; height: 18px; flex: none; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--ss-g-strong-line); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] { color: var(--ss-g-ink); border-color: var(--ss-g-line-warm); }\\n.ss-g-mp-none[aria-pressed=\\\"true\\\"] .ss-g-mp-radio { border-color: var(--ss-w-accent); background: var(--ss-w-accent); box-shadow: inset 0 0 0 3px var(--ss-g-ground); }\\n.ss-g-mp-closed { padding: 10px 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); color: var(--ss-g-muted); font-size: 13px; text-align: center; }\\n.ss-g-mp-fun { font-size: 11px; color: var(--ss-g-faint); text-align: center; }\\n.ss-g-mp-rows { list-style: none; display: flex; flex-direction: column; gap: 6px; }\\n.ss-g-mp-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 0 14px; border-radius: 12px; background: var(--ss-g-surface); border: 1px solid var(--ss-g-line); font-size: 14px; }\\n.ss-g-mp-row-k { color: var(--ss-g-ink-2); }\\n.ss-g-mp-row-v { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--ss-g-muted); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] { border-color: var(--ss-g-correct); }\\n.ss-g-mp-row[data-ok=\\\"true\\\"] .ss-g-mp-row-v { color: var(--ss-g-success); }\\n.ss-g-mp-row-d { color: var(--ss-g-ink); }\\n\\n/* ── Fan MOTM (u393) ── */\\n.ss-g-motm-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }\\n.ss-g-motm-row { width: 100%; min-height: 60px; display: flex; align-items: center; gap: 12px; padding: 0 14px 0 10px; border-radius: 14px; border: 1px solid var(--ss-g-line); background: var(--ss-g-surface); color: var(--ss-g-ink); font: inherit; text-align: left; cursor: pointer; }\\n.ss-g-motm-row:not(:disabled):hover { border-color: var(--ss-g-line-warm); }\\n.ss-g-motm-row:disabled { cursor: default; }\\n.ss-g-motm-row--voted { border: 1.5px solid var(--ss-w-accent); background: var(--ss-g-warm); }\\n.ss-g-motm-av { width: 40px; height: 40px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-ink-2); font-size: 13px; font-weight: 700; }\\n.ss-g-motm-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-motm-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-motm-pill { flex: none; padding: 3px 8px; font-size: 11px; }\\n.ss-g-motm-foot { font-size: 14px; font-weight: 600; }\\n.ss-g-motm-fun { font-size: 11px; color: var(--ss-g-faint); }\\n\\n/* ── tap-to-answer tray + per-game team-colour band (u503) ── */\\n.ss-g-tray { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; max-height: 150px; overflow-y: auto; overscroll-behavior: contain; padding: 2px; }\\n.ss-g-tray-chip { display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 78px; padding: 6px 4px; border: 1px solid var(--ss-g-line); border-radius: 14px; background: var(--ss-g-surface); color: var(--ss-g-ink); font-family: var(--ss-g-font-body); cursor: pointer; }\\n.ss-g-tray-chip:hover, .ss-g-tray-chip:focus-visible { background: var(--ss-g-raised); border-color: var(--ss-w-accent); outline: none; }\\n.ss-g-tray-chip:disabled { opacity: .5; cursor: default; }\\n.ss-g-tray-av { width: 38px; height: 38px; flex: none; border-radius: 50%; overflow: hidden; display: grid; place-items: center; background: var(--ss-g-raised); color: var(--ss-g-muted); font-size: 14px; font-weight: 700; }\\n.ss-g-tray-av img { width: 100%; height: 100%; object-fit: cover; }\\n.ss-g-tray-name { width: 100%; display: flex; flex-direction: column; align-items: center; line-height: 1.1; }\\n.ss-g-tray-first { max-width: 100%; font-size: 10px; font-weight: 500; color: var(--ss-g-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n.ss-g-tray-last { max-width: 100%; font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n\\n/* Each game gets its own band colour: the operator accent mixed into the ground, hue-nudged per game.\\n   Browsers without relative colour syntax keep the plain accent mix. */\\n.ss-g-screen[data-game] { --ss-g-band: color-mix(in srgb, var(--ss-w-accent) var(--ss-g-band-mix, 18%), var(--ss-g-ground)); }\\n@supports (color: oklch(from red l c h)) {\\n  .ss-g-screen[data-game] { --ss-g-band: oklch(from color-mix(in srgb, var(--ss-w-accent) var(--ss-g-band-mix, 18%), var(--ss-g-ground)) l calc(c * 1.5) calc(h + var(--ss-g-hue-shift, 0))); }\\n}\\n.ss-g-screen[data-game=\\\"mystery-tiger\\\"] { --ss-g-band-mix: 14%; --ss-g-hue-shift: 0; }\\n.ss-g-screen[data-game=\\\"career-path\\\"] { --ss-g-band-mix: 11%; --ss-g-hue-shift: -24; }\\n.ss-g-screen[data-game] > .ss-g-head { background: var(--ss-g-band); border-radius: 0 0 24px 24px; padding-bottom: 12px; }\\n.ss-g-worth { flex: none; display: flex; align-items: baseline; gap: 10px; font-size: 13px; color: var(--ss-g-muted); }\\n.ss-g-worth-now { font-family: var(--ss-g-font-display); font-weight: 800; font-size: 18px; letter-spacing: .02em; text-transform: uppercase; color: var(--ss-w-accent); }\\n.ss-g-screen[data-game=\\\"beat-the-grid\\\"] { --ss-g-band-mix: 13%; --ss-g-hue-shift: 14; }\\n.ss-g-screen[data-game=\\\"guess-the-xi\\\"] { --ss-g-band-mix: 12%; --ss-g-hue-shift: -36; }\\n.ss-g-screen[data-game=\\\"higher-or-lower\\\"] { --ss-g-band-mix: 16%; --ss-g-hue-shift: 28; }\\n.ss-g-screen[data-game=\\\"daily-quiz\\\"] { --ss-g-band-mix: 10%; --ss-g-hue-shift: -12; }\\n.ss-g-screen[data-game=\\\"stat-ladder\\\"] { --ss-g-band-mix: 15%; --ss-g-hue-shift: 36; }\\n.ss-g-screen[data-game=\\\"matchday-predictor\\\"] { --ss-g-band-mix: 18%; --ss-g-hue-shift: -4; }\\n.ss-g-screen[data-game=\\\"starting-xi\\\"] { --ss-g-band-mix: 9%; --ss-g-hue-shift: -30; }\\n.ss-g-screen[data-game=\\\"fan-motm\\\"] { --ss-g-band-mix: 14%; --ss-g-hue-shift: 8; }\\n\"\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,iBAAsF;AACtF,IAAAC,qBAAqD;;;ACD9C,SAAS,qBACd,YACA,IACA,QACA,MAAY,oBAAI,KAAK,GACe;AACpC,QAAM,KAAK,IAAI,KAAK,UAAU;AAC9B,QAAM,aAAa,WAAW,OAAO,UAAU;AAC/C,QAAM,OAAO,IAAI,KAAK,eAAe,YAAY,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,EAAE;AAClG,QAAM,cAAc,IAAI,KAAK,GAAG,YAAY,GAAG,GAAG,SAAS,GAAG,GAAG,QAAQ,CAAC;AAC1E,QAAM,eAAe,IAAI,KAAK,IAAI,YAAY,GAAG,IAAI,SAAS,GAAG,IAAI,QAAQ,CAAC;AAC9E,QAAM,UAAU,KAAK,OAAO,YAAY,QAAQ,IAAI,aAAa,QAAQ,KAAK,KAAU;AACxF,QAAM,WACJ,YAAY,IACR,GAAG,QACH,YAAY,IACV,GAAG,WACH,IAAI,KAAK,eAAe,YAAY,EAAE,SAAS,SAAS,KAAK,WAAW,OAAO,QAAQ,CAAC,EAAE,OAAO,EAAE;AAC3G,SAAO,EAAE,UAAU,KAAK;AAC1B;;;AC6NA,IAAM,gBAAgB,EAAE,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,GAAG,WAAW;AAC1F,IAAM,gBAAgB,EAAE,GAAG,cAAc,GAAG,0BAAqB,GAAG,6BAAwB,GAAG,aAAa;AAC5G,IAAM,cAAc,CAAC,MAAsB,IAAI,KAAK,aAAa,OAAO,EAAE,OAAO,CAAC;AAClF,IAAM,cAAc,CAAC,MAAsB,IAAI,KAAK,aAAa,OAAO,EAAE,OAAO,CAAC;AAElF,IAAM,OAAO,CAAC,MAAsB,EAAE,QAAQ,OAAO,MAAQ;AAC7D,IAAM,WAAW,CAAC,IAAY,SAC5B,KAAK,IAAI,KAAK,eAAe,SAAS,IAAI,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,EAAE,QAAQ,QAAQ,KAAK,CAAC;AACzF,IAAM,WAAW,CAAC,IAAY,SAC5B,KAAK,IAAI,KAAK,eAAe,SAAS,IAAI,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;AAiOlE,IAAM,UAAyC;AAAA,EAC7C,IAAI;AAAA,IACF,eAAe;AAAA,IACf,aAAa;AAAA,IACb,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,OAAO;AAAA,IACP,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,UAAU;AAAA,IACV,UAAU,CAAC,MAAM,QAAQ,CAAC;AAAA,IAC1B,YAAY,CAAC,MAAM,gBAAgB,CAAC;AAAA,IACpC,gBAAgB,CAAC,GAAG,MAAM,SAAS,OAAO,CAAC,gBAAgB,IAAI,MAAM,IAAI;AAAA,IACzE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,MACR,OAAO,CAAC,SAAS,eAAe,IAAI;AAAA,MACpC,WAAW;AAAA,MACX,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,IACA,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW,CAAC,KAAK,KAAK,cAAc,OAAO,GAAG,SAAS,GAAG,KAAK,SAAS;AAAA,IACxE,eAAe;AAAA,IACf,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB,CAAC,UAAW,QAAQ,OAAO,IAAI,QAAQ,QAAQ,EAAE,MAAM,QAAQ,KAAK;AAAA,IACpF,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,mBAAmB,CAAC,MAAM,GAAG,CAAC,mBAAmB,MAAM,IAAI,KAAK,GAAG;AAAA,IACnE,gBAAgB,CAAC,OACf,IAAI,KAAK,eAAe,SAAS,EAAE,KAAK,WAAW,OAAO,SAAS,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC;AAAA,IAC9H,WAAW,CAAC,SAAS,SAAS,WAAW,UAAU;AACjD,YAAM,OAAO,QAAQ,OAAO,IAAI,GAAG,QAAQ,EAAE,OAAO,QAAQ,OAAO,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,QAAQ,UAAU,IAAI,KAAK,GAAG;AAE1H,YAAM,QAAQ,YAAY,KAAK,SAAS,KAAK;AAC7C,aAAO,gCAAgC,IAAI,eAAe,OAAO,eAAe,OAAO,GAAG,KAAK;AAAA,IACjG;AAAA,IACA,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,eAAe;AAAA,IACf,kBAAkB,CAAC,MAAM,OAAO,YAAY,EAAE,SAAS,IAAI;AAAA,IAC3D,sBAAsB,CAAC,MAAM,OAAO,kBAAkB,EAAE,SAAS,IAAI;AAAA,IACrE,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,cAAc,CAAC,MAAM,WAAW,CAAC;AAAA,IACjC,eAAe,CAAC,MAAO,MAAM,IAAI,8BAA8B,iBAAiB,CAAC;AAAA,IACjF,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,YAAY,CAAC,MAAM,OAAO,CAAC;AAAA,IAC3B,kBAAkB,CAAC,MAAM,OAAO,CAAC;AAAA,IACjC,eAAe,CAAC,OAAO,IAAI,aAAa,GAAG,KAAK,OAAO,EAAE,sBAAsB,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAClI,OAAO;AAAA,IACP,UAAU;AAAA,IACV,gBAAgB,CAAC,YAAY,QAAQ,qBAAqB,YAAY,QAAQ,IAAI,MAAM,GAAG;AAAA,IAC3F,SAAS;AAAA,IACT,cAAc;AAAA,IACd,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,MAAM,CAAC,SAAS,gBAAgB,IAAI;AAAA,IACpC,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB,CAAC,MAAc,kBAAkB,CAAC;AAAA,IACnD,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,wBAAwB;AAAA,IACxB,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,mBAAmB,CAAC,QAAQ,aAAa,MAAM,GAAG,MAAM,IAAI,WAAW,eAAY,CAAC,QAAQ,MAAM,IAAI,KAAK,GAAG;AAAA,IAC9G,gBAAgB,CAAC,MAAM,MAAM,eAAe,IAAI,KAAK,CAAC;AAAA,IACtD,iBAAiB,CAAC,MAAM,MAAM,iBAAiB,IAAI,KAAK,CAAC;AAAA,IACzD,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB,CAAC,UAAU,QAAQ,cACnC,SAAS,SAAS,OAAO,IAAI,IAAI,QAAQ,KAAK,SAAS,MAAM,GAAG,OAC/D,cAAc,QAAQ,YAAY,IAAI,SAAM,SAAS,WAAW,EAAE,SAAS,SAAS,KAAK,WAAW,OAAO,QAAQ,CAAC,CAAC,KAAK;AAAA,IAC7H,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,yBAAyB;AAAA,IACzB,wBAAwB;AAAA,IACxB,kBAAkB,CAAC,OAAO,iBAAiB,SAAS,IAAI,EAAE,KAAK,WAAW,OAAO,QAAQ,CAAC,CAAC;AAAA,IAC3F,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,mBAAmB,CAAC,aAAa,UAAU,kBAAkB,WAAW,IAAI,cAAc,KAAmC,KAAK,KAAK;AAAA,IACvI,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,YAAY;AAAA,MACV,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,eAAe;AAAA,MACf,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,UAAU;AAAA,IACZ;AAAA,IACA,eAAe;AAAA,IACf,eAAe;AAAA,IACf,kBAAkB,CAAC,MAAM,WAAY,SAAS,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,IACvE,cAAc,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;AAAA,IACvC,cAAc,CAAC,OAAO,SAAS,IAAI,EAAE,KAAK,WAAW,OAAO,QAAQ,CAAC;AAAA,IACrE,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,qBAAqB,CAAC,MAAc,iBAAiB,CAAC;AAAA,IACtD,0BAA0B;AAAA,IAC1B,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,sBAAsB,CAAC,OAAe,UAAkB,GAAG,KAAK,OAAO,KAAK;AAAA,IAC5E,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,MAAM;AAAA,IACN,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,4BAA4B;AAAA,IAC5B,2BAA2B;AAAA,IAC3B,2BAA2B;AAAA,IAC3B,0BAA0B;AAAA,IAC1B,qBAAqB;AAAA,IACrB,0BAA0B;AAAA,IAC1B,yBAAyB;AAAA,IACzB,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,aAAa;AAAA,MACb,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY,CAAC,MAAM,GAAG,CAAC;AAAA,MACvB,SAAS,CAAC,UAAU,YAAY,MAAM,QAAQ,CAAC,CAAC;AAAA,MAChD,iBAAiB,CAAC,OAAO,UAAU,GAAG,KAAK,eAAe,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC1E,iBAAiB,CAAC,OAAO,UAAU,WAAW,KAAK,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,MACvF,iBAAiB,CAAC,OAAO,UAAU,GAAG,KAAK,eAAe,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC1E,iBAAiB,CAAC,OAAO,UAAU,WAAW,KAAK,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,MACvF,cAAc,CAAC,MAAM,UAAU,cAAc,IAAI,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,MACrF,cAAc,CAAC,MAAM,UAAU,uBAAuB,IAAI,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC9F,aAAa;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,cAAc;AAAA,MACd,UAAU;AAAA,MACV,aAAa;AAAA,MACb,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,aAAa,CAAC,KAAK,QAAQ,SAAS,EAAE,qBAAqB,QAAQ,eAAe,iBAAiB,iBAAiB,eAAe,GAA6B,GAAG,MAC7J,QAAQ,sBAAsB,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,KAAK;AAAA,MAC3E,eAAe,CAAC,QAAQ,KAAK,UAAU,WAAW,KAAK,IAAI,MAAM,GAAG,MAAM,WAAM,GAAG,KAAK,MAAM;AAAA,MAC9F,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,eAAe;AAAA,MACf,WAAW,CAAC,MAAM,YAAY,CAAC;AAAA,MAC/B,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU,SAAO,SAAS,GAAG;AAAA,MAC7B,gBAAgB,SAAO,GAAG,GAAG;AAAA,MAC7B,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,eAAe,CAAC,MAAM,cAAW,YAAY,CAAC,CAAC;AAAA,MAC/C,SAAS,CAAC,MAAM,SAAS,CAAC;AAAA,MAC1B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,OAAO;AAAA,MACP,eAAe,CAAC,QACd,IAAI,KAAK,eAAe,SAAS,EAAE,SAAS,SAAS,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,IAAI,KAAK,GAAG,CAAC;AAAA,MACjH,QAAQ;AAAA,QACN,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,mBAAmB;AAAA,QACnB,sBAAsB;AAAA,QACtB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,MACA,UAAU;AAAA,QACR,iBAAiB;AAAA,QACjB,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,sBAAsB;AAAA,QACtB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,MACA,cAAc;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ,EAAE,UAAU,OAAO,aAAa,OAAO,KAAK,OAAO,aAAa,OAAO,MAAM,OAAO;AAAA,QAC5F,aAAa;AAAA,QACb,aAAa;AAAA,QACb,aAAa;AAAA,QACb,cAAc;AAAA,QACd,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,UAAU,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,KAAK;AAAA,QAC9C,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI,UAAU,SAAS;AAAA,MACtD;AAAA,MACA,eAAe;AAAA,QACb,SAAS,CAAC,MAAM,IAAI,CAAC;AAAA,QACrB,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,QAAQ,CAAC,MAAM,GAAG,CAAC;AAAA,QACnB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,YAAY,CAAC,MAAM,UAAU,GAAG,IAAI,QAAQ,KAAK;AAAA,QACjD,cAAc,CAAC,GAAG,UAAU,GAAG,CAAC,OAAO,KAAK;AAAA,QAC5C,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,WAAW,CAAC,MAAM,GAAG,CAAC;AAAA,MACxB;AAAA,MACA,YAAY;AAAA,QACV,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,WAAW,CAAC,SAAS,4BAAyB,IAAI;AAAA,QAClD,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI,UAAU,SAAS;AAAA,QACpD,WAAW;AAAA,MACb;AAAA,MACA,WAAW;AAAA,QACT,YAAY,CAAC,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;AAAA,QAC3C,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,WAAW,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC;AAAA,QACjC,cAAc,CAAC,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;AAAA,MAC/C;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,eAAe;AAAA,QACf,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,WAAW;AAAA,QACX,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,WAAW,CAAC,MAAM,KAAK,CAAC,aAAa,MAAM,IAAI,KAAK,GAAG;AAAA,QACvD,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,aAAa,CAAC,MAAM,GAAG,CAAC,SAAS,MAAM,IAAI,KAAK,IAAI;AAAA,MACtD;AAAA,MACA,aAAa;AAAA,QACX,SAAS;AAAA,QACT,QAAQ,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC;AAAA,QAC9B,MAAM,CAAC,MAAM,GAAG,CAAC;AAAA,QACjB,cAAc,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC;AAAA,QACpC,WAAW,EAAE,YAAY,MAAM,UAAU,OAAO,YAAY,OAAO,SAAS,MAAM;AAAA,QAClF,UAAU,CAAC,GAAG,MAAM,UAAU,EAAE,YAAY,CAAC,SAAS,CAAC;AAAA,QACvD,YAAY,CAAC,GAAG,GAAG,MAAM,YAAY,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,QAAQ,YAAY,CAAC;AAAA,QACtF,SAAS;AAAA,QACT,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa,CAAC,GAAG,MAAM,qBAAqB,CAAC,SAAM,CAAC;AAAA,QACpD,mBAAmB;AAAA,QACnB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,QACT,SAAS,CAAC,MAAM,SAAS,GAAG,IAAI,MAAM,IAAI;AAAA,QAC1C,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,SAAS,GAAG,IAAI;AAAA,QAC1B,WAAW,CAAC,SAAS,GAAG,IAAI;AAAA,QAC5B,aAAa;AAAA,QACb,UAAU;AAAA,QACV,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,aAAa,CAAC,MACZ,GAAG,EAAE,OAAO,GAAG,EAAE,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,SAAI,EAAE,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE,GAAG,EAAE,SAAS,SAAM,EAAE,MAAM,WAAW,EAAE;AAAA,QAClH,UAAU,CAAC,GAAG,MAAM,aAAa,CAAC,WAAM,CAAC;AAAA,QACzC,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,YAAY,CAAC,MAAM,IAAI,CAAC;AAAA,QACxB,QAAQ,CAAC,MAAM,GAAG,CAAC;AAAA,QACnB,MAAM,CAAC,MAAM,GAAG,CAAC;AAAA,QACjB,UAAU,CAAC,QAAQ,QAAQ,GAAG;AAAA,QAC9B,WAAW,CAAC,KAAK,SAAS,UAAU,IAAI,SAAS,GAAG;AAAA,QACpD,SAAS,CAAC,QAAQ,aAAa,GAAG;AAAA,QAClC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS,CAAC,MAAM,SAAS,CAAC;AAAA,QAC1B,WAAW;AAAA,QACX,SAAS,CAAC,MAAM,yBAAyB,CAAC;AAAA,QAC1C,YAAY,CAAC,MAAM,GAAG,CAAC;AAAA,QACvB,QAAQ;AAAA,MACV;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU,CAAC,SAAS,aAAa,IAAI;AAAA,QACrC,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,UAAU,CAAC,UAAU,EAAE,KAAK,iBAAiB,MAAM,YAAY,MAAM,IAAI,KAAK,YAAY,CAAC,IAAI;AAAA,QAC/F,WAAW;AAAA,QACX,MAAM,CAAC,GAAG,SAAS;AACjB,gBAAM,QAAkB,CAAC;AACzB,cAAI,EAAE,MAAO,OAAM,KAAK,EAAE,MAAM,SAAS,IAAI,eAAe,EAAE,MAAM,IAAI,KAAK,GAAG,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,IAAI,EAAE;AACzH,cAAI,EAAE,MAAO,OAAM,KAAK,EAAE,MAAM,SAAS,IAAI,eAAe,EAAE,MAAM,IAAI,KAAK,GAAG,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,IAAI,EAAE;AACxH,iBAAO,aAAa,EAAE,KAAK,IAAI,KAAK,YAAY,CAAC,GAAG,MAAM,SAAS,KAAK,MAAM,KAAK,OAAO,CAAC,KAAK,EAAE;AAAA,QACpG;AAAA,QACA,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO,CAAC,SAAS,uBAAkB,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAAA,EACA,IAAI;AAAA,IACF,eAAe;AAAA,IACf,aAAa;AAAA,IACb,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,OAAO;AAAA,IACP,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,UAAU;AAAA,IACV,UAAU,CAAC,MAAM,GAAG,CAAC;AAAA,IACrB,YAAY,CAAC,MAAM,oBAAiB,CAAC;AAAA,IACrC,gBAAgB,CAAC,GAAG,MAAM,SAAS,GAAG,IAAI,MAAM,IAAI,KAAK,CAAC;AAAA,IAC1D,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,MACR,OAAO,CAAC,SAAS,GAAG,IAAI;AAAA,MACxB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,IACA,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW,CAAC,KAAK,KAAK,cAAc,WAAQ,GAAG,gBAAW,GAAG,KAAK,SAAS;AAAA,IAC3E,eAAe;AAAA,IACf,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB,CAAC,UAAW,QAAQ,OAAO,IAAI,OAAO,QAAQ,EAAE,YAAS,OAAO,KAAK;AAAA,IACrF,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,mBAAmB,CAAC,MAAM,GAAG,CAAC;AAAA,IAC9B,gBAAgB,CAAC,OACf,IAAI,KAAK,eAAe,SAAS,EAAE,KAAK,WAAW,OAAO,SAAS,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC;AAAA,IAC9H,WAAW,CAAC,SAAS,SAAS,WAAW,UAAU;AACjD,YAAM,OAAO,QAAQ,OAAO,IAAI,GAAG,QAAQ,EAAE,YAAS,GAAG,KAAK;AAC9D,YAAM,QAAQ,YAAY,KAAK,SAAS,KAAK;AAC7C,aAAO,OAAO,IAAI,+BAA4B,OAAO,0CAAwB,OAAO,GAAG,KAAK;AAAA,IAC9F;AAAA,IACA,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,eAAe;AAAA,IACf,kBAAkB,CAAC,MAAM,OAAO,GAAG,EAAE,qCAA6B,IAAI;AAAA,IACtE,sBAAsB,CAAC,MAAM,OAAO,QAAQ,EAAE,oBAAiB,IAAI;AAAA,IACnE,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,cAAc,CAAC,MAAM,GAAG,CAAC;AAAA,IACzB,eAAe,CAAC,MAAO,MAAM,IAAI,8BAA2B,SAAS,CAAC;AAAA,IACtE,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,YAAY,CAAC,MAAM,GAAG,CAAC;AAAA,IACvB,kBAAkB,CAAC,MAAM,GAAG,CAAC;AAAA,IAC7B,eAAe,CAAC,OAAO,IAAI,aAAa,GAAG,EAAE,gBAAa,KAAK,iCAAiC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAClJ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,gBAAgB,CAAC,YAAY,QAAQ,qBAAqB,YAAY,QAAQ,IAAI,MAAM,GAAG;AAAA,IAC3F,SAAS;AAAA,IACT,cAAc;AAAA,IACd,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,MAAM,CAAC,SAAS,YAAY,IAAI;AAAA,IAChC,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,aAAa;AAAA,IACb,iBAAiB,CAAC,MAAc,uBAAoB,CAAC;AAAA,IACrD,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,wBAAwB;AAAA,IACxB,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,mBAAmB,CAAC,QAAQ,aAAa,MAAM,GAAG,MAAM,IAAI,WAAW,SAAM,CAAC;AAAA,IAC9E,gBAAgB,CAAC,MAAM,MAAM,mBAAc,IAAI,KAAK,CAAC;AAAA,IACrD,iBAAiB,CAAC,MAAM,MAAM,iBAAiB,IAAI,KAAK,CAAC;AAAA,IACzD,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB,CAAC,UAAU,QAAQ,cACnC,YAAY,QAAQ,KAAK,SAAS,uBAAiB,WAAW,OAC7D,cAAc,QAAQ,YAAY,IAAI,SAAM,SAAS,WAAW,EAAE,KAAK,WAAW,OAAO,SAAS,SAAS,QAAQ,CAAC,CAAC,KAAK;AAAA,IAC7H,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,yBAAyB;AAAA,IACzB,wBAAwB;AAAA,IACxB,kBAAkB,CAAC,OAAO,qBAAU,SAAS,IAAI,EAAE,KAAK,WAAW,OAAO,QAAQ,CAAC,CAAC;AAAA,IACpF,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,mBAAmB,CAAC,aAAa,UAAU,GAAG,WAAW,IAAI,cAAc,KAAmC,KAAK,KAAK;AAAA,IACxH,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,YAAY;AAAA,MACV,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,eAAe;AAAA,MACf,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,UAAU;AAAA,IACZ;AAAA,IACA,eAAe;AAAA,IACf,eAAe;AAAA,IACf,kBAAkB,CAAC,MAAM,WAAY,SAAS,GAAG,IAAI,cAAS,GAAG,IAAI;AAAA,IACrE,cAAc,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;AAAA,IACvC,cAAc,CAAC,OAAO,SAAS,IAAI,EAAE,KAAK,WAAW,OAAO,QAAQ,CAAC;AAAA,IACrE,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,qBAAqB,CAAC,MAAc,qBAAe,CAAC;AAAA,IACpD,0BAA0B;AAAA,IAC1B,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,sBAAsB,CAAC,OAAe,UAAkB,GAAG,KAAK,MAAM,KAAK;AAAA,IAC3E,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,IACpB,MAAM;AAAA,IACN,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,4BAA4B;AAAA,IAC5B,2BAA2B;AAAA,IAC3B,2BAA2B;AAAA,IAC3B,0BAA0B;AAAA,IAC1B,qBAAqB;AAAA,IACrB,0BAA0B;AAAA,IAC1B,yBAAyB;AAAA,IACzB,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,aAAa;AAAA,MACb,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY,CAAC,MAAM,GAAG,CAAC;AAAA,MACvB,SAAS,CAAC,UAAU,GAAG,MAAM,QAAQ,CAAC,CAAC;AAAA,MACvC,iBAAiB,CAAC,OAAO,UAAU,GAAG,KAAK,uBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC/E,iBAAiB,CAAC,OAAO,UAAU,GAAG,MAAM,QAAQ,CAAC,CAAC,+BAAqB,KAAK;AAAA,MAChF,iBAAiB,CAAC,OAAO,UAAU,GAAG,KAAK,cAAW,MAAM,QAAQ,CAAC,CAAC;AAAA,MACtE,iBAAiB,CAAC,OAAO,UAAU,GAAG,MAAM,QAAQ,CAAC,CAAC,8BAAsB,KAAK;AAAA,MACjF,cAAc,CAAC,MAAM,UAAU,GAAG,IAAI,8CAA4B,MAAM,QAAQ,CAAC,CAAC;AAAA,MAClF,cAAc,CAAC,MAAM,UAAU,sBAAY,MAAM,QAAQ,CAAC,CAAC,gBAAW,IAAI;AAAA,MAC1E,aAAa;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,cAAc;AAAA,MACd,UAAU;AAAA,MACV,aAAa;AAAA,MACb,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,aAAa,CAAC,KAAK,QAAQ,SAAS,EAAE,qBAAqB,UAAU,eAAe,sBAAc,iBAAiB,gBAAa,GAA6B,GAAG,MAC1J,QAAQ,sBAAsB,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,KAAK;AAAA,MAC3E,eAAe,CAAC,QAAQ,KAAK,UAAU,GAAG,KAAK,IAAI,MAAM,GAAG,MAAM,WAAM,GAAG,KAAK,MAAM;AAAA,MACtF,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,eAAe;AAAA,MACf,WAAW,CAAC,MAAM,gBAAW,CAAC;AAAA,MAC9B,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,UAAU;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU,SAAO,cAAS,GAAG;AAAA,MAC7B,gBAAgB,SAAO,sBAAY,GAAG;AAAA,MACtC,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,eAAe,CAAC,MAAM,yBAAiB,YAAY,CAAC,CAAC;AAAA,MACrD,SAAS,CAAC,MAAM,SAAS,CAAC;AAAA,MAC1B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,OAAO;AAAA,MACP,eAAe,CAAC,QACd,IAAI,KAAK,eAAe,SAAS,EAAE,SAAS,SAAS,MAAM,WAAW,QAAQ,UAAU,CAAC,EAAE,OAAO,IAAI,KAAK,GAAG,CAAC;AAAA,MACjH,QAAQ;AAAA,QACN,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,mBAAmB;AAAA,QACnB,sBAAsB;AAAA,QACtB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,MACA,UAAU;AAAA,QACR,iBAAiB;AAAA,QACjB,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,sBAAsB;AAAA,QACtB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,MACA,cAAc;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ,EAAE,UAAU,OAAO,aAAa,OAAO,KAAK,YAAO,aAAa,OAAO,MAAM,SAAM;AAAA,QAC3F,aAAa;AAAA,QACb,aAAa;AAAA,QACb,aAAa;AAAA,QACb,cAAc;AAAA,QACd,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,UAAU,CAAC,MAAM,UAAU,GAAG,KAAK,cAAc,IAAI;AAAA,QACrD,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,eAAe;AAAA,QACb,SAAS,CAAC,MAAM,gCAAiB,CAAC;AAAA,QAClC,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,QAAQ,CAAC,MAAM,GAAG,CAAC;AAAA,QACnB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,YAAY,CAAC,MAAM,UAAU,GAAG,IAAI,KAAK,KAAK;AAAA,QAC9C,cAAc,CAAC,GAAG,UAAU,GAAG,KAAK,yBAAe,CAAC;AAAA,QACpD,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,WAAW,CAAC,MAAM,kBAAY,CAAC;AAAA,MACjC;AAAA,MACA,YAAY;AAAA,QACV,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,WAAW,CAAC,SAAS,2BAAqB,IAAI;AAAA,QAC9C,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM,GAAG,CAAC;AAAA,QACnB,WAAW;AAAA,MACb;AAAA,MACA,WAAW;AAAA,QACT,YAAY,CAAC,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;AAAA,QACtC,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,WAAW,CAAC,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC;AAAA,QACrC,cAAc,CAAC,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;AAAA,MAC1C;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,eAAe;AAAA,QACf,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,WAAW;AAAA,QACX,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,WAAW,CAAC,MAAM,KAAK,CAAC;AAAA,QACxB,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,aAAa,CAAC,MAAM,GAAG,CAAC;AAAA,MAC1B;AAAA,MACA,aAAa;AAAA,QACX,SAAS;AAAA,QACT,QAAQ,CAAC,GAAG,MAAM,GAAG,CAAC,gBAAa,CAAC;AAAA,QACpC,MAAM,CAAC,MAAM,GAAG,CAAC;AAAA,QACjB,cAAc,CAAC,GAAG,MAAM,GAAG,CAAC,gBAAa,CAAC;AAAA,QAC1C,WAAW,EAAE,YAAY,MAAM,UAAU,OAAO,YAAY,MAAM,SAAS,KAAK;AAAA,QAChF,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,SAAM,CAAC;AAAA,QAC/B,YAAY,CAAC,GAAG,GAAG,MAAM,YAAY,GAAG,CAAC,SAAM,CAAC,KAAK,IAAI,KAAK,QAAQ,kBAAkB,IAAI,CAAC;AAAA,QAC7F,SAAS;AAAA,QACT,OAAO;AAAA,QACP,aAAa;AAAA,QACb,aAAa,CAAC,GAAG,MAAM,GAAG,CAAC,SAAM,CAAC;AAAA,QAClC,mBAAmB;AAAA,QACnB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS,CAAC,GAAG,MAAM,GAAG,CAAC,eAAY,CAAC;AAAA,MACtC;AAAA,MACA,WAAW;AAAA,QACT,SAAS,CAAC,MAAM,SAAS,GAAG,IAAI,MAAM,IAAI;AAAA,QAC1C,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,SAAS,GAAG,IAAI;AAAA,QAC1B,WAAW,CAAC,SAAS,GAAG,IAAI;AAAA,QAC5B,aAAa;AAAA,QACb,UAAU;AAAA,QACV,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,aAAa,CAAC,MACZ,GAAG,EAAE,OAAO,GAAG,EAAE,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,SAAI,EAAE,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE,GAAG,EAAE,SAAS,iBAAc,EAAE,MAAM,KAAK,EAAE;AAAA,QACpH,UAAU,CAAC,GAAG,MAAM,eAAY,CAAC,WAAM,CAAC;AAAA,QACxC,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,YAAY,CAAC,MAAM,wCAAyB,CAAC;AAAA,QAC7C,QAAQ,CAAC,MAAM,gBAAgB,CAAC;AAAA,QAChC,MAAM,CAAC,MAAM,GAAG,CAAC;AAAA,QACjB,UAAU,CAAC,QAAQ,GAAG,GAAG;AAAA,QACzB,WAAW,CAAC,KAAK,SAAS,GAAG,IAAI,eAAe,GAAG;AAAA,QACnD,SAAS,CAAC,QAAQ,GAAG,GAAG;AAAA,QACxB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS,CAAC,MAAM,GAAG,CAAC;AAAA,QACpB,WAAW;AAAA,QACX,SAAS,CAAC,MAAM,sBAAsB,CAAC;AAAA,QACvC,YAAY,CAAC,MAAM,gBAAgB,CAAC;AAAA,QACpC,QAAQ;AAAA,MACV;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU,CAAC,SAAS,GAAG,IAAI;AAAA,QAC3B,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,UAAU,CAAC,UAAU,EAAE,KAAK,GAAG,KAAK,kBAAkB,IAAI,CAAC,6BAAmB,MAAM,kBAAa,MAAM,YAAY;AAAA,QACnH,WAAW;AAAA,QACX,MAAM,CAAC,GAAG,SAAS;AACjB,gBAAM,QAAkB,CAAC;AACzB,cAAI,EAAE,MAAO,OAAM,KAAK,EAAE,MAAM,SAAS,IAAI,GAAG,EAAE,MAAM,IAAI,mBAAc,GAAG,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,IAAI,QAAQ;AAC9H,cAAI,EAAE,MAAO,OAAM,KAAK,EAAE,MAAM,SAAS,IAAI,GAAG,EAAE,MAAM,IAAI,mBAAc,GAAG,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,IAAI,QAAQ;AAC9H,iBAAO,GAAG,EAAE,KAAK,IAAI,KAAK,kBAAkB,IAAI,CAAC,GAAG,MAAM,SAAS,KAAK,MAAM,KAAK,MAAM,CAAC,KAAK,EAAE;AAAA,QACnG;AAAA,QACA,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO,CAAC,SAAS,4CAAwB,IAAI;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,QAAgC;AACnE,SAAO,QAAQ,MAAgB,KAAK,QAAQ;AAC9C;AAIO,SAAS,gBAAgB,QAA0B;AACxD,QAAM,QAAQ,UAAU,IAAI,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,EAAE,CAAC,KAAK;AACrE,SAAO,SAAS,QAAQ,CAAC,OAAO,UAAU,eAAe,KAAK,SAAS,IAAI;AAC7E;;;AC/nCO,SAAS,YAAY,KAAgD;AAC1E,QAAM,UAAU,qBAAqB,IAAI,MAAM;AAC/C,SAAO;AAAA,IACL,OAAO,IAAI,SAAS;AAAA,IACpB,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,aAAa,IAAI;AAAA,IACjB,QAAQ,IAAI,UAAU;AAAA,IACtB,kBAAkB,gBAAgB,IAAI,MAAM;AAAA,IAC5C,KAAK,IAAI;AAAA,IACT,SAAS,IAAI;AAAA,IACb,KAAK,IAAI;AAAA,IACT,SAAS,IAAI,WAAW;AAAA,IACxB,UAAU,IAAI,YAAY;AAAA,IAC1B,QAAQ,EAAE,GAAG,IAAI,QAAQ,KAAK,IAAI,GAAG,IAAI,QAAQ,KAAK,GAAG;AAAA,IACzD,QAAQ,IAAI,UAAU;AAAA,IACtB,eAAe,IAAI,iBAAiB,QAAQ;AAAA,IAC5C,UAAU,IAAI;AAAA,IACd,iBAAiB,IAAI;AAAA,IACrB,aAAa,IAAI,eAAe,QAAQ;AAAA,IACxC,UAAU,IAAI,YAAY,CAAC;AAAA,IAC3B,cAAc,IAAI,gBAAgB;AAAA,IAClC,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,IACzB,aAAa,QAAQ;AAAA,IACrB,iBAAiB,QAAQ;AAAA,IACzB,cAAc,QAAQ;AAAA,IACtB,aAAa,QAAQ;AAAA,IACrB,iBAAiB,QAAQ;AAAA,IACzB,oBAAoB,QAAQ;AAAA,IAC5B,OAAO,QAAQ;AAAA,IACf,eAAe,QAAQ;AAAA,IACvB,qBAAqB,QAAQ;AAAA,IAC7B,sBAAsB,QAAQ;AAAA,IAC9B,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,IACpB,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ;AAAA,IACtB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,eAAe,QAAQ;AAAA,IACvB,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,IACtB,eAAe,QAAQ;AAAA,IACvB,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,kBAAkB,QAAQ;AAAA,IAC1B,kBAAkB,QAAQ;AAAA,IAC1B,oBAAoB,QAAQ;AAAA,IAC5B,mBAAmB,QAAQ;AAAA,IAC3B,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,sBAAsB,QAAQ;AAAA,IAC9B,mBAAmB,QAAQ;AAAA,IAC3B,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,eAAe,QAAQ;AAAA,IACvB,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,IACzB,YAAY,QAAQ;AAAA,IACpB,kBAAkB,QAAQ;AAAA,IAC1B,eAAe,QAAQ;AAAA,IACvB,OAAO,QAAQ;AAAA,IACf,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,SAAS,QAAQ;AAAA,IACjB,cAAc,QAAQ;AAAA,IACtB,SAAS,QAAQ;AAAA,IACjB,UAAU,QAAQ;AAAA,IAClB,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,IACtB,UAAU,QAAQ;AAAA,IAClB,mBAAmB,QAAQ;AAAA,IAC3B,oBAAoB,QAAQ;AAAA,IAC5B,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,IAClB,oBAAoB,QAAQ;AAAA,IAC5B,kBAAkB,QAAQ;AAAA,IAC1B,oBAAoB,QAAQ;AAAA,IAC5B,kBAAkB,QAAQ;AAAA,IAC1B,YAAY,QAAQ;AAAA,IACpB,qBAAqB,QAAQ;AAAA,IAC7B,uBAAuB,QAAQ;AAAA,IAC/B,kBAAkB,QAAQ;AAAA,IAC1B,iBAAiB,QAAQ;AAAA,IACzB,gBAAgB,QAAQ;AAAA,IACxB,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,WAAW,QAAQ;AAAA,IACnB,cAAc,QAAQ;AAAA,IACtB,mBAAmB,QAAQ;AAAA,IAC3B,WAAW,QAAQ;AAAA,IACnB,cAAc,QAAQ;AAAA,IACtB,YAAY,QAAQ;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,mBAAmB,QAAQ;AAAA,IAC3B,wBAAwB,QAAQ;AAAA,IAChC,oBAAoB,QAAQ;AAAA,IAC5B,cAAc,QAAQ;AAAA,IACtB,kBAAkB,QAAQ;AAAA,IAC1B,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,IACtB,eAAe,QAAQ;AAAA,IACvB,iBAAiB,QAAQ;AAAA,IACzB,gBAAgB,QAAQ;AAAA,IACxB,aAAa,QAAQ;AAAA,IACrB,gBAAgB,QAAQ;AAAA,IACxB,mBAAmB,QAAQ;AAAA,IAC3B,gBAAgB,QAAQ;AAAA,IACxB,iBAAiB,QAAQ;AAAA,IACzB,eAAe,QAAQ;AAAA,IACvB,eAAe,QAAQ;AAAA,IACvB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,kBAAkB,QAAQ;AAAA,IAC1B,uBAAuB,QAAQ;AAAA,IAC/B,qBAAqB,QAAQ;AAAA,IAC7B,uBAAuB,QAAQ;AAAA,IAC/B,yBAAyB,QAAQ;AAAA,IACjC,wBAAwB,QAAQ;AAAA,IAChC,kBAAkB,QAAQ;AAAA,IAC1B,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,mBAAmB,QAAQ;AAAA,IAC3B,cAAc,QAAQ;AAAA,IACtB,oBAAoB,QAAQ;AAAA,IAC5B,sBAAsB,QAAQ;AAAA,IAC9B,mBAAmB,QAAQ;AAAA,IAC3B,kBAAkB,QAAQ;AAAA,IAC1B,qBAAqB,QAAQ;AAAA,IAC7B,oBAAoB,QAAQ;AAAA,IAC5B,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ;AAAA,IACvB,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,oBAAoB,QAAQ;AAAA,IAC5B,iBAAiB,QAAQ;AAAA,IACzB,mBAAmB,QAAQ;AAAA,IAC3B,kBAAkB,QAAQ;AAAA,IAC1B,sBAAsB,QAAQ;AAAA,IAC9B,oBAAoB,QAAQ;AAAA,IAC5B,kBAAkB,QAAQ;AAAA,IAC1B,aAAa,QAAQ;AAAA,IACrB,aAAa,QAAQ;AAAA,IACrB,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,IACpB,qBAAqB,QAAQ;AAAA,IAC7B,0BAA0B,QAAQ;AAAA,IAClC,iBAAiB,QAAQ;AAAA,IACzB,kBAAkB,QAAQ;AAAA,IAC1B,aAAa,QAAQ;AAAA,IACrB,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,sBAAsB,QAAQ;AAAA,IAC9B,iBAAiB,QAAQ;AAAA,IACzB,iBAAiB,QAAQ;AAAA,IACzB,UAAU,QAAQ;AAAA,IAClB,aAAa,QAAQ;AAAA,IACrB,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ;AAAA,IACvB,iBAAiB,QAAQ;AAAA,IACzB,kBAAkB,QAAQ;AAAA,IAC1B,mBAAmB,QAAQ;AAAA,IAC3B,iBAAiB,QAAQ;AAAA,IACzB,cAAc,QAAQ;AAAA,IACtB,MAAM,QAAQ;AAAA,IACd,WAAW,QAAQ;AAAA,IACnB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,cAAc,QAAQ;AAAA,IACtB,aAAa,QAAQ;AAAA,IACrB,iBAAiB,QAAQ;AAAA,IACzB,eAAe,QAAQ;AAAA,IACvB,iBAAiB,QAAQ;AAAA,IACzB,eAAe,QAAQ;AAAA,IACvB,aAAa,QAAQ;AAAA,IACrB,iBAAiB,QAAQ;AAAA,IACzB,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,oBAAoB,QAAQ;AAAA,IAC5B,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,oBAAoB,QAAQ;AAAA,IAC5B,MAAM,QAAQ;AAAA,IACd,qBAAqB,QAAQ;AAAA,IAC7B,qBAAqB,QAAQ;AAAA,IAC7B,oBAAoB,QAAQ;AAAA,IAC5B,4BAA4B,QAAQ;AAAA,IACpC,2BAA2B,QAAQ;AAAA,IACnC,2BAA2B,QAAQ;AAAA,IACnC,0BAA0B,QAAQ;AAAA,IAClC,qBAAqB,QAAQ;AAAA,IAC7B,0BAA0B,QAAQ;AAAA,IAClC,yBAAyB,QAAQ;AAAA,IACjC,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,UAAU,QAAQ;AAAA,EACpB;AACF;AAEO,SAAS,gBAAgB,KAAkD;AAChF,QAAM,OAAiC,EAAE,YAAY,IAAI,YAAY,WAAW,IAAI,UAAU;AAC9F,MAAI,IAAI,YAAY,OAAW,MAAK,UAAU,IAAI;AAClD,SAAO;AACT;AAEO,SAAS,cAAc,KAAiD;AAC7E,SAAO,IAAI,eAAe,OAAO,KAAK,IAAI,WAAW,EAAE,SAAS,IAAI,IAAI,cAAc;AACxF;;;ACjgBO,IAAM,eAAe;AACrB,IAAM,eAAe;AAE5B,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,UAAU;AAMhB,IAAM,oBAAoB;AAI1B,IAAM,kBAAkB;AAExB,IAAM,SAAS,CAAC,MAAsB,KAAK,MAAM,IAAI,GAAG,IAAI;AAErD,SAAS,cAAc,SAA8C;AAC1E,MAAI,QAAQ,SAAS,EAAG,QAAO;AAG/B,QAAM,OAAO,QAAQ,CAAC,EAAG;AACzB,QAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC,EAAG;AAC1C,MAAI,QAAQ,KAAM,QAAO;AAEzB,QAAM,SAAS,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK;AACzC,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM;AAC/B,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM;AAE/B,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,MAAM;AACjB,WAAO,OAAO;AACd,WAAO,OAAO;AAAA,EAChB,OAAO;AACL,UAAM,OAAO,OAAO,QAAQ;AAC5B,WAAO,OAAO;AACd,WAAO,OAAO;AAAA,EAChB;AAEA,QAAM,IAAI,CAAC,SACT,OAAO,WAAY,OAAO,SAAS,OAAO,SAAU,UAAU,QAAQ;AACxE,QAAM,IAAI,CAAC,UACT,OAAO,WAAY,QAAQ,SAAS,OAAO,SAAU,UAAU,QAAQ;AAEzE,QAAM,YAAY,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,GAAG,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE;AACtE,QAAM,OAAO,UAAU,IAAI,CAAC,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG;AAEpF,SAAO;AAAA,IACL;AAAA,IACA,SAAS,QAAQ,UAAU,oBAAoB,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA,IAI5D,WAAW,SAAS,OAChB,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,KAAK,CAAC,IAC5B;AAAA,MACE,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,KAAK;AAAA,MAC1B,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,KAAK;AAAA,IAC5B;AAAA,IACJ,SAAS,OAAO,YAAY,IAAI,YAAY;AAAA,IAC5C,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AACF;;;ACiBA,SAAS,IAAI,GAAgC;AAC3C,SAAO,OAAO,MAAM,YAAY,EAAE,SAAS,IAAI,IAAI;AACrD;AACA,SAAS,IAAI,GAAgC;AAC3C,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI;AACnE;AAEA,SAAS,cAAc,KAA0B;AAC/C,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACjC,QAAM,QAAoB,CAAC;AAC3B,aAAW,SAAS,KAAuC;AACzD,UAAM,QAAQ,IAAI,MAAM,KAAK;AAC7B,UAAM,QAAQ,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK;AACjD,QAAI,UAAU,UAAa,UAAU,OAAW,OAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAC7E;AACA,SAAO;AACT;AAEO,SAAS,SAAS,MAA0B;AACjD,QAAM,aAAa,IAAI,KAAK,UAAU,GAAG,YAAY;AACrD,QAAM,OAAiB,eAAe,WAAW,WAAW,eAAe,SAAS,SAAS;AAC7F,QAAM,SAAS,MAAM,QAAQ,KAAK,MAAM,IACnC,KAAK,OACH,IAAI,CAAC,MAAwB;AAC5B,UAAM,QAAQ,IAAI,EAAE,KAAK;AACzB,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO;AAAA,MACL,eAAe,OAAO,EAAE,kBAAkB,WAAW,EAAE,gBAAgB;AAAA,MACvE;AAAA,MACA,OAAO,IAAI,EAAE,SAAS;AAAA,MACtB,OAAO,cAAc,EAAE,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC,EACA,OAAO,CAAC,MAAsB,MAAM,IAAI,IAC3C,CAAC;AACL,SAAO;AAAA,IACL,IAAI,OAAO,KAAK,QAAQ;AAAA,IACxB;AAAA,IACA,MAAM,KAAK;AAAA,IACX,OAAO,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAK,IAAI;AAAA,IAC7G,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,KAAK,QAAQ;AAAA,IAC1F,QAAQ,IAAI,KAAK,UAAU;AAAA,IAC3B;AAAA,EACF;AACF;AAEO,SAAS,WAAW,QAA2C;AACpE,QAAM,QAAQ,IAAI,OAAO,WAAW,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK;AACvG,QAAM,WAAW,IAAI,OAAO,QAAQ,KAAK,IAAI,OAAO,EAAE;AACtD,QAAM,YAAY,IAAI,OAAO,SAAS;AACtC,QAAM,UAAU,IAAI,OAAO,WAAW,KAAK,IAAI,OAAO,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK;AACvF,SAAO,EAAE,OAAO,UAAU,WAAW,QAAQ;AAC/C;AAEO,SAAS,SAAS,QAAgD;AACvE,QAAM,OAAO,IAAI,OAAO,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK;AACtE,SAAO,OAAO,EAAE,KAAK,IAAI;AAC3B;AAEO,SAAS,aAAa,MAAsB;AACjD,SAAO,EAAE,KAAK;AAChB;AAIO,SAAS,cAAc,OAAgB,MAAmC;AAC/E,MAAI,SAAS,QAAQ,MAAM,SAAS,IAAI,EAAG,QAAO;AAClD,SAAO,CAAC,OAAO,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK;AACpD;AAEO,SAAS,YAAY,SAAoC;AAC9D,QAAM,SAAS,IAAI,QAAQ,WAAW,KAAK,IAAI,QAAQ,mBAAmB,KAAK;AAC/E,QAAM,iBAAiB,IAAI,QAAQ,cAAc;AACjD,QAAM,gBAAgB,IAAI,QAAQ,IAAI;AACtC,QAAM,YAAY,cAAc,gBAAgB,aAAa;AAC7D,QAAM,QAAQ,QAAQ,MAAM;AAC5B,QAAM,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,MAAM,QAAQ,CAAC,IAAI;AACtF,QAAM,YAAY,QAAQ,MAAM;AAChC,QAAM,cAAc,OAAO,QAAQ,MAAM,gBAAgB,WAAW,QAAQ,KAAK,cAAc;AAC/F,QAAM,OAAO,IAAI,QAAQ,YAAY;AACrC,QAAM,OAAO,IAAI,QAAQ,YAAY;AACrC,QAAM,UAAU,QAAQ,OAAO,GAAG,IAAI,OAAO,IAAI,KAAK;AACtD,QAAM,cAAc,IAAI,QAAQ,eAAe;AAC/C,QAAM,gBAAgB,QAAQ,MAAM;AACpC,QAAM,WACJ,OAAO,kBAAkB,YAAY,OAAO,SAAS,aAAa,IAAI,gBAAgB;AACxF,QAAM,YACJ,QAAQ,MAAM,sBAAsB,eAAe,QAAQ,MAAM,sBAAsB,YACnF,QAAQ,KAAK,oBACb;AACN,SAAO;AAAA,IACL,IAAI,IAAI,QAAQ,SAAS,KAAK,GAAG,IAAI,QAAQ,MAAM,KAAK,SAAS,IAAI,IAAI,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC/F;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA,WAAW,IAAI,QAAQ,MAAM,aAAa;AAAA,IAC1C,QAAQ,QAAQ,MAAM,WAAW;AAAA,IACjC,OAAO,IAAI,QAAQ,KAAK;AAAA,IACxB;AAAA,IACA;AAAA,IACA,MAAM,IAAI,QAAQ,IAAI,KAAK;AAAA,IAC3B,YAAY,IAAI,QAAQ,UAAU;AAAA,IAClC,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAAA,IACjE;AAAA,IACA,qBAAqB,IAAI,QAAQ,mBAAmB;AAAA,IACpD,gBAAgB,IAAI,QAAQ,cAAc;AAAA,IAC1C,MAAM,IAAI,QAAQ,IAAI;AAAA,IACtB,kBAAkB,QAAQ,qBAAqB;AAAA,IAC/C,YAAY,QAAQ,eAAe;AAAA,IACnC,eAAe,QAAQ,kBAAkB;AAAA,IACzC,aAAa,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,IAAI,YAAY;AAAA,IACvF,aAAa,IAAI,QAAQ,MAAM,WAAW;AAAA,IAC1C,cAAc,aAAa,UAAa,cAAc,SAAY,SAAS,QAAQ,CAAC,IAAI;AAAA,IACxF,mBAAmB,aAAa,UAAa,cAAc,SAAY,YAAY;AAAA,IACnF,cAAc;AAAA,IACd,cAAc;AAAA,IACd,WAAW,IAAI,QAAQ,iBAAiB;AAAA,IACxC,WAAW,IAAI,QAAQ,iBAAiB;AAAA,IACxC,kBAAkB,IAAI,QAAQ,oBAAoB;AAAA,IAClD,YAAY,IAAI,QAAQ,UAAU;AAAA,IAClC,cAAc,IAAI,QAAQ,YAAY;AAAA,EACxC;AACF;AAEO,SAAS,gBAAgB,IAAe,gBAA+C;AAC5F,MAAI,GAAG,gBAAgB,UAAa,GAAG,gBAAgB,OAAW,QAAO;AACzE,QAAM,YAA2B;AAAA,IAC/B,aAAa,GAAG;AAAA,IAChB,SAAS,GAAG;AAAA,IACZ,aAAa,GAAG;AAAA,EAClB;AACA,MAAI,GAAG,gBAAgB,OAAW,WAAU,cAAc,GAAG;AAC7D,MAAI,GAAG,OAAO,OAAW,WAAU,YAAY,GAAG;AAClD,MAAI,mBAAmB,OAAW,WAAU,iBAAiB;AAC7D,SAAO;AACT;AAEO,SAAS,eAAe,MAAoC;AACjE,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,OAAO,CAAC;AACrD,QAAM,QAAQ,CAAC,GAAkB,MAA+B;AAC9D,UAAM,YAAY,cAAc,IAAI,EAAE,cAAc,GAAG,IAAI,EAAE,IAAI,CAAC,KAAK;AACvE,UAAM,QAAQ,OAAO,EAAE,UAAU,YAAY,OAAO,SAAS,EAAE,KAAK,IAAI,EAAE,QAAQ;AAClF,UAAM,WACJ,OAAO,EAAE,kBAAkB,YAAY,OAAO,SAAS,EAAE,aAAa,IAAI,EAAE,gBAAgB;AAC9F,UAAM,YACJ,EAAE,sBAAsB,eAAe,EAAE,sBAAsB,YAAY,EAAE,oBAAoB;AACnG,WAAO;AAAA,MACL,KAAK,GAAG,SAAS,IAAI,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,CAAC;AAAA,MAC3C;AAAA,MACA,gBAAgB,IAAI,EAAE,cAAc;AAAA,MACpC,MAAM,IAAI,EAAE,IAAI;AAAA,MAChB,MAAM,UAAU,SAAY,MAAM,QAAQ,CAAC,IAAI;AAAA,MAC/C,aAAa;AAAA,MACb,aAAa,OAAO,EAAE,gBAAgB,WAAW,EAAE,cAAc;AAAA,MACjE,aAAa,IAAI,EAAE,WAAW;AAAA,MAC9B,QAAQ,EAAE,eAAe;AAAA;AAAA;AAAA,MAGzB,aAAa,EAAE,gBAAgB;AAAA,MAC/B,cAAc,aAAa,UAAa,cAAc,SAAY,SAAS,QAAQ,CAAC,IAAI;AAAA,MACxF,mBAAmB,aAAa,UAAa,cAAc,SAAY,YAAY;AAAA,IACrF;AAAA,EACF;AAIA,QAAM,MAAM,KAAK,IAAI,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,WAAW;AACjF,QAAM,OAAO,IAAI,KAAK,YAAY;AAClC,QAAM,OAAO,IAAI,KAAK,YAAY;AAClC,QAAM,UAAU,KAAK,IAAI,CAAC,MAAM,IAAI,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC,EAAE,KAAK;AACzF,SAAO;AAAA,IACL,IAAI,GAAG,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,CAAC,IAAI,IAAI,KAAK,mBAAmB,KAAK,EAAE;AAAA,IACjG,QAAQ,IAAI,KAAK,WAAW,KAAK,IAAI,KAAK,mBAAmB,KAAK;AAAA,IAClE,SAAS,QAAQ,OAAO,GAAG,IAAI,OAAO,IAAI,KAAK;AAAA,IAC/C,cAAc;AAAA,IACd,cAAc;AAAA,IACd,WAAW,IAAI,KAAK,iBAAiB;AAAA,IACrC,WAAW,IAAI,KAAK,iBAAiB;AAAA,IACrC,kBAAkB,IAAI,KAAK,oBAAoB;AAAA,IAC/C,aAAa,IAAI,KAAK,eAAe;AAAA,IACrC,YAAY,IAAI,KAAK,UAAU;AAAA,IAC/B,cAAc,IAAI,KAAK,YAAY;AAAA,IACnC,WAAW,KAAK,IAAI,CAAC,MAAM,IAAI,EAAE,aAAa,CAAC,EAAE,KAAK,OAAO;AAAA,IAC7D,WAAW,QAAQ,SAAS,IAAI,QAAQ,QAAQ,SAAS,CAAC,IAAI;AAAA,IAC9D,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI;AAAA,IAC1C,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,IAC3D,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,MAAM;AAAA,IACpC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM;AAAA,IACrC,YAAY,IAAI,KAAK,UAAU;AAAA,IAC/B,kBAAkB,KAAK,qBAAqB;AAAA,IAC5C,qBAAqB,IAAI,KAAK,mBAAmB;AAAA,IACjD,UAAU,IAAI,KAAK,QAAQ;AAAA,IAC3B,YAAY,KAAK,eAAe;AAAA,IAChC,UAAU,KAAK,WAAW,OAAO,KAAK,YAAY,WAAW,IAAI,KAAK,QAAQ,IAAI,IAAI;AAAA,IACtF,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAClC,KAAK,SAAS,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC,IACrE;AAAA,IACJ,KAAK,KAAK,QAAQ,gBAAgB,gBAAgB;AAAA,IAClD,MAAM,KAAK,QAAQ;AAAA,IACnB,aAAa,OAAO,KAAK,gBAAgB,YAAY,OAAO,SAAS,KAAK,WAAW,IAAI,KAAK,cAAc;AAAA,EAC9G;AACF;AA0BO,SAAS,iBAAiB,MAAwC;AACvE,QAAM,MAAM,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC;AACxD,QAAM,UAAyB,CAAC;AAChC,aAAW,KAAK,KAAK;AACnB,UAAM,QAAQ,OAAO,EAAE,UAAU,YAAY,OAAO,SAAS,EAAE,KAAK,IAAI,EAAE,QAAQ;AAClF,UAAM,OAAO,OAAO,EAAE,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK,IAAI;AACjE,QAAI,UAAU,UAAa,OAAO,MAAM,IAAI,EAAG;AAC/C,YAAQ,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,EAC9B;AAIA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAEtC,QAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,IAAI;AACpD,QAAM,UAAU,SAAS,KAAK,YAAY;AAC1C,QAAM,UAAU,SAAS,KAAK,YAAY;AAC1C,QAAM,OAAO,IAAI,KAAK,YAAY;AAClC,QAAM,OAAO,IAAI,KAAK,YAAY;AAClC,QAAM,YAAY,cAAc,IAAI,KAAK,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC,KAAK;AAC7E,QAAM,cAAc,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAE9E,SAAO;AAAA,IACL,IAAI,GAAG,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,CAAC,IAAI,IAAI,KAAK,mBAAmB,KAAK,EAAE,IAAI,SAAS,IAAI,WAAW;AAAA,IAC7H,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,IAC3D,QAAQ,IAAI,KAAK,WAAW,KAAK,IAAI,KAAK,mBAAmB,KAAK;AAAA,IAClE,qBAAqB,IAAI,KAAK,mBAAmB;AAAA,IACjD;AAAA,IACA,gBAAgB,IAAI,KAAK,cAAc;AAAA,IACvC,MAAM,IAAI,KAAK,IAAI;AAAA,IACnB,SAAS,QAAQ,OAAO,GAAG,IAAI,OAAO,IAAI,KAAK;AAAA,IAC/C,aAAa,IAAI,KAAK,eAAe;AAAA,IACrC,WAAW,IAAI,KAAK,aAAa;AAAA,IACjC,SAAS,YAAY,SAAY,QAAQ,QAAQ,CAAC,IAAI;AAAA,IACtD,SAAS,YAAY,SAAY,QAAQ,QAAQ,CAAC,IAAI;AAAA,IACtD,WACE,KAAK,sBAAsB,eAAe,KAAK,sBAAsB,YACjE,KAAK,oBACL;AAAA,IACN,aAAa,SAAS,KAAK,WAAW,KAAK;AAAA,IAC3C,eAAe,SAAS,KAAK,sBAAsB,KAAK;AAAA,IACxD,aAAa,KAAK,gBAAgB;AAAA,IAClC,YAAY,IAAI,KAAK,UAAU;AAAA,IAC/B,UAAU,cAAc,OAAO;AAAA,IAC/B,kBAAkB,QAAQ;AAAA,IAC1B,YAAY,KAAK,eAAe;AAAA,IAChC,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,EACzE;AACF;AAEO,SAAS,6BACd,IAAkB,KAAsB,gBAClB;AACtB,MAAI,IAAI,gBAAgB,UAAa,IAAI,gBAAgB,OAAW,QAAO;AAC3E,QAAM,YAA2B,EAAE,aAAa,IAAI,aAAa,SAAS,GAAG,SAAS,aAAa,IAAI,YAAY;AACnH,MAAI,IAAI,gBAAgB,OAAW,WAAU,cAAc,IAAI;AAC/D,MAAI,mBAAmB,OAAW,WAAU,iBAAiB;AAC7D,SAAO;AACT;AAuCA,SAAS,OAAO,GAAgC;AAC9C,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D;AAEA,SAAS,aAAa,KAAqD;AACzE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,QAAM,cAAc,OAAO,IAAI,WAAW;AAC1C,QAAM,UAAU,OAAO,IAAI,OAAO;AAClC,QAAM,OAAO,IAAI,IAAI,YAAY;AACjC,QAAM,OAAO,IAAI,IAAI,YAAY;AACjC,QAAM,iBAAiB,IAAI,IAAI,cAAc;AAC7C,QAAM,UAAU,IAAI,WAAW,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAC/E,QAAM,YAAY,IAAI,SAAS,SAAS;AACxC,QAAM,WAAW,IAAI,SAAS,IAAI;AAElC,QAAM,UAAU,CAAC,CAAC,aAAa,CAAC,CAAC;AAGjC,MAAI,UAAU,UAAa,gBAAgB,UAAa,YAAY,UAAa,CAAC,QAAQ,CAAC,QACtF,CAAC,eAAgB,QAAO;AAC7B,QAAM,OAAO,IAAI,IAAI,IAAI;AACzB,SAAO;AAAA,IACL,KAAK,GAAG,WAAW;AAAA,IACnB;AAAA,IACA,cAAc;AAAA,IACd,cAAc;AAAA,IACd,WAAW,IAAI,IAAI,iBAAiB;AAAA,IACpC,WAAW,IAAI,IAAI,iBAAiB;AAAA,IACpC,aAAa,IAAI,IAAI,eAAe;AAAA,IACpC,YAAY,IAAI,IAAI,UAAU;AAAA,IAC9B,cAAc,IAAI,IAAI,YAAY;AAAA,IAClC,QAAQ,IAAI,IAAI,WAAW,KAAK,IAAI,IAAI,mBAAmB,KAAK;AAAA,IAChE,qBAAqB,IAAI,IAAI,mBAAmB,KAAK;AAAA,IACrD,WAAW,cAAc,gBAAgB,IAAI,KAAK;AAAA,IAClD;AAAA,IACA;AAAA,IACA,MAAM,MAAM,QAAQ,CAAC;AAAA,IACrB,aAAa;AAAA,IACb;AAAA,IACA,aAAa,IAAI,IAAI,WAAW;AAAA,IAChC,GAAI,UAAU,EAAE,WAAW,SAAS,IAAI,CAAC;AAAA,IACzC,YAAY,IAAI,eAAe;AAAA,EACjC;AACF;AAEO,SAAS,cAAc,MAAqC;AACjE,QAAM,UAAU,MAAM,QAAQ,MAAM,IAAI,IAAI,KAAK,OAAO,CAAC;AACzD,QAAM,iBAAiB,IAAI,MAAM,cAAc;AAC/C,MAAI,QAAQ,SAAS,KAAK,CAAC,eAAgB,QAAO;AAClD,QAAM,OAAqB,CAAC;AAC5B,aAAW,OAAO,SAAS;AACzB,UAAM,KAAK,aAAa,GAAG;AAC3B,QAAI,CAAC,GAAI,QAAO;AAChB,SAAK,KAAK,EAAE;AAAA,EACd;AACA,SAAO;AAAA,IACL,IAAI,IAAI,KAAK,OAAO,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,GAAG;AAAA,IAChE;AAAA,IACA;AAAA,IACA,cAAc,IAAI,KAAK,YAAY;AAAA,IACnC,kBAAkB,KAAK,qBAAqB;AAAA,IAC5C,QAAQ,OAAO,KAAK,MAAM;AAAA,IAC1B,UAAU,OAAO,KAAK,QAAQ;AAAA,EAChC;AACF;AAEO,SAAS,wBAAwB,KAAiB,gBAAwC;AAC/F,QAAM,YAA2B;AAAA,IAC/B,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,IACb,aAAa,IAAI;AAAA,EACnB;AACA,MAAI,IAAI,cAAc,OAAW,WAAU,YAAY,IAAI;AAC3D,MAAI,IAAI,gBAAgB,OAAW,WAAU,cAAc,IAAI;AAC/D,MAAI,mBAAmB,OAAW,WAAU,iBAAiB;AAC7D,SAAO;AACT;;;AC7eO,IAAM,yBAAyB;AAW/B,IAAM,gBAAgB;AACtB,IAAM,WAAW;AACjB,IAAM,WAAW;AAIjB,SAAS,eAAe,WAA0B,OAAgB,MAA+B;AACtG,QAAM,SAAyB,CAAC;AAChC,MAAI,OAAO,cAAc,UAAU,OAAO,KAAK,UAAU,UAAU,EAAG,QAAO,UAAU,UAAU;AACjG,MAAI,SAAS,MAAM,KAAK,KAAK,MAAM,UAAU,cAAe,QAAO,YAAY;AAC/E,MAAI,QAAQ,KAAK,KAAK,KAAK,KAAK,UAAU,SAAU,QAAO,OAAO;AAClE,QAAM,OAAO,UAAU;AACvB,MAAI,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,QAAQ,SAAU,QAAO,OAAO;AACzE,SAAO;AACT;AAIO,SAAS,cAAc,QAAiD,SAAiB,gBAA+C;AAC7I,MAAI,CAAC,UAAU,CAAC,OAAO,oBAAoB,OAAO,OAAO,gBAAgB,YAAY,OAAO,OAAO,UAAU,SAAU,QAAO;AAC9H,QAAM,YAA2B,EAAE,aAAa,OAAO,aAAa,SAAS,aAAa,OAAO,MAAM;AACvG,MAAI,mBAAmB,OAAW,WAAU,iBAAiB;AAC7D,SAAO;AACT;AAEO,SAAS,SAAS,QAAyC;AAChE,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,WAAW,gBAAiB,QAAO,OAAO;AACrD,SAAO,OAAO,WAAW;AAC3B;AAEO,SAAS,WAAW,QAAyC;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,WAAW,gBAAiB,QAAO,OAAO;AACrD,SAAO,OAAO,WAAW,WAAW,OAAO,WAAW;AACxD;AAKO,SAAS,YAAY,QAAwC;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,OAAO,WAAW,UAAU;AAAA,IACrC,KAAK;AACH,aAAO,OAAO;AAAA,EAClB;AACF;AAEO,SAAS,cAAc,QAAgC,WAAmB,IAAyB;AACxG,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,WAAW,MAAM,GAAG,UAAU;AAC1D,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,MAAM,WAAW,MAAM,GAAG,UAAU;AAAA,IAC/C,KAAK;AACH,aAAO,EAAE,MAAM,WAAW,MAAM,GAAG,cAAc;AAAA,IACnD,KAAK;AACH,aAAO,OAAO,WACV,EAAE,MAAM,WAAW,MAAM,GAAG,iBAAiB,WAAW,OAAO,eAAe,QAAQ,CAAC,CAAC,EAAE,IAC1F,EAAE,MAAM,SAAS,MAAM,GAAG,qBAAqB,WAAW,OAAO,eAAe,QAAQ,CAAC,CAAC,EAAE;AAAA,IAClG,KAAK;AACH,UAAI,OAAO,WAAW,iBAAkB,QAAO,EAAE,MAAM,SAAS,MAAM,GAAG,kBAAkB;AAC3F,UAAI,OAAO,WAAW,YAAa,QAAO,EAAE,MAAM,SAAS,MAAM,GAAG,cAAc;AAClF,aAAO,EAAE,MAAM,SAAS,MAAM,OAAO,WAAW,GAAG,WAAW;AAAA,EAClE;AACF;AAMO,SAAS,WAAW,SAAqC;AAC9D,MAAI,QAAQ,SAAS,SAAU,QAAO;AACtC,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OAAQ,QAAO;AACpB,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,OAAO,WAAW,gBAAgB;AAAA,IAC3C,KAAK;AACH,UAAI,OAAO,WAAW,iBAAkB,QAAO;AAC/C,UAAI,OAAO,WAAW,QAAS,QAAO;AACtC,aAAO;AAAA,EACX;AACF;AAaO,SAAS,YAAY,GAAgB,IAAyB;AACnE,MAAI,EAAE,SAAS,EAAE,UAAU,EAAG,QAAO,EAAE,MAAM,SAAS,MAAM,GAAG,kBAAkB;AACjF,MAAI,EAAE,UAAU,EAAG,QAAO,EAAE,MAAM,SAAS,MAAM,GAAG,WAAW;AAC/D,MAAI,EAAE,SAAS,WAAW,GAAG;AAC3B,WAAO,EAAE,MAAM,WAAW,MAAM,EAAE,aAAa,GAAG,iBAAiB,EAAE,KAAK,IAAI,GAAG,WAAW,EAAE,KAAK,EAAE;AAAA,EACvG;AACA,SAAO,EAAE,MAAM,SAAS,MAAM,GAAG,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE;AACnF;;;AC7HA,mBAAkE;;;ACgB3D,IAAM,iBAAiB;AAS9B,IAAM,SAAS,oBAAI,QAA+B;AAE3C,SAAS,UAAU,OAAiC;AACzD,SAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,QAAQ;AAC7E;AAQO,SAAS,mBAA+B;AAC7C,QAAM,QAAmB,EAAE,OAAO,CAAC,GAAG,MAAM,KAAK;AAEjD,QAAM,WAAW,CAAC,YAA+B;AAC/C,QAAI,MAAM,MAAM;AACd,YAAM,KAAK,OAAO;AAClB;AAAA,IACF;AACA,UAAM,MAAM,KAAK,OAAO;AACxB,QAAI,MAAM,MAAM,SAAS,eAAgB,OAAM,MAAM,MAAM;AAAA,EAC7D;AAEA,QAAM,OAAmB;AAAA;AAAA;AAAA,IAGvB,YAAY,WAAW;AACrB,UAAI;AACF,cAAM,KAAc,UAAU;AAC9B,YAAI,UAAU,EAAE,EAAG,UAAS,EAAE,MAAM,eAAe,aAAa,GAAG,CAAC;AAAA,MACtE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,UAAU,KAAK;AACb,UAAI;AACF,cAAM,OAAgB,IAAI;AAC1B,YAAI,CAAC,MAAM,QAAQ,IAAI,EAAG;AAC1B,cAAM,MAAgB,CAAC;AACvB,mBAAW,OAAO,MAAqE;AACrF,gBAAM,KAAK,KAAK;AAChB,cAAI,UAAU,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,EAAG,KAAI,KAAK,EAAE;AAAA,QACrD;AACA,YAAI,IAAI,SAAS,EAAG,UAAS,EAAE,MAAM,aAAa,cAAc,IAAI,CAAC;AAAA,MACvE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,YAAY,OAAO;AACjB,UAAI;AACF,cAAM,KAAc,MAAM;AAC1B,YAAI,UAAU,EAAE,EAAG,UAAS,EAAE,MAAM,eAAe,SAAS,GAAG,CAAC;AAAA,MAClE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO,IAAI,MAAM,KAAK;AACtB,SAAO;AACT;AAMO,SAAS,WAAW,MAAkB,MAA4B;AACvE,QAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,MAAI,CAAC,MAAO,QAAO,MAAM;AAAA,EAAC;AAC1B,QAAM,OAAO;AACb,QAAM,SAAS,MAAM;AACrB,QAAM,QAAQ,CAAC;AACf,aAAW,WAAW,QAAQ;AAC5B,QAAI;AACF,WAAK,OAAO;AAAA,IACd,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,MAAM;AAEX,QAAI,MAAM,SAAS,KAAM,OAAM,OAAO;AAAA,EACxC;AACF;;;AC3GO,IAAM,iBAAiB,KAAK,KAAK;AACjC,IAAM,WAAW;AA0BxB,IAAM,QAAQ,OAAkB,EAAE,QAAQ,OAAO,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE;AAEpE,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,MAAM,KAAoB,MAAqC;AACtE,MAAI,CAAC,IAAK,QAAO,MAAM;AACvB,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,MAAM;AAAA,EACf;AACA,MAAI,CAAC,SAAS,IAAI,KAAK,KAAK,MAAM,EAAG,QAAO,MAAM;AAGlD,MAAI,KAAK,SAAS,UAAa,KAAK,SAAS,KAAM,QAAO,MAAM;AAChE,QAAM,QAAQ,MAAM;AACpB,QAAM,SAAS,KAAK,WAAW;AAC/B,MAAI,SAAS,KAAK,IAAI,GAAG;AACvB,eAAW,CAAC,KAAK,EAAE,KAAK,OAAO,QAAQ,KAAK,IAAI,GAAG;AACjD,UAAI,OAAO,OAAO,YAAY,OAAO,SAAS,EAAE,EAAG,OAAM,KAAK,GAAG,IAAI;AAAA,IACvE;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,KAAK,IAAI,GAAG;AAC5B,UAAM,OAAO,KAAK,KAAK,OAAO,SAAS,EAAE,MAAM,CAAC,QAAQ;AAAA,EAC1D;AACA,SAAO;AACT;AAIA,SAAS,iBAAiC;AACxC,MAAI;AACF,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,iBAAiB,YAAoB,UAA6B,CAAC,GAAe;AAChG,QAAM,MAAM,QAAQ,QAAQ,MAAM,KAAK,IAAI;AAC3C,QAAM,OAAO,QAAQ;AACrB,MAAI,UAAsC,QAAQ;AAClD,MAAI,SAAoB,MAAM;AAE9B,QAAMC,QAAO,MAAiB;AAC5B,QAAI,YAAY,OAAW,WAAU,eAAe;AACpD,QAAI,SAAS;AACX,UAAI;AACF,iBAAS,MAAM,QAAQ,QAAQ,UAAU,GAAG,IAAI;AAAA,MAClD,QAAQ;AACN,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,CAAC,UAA2B;AACxC,aAAS;AACT,QAAI,CAAC,QAAS;AACd,QAAI;AACF,cAAQ,QAAQ,YAAY,KAAK,UAAU,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;AAAA,IACtE,QAAQ;AACN,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,SAAS;AACZ,YAAM,KAAK,IAAI;AACf,YAAM,QAAQA,MAAK;AACnB,iBAAWC,QAAO,OAAO,KAAK,MAAM,IAAI,GAAG;AACzC,YAAI,MAAM,MAAM,KAAKA,IAAG,KAAK,MAAM,eAAgB,QAAO,MAAM,KAAKA,IAAG;AAAA,MAC1E;AACA,YAAM,MAAM,OAAO,OAAO;AAC1B,UAAI,MAAM,KAAK,GAAG,MAAM,OAAW,QAAO;AAC1C,YAAM,KAAK,GAAG,IAAI;AAClB,UAAI,SAAqB;AACzB,UAAI,CAAC,MAAM,QAAQ;AACjB,cAAM,OAAO,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,OAAO,OAAO,OAAO,GAAG,OAAO,EAAE,MAAM,CAAC,QAAQ;AACpF,iBAAS;AAAA,MACX;AACA,YAAM,KAAK;AACX,aAAO;AAAA,IACT;AAAA,IACA,aAAa;AACX,YAAM,QAAQD,MAAK;AACnB,UAAI,MAAM,OAAQ,QAAO,CAAC;AAC1B,YAAM,KAAK,IAAI;AACf,YAAM,OAAO,MAAM;AAEnB,iBAAW,MAAM,KAAM,OAAM,KAAK,OAAO,EAAE,CAAC,IAAI;AAChD,YAAM,EAAE,QAAQ,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC,EAAE,CAAC;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AClIO,IAAM,gBAAgB,IAAI,KAAK,KAAK,KAAK;AACzC,IAAM,aAAa;AAInB,IAAM,iBAAiB;AAC9B,IAAM,aAAa;AAEnB,IAAM,WAAW;AA4BjB,SAASE,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,KAAK,OAAgB,KAA8B;AAC1D,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,KAAK,MAAM,UAAU;AACjF;AAKA,SAAS,MAAM,MAAmC;AAChD,MAAI,CAACA,UAAS,IAAI,EAAG,QAAO;AAC5B,QAAM,EAAE,IAAI,QAAQ,IAAI,KAAK,IAAI;AACjC,MAAI,CAAC,UAAU,EAAE,EAAG,QAAO;AAC3B,MAAI,OAAO,OAAO,YAAY,CAAC,OAAO,SAAS,EAAE,EAAG,QAAO;AAC3D,MAAI,CAAC,KAAK,QAAQ,UAAU,EAAG,QAAO;AACtC,MAAI,SAAS,WAAc,OAAO,SAAS,YAAY,KAAK,WAAW,GAAI,QAAO;AAClF,QAAM,QAAqB,EAAE,IAAI,QAAQ,GAAG;AAC5C,MAAI,OAAO,SAAS,SAAU,OAAM,OAAO;AAC3C,MAAI,UAAU,KAAK,OAAO,EAAG,OAAM,UAAU,KAAK;AAClD,MAAI,KAAK,KAAK,WAAW,aAAa,EAAG,OAAM,YAAY,KAAK;AAChE,MAAI,KAAK,KAAK,MAAM,QAAQ,EAAG,OAAM,OAAO,KAAK;AACjD,QAAM,OAAO,KAAK;AAClB,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,KAAK,QAAQ,YAAY,QAAQ,SAAU,OAAM,OAAO;AAC5G,SAAO;AACT;AAEA,SAASC,OAAM,KAAmC;AAChD,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,MAAI,CAACD,UAAS,IAAI,KAAK,KAAK,MAAM,KAAK,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,QAAO,CAAC;AAC7E,QAAM,UAAyB,CAAC;AAChC,aAAW,QAAQ,KAAK,SAAS;AAC/B,UAAM,QAAQ,MAAM,IAAI;AACxB,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,EAC/B;AACA,SAAO;AACT;AAIA,SAASE,kBAAiC;AACxC,MAAI;AACF,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,iBAAiB,YAAoB,UAA6B,CAAC,GAAe;AAChG,QAAM,MAAM,QAAQ,QAAQ,MAAM,KAAK,IAAI;AAC3C,MAAI,UAAsC,QAAQ;AAElD,MAAI,SAAwB,CAAC;AAE7B,QAAMC,QAAO,MAAqB;AAChC,QAAI,YAAY,OAAW,WAAUD,gBAAe;AACpD,QAAI,SAAS;AACX,UAAI;AACF,iBAASD,OAAM,QAAQ,QAAQ,UAAU,CAAC;AAAA,MAC5C,QAAQ;AACN,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,CAAC,YAAiC;AAC9C,aAAS;AACT,QAAI,CAAC,QAAS;AACd,QAAI;AACF,cAAQ,QAAQ,YAAY,KAAK,UAAU,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC;AAAA,IAC/D,QAAQ;AACN,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,OAAO,CAAC,OAAoB,OAAwB,KAAK,MAAM,MAAM;AAE3E,SAAO;AAAA,IACL,OAAO,OAAO;AACZ,YAAM,KAAK,IAAI;AACf,YAAM,UAAU,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC;AACtC,UAAI,CAAC,QAAS;AACd,YAAM,OAAOE,MAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AAEpE,WAAK,KAAK,OAAO;AACjB,YAAM,KAAK,MAAM,CAAC,UAAU,CAAC;AAAA,IAC/B;AAAA,IACA,KAAK,IAAI,aAAa;AACpB,YAAM,KAAK,IAAI;AACf,YAAM,UAAUA,MAAK,EAAE,OAAO,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;AAChD,YAAM,QAAQ,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,YAAM,QAAQ,QAAQ,KAAK;AAC3B,UAAI,CAAC,MAAO,QAAO;AAGnB,UAAI,MAAM,SAAS,UAAa,MAAM,SAAS,YAAa,QAAO;AACnE,cAAQ,OAAO,OAAO,CAAC;AACvB,YAAM,OAAO;AACb,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAIO,SAAS,YAAY,MAAoC,OAAsC;AACpG,SAAO;AAAA,IACL;AAAA,IAAM,YAAY;AAAA,IAAU,UAAU,MAAM;AAAA,IAAQ,qBAAqB,MAAM;AAAA,IAC/E,SAAS,MAAM;AAAA,IAAS,WAAW,MAAM;AAAA,IAAW,MAAM,MAAM;AAAA,IAAM,MAAM,MAAM;AAAA,EACpF;AACF;;;AH5IO,SAAS,cAAc,MAAqC;AACjE,QAAM,EAAE,MAAM,YAAY,aAAa,QAAQ,QAAQ,WAAW,IAAI;AAItE,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAA+B,CAAC,CAAC;AAC3D,QAAM,CAAC,SAAS,UAAU,QAAI,uBAA+B,CAAC,CAAC;AAC/D,QAAM,gBAAY,0BAAY,CAAC,gBAAwB;AACrD,aAAS,CAAC,SAAU,KAAK,WAAW,IAAI,OAAO,EAAE,GAAG,MAAM,CAAC,WAAW,GAAG,KAAK,CAAE;AAAA,EAClF,GAAG,CAAC,CAAC;AACL,QAAM,aAAS,0BAAY,CAAC,gBAAwB;AAClD,eAAW,CAAC,SAAU,KAAK,WAAW,IAAI,OAAO,EAAE,GAAG,MAAM,CAAC,WAAW,GAAG,KAAK,CAAE;AAAA,EACpF,GAAG,CAAC,CAAC;AACL,QAAM,iBAAa,0BAAY,CAAC,QAA2B;AACzD,UAAM,OAAO,CAAC,SAAqD;AACjE,UAAI,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,CAAC,EAAG,QAAO;AACxC,YAAM,OAAO,EAAE,GAAG,KAAK;AACvB,iBAAW,MAAM,IAAK,QAAO,KAAK,EAAE;AACpC,aAAO;AAAA,IACT;AACA,aAAS,IAAI;AACb,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,SAAS;AAEzB,QAAM,aAAS;AAAA,IACb,MAAO,UAAU,iBAAiB,aAAa,UAAU,EAAE,IAAI;AAAA,IAC/D,CAAC,SAAS,UAAU;AAAA,EACtB;AACA,QAAM,qBAAiB,qBAAO,WAAW;AACzC,iBAAe,UAAU;AACzB,QAAM,gBAAY,0BAAY,CAAC,QAAiB;AAC9C,YAAQ,OAAO,EAAE,IAAI,IAAI,UAAU,aAAa,QAAQ,IAAI,QAAQ,GAAG,IAAI,MAAM,MAAM,eAAe,QAAQ,CAAC;AAAA,EACjH,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,gBAAY;AAAA,IAChB,OAAO,EAAE,OAAO,SAAS,QAAQ,UAAU;AAAA,IAC3C,CAAC,OAAO,SAAS,QAAQ,SAAS;AAAA,EACpC;AAEA,QAAM,cAAc;AAGpB,QAAM,YAAQ;AAAA,IACZ,MAAO,cAAc,iBAAiB,cAAc,UAAU,IAAI,EAAE,MAAM,YAAY,CAAC,IAAI;AAAA,IAC3F,CAAC,aAAa,YAAY,WAAW;AAAA,EACvC;AAIA,QAAM,cAAU,qBAAiB,MAAM;AAAA,EAAC,CAAC;AACzC,UAAQ,UAAU,CAAC,YAAY;AAC7B,QAAI,QAAQ,SAAS,eAAe;AAClC,UAAI,OAAO,KAAK,QAAQ,OAAO,MAAM,OAAO;AAC1C,gBAAQ,IAAI,EAAE,MAAM,cAAc,YAAY,SAAS,UAAU,OAAO,QAAQ,OAAO,EAAE,CAAC;AAAA,MAC5F;AACA;AAAA,IACF;AACA,UAAM,OAAO,QAAQ,SAAS,gBAAgB,gBAAgB;AAC9D,UAAM,MAAM,QAAQ,SAAS,gBAAgB,CAAC,QAAQ,WAAW,IAAI,QAAQ;AAG7E,eAAW,GAAG;AACd,QAAI,CAAC,OAAQ;AACb,QAAI,WAAW;AACf,eAAW,MAAM,KAAK;AACpB,YAAM,QAAQ,OAAO,KAAK,IAAI,WAAW;AACzC,UAAI,CAAC,SAAS,YAAY,eAAgB;AAC1C;AACA,cAAQ,IAAI,YAAY,MAAM,KAAK,CAAC;AAAA,IACtC;AAAA,EACF;AACA,8BAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,WAAO,WAAW,MAAM,CAAC,YAAY,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC/D,GAAG,CAAC,IAAI,CAAC;AAMT,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,MAAO;AACvB,UAAM,OAAO,MAAM,WAAW;AAC9B,QAAI,KAAK,WAAW,EAAG;AACvB,eAAW,WAAW,MAAM;AAC1B,cAAQ,IAAI,EAAE,MAAM,cAAc,YAAY,SAAS,UAAU,OAAO,OAAO,EAAE,CAAC;AAAA,IACpF;AACA,SAAK,QAAQ,SAAS;AAAA,EACxB,GAAG,CAAC,QAAQ,OAAO,MAAM,CAAC;AAE1B,SAAO,EAAE,WAAW,UAAU;AAChC;;;AIpHA,wBAA+K;AAQ/K,SAAS,mBAAmB,OAA0C;AACpE,SAAO,OAAO,UAAU,eAAe,KAAK,qCAAmB,KAAK;AACtE;AAMA,SAAS,mBAAmB,OAAwC;AAClE,UAAQ,MAAM,YAAY,GAAG;AAAA,IAC3B,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAe,aAAO;AAAA,IAC3B,KAAK;AAAU,aAAO;AAAA,IACtB;AAAS,aAAO;AAAA,EAClB;AACF;AAUO,SAAS,yBAAyB,YAAwC,KAA+C;AAC9H,SAAO,CAAC,MAAM,OAAO,WAAW;AAC9B,UAAM,mBAAmB,mBAAmB,KAAK,OAAO,UAAU;AAClE,QAAI,kBAAkB;AACpB,WAAK,IAAI,EAAE,MAAM,YAAY,YAAY,kBAAkB,UAAU,KAAK,OAAO,SAAS,CAAC;AAAA,IAC7F;AACA,QAAI,CAAC,mBAAmB,KAAK,OAAO,UAAU,EAAG;AAIjD,QAAI;AACF,WAAK,WAAW;AAAA,QACd,YAAY;AAAA,QACZ,YAAY,KAAK,OAAO;AAAA,QACxB,UAAU,KAAK,OAAO;AAAA,QACtB,iBAAiB;AAAA,QACjB,WAAW;AAAA,MACb,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ACjDO,SAAS,WAAW,IAA0B;AACnD,QAAM,QAAgC;AAAA,IACpC,mBAAmB,GAAG,GAAG,OAAO,CAAC;AAAA,IACjC,mBAAmB,GAAG,GAAG,OAAO,CAAC;AAAA,IACjC,iBAAiB,GAAG,GAAG,MAAM;AAAA,EAC/B;AACA,MAAI,GAAG,OAAQ,OAAM,eAAe,IAAI,GAAG;AAC3C,MAAI,GAAG,IAAK,OAAM,YAAY,IAAI,GAAG;AACrC,MAAI,GAAG,QAAS,OAAM,cAAc,IAAI,GAAG;AAC3C,MAAI,GAAG,IAAK,OAAM,YAAY,IAAI,GAAG;AACrC,MAAI,GAAG,WAAW,GAAG,KAAK;AACxB,UAAM,eAAe,IAAI;AACzB,UAAM,aAAa,IAAI;AACvB,UAAM,cAAc,IAAI;AAAA,EAC1B;AACA,SAAO,EAAE,mBAAmB,GAAG,OAAO,iBAAiB,GAAG,UAAU,MAAM;AAC5E;;;ACxBA,IAAAC,gBAAoE;AAEpE,IAAAC,qBAA+B;;;ACD/B,IAAAC,qBAA+B;;;ACC/B,IAAAC,qBAAwD;AAajD,IAAM,qBAAqB,KAAK,KAAK;AAE5C,IAAM,QAAQ;AAEd,SAAS,MACP,MAAiB,SACjB,UAAqC,mBACzB;AACZ,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,SAAS,SAAS,KAAK,KAAK;AAAA,IAC5B,UAAU,YAAY;AAAA,IACtB,mBAAmB,OAAO,sBAAsB,YAAY,OAAO,SAAS,iBAAiB,IAAI,oBAAoB;AAAA,EACvH;AACF;AAEO,SAAS,eAAe,MAA+C;AAC5E,aAAO,gCAAY,KAAK,IAAI,IAAI,MAAM,KAAK,MAAM,KAAK,SAAS,KAAK,UAAU,KAAK,iBAAiB,IAAI;AAC1G;AAEO,SAAS,eAAe,OAA0C;AACvE,SAAO,iBAAiB,gCAAa,MAAM,MAAM,WAAW,MAAM,cAAc,MAAM,UAAU,MAAM,UAAU,IAAI;AACtH;AAGO,SAAS,cAAc,MAAqC;AACjE,SAAO,KAAK,aAAa,aAAS,gCAAY,KAAK,IAAI;AACzD;AAEO,SAAS,SAAS,OAAmC;AAC1D,SAAO,OAAO,WAAW;AAC3B;AAEO,SAAS,UAAU,OAAmB,IAAsB;AACjE,MAAI,MAAM,QAAS,QAAO,MAAM;AAChC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAa,aAAO,GAAG;AAAA,IAC5B,KAAK;AAAmB,aAAO,GAAG;AAAA,IAClC,KAAK;AAAoB,aAAO,GAAG;AAAA,EACrC;AACF;AAIO,SAAS,aAAa,OAAmB,OAA8B;AAC5E,QAAM,QAAQ,MAAM;AACpB,MAAI,SAAS,QAAQ,OAAO,SAAS,KAAK,KAAK,SAAS,EAAG,QAAO,KAAK,IAAI,QAAQ,KAAM,kBAAkB;AAC3G,QAAM,KAAK,MAAM,WAAW,KAAK,MAAM,MAAM,KAAK,MAAM,QAAQ,IAAI,MAAM,WAAW,GAAG,MAAM,QAAQ,GAAG,IAAI,OAAO;AACpH,SAAO,OAAO,MAAM,EAAE,IAAI,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,OAAO,CAAC,GAAG,kBAAkB;AACvF;;;ADtBA,IAAM,YAAY;AAKX,SAAS,uBAAuB,UAAqB,OAAkB,CAAC,GAAc;AAC3F,MAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,WAAW,KAAK,CAAC,OAAO,GAAG,QAAQ,IAAI,CAAC,EAAG,QAAO;AACxG,QAAM,YAAY,oBAAI,IAAqB;AAC3C,aAAW,KAAK,MAAM;AACpB,QAAI,EAAE,SAAS,YAAa;AAC5B,eAAW,MAAM,EAAE,WAAY,KAAI,GAAG,QAAQ,KAAM,WAAU,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,IAAI,GAAG,uBAAuB,IAAI;AAAA,EACtH;AACA,SAAO,SAAS,IAAI,CAAC,MAAM;AACzB,QAAI,EAAE,SAAS,eAAe,CAAC,EAAE,WAAW,KAAK,CAAC,OAAO,GAAG,QAAQ,IAAI,EAAG,QAAO;AAClF,WAAO;AAAA,MACL,GAAG;AAAA,MACH,YAAY,EAAE,WAAW,IAAI,CAAC,OAC5B,GAAG,QAAQ,OAAO,EAAE,GAAG,IAAI,oBAAoB,UAAU,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,KAAK,IAAI,EAAE;AAAA,IACnG;AAAA,EACF,CAAC;AACH;AAEO,SAAS,aAAa,UAAiC;AAC5D,SAAO,EAAE,QAAQ,OAAO,UAAU,CAAC,GAAG,aAAa,OAAO,QAAQ,MAAM,gBAAgB,OAAO,UAAU,oBAAoB,UAAU,OAAO,MAAM,eAAe,MAAM,iBAAiB,MAAM,WAAW,MAAM,gBAAgB,MAAM,OAAO,KAAK;AACrP;AAEA,SAAS,WAAW,OAA0C;AAC5D,QAAM,OAAO,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC;AACrD,SAAO,QAAQ,KAAK,SAAS,eAAe,CAAC,KAAK,OAAO,OAAO;AAClE;AAGA,SAAS,cAAc,OAAoB,OAAgC;AACzE,SAAO,EAAE,GAAG,OAAO,OAAO,OAAO,MAAM,aAAa,OAAO,QAAQ,MAAM,gBAAgB,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,KAAK,EAAE,EAAE;AAC5J;AAIA,SAAS,aAAa,OAAkC;AACtD,SAAO,CAAC,CAAC,SAAS,CAAC,MAAM,aAAa,CAAC,MAAM,YAAY,CAAC,MAAM,aAAa,CAAC,MAAM;AACtF;AAEA,SAAS,UAAU,OAAoB,IAAoD;AACzF,QAAM,OAAO,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC;AACrD,MAAI,CAAC,QAAQ,KAAK,SAAS,eAAe,KAAK,KAAM,QAAO,MAAM;AAClE,SAAO,CAAC,GAAG,MAAM,SAAS,MAAM,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;AAClD;AAEA,SAAS,WAAW,OAAoB,OAA+B;AACrE,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,MAAM,KAAK,QAAQ;AAAA,IAChD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,MAAM,KAAK,KAAK,EAAE,EAAE;AAAA,IAC1F,KAAK,eAAe;AAClB,UAAI,MAAM,KAAK,KAAK,WAAW,MAAO,QAAO;AAC7C,YAAM,OAAO,SAAS,MAAM,KAAK,IAAI;AAIrC,UAAI,KAAK,SAAS,UAAW,QAAO;AACpC,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,EAAE,EAAE;AAAA,IAC9F;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,gBAAgB,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,SAAS,WAAW,MAAM,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE;AAAA,IAClJ,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,YAAY,MAAM,KAAK,OAAO,CAAC,EAAE,EAAE,EAAE;AAAA,IAC/H,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,YAAY,eAAe,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,EAAE;AAAA,IACnI,KAAK,cAAc;AACjB,YAAM,KAAK,cAAc,MAAM,KAAK,IAAI;AACxC,UAAI,CAAC,GAAI,QAAO;AAChB,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,YAAY,CAAC,GAAI,EAAE,cAAc,CAAC,GAAI,EAAE,EAAE,EAAE,EAAE;AAAA,IAC9G;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,cAAc,iBAAiB,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,EAAE;AAAA,IACzI,KAAK,eAAe;AAClB,YAAM,OAAO,SAAS,MAAM,KAAK,MAAM;AACvC,aAAO,OAAO,EAAE,GAAG,OAAO,UAAU,CAAC,GAAG,MAAM,UAAU,IAAI,EAAE,IAAI;AAAA,IACpE;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,gBAAgB,MAAM,QAAQ,MAAM,KAAK,QAAQ;AAAA,IACtE,KAAK,iBAAiB;AACpB,YAAM,SAAS,WAAW,KAAK;AAI/B,YAAM,eAAe,MAAM,KAAK,kBAAkB,UAAU,KAAK,MAAM,QAAQ,KAAK,KAAK,KAAK;AAC9F,YAAM,cAAc,CAAC,QAAQ,cAAc,aAAa,MAAM,aAAa;AAC3E,YAAM,YAAY,QAAQ,cAAc,CAAC,MAAM,UAAU,eAAe,aAAa,MAAM,GAAG,SAAS,IAAI,MAAM;AACjH,aAAO;AAAA,QACL,GAAG;AAAA,QAAO,aAAa;AAAA,QAAO,QAAQ;AAAA,QAAM,gBAAgB;AAAA,QAAO;AAAA,QAAW,OAAO,cAAc,OAAO,MAAM;AAAA,QAChH,gBAAgB,MAAM,KAAK,kBAAkB,MAAM;AAAA,QACnD,UAAU,UAAU,OAAO,CAAC,OAAO;AAAA,UACjC,GAAG;AAAA,UACH,MAAM;AAAA,UACN,mBAAmB,MAAM,KAAK,aAAa;AAAA,UAC3C,kBAAkB,MAAM,KAAK,oBAAoB;AAAA,QACnD,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,QAAQ,eAAe,MAAM,IAAI;AAEvC,UAAI,SAAS,MAAM,KAAK,aAAa,MAAO,QAAO,EAAE,GAAG,OAAO,MAAM;AAErE,UAAI,MAAO,QAAO,cAAc,OAAO,KAAK;AAE5C,YAAM,WAAW,WAAW,KAAK,GAAG,eAAe;AACnD,aAAO,EAAE,GAAG,OAAO,OAAO,WAAW,MAAM,QAAQ,MAAM,MAAM,aAAa,OAAO,QAAQ,MAAM,gBAAgB,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,KAAK,EAAE,EAAE;AAAA,IACpL;AAAA,EACF;AAGA,SAAO;AACT;AAEO,SAAS,QAAQ,OAAoB,QAA6B;AACvE,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,MAAM,WAAW,KAAK;AAAA,IACnD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,OAAO,aAAa,OAAO,QAAQ,MAAM,gBAAgB,MAAM;AAAA,IAC5F,KAAK,aAAa;AAChB,YAAM,OAAoB,EAAE,MAAM,QAAQ,IAAI,OAAO,QAAQ,MAAM,OAAO,eAAe,OAAO,MAAM,QAAQ;AAC9G,YAAM,YAA2B,EAAE,MAAM,aAAa,IAAI,OAAO,aAAa,MAAM,IAAI,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,YAAY,CAAC,GAAG,cAAc,CAAC,GAAG,MAAM,MAAM;AAC5K,aAAO,EAAE,GAAG,OAAO,UAAU,CAAC,GAAG,MAAM,UAAU,MAAM,SAAS,GAAG,aAAa,MAAM,QAAQ,MAAM,gBAAgB,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,eAAe,OAAO,OAAO,iBAAiB,OAAO,eAAe,KAAK;AAAA,IACjO;AAAA,IACA,KAAK,iBAAiB;AAEpB,YAAM,YAA2B,EAAE,MAAM,aAAa,IAAI,OAAO,aAAa,MAAM,IAAI,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,YAAY,CAAC,GAAG,cAAc,CAAC,GAAG,MAAM,OAAO,YAAY,KAAK;AAC9L,aAAO,EAAE,GAAG,OAAO,UAAU,CAAC,GAAG,MAAM,UAAU,SAAS,GAAG,aAAa,MAAM,QAAQ,MAAM,OAAO,KAAK;AAAA,IAC5G;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,WAAW,KAAK;AAAA,IACrC,KAAK;AAIH,aAAO,EAAE,GAAG,aAAa,MAAM,kBAAkB,GAAG,QAAQ,MAAM,QAAQ,OAAO,MAAM,MAAM;AAAA,IAC/F,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,uBAAuB,OAAO,UAAU,MAAM,QAAQ;AAAA,QAChE,gBAAgB,OAAO;AAAA,QACvB,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,UAAU,OAAO,SAAS,SAAS,CAAC,IAAI,MAAM;AAAA,QAC9C,OAAO;AAAA,MACT;AAAA,IACF,KAAK;AACH,aAAO,WAAW,OAAO,OAAO,KAAK;AAAA,IACvC,KAAK,gBAAgB;AACnB,YAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,UAAI,MAAO,QAAO,cAAc,OAAO,KAAK;AAC5C,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,OAAO,aAAa,OAAO,QAAQ,MAAM,gBAAgB,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,KAAK,EAAE,EAAE;AAAA,IAC7J;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,KAAK;AAAA,IACjC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,aAAa,OAAO,QAAQ,MAAM,gBAAgB,OAAO,UAAU,UAAU,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,KAAK,EAAE,EAAE;AAAA,IACxI,KAAK,oBAAoB;AACvB,YAAM,EAAE,SAAS,MAAM,UAAU,UAAU,iBAAiB,IAAI;AAChE,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,MAAM,SAAS,IAAI,CAAC,MAAM;AAClC,cAAI,EAAE,SAAS,YAAa,QAAO;AAEnC,cAAI,CAAC,EAAE,WAAW,KAAK,CAAC,OAAO,GAAG,YAAY,WAAW,GAAG,QAAQ,IAAI,EAAG,QAAO;AAClF,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,YAAY,EAAE,WAAW;AAAA,cAAI,CAAC,OAC5B,GAAG,YAAY,WAAW,GAAG,QAAQ,OACjC,EAAE,GAAG,IAAI,MAAM,UAAU,UAAU,kBAAkB,oBAAoB,MAAM,IAC/E;AAAA,YACN;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,MAAM,SAAS;AAAA,UAAI,CAAC,MAC5B,EAAE,SAAS,eAAe,EAAE,OAAO,OAAO,aAAa,EAAE,mBACrD,EAAE,GAAG,GAAG,kBAAkB,EAAE,GAAG,EAAE,kBAAkB,OAAO,OAAO,OAAO,UAAU,OAAO,YAAY,EAAE,iBAAiB,SAAS,EAAE,IACnI;AAAA,QACN;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,MAAM,SAAS;AAAA,UAAI,CAAC,MAC5B,EAAE,SAAS,eAAe,EAAE,OAAO,OAAO,aAAa,EAAE,mBACrD,EAAE,GAAG,GAAG,kBAAkB,OAAO,UAAU,IAC3C;AAAA,QACN;AAAA,MACF;AAAA,EACJ;AACF;;;AEnPA,IAAAC,gBAA8C;AAI9C,IAAM,mBAAmB;AACzB,IAAM,UAAU;AAChB,IAAM,aAAa,KAAK;AAYxB,SAAS,iBAAiB,WAAmD;AAC3E,QAAM,YAAY,UAAU,MAAM,KAAK,CAAC,MAA0B,EAAE,aAAa,WAAW;AAC5F,MAAI,UAAW,QAAO,UAAU,KAAK,cAAc;AAEnD,aAAW,KAAK,UAAU,OAAO;AAC/B,UAAM,IAAK,EAA0C;AACrD,QAAI,OAAO,GAAG,gBAAgB,SAAU,QAAO,EAAE,cAAc;AAAA,EACjE;AACA,SAAO;AACT;AAKA,SAAS,WAAW,UAAoC;AACtD,QAAM,MAAM,KAAK,IAAI;AACrB,aAAW,KAAK,SAAS,MAAM,EAAE,QAAQ,GAAG;AAC1C,QAAI,EAAE,SAAS,eAAe,CAAC,EAAE,iBAAkB;AACnD,UAAM,EAAE,MAAM,IAAI,EAAE;AACpB,QAAI,UAAU,OAAQ,QAAO,EAAE,WAAW,EAAE,IAAI,MAAM,OAAO;AAC7D,QAAI,UAAU,YAAY;AACxB,YAAM,YAAY,iBAAiB,EAAE,gBAAgB;AACrD,UAAI,cAAc,KAAM;AACxB,UAAI,OAAO,YAAY,WAAW,OAAO,YAAY,YAAY;AAC/D,eAAO,EAAE,WAAW,EAAE,IAAI,MAAM,YAAY,UAAU;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAIA,SAAS,qBAAqB,UAAoC;AAChE,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,WAA0B;AAC9B,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,SAAS,eAAe,EAAE,kBAAkB,UAAU,WAAY;AACxE,UAAM,YAAY,iBAAiB,EAAE,gBAAgB;AACrD,QAAI,cAAc,KAAM;AACxB,UAAM,SAAS,YAAY;AAC3B,QAAI,SAAS,QAAQ,aAAa,QAAQ,SAAS,UAAW,YAAW;AAAA,EAC3E;AACA,SAAO;AACT;AAWO,SAAS,qBAAqB,EAAE,UAAU,UAAU,iBAAiB,GAAsC;AAChH,QAAM,CAAC,EAAE,WAAW,QAAI,0BAAW,CAAC,MAAc,IAAI,GAAG,CAAC;AAC1D,QAAM,SAAS,WAAW,QAAQ;AAClC,QAAM,gBAAY,sBAAsB,MAAM;AAC9C,YAAU,UAAU;AACpB,QAAM,kBAAc,sBAAO,KAAK;AAGhC,QAAM,YAAY,SAAS,GAAG,OAAO,SAAS,IAAI,OAAO,IAAI,KAAK;AAElE,+BAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,UAAU,QAAS;AAEtC,UAAM,OAAO,YAAY;AACvB,UAAI,YAAY,QAAS;AACzB,kBAAY,UAAU;AACtB,UAAI;AACF,cAAM,UAAU,MAAM,iBAAiB;AACvC,cAAM,UAAU,UAAU;AAC1B,YAAI,CAAC,QAAS;AAEd,YAAI,SAAS,UAAU,QAAQ;AAC7B,cAAI,QAAQ,SAAS,YAAY;AAC/B,qBAAS,EAAE,MAAM,mBAAmB,WAAW,QAAQ,WAAW,WAAW,QAAQ,CAAC;AACtF,mBAAO,cAAc,EAAE;AAAA,UACzB,OAAO;AACL,qBAAS,EAAE,MAAM,gBAAgB,WAAW,QAAQ,WAAW,OAAO,QAAQ,OAAO,UAAU,QAAQ,SAAS,CAAC;AAAA,UACnH;AAAA,QACF,WAAW,SAAS,UAAU,eAAe,QAAQ,SAAS,QAAQ;AAGpE,mBAAS,EAAE,MAAM,mBAAmB,WAAW,QAAQ,WAAW,WAAW,QAAQ,CAAC;AACtF,iBAAO,cAAc,EAAE;AAAA,QACzB,OAAO;AAEL,cAAI,QAAQ,SAAS,QAAQ;AAC3B,mBAAO,cAAc,EAAE;AAAA,UACzB,WAAW,KAAK,IAAI,IAAI,QAAQ,YAAY,YAAY;AACtD,mBAAO,cAAc,EAAE;AAAA,UACzB;AAAA,QAEF;AAAA,MACF,QAAQ;AAAA,MAGR,UAAE;AACA,oBAAY,UAAU;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,KAAK,OAAO,YAAY,MAAM;AAAE,WAAK,KAAK;AAAA,IAAE,GAAG,gBAAgB;AACrE,WAAO,MAAM,OAAO,cAAc,EAAE;AAAA,EAEtC,GAAG,CAAC,WAAW,UAAU,gBAAgB,CAAC;AAG1C,+BAAU,MAAM;AACd,QAAI,cAAc,KAAM;AACxB,UAAM,SAAS,qBAAqB,QAAQ;AAC5C,QAAI,WAAW,KAAM;AACrB,UAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,QAAI,SAAS,EAAG;AAChB,UAAM,KAAK,OAAO,WAAW,aAAa,KAAK;AAC/C,WAAO,MAAM,OAAO,aAAa,EAAE;AAAA,EACrC,GAAG,CAAC,WAAW,UAAU,WAAW,CAAC;AACvC;;;ACxIO,IAAM,SAAS;AACf,IAAM,eAAe;AAgBrB,SAAS,iBAAiB,YAAoB,KAA2D;AAC9G,MAAI;AACJ,MAAI;AACF,UAAM,OAAO,aAAa,QAAQ,UAAU;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,MAAM,KAAK,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,OAAO,cAAc,SAAU,QAAO;AACvG,MAAI,MAAM,OAAO,YAAY,OAAQ,QAAO;AAC5C,SAAO,EAAE,gBAAgB,OAAO,kBAAkB,MAAM,UAAU,OAAO,SAAS;AACpF;AAEO,SAAS,kBAAkB,YAAoB,gBAA+B,UAAqB,KAAmB;AAC3H,MAAI,SAAS,SAAS,MAAM,CAAC,YAAY;AACzC,WAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,QAAI;AACF,aAAO,aAAa,QAAQ,YAAY,KAAK,UAAU,EAAE,GAAG,GAAG,WAAW,KAAK,gBAAgB,UAAU,OAAO,CAA8B,CAAC;AAC/I;AAAA,IACF,QAAQ;AAEN,UAAI,OAAO,UAAU,EAAG;AACxB,eAAS,OAAO,MAAM,KAAK,KAAK,OAAO,SAAS,CAAC,CAAC;AAAA,IACpD;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,YAA0B;AAC1D,MAAI;AACF,WAAO,aAAa,WAAW,UAAU;AAAA,EAC3C,QAAQ;AAAA,EAER;AACF;;;AC/CO,IAAM,sBAAyC,CAAC,iBAAiB,sBAAsB,cAAc;AAGrG,IAAM,oBAAoB;AAE1B,SAAS,YAAY,MAAsC;AAChE,QAAM,KAAK,KAAK,QAAQ;AACxB,SAAO,OAAO,OAAO,YAAY,GAAG,WAAW,iBAAiB;AAClE;AAIO,SAAS,gBAAgB,MAAqC;AACnE,QAAM,WAAW,KAAK,UAAU,KAAK;AACrC,SAAO,YAAY,IAAI,KAAK,WAAW,WAAW,KAAK;AACzD;AAGO,IAAM,oBAAoB;AAE1B,IAAM,mBAAmB;AAgBzB,SAAS,WAAW,UAAqB,eAAoC;AAClF,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,CAAC,KAAK,EAAE,SAAS,eAAe,CAAC,EAAE,WAAY;AACnD,UAAM,YAAY,EAAE;AACpB,QAAI,CAAC,aAAa,CAAC,UAAU,MAAM,KAAK,WAAW,EAAG,QAAO,CAAC;AAC9D,UAAM,OAAoB,CAAC;AAC3B,UAAM,MAAM,CAAC,UAAkB,YAAuE;AACpG,YAAM,QAAQ,UAAU,MAAM,UAAU,CAACC,UAASA,MAAK,QAAQ,aAAa,QAAQ;AACpF,YAAM,OAAO,UAAU,MAAM,KAAK;AAClC,YAAM,QAAQ,OAAO,QAAQ,IAAI,GAAG,KAAK,IAAI;AAC7C,UAAI,QAAQ,MAAO,MAAK,KAAK,EAAE,MAAM,OAAO,UAAU,KAAK,QAAQ,QAAQ,UAAU,QAAQ,MAAM,CAAC;AAAA,IACtG;AACA,QAAI,mBAAmB,CAAC,SAAS,KAAK,YAAY,MAAS;AAC3D,QAAI,kBAAkB,MAAM,aAAa;AACzC,WAAO;AAAA,EACT;AACA,SAAO,CAAC;AACV;AAYO,SAAS,aAAa,KAAgB,MAA2B;AACtE,OAAK,KAAK,IAAI,EAAE,MAAM,iBAAiB,SAAS,OAAO,IAAI,QAAQ,EAAE,CAAC;AACtE,OAAK,KAAK;AACV,OAAK,aAAa,MAAM;AACxB,QAAM,cAAc,IAAI;AACxB,OAAK,KAAK,IAAI,KAAK,aAAa,IAAI,KAAK,YAAY,EAAE,WAAW,IAAI,KAAK,WAAW,YAAY,IAAI,EAAE,YAAY,CAAC;AACrH,OAAK,iBAAiB,IAAI,MAAM,IAAI,OAAO,IAAI,MAAM;AACvD;;;ALvEA,SAAS,iBAAiB,GAA2B;AACnD,SAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,SAAS,KAAK,EAAE,SAAS,SAAS,KAC3D,EAAE,WAAW,SAAS,KAAK,EAAE,aAAa,SAAS,MAAM,EAAE,YAAY,UAAU,KAAK,KACtF,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC,EAAE;AACjC;AAKO,IAAM,6BAA6B;AAG1C,SAAS,cAAc,UAAoC;AACzD,MAAI,MAAM;AACV,aAAW,KAAK,UAAU;AACxB,UAAM,IAAI,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;AAC9B,QAAI,EAAE,GAAG,CAAC,MAAM,OAAO,OAAO,SAAS,CAAC,KAAK,IAAI,IAAK,OAAM;AAAA,EAC9D;AACA,SAAO,MAAM;AACf;AA4BO,SAAS,cAAc,cAA4B,cAAwB,iBAA0B,YAAqC;AAC/I,QAAM,WAAO,uBAAQ,MAAM;AACzB,UAAM,UAAU,aAAa,iBAAiB,YAAY,KAAK,IAAI,CAAC,IAAI;AACxE,UAAM,WAAW,WAAW,QAAQ,YAAY,aAAa,YAAY;AACzE,UAAM,OAAO,aAAa,aAAa,IAAI,YAAY,CAAC;AACxD,QAAI,UAAU;AACZ,aAAO,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,uBAAuB,QAAQ,QAAQ,GAAG,gBAAgB,QAAQ,gBAAgB,UAAU,CAAC,EAAE,GAAG,UAAU,MAAM,OAAO,MAAM;AAAA,IACtK;AACA,WAAO,EAAE,OAAO,MAAM,UAAU,OAAO,OAAO,YAAY,aAAa,YAAY,UAAU;AAAA,EAC/F,GAAG,CAAC,CAAC;AACL,QAAM,CAAC,OAAO,QAAQ,QAAI,0BAAW,SAAS,KAAK,KAAK;AACxD,QAAM,YAAQ,sBAAO,cAAc,KAAK,MAAM,QAAQ,CAAC;AACvD,QAAM,gBAAY,sBAA0B,IAAI;AAChD,QAAM,uBAAmB,sBAA6C,IAAI;AAC1E,QAAM,eAAW,sBAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,iBAAa,sBAAO,KAAK,QAAQ;AACvC,QAAM,kBAAc,sBAAO,KAAK;AAEhC,QAAM,uBAAmB,sBAAO,KAAK;AACrC,MAAI,CAAC,iBAAiB,SAAS;AAC7B,qBAAiB,UAAU;AAC3B,QAAI,KAAK,YAAY,KAAK,MAAM,eAAgB,cAAa,iBAAiB,KAAK,MAAM;AAAA,EAC3F;AAEA,QAAM,SAAS,MAAM,IAAI,MAAM,SAAS;AAExC,QAAM,yBAAqB,2BAAY,MAAM;AAC3C,QAAI,iBAAiB,WAAW,MAAM;AACpC,mBAAa,iBAAiB,OAAO;AACrC,uBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,CAAC;AAQL,QAAM,uBAAmB,2BAAY,CAAC,WAAuB;AAC3D,uBAAmB;AACnB,qBAAiB,UAAU,WAAW,MAAM;AAC1C,uBAAiB,UAAU;AAC3B,gBAAU,SAAS,OAAO;AAC1B,gBAAU,UAAU;AACpB,aAAO;AAAA,IACT,GAAG,0BAA0B;AAAA,EAC/B,GAAG,CAAC,kBAAkB,CAAC;AAEvB,QAAM,cAAU,2BAAY,CAAC,QAAoB,YAA2C;AAC1F;AAAC,KAAC,YAAY;AACZ,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAChC,mBAAS,EAAE,MAAM,SAAS,MAAM,CAAC;AAEjC,cAAI,MAAM,SAAS,mBAAoB,MAAM,SAAS,WAAW,CAAC,cAAc,MAAM,IAAI,EAAI,oBAAmB;AAAA,QACnH;AAAA,MACF,SAAS,KAAK;AAIZ,YAAI,UAAU,YAAY,OAAQ,oBAAmB;AACrD,YAAI,eAAe,kCAAgB,SAAQ,GAAG;AAAA,iBACpC,KAAkC,SAAS,cAAc;AAAA,QAA0C,MACxG,OAAM;AAAA,MACb,UAAE;AACA,YAAI,UAAU,YAAY,OAAQ,WAAU,UAAU;AAAA,MACxD;AAAA,IACF,GAAG;AAAA,EACL,GAAG,CAAC,kBAAkB,CAAC;AAEvB,QAAM,UAAM,2BAAY,CAAC,OAAkB,gBAAyB;AAClE,QAAI,SAAS,SAAS,QAAQ,KAAK,EAAG;AACtC,cAAU,SAAS,OAAO;AAC1B,uBAAmB;AACnB,aAAS,EAAE,MAAM,aAAa,OAAO,QAAQ,OAAO,GAAG,aAAa,OAAO,GAAG,YAAY,CAAC;AAC3F,UAAM,SAAS,aAAa,KAAK,KAAK;AACtC,cAAU,UAAU;AACpB,qBAAiB,MAAM;AACrB,eAAS,EAAE,MAAM,OAAO,CAAC;AACzB,eAAS,EAAE,MAAM,gBAAgB,OAAO,IAAI,kCAAe,gCAAgC,SAAS,EAAE,CAAC;AAAA,IACzG,CAAC;AACD,YAAQ,QAAQ,CAAC,QAAQ,SAAS,EAAE,MAAM,gBAAgB,OAAO,IAAI,CAAC,CAAC;AAAA,EACzE,GAAG,CAAC,cAAc,SAAS,oBAAoB,gBAAgB,CAAC;AAEhE,QAAM,WAAO,2BAAY,CAAC,MAAc,SAAuB;AAC7D,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AACd,QAAI;AAAA,MACF,SAAS;AAAA,MAAS,UAAU,MAAM;AAAA,MAAU,WAAW,MAAM;AAAA,MAAW,WAAW,MAAM;AAAA,MACzF,oBAAoB,CAAC,GAAG,mBAAmB;AAAA,MAC3C,GAAI,MAAM,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAChD,GAAG,MAAM,WAAW;AAAA,EACtB,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,YAAQ,2BAAY,MAAM;AAC9B,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,KAAM,KAAI,MAAM,SAAS,QAAQ,mBAAmB,MAAS;AAAA,EACnE,GAAG,CAAC,GAAG,CAAC;AAMR,QAAM,mBAAe,2BAAY,MAAM;AACrC,UAAM,UAAU,iBAAiB,KAAK;AACtC,QAAI,CAAC,QAAS;AACd,QAAI;AACF,gBAAU,SAAS,OAAO;AAC1B,yBAAmB;AACnB,eAAS,EAAE,MAAM,iBAAiB,aAAa,OAAO,EAAE,CAAC;AACzD,YAAM,SAAS,aAAa,KAAK,EAAE,SAAS,oBAAoB,CAAC,GAAG,mBAAmB,EAAE,CAAC;AAC1F,gBAAU,UAAU;AACpB,uBAAiB,MAAM,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC;AACjD,cAAQ,QAAQ,MAAM,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC;AAAA,IAClD,QAAQ;AACN,eAAS,EAAE,MAAM,OAAO,CAAC;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,iBAAiB,cAAc,SAAS,oBAAoB,gBAAgB,CAAC;AAEjF,+BAAU,MAAM;AACd,QAAI,WAAW,QAAS;AACxB,eAAW,UAAU;AACrB,iBAAa;AAAA,EACf,GAAG,CAAC,YAAY,CAAC;AAGjB,+BAAU,MAAM;AACd,QAAI,CAAC,MAAM,MAAO;AAClB,UAAM,QAAQ,aAAa,MAAM,OAAO,KAAK,IAAI,CAAC;AAClD,QAAI,UAAU,KAAM;AACpB,UAAM,QAAQ,WAAW,MAAM,SAAS,EAAE,MAAM,gBAAgB,CAAC,GAAG,KAAK;AACzE,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,MAAM,KAAK,CAAC;AAGhB,+BAAU,MAAM;AACd,QAAI,KAAK,SAAS,WAAY,mBAAkB,UAAU;AAAA,EAC5D,GAAG,CAAC,CAAC;AAML,+BAAU,MAAM;AACd,QAAI,CAAC,cAAc,MAAM,YAAa;AACtC,QAAI,YAAY,SAAS;AAAE,kBAAY,UAAU;AAAO;AAAA,IAAO;AAC/D,UAAM,OAAO,MAAM;AACnB,UAAM,cAAc,KAAK,OAAO,CAAC,GAAG,MAAM;AACxC,UAAI,EAAE,SAAS,QAAQ;AACrB,cAAM,OAAO,KAAK,IAAI,CAAC;AACvB,eAAO,CAAC,CAAC,QAAQ,KAAK,SAAS,eAAe,KAAK,QAAQ,CAAC,KAAK,cAAc,iBAAiB,IAAI;AAAA,MACtG;AACA,aAAO,EAAE,QAAQ,CAAC,EAAE,cAAc,iBAAiB,CAAC;AAAA,IACtD,CAAC;AACD,QAAI,YAAY,WAAW,EAAG;AAC9B,sBAAkB,YAAY,MAAM,gBAAgB,aAAa,KAAK,IAAI,CAAC;AAAA,EAC7E,GAAG,CAAC,YAAY,MAAM,aAAa,MAAM,UAAU,MAAM,cAAc,CAAC;AAGxE,+BAAU,MAAM;AACd,QAAI,CAAC,WAAY;AACjB,UAAM,YAAY,CAAC,MAAoB;AACrC,UAAI,EAAE,QAAQ,cAAc,EAAE,gBAAgB,OAAO,aAAc;AACnE,UAAI,SAAS,QAAQ,YAAa;AAClC,UAAI,EAAE,YAAY,MAAM;AAEtB,cAAM,UAAU;AAChB,qBAAa,iBAAiB;AAC9B,oBAAY,UAAU;AACtB,iBAAS,EAAE,MAAM,QAAQ,CAAC;AAC1B,mBAAW,UAAU;AACrB,qBAAa;AACb;AAAA,MACF;AACA,YAAM,SAAS,iBAAiB,YAAY,KAAK,IAAI,CAAC;AACtD,UAAI,CAAC,UAAU,WAAW,aAAa,WAAW,UAAW;AAC7D,YAAM,UAAU,cAAc,OAAO,QAAQ;AAC7C,mBAAa,iBAAiB,OAAO,kBAAkB;AACvD,kBAAY,UAAU;AACtB,eAAS,EAAE,MAAM,WAAW,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe,CAAC;AAAA,IAChG;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,YAAY,cAAc,YAAY,CAAC;AAE3C,QAAM,WAAO,2BAAY,MAAM,SAAS,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7D,QAAM,YAAQ,2BAAY,MAAM;AAAE,cAAU,SAAS,OAAO;AAAG,cAAU,UAAU;AAAM,uBAAmB;AAAG,aAAS,EAAE,MAAM,QAAQ,CAAC;AAAA,EAAE,GAAG,CAAC,kBAAkB,CAAC;AAClK,QAAM,WAAO,2BAAY,MAAM;AAAE,cAAU,SAAS,OAAO;AAAG,cAAU,UAAU;AAAM,uBAAmB;AAAG,aAAS,EAAE,MAAM,OAAO,CAAC;AAAA,EAAE,GAAG,CAAC,kBAAkB,CAAC;AAChK,QAAM,aAAS,2BAAY,MAAM;AAAE,QAAI,SAAS,QAAQ,OAAQ,OAAM;AAAA,QAAQ,MAAK;AAAA,EAAE,GAAG,CAAC,OAAO,IAAI,CAAC;AACrG,QAAM,mBAAe,2BAAY,MAAM,SAAS,EAAE,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAE9E,QAAM,YAAQ,2BAAY,MAAM;AAC9B,cAAU,SAAS,OAAO;AAAG,cAAU,UAAU;AAAM,uBAAmB;AAC1E,QAAI,WAAY,mBAAkB,UAAU;AAC5C,UAAM,UAAU;AAChB,iBAAa,iBAAiB;AAC9B,aAAS,EAAE,MAAM,QAAQ,CAAC;AAC1B,eAAW,UAAU;AACrB,iBAAa;AAAA,EACf,GAAG,CAAC,YAAY,cAAc,oBAAoB,YAAY,CAAC;AAE/D,QAAM,uBAAmB,2BAAY,MAAM,aAAa,iBAAiB,GAAG,CAAC,YAAY,CAAC;AAC1F,uBAAqB,EAAE,UAAU,MAAM,UAAU,UAAU,iBAAiB,CAAC;AAE7E,SAAO,EAAE,OAAO,MAAM,OAAO,MAAM,QAAQ,MAAM,OAAO,cAAc,OAAO,WAAW,SAAS;AACnG;;;AM3QA,IAAAC,gBAAyD;;;ACElD,IAAM,kBAAkB;AAexB,SAAS,OAAO,GAAgC;AACrD,SAAO,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE;AAC/H;AAEO,IAAM,WAAW,IAAI,KAAK,KAAK;AAG/B,SAAS,aAAa,MAAmB,WAAmB,KAA0B;AAC3F,SAAO,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,UAAc,EAAE,iBAAiB,aAAa,MAAM,EAAE,WAAW,QAAS;AACpH;AAGO,SAAS,YAAY,MAAgC;AAC1D,QAAM,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO;AACrD,QAAM,SAAS,QAAQ,QAAQ,SAAS,CAAC;AACzC,SAAO,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,MAAM,MAAM;AAC9D;AAOA,SAAS,SAAS,YAAiC;AACjD,MAAI;AACF,UAAM,MAAM,OAAO,aAAa,QAAQ,UAAU;AAClD,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO,OAAO,MAAM,KAAK,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC;AAAA,EACvE,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,UAAU,YAAoB,MAAyB;AAC9D,MAAI;AACF,WAAO,aAAa,QAAQ,YAAY,KAAK,UAAU,EAAE,GAAG,GAAG,KAAK,CAAsB,CAAC;AAAA,EAC7F,QAAQ;AAAA,EAER;AACF;AAMO,SAAS,eAAe,YAAoB,WAAmB,UAA8C;AAElH,MAAI,OAAO,YAAY,aAAa,SAAS,UAAU,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC;AAEhF,QAAM,SAAS,CAAC,SAAsB;AACpC,WAAO;AACP,cAAU,YAAY,IAAI;AAC1B,aAAS,IAAI;AAAA,EACf;AACA,SAAO,IAAI;AAEX,SAAO;AAAA,IACL,IAAI,OAAO;AACT,aAAO;AAAA,IACT;AAAA,IACA,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AAAA,IAC5C,QAAQ,CAAC,QAAQ,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC;AAAA,IACzD,UAAU,MAAM,SAAS,KAAK;AAC5B;AAAA,QACE,KAAK,IAAI,CAAC,MAAO,KAAK,SAAS,EAAE,GAAG,KAAK,EAAE,YAAY,SAAY,EAAE,GAAG,GAAG,SAAS,KAAK,cAAc,QAAQ,IAAI,CAAE;AAAA,MACvH;AAAA,IACF;AAAA,IACA,OAAO,KAAK;AACV,UAAI,KAAK,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,GAAG;AACvC,eAAO,KAAK,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,CAAC;AAC5C,eAAO;AAAA,MACT;AACA,UAAI,IAAI,SAAS,SAAS;AACxB,eAAO,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,GAAG,GAAG,CAAC;AACvD,eAAO;AAAA,MACT;AACA,UAAI,KAAK,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,UAAU,gBAAiB,QAAO;AAC3F,aAAO,CAAC,GAAG,MAAM,GAAG,CAAC;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACnGA,IAAAC,gBAAyB;AAIlB,SAAS,QAAQ,UAAqB,QAAwE;AACnH,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAoB,OAAO;AAC7D,SAAO,EAAE,WAAW,aAAa;AACnC;;;AFmEA,IAAM,cAAqD,oBAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;AAClF,IAAM,cAAc;AACpB,IAAM,kBAAkB;AAExB,IAAM,qBAAqB;AAE3B,SAAS,cAAc,GAA6B;AAClD,SAAO,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,WAAW,IAAI,EAAE,UAAU,EAAE;AAC/D;AAEA,SAAS,YAAY,UAAsC,KAAiC;AAC1F,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG;AAC7D,QAAM,OAAO,QAAQ,MAAM;AAC3B,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,MAAM,IAAI,eAAe,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,gBAAgB,IAAI,WAAW,IAAI,KAAK,CAAC;AAClG,SAAO,KAAK;AACd;AAEA,SAAS,YAAY,UAA+B,KAAiC;AACnF,MAAI,IAAI,SAAS,QAAS,QAAO,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,IAAI,OAAO,GAAG;AAC1F,SAAO,SAAS,QAAQ,KAAK,CAAC,OAAO,GAAG,QAAQ,IAAI,GAAG,GAAG;AAC5D;AAEO,SAAS,eAAe,MAAoD;AACjF,QAAM,mBAAe,sBAAO,OAAO,WAAW,CAAC;AAE/C,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAmB,CAAC,CAAC;AAI7C,QAAM,CAAC,KAAK,QAAI,wBAAmB,MAAM,eAAe,KAAK,YAAY,aAAa,SAAS,OAAO,CAAC;AAEvG,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,IAAI;AAC3C,QAAM,CAAC,UAAU,gBAAgB,QAAI,wBAAqC,IAAI;AAC9E,QAAM,EAAE,WAAW,cAAc,kBAAkB,IAAI,QAAQ,MAAM;AACrE,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAS,KAAK;AAClD,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,KAAK;AAC9C,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,wBAAiC,CAAC,CAAC;AACnF,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAwC,CAAC,CAAC;AAC9E,QAAM,CAAC,YAAY,aAAa,QAAI,wBAElC,CAAC,CAAC;AAEJ,QAAM,cAAU,sBAAO,IAAI;AAC3B,UAAQ,UAAU;AAGlB,QAAM,iBAAa,sBAAmB,KAAK,WAAW,CAAC,CAAC;AACxD,aAAW,UAAU,KAAK,WAAW,CAAC;AACtC,QAAM,mBAAe,sBAAO,SAAS;AACrC,eAAa,UAAU;AACvB,QAAM,kBAAc,sBAAO,QAAQ;AACnC,cAAY,UAAU;AACtB,QAAM,0BAAsB,sBAAO,gBAAgB;AACnD,sBAAoB,UAAU;AAC9B,QAAM,oBAAgB,sBAAO,UAAU;AACvC,gBAAc,UAAU;AACxB,QAAM,oBAAgB,sBAAO,UAAU;AACvC,gBAAc,UAAU;AACxB,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,cAAc,KAAK,eAAe;AAExC,QAAM,YAAY,CAAC,SAAiB,QAAwB,GAAG,OAAO,IAAI,GAAG;AAE7E,QAAM,uBAAmB,sBAAO,KAAK,aAAa;AAClD,mBAAiB,UAAU,KAAK;AAIhC,QAAM,kBAAc,2BAAY,CAAC,SAAiB,QAAgB;AAChE,UAAM,MAAM,UAAU,SAAS,GAAG;AAClC,UAAM,WAAW,cAAc,QAAQ,GAAG;AAC1C,QAAI,UAAU,QAAS;AACvB,UAAM,eAAe,EAAE,GAAG,UAAU,SAAS,MAAM,OAAO,MAAM;AAChE,kBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,GAAG,GAAG,aAAa;AACxE,kBAAc,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,aAAa,EAAE;AAC1D,UAAM,KAAK,iBAAiB;AAC5B,QAAI,CAAC,GAAI;AACT,SAAK,GAAG,SAAS,GAAG,EACjB,KAAK,CAAC,UAAU;AACf,YAAM,QAAQ,EAAE,OAAO,SAAS,QAAW,SAAS,OAAO,OAAO,MAAM;AACxE,oBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,GAAG,GAAG,MAAM;AACjE,oBAAc,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,EAAE;AAAA,IACrD,CAAC,EACA,MAAM,MAAM;AACX,YAAM,QAAQ,EAAE,GAAG,cAAc,QAAQ,GAAG,GAAG,SAAS,OAAO,OAAO,KAAK;AAC3E,oBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,GAAG,GAAG,MAAM;AACjE,oBAAc,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,EAAE;AAAA,IACrD,CAAC;AAAA,EACL,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAe,2BAAY,CAAC,SAAiB,QAAgB;AACjE,UAAM,MAAM,UAAU,SAAS,GAAG;AAClC,UAAM,UAAU,cAAc,QAAQ,OAAO,MAAM;AACnD,UAAM,YAAY,UAAU,OAAO;AACnC,kBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,OAAO,GAAG,UAAU;AACzE,kBAAc,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,OAAO,GAAG,UAAU,EAAE;AAI3D,UAAM,WAAW,cAAc,QAAQ,GAAG;AAC1C,QAAI,CAAC,WAAW,EAAE,UAAU,WAAW,UAAU,QAAQ;AACvD,kBAAY,SAAS,GAAG;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,kBAAc,2BAAY,CAAC,SAAiB,QAAgB;AAChE,gBAAY,SAAS,GAAG;AAAA,EAC1B,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,oBAAgB,2BAAY,CAAC,SAAqC;AACtE,QAAI,SAAS,MAAM;AACjB,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,UAAM,OAAO,YAAY;AACzB,UAAM,cAAc,QAAQ;AAE5B,UAAM,iBAAiB,IAAI,IAAI,YAAY,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAClG,QAAI,kBAAkB;AACtB,eAAW,KAAK,KAAK,SAAS;AAC5B,UAAI,CAAC,eAAe,IAAI,EAAE,OAAO,EAAG;AACpC,YAAM,YAAY,MAAM,QAAQ,KAAK,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO;AACrE,YAAM,WAAW,IAAI,KAAK,WAAW,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,YAAY,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,CAAC;AAC5G,UAAI,EAAE,OAAO,KAAK,CAAC,MAAM,YAAY,IAAI,EAAE,IAAI,KAAK,CAAC,SAAS,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG;AACpF,0BAAkB;AAClB;AAAA,MACF;AAAA,IACF;AACA,QAAI,mBAAmB,aAAa,YAAY,YAAa,eAAc,IAAI;AAI/E,eAAW,KAAK,KAAK,SAAS;AAC5B,UAAI,CAAC,eAAe,IAAI,EAAE,OAAO,EAAG;AACpC,YAAM,QAAQ,EAAE,mBAAmB,CAAC;AACpC,UAAI,CAAC,MAAO;AACZ,UAAI,EAAE,WAAW,cAAc,QAAS;AACxC,YAAM,MAAM,MAAM;AAClB,oBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI;AACrE,oBAAc,CAAC,cAAc,EAAE,GAAG,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE;AAC/D,kBAAY,EAAE,SAAS,GAAG;AAAA,IAC5B;AAEA,UAAM,aAAa,YAAY,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO;AAC/D,QAAI,aAAa,YAAY,QAAQ;AACnC,0BAAoB,CAAC,YAAY;AAC/B,YAAI,UAAU;AACd,cAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,mBAAW,OAAO,YAAY;AAC5B,gBAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,cAAI,UAAU,UAAa,IAAI,IAAI,GAAG,MAAM,OAAO;AACjD,gBAAI,IAAI,GAAG,IAAI;AACf,sBAAU;AAAA,UACZ;AAAA,QACF;AACA,eAAO,UAAU,MAAM;AAAA,MACzB,CAAC;AAAA,IACH,OAAO;AACL,UAAI,eAAe;AACnB,iBAAW,OAAO,YAAY;AAC5B,cAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,cAAM,OAAO,oBAAoB,QAAQ,IAAI,GAAG;AAChD,YAAI,UAAU,UAAa,SAAS,UAAa,UAAU,MAAM;AAC/D,yBAAe;AACf;AAAA,QACF;AAAA,MACF;AACA,UAAI,aAAc,YAAW,IAAI;AAAA,IACnC;AAEA,UAAM,YAAY,YACf,OAAO,CAAC,MAAM;AACb,YAAM,QAAQ,YAAY,MAAM,CAAC;AACjC,aAAO,UAAU,cAAc,UAAU,eAAe,UAAU;AAAA,IACpE,CAAC,EACA,IAAI,CAAC,MAAM,EAAE,GAAG;AACnB,QAAI,UAAU,SAAS,EAAG,OAAM,UAAU,WAAW,aAAa,SAAS,KAAK,IAAI,CAAC;AAKrF,gBAAY,UAAU;AACtB,qBAAiB,IAAI;AAAA,EAEvB,GAAG,CAAC,KAAK,CAAC;AAMV,QAAM,kBAAc,sBAAO,KAAK;AAChC,QAAM,iBAAa,sBAAO,KAAK;AAC/B,QAAM,sBAAkB,sBAAO,EAAE;AACjC,QAAM,eAAW,sBAA2B,MAAS;AACrD,QAAM,kBAAc,sBAAO,KAAK;AAChC,QAAM,iBAAa,sBAAO,KAAK;AAC/B,QAAM,wBAAoB,sBAAO,KAAK,cAAc;AACpD,oBAAkB,UAAU,KAAK;AAEjC,QAAM,WAAO,2BAAY,YAAY;AACnC,UAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,GAAG,WAAW,OAAO;AAC1D,QAAI,YAAY,WAAW,QAAQ,WAAW,EAAG;AACjD,UAAM,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG;AAC/C,QAAI,YAAY,SAAS;AAGvB,UAAI,SAAS,gBAAgB,QAAS,YAAW,UAAU;AAC3D;AAAA,IACF;AACA,oBAAgB,UAAU;AAC1B,gBAAY,UAAU;AACtB,QAAI;AACF,YAAM,OAAO,MAAM,kBAAkB,QAAQ,OAAO;AACpD,UAAI,CAAC,WAAW,QAAS;AACzB,UAAI,SAAS,MAAM;AAEjB,oBAAY,UAAU;AACtB,sBAAc,IAAI;AAClB;AAAA,MACF;AACA,oBAAc,IAAI;AAIlB,iBAAW,KAAK,KAAK,SAAS;AAC5B,YAAI,EAAE,UAAU,OAAQ;AACxB,cAAM,MAAM,cAAc,QAAQ,EAAE,OAAO;AAC3C,YAAI,IAAK,aAAY,EAAE,SAAS,GAAG;AAAA,MACrC;AAAA,IACF,QAAQ;AAAA,IAER,UAAE;AACA,kBAAY,UAAU;AACtB,UAAI,WAAW,WAAW,WAAW,SAAS;AAC5C,mBAAW,UAAU;AACrB,aAAK,KAAK;AAAA,MACZ,OAAO;AACL,oBAAY,QAAQ;AAAA,MACtB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,eAAe,WAAW,CAAC;AAE/B,QAAM,kBAAc,sBAAmB,MAAM;AAAA,EAAC,CAAC;AAC/C,cAAY,UAAU,MAAM;AAC1B,WAAO,aAAa,SAAS,OAAO;AACpC,UAAM,UAAU,QAAQ,QAAQ,SAAS,KAAK,WAAW,QAAQ,SAAS;AAC1E,QAAI,CAAC,WAAW,WAAW,YAAY,WAAW,CAAC,WAAW,SAAS,oBAAoB,SAAU;AACrG,UAAM,aAAa,WAAW,QAAQ,SAAS,IAAI,qBAAqB;AACxE,UAAM,SAAS,YAAY,UAAU,YAAY,QAAQ,kBAAkB,MAAO;AAClF,aAAS,UAAU,OAAO,WAAW,MAAM,KAAK,KAAK,GAAG,KAAK,IAAI,aAAa,MAAM,CAAC;AAAA,EACvF;AAIA,+BAAU,MAAM;AACd,eAAW,UAAU;AACrB,WAAO,MAAM;AAAE,iBAAW,UAAU;AAAA,IAAM;AAAA,EAC5C,GAAG,CAAC,CAAC;AAQL,QAAM,wBAAoB,sBAAO,CAAC;AAClC,+BAAU,MAAM;AACd,UAAM,WAAW,kBAAkB,YAAY,KAAK,WAAW,QAAQ,WAAW;AAClF,sBAAkB,UAAU,KAAK;AACjC,QAAI,KAAK,WAAW,KAAK,WAAW,QAAQ,WAAW,GAAG;AACxD,aAAO,aAAa,SAAS,OAAO;AACpC;AAAA,IACF;AACA,QAAI,SAAU,MAAK,KAAK;AAAA,EAC1B,GAAG,CAAC,KAAK,QAAQ,IAAI,CAAC;AAMtB,QAAM,2BAAuB,sBAAO,CAAC;AACrC,QAAM,gBAAgB,KAAK,SAAS,UAAU;AAC9C,+BAAU,MAAM;AACd,UAAM,WAAW,qBAAqB,YAAY,KAAK,QAAQ,QAAQ,WAAW;AAClF,yBAAqB,UAAU;AAC/B,QAAI,YAAY,gBAAgB,EAAG,MAAK,KAAK;AAAA,EAC/C,GAAG,CAAC,eAAe,IAAI,CAAC;AAOxB,+BAAU,MAAM;AACd,QAAI,gBAAgB,cAAc,WAAW,cAAc,eAAe,cAAc,SAAS;AAC/F,wBAAkB,MAAM;AACxB;AAAA,IACF;AACA,UAAM,YAAY,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE;AACzD,UAAM,aAAa,KAAK,SAAS;AACjC,QAAI,cAAc,eAAe,cAAc,EAAG,mBAAkB,WAAW,UAAU,MAAM;AAC/F,QAAI,cAAc,UAAU,eAAe,EAAG,mBAAkB,WAAW,UAAU,MAAM;AAC3F,QAAI,cAAc,WAAW,CAAC,SAAU,mBAAkB,MAAM;AAAA,EAClE,GAAG,CAAC,MAAM,WAAW,UAAU,WAAW,CAAC;AAG3C,QAAM,oBAAgB,sBAAO,KAAK;AAClC,+BAAU,MAAM;AACd,UAAM,YAAY,CAAC,cAAc;AACjC,kBAAc,UAAU,KAAK;AAC7B,QAAI,aAAa,KAAK,OAAQ,MAAK,KAAK;AAAA,EAC1C,GAAG,CAAC,KAAK,QAAQ,IAAI,CAAC;AAItB,+BAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,UAAI,SAAS,oBAAoB,SAAU,QAAO,aAAa,SAAS,OAAO;AAAA,UAC1E,MAAK,KAAK;AAAA,IACjB;AACA,aAAS,iBAAiB,oBAAoB,YAAY;AAC1D,WAAO,MAAM;AACX,eAAS,oBAAoB,oBAAoB,YAAY;AAC7D,aAAO,aAAa,SAAS,OAAO;AAAA,IACtC;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,mBAAe,2BAAY,CAAC,QAAmB;AACnD,sBAAkB,GAAG;AACrB,QAAI,QAAQ,OAAQ,YAAW,KAAK;AACpC,QAAI,QAAQ,QAAS,aAAY,KAAK;AACtC,QAAI,QAAQ,aAAa;AACvB,oBAAc,KAAK;AACnB,WAAK,KAAK;AAAA,IACZ;AACA,QAAI,QAAQ,QAAQ;AAClB,iBAAW,KAAK;AAChB,0BAAoB,CAAC,YAAY;AAC/B,cAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,mBAAW,OAAO,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,GAAG;AACnE,gBAAM,QAAQ,YAAY,YAAY,SAAS,GAAG;AAClD,cAAI,UAAU,OAAW,KAAI,IAAI,GAAG,IAAI;AAAA,QAC1C;AACA,eAAO;AAAA,MACT,CAAC;AACD,WAAK,KAAK;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAIT,QAAM,gBAAY,2BAAY,CAAC,QAA8B;AAC3D,UAAM,SAAS,MAAM,OAAO,GAAG;AAC/B,YAAQ,UAAU,MAAM;AACxB,WAAO;AAAA,EACT,GAAG,CAAC,KAAK,CAAC;AACV,QAAM,eAAW,2BAAY,CAAC,QAAyB,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,CAAC,CAAC;AACrG,QAAM,eAAW,2BAAY,CAAC,WAAgF;AAC5G,UAAM,EAAE,SAAS,qBAAqB,IAAI,IAAI;AAC9C,UAAM,MAAM,OAAO,EAAE,MAAM,SAAS,QAAQ,CAAC;AAC7C,UAAM,SAAS,MAAM,IAAI,GAAG,IAAI,SAAS;AACzC,QAAI,WAAW,QAAS,OAAM,OAAO,EAAE,KAAK,MAAM,SAAS,QAAQ,CAAC;AACpE,YAAQ,UAAU,MAAM;AACxB,QAAI,KAAK;AACP,oBAAc,UAAU,EAAE,GAAG,cAAc,SAAS,CAAC,OAAO,GAAG,IAAI;AACnE,oBAAc,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE;AACrD,YAAM,WAAW,cAAc,QAAQ,UAAU,SAAS,GAAG,CAAC;AAC9D,UAAI,EAAE,UAAU,WAAW,UAAU,OAAQ,aAAY,SAAS,GAAG;AAAA,IACvE,OAAO;AACL,YAAM,OAAO,EAAE,GAAG,cAAc,QAAQ;AACxC,aAAO,KAAK,OAAO;AACnB,oBAAc,UAAU;AACxB,oBAAc,CAAC,SAAS;AACtB,cAAM,MAAM,EAAE,GAAG,KAAK;AACtB,eAAO,IAAI,OAAO;AAClB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,iBAAa,WAAW;AACxB,WAAO;AAAA,EACT,GAAG,CAAC,OAAO,aAAa,YAAY,CAAC;AACrC,QAAM,uBAAmB,2BAAY,MAAM,WAAW,IAAI,GAAG,CAAC,CAAC;AAG/D,QAAM,wBAAoB,2BAAY,MAAM;AAC1C,QAAI,aAAa,YAAY,QAAS,aAAY,IAAI;AAAA,EACxD,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,EAChB;AACF;;;AGxeA,IAAAC,gBAAkE;;;ACElE,IAAM,SAAS;AACR,IAAM,iBAAiB;AAC9B,IAAMC,UAAS,IAAI;AAQZ,SAAS,iBAAiB,YAAoBC,iBAAwB,WAA2B;AACtG,SAAO,GAAG,MAAM,GAAG,UAAU,IAAIA,eAAc,IAAI,SAAS;AAC9D;AAEA,SAAS,KAAK,YAAoBA,iBAAwB,WAAiC;AACzF,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,iBAAiB,YAAYA,iBAAgB,SAAS,CAAC;AACxF,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,QAAQ,KAAK,MAAM,GAAG;AAG5B,QAAI,MAAM,MAAM,kBAAkB,CAAC,MAAM,QAAS,QAAO;AACzD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aACd,YAAoBA,iBAAwB,WAAmB,OACvC;AACxB,QAAM,QAAQ,KAAK,YAAYA,iBAAgB,SAAS;AACxD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,QAAQ,MAAM,KAAKD,UAAS,OAAO,MAAM;AAClD;AAGO,SAAS,wBACd,YAAoBC,iBAAwB,WACpB;AACxB,SAAO,KAAK,YAAYA,iBAAgB,SAAS,GAAG,WAAW;AACjE;AAIA,SAAS,aAAa,SAA2C;AAC/D,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,QAAQ,QAAQ,OAAO,IAAI,CAAC,OAAO;AAAA,MACjC,eAAe,EAAE;AAAA,MACjB,iBAAiB,EAAE;AAAA,MACnB,oBAAoB,EAAE,sBAAsB;AAAA,MAC5C,sBAAsB,EAAE,wBAAwB;AAAA,MAChD,MAAM,EAAE;AAAA,MACR,mBAAmB,EAAE;AAAA,MACrB,WAAW,EAAE;AAAA,MACb,WAAW,EAAE;AAAA,MACb,aAAa,EAAE;AAAA,MACf,SAAS,EAAE,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC7B,SAAS,EAAE;AAAA,QACX,cAAc,EAAE;AAAA,QAChB,cAAc,EAAE;AAAA,QAChB,mBAAmB,EAAE,qBAAqB;AAAA,QAC1C,mBAAmB,EAAE,qBAAqB;AAAA,QAC1C,aAAa,EAAE;AAAA,MACjB,EAAE;AAAA,IACJ,EAAE;AAAA,EACJ;AACF;AAEO,SAAS,cACd,YAAoBA,iBAAwB,WAAmB,SAA0B,OACnF;AACN,QAAM,OAAO,iBAAiB,YAAYA,iBAAgB,SAAS;AAGnE,QAAM,OAAO,GAAG,MAAM,GAAG,UAAU,IAAIA,eAAc;AACrD,MAAI;AACF,aAAS,IAAI,aAAa,SAAS,GAAG,KAAK,GAAG,KAAK;AACjD,YAAM,MAAM,aAAa,IAAI,CAAC;AAC9B,UAAI,OAAO,IAAI,WAAW,IAAI,KAAK,QAAQ,KAAM,cAAa,WAAW,GAAG;AAAA,IAC9E;AACA,UAAM,QAAe,EAAE,GAAG,gBAAgB,IAAI,OAAO,SAAS,aAAa,OAAO,EAAE;AACpF,iBAAa,QAAQ,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,EAClD,QAAQ;AAAA,EAER;AACF;AAKO,SAAS,kBACd,YAAoBA,iBAAwB,WAAmB,eAC/D,MACM;AACN,QAAM,QAAQ,KAAK,YAAYA,iBAAgB,SAAS;AACxD,MAAI,CAAC,MAAO;AACZ,QAAM,SAAS,MAAM,QAAQ,OAAO,IAAI,CAAC,MAAO,EAAE,kBAAkB,gBAAgB,EAAE,GAAG,GAAG,GAAG,KAAK,IAAI,CAAE;AAC1G,gBAAc,YAAYA,iBAAgB,WAAW,EAAE,GAAG,MAAM,SAAS,OAAO,GAAG,MAAM,EAAE;AAC7F;;;AClGA,IAAM,kBAAuC,oBAAI,IAAI,CAAC,YAAY,WAAW,CAAC;AAiBvE,SAAS,YACd,QAAyB,QAAoC,OACnD;AACV,QAAM,MAAM,oBAAI,IAAY;AAE5B,aAAW,SAAS,QAAQ;AAC1B,eAAW,SAAS,MAAM,SAAS;AACjC,UAAI,QAAQ,MAAM,cAAc,MAAO,EAAG;AAC1C,YAAM,QAAQ,OAAO,MAAM,OAAO,GAAG;AACrC,UAAI,UAAU,UAAa,gBAAgB,IAAI,KAAK,EAAG;AACvD,UAAI,IAAI,MAAM,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,GAAG;AAChB;;;AF/BA,IAAM,UAAU;AAGhB,IAAM,oBAAoB;AAC1B,IAAM,uBAAuB;AAwB7B,SAAS,eAAe,gBAAyB,iBAAkC;AACjF,SAAO,mBAAmB,kBAAkB,mBAAmB,MAAM;AACvE;AAEA,SAAS,YAAY,KAAmB;AACtC,QAAM,IAAI,IAAI,YAAY;AAC1B,QAAM,IAAI,GAAG,IAAI,SAAS,IAAI,CAAC,GAAG,SAAS,GAAG,GAAG;AACjD,QAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,SAAS,GAAG,GAAG;AAC5C,SAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACvB;AAEO,SAAS,kBAAkB,MAA0D;AAC1F,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAA0B,CAAC,CAAC;AACxD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAqC,CAAC,CAAC;AACnE,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,CAAC;AAE1C,QAAM,gBAAY,sBAAO,MAAM;AAC/B,YAAU,UAAU;AACpB,QAAM,gBAAY,sBAAO,MAAM;AAC/B,YAAU,UAAU;AAIpB,QAAM,mBAAe,sBAAO,KAAK,SAAS;AAC1C,eAAa,UAAU,KAAK;AAK5B,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,MAAM,YAAY,oBAAI,KAAK,CAAC,CAAC;AACxE,+BAAU,MAAM;AACd,UAAM,KAAK,YAAY,MAAM;AAC3B,YAAM,OAAO,YAAY,oBAAI,KAAK,CAAC;AACnC,mBAAa,CAAC,SAAU,SAAS,OAAO,OAAO,IAAK;AAAA,IACtD,GAAG,iBAAiB;AACpB,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,CAAC;AAIL,+BAAU,MAAM;AACd,QAAI,YAAY;AAEhB,UAAM,mBAAmB,EAAC,oBAAI,KAAK,GAAE,kBAAkB;AACvD,UAAM,MAAM,eAAe,KAAK,gBAAgB,KAAK,eAAe;AAEpE,UAAM,SAAS,aAAa,KAAK,YAAY,KAAK,WAAW,KAAK,IAAI,CAAC;AACvE,QAAI,QAAQ;AACV,UAAI,CAAC,UAAW,WAAU,OAAO,MAAM;AACvC,aAAO,MAAM;AAAE,oBAAY;AAAA,MAAK;AAAA,IAClC;AAEA,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,UAAU,MAAM,KAAK,YAAY,WAAW,gBAAgB;AAClE,YAAI,aAAa,CAAC,QAAS;AAC3B,sBAAc,KAAK,YAAY,KAAK,WAAW,SAAS,KAAK,IAAI,CAAC;AAClE,kBAAU,QAAQ,MAAM;AAAA,MAC1B,QAAQ;AAEN,cAAM,WAAW,wBAAwB,KAAK,YAAY,KAAK,SAAS;AACxE,YAAI,CAAC,aAAa,SAAU,WAAU,SAAS,MAAM;AAAA,MACvD;AAAA,IACF,GAAG;AAEH,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,KAAK,YAAY,KAAK,gBAAgB,KAAK,iBAAiB,SAAS,CAAC;AAE1E,QAAM,WAAO,2BAAY,YAAY;AACnC,UAAM,MAAM,YAAY,UAAU,SAAS,UAAU,SAAS,KAAK,IAAI,CAAC;AACxE,QAAI,IAAI,WAAW,EAAG;AACtB,QAAI;AACF,YAAM,UAAU,MAAM,aAAa,QAAQ,GAAG;AAC9C,UAAI,CAAC,QAAS;AACd,gBAAU,CAAC,SAAS;AAGlB,cAAM,OAAO,EAAE,GAAG,KAAK;AACvB,mBAAW,SAAS,QAAQ,OAAQ,MAAK,MAAM,OAAO,IAAI;AAC1D,eAAO;AAAA,MACT,CAAC;AACD,kBAAY,CAAC;AAAA,IACf,QAAQ;AACN,kBAAY,CAAC,MAAM,IAAI,CAAC;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,CAAC;AAKL,+BAAU,MAAM;AACd,QAAI,CAAC,KAAK,OAAQ;AAClB,SAAK,KAAK;AACV,UAAM,KAAK,YAAY,MAAM;AAAE,WAAK,KAAK;AAAA,IAAE,GAAG,OAAO;AACrD,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,KAAK,QAAQ,MAAM,MAAM,CAAC;AAE9B,QAAM,QAAQ,YAAY;AAE1B,QAAM,gBAAY;AAAA,IAChB,MAAO,QACH,IAGA,OAAO,OAAO,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AAAA,IAC5D,CAAC,QAAQ,KAAK;AAAA,EAChB;AAEA,QAAM,iBAAa,2BAAY,OAAO,eAAuB,YAAuC;AAClG,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,KAAK,eAAe,eAAe,OAAO;AAAA,IAC3D,QAAQ;AAGN,aAAO;AAAA,IACT;AACA,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,QAAQ,EAAE,WAAW,OAAO,SAAS,WAAW,OAAO,aAAa,KAAK;AAC/E,cAAU,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,kBAAkB,gBAAgB,EAAE,GAAG,GAAG,GAAG,MAAM,IAAI,CAAE,CAAC;AACjG,sBAAkB,KAAK,YAAY,eAAe,KAAK,gBAAgB,KAAK,eAAe,GAAG,WAAW,eAAe,KAAK;AAC7H,WAAO;AAAA,EACT,GAAG,CAAC,KAAK,gBAAgB,KAAK,YAAY,KAAK,gBAAgB,KAAK,iBAAiB,SAAS,CAAC;AAE/F,SAAO,EAAE,QAAQ,QAAQ,WAAW,OAAO,YAAY,OAAO,KAAK;AACrE;;;AG9JA,IAAAC,gBAAyD;AAIzD,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAEnB,SAAS,eAAe,UAA0B;AAEhD,SAAO,IAAI,KAAK,eAAe,SAAS,EAAE,UAAU,SAAS,CAAC,EAAE,OAAO,oBAAI,KAAK,CAAC;AACnF;AASO,SAAS,SACd,cACA,EAAE,WAAW,iBAAiB,GACd;AAKhB,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAwB,CAAC,CAAC;AACpD,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,CAAC;AAElD,QAAM,kBAAc,sBAAO,KAAK;AAGhC,QAAM,iBAAa,sBAAO,KAAK;AAC/B,QAAM,sBAAkB,sBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAC1B,QAAM,YAAQ,sBAAO,oBAAoB,UAAU;AACnD,QAAM,UAAU,oBAAoB;AAOpC,QAAM,QAAQ,gBAAgB;AAE9B,+BAAU,MAAM;AACd,QAAI,WAAW,QAAS;AACxB,QAAI,SAAS;AAEb,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,WAAW,CAAC,OAAQ;AAC7C,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,UAAU,eAAe,MAAM,OAAO;AAC5C,cAAM,SAAS,MAAM,KAAK,SAAS,OAAO;AAC1C,YAAI,CAAC,OAAQ;AACb,YAAI,WAAW,MAAM;AAEnB,qBAAW,UAAU;AACrB,qBAAW,KAAK;AAChB,mBAAS,CAAC,CAAC;AAAA,QACb,OAAO;AAEL,mBAAS,OAAO,KAAK;AACrB,qBAAW,OAAO,MAAM,SAAS,CAAC;AAAA,QACpC;AAAA,MACF,QAAQ;AAAA,MAER,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAGA,SAAK,QAAQ;AAGb,QAAI;AACJ,QAAI,cAAc,SAAS;AACzB,mBAAa,OAAO,YAAY,MAAM;AACpC,YAAI,WAAW,SAAS;AACtB,iBAAO,cAAc,UAAU;AAC/B;AAAA,QACF;AACA,aAAK,QAAQ;AAAA,MACf,GAAG,aAAa;AAAA,IAClB;AAEA,WAAO,MAAM;AACX,eAAS;AAKT,kBAAY,UAAU;AACtB,UAAI,eAAe,OAAW,QAAO,cAAc,UAAU;AAAA,IAC/D;AAAA,EAEF,GAAG,CAAC,WAAW,cAAc,KAAK,CAAC;AAEnC,QAAM,cAAU,2BAAY,MAAM;AAChC,oBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,SAAS,OAAO,SAAS,QAAQ;AAC5C;;;AC/GA,IAAAC,gBAAyD;AAUlD,SAAS,eACd,cACA,EAAE,UAAU,GACU;AACtB,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAoC,IAAI;AAChE,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,CAAC;AAElD,QAAM,kBAAc,sBAAO,KAAK;AAChC,QAAM,sBAAkB,sBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,+BAAU,MAAM;AAEd,QAAI,cAAc,QAAS;AAC3B,QAAI,SAAS;AAEb,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,QAAS;AAClC,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,eAAe;AACzC,YAAI,OAAQ,SAAQ,MAAM;AAAA,MAC5B,QAAQ;AAAA,MAER,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AACb,WAAO,MAAM;AACX,eAAS;AAGT,kBAAY,UAAU;AAAA,IACxB;AAAA,EAEF,GAAG,CAAC,WAAW,YAAY,CAAC;AAE5B,QAAM,cAAU,2BAAY,MAAM;AAChC,oBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,MAAM,SAAS,QAAQ;AAClC;;;AC1DA,IAAAC,gBAAyD;AAGzD,IAAM,sBAAsB;AAI5B,IAAM,0BAA0B;AAUzB,SAAS,gBACd,cACuB;AACvB,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAwB,CAAC,CAAC;AAC1D,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,CAAC;AAElD,QAAM,kBAAc,sBAAO,KAAK;AAChC,QAAM,iBAAa,sBAAO,KAAK;AAC/B,QAAM,sBAAkB,sBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAC1B,QAAM,QAAQ,gBAAgB;AAE9B,+BAAU,MAAM;AACd,QAAI,WAAW,QAAS;AACxB,QAAI,SAAS;AACb,QAAI;AACJ,QAAI,WAAW;AAEf,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,WAAW,CAAC,OAAQ;AAC7C,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,oBAAY;AACZ,cAAM,SAAS,MAAM,KAAK,gBAAgB;AAC1C,YAAI,CAAC,OAAQ;AACb,YAAI,WAAW,MAAM;AACnB,qBAAW,UAAU;AACrB,qBAAW,KAAK;AAChB,sBAAY,CAAC,CAAC;AAAA,QAChB,OAAO;AACL,sBAAY,OAAO,QAAQ;AAC3B,qBAAW,IAAI;AAAA,QACjB;AACA,mBAAW,IAAI;AAAA,MACjB,QAAQ;AAKN,YAAI,CAAC,OAAQ;AACb,YAAI,WAAW,yBAAyB;AACtC,2BAAiB,OAAO,WAAW,MAAM;AACvC,gBAAI,CAAC,WAAW,QAAS,MAAK,QAAQ;AAAA,UACxC,GAAG,mBAAmB;AAAA,QACxB,OAAO;AACL,qBAAW,KAAK;AAChB,sBAAY,CAAC,CAAC;AACd,qBAAW,IAAI;AAAA,QACjB;AAAA,MACF,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AAEb,WAAO,MAAM;AACX,eAAS;AACT,kBAAY,UAAU;AACtB,UAAI,mBAAmB,OAAW,QAAO,aAAa,cAAc;AAAA,IACtE;AAAA,EAEF,GAAG,CAAC,cAAc,KAAK,CAAC;AAExB,QAAM,cAAU,2BAAY,MAAM,gBAAgB,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;AAEnE,SAAO,EAAE,SAAS,SAAS,UAAU,SAAS,QAAQ;AACxD;;;AC1FA,IAAAC,iBAAyD;AAUlD,SAAS,iBACd,cACA,EAAE,WAAW,QAAQ,GACG;AACxB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAmC,IAAI;AAC/D,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,CAAC;AAElD,QAAM,kBAAc,uBAAO,KAAK;AAChC,QAAM,sBAAkB,uBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,gCAAU,MAAM;AACd,QAAI,cAAc,eAAe,CAAC,QAAS;AAC3C,QAAI,SAAS;AAEb,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,QAAS;AAClC,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,iBAAiB;AAC3C,YAAI,OAAQ,SAAQ,QAAQ,QAAQ,IAAI;AAAA,MAC1C,QAAQ;AAAA,MAER,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AACb,WAAO,MAAM;AACX,eAAS;AACT,kBAAY,UAAU;AAAA,IACxB;AAAA,EAEF,GAAG,CAAC,WAAW,SAAS,YAAY,CAAC;AAErC,QAAM,cAAU,4BAAY,MAAM;AAChC,oBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAIL,QAAM,mBAAmB,WAAY,cAAc,eAAe,WAAW,SAAS;AAEtF,SAAO,EAAE,MAAM,SAAS,kBAAkB,QAAQ;AACpD;;;AC3DA,IAAAC,iBAAyD;AAUlD,SAAS,aACd,cACA,EAAE,WAAW,QAAQ,GACD;AACpB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAmC,IAAI;AAC/D,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,CAAC;AAElD,QAAM,kBAAc,uBAAO,KAAK;AAChC,QAAM,sBAAkB,uBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,gCAAU,MAAM;AACd,QAAI,cAAc,WAAW,CAAC,QAAS;AACvC,QAAI,SAAS;AAEb,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,QAAS;AAClC,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,aAAa;AACvC,YAAI,OAAQ,SAAQ,QAAQ,WAAW,IAAI;AAAA,MAC7C,QAAQ;AAAA,MAER,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AACb,WAAO,MAAM;AACX,eAAS;AACT,kBAAY,UAAU;AAAA,IACxB;AAAA,EAEF,GAAG,CAAC,WAAW,SAAS,YAAY,CAAC;AAErC,QAAM,cAAU,4BAAY,MAAM;AAChC,oBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAIL,QAAM,mBAAmB,WAAY,cAAc,WAAW,WAAW,SAAS;AAElF,SAAO,EAAE,MAAM,SAAS,kBAAkB,QAAQ;AACpD;;;AC3DA,IAAAC,iBAAyD;AAalD,SAAS,kBACd,cACA,EAAE,WAAW,QAAQ,GACI;AACzB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAyC,IAAI;AACrE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAwB,IAAI;AAChE,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,yBAAwB,IAAI;AAC1E,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAwB,IAAI;AACtE,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,CAAC;AAElD,QAAM,kBAAc,uBAAO,KAAK;AAChC,QAAM,sBAAkB,uBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,gCAAU,MAAM;AACd,QAAI,cAAc,WAAW,CAAC,QAAS;AACvC,QAAI,SAAS;AAEb,UAAM,UAAU,YAA2B;AACzC,YAAM,OAAO,gBAAgB;AAC7B,UAAI,CAAC,QAAQ,YAAY,QAAS;AAClC,kBAAY,UAAU;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,kBAAkB;AAC5C,YAAI,QAAQ;AACV,kBAAQ,QAAQ,WAAW,IAAI;AAC/B,wBAAc,QAAQ,cAAc,IAAI;AACxC,6BAAmB,QAAQ,mBAAmB,IAAI;AAClD,2BAAiB,QAAQ,qBAAqB,IAAI;AAAA,QACpD;AAAA,MACF,QAAQ;AAAA,MAER,UAAE;AACA,oBAAY,UAAU;AACtB,YAAI,OAAQ,YAAW,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AACb,WAAO,MAAM;AACX,eAAS;AACT,kBAAY,UAAU;AAAA,IACxB;AAAA,EAEF,GAAG,CAAC,WAAW,SAAS,YAAY,CAAC;AAErC,QAAM,cAAU,4BAAY,MAAM;AAChC,oBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAIL,QAAM,mBAAmB,WAAY,cAAc,WAAW,WAAW,SAAS;AAElF,SAAO,EAAE,MAAM,YAAY,iBAAiB,eAAe,SAAS,kBAAkB,QAAQ;AAChG;;;ACtEA,IAAAC,iBAA8C;AAUvC,SAAS,oBACd,cAC2B;AAC3B,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAyC,IAAI;AACrE,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAE5C,QAAM,oBAAgB,uBAAO,CAAC;AAC9B,QAAM,sBAAkB,uBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,QAAM,YAAQ,4BAAY,CAAC,aAAqB;AAC9C,UAAM,OAAO,gBAAgB;AAC7B,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,EAAE,cAAc;AAC5B,YAAQ,IAAI;AACZ,eAAW,IAAI;AACf,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,oBAAoB,QAAQ;AACtD,YAAI,QAAQ,cAAc,QAAS,SAAQ,MAAM;AAAA,MACnD,QAAQ;AAAA,MAER,UAAE;AACA,YAAI,QAAQ,cAAc,QAAS,YAAW,KAAK;AAAA,MACrD;AAAA,IACF,GAAG;AAAA,EACL,GAAG,CAAC,CAAC;AAEL,QAAM,YAAQ,4BAAY,MAAM;AAC9B,kBAAc;AACd,YAAQ,IAAI;AACZ,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,MAAM,SAAS,OAAO,MAAM;AACvC;;;AC7CA,IAAAC,iBAA4C;;;ACMrC,IAAM,yBAA4C,CAAC,KAAK,KAAK,KAAK,CAAG;AACrE,IAAM,yBAA4C,CAAC,KAAK,GAAK,KAAK,CAAG;AACrE,IAAM,uBAA0C,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;AAEjE,IAAM,sBAAsB;AACnC,IAAM,iBAAiB;AAEvB,IAAM,iBAAiB;AAEhB,IAAM,QAAQ,EAAE,UAAU,KAAK,UAAU,GAAG,YAAY,GAAG,WAAW,EAAE;AAE/E,IAAMC,UAAS,CAAC,MAA4B,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AACtF,IAAM,QAAQ,CAAC,MAAsB,KAAK,MAAM,IAAI,GAAG;AAEhD,SAAS,UAAU,GAAW,GAAoB;AACvD,SAAO,MAAM,CAAC,MAAM,MAAM,CAAC;AAC7B;AAGO,SAAS,aAAa,GAA6B;AACxD,MAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,QAAM,IAAI;AACV,SAAO,MAAM,QAAQ,EAAE,OAAO,KAAK,MAAM,QAAQ,EAAE,WAAW,KAAK,MAAM,QAAQ,EAAE,MAAM,KAAKA,QAAO,EAAE,OAAO;AAChH;AAEA,SAAS,SAAS,GAA2C;AAC3D,SAAO,CAAC,CAAC,KAAKA,QAAO,EAAE,KAAK,KAAKA,QAAO,EAAE,WAAW,KAAKA,QAAO,EAAE,OAAO,KAAK,OAAO,EAAE,iBAAiB,YAAY,OAAO,EAAE,iBAAiB;AACjJ;AAGA,SAAS,QAAQ,UAA6B,SAA8B;AAC1E,QAAM,MAAgB,CAAC;AACvB,aAAW,KAAK,CAAC,GAAG,UAAU,GAAG,OAAO,GAAG;AACzC,QAAIA,QAAO,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,EAAG,KAAI,KAAK,CAAC;AAAA,EACzE;AACA,SAAO,IAAI,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACjC;AAEO,SAAS,cAAc,MAA4B;AACxD,SAAO,QAAQ,wBAAwB,KAAK,QAAQ,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AAC1E;AAEO,SAAS,cAAc,MAA4B;AACxD,SAAO,QAAQ,wBAAwB,KAAK,YAAY,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AAC9E;AAEO,SAAS,YAAY,MAA4B;AACtD,SAAO,QAAQ,sBAAsB,KAAK,OAAO,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACvE;AAEO,SAAS,gBAAgB,MAA4B;AAC1D,QAAM,MAAM,KAAK,IAAI,gBAAgB,KAAK,MAAM,KAAK,OAAO,CAAC;AAC7D,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,gBAAgB,KAAK,KAAK,IAAK,KAAI,KAAK,CAAC;AACtD,SAAO;AACT;AASO,SAAS,WAAW,QAAkB,WAA2B;AACtE,SAAO,OAAO,KAAK,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,OAAO,CAAC,KAAK;AACrE;AAGO,SAAS,QAAQ,QAAkB,QAAwB;AAChE,QAAM,QAAQ,OAAO,CAAC;AACtB,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,EAAE,SAAS,GAAI,QAAO;AAC1B,QAAM,WAAW,CAAC,MAAsB,KAAK,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC;AACrE,SAAO,OAAO,OAAO,CAAC,MAAM,MAAO,SAAS,CAAC,IAAI,SAAS,IAAI,IAAI,IAAI,MAAO,KAAK;AACpF;AAEO,SAAS,UAAU,QAAkB,MAAsB;AAChE,QAAM,KAAK,OAAO,CAAC;AACnB,QAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACnC,MAAI,OAAO,UAAa,OAAO,OAAW,QAAO;AACjD,SAAO,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE;AACpD;AAEO,SAAS,YAAY,OAA4B,OAAe,OAAyC;AAC9G,QAAM,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAKC,QAAO,EAAE,KAAK,KAAK,UAAU,EAAE,OAAO,KAAK,KAAK,EAAE,UAAU,KAAK;AACvG,SAAO,QAAQ,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,WAAW,SAAS,KAAK,MAAM,MAAM,QAAQ,IAAI,OAAO;AACjH;AAEO,SAAS,UAAU,MAAkB,OAAe,MAAsC;AAC/F,QAAM,OAAO,KAAK,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,KAAKA,QAAO,EAAE,KAAK,KAAK,UAAU,EAAE,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI;AAC3G,QAAM,QAAQ,MAAM;AACpB,QAAM,QAAQ,CAAC,CAAC,SAAS,OAAO,MAAM,mBAAmB,YAAY,MAAM,mBAAmB,MACzF,MAAM,QAAQ,MAAM,IAAI,KAAK,MAAM,KAAK,WAAW,QAAQ,MAAM,KAAK,MAAM,QAAQ;AACzF,SAAO,QAAQ,QAAQ,OAAO;AAChC;AAGO,SAAS,aAAa,MAAkB,OAAe,MAAsB;AAClF,MAAI,UAAU,MAAM,OAAO,IAAI,EAAG,QAAO;AACzC,MAAI,OAAO;AACX,MAAI,UAAU;AACd,aAAW,KAAK,gBAAgB,IAAI,GAAG;AACrC,QAAI,CAAC,UAAU,MAAM,OAAO,CAAC,EAAG;AAChC,UAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,QAAI,MAAM,SAAS;AAAE,aAAO;AAAG,gBAAU;AAAA,IAAI;AAAA,EAC/C;AACA,SAAO;AACT;AAGO,SAAS,aAAa,OAA4B,QAAkB,OAAe,OAAuB;AAC/G,QAAM,OAAO,WAAW,QAAQ,KAAK;AACrC,MAAI,YAAY,OAAO,MAAM,KAAK,EAAG,QAAO;AAC5C,MAAI,OAAsB;AAC1B,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,YAAY,OAAO,GAAG,KAAK,EAAG;AACnC,QAAI,SAAS,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC,EAAG,QAAO;AAAA,EACxG;AACA,SAAO,QAAQ;AACjB;AAGO,SAAS,WAAW,MAAkB,QAAkB,YAAsB,YAAoB,WAAoD;AAC3J,QAAM,OAAO,EAAE,OAAO,WAAW,QAAQ,UAAU,GAAG,MAAM,WAAW,YAAY,SAAS,EAAE;AAC9F,MAAI,UAAU,MAAM,KAAK,OAAO,KAAK,IAAI,EAAG,QAAO;AACnD,MAAI,OAAsB;AAC1B,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,WAAW,KAAK,CAAC,MAAM,UAAU,MAAM,GAAG,CAAC,CAAC,EAAG;AACpD,QAAI,SAAS,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI,MAAM,UAAU,CAAC,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,UAAU,CAAC,EAAG,QAAO;AAAA,EAClH;AACA,SAAO,SAAS,OAAO,OAAO,EAAE,OAAO,MAAM,MAAM,aAAa,MAAM,MAAM,KAAK,IAAI,EAAE;AACzF;AAUA,SAAS,MAAM,OAAoE;AACjF,SAAO,EAAE,cAAc,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE;AAChG;AAEO,SAAS,YAAY,MAAyB,GAA6B;AAChF,SAAO;AAAA,IACL,SAAS,EAAE,gBAAgB,KAAK,OAAO,KAAK,KAAK;AAAA,IACjD,aAAa,EAAE,gBAAgB,KAAK,OAAO,KAAK,KAAK;AAAA,IACrD,QAAQ,EAAE,MAAM,aAAa,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO,GAAG,MAAM,KAAK,KAAK,EAAE;AAAA,EAC1F;AACF;AAEO,SAAS,YAAY,MAAyB,GAA6B;AAChF,SAAO;AAAA,IACL,SAAS,EAAE,gBAAgB,KAAK,OAAO,KAAK,KAAK;AAAA,IACjD,aAAa,EAAE,gBAAgB,KAAK,OAAO,KAAK,KAAK;AAAA,IACrD,QAAQ,EAAE,MAAM,aAAa,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO,GAAG,MAAM,KAAK,KAAK,EAAE;AAAA,EAC1F;AACF;AAEO,SAAS,SAAS,MAAuB,GAA6B;AAC3E,SAAO;AAAA,IACL,SAAS,EAAE,aAAa,KAAK,MAAM,KAAK,KAAK;AAAA,IAC7C,aAAa,EAAE,aAAa,KAAK,MAAM,KAAK,KAAK;AAAA,IACjD,QAAQ,EAAE,MAAM,SAAS,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,GAAG,MAAM,KAAK,MAAM,IAAI,EAAE;AAAA,EACzF;AACF;AAEO,SAAS,UAAU,MAAwB,GAA6B;AAC7E,SAAO;AAAA,IACL,SAAS,EAAE,cAAc,KAAK,aAAa,KAAK,kBAAkB,MAAM,KAAK,KAAK;AAAA,IAClF,aAAa,cAAc,MAAM,CAAC;AAAA,IAClC,QAAQ,EAAE,MAAM,UAAU,qBAAqB,KAAK,qBAAqB,GAAG,MAAM,KAAK,KAAK,EAAE;AAAA,EAChG;AACF;AAGO,SAAS,cAAc,MAAwB,GAA0B;AAC9E,SAAO,EAAE,UAAU,QAAQ,YAAY,EAAE,YAAY,KAAK,qBAAqB,KAAK,aAAa,KAAK,kBAAkB,IAAI,CAAC;AAC/H;;;ADtLO,IAAM,kBAAkB;AAUxB,SAAS,cAAc,EAAE,iBAAiB,QAAQ,QAAQ,MAAM,KAAK,IAAI,GAK1D;AACpB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA4B,IAAI;AACxD,QAAM,cAAU,uBAA0B,IAAI;AAC9C,QAAM,gBAAY,uBAAO,MAAM;AAC/B,QAAM,kBAAc,uBAAO,KAAK;AAChC,QAAM,iBAAa,uBAAO,IAAI;AAE9B,QAAM,aAAS,uBAAO,eAAe;AACrC,SAAO,UAAU;AACjB,QAAM,aAAS,uBAAO,GAAG;AACzB,SAAO,UAAU;AAEjB,gCAAU,MAAM;AACd,eAAW,UAAU;AACrB,WAAO,MAAM;AAAE,iBAAW,UAAU;AAAA,IAAM;AAAA,EAC5C,GAAG,CAAC,CAAC;AAEL,gCAAU,MAAM;AACd,QAAI,UAAU,YAAY,QAAQ;AAChC,gBAAU,UAAU;AACpB,cAAQ,UAAU;AAClB,cAAQ,IAAI;AAAA,IACd;AACA,QAAI,CAAC,UAAU,YAAY,QAAS;AACpC,UAAM,OAAO,QAAQ;AACrB,UAAM,MAAM,OAAO,OAAO,QAAQ,IAAI,KAAK,MAAM,KAAK,UAAU,IAAI,OAAO;AAE3E,QAAI,OAAO,gBAAiB;AAC5B,gBAAY,UAAU;AAGtB,YAAQ,QAAQ,EACb,KAAK,MAAM,OAAO,QAAQ,MAAM,CAAC,EACjC,KAAK,CAAC,SAAS;AAKd,UAAI,SAAS,QAAS,aAAa,IAAI,KAAK,CAAC,WAAW,IAAI,GAAI;AAC9D,gBAAQ,UAAU;AAClB,YAAI,WAAW,QAAS,SAAQ,IAAI;AACpC;AAAA,MACF;AACA,UAAI,CAAC,aAAa,IAAI,EAAG;AACzB,cAAQ,UAAU;AAClB,UAAI,WAAW,QAAS,SAAQ,IAAI;AAAA,IACtC,CAAC,EACA,MAAM,MAAM;AAAA,IAAsD,CAAC,EACnE,QAAQ,MAAM;AAAE,kBAAY,UAAU;AAAA,IAAM,CAAC;AAAA,EAClD,GAAG,CAAC,QAAQ,MAAM,CAAC;AAEnB,SAAO;AACT;AAEA,SAAS,WAAW,MAA2B;AAC7C,SAAO,KAAK,QAAQ,SAAS,KAAK,KAAK,YAAY,SAAS,KAAK,KAAK,OAAO,SAAS,KAChF,KAAK,YAAY,UAAa,KAAK,QAAQ,SAAS;AAC5D;;;AElEO,SAAS,cAAc,OAA+B,WAA6B;AACxF,SAAO,OAAO,UAAU,UAAU,CAAC;AACrC;AAaO,SAAS,WAAW,OAAwC;AACjE,SAAO,OAAO,UAAU;AAC1B;AAQO,SAAS,gBACd,QACA,QACiB;AACjB,SAAO,OACJ,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,SAAS,MAAM,QAAQ,OAAO,CAAC,MAAM,CAAC,WAAW,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EACnG,OAAO,CAAC,UAAU,MAAM,QAAQ,SAAS,CAAC;AAC/C;;;AC3CA,IAAAC,iBAA0C;AAGnC,IAAM,sBAAkB,8BAAkC,IAAI;AAE9D,SAAS,cAAkC;AAChD,aAAO,2BAAW,eAAe;AACnC;;;ACPA,IAAAC,iBAA+C;AAMxC,SAAS,kBACd,KACA,QACA,WACA,cACY;AACZ,QAAM,eAAW,uBAAO,oBAAI,IAAY,CAAC;AACzC,QAAM,oBAAgB,uBAAsB,IAAI;AAEhD,gCAAU,MAAM;AACd,QAAI,QAAQ;AACV,UAAI,cAAc,QAAS,MAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAC5D,oBAAc,UAAU;AACxB;AAAA,IACF;AACA,kBAAc,UAAU;AACxB,QAAI,aAAa,CAAC,SAAS,QAAQ,IAAI,SAAS,GAAG;AACjD,eAAS,QAAQ,IAAI,SAAS;AAC9B,WAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,KAAK,QAAQ,SAAS,CAAC;AAE3B,aAAO,4BAAY,MAAM;AACvB,SAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACpC,iBAAa;AAAA,EACf,GAAG,CAAC,KAAK,YAAY,CAAC;AACxB;;;AChCA,IAAAC,iBAAkC;AAM3B,SAAS,iBAAiB,KAAyB,QAAuB;AAC/E,QAAM,oBAAgB,uBAAO,KAAK;AAElC,gCAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX,oBAAc,UAAU;AACxB;AAAA,IACF;AACA,QAAI,cAAc,WAAW,CAAC,IAAK;AACnC,kBAAc,UAAU;AACxB,QAAI,IAAI,EAAE,MAAM,cAAc,CAAC;AAAA,EACjC,GAAG,CAAC,KAAK,MAAM,CAAC;AAClB;;;AClBA,IAAAC,iBAA4C;;;ACA5C,IAAAC,iBAAyB;;;ACGlB,IAAM,mBAAmB;;;ACCvB;AADF,SAAS,OAAO,EAAE,UAAU,GAAwC;AACzE,SAAO,4CAAC,SAAI,WAAsB,KAAK,kBAAkB,KAAI,IAAG,eAAY,QAAO;AACrF;AACO,SAAS,WAAwB;AACtC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,sDAAC,UAAK,MAAK,gBAAe,GAAE,+BAA8B,GAAE;AAC1I;AACO,SAAS,YAAyB;AACvC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,sDAAC,UAAK,MAAK,QAAO,GAAE,wBAAuB,QAAO,gBAAe,aAAY,KAAI,GAAE;AACjK;AACO,SAAS,cAA2B;AACzC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,sDAAC,UAAK,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,GAAE,gBAAe,GAAE;AACtM;AAIO,SAAS,YAAyB;AACvC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,uDAAC,OAAE,MAAK,gBAAe;AAAA,gDAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,OAAM;AAAA,IAAE,4CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA,IAAE,4CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA,KAAE,GAAI;AAC9M;AACO,SAAS,cAA2B;AACzC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,uDAAC,OAAE,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ;AAAA,gDAAC,UAAK,GAAE,gDAA+C;AAAA,IAAE,4CAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI;AAAA,IAAE,4CAAC,YAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI;AAAA,IAAE,4CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,KAAE,GAAI;AACpT;AACO,SAAS,YAAyB;AACvC,SAAO,4CAAC,SAAI,SAAQ,aAAY,OAAM,OAAM,QAAO,OAAM,eAAY,QAAO,uDAAC,OAAE,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,gBAAe,SAAQ;AAAA,gDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI;AAAA,IAAE,4CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI;AAAA,KAAE,GAAI;AACpQ;AAIA,IAAM,kBAA0C;AAAA,EAC9C,UAAU;AAAA,EAAK,YAAY;AAAA,EAAM,MAAM;AAAA,EACvC,MAAM;AAAA,EAAM,eAAe;AAAA,EAAM,QAAQ;AAAA,EACzC,QAAQ;AAAA,EAAM,QAAQ;AAAA,EAAM,cAAc;AAAA,EAC1C,aAAa;AAAA,EAAM,MAAM;AAAA,EAAM,MAAM;AAAA,EAAM,SAAS;AACtD;AAEO,SAAS,cAAc,EAAE,KAAK,GAAkC;AAGrE,QAAM,QAAQ,OAAO,UAAU,eAAe,KAAK,iBAAiB,IAAI,IACpE,gBAAgB,IAAI,IACpB,gBAAgB;AACpB,SAAO,4CAAC,UAAK,WAAU,mBAAkB,eAAY,QAAQ,iBAAM;AACrE;;;AFrCiC,IAAAC,sBAAA;AAF1B,SAAS,UAAU,EAAE,SAAS,UAAU,GAA0D;AACvG,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,MAAI,CAAC,WAAW,OAAQ,QAAO,6CAAC,UAAO,WAAsB;AAC7D,SAAO,6CAAC,SAAI,WAAsB,KAAK,SAAS,KAAI,IAAG,eAAY,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAC5G;;;AGEM,IAAAC,sBAAA;AANC,SAAS,eACd,EAAE,MAAM,QAAQ,WAAW,eAAe,WAAW,KAAK,GAE7C;AACb,QAAM,OACJ,8CAAC,YAAO,MAAK,UAAS,WAAU,sBAAqB,SAAS,QAC5D;AAAA,kDAAC,UAAK,WAAU,sBAAqB,eAAY,QAAO;AAAA,mDAAC,OAAE;AAAA,MAAI,6CAAC,OAAE;AAAA,MAAI,6CAAC,OAAE;AAAA,OAAI;AAAA,IAC7E,6CAAC,UAAK,WAAU,sBAAsB,gBAAK;AAAA,KAC7C;AAEF,QAAM,UAAU,YACd,6CAAC,YAAO,MAAK,UAAS,WAAU,mBAAkB,cAAY,cAAc,SAAS,WAAW,kBAAC,IAC/F;AACJ,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO,8CAAC,SAAI,WAAU,iBAAgB,MAAK,QAAQ;AAAA;AAAA,MAAM;AAAA,OAAQ;AAAA,EACnE;AACA,SACE,8CAAC,SAAI,WAAU,qCAAoC,MAAK,QACtD;AAAA,kDAAC,SAAI,WAAU,qBAAqB;AAAA;AAAA,MAAM;AAAA,OAAQ;AAAA,IAClD,6CAAC,SAAI,WAAU,sBACZ,eAAK,IAAI,CAAC,KAAK,MACd,6CAAC,YAAiC,MAAK,UAAS,WAAU,qBAAoB,SAAS,IAAI,OAAQ,cAAI,SAA1F,GAAG,CAAC,IAAI,IAAI,KAAK,EAA+E,CAC9G,GACH;AAAA,KACF;AAEJ;;;AJPI,IAAAC,sBAAA;AAZG,SAAS,QAAQ,EAAE,OAAO,UAAU,WAAW,SAAS,QAAQ,gBAAgB,eAAe,WAAW,eAAe,OAAO,cAAc,KAAK,GAAyP;AACjZ,QAAM,SAAS,aAAa;AAC5B,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,KAAK;AACxC,QAAM,eAAW,uBAAO,YAAY;AACpC,gCAAU,MAAM;AACd,QAAI,SAAS,WAAW,QAAQ;AAC9B,eAAS,UAAU;AACnB,eAAS,IAAI;AACb,qBAAe;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,CAAC;AACzB,SACE,8CAAC,SAAI,WAAW,QAAQ,6BAA6B,iBAClD;AAAA,aAAS,6CAAC,kBAAe,MAAM,QAAQ,QAAgB,WAAW,YAAY,iBAAiB,QAAW,cAA4B,MAAM,YAAY,OAAO,QAAW,IAAK;AAAA,IAChL,6CAAC,YAAO,MAAK,UAAS,WAAU,YAAW,cAAY,OAAO,SAAS,QACrE,uDAAC,aAAU,SAAkB,WAAU,iBAAgB,GACzD;AAAA,KACF;AAEJ;;;AK/BA,IAAAC,iBAAuG;;;ACAvG,IAAAC,iBAA4C;AA8DtC,IAAAC,sBAAA;AA1DC,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AAAA,EACvB,mBAAmB;AACrB,GASgB;AACd,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,eAAW,uBAA0B,IAAI;AAC/C,QAAM,mBAAe,uBAA0B,IAAI;AAInD,QAAM,UAAU,CAAC,EAAE,YAAY;AAE/B,gCAAU,MAAM;AACd,QAAI,SAAU,cAAa,SAAS,MAAM;AAAA,EAC5C,GAAG,CAAC,QAAQ,CAAC;AAEb,gCAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,YAAY,CAAC,MAAkB;AACnC,UAAI,CAAC,QAAQ,SAAS,SAAS,EAAE,MAAc,EAAG,aAAY,KAAK;AAAA,IACrE;AACA,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,UAAU;AACtB,oBAAY,KAAK;AACjB,iBAAS,SAAS,MAAM;AAAA,MAC1B;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,SAAS;AAChD,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,SAAS;AACnD,eAAS,oBAAoB,WAAW,KAAK;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,qBAAqB,MAAY;AACrC,gBAAY,KAAK;AACjB,wBAAoB;AAAA,EACtB;AAEA,SACE,8CAAC,YAAO,WAAU,eAChB;AAAA,iDAAC,aAAU,SAAkB,WAAU,oBAAmB;AAAA,IAC1D,6CAAC,UAAK,WAAU,qBAAqB,yBAAe,iBAAgB;AAAA,IACnE,UACC,8CAAC,SAAI,WAAU,kBAAiB,KAAK,SACnC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,KAAK;AAAA,UACL,iBAAc;AAAA,UACd,iBAAe;AAAA,UACf,cAAY;AAAA,UACZ,SAAS,MAAM,YAAY,CAAC,SAAS,CAAC,IAAI;AAAA,UAE1C,uDAAC,aAAU;AAAA;AAAA,MACb;AAAA,MACC,WACC,6CAAC,SAAI,WAAU,aAAY,MAAK,QAAO,cAAY,kBACjD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,MAAK;AAAA,UACL,KAAK;AAAA,UACL,SAAS;AAAA,UAET,uDAAC,UAAM,gCAAqB;AAAA;AAAA,MAC9B,GACF,IACE;AAAA,OACN,IACE;AAAA,IACJ,6CAAC,YAAO,MAAK,UAAS,WAAU,cAAa,cAAY,YAAY,SAAS,SAC5E,uDAAC,aAAU,GACb;AAAA,KACF;AAEJ;;;ACjGA,IAAAC,iBAAkC;;;ACAlC,4BAA+C;AAC/C,wBAAsB;AAIlB,IAAAC,sBAAA;AAFJ,IAAM,aAAyB;AAAA,EAC7B,GAAG,CAAC,EAAE,UAAU,KAAK,MACnB,6CAAC,OAAE,MAAY,QAAO,UAAS,KAAI,uBAAsB,WAAU,gBAAgB,UAAS;AAAA,EAE9F,OAAO,CAAC,EAAE,SAAS,MACjB,6CAAC,SAAI,WAAU,mBAAkB,uDAAC,WAAM,WAAU,iBAAiB,UAAS,GAAQ;AAAA,EAEtF,IAAI,CAAC,EAAE,SAAS,MAAM,6CAAC,QAAG,WAAU,cAAc,UAAS;AAAA,EAC3D,IAAI,CAAC,EAAE,SAAS,MAAM,6CAAC,QAAG,WAAU,cAAc,UAAS;AAAA,EAC3D,MAAM,CAAC,EAAE,SAAS,MAAM,6CAAC,UAAK,WAAU,gBAAgB,UAAS;AACnE;AAEO,SAAS,SAAS,EAAE,KAAK,GAAkC;AAChE,SACE,6CAAC,SAAI,WAAU,WACb,uDAAC,sBAAAC,SAAA,EAAc,eAAe,CAAC,kBAAAC,OAAS,GAAG,YAAyB,gBAAK,GAC3E;AAEJ;;;ACrBA,IAAAC,iBAAyB;AAiBrB,IAAAC,sBAAA;AAdJ,IAAM,cAAc;AACpB,IAAM,YAAY;AAElB,SAAS,SAAS,MAAsB;AACtC,SAAO,KAAK,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,YAAY;AACnF;AAGA,SAAS,YAAY,QAAwB;AAC3C,SAAO,OAAO,QAAQ,UAAU,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;AACzD;AAEA,SAAS,MAAM,EAAE,OAAO,MAAM,GAAmD;AAC/E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,iBAAiB,OAAO,KAAK,IAAI;AAAA,MACzC,GAAI,QAAQ,EAAE,MAAM,OAAO,OAAO,OAAO,cAAc,MAAM,IAAI,EAAE,eAAe,OAAgB;AAAA;AAAA,EACrG;AAEJ;AAGA,SAAS,QAAQ,EAAE,GAAG,GAAG,EAAE,GAA4D;AACrF,MAAI,IAAI,IAAI,MAAM,EAAG,QAAO;AAC5B,SACE,8CAAC,UAAK,WAAU,aAAY,eAAY,QACrC;AAAA,QAAI,IAAI,6CAAC,UAAK,WAAU,eAAc,OAAO,EAAE,UAAU,EAAE,GAAG,IAAK;AAAA,IACnE,IAAI,IAAI,6CAAC,UAAK,WAAU,eAAc,OAAO,EAAE,UAAU,EAAE,GAAG,IAAK;AAAA,IACnE,IAAI,IAAI,6CAAC,UAAK,WAAU,eAAc,OAAO,EAAE,UAAU,EAAE,GAAG,IAAK;AAAA,KACtE;AAEJ;AAEA,SAAS,aAAa,EAAE,EAAE,GAAiC;AACzD,QAAM,IAAI,UAAU,KAAK,EAAE,KAAK;AAChC,MAAI,GAAG;AACL,WACE,8CAAC,SAAI,WAAU,mBACb;AAAA,mDAAC,UAAK,WAAU,mBAAkB,uDAAC,WAAQ,GAAG,OAAO,EAAE,CAAC,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC,GAAG,GAAE;AAAA,MAChG,6CAAC,UAAK,WAAU,qBAAqB,YAAE,OAAM;AAAA,OAC/C;AAAA,EAEJ;AACA,SACE,8CAAC,SAAI,WAAU,mBACb;AAAA,iDAAC,UAAK,WAAU,mBAAmB,YAAE,OAAM;AAAA,IAC3C,6CAAC,UAAK,WAAU,qBAAqB,YAAE,OAAM;AAAA,KAC/C;AAEJ;AAEA,SAAS,UAAU,EAAE,MAAM,GAA8C;AACvE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AACrC,SACE,6CAAC,SAAI,WAAU,oBAAmB,OAAO,EAAE,qBAAqB,UAAU,IAAI,SAAS,GACpF,gBAAM,IAAI,CAAC,MAAM,6CAAC,gBAAqC,KAAnB,EAAE,QAAQ,EAAE,KAAa,CAAE,GAClE;AAEJ;AAEA,SAAS,WAAW,EAAE,GAAG,eAAe,GAAwD;AAC9F,QAAM,YAAY,EAAE,OAAO,WAAW,IAAI,EAAE,OAAO,CAAC,IAAK;AACzD,SACE,8CAAC,SAAI,WAAU,iBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,EAAE,SAAS,SAAS,yBAAyB;AAAA,QACxD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,OAAO,EAAE,KAAK,IAAI,IAAI;AAAA,QAEzD,YAAE,QAAQ,KAAK,SAAS,EAAE,IAAI;AAAA;AAAA,IACjC;AAAA,IACA,8CAAC,UAAK,WAAU,qBACd;AAAA,mDAAC,UAAK,WAAU,WAAW,YAAE,MAAK;AAAA,MACjC,EAAE,MAAM,6CAAC,UAAK,WAAU,YAAY,YAAE,KAAI,IAAU;AAAA,OACvD;AAAA,IACA,8CAAC,UAAK,WAAU,mBACb;AAAA,wBAAkB,WAAW,QAAQ,6CAAC,SAAM,OAAO,UAAU,OAAO,OAAO,UAAU,OAAO,IAAK;AAAA,MACjG,EAAE,SAAS,6CAAC,UAAK,WAAU,qBAAqB,sBAAY,EAAE,MAAM,GAAE,IAAU;AAAA,OACnF;AAAA,KACF;AAEJ;AAEA,SAAS,UAAU,EAAE,QAAQ,QAAQ,SAAS,GAAwF;AACpI,SACE,6CAAC,SAAI,WAAU,qBAAoB,MAAK,WACrC,iBAAO,IAAI,CAAC,GAAG,MACd;AAAA,IAAC;AAAA;AAAA,MAEC,MAAK;AAAA,MACL,MAAK;AAAA,MACL,WAAU;AAAA,MACV,iBAAe,MAAM;AAAA,MACrB,cAAY,EAAE;AAAA,MACd,OAAO,EAAE;AAAA,MACT,SAAS,MAAM,SAAS,CAAC;AAAA,MAExB,YAAE,QAAQ,6CAAC,SAAM,OAAO,EAAE,OAAO,IAAK,EAAE;AAAA;AAAA,IATpC,OAAO,EAAE,iBAAiB,KAAK;AAAA,EAUtC,CACD,GACH;AAEJ;AAEA,SAAS,eAAe,EAAE,EAAE,GAA+B;AACzD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,CAAC;AACtC,QAAM,UAAU,EAAE,OAAO,SAAS;AAClC,MAAI,CAAC,SAAS;AACZ,WACE,6CAAC,SAAI,WAAU,8BAA6B,aAAW,EAAE,MACvD,uDAAC,cAAW,GAAM,gBAAgB,OAAO,GAC3C;AAAA,EAEJ;AACA,QAAM,QAAQ,EAAE,OAAO,SAAS;AAChC,QAAM,QAAQ,EAAE,OAAO,QAAS,EAAE,OAAO,MAAM,IAAI,SAAS,IAAK,CAAC;AAClE,SACE,8CAAC,SAAI,WAAU,cAAa,aAAW,EAAE,MACvC;AAAA,iDAAC,cAAW,GAAM,gBAAgB,CAAC,OAAO;AAAA,IACzC,QAAQ,6CAAC,aAAU,QAAQ,EAAE,QAAQ,QAAgB,UAAU,WAAW,IAAK;AAAA,IAChF,6CAAC,aAAU,OAAO,MAAM,OAAO;AAAA,KACjC;AAEJ;AAEO,SAAS,eAAe,EAAE,OAAO,UAAU,gBAAgB,aAAa,gBAAgB,CAAC,MAAc,QAAQ,CAAC,QAAQ,GAA+H;AAC5P,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,UAAU,WAAW,QAAQ,MAAM,MAAM,GAAG,WAAW;AAC7D,QAAM,WAAW,MAAM,SAAS;AAChC,SACE,8CAAC,SAAI,WAAU,cACZ;AAAA,YAAQ,IAAI,CAAC,MAAM,6CAAC,kBAA0B,KAAN,EAAE,EAAU,CAAE;AAAA,IACtD,WAAW,IACV,6CAAC,YAAO,MAAK,UAAS,WAAU,mBAAkB,UAAoB,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,GACvG,qBAAW,gBAAgB,cAAc,QAAQ,GACpD,IACE;AAAA,KACN;AAEJ;;;AChJA,IAAAC,iBAAsC;;;ACAtC,IAAAC,iBAA4B;AAC5B,IAAAC,qBAA4E;;;ACD5E,IAAAC,iBAA0C;AAqBnC,IAAM,uBAAmB,8BAAgC,IAAI;AAE7D,SAAS,eAAiC;AAC/C,aAAO,2BAAW,gBAAgB;AACpC;;;ADNA,SAAS,YAAY,OAAyE;AAC5F,SAAO,QAAQ,KAAK;AAAA,IAClB;AAAA,IACA,IAAI,QAAe,CAAC,GAAG,WACrB,WAAW,MAAM,OAAO,IAAI,MAAM,uBAAuB,CAAC,GAAG,sBAAsB,CAAC;AAAA,EACxF,CAAC;AACH;AAIO,SAAS,WACd,MAAwB,IACkD;AAC1E,QAAM,MAAM,YAAY;AACxB,QAAM,YAAY,aAAa;AAC/B,QAAM,UAAU,KAAK;AACrB,QAAM,YAAY,CAAC,CAAC,IAAI;AACxB,aAAO,4BAAY,OAAO,WAAW,EAAE,qBAAqB,gBAAgB,KAAK,MAAM;AACrF,QAAI,CAAC,QAAS,QAAO,EAAE,MAAM,SAAS;AACtC,UAAM,OAAO,eAAe,WAAW,YAAY,iBAAiB,QAAW,IAAI;AAGnF,QAAI,wBAAwB,QAAW;AACrC,WAAK,IAAI,EAAE,MAAM,cAAc,YAAY,UAAU,qBAAqB,UAAU,qBAAqB,GAAG,KAAK,CAAC;AAAA,IACpH;AACA,QAAI;AACF,YAAM,MAAM,MAAM,YAAY,QAAQ,QAAQ,QAAQ,SAAS,CAAC,CAAC;AAKjE,UAAI,OAAO,QAAQ,KAAC,sCAAkB,GAAG,EAAG,OAAM,IAAI,MAAM,8BAA8B;AAC1F,YAAM,SAAS,OAAO;AACtB,UAAI,wBAAwB,QAAW;AACrC,aAAK,IAAI;AAAA,UACP,MAAM;AAAA,UAAe,YAAY;AAAA,UAAU;AAAA,UAAqB,UAAU;AAAA,UAC1E,SAAS,YAAY,MAAM;AAAA,UAAG,GAAG;AAAA,QACnC,CAAC;AAAA,MACH;AACA,UAAI,WAAW;AACb,YAAI,WAAW,MAAM,EAAG,WAAU,OAAO,UAAU,WAAW;AAC9D,YAAI,SAAS,MAAM,KAAK,wBAAwB,QAAW;AACzD,oBAAU,UAAU,EAAE,WAAW,QAAQ,qBAAqB,KAAK,CAAC;AAAA,QACtE;AAAA,MACF;AACA,aAAO,EAAE,MAAM,YAAY,OAAO;AAAA,IACpC,QAAQ;AACN,UAAI,wBAAwB,QAAW;AACrC,aAAK,IAAI,EAAE,MAAM,eAAe,YAAY,UAAU,qBAAqB,UAAU,qBAAqB,SAAS,WAAW,GAAG,KAAK,CAAC;AAAA,MACzI;AACA,aAAO,EAAE,MAAM,SAAS;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,SAAS,KAAK,WAAW,SAAS,CAAC;AACzC;;;AExEA,IAAAC,iBAA0B;AActB,IAAAC,sBAAA;AAXJ,IAAM,aAAa;AAEZ,SAAS,MAAM,EAAE,OAAO,UAAU,GAA2E;AAClH,gCAAU,MAAM;AACd,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,WAAW,WAAW,UAAU;AAC9C,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,OAAO,SAAS,CAAC;AAErB,MAAI,CAAC,MAAO,QAAO;AACnB,SACE,6CAAC,SAAI,WAAW,yBAAyB,MAAM,IAAI,IAAI,MAAK,UAAS,aAAU,UAC5E,gBAAM,MACT;AAEJ;;;AHmCQ,IAAAC,sBAAA;AA5CD,SAAS,WACd,EAAE,WAAW,WAAW,qBAAqB,gBAAgB,MAAM,MAAM,IAAI,OAAO,UAAU,GAW1E;AACpB,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,KAAK;AACtD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA2B,IAAI;AACzD,QAAM,cAAU,4BAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AACpD,QAAM,MAAM,WAAW,MAAM,EAAE;AAC/B,QAAM,YAAY,aAAa;AAE/B,QAAM,UAAU,KAAK;AACrB,MAAI,CAAC,MAAM,CAAC,WAAW,CAAC,UAAW,QAAO;AAG1C,QAAM,UAAU,YAAY,CAAC,CAAC,UAAU,QAAQ,UAAU,WAAW,IAAI;AAEzE,QAAM,UAAU,YAA2B;AACzC,eAAW,IAAI;AACf,QAAI;AACF,YAAM,UAAU,MAAM,IAAI,WAAW,EAAE,qBAAqB,gBAAgB,KAAK,CAAC;AAClF,UAAI,QAAQ,SAAS,UAAU;AAC7B,iBAAS,EAAE,MAAM,SAAS,MAAM,GAAG,WAAW,CAAC;AAC/C;AAAA,MACF;AACA,eAAS,cAAc,QAAQ,QAAQ,aAAa,UAAU,YAAY,QAAQ,CAAC,GAAG,EAAE,CAAC;AACzF,UAAI,CAAC,UAAW,iBAAgB,WAAW,QAAQ,MAAM,CAAC;AAAA,IAC5D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE,8CAAC,SAAI,WAAU,aACZ;AAAA,YACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,gBAAc,WAAW;AAAA,QACzB,cAAY,GAAG,MAAM,SAAS,KAAK,UAAU,GAAG,SAAS,GAAG,SAAS;AAAA,QACrE,UAAU,WAAW;AAAA,QACrB;AAAA,QAEC;AAAA,oBAAU,6CAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO,oBAAC,IAAU;AAAA,UACxE,MAAM,QAAQ,6CAAC,UAAK,WAAU,gBAAgB,gBAAM,OAAM,IAAU;AAAA,UACrE,6CAAC,UAAM,qBAAU;AAAA;AAAA;AAAA,IACnB,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,cAAY,YAAY,GAAG,SAAS,KAAK,UAAU,GAAG,SAAS,GAAG,SAAS,KAAK;AAAA,QAChF,UAAU,WAAW;AAAA,QACrB;AAAA,QAEC,oBAAU,GAAG,SAAS,GAAG;AAAA;AAAA,IAC5B;AAAA,IAEF,6CAAC,SAAM,OAAc,WAAW,SAAS;AAAA,KAC3C;AAEJ;AAEO,SAAS,gBACd,EAAE,IAAI,MAAM,GAAG,GACK;AACpB,QAAM,YAAY,GAAG,mBAAmB,gBAAgB,IAAI,KAAK,cAAc,IAAI;AACnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,QAAQ;AAAA,MACtB,qBAAqB,GAAG;AAAA,MACxB,gBAAgB,GAAG;AAAA,MACnB,MAAM,GAAG;AAAA,MACT;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;;;AIzEI,IAAAC;AAAA;AAAA;AAAA,EAAA;AAAA;AAnBG,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKuB;AACrB,MAAI,aAAa,UAAa,cAAc,OAAW,QAAO;AAC9D,QAAMC,iBACJ,cAAc,cAAe,IAAI,iBAAiB,cAAgB,IAAI,eAAe;AACvF,QAAM,QACJ,IAAI,YAAY,UAAU,SAASA,cAAa,KAAK,OAAO,QAAQ,SAAS,OAAO,KAAKA,cAAa;AACxG,SAGE,+CAAC,UAAK,WAAU,aAAY,MAAK,OAAM,cAAY,OACjD;AAAA,kDAAC,UAAK,WAAU,kBAAiB,eAAY,QAAQ,oBAAS;AAAA,IAC9D,8CAAC,UAAK,WAAU,mBAAkB,eAAY,QAAQ,wBAAc,cAAc,WAAM,UAAI;AAAA,KAC9F;AAEJ;;;AC5BA,IAAAC,iBAAyB;AAad,IAAAC,uBAAA;AAXJ,SAASC,UAAS,MAAuB;AAC9C,UAAQ,QAAQ,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,YAAY,KAAK;AAC1D;AAKO,SAASC,OAAM,EAAE,KAAK,MAAM,KAAK,GAAwE;AAC9G,QAAM,MAAM,SAAS,SAAS,sBAAsB;AACpD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,MAAI,OAAO,CAAC,QAAQ;AAClB,WAAO,8CAAC,SAAI,WAAW,KAAK,KAAK,KAAK,KAAI,IAAG,eAAY,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAAA,EAClG;AACA,SAAO,8CAAC,UAAK,WAAW,GAAG,GAAG,uBAAuB,eAAY,QAAQ,UAAAD,UAAS,IAAI,GAAE;AAC1F;;;AChBA,IAAAE,iBAAuD;AAkEnD,IAAAC,uBAAA;AArDJ,IAAM,aAA2H;AAAA,EAC/H,KAAK,EAAE,SAAS,aAAa,aAAa,KAAK,WAAW,cAAc,GAAG,kHAAkH;AAAA,EAC7L,MAAM,EAAE,SAAS,aAAa,aAAa,GAAG,GAAG,wFAAwF;AAAA,EACzI,UAAU,EAAE,SAAS,aAAa,aAAa,GAAG,GAAG,0EAA0E;AACjI;AAEO,SAAS,UAAU,EAAE,KAAK,SAAS,IAAI,OAAO,GAM9B;AACrB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA2B,IAAI;AACzD,QAAM,cAAU,4BAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AACpD,QAAM,MAAM,YAAY;AAExB,MAAI,CAAC,WAAW,CAAC,QAAQ,QAAS,QAAO;AAEzC,QAAM,MAAM,OAAO,GAAG;AACtB,QAAM,SAAS,QAAQ,SAAS,GAAG;AAGnC,QAAM,SAAS,IAAI,SAAS,UACxB,EAAE,KAAK,GAAG,eAAe,OAAO,GAAG,gBAAgB,IACnD,EAAE,KAAK,GAAG,UAAU,OAAO,GAAG,WAAW;AAE7C,QAAM,UAAU,CAAC,MAA2C;AAC1D,MAAE,gBAAgB;AAClB,QAAI,IAAI,SAAS,WAAW,CAAC,QAAQ,SAAS,GAAG,GAAG;AAClD,UAAI,QAAQ,SAAS,EAAE,SAAS,IAAI,SAAS,qBAAqB,OAAO,CAAC,MAAM,SAAS;AACvF,aAAK,IAAI,EAAE,MAAM,WAAW,YAAY,SAAS,UAAU,OAAO,IAAI,OAAO,GAAG,qBAAqB,IAAI,oBAAoB,CAAC;AAAA,MAChI;AACA;AAAA,IACF;AACA,UAAM,SAAS,QAAQ,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;AAIhD,SAAK,WAAW,WAAW,WAAW,eAAe,IAAI,SAAS,WAAW,IAAI,wBAAwB,SAAY;AACnH,WAAK,IAAI;AAAA,QACP,MAAM,WAAW,UAAU,YAAY;AAAA,QACvC,YAAY,IAAI,SAAS,UAAU,UAAU;AAAA,QAC7C,UAAU,IAAI,SAAS,UAAU,OAAO,IAAI,OAAO,IAAI,IAAI;AAAA,QAC3D,qBAAqB,IAAI;AAAA,MAC3B,CAAC;AAAA,IACH,WAAW,WAAW,gBAAgB;AACpC,eAAS,EAAE,MAAM,SAAS,MAAM,GAAG,iBAAiB,CAAC;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,QAAQ,WAAW,GAAG,OAAO;AACnC,SACE,+CAAC,SAAI,WAAU,iBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,WAAS,UAAU;AAAA,QACnB,aAAW,GAAG;AAAA,QACd,gBAAc;AAAA,QACd,cAAY,SAAS,OAAO,QAAQ,OAAO;AAAA,QAC3C;AAAA,QAEA,wDAAC,SAAI,SAAS,MAAM,SAAS,eAAY,QACvC;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,MAAM;AAAA,YACjB,GAAG,MAAM;AAAA,YACT,MAAM,SAAS,iBAAiB;AAAA,YAChC,QAAQ,SAAS,SAAS;AAAA,YAC1B,aAAa,MAAM;AAAA,YACnB,gBAAe;AAAA,YACf,eAAc;AAAA;AAAA,QAChB,GACF;AAAA;AAAA,IACF;AAAA,IACA,8CAAC,SAAM,OAAc,WAAW,SAAS;AAAA,KAC3C;AAEJ;;;AC3FA,IAAAC,iBAAsC;AA+ClC,IAAAC,uBAAA;AAhCG,SAAS,mBAAmB,EAAE,WAAW,SAAS,GAAG,GAIrC;AACrB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA2B,IAAI;AACzD,QAAM,cAAU,4BAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AACpD,QAAM,MAAM,YAAY;AAExB,MAAI,CAAC,WAAW,CAAC,QAAQ,QAAS,QAAO;AAEzC,QAAM,OAAO,cAAc,UAAU,kBAAkB,QAAW,UAAU,QAAQ,MAAS;AAC7F,QAAM,QAAQ,OAAO,GAAG,GAAG,iBAAiB,KAAK,IAAI,KAAK,GAAG;AAE7D,QAAM,UAAU,MAAY;AAC1B,UAAM,MAAM,EAAE,GAAG,WAAW,MAAM,aAAsB,aAAa,KAAK;AAC1E,UAAM,MAAM,OAAO,GAAG;AACtB,QAAI,CAAC,QAAQ,SAAS,GAAG,GAAG;AAC1B,YAAM,SAAS,QAAQ,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;AAChD,UAAI,WAAW,gBAAgB;AAC7B,iBAAS,EAAE,MAAM,SAAS,MAAM,GAAG,iBAAiB,CAAC;AACrD;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,IAAI,wBAAwB,QAAW;AAC/D,aAAK,IAAI,EAAE,MAAM,WAAW,YAAY,UAAU,UAAU,IAAI,qBAAqB,qBAAqB,IAAI,oBAAoB,CAAC;AAAA,MACrI;AAAA,IACF;AACA,YAAQ,aAAa,MAAM;AAAA,EAC7B;AAEA,SACE,+CAAC,SAAI,WAAU,iBACb;AAAA,kDAAC,YAAO,MAAK,UAAS,WAAU,aAAY,cAAY,OAAO,OAAO,OAAO,SAC3E,wDAAC,SAAI,SAAQ,aAAY,eAAY,QACnC,wDAAC,UAAK,GAAE,4CAA2C,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,GACtJ,GACF;AAAA,IACA,8CAAC,SAAM,OAAc,WAAW,SAAS;AAAA,KAC3C;AAEJ;;;ACzCI,IAAAC,uBAAA;AAHJ,SAAS,YAAY,EAAE,GAAG,GAA0C;AAClE,MAAI,CAAC,GAAG,KAAM,QAAO;AACrB,SACE,+CAAC,SAAI,WAAU,kBACb;AAAA,kDAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO;AAAA,IACnD,8CAAC,OAAE,WAAU,gBAAgB,aAAG,MAAK;AAAA,KACvC;AAEJ;AAMA,SAAS,YAAY,EAAE,GAAG,GAA0C;AAClE,MAAI,GAAG,gBAAgB,GAAG,cAAc;AACtC,WACE,gFACE;AAAA,oDAACC,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,cAAc;AAAA,MAC7D,8CAAC,UAAK,WAAU,gBAAgB,aAAG,cAAa;AAAA,MAChD,8CAAC,UAAK,WAAU,cAAa,eAAY,QAAO,gBAAE;AAAA,MAClD,8CAAC,UAAK,WAAU,gBAAgB,aAAG,cAAa;AAAA,MAChD,8CAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,cAAc;AAAA,OAC/D;AAAA,EAEJ;AACA,MAAI,GAAG,QAAS,QAAO,8CAAC,UAAK,WAAU,uBAAuB,aAAG,SAAQ;AACzE,MAAI,GAAG,aAAa;AAClB,WACE,gFACE;AAAA,oDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,kBAAkB,MAAM,GAAG,aAAa;AAAA,MACnE,8CAAC,UAAK,WAAU,gBAAgB,aAAG,aAAY;AAAA,OACjD;AAAA,EAEJ;AACA,SAAO;AACT;AAEA,SAAS,YACP,EAAE,IAAI,IAAI,MAAM,QAAQ,GACX;AACb,QAAM,OAAO,GAAG,UAAU,GAAG,UAAU;AAGvC,QAAM,kBAAkB,GAAG,cAAc,IAAI,iBAAiB,GAAG,eAAe,GAAG,UAAU,IAAI;AACjG,QAAM,UAAU,GAAG,iBAAiB,kBAAkB,GAAG,gBAAgB,QAAQ,IAAI,gBAAgB,IAAI,KAAK;AAC9G,QAAM,gBAAgB,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,GAAG;AAKhD,QAAM,gBAAgB,iBAAiB,CAAC,CAAC,GAAG;AAC5C,QAAM,UAAU,CAAC,CAAC,WAAW,GAAG;AAChC,QAAM,aAAa,iBAAiB,CAAC,CAAC,GAAG,eAAe,QAAQ,CAAC,CAAC,WAAW;AAI7E,QAAM,iBACJ,gFACG;AAAA,WACC,+CAAC,UAAK,WAAU,gBAAe;AAAA,oDAAC,UAAK,WAAU,oBAAmB,eAAY,QAAO;AAAA,MAAG,IAAI,aAAa;AAAA,OAAO,IAC9G;AAAA,IACH,UAAU,8CAAC,UAAK,WAAU,gBAAgB,mBAAQ,IAAU;AAAA,IAC5D,WAAW,KACV,8CAAC,aAAU,IAAQ,SAAkB,KAAK,EAAE,MAAM,SAAS,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,qBAAqB,IAChH;AAAA,KACN;AAEF,SACE,+CAAC,SAAI,WAAU,iBACZ;AAAA,iBACC,gBACE,+CAAC,SAAI,WAAU,gBACX;AAAA,SAAG,eAAe,QAAQ,WAAW,UACrC,+CAAC,SAAI,WAAU,gBACb;AAAA,sDAAC,UAAK,WAAU,qBACb,aAAG,cACF,gFACE;AAAA,wDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,kBAAkB,MAAM,GAAG,aAAa;AAAA,UACnE,8CAAC,UAAK,WAAU,gBAAgB,aAAG,aAAY;AAAA,WACjD,IACE,MACN;AAAA,QACA,8CAAC,UAAK,WAAU,sBAAsB,0BAAe;AAAA,SACvD,IACE;AAAA,MACJ,8CAAC,SAAI,WAAU,wBACb,wDAAC,eAAY,IAAQ,GACvB;AAAA,OACF,IAEA,+CAAC,SAAI,WAAU,kBACb;AAAA,oDAAC,UAAK,WAAU,uBAAsB,wDAAC,eAAY,IAAQ,GAAE;AAAA,MAC7D,8CAAC,UAAK,WAAU,wBAAwB,0BAAe;AAAA,OACzD,IAEA;AAAA,IACJ,+CAAC,SAAI,WAAU,kBACZ;AAAA,SAAG,SAAS,8CAAC,UAAK,WAAU,kBAAkB,aAAG,QAAO,IAAU;AAAA,MACnE,+CAAC,SAAI,WAAU,oBACZ;AAAA,WAAG,YAAY,8CAAC,UAAK,WAAU,eAAe,aAAG,WAAU,IAAU;AAAA,QACrE,GAAG,OACF,+CAAC,UAAK,WAAU,gBACd;AAAA,wDAAC,OAAG,aAAG,MAAK;AAAA,UACZ,8CAAC,qBAAkB,UAAU,GAAG,cAAc,SAAS,GAAG,MAAM,WAAW,GAAG,mBAAmB,IAAQ;AAAA,UACxG,GAAG,YAAY,8CAAC,UAAK,WAAU,gBAAgB,aAAG,WAAU,IAAU;AAAA,WACzE,IACE;AAAA,QACH,GAAG,QAAQ,WAAW,MAAM,GAAG,eAC9B;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,WAAW,EAAE,SAAS,GAAG,SAAS,qBAAqB,GAAG,qBAAqB,gBAAgB,GAAG,gBAAgB,MAAM,GAAG,MAAM,aAAa,GAAG,YAAY;AAAA;AAAA,QAC/J,IACE;AAAA,QACJ,8CAAC,mBAAgB,IAAQ,MAAY,IAAQ;AAAA,SAC/C;AAAA,OACF;AAAA,IACC,GAAG,gBACF,8CAAC,UAAK,WAAU,iBAAiB,cAAI,oBAAoB,sCAAkC,IACzF;AAAA,IACJ,8CAAC,eAAY,IAAQ;AAAA,IACpB,GAAG,aAAa,8CAAC,OAAE,WAAU,gBAAgB,aAAG,YAAW,IAAO;AAAA,KACrE;AAEJ;AAEO,SAAS,mBACd,EAAE,UAAU,IAAI,MAAM,QAAQ,GAEV;AACpB,MAAI,CAAC,YAAY,SAAS,WAAW,EAAG,QAAO;AAC/C,SACE,8CAAC,SAAI,WAAU,kBACZ,mBAAS,IAAI,CAAC,OAAO,8CAAC,eAAwB,IAAQ,IAAQ,MAAY,WAAnC,GAAG,EAAkD,CAAE,GACjG;AAEJ;;;ACrJA,IAAAC,iBAAsC;AA+DlC,IAAAC,uBAAA;AApDG,SAAS,mBACd,EAAE,MAAM,MAAM,GAAG,GACG;AACpB,QAAM,MAAM,WAAW,MAAM,EAAE;AAC/B,QAAM,YAAY,aAAa;AAC/B,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAyC,CAAC,CAAC;AACnF,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA2B,IAAI;AACzD,QAAM,cAAU,4BAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AAEpD,MAAI,CAAC,MAAM,CAAC,KAAK,eAAe,KAAK,SAAS,EAAG,QAAO;AACxD,QAAM,UAAU,YAAY,UAAU,UAAU;AAChD,QAAM,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,QAAQ,IAAI,WAAW,CAAC;AAE3D,QAAM,UAAU,YAA2B;AACzC,eAAW,IAAI;AACf,UAAM,QAAqB,EAAE,WAAW,KAAK,QAAQ,OAAO,GAAG,YAAY,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM;AAC7G,UAAM,QAA8B,CAAC;AACrC,QAAI;AACF,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,MAAM,KAAK,CAAC;AAClB,cAAM,OAAO,WAAW,MAAM,IAAI,wBAAwB,KAAK,KAAK,cAAc,GAAG;AAAA,UACnF,qBAAqB,IAAI,uBAAuB;AAAA,UAChD,gBAAgB,IAAI;AAAA,UACpB,MAAM,IAAI;AAAA,QACZ,CAAC,CAAC;AACF,YAAI,SAAS,WAAW,SAAS,eAAe;AAC9C,gBAAM;AACN,cAAI,SAAS,cAAe,OAAM,aAAa;AAC/C,gBAAM,IAAI,WAAW,IAAI;AACzB;AAAA,QACF;AACA,cAAM,SAAS,KAAK,CAAC,IAAI,cAAc,IAAI,YAAY,CAAC;AACxD,YAAI,SAAS,OAAQ;AACrB,YAAI,SAAS,aAAc,OAAM,QAAQ;AACzC,mBAAW,QAAQ,KAAK,MAAM,IAAI,CAAC,EAAG,OAAM,SAAS,KAAK,CAAC,KAAK,cAAc,KAAK,YAAY,CAAC;AAChG;AAAA,MACF;AAAA,IACF,UAAE;AACA,UAAI,CAAC,UAAW,iBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,MAAM,EAAE;AAC3D,eAAS,YAAY,OAAO,EAAE,CAAC;AAC/B,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,QAAQ,UACV,GAAG,kBACH,KAAK,WAAW,IACd,GAAG,YACH,KAAK,WAAW,KAAK,SAAS,GAAG,aAAa,KAAK,MAAM,IAAI,GAAG,cAAc,KAAK,MAAM;AAE/F,SACE,+CAAC,SAAI,WAAU,+BACb;AAAA,kDAAC,YAAO,MAAK,UAAS,WAAU,iBAAgB,UAAU,WAAW,KAAK,WAAW,GAAG,SAAmB,iBAAM;AAAA,IACjH,8CAAC,SAAM,OAAc,WAAW,SAAS;AAAA,KAC3C;AAEJ;;;ACpEA,IAAAC,iBAA0C;AAWnC,IAAM,yBAAqB,8BAAuC,IAAI;AAEtE,SAAS,iBAA0C;AACxD,aAAO,2BAAW,kBAAkB;AACtC;;;ACUU,IAAAC,uBAAA;AAXV,SAAS,YACP,EAAE,KAAK,kBAAkB,IAAI,MAAM,QAAQ,GAC9B;AACb,QAAM,kBAAkB,CAAC,IAAI,gBAAgB,IAAI,cAAc,IAAI,iBAAiB,GAAG,eAAe,IAAI,UAAU,IAAI;AACxH,QAAM,UAAU,IAAI,iBAAiB,kBAAkB,GAAG,gBAAgB,QAAQ,IAAI,gBAAgB,IAAI,KAAK;AAC/G,QAAM,YAAY,mBAAmB,wBAAwB,KAAK,KAAK,cAAc,IAAI;AACzF,QAAM,UAAU,CAAC,CAAC,WAAW,IAAI,cAAc,CAAC,CAAC;AACjD,SACE,+CAAC,QAAG,WAAU,kBACX;AAAA,QAAI,eAAe,WAAW,UAC7B,+CAAC,SAAI,WAAU,uBACb;AAAA,oDAAC,UAAK,WAAU,gBAAgB,cAAI,eAAe,IAAG;AAAA,MACtD,+CAAC,UAAK,WAAU,sBACb;AAAA,kBAAU,8CAAC,UAAK,WAAU,gBAAgB,mBAAQ,IAAU;AAAA,QAC5D,WAAW,KAAK,8CAAC,aAAU,IAAQ,SAAkB,KAAK,EAAE,MAAM,SAAS,SAAS,IAAI,QAAQ,GAAG,QAAQ,IAAI,uBAAuB,QAAW,IAAK;AAAA,SACzJ;AAAA,OACF,IACE;AAAA,IACJ,+CAAC,SAAI,WAAU,wBACb;AAAA,oDAACC,QAAA,EAAM,MAAK,QAAO,KAAK,IAAI,WAAW,MAAM,IAAI,cAAc;AAAA,MAC/D,8CAAC,UAAK,WAAU,gBAAgB,cAAI,cAAa;AAAA,MACjD,8CAAC,UAAK,WAAU,cAAa,eAAY,QAAO,gBAAE;AAAA,MAClD,8CAAC,UAAK,WAAU,gBAAgB,cAAI,cAAa;AAAA,MACjD,8CAACA,QAAA,EAAM,MAAK,QAAO,KAAK,IAAI,WAAW,MAAM,IAAI,cAAc;AAAA,OACjE;AAAA,IACA,+CAAC,SAAI,WAAU,uBACb;AAAA,qDAAC,UAAK,WAAU,uBACd;AAAA,sDAAC,UAAK,WAAU,yBAAyB,cAAI,QAAO;AAAA,QACpD,8CAAC,UAAK,WAAU,sBAAsB,cAAI,WAAU;AAAA,SACtD;AAAA,MACA,8CAAC,UAAK,WAAU,wBAAwB,cAAI,MAAK;AAAA,MACjD;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,IAAI;AAAA,UACf,qBAAqB,IAAI,uBAAuB;AAAA,UAChD,gBAAgB,IAAI;AAAA,UACpB,MAAM,IAAI;AAAA,UACV;AAAA,UACA;AAAA,UACA,WAAW,GAAG,IAAI,YAAY,IAAI,IAAI,YAAY,KAAK,IAAI,SAAS,IAAI,IAAI,IAAI;AAAA;AAAA,MAClF;AAAA,OACF;AAAA,IACC,IAAI,WAAW,8CAAC,OAAE,WAAU,uBAAuB,cAAI,UAAS,IAAO;AAAA,KAC1E;AAEJ;AAEA,SAAS,cAAc,EAAE,IAAI,IAAI,MAAM,QAAQ,GAA6G;AAC1J,QAAM,QAAQ,eAAe;AAC7B,QAAM,EAAE,QAAQ,SAAS,IAAI;AAC7B,SACE,+CAAC,SAAI,WAAU,cACb;AAAA,kDAAC,QAAG,WAAU,mBAAkB,MAAK,QAClC,aAAG,KAAK,IAAI,CAAC,QACZ,8CAAC,eAA0B,KAAU,kBAAkB,GAAG,kBAAkB,IAAQ,MAAY,WAA9E,IAAI,GAA4F,CACnH,GACH;AAAA,IACA,8CAAC,SAAI,WAAU,mBAAmB,aAAG,gBAAe;AAAA,IACnD,GAAG,eAAe,8CAAC,OAAE,WAAU,mBAAmB,aAAG,cAAa,IAAO;AAAA,IACzE,GAAG,mBAAmB,8CAAC,sBAAmB,MAAM,GAAG,MAAM,MAAY,IAAQ,IAAK;AAAA,IAClF,SAAS,WAAW,UAAa,aAAa,SAC7C,8CAAC,YAAO,MAAK,UAAS,WAAU,qBAAoB,SAAS,MAAM,MAAM,YAAY,QAAQ,QAAQ,GAAI,gBAAM,aAAY,IACzH;AAAA,KACN;AAEJ;AAEO,SAAS,cACd,EAAE,OAAO,IAAI,MAAM,QAAQ,GACP;AACpB,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,SACE,8CAAC,SAAI,WAAU,eACZ,gBAAM,IAAI,CAAC,OAAO,8CAAC,iBAA0B,IAAQ,IAAQ,MAAY,WAAnC,GAAG,EAAkD,CAAE,GAChG;AAEJ;;;AC1FA,IAAAC,iBAAoC;;;AC4B9B,IAAAC,uBAAA;AAtBC,SAAS,gBAAgB,IAAkB,SAA2D;AAC3G,MAAI,CAAC,SAAS,WAAW,CAAC,GAAG,WAAY,QAAO;AAChD,SAAO,GAAG,gBAAgB,UAAa,GAAG,eAAe,IAAI,GAAG,cAAc;AAChF;AAEO,SAAS,iBAAiB,EAAE,IAAI,OAAO,SAAS,IAAI,QAAQ,GAEnD;AACd,QAAM,MAAM,YAAY;AACxB,QAAM,UAAU,MAAY;AAC1B,YAAQ,SAAS,EAAE,SAAS,GAAG,SAAS,qBAAqB,GAAG,oBAAoB,CAAC;AACrF,SAAK,IAAI;AAAA,MACP,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,UAAU,OAAO,GAAG,OAAO;AAAA,MAC3B,qBAAqB,GAAG;AAAA,MACxB,SAAS,YAAY,SAAS,qBAAqB;AAAA,IACrD,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,GAAG,gBAAgB,GAAG,eAAe,GAAG,eAAe,OAAO,GAAG,cAAc,GAAG,YAAY,IAAI;AAChH,SACE,+CAAC,YAAO,MAAK,UAAS,WAAW,YAAY,SAAS,eAAe,+BAA+B,cAAY,SAAS,GAAG,WAAW,KAAK,GAAG,SAC7I;AAAA,mDAAC,SAAI,SAAQ,aAAY,eAAY,QAAO,MAAK,QAAO,QAAO,gBAAe,aAAY,KACxF;AAAA,oDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,MAAE,8CAAC,UAAK,GAAE,OAAM,GAAE,KAAI,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,MAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,KAAI,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,MACvJ,8CAAC,UAAK,GAAE,KAAI,GAAE,MAAK,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,MAAE,8CAAC,UAAK,GAAE,OAAM,GAAE,MAAK,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,MAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM;AAAA,OAC5J;AAAA,IACC,YAAY,SAAS,GAAG,WAAW,KAAK,IAAI;AAAA,KAC/C;AAEJ;;;ADNM,IAAAC,uBAAA;AAfN,SAAS,QACP,EAAE,IAAI,KAAK,IAAI,MAAM,WAAW,SAAS,aAAa,GAEzC;AACb,QAAM,YAAY,GAAG,oBAAoB,CAAC,eAAe,6BAA6B,IAAI,KAAK,KAAK,cAAc,IAAI;AAQtH,QAAM,SAAS,CAAC,CAAC,aAAa,IAAI,eAAe,QAAQ,CAAC,CAAC,UAAU,IAAI,WAAW;AACpF,SACE,+CAAC,SAAI,WAAU,eACb;AAAA,kDAAC,UAAK,WAAU,eAAe,cAAI,WAAU;AAAA,IAC7C,8CAAC,qBAAkB,UAAU,IAAI,cAAc,SAAS,IAAI,MAAM,WAAW,IAAI,mBAAmB,IAAQ;AAAA,IAC5G,8CAAC,UAAK,WAAU,iBAAiB,cAAI,MAAK;AAAA,IACzC,WAAW,MAAM,IAAI,eACpB;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,SAAS;AAAA,QACT,WAAW,EAAE,SAAS,GAAG,SAAS,qBAAqB,GAAG,qBAAqB,gBAAgB,IAAI,gBAAgB,MAAM,IAAI,MAAM,aAAa,IAAI,YAAY;AAAA;AAAA,IAClK,IACE;AAAA,IACH,UAAU,KAAK,+CAAC,UAAK,WAAU,mBAAkB;AAAA;AAAA,MAAG,GAAG;AAAA,OAAY,IAAU;AAAA,IAC7E,CAAC,eAAe,8CAAC,cAAW,WAAsB,WAAW,IAAI,MAAM,qBAAqB,GAAG,qBAAqB,gBAAgB,IAAI,gBAAgB,MAAM,IAAI,MAAM,MAAY,IAAQ,IAAK;AAAA,KACpM;AAEJ;AAEA,IAAM,iBAAiB;AAEvB,SAAS,QAAQ,KAAa,QAAwB;AACpD,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB,QAAQ,EAAE,MAAM,WAAW,QAAQ,WAAW,QAAQ,MAAM,CAAC;AACvG;AAEA,SAAS,eACP,EAAE,IAAI,IAAI,MAAM,SAAS,WAAW,YAAY,OAAO,GAE1C;AACb,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAS,KAAK;AACtC,QAAM,kBAAkB,GAAG,cAAc,IAAI,iBAAiB,GAAG,eAAe,GAAG,UAAU,IAAI;AACjG,QAAM,UAAU,GAAG,iBAAiB,kBAAkB,GAAG,gBAAgB,QAAQ,IAAI,gBAAgB,IAAI,KAAK;AAC9G,QAAM,gBAAgB,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,GAAG;AAGhD,QAAM,OAAO,GAAG,QAAQ;AACxB,QAAM,eAAe,MAAM,gBAAgB;AAC3C,QAAM,WAAW,iBAAiB;AAElC,QAAM,SAAS,OAAO,IAAI,KAAK,KAAK,OAAO,EAAE,QAAQ,IAAI;AACzD,QAAM,UAAU,QAAQ,QAAQ,CAAC,aAAa,GAAG,uBAAuB,QAAQ,KAAK,IAAI,IAAI,SAAS;AACtG,QAAM,YAAY,WAAW,OAAO,QAAQ,KAAK,SAAS,IAAI,UAAU,IAAI,IAAI;AAEhF,QAAM,CAAC,EAAE,YAAY,QAAI,yBAAS,CAAC;AACnC,QAAM,aAAa,QAAQ,QAAQ,CAAC,YAAY,CAAC;AACjD,gCAAU,MAAM;AACd,QAAI,CAAC,WAAY;AACjB,UAAM,KAAK,OAAO,WAAW,MAAM,aAAa,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,IAAI,GAAG,SAAS,iBAAiB,KAAK,IAAI,CAAC,IAAI,CAAC;AACpH,WAAO,MAAM,OAAO,aAAa,EAAE;AAAA,EACrC,GAAG,CAAC,YAAY,MAAM,CAAC;AAGvB,QAAM,UAAU,CAAC,CAAC,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,GAAG;AAIxE,QAAM,UAAU,WAAW,CAAC,UAAU,CAAC,aAAa,UAAU;AAE9D,QAAM,aAAa,CAAC,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,SAAS,gBAAgB,IAAI,OAAO,IAAI;AAClG,QAAM,aAAa,CAAC,CAAC,GAAG,eAAe,GAAG,UAAU,CAAC,CAAC,WAAW,WAAW,CAAC,CAAC;AAC9E,SACE,+CAAC,SAAI,WAAW,aAAa,kCAAkC,eAC5D;AAAA,KAAC,cACA,gFACG;AAAA,mBACC,+CAAC,SAAI,WAAU,kBACb;AAAA,sDAAC,UAAK,WAAU,uBACb,aAAG,cACF,gFACE;AAAA,wDAACC,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,kBAAkB,MAAM,GAAG,aAAa;AAAA,UACnE,8CAAC,UAAK,WAAU,gBAAgB,aAAG,aAAY;AAAA,WACjD,IACE,MACN;AAAA,QACA,+CAAC,UAAK,WAAU,wBAEb;AAAA,kBAAQ,CAAC,WACR,gFACE;AAAA,2DAAC,UAAK,WAAU,iBAAiB;AAAA,mBAAK;AAAA,cAAU;AAAA,cAAE,KAAK;AAAA,eAAU;AAAA,YAChE,KAAK,cAAc,8CAAC,UAAK,WAAU,eAAe,eAAK,aAAY,IAAU;AAAA,aAChF,IACE,CAAC,QAAQ,GAAG,SACd,+CAAC,UAAK,WAAU,gBAAe;AAAA,0DAAC,UAAK,WAAU,oBAAmB,eAAY,QAAO;AAAA,YAAG,IAAI,aAAa;AAAA,aAAO,IAC9G;AAAA,UACH,UAAU,8CAAC,UAAK,WAAU,gBAAgB,mBAAQ,IAAU;AAAA,UAC5D,WAAW,KACV;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA,KAAK,UAAU,EAAE,MAAM,SAAS,SAAS,GAAG,QAAQ;AAAA,cACpD,QAAQ,SAAS,SAAY,GAAG;AAAA;AAAA,UAClC,IACE;AAAA,WACN;AAAA,SACF,IACE;AAAA,MACF,iBAAiB,GAAG,WAAW,GAAG,SAClC,+CAAC,SAAI,WAAU,eACZ;AAAA,wBACC,+CAAC,SAAI,WAAU,mBACb;AAAA,wDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,cAAc;AAAA,UAC7D,8CAAC,UAAK,WAAU,gBAAgB,aAAG,cAAa;AAAA,UAChD,8CAAC,UAAK,WAAU,cAAa,eAAY,QAAO,gBAAE;AAAA,UAClD,8CAAC,UAAK,WAAU,gBAAgB,aAAG,cAAa;AAAA,UAChD,8CAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,cAAc;AAAA,WAC/D,IACE,GAAG,UAAU,8CAAC,UAAK,WAAU,iBAAiB,aAAG,SAAQ,IAAU;AAAA,QACtE,GAAG,SACF,+CAAC,SAAI,WAAU,sBACb;AAAA,wDAAC,UAAK,WAAU,kBAAkB,aAAG,QAAO;AAAA,UAC3C,GAAG,QAAQ,gBAAgB,8CAAC,UAAK,WAAU,eAAe,cAAI,iBAAiB,eAAc,IAAU;AAAA,WAC1G,IACE;AAAA,SACN,IACE;AAAA,OACN;AAAA,IAED,CAAC,cAAc,CAAC,UACZ,GAAG,aAAa,GAAG,UAAU,SAAS,IAAI,GAAG,YAAY,GAAG,WAAW,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,MACrG,8CAAC,SAAY,WAAU,gBAAgB,kBAA7B,CAAkC,CAC7C,IACD;AAAA,IAEH,WACC,8CAAC,SAAI,WAAU,kBACZ,2BAAiB,cAAc,8CAAC,UAAM,cAAI,SAAS,aAAa,oBAAmB,IAChF,iBAAiB,kBAAkB,8CAAC,UAAM,cAAI,SAAS,WAAW,2BAA0B,IAC5F,iBAAiB,cAAc,8CAAC,UAAM,cAAI,SAAS,YAAY,aAAY,IAC3E,MACN,IAEA,gFACE;AAAA,qDAAC,SAAI,WAAU,gBACZ;AAAA,WAAG,SAAS,IAAI,CAAC,QAAQ,8CAAC,WAAsB,IAAQ,KAAU,IAAQ,MAAY,WAAsB,SAAkB,cAAc,WAArG,IAAI,GAA0G,CAAE;AAAA,QACvJ,OAAO,GAAG,SAAS,IAAI,CAAC,QAAQ,8CAAC,WAAsB,IAAQ,KAAU,IAAQ,MAAY,WAAsB,SAAkB,cAAc,WAArG,IAAI,GAA0G,CAAE,IAAI;AAAA,SACrK;AAAA,MACC,GAAG,SAAS,SAAS,IACpB,+CAAC,YAAO,MAAK,UAAS,WAAU,gBAAe,iBAAe,MAAM,SAAS,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAClG;AAAA,sDAAC,UAAM,iBAAO,IAAI,aAAa,eAAe,GAAG,IAAI,aAAa,YAAY,KAAK,GAAG,SAAS,MAAM,KAAI;AAAA,QACzG,8CAAC,UAAK,WAAW,oBAAoB,OAAO,0BAA0B,EAAE,IAAI,eAAY,QAAO;AAAA,SACjG,IACE;AAAA,MAEH,YAAY,8CAAC,OAAE,WAAU,iBAAiB,cAAI,SAAS,MAAM,SAAS,KAAK,eAAe,SAAS,IAAG,IAAO;AAAA,OAChH;AAAA,IAED,GAAG,aAAc,eAAe,QAAQ,WAAW,KAClD,+CAAC,SAAI,WAAU,gBACZ;AAAA,SAAG,YAAY,8CAAC,UAAM,aAAG,WAAU,IAAU;AAAA,MAC7C,eAAe,QAAQ,WAAW,KAAK,8CAAC,oBAAiB,IAAQ,OAAO,YAAY,SAAkB,IAAQ,SAAQ,QAAO,IAAK;AAAA,OACrI,IACE;AAAA,IACH,GAAG,aAAa,8CAAC,OAAE,WAAU,gBAAgB,aAAG,YAAW,IAAO;AAAA,KACrE;AAEJ;AAEO,SAAS,mBACd,EAAE,OAAO,IAAI,MAAM,SAAS,WAAW,YAAY,OAAO,GAEtC;AACpB,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,SACE,8CAAC,SAAI,WAAU,gBACZ,gBAAM,IAAI,CAAC,OACV,8CAAC,kBAA2B,IAAQ,IAAQ,MAAY,SAAkB,WAAsB,YAAwB,UAAnG,GAAG,EAAgH,CACzI,GACH;AAEJ;;;AEnMA,IAAAC,iBAA4C;;;AC8BrC,IAAM,oBAAoB;AAIjC,IAAM,qBAAqB;AAI3B,IAAM,gBAAgB;AACtB,IAAM,eAAe,CAAC,KAAK,KAAK,GAAG;AAC5B,IAAM,eAAe;AAG5B,SAAS,gBAAgB,OAA2C;AAClE,QAAM,SAAS,oBAAI,IAAgC;AACnD,aAAW,KAAK,MAAO,QAAO,IAAI,EAAE,sBAAsB,OAAO,IAAI,EAAE,mBAAmB,KAAK,KAAK,CAAC;AACrG,MAAI,OAAO,MAAM,CAAC,EAAG;AACrB,aAAW,KAAK,OAAO;AACrB,SAAK,OAAO,IAAI,EAAE,mBAAmB,KAAK,MAAM,OAAO,IAAI,IAAI,KAAK,GAAI,QAAO,EAAE;AAAA,EACnF;AACA,SAAO;AACT;AAQO,SAAS,cAAc,OAA6C;AACzE,MAAI,MAAM,SAAS,kBAAmB,QAAO;AAC7C,MAAI,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,OAAQ,QAAO;AACvE,MAAI,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,WAAW,KAAK,EAAE,SAAS,SAAS,kBAAkB,EAAG,QAAO;AAEjG,QAAM,SAAS,gBAAgB,KAAK;AAGpC,QAAMC,QAAO,MACV,OAAO,CAAC,MAAM,EAAE,wBAAwB,MAAM,EAC9C,OAAO,CAAC,MAAM,MAAO,EAAE,SAAS,SAAS,KAAK,SAAS,SAAS,IAAI,IAAK;AAC5E,QAAM,SAASA,MAAK,SAAS,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,SAAS;AACvE,QAAM,UAAU,WAAW,iBAAiB,OAAO,WAAW,aAAa,SAAS,eAAe;AAEnG,QAAM,QAAQ,CAAC,SAAqC;AAClD,UAAM,aAAa,KAAK,wBAAwB;AAChD,UAAM,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,SAAS;AACpE,UAAM,UAAU,cAAc,IAAI,WAAW,OAAO,UAAU,IAAI,MAAM,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC,CAAC;AACjG,WAAO;AAAA,MACL;AAAA,MACA,aAAa,aAAa,SAAY,KAAK;AAAA,MAC3C,OAAO,KAAK,SAAS,IAAI,CAAC,SAAS;AAAA,QACjC;AAAA,QACA,OAAO,CAAC,UAAU,IAAI,YAAY,IAAI,SAASA,MAAK,YAAY,IAAI,OAAO,IAAI,OAAO;AAAA,MACxF,EAAE;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,SAA2B,CAAC;AAClC,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,gBAAgB,KAAK,WAAW;AACjE,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,aAAa,KAAK,aAAa,kBAAkB,KAAK,kBAAkB,MAAM,CAAC,EAAE;AAC3F,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,UAAM,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL,QAAQA,MAAK;AAAA,IACb;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,OAAO;AAAA,IACrD,YAAY,MAAM,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,OAAO;AAAA,EACzD;AACF;;;ADtFI,IAAAC,uBAAA;AALJ,SAAS,KAAK,EAAE,KAAK,MAAM,IAAI,KAAK,GAAmG;AACrI,QAAM,KAAK,IAAI;AACf,QAAM,YAAY,GAAG,mBAAmB,6BAA6B,IAAI,KAAK,KAAK,KAAK,cAAc,IAAI;AAC1G,QAAM,OAAO,GAAG,GAAG,gBAAgB,EAAE,IAAI,GAAG,gBAAgB,EAAE,KAAK,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,IAAI;AACtG,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,qBAAqB,GAAG;AAAA,MACxB,gBAAgB,KAAK,IAAI;AAAA,MACzB,MAAM,KAAK,IAAI;AAAA,MACf;AAAA,MACA;AAAA,MACA,OAAO,EAAE,OAAO,KAAK,OAAO,WAAW,KAAK;AAAA;AAAA,EAC9C;AAEF;AAAA;AAAA;AAAA,IAGE,+CAAC,UAAK,WAAW,CAAC,iBAAiB,KAAK,IAAI,KAAK,UAAU,KAAK,uBAAuB,KAAK,IAAI,KAAK,UAAU,KAAK,sBAAsB,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GACjK;AAAA,mBAAa,KAAK,eAAe,KAAK,SACrC,+CAAC,UAAK,WAAU,kBACb;AAAA,aAAK,QAAQ,8CAAC,UAAK,WAAU,gBAAe,eAAY,QAAQ,eAAK,OAAM,IAAU;AAAA,QACtF,8CAAC,UAAK,eAAY,QAAQ,eAAK,IAAI,MAAK;AAAA,QACxC,8CAAC,UAAK,WAAU,WAAW,gBAAK;AAAA,SAClC;AAAA,MAEF,8CAAC,qBAAkB,UAAU,KAAK,IAAI,cAAc,SAAS,KAAK,IAAI,MAAM,WAAW,KAAK,IAAI,mBAAmB,IAAQ;AAAA,OAC7H;AAAA;AAEJ;AAEA,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,MAAM,SAAS,OAAO,GAGvC;AACd,QAAM,KAAK,IAAI;AACf,QAAM,QAAQ,gBAAgB,IAAI,OAAO;AACzC,QAAM,kBAAkB,GAAG,cAAc,IAAI,iBAAiB,GAAG,eAAe,GAAG,UAAU,IAAI;AACjG,QAAM,OAAO,GAAG,SACZ,IAAI,aAAa,SACjB,GAAG,iBAAiB,kBAAkB,GAAG,gBAAgB,QAAQ,IAAI,gBAAgB,IAAI,KAAK;AAClG,SACE,+CAAC,SAAI,WAAU,gBAAe,KAAK,QAAQ,UAAU,SAAS,KAAK,QACjE;AAAA,mDAAC,SAAI,WAAU,eACb;AAAA,qDAAC,UAAK,WAAU,iBAAgB;AAAA,sDAACC,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,gBAAgB,IAAI;AAAA,QAAE,8CAAC,UAAK,WAAU,eAAe,aAAG,cAAa;AAAA,SAAO;AAAA,MAC3J,+CAAC,UAAK,WAAU,iBAAgB;AAAA,sDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,GAAG,WAAW,MAAM,GAAG,gBAAgB,IAAI;AAAA,QAAE,8CAAC,UAAK,WAAU,eAAe,aAAG,cAAa;AAAA,SAAO;AAAA,MAC1J,IAAI,cAAc,8CAAC,UAAK,WAAU,gBAAgB,cAAI,aAAY,IAAU;AAAA,OAC/E;AAAA,IACA,8CAAC,UAAK,WAAU,kBAAiB,OAAO,EAAE,qBAAqB,UAAU,IAAI,MAAM,UAAU,OAAO,oBAAoB,GACrH,cAAI,MAAM,IAAI,CAAC,SAAS,8CAAC,QAAwB,KAAU,MAAY,IAAQ,QAA5C,KAAK,IAAI,GAA+C,CAAE,GAChG;AAAA,IACA,+CAAC,UAAK,WAAW,GAAG,SAAS,sCAAsC,iBAChE;AAAA,aAAO,8CAAC,UAAK,WAAU,iBAAiB,gBAAK,IAAU;AAAA,MACvD,UAAU,QAAQ,WAAW,KAC1B,8CAAC,oBAAiB,IAAQ,OAAc,SAAkB,IAAQ,SAAQ,QAAO,IACjF,WAAW,GAAG,cAAc,GAAG,UAAU,KAAK,8CAAC,aAAU,IAAQ,SAAkB,KAAK,EAAE,MAAM,SAAS,SAAS,GAAG,QAAQ,GAAG,IAAK;AAAA,OAC3I;AAAA,KACF;AAEJ;AAEO,SAAS,gBAAgB,EAAE,MAAM,IAAI,MAAM,QAAQ,GAE1C;AACd,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,YAAY;AAC/C,QAAM,SAAS,KAAK,WAAW;AAE/B,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAwB,IAAI;AAChE,QAAM,eAAW,uBAAuB,IAAI;AAC5C,gCAAU,MAAM;AACd,QAAI,eAAe,KAAM,UAAS,SAAS,MAAM;AAAA,EACnD,GAAG,CAAC,UAAU,CAAC;AACf,MAAI,OAAO;AACX,MAAI,QAAQ;AACZ,SACE,+CAAC,SAAI,WAAU,YACb;AAAA,mDAAC,SAAI,WAAU,iBACb;AAAA,oDAAC,UAAK,WAAU,mBAAmB,eAAK,QAAO;AAAA,MAC/C,8CAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO,OAAO,EAAE,qBAAqB,UAAU,KAAK,QAAQ,MAAM,oBAAoB,GAC/H,eAAK,QAAQ,IAAI,CAAC,GAAG,MAAM,8CAAC,UAAuB,WAAU,gBAAgB,eAAvC,GAAG,CAAC,IAAI,CAAC,EAAgC,CAAO,GACzF;AAAA,MACA,8CAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO;AAAA,OACrD;AAAA,IACC,KAAK,OAAO,IAAI,CAAC,OAAO,OAAO;AAC9B,YAAM,OAAO,MAAM,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;AAClD,cAAQ,KAAK;AACb,UAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,aACE,+CAAC,SAAI,WAAU,kBACZ;AAAA,cAAM,cACL,+CAAC,SAAI,WAAU,iBACb;AAAA,wDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,MAAM,kBAAkB,MAAM,MAAM,aAAa;AAAA,UACzE,8CAAC,UAAM,gBAAM,aAAY;AAAA,WAC3B,IACE;AAAA,QACH,KAAK,IAAI,CAAC,QAAQ;AACjB,gBAAM,KAAK;AACX,iBAAO,8CAAC,OAAsB,KAAU,SAAS,KAAK,QAAQ,QAAQ,IAAQ,MAAY,SAAkB,QAAQ,OAAO,aAAa,WAAW,UAAlI,IAAI,KAAK,EAAoI;AAAA,QAChK,CAAC;AAAA,WAVkC,GAAG,MAAM,eAAe,EAAE,IAAI,EAAE,EAWrE;AAAA,IAEJ,CAAC;AAAA,IACA,SAAS,IACR,+CAAC,YAAO,MAAK,UAAS,WAAU,gBAAe,SAAS,MAAM;AAAE,oBAAc,KAAK;AAAG,eAAS,CAAC,MAAM,IAAI,YAAY;AAAA,IAAE,GACtH;AAAA,oDAAC,UAAM,cAAI,WAAW,GAAG,SAAS,KAAK,IAAI,cAAc,MAAM,CAAC,IAAI,QAAQ,KAAK,IAAI,cAAc,MAAM,CAAC,SAAQ;AAAA,MAClH,8CAAC,UAAK,WAAU,qBAAoB,eAAY,QAAO;AAAA,OACzD,IACE;AAAA,IACH,KAAK,YAAY,8CAAC,SAAI,WAAU,gBAAe,wDAAC,UAAM,eAAK,WAAU,GAAO,IAAS;AAAA,IACrF,KAAK,aAAa,8CAAC,OAAE,WAAU,gBAAgB,eAAK,YAAW,IAAO;AAAA,KACzE;AAEJ;;;AEtGM,IAAAC,uBAAA;AAlBN,SAAS,cAAc,IAAoB,IAAuB;AAChE,MAAI,GAAG,cAAc,YAAa,QAAO,IAAI,iBAAiB;AAC9D,MAAI,GAAG,cAAc,UAAW,QAAO,IAAI,eAAe;AAC1D,SAAO;AACT;AAEA,SAAS,iBACP,EAAE,IAAI,IAAI,QAAQ,GACL;AACb,QAAM,OAAO,cAAc,IAAI,EAAE;AACjC,QAAM,QAAQ,OAAO,KAAK,IAAI,KAAK;AACnC,QAAM,OAAO,IAAI,YACb,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,MAAM,GAAG,WAAW,IACzD,gCAAgC,GAAG,WAAW,qBAAqB,GAAG,OAAO,eAAe,GAAG,OAAO,GAAG,KAAK;AAClH,QAAM,UAAU,CAAC,CAAC,WAAW,GAAG;AAEhC,SACE,+CAAC,SAAI,WAAU,eACb;AAAA,mDAAC,SAAI,WAAU,gBACb;AAAA,oDAAC,UAAK,WAAU,kBAAkB,aAAG,QAAO;AAAA,MAC5C,8CAAC,UAAK,WAAU,eAAe,cAAI,iBAAiB,kBAAiB;AAAA,MACpE,WAAW,KACV;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,WAAW;AAAA,YACT,SAAS,GAAG;AAAA,YACZ,qBAAqB,GAAG;AAAA,YACxB,gBAAgB,GAAG;AAAA,YACnB,MAAM,GAAG;AAAA,YACT,aAAa,GAAG;AAAA,UAClB;AAAA;AAAA,MACF,IACE;AAAA,OACN;AAAA,IACC,GAAG,UACF,+CAAC,SAAI,WAAU,mBACb;AAAA,oDAAC,UAAM,aAAG,SAAQ;AAAA,MACjB,GAAG,cAAc,8CAAC,UAAK,WAAU,gBAAgB,aAAG,aAAY,IAAU;AAAA,OAC7E,IACE;AAAA,IACJ,8CAAC,SAAI,WAAU,eAAe,aAAG,WAAU;AAAA,IAC3C,8CAAC,qBAAkB,UAAU,GAAG,SAAS,SAAS,GAAG,SAAS,WAAW,GAAG,WAAW,IAAQ;AAAA,IAE9F,GAAG,aAAa,OACf,8CAAC,SAAI,WAAU,iBACZ,aAAG,qBAAqB,IACrB,IAAI,oBAAoB,uDACxB,IAAI,oBAAoB,qDAC9B,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,GAAG,SAAS;AAAA,QACrB,OAAM;AAAA,QACN,MAAK;AAAA,QACL,cAAY;AAAA,QAEX;AAAA,aAAG,SAAS,UAAU,IAAI,CAAC,MAC1B,+CAAC,OACC;AAAA,0DAAC,UAAK,WAAU,gBAAe,IAAI,IAAI,IAAI,EAAE,GAAG,IAAI,eAAe,GAAG,IAAI,EAAE,GAAG;AAAA,YAC/E,8CAAC,UAAK,WAAU,gBAAe,GAAG,IAAI,GAAG,EAAE,IAAI,GAAG,YAAW,OAAO,YAAE,MAAM,QAAQ,CAAC,GAAE;AAAA,eAFjF,EAAE,KAGV,CACD;AAAA,UACD,8CAAC,UAAK,WAAU,gBAAe,GAAG,GAAG,SAAS,MAAM,MAAK,QAAO;AAAA,UAC/D,GAAG,SAAS,QAAQ,IAAI,CAAC,GAAG,MAC3B,8CAAC,YAAe,WAAU,eAAc,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,OAAhD,CAAqD,CACnE;AAAA,UACA,IAAI,iBACH,gFACE;AAAA,0DAAC,UAAK,WAAU,gBAAe,GAAG,IAAI,GAAG,eAAe,GAAG,YAAW,SACnE,aAAG,eAAe,GAAG,SAAS,OAAO,GACxC;AAAA,YACA,8CAAC,UAAK,WAAU,gBAAe,GAAG,eAAe,GAAG,GAAG,eAAe,GAAG,YAAW,OACjF,aAAG,eAAe,GAAG,SAAS,KAAK,GACtC;AAAA,aACF,IAEA,8CAAC,UAAK,WAAU,gBAAe,GAAG,IAAI,GAAG,eAAe,GACrD,cAAI,iBAAiB,GAAG,eAAe,GAAG,WAAW,IAAI,QAAQ,GAAG,WAAW,KAClF;AAAA;AAAA;AAAA,IAEJ;AAAA,IAGF,+CAAC,SAAI,WAAU,gBACb;AAAA,qDAAC,UAAM;AAAA,YAAI,gBAAgB;AAAA,QAAU;AAAA,QAAC,8CAAC,OAAG,aAAG,SAAQ;AAAA,SAAI;AAAA,MACzD,+CAAC,UAAM;AAAA,YAAI,gBAAgB;AAAA,QAAU;AAAA,QAAC,8CAAC,OAAG,aAAG,SAAQ;AAAA,SAAI;AAAA,OAC3D;AAAA,IACC,GAAG,YACF,8CAAC,SAAI,WAAU,gBACb,wDAAC,UAAM,aAAG,WAAU,GACtB,IACE;AAAA,IACH,GAAG,gBAAgB,IAClB,8CAAC,SAAI,WAAU,gBACZ,cAAI,oBAAoB,GAAG,kBAAkB,GAAG,aAAa,IAAI,GAAG,GAAG,aAAa,iDACvF,IACE;AAAA,IACH,GAAG,cACF,8CAAC,SAAI,WAAU,gBAAgB,cAAI,sBAAsB,qDAAoD,IAC3G;AAAA,IACH,GAAG,aAAa,8CAAC,SAAI,WAAU,gBAAgB,aAAG,YAAW,IAAS;AAAA,KACzE;AAEJ;AAEO,SAAS,qBACd,EAAE,OAAO,IAAI,QAAQ,GACD;AACpB,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,SACE,8CAAC,SAAI,WAAU,gBACZ,gBAAM,IAAI,CAAC,OAAO,8CAAC,oBAA6B,IAAQ,IAAQ,WAAvB,GAAG,EAAsC,CAAE,GACvF;AAEJ;;;ACpHQ,IAAAC,uBAAA;AALD,SAAS,cAAc,EAAE,SAAS,SAAS,UAAU,MAAM,GAAyH;AACzL,MAAI,QAAQ,WAAW,KAAK,CAAC,QAAS,QAAO;AAC7C,SACE,+CAAC,SAAI,WAAU,gBACZ;AAAA,YAAQ,IAAI,CAAC,GAAG,MACf,8CAAC,YAA+B,MAAK,UAAS,WAAU,aAAY,UAAoB,SAAS,MAAM,MAAM,CAAC,GAAI,YAAE,SAAvG,GAAG,EAAE,KAAK,IAAI,CAAC,EAA8F,CAC3H;AAAA,IACA,QAAQ,WAAW,KAAK,UACvB,gFACE;AAAA,oDAAC,UAAK,WAAU,qBAAoB;AAAA,MACpC,8CAAC,UAAK,WAAU,qBAAoB;AAAA,OACtC,IACE;AAAA,KACN;AAEJ;;;ACM0B,IAAAC,uBAAA;AAjB1B,IAAM,aAAa;AAInB,IAAM,YAAY;AAElB,SAAS,UAAU,UAAmD;AACpE,QAAM,IAAI,UAAU,KAAK,QAAQ;AACjC,SAAO,IAAI,EAAE,MAAM,SAAS,MAAM,GAAG,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,SAAS;AACjF;AAEA,SAAS,SAAS,EAAE,MAAM,OAAO,UAAU,GAAuF;AAChI,QAAM,UAAU,KAAK,aAAa,CAAC,GAAG,OAAO,OAAO,EAAE,MAAM,GAAG,CAAC;AAChE,QAAM,MAAM,KAAK,WAAW,UAAU,KAAK,QAAQ,IAAI;AACvD,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,sDAAqD,SAAS,OAC5F;AAAA,mDAAC,UAAK,WAAU,sBACb;AAAA,WAAK,YAAY,8CAAC,UAAK,WAAU,wBAAwB,eAAK,WAAU,IAAU;AAAA,MAClF,KAAK,OAAO,+CAAC,UAAK,WAAU,wBAAuB;AAAA,uDAAC,UAAK,WAAU,WAAW;AAAA;AAAA,UAAU;AAAA,WAAC;AAAA,QAAQ,IAAI;AAAA,SAAK,IAAU;AAAA,MACrH,8CAAC,UAAK,WAAU,0BAAyB,wDAAC,eAAY,GAAE;AAAA,OAC1D;AAAA,IACA,+CAAC,UAAK,WAAU,uBACd;AAAA,oDAAC,UAAK,WAAU,yBAAwB,eAAY,QACjD,iBAAO,SAAS,IACb,OAAO,IAAI,CAAC,KAAK,MACf,8CAAC,UAAyB,WAAU,wBAAuB,OAAO,EAAE,iBAAiB,OAAO,GAAG,IAAI,KAAxF,GAAG,GAAG,IAAI,CAAC,EAAgF,CACvG,IACD,8CAAC,UAAK,WAAU,uBAAsB,wDAAC,iBAAc,MAAM,KAAK,MAAM,GAAE,GAC9E;AAAA,MACA,+CAAC,UAAK,WAAU,uBACd;AAAA,sDAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM;AAAA,QAClD,KAAK,OAAO,8CAAC,UAAK,WAAU,2BAA2B,cAAI,MAAK,IAAU;AAAA,SAC7E;AAAA,OACF;AAAA,KACF;AAEJ;AAOO,SAAS,cAAc,EAAE,MAAM,OAAO,YAAY,QAAQ,iBAAiB,OAAO,GAAyH;AAChN,MAAI,KAAK,aAAa,OAAQ,QAAO,8CAAC,YAAS,MAAY,OAAc,WAAsB;AAC/F,QAAM,YAAY,KAAK,SAAS,SAAS,yBAAyB;AAClE,QAAM,UAAU,KAAK,aAAa,CAAC,GAAG,MAAM,GAAG,UAAU;AACzD,QAAM,WAAW,mBAAmB,SAAS,KAAK,YAAY,KAAK,YAAY;AAC/E,QAAM,YAAY,WAAW,OAAO,KAAK;AACzC,QAAM,UAAU,QAAQ,SAAS,KAAK,OAAO,SAAS;AACtD,SACE,+CAAC,YAAO,MAAK,UAAS,WAAW,kBAAkB,SAAS,IAAI,SAAS,OACvE;AAAA,kDAAC,UAAK,WAAU,uBAAsB,wDAAC,iBAAc,MAAM,KAAK,MAAM,GAAE;AAAA,IACxE,+CAAC,UAAK,WAAU,uBACd;AAAA,oDAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM;AAAA,MAClD,KAAK,WAAW,8CAAC,UAAK,WAAU,2BAA2B,eAAK,UAAS,IAAU;AAAA,MACnF;AAAA;AAAA;AAAA;AAAA,QAIC,+CAAC,UAAK,WAAU,uBACb;AAAA,sBAAY,8CAAC,UAAK,WAAU,wBAAwB,qBAAU,IAAU;AAAA,UACxE,OAAO,SAAS,IACf,8CAAC,UAAK,WAAU,yBACb,iBAAO,IAAI,CAAC,KAAK,MAChB,8CAAC,UAAyB,WAAU,wBAAuB,OAAO,EAAE,iBAAiB,OAAO,GAAG,IAAI,GAAG,eAAY,UAAvG,GAAG,GAAG,IAAI,CAAC,EAAmG,CAC1H,GACH,IACE;AAAA,WACN;AAAA,UACE;AAAA,OACN;AAAA,IACC,WACG,8CAAC,UAAK,WAAU,wBAAwB,oBAAS,IACjD,8CAAC,UAAK,WAAU,0BAAyB,wDAAC,eAAY,GAAE;AAAA,KAC9D;AAEJ;;;AC1DM,IAAAC,uBAAA;AAtBN,IAAM,iBAA0D;AAAA,EAC9D,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AACb;AAOA,SAAS,YAAY,QAAwB;AAC3C,SAAO,OAAO,UAAU,eAAe,KAAK,gBAAgB,MAAM,IAC9D,eAAe,MAAiC,IAChD,eAAe;AACrB;AAEO,SAAS,kBAAkB,EAAE,WAAW,OAAO,UAAU,GAA2I;AACzM,QAAM,SAAS,YAAY,UAAU,MAAM;AAC3C,QAAM,iBAAiB,WAAW,eAAe,OAAO,QAAQ;AAChE,SACE,+CAAC,SAAI,WAAW,aAAa,MAAM,IACjC;AAAA,mDAAC,SAAI,WAAU,kBACb;AAAA,oDAAC,UAAK,WAAU,mBAAmB,oBAAU,OAAM;AAAA,MAClD,UAAU,WAAW,8CAAC,UAAK,WAAU,sBAAsB,oBAAU,UAAS,IAAU;AAAA,OAC3F;AAAA,IACA,8CAAC,SAAI,WAAU,kBACZ,oBAAU,MAAM,IAAI,CAAC,GAAG,MACvB,8CAAC,iBAAsC,MAAM,GAAG,OAAO,MAAM,MAAM,GAAG,CAAC,GAAG,WAAsB,kBAA5E,GAAG,EAAE,KAAK,IAAI,CAAC,EAA6F,CACjI,GACH;AAAA,IACC,UAAU,YAAY,8CAAC,UAAK,WAAU,kBAAkB,oBAAU,WAAU,IAAU;AAAA,KACzF;AAEJ;;;ACrBuB,IAAAC,uBAAA;AAbvB,SAAS,oBAAoB,QAAqC;AAChE,MAAI,WAAW,IAAK,QAAO;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAIA,SAAS,aAAa,EAAE,GAAG,iBAAiB,YAAY,GAIxC;AACd,QAAM,eAAe,8CAACC,QAAA,EAAM,KAAK,mBAAmB,QAAW,MAAM,aAAa,MAAK,QAAO;AAC9F,QAAM,gBAAgB,8CAACA,QAAA,EAAM,KAAK,EAAE,oBAAoB,QAAW,MAAK,QAAO;AAC/E,QAAM,QAAQ,EAAE,aAAa,GAAG,EAAE,SAAS,MAAM,EAAE,QAAQ,KAAK,GAAG,EAAE,QAAQ,MAAM,EAAE,SAAS;AAC9F,SACE,+CAAC,SAAI,WAAW,8BAA8B,oBAAoB,EAAE,MAAM,CAAC,IACxE;AAAA,MAAE,aAAa,eAAe;AAAA,IAC/B,8CAAC,UAAK,WAAU,+BAA+B,iBAAM;AAAA,IACpD,EAAE,aAAa,gBAAgB;AAAA,KAClC;AAEJ;AAEA,IAAM,iBAAiB;AAMvB,SAAS,aAAa,MAA8C;AAClE,SAAO,MAAM,KAAK,EAAE,QAAQ,eAAe,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM;AAAA,IACxE,8CAAC,UAAoB,WAAU,8BAC5B,eAAK,SAAS,CAAC,IACd,8CAAC,gBAAa,GAAG,KAAK,SAAS,CAAC,GAAG,iBAAiB,KAAK,cAAc,aAAa,KAAK,UAAU,IACjG,QAHK,KAAK,CAAC,EAIjB;AAAA,IACA,8CAAC,UAAoB,WAAU,8BAC5B,eAAK,SAAS,CAAC,IACd,8CAAC,gBAAa,GAAG,KAAK,SAAS,CAAC,GAAG,iBAAiB,KAAK,cAAc,aAAa,KAAK,UAAU,IACjG,QAHK,KAAK,CAAC,EAIjB;AAAA,EACF,CAAC;AACH;AAMO,SAAS,YAAY,EAAE,KAAK,GAA2C;AAC5E,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,MAAM,KAAK;AACjB,SACE,gFACE;AAAA,mDAAC,SAAI,WAAU,0CACb;AAAA,qDAAC,UAAK,WAAU,wBAAwB;AAAA,aAAK;AAAA,QAAM;AAAA,QAAI,KAAK;AAAA,SAAY;AAAA,MACxE,+CAAC,SAAI,WAAU,8BACb;AAAA,uDAAC,UAAK,WAAU,6BACd;AAAA,wDAACA,QAAA,EAAM,KAAK,KAAK,gBAAgB,QAAW,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,UAC7E,8CAAC,UAAK,WAAU,6BAA6B,eAAK,UAAS;AAAA,WAC7D;AAAA,QACA,8CAAC,UAAK,WAAU,2BAA0B,eAAC;AAAA,QAC3C,+CAAC,UAAK,WAAU,6DACd;AAAA,wDAAC,UAAK,WAAU,6BAA6B,eAAK,UAAS;AAAA,UAC3D,8CAACA,QAAA,EAAM,KAAK,KAAK,gBAAgB,QAAW,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,WAC/E;AAAA,SACF;AAAA,MACA,+CAAC,SAAI,WAAU,6BACb;AAAA,sDAAC,UAAK,WAAU,gCAAgC,eAAK,cAAa;AAAA,QACjE,KAAK,QAAQ,+CAAC,UAAK,WAAU,8BAA6B;AAAA;AAAA,UAAI,KAAK;AAAA,WAAM,IAAU;AAAA,SACtF;AAAA,OACF;AAAA,IAEA,+CAAC,SAAI,WAAU,2CACb;AAAA,oDAAC,UAAK,WAAU,wBAAwB,eAAK,WAAU;AAAA,MACvD,+CAAC,SAAI,WAAU,8BACb;AAAA,uDAAC,UAAK,WAAU,mCACd;AAAA,wDAACA,QAAA,EAAM,KAAK,KAAK,gBAAgB,QAAW,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,UAC7E,8CAAC,UAAK,WAAU,mCAAmC,eAAK,UAAS;AAAA,WACnE;AAAA,QACA,+CAAC,UAAK,WAAU,mCACd;AAAA,wDAACA,QAAA,EAAM,KAAK,KAAK,gBAAgB,QAAW,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,UAC7E,8CAAC,UAAK,WAAU,mCAAmC,eAAK,UAAS;AAAA,WACnE;AAAA,SACF;AAAA,MACA,8CAAC,SAAI,WAAU,8BACZ,uBAAa,IAAI,GACpB;AAAA,OACF;AAAA,IAEC,OAAO,KAAK,OACX,+CAAC,SAAI,WAAU,sCACZ;AAAA,YACC,gFACE;AAAA,sDAAC,UAAK,WAAU,wBAAwB,cAAI,OAAM;AAAA,QAClD,+CAAC,SAAI,WAAU,sBACb;AAAA,yDAAC,UAAK,WAAU,2BACd;AAAA,0DAAC,UAAK,WAAU,4BAA4B,cAAI,MAAK;AAAA,YACrD,8CAAC,UAAK,WAAU,4BAA4B,cAAI,eAAc;AAAA,aAChE;AAAA,UACA,+CAAC,UAAK,WAAU,2BACd;AAAA,0DAAC,UAAK,WAAU,4BAA4B,cAAI,OAAM;AAAA,YACtD,8CAAC,UAAK,WAAU,4BAA4B,cAAI,YAAW;AAAA,aAC7D;AAAA,UACA,+CAAC,UAAK,WAAU,2BACd;AAAA,0DAAC,UAAK,WAAU,4BAA4B,cAAI,QAAO;AAAA,YACvD,8CAAC,UAAK,WAAU,4BAA4B,cAAI,eAAc;AAAA,aAChE;AAAA,WACF;AAAA,SACF,IACE;AAAA,MACH,KAAK,OAAO,8CAAC,UAAK,WAAU,qBAAqB,eAAK,MAAK,IAAU;AAAA,OACxE,IACE;AAAA,KACN;AAEJ;;;ACxHA,IAAAC,iBAA8C;AA+CtC,IAAAC,uBAAA;AAzCR,IAAM,SAAS;AAMf,SAAS,kBAAkB,aAAqB,OAAe,aAAwC;AACrG,QAAM,eAAe,KAAK,OAAO,cAAc,MAAO,SAAS,GAAI;AACnE,MAAI,gBAAgB,EAAG,QAAO;AAC9B,QAAM,OAAO,KAAK,MAAM,eAAe,KAAM;AAC7C,QAAM,QAAQ,KAAK,MAAO,eAAe,QAAU,IAAI;AACvD,QAAM,UAAU,KAAK,MAAO,eAAe,OAAQ,EAAE;AACrD,QAAM,UAAU,eAAe;AAC/B,QAAM,MAAM,CAAC,MAAc,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,MAAI,OAAO,EAAG,QAAO,CAAC,EAAE,OAAO,IAAI,IAAI,GAAG,MAAM,IAAI,GAAG,EAAE,OAAO,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC;AACvF,QAAM,OAAkB,CAAC,EAAE,OAAO,IAAI,KAAK,GAAG,MAAM,IAAI,GAAG,EAAE,OAAO,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC;AAC7F,MAAI,YAAa,MAAK,KAAK,EAAE,OAAO,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC;AAC7D,SAAO;AACT;AAEO,SAAS,cAAc,EAAE,KAAK,GAA6C;AAChF,QAAM,EAAE,KAAK,IAAI;AAEjB,QAAM,YAAsC,EAAE,GAAG,KAAK,UAAU,GAAG,KAAK,WAAW,GAAG,KAAK,aAAa,GAAG,KAAK,YAAY;AAC5H,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,MAAM,KAAK,IAAI,CAAC;AAInD,QAAM,CAAC,OAAO,QAAI;AAAA,IAChB,MAAM,OAAO,WAAW,eAAe,OAAO,WAAW,kCAAkC,EAAE;AAAA,EAC/F;AACA,QAAM,YAAY,KAAK,cAAc,MAAO,QAAQ;AACpD,gCAAU,MAAM;AACd,QAAI,QAAS;AACb,UAAM,KAAK,OAAO,YAAY,MAAM,SAAS,KAAK,IAAI,CAAC,GAAG,YAAY,MAAO,GAAM;AACnF,WAAO,MAAM,OAAO,cAAc,EAAE;AAAA,EACtC,GAAG,CAAC,SAAS,SAAS,CAAC;AACvB,QAAM,WAAW,kBAAkB,KAAK,aAAa,OAAO,aAAa,CAAC,OAAO;AACjF,SACE,8CAAC,SAAI,WAAU,4CACb,yDAAC,SAAI,WAAU,8BACb;AAAA,kDAAC,UAAK,WAAU,wBAAwB,eAAK,SAAS,eAAc;AAAA,IACnE,WACC,8CAAC,UAAK,WAAU,gCACb,mBAAS,IAAI,CAAC,GAAG,MAChB,+CAAC,2BACE;AAAA,UAAI,IAAI,8CAAC,UAAK,WAAU,gCAA+B,eAAC,IAAU;AAAA,MACnE,+CAAC,UAAK,WAAU,8BACd;AAAA,sDAAC,UAAK,WAAU,gCAAgC,YAAE,OAAM;AAAA,QACxD,8CAAC,UAAK,WAAU,+BAA+B,oBAAU,EAAE,IAAI,GAAE;AAAA,SACnE;AAAA,SALa,EAAE,IAMjB,CACD,GACH,IACE;AAAA,KACN,GACF;AAEJ;;;AChEA,IAAAC,iBAAyB;AASrB,IAAAC,uBAAA;AAJJ,IAAM,QAAQ;AAEd,SAAS,QAAQ,EAAE,MAAM,SAAS,GAA4D;AAC5F,SACE,+CAAC,UAAK,WAAU,kCACd;AAAA,kDAACC,QAAA,EAAM,KAAK,YAAY,QAAW,MAAY,MAAK,QAAO;AAAA,IAC3D,8CAAC,UAAK,WAAU,uCAAuC,gBAAK;AAAA,KAC9D;AAEJ;AAEA,SAAS,WAAW,EAAE,MAAM,YAAY,MAAM,GAA2E;AACvH,MAAI,KAAK,WAAW,EAAG,QAAO,8CAAC,UAAK,WAAU,+BAA+B,sBAAW;AACxF,QAAM,QAAQ,UAAU,SAAY,OAAO,KAAK,MAAM,GAAG,KAAK;AAC9D,SACE,8CAAC,QAAG,WAAU,4BACX,gBAAM,IAAI,CAAC,GAAG,MACb,+CAAC,QAAgC,WAAU,2BACzC;AAAA,kDAAC,UAAK,WAAU,4BAA4B,YAAE,YAAW;AAAA,IACzD,+CAAC,UAAK,WAAU,4BACd;AAAA,oDAAC,UAAK,WAAU,8BAA8B,YAAE,QAAO;AAAA,MACtD,EAAE,aAAa,8CAAC,UAAK,WAAU,4BAA4B,YAAE,YAAW,IAAU;AAAA,MAClF,EAAE,sBAAsB,8CAAC,UAAK,WAAU,8BAA8B,YAAE,qBAAoB,IAAU;AAAA,OACzG;AAAA,OANO,GAAG,EAAE,UAAU,IAAI,CAAC,EAO7B,CACD,GACH;AAEJ;AAEO,SAAS,aAAa,EAAE,MAAM,GAAG,GAA2D;AACjG,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAG9C,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,OAAO,SAAS,KAAK;AAC7F,QAAM,QAAQ,WAAW,SAAY;AACrC,QAAM,WAAW,IAAI,aAAa,CAAC,MAAc,QAAQ,CAAC;AAC1D,QAAM,WAAW,IAAI,YAAY;AAGjC,QAAM,UAAU,KAAK,aACjB,EAAE,MAAM,KAAK,UAAU,OAAO,KAAK,cAAc,MAAM,KAAK,KAAK,IACjE,EAAE,MAAM,KAAK,YAAY,OAAO,KAAK,gBAAgB,MAAM,KAAK,OAAO;AAC3E,QAAM,UAAU,KAAK,aACjB,EAAE,MAAM,KAAK,YAAY,OAAO,KAAK,gBAAgB,MAAM,KAAK,OAAO,IACvE,EAAE,MAAM,KAAK,UAAU,OAAO,KAAK,cAAc,MAAM,KAAK,KAAK;AACrE,SACE,+CAAC,SAAI,WAAU,2CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,8BACb;AAAA,qDAAC,SAAI,WAAU,6BACb;AAAA,sDAAC,WAAQ,MAAM,QAAQ,MAAM,UAAU,QAAQ,OAAO;AAAA,QACtD,8CAAC,cAAW,MAAM,QAAQ,MAAM,YAAY,KAAK,YAAY,OAAc;AAAA,SAC7E;AAAA,MACA,8CAAC,SAAI,WAAU,iCAAgC;AAAA,MAC/C,+CAAC,SAAI,WAAU,6BACb;AAAA,sDAAC,WAAQ,MAAM,QAAQ,MAAM,UAAU,QAAQ,OAAO;AAAA,QACtD,8CAAC,cAAW,MAAM,QAAQ,MAAM,YAAY,KAAK,YAAY,OAAc;AAAA,SAC7E;AAAA,OACF;AAAA,IACC,SAAS,IACR;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,iBAAe;AAAA,QACf,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,QAEnC,qBAAW,WAAW,SAAS,MAAM;AAAA;AAAA,IACxC,IACE;AAAA,KACN;AAEJ;;;AC1EI,IAAAC,uBAAA;AAFG,SAAS,gBAAgB,EAAE,KAAK,GAA+C;AACpF,SACE,+CAAC,SAAI,WAAU,0CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,QAAG,WAAU,4BACX,eAAK,KAAK,OAAO,IAAI,CAAC,OAAO,MAC5B,8CAAC,QAAyB,WAAU,4BAA4B,mBAAvD,GAAG,KAAK,IAAI,CAAC,EAAgD,CACvE,GACH;AAAA,KACF;AAEJ;;;ACTI,IAAAC,uBAAA;AAFG,SAAS,iBAAiB,EAAE,KAAK,GAAgD;AACtF,SACE,+CAAC,SAAI,WAAU,wCACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,UAAK,WAAU,yBACb,eAAK,KAAK,SAAS,IAAI,CAAC,SAAS,MAChC,8CAAC,UAA6B,WAAU,6BAA6B,qBAA1D,GAAG,OAAO,IAAI,CAAC,EAAmD,CAC9E,GACH;AAAA,KACF;AAEJ;;;ACRoB,IAAAC,uBAAA;AAHb,SAAS,kBAAkB,EAAE,MAAM,MAAM,GAA+F;AAC7I,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,mEAAkE,SAAS,MAAM,MAAM,IAAI,GACxH;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,+BACZ,eAAK,KAAK,QAAQ,IAAI,CAAC,OAAO,MAC7B,+CAAC,UAAoC,WAAU,+BAC7C;AAAA,oDAAC,UAAK,WAAU,8BAA8B,gBAAM,UAAS;AAAA,MAC7D,8CAAC,UAAK,WAAU,mCAAmC,gBAAM,UAAS;AAAA,MAClE,8CAAC,UAAK,WAAU,+BAA+B,gBAAM,aAAY;AAAA,MACjE,8CAAC,UAAK,WAAU,+BAA+B,gBAAM,WAAU;AAAA,SAJtD,GAAG,MAAM,QAAQ,IAAI,CAAC,EAKjC,CACD,GACH;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;AChBgC,IAAAC,uBAAA;AADhC,SAAS,aAAa,EAAE,KAAK,GAAyC;AACpE,MAAI,KAAK,WAAW,EAAG,QAAO,8CAAC,UAAK,WAAU,gCAA+B,kBAAI;AACjF,SACE,8CAAC,QAAG,WAAU,8BACX,eAAK,IAAI,CAAC,GAAG,MACZ,+CAAC,QAAgC,WAAU,6BACzC;AAAA,kDAAC,UAAK,WAAU,8BAA8B,YAAE,YAAW;AAAA,IAC3D,8CAAC,UAAK,WAAU,8BAA8B,YAAE,WAAU;AAAA,IACzD,EAAE,OAAO,8CAAC,UAAK,WAAU,8BAA8B,YAAE,MAAK,IAAU;AAAA,OAHlE,GAAG,EAAE,UAAU,IAAI,CAAC,EAI7B,CACD,GACH;AAEJ;AAEO,SAAS,cAAc,EAAE,KAAK,GAA6C;AAChF,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,SAAI,WAAU,4CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,+BACb;AAAA,qDAAC,SAAI,WAAU,8BACb;AAAA,sDAAC,UAAK,WAAU,mCAAkC,gBAAE;AAAA,QACpD,8CAAC,gBAAa,MAAM,KAAK,IAAI;AAAA,SAC/B;AAAA,MACA,+CAAC,SAAI,WAAU,8BACb;AAAA,sDAAC,UAAK,WAAU,mCAAkC,iBAAG;AAAA,QACrD,8CAAC,gBAAa,MAAM,KAAK,KAAK;AAAA,SAChC;AAAA,OACF;AAAA,KACF;AAEJ;;;AC5BoB,IAAAC,uBAAA;AAHb,SAAS,UAAU,EAAE,KAAK,GAAyC;AACxE,SACE,+CAAC,SAAI,WAAU,wCACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,0BACZ,eAAK,KAAK,MAAM,IAAI,CAAC,MAAM,MAC1B,+CAAC,OAA2B,WAAU,0BAAyB,MAAM,KAAK,KAAK,QAAO,UAAS,KAAI,uBACjG;AAAA,oDAAC,UAAK,WAAU,2BAA2B,eAAK,OAAM;AAAA,MACtD,8CAAC,UAAK,WAAU,6BAA4B,wDAAC,eAAY,GAAE;AAAA,SAFrD,GAAG,KAAK,GAAG,IAAI,CAAC,EAGxB,CACD,GACH;AAAA,KACF;AAEJ;;;ACjBA,IAAAC,iBAAyB;AAqBd,IAAAC,uBAAA;AAlBX,SAASC,UAAS,MAAsB;AACtC,SAAO,KAAK,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,YAAY;AAC7C;AAIA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAIgB;AACd,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,MAAM,8DAA8D,IAAI;AAC9E,MAAI,OAAO,CAAC,QAAQ;AAClB,WAAO,8CAAC,SAAI,WAAW,KAAK,KAAK,KAAK,KAAI,IAAG,eAAY,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAAA,EAClG;AACA,SACE,8CAAC,UAAK,WAAW,GAAG,GAAG,2CAA2C,eAAY,QAC3E,UAAAA,UAAS,IAAI,GAChB;AAEJ;AAIO,SAAS,oBAAoB,EAAE,KAAK,GAAmD;AAC5F,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,UAAU,KAAK,aAAa,KAAK;AACvC,QAAM,UAAU,KAAK,aAAa,KAAK;AAEvC,SACE,+CAAC,SAAI,WAAU,mDACb;AAAA,mDAAC,SAAI,WAAU,8BAGZ;AAAA,WAAK,QAAQ,8CAAC,UAAK,WAAU,+BAA+B,eAAK,OAAM,IAAU;AAAA,MAClF,8CAAC,UAAK,WAAW,0DAA0D,KAAK,OAAO,IACpF,eAAK,aACR;AAAA,OACF;AAAA,IACA,+CAAC,SAAI,WAAU,+BACb;AAAA,qDAAC,SAAI,WAAU,iEACb;AAAA,sDAAC,kBAAe,KAAK,KAAK,cAAc,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,QACzE,8CAAC,UAAK,WAAU,oCAAoC,eAAK,UAAS;AAAA,SACpE;AAAA,MACA,+CAAC,SAAI,WAAU,qCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,0EAA0E,UAAU,QAAQ,MAAM;AAAA,YAE5G,eAAK;AAAA;AAAA,QACR;AAAA,QACA,8CAAC,UAAK,WAAU,oCAAmC,oBAAC;AAAA,QACpD;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,0EAA0E,UAAU,QAAQ,MAAM;AAAA,YAE5G,eAAK;AAAA;AAAA,QACR;AAAA,SACF;AAAA,MACA,+CAAC,SAAI,WAAU,iEACb;AAAA,sDAAC,kBAAe,KAAK,KAAK,cAAc,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,QACzE,8CAAC,UAAK,WAAU,oCAAoC,eAAK,UAAS;AAAA,SACpE;AAAA,OACF;AAAA,IACA,+CAAC,SAAI,WAAU,+BACZ;AAAA,WAAK;AAAA,MACL,KAAK,cAAc,SAAM,KAAK,WAAW,KAAK;AAAA,OACjD;AAAA,KACF;AAEJ;;;AClEoB,IAAAC,uBAAA;AANb,SAAS,mBAAmB,EAAE,MAAM,MAAM,GAGjC;AACd,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,yEAAwE,SAAS,MAAM,MAAM,IAAI,GAC9H;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,QAAG,WAAU,oCACX,eAAK,KAAK,MAAM,IAAI,CAAC,GAAG,MACvB,+CAAC,QAA0B,WAAW,EAAE,eAAe,kEAAkE,+BACvH;AAAA,oDAAC,UAAK,WAAU,oCAAmC;AAAA,MACnD,8CAAC,UAAM,YAAE,MAAK;AAAA,SAFP,GAAG,EAAE,IAAI,IAAI,CAAC,EAGvB,CACD,GACH;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACFoB,IAAAC,uBAAA;AAfpB,SAAS,YAAY,SAAiB,SAAiD;AACrF,QAAM,QAAQ,UAAU;AACxB,MAAI,SAAS,EAAG,QAAO,EAAE,MAAM,OAAO,MAAM,MAAM;AAClD,QAAM,UAAU,KAAK,MAAO,UAAU,QAAS,GAAI,IAAI;AACvD,SAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,GAAG,KAAK,OAAO,MAAM,WAAW,EAAE,IAAI,EAAE,IAAI;AAClF;AAGO,SAAS,mBAAmB,EAAE,MAAM,MAAM,GAGjC;AACd,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,yEAAwE,SAAS,MAAM,MAAM,IAAI,GAC9H;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,oCACZ,eAAK,KAAK,IAAI,CAAC,GAAG,MAAM;AAIvB,YAAM,YAAY,KAAK,aAAa,EAAE,YAAY,EAAE;AACpD,YAAM,aAAa,KAAK,aAAa,EAAE,WAAW,EAAE;AACpD,YAAM,UAAU,KAAK,aAAa,EAAE,UAAU,EAAE;AAChD,YAAM,UAAU,KAAK,aAAa,EAAE,SAAS,EAAE;AAC/C,YAAM,EAAE,MAAM,KAAK,IAAI,YAAY,SAAS,OAAO;AACnD,aACE,+CAAC,SAA4B,WAAU,+BACrC;AAAA,uDAAC,SAAI,WAAU,mCACb;AAAA,wDAAC,UAAK,WAAU,6EAA6E,qBAAU;AAAA,UACvG,8CAAC,UAAK,WAAU,qCAAqC,YAAE,OAAM;AAAA,UAC7D,8CAAC,UAAK,WAAU,6EAA6E,sBAAW;AAAA,WAC1G;AAAA,QACA,+CAAC,SAAI,WAAU,mCACb;AAAA,wDAAC,UAAK,WAAU,wCAAuC,OAAO,EAAE,OAAO,KAAK,GAAG;AAAA,UAC/E,8CAAC,UAAK,WAAU,wCAAuC,OAAO,EAAE,OAAO,KAAK,GAAG;AAAA,WACjF;AAAA,WATQ,GAAG,EAAE,KAAK,IAAI,CAAC,EAUzB;AAAA,IAEJ,CAAC,GACH;AAAA,IACC,KAAK,KAAK,SAAS,IAClB,+CAAC,SAAI,WAAU,iCACb;AAAA,qDAAC,UAAK,WAAU,sCACd;AAAA,sDAAC,OAAE,WAAU,mFAAkF;AAAA,QAC9F,KAAK;AAAA,SACR;AAAA,MACA,+CAAC,UAAK,WAAU,sCACd;AAAA,sDAAC,OAAE,WAAU,mFAAkF;AAAA,QAC9F,KAAK;AAAA,SACR;AAAA,OACF,IACE;AAAA,IACJ,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACvCoB,IAAAC,uBAAA;AAlBpB,SAASC,UAAS,YAA4B;AAC5C,QAAM,QAAQ,WAAW,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AAC3D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,CAAC,EAAG,OAAO,CAAC;AAChC,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC,EAAG,OAAO,CAAC;AAC9C,UAAQ,MAAM,SAAS,IAAI,GAAG,KAAK,GAAG,IAAI,KAAK,OAAO,YAAY;AACpE;AAKO,SAAS,0BAA0B,EAAE,MAAM,MAAM,GAGxC;AACd,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,6EAA4E,SAAS,MAAM,MAAM,IAAI,GAClI;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,mCACb;AAAA,oDAAC,UAAK,WAAU,sCAAqC,eAAY,QAAQ,UAAAA,UAAS,KAAK,UAAU,GAAE;AAAA,MACnG,8CAAC,UAAK,WAAU,oCAAoC,eAAK,YAAW;AAAA,MACpE,8CAAC,UAAK,WAAU,sCAAsC,eAAK,aAAY;AAAA,OACzE;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACnBI,IAAAC,uBAAA;AAHG,SAAS,kBAAkB,EAAE,KAAK,GAAiD;AACxF,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,SAAI,WAAU,iDACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,mCACb,wDAAC,UAAK,WAAU,oCAAoC,eAAK,WAAU,GACrE;AAAA,KACF;AAEJ;;;ACRoB,IAAAC,uBAAA;AAPb,SAAS,gBAAgB,EAAE,MAAM,MAAM,GAG9B;AACd,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,sEAAqE,SAAS,MAAM,MAAM,IAAI,GAC3H;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,iCACb;AAAA,oDAAC,UAAK,WAAU,kCAAkC,eAAK,WAAU;AAAA,MAChE,KAAK,cAAc,8CAAC,UAAK,WAAU,yCAAyC,eAAK,aAAY,IAAU;AAAA,OAC1G;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACToB,IAAAC,uBAAA;AAPb,SAAS,qBAAqB,EAAE,MAAM,MAAM,GAGnC;AACd,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,2EAA0E,SAAS,MAAM,MAAM,IAAI,GAChI;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,sCACb;AAAA,oDAAC,UAAK,WAAU,2CAA2C,eAAK,eAAc;AAAA,MAC9E,8CAAC,UAAK,WAAU,yCAAyC,eAAK,aAAY;AAAA,OAC5E;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACRoB,IAAAC,uBAAA;AAPb,SAAS,kBAAkB,EAAE,MAAM,MAAM,GAGhC;AACd,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,YAAO,MAAK,UAAS,WAAU,wEAAuE,SAAS,MAAM,MAAM,IAAI,GAC7H;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,oCACZ;AAAA,WAAK,cAAc,8CAAC,UAAK,WAAU,mCAAmC,eAAK,aAAY,IAAU;AAAA,MACjG,KAAK,cAAc,8CAAC,UAAK,WAAU,mCAAmC,eAAK,aAAY,IAAU;AAAA,MAClG,8CAAC,UAAK,WAAU,mCAAmC,eAAK,YAAW;AAAA,OACrE;AAAA,IACA,8CAAC,UAAK,WAAU,yBAAyB,eAAK,aAAY;AAAA,KAC5D;AAEJ;;;ACLI,IAAAC,uBAAA;AAZJ,SAAS,YAAY,QAAwB;AAC3C,QAAM,QAAQ,OAAO,YAAY;AACjC,MAAI,UAAU,IAAK,QAAO;AAC1B,MAAI,UAAU,IAAK,QAAO;AAC1B,SAAO;AACT;AAIO,SAAS,gBAAgB,EAAE,KAAK,GAA+C;AACpF,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,SAAI,WAAU,+CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,UAAK,WAAU,qBACb,eAAK,QAAQ,IAAI,CAAC,GAAG,MACpB,8CAAC,UAAuB,WAAW,0BAA0B,YAAY,CAAC,CAAC,IAAK,eAArE,GAAG,CAAC,IAAI,CAAC,EAA8D,CACnF,GACH;AAAA,KACF;AAEJ;;;ACvBA,IAAAC,iBAAiC;;;ACAjC,IAAAC,iBAAoC;AAEpC,IAAM,UAAU;AAIhB,IAAM,wBAAwB;AAE9B,SAAS,qBAAqB,QAAgB,cAAuB,cAA8B;AACjG,MAAI,CAAC,aAAc,QAAO;AAC1B,QAAM,iBAAiB,KAAK,OAAO,KAAK,IAAI,IAAI,gBAAgB,OAAO;AACvE,SAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,cAAc,GAAG,qBAAqB;AAC7E;AAKO,SAAS,aAAa,QAAgB,cAAuB,cAA8B;AAChG,QAAM,CAAC,eAAe,gBAAgB,QAAI;AAAA,IAAS,MACjD,qBAAqB,QAAQ,cAAc,YAAY;AAAA,EACzD;AAEA,gCAAU,MAAM;AACd,qBAAiB,qBAAqB,QAAQ,cAAc,YAAY,CAAC;AAEzE,QAAI,CAAC,aAAc;AAEnB,UAAM,KAAK,OAAO,YAAY,MAAM;AAClC,uBAAiB,qBAAqB,QAAQ,cAAc,YAAY,CAAC;AAAA,IAC3E,GAAG,OAAO;AAEV,WAAO,MAAM,OAAO,cAAc,EAAE;AAAA,EACtC,GAAG,CAAC,QAAQ,cAAc,YAAY,CAAC;AAEvC,SAAO;AACT;;;ADpBW,IAAAC,uBAAA;AAXX,SAASC,UAAS,MAAsB;AACtC,SAAO,KAAK,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,YAAY;AAC7C;AAKA,SAAS,UAAU,EAAE,KAAK,MAAM,KAAK,GAA8E;AACjH,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,MAAM,oDAAoD,IAAI;AACpE,MAAI,OAAO,CAAC,QAAQ;AAClB,WAAO,8CAAC,SAAI,WAAW,KAAK,KAAK,KAAK,KAAI,IAAG,eAAY,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAAA,EAClG;AACA,SACE,8CAAC,UAAK,WAAW,GAAG,GAAG,sCAAsC,eAAY,QACtE,UAAAA,UAAS,IAAI,GAChB;AAEJ;AAMA,SAAS,cAAc,YAAuF;AAC5G,MAAI,CAAC,cAAc,WAAW,WAAW,EAAG,QAAO,EAAE,MAAM,MAAM,MAAM,KAAK;AAE5E,QAAM,QAAQ,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,MAAM;AACpE,QAAM,OAAO,CAAC,SAAyC;AACrD,UAAM,UAAU,MACb,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,EAC7B,MAAM,EACN,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAClC,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,WAAW,EAAE;AAC5C,WAAO,QAAQ,WAAW,IAAI,OAAO,QAAQ,KAAK,IAAI;AAAA,EACxD;AACA,SAAO,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,KAAK,MAAM,EAAE;AAClD;AAIO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAGgB;AACd,QAAM,EAAE,KAAK,IAAI;AAKjB,QAAM,UAAU,GAAG,KAAK,MAAM,IAAI,KAAK,SAAS,IAAI,KAAK,SAAS;AAClE,QAAM,cAAU,uBAAqD,IAAI;AACzE,MAAI,CAAC,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,SAAS;AACvD,YAAQ,UAAU,EAAE,KAAK,SAAS,cAAc,KAAK,IAAI,EAAE;AAAA,EAC7D;AAEA,QAAM,gBAAgB,aAAa,KAAK,QAAQ,KAAK,cAAc,QAAQ,QAAQ,YAAY;AAC/F,QAAM,eAAe,KAAK,YAAY,QAAQ,QAAQ,EAAE;AACxD,QAAM,EAAE,MAAM,aAAa,MAAM,YAAY,IAAI,cAAc,UAAU;AAEzE,SACE,+CAAC,SAAI,WAAU,6CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,+CAAC,SAAI,WAAU,yBACb;AAAA,qDAAC,UAAK,WAAU,0BACd;AAAA,sDAAC,UAAK,WAAU,yBAAwB,eAAY,QAAO;AAAA,QAC1D,KAAK;AAAA,SACR;AAAA,MACA,8CAAC,UAAK,WAAU,4BAA4B,aAAG,aAAa,GAAG,YAAY,IAAG;AAAA,MAC7E,KAAK,cAAc,8CAAC,UAAK,WAAU,iCAAiC,eAAK,aAAY,IAAU;AAAA,OAClG;AAAA,IACA,+CAAC,SAAI,WAAU,0BACb;AAAA,qDAAC,SAAI,WAAU,uDACb;AAAA,sDAAC,aAAU,KAAK,KAAK,cAAc,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,QACpE,8CAAC,UAAK,WAAU,+BAA+B,eAAK,UAAS;AAAA,SAC/D;AAAA,MACA,+CAAC,SAAI,WAAU,gCACb;AAAA,sDAAC,UAAK,WAAU,iCAAiC,eAAK,WAAU;AAAA,QAChE,8CAAC,UAAK,WAAU,+BAA8B,oBAAC;AAAA,QAC/C,8CAAC,UAAK,WAAU,iCAAiC,eAAK,WAAU;AAAA,SAClE;AAAA,MACA,+CAAC,SAAI,WAAU,uDACb;AAAA,sDAAC,aAAU,KAAK,KAAK,cAAc,MAAM,KAAK,UAAU,MAAK,QAAO;AAAA,QACpE,8CAAC,UAAK,WAAU,+BAA+B,eAAK,UAAS;AAAA,SAC/D;AAAA,OACF;AAAA,IACC,eAAe,cACd,+CAAC,SAAI,WAAU,iCACb;AAAA,oDAAC,SAAI,WAAU,6DACZ,wBACC,gFACE;AAAA,sDAAC,UAAK,WAAU,kCAAiC,eAAY,QAAO,oBAEpE;AAAA,QACC;AAAA,SACH,IACE,MACN;AAAA,MACA,8CAAC,SAAI,WAAU,6DACZ,wBACC,gFACG;AAAA;AAAA,QACD,8CAAC,UAAK,WAAU,kCAAiC,eAAY,QAAO,oBAEpE;AAAA,SACF,IACE,MACN;AAAA,OACF,IACE;AAAA,KACN;AAEJ;;;AEvHA,IAAAC,iBAAyB;AAajB,IAAAC,uBAAA;AATR,IAAMC,SAAQ;AAKd,SAAS,UAAU,EAAE,KAAK,GAAiD;AACzE,MAAI,SAAS,QAAQ;AACnB,WACE,8CAAC,UAAK,WAAU,2DAA0D,eAAY,QACpF,wDAAC,UAAK,WAAU,6BAA4B,GAC9C;AAAA,EAEJ;AACA,MAAI,SAAS,YAAY,SAAS,OAAO;AACvC,WACE,8CAAC,UAAK,WAAU,4BAA2B,eAAY,QACrD,wDAAC,UAAK,WAAW,wDAAwD,IAAI,IAAI,GACnF;AAAA,EAEJ;AACA,MAAI,SAAS,OAAO;AAClB,WACE,8CAAC,UAAK,WAAU,4BAA2B,eAAY,QACrD,wDAAC,UAAK,WAAU,kCAAiC,oBAAC,GACpD;AAAA,EAEJ;AACA,SAAO,8CAAC,UAAK,WAAU,4BAA2B,eAAY,QAAO,wDAAC,UAAK,WAAU,4BAA2B,GAAE;AACpH;AAIA,SAAS,WAAW,EAAE,EAAE,GAAsC;AAC5D,MAAI,EAAE,SAAS,OAAO;AACpB,WACE,+CAAC,UAAK,WAAU,4BACb;AAAA,QAAE,UAAU,EAAE;AAAA,MACd,EAAE,YAAY,+CAAC,UAAK,WAAU,4BAA2B;AAAA;AAAA,QAAM,EAAE;AAAA,SAAU,IAAU;AAAA,OACxF;AAAA,EAEJ;AACA,SAAO,8CAAC,UAAK,WAAU,4BAA4B,YAAE,UAAU,EAAE,MAAK;AACxE;AAEA,SAAS,SAAS,EAAE,EAAE,GAAsC;AAC1D,QAAM,MAAM;AAAA,IACV;AAAA,IACA,EAAE,SAAS,SAAS,kCAAkC;AAAA,IACtD,EAAE,SAAS,SAAS,kCAAkC;AAAA,EACxD,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AACX,SACE,+CAAC,SAAI,WAAW,KACd;AAAA,mDAAC,UAAK,WAAU,4BACd;AAAA,oDAAC,cAAW,GAAM;AAAA,MAClB,8CAAC,aAAU,MAAM,EAAE,MAAM;AAAA,OAC3B;AAAA,IACA,8CAAC,UAAK,WAAU,8BAA8B,YAAE,aAAY;AAAA,KAC9D;AAEJ;AAKO,SAAS,iBAAiB,EAAE,MAAM,GAAG,GAAsE;AAChH,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,SAAS,KAAK,KAAK;AACzB,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAE3C,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,QAAM,OAAO,OAAO,SAASA;AAC7B,QAAM,QAAQ,WAAW,SAAS,OAAO,MAAM,GAAGA,MAAK;AAEvD,QAAM,WAAW,IAAI,aAAa,CAAC,MAAc,QAAQ,CAAC;AAC1D,QAAM,WAAW,IAAI,YAAY;AAEjC,SACE,+CAAC,SAAI,WAAU,gDACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,wBACZ,gBAAM,IAAI,CAAC,GAAG,MACb,8CAAC,YAAsD,KAAxC,GAAG,EAAE,MAAM,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC,EAAU,CAC9D,GACH;AAAA,IACC,OAAO,IACN;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,iBAAe;AAAA,QACf,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,QAEnC,qBAAW,WAAW,SAAS,IAAI;AAAA;AAAA,IACtC,IACE;AAAA,KACN;AAEJ;;;ACtGA,IAAAC,iBAAsB;AA0DL,IAAAC,uBAAA;AAlDjB,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,WAAW,SAAS;AAC1B,IAAM,QAAQ;AAEd,SAAS,WACP,QACwE;AACxE,QAAM,YAAY,OAAO,SAAS;AAClC,QAAM,KAAK,CAAC,MAAuB,cAAc,IAAI,IAAK,IAAI,YAAa;AAC3E,QAAM,KAAK,CAAC,MAAsB,WAAW,IAAI;AACjD,QAAM,UAAU,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE;AACpF,QAAM,OAAO,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,QAAQ;AACxE,QAAM,OAAO,IAAI,QAAQ,KAAK,IAAI,CAAC;AAGnC,QAAM,YAAY,OAAO,SAAS,GAAG,SAAS;AAI9C,QAAM,cAAc,cAAc,IAAI,IAAI;AAC1C,SAAO,EAAE,MAAM,MAAM,aAAa,WAAW,GAAG,SAAS,EAAE;AAC7D;AAQO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIuB;AACrB,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,EAAE,MAAM,MAAM,aAAa,UAAU,IAAI,WAAW,MAAM;AAChE,QAAM,aAAS,sBAAM;AACrB,QAAM,YAAY,GAAG,MAAM;AAC3B,QAAM,eAAe,GAAG,MAAM;AAC9B,QAAM,WAAW,aAAa,+BAA+B;AAC7D,QAAM,cAAc,aAAa,+BAA+B;AAEhE,SACE,+CAAC,SAAI,WAAU,yBACZ;AAAA,cAAU,8CAAC,UAAK,WAAU,iCAAiC,mBAAQ,IAAU;AAAA,IAC9E,+CAAC,SAAI,WAAU,8BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS,OAAO,KAAK,IAAI,MAAM;AAAA,UAC/B,qBAAoB;AAAA,UACpB,MAAK;AAAA,UACL,cAAY,WAAW;AAAA,UAEvB;AAAA,2DAAC,UACC;AAAA,4DAAC,cAAS,IAAI,WACZ,wDAAC,UAAK,GAAG,GAAG,GAAG,GAAG,OAAO,OAAO,QAAQ,UAAU,GACpD;AAAA,cACA,8CAAC,cAAS,IAAI,cACZ,wDAAC,UAAK,GAAG,GAAG,GAAG,UAAU,OAAO,OAAO,QAAQ,SAAS,UAAU,GACpE;AAAA,eACF;AAAA,YACA,8CAAC,UAAK,GAAG,MAAM,WAAW,UAAU,UAAU,QAAQ,SAAS,KAAK;AAAA,YACpE,8CAAC,UAAK,GAAG,MAAM,WAAW,aAAa,UAAU,QAAQ,YAAY,KAAK;AAAA,YAC1E,8CAAC,UAAK,IAAI,GAAG,IAAI,UAAU,IAAI,OAAO,IAAI,UAAU,WAAU,8BAA6B;AAAA,YAC3F,8CAAC,UAAK,GAAG,MAAM,WAAU,8BAA6B,cAAa,sBAAqB;AAAA;AAAA;AAAA,MAC1F;AAAA,MAKA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,MAAM,cAAc,WAAW,wBAAwB,KAAK,GAAG,SAAS,KAAK;AAAA,UACtF,eAAY;AAAA;AAAA,MACd;AAAA,OACF;AAAA,KACF;AAEJ;;;AClEoB,IAAAC,uBAAA;AApBpB,SAASC,aAAY,SAAiB,SAAiD;AACrF,QAAM,QAAQ,UAAU;AACxB,MAAI,SAAS,EAAG,QAAO,EAAE,MAAM,OAAO,MAAM,MAAM;AAClD,QAAM,UAAU,KAAK,MAAO,UAAU,QAAS,GAAI,IAAI;AACvD,SAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,GAAG,KAAK,OAAO,MAAM,WAAW,EAAE,IAAI,EAAE,IAAI;AAClF;AAWO,SAAS,cAAc,EAAE,KAAK,GAA6C;AAChF,QAAM,EAAE,KAAK,IAAI;AACjB,SACE,+CAAC,SAAI,WAAU,6CACZ;AAAA,SAAK,QAAQ,8CAAC,UAAK,WAAU,wBAAwB,eAAK,OAAM,IAAU;AAAA,IAC3E,8CAAC,SAAI,WAAU,+BACZ,eAAK,KAAK,IAAI,CAAC,GAAG,MAAM;AACvB,YAAM,YAAY,KAAK,aAAa,EAAE,YAAY,EAAE;AACpD,YAAM,YAAY,KAAK,aAAa,EAAE,WAAW,EAAE;AACnD,YAAM,UAAU,KAAK,aAAa,EAAE,UAAU,EAAE;AAChD,YAAM,UAAU,KAAK,aAAa,EAAE,SAAS,EAAE;AAC/C,YAAM,EAAE,MAAM,KAAK,IAAIA,aAAY,SAAS,OAAO;AACnD,aACE,+CAAC,SAA4B,WAAU,0BACrC;AAAA,uDAAC,SAAI,WAAU,8BACb;AAAA,wDAAC,UAAK,WAAU,mEAAmE,qBAAU;AAAA,UAC7F,8CAAC,UAAK,WAAU,gCAAgC,YAAE,OAAM;AAAA,UACxD,8CAAC,UAAK,WAAU,mEAAmE,qBAAU;AAAA,WAC/F;AAAA,QACA,+CAAC,SAAI,WAAU,yBACb;AAAA,wDAAC,UAAK,WAAU,8BAA6B,OAAO,EAAE,OAAO,KAAK,GAAG;AAAA,UACrE,8CAAC,UAAK,WAAU,8BAA6B,OAAO,EAAE,OAAO,KAAK,GAAG;AAAA,WACvE;AAAA,WATQ,GAAG,EAAE,KAAK,IAAI,CAAC,EAUzB;AAAA,IAEJ,CAAC,GACH;AAAA,IACC,KAAK,SAAS,SAAS,IACtB,8CAAC,gBAAa,QAAQ,KAAK,UAAU,SAAS,KAAK,eAAe,YAAY,KAAK,YAAY,IAC7F,KAAK,gBACP,8CAAC,UAAK,WAAU,8BAA8B,eAAK,eAAc,IAC/D;AAAA,IACH,KAAK,KAAK,SAAS,IAClB,+CAAC,SAAI,WAAU,4BACb;AAAA,qDAAC,UAAK,WAAU,iCACd;AAAA,sDAAC,OAAE,WAAU,yEAAwE;AAAA,QACpF,KAAK;AAAA,SACR;AAAA,MACA,+CAAC,UAAK,WAAU,iCACd;AAAA,sDAAC,OAAE,WAAU,yEAAwE;AAAA,QACpF,KAAK;AAAA,SACR;AAAA,OACF,IACE;AAAA,KACN;AAEJ;;;ACDI,IAAAC,uBAAA;AAnBG,SAAS,iBAAiB,EAAE,WAAW,OAAO,GAAG,GAIxC;AAGd,QAAM,eAAe;AAAA,IACnB,GAAG,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,WAAW;AAAA,IAC3D,GAAG,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,WAAW;AAAA,EAC7D;AAIA,QAAM,eAAe,UAAU,MAAM;AAAA,IACnC,CAAC,MAAiC,EAAE,aAAa;AAAA,EACnD;AACA,QAAM,aAAa,cAAc,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAC5E,SACE,+CAAC,SAAI,WAAU,gBACZ;AAAA,cAAU,WAAW,8CAAC,UAAK,WAAW,UAAU,iBAAiB,sDAAsD,yBAA0B,oBAAU,UAAS,IAAU;AAAA,IAC/K,8CAAC,SAAI,WAAU,sBACZ,uBAAa,IAAI,CAAC,MAAM,MACvB,8CAAC,oBAA+C,MAAY,OAAc,IAAQ,cAA3D,GAAG,KAAK,QAAQ,IAAI,CAAC,EAA8D,CAC3G,GACH;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAiB,EAAE,MAAM,OAAO,IAAI,WAAW,GAKjC;AACrB,UAAQ,KAAK,UAAU;AAAA,IACrB,KAAK;AACH,aAAO,8CAAC,eAAY,MAAY;AAAA,IAClC,KAAK;AACH,aAAO,8CAAC,iBAAc,MAAY;AAAA,IACpC,KAAK;AACH,aAAO,8CAAC,gBAAa,MAAY,IAAQ;AAAA,IAC3C,KAAK;AACH,aAAO,8CAAC,mBAAgB,MAAY;AAAA,IACtC,KAAK;AACH,aAAO,8CAAC,oBAAiB,MAAY;AAAA,IACvC,KAAK;AACH,aAAO,8CAAC,qBAAkB,MAAY,OAAc;AAAA,IACtD,KAAK;AACH,aAAO,8CAAC,iBAAc,MAAY;AAAA,IACpC,KAAK;AACH,aAAO,8CAAC,aAAU,MAAY;AAAA,IAChC,KAAK;AACH,aAAO,8CAAC,uBAAoB,MAAY;AAAA,IAC1C,KAAK;AACH,aAAO,8CAAC,sBAAmB,MAAY,OAAc;AAAA,IACvD,KAAK;AACH,aAAO,8CAAC,sBAAmB,MAAY,OAAc;AAAA,IACvD,KAAK;AACH,aAAO,8CAAC,6BAA0B,MAAY,OAAc;AAAA,IAC9D,KAAK;AACH,aAAO,8CAAC,qBAAkB,MAAY;AAAA,IACxC,KAAK;AACH,aAAO,8CAAC,mBAAgB,MAAY,OAAc;AAAA,IACpD,KAAK;AACH,aAAO,8CAAC,wBAAqB,MAAY,OAAc;AAAA,IACzD,KAAK;AACH,aAAO,8CAAC,qBAAkB,MAAY,OAAc;AAAA,IACtD,KAAK;AACH,aAAO,8CAAC,mBAAgB,MAAY;AAAA,IACtC,KAAK;AACH,aAAO,8CAAC,iBAAc,MAAY,YAAwB;AAAA,IAC5D,KAAK;AACH,aAAO,8CAAC,oBAAiB,MAAY,IAAQ;AAAA,IAC/C,KAAK;AACH,aAAO,8CAAC,iBAAc,MAAY;AAAA,IACpC;AAGE,aAAO;AAAA,EACX;AACF;;;ACtGwE,IAAAC,uBAAA;AAVjE,SAAS,YAAY,EAAE,SAAS,UAAU,OAAO,OAAO,IAAI,MAAM,QAAQ,GAQjE;AACd,MAAI,QAAQ,SAAS,QAAQ;AAC3B,WAAO,8CAAC,SAAI,WAAU,sBAAqB,eAAa,QAAQ,IAAI,wDAAC,SAAI,WAAU,eAAe,kBAAQ,MAAK,GAAM;AAAA,EACvH;AAKA,QAAM,oBAAoB,CAAC,SAAwC;AACjE,UAAM,EAAE,SAAS,KAAK,aAAa,WAAW,KAAK,WAAW,OAAO,KAAK,eAAe,KAAK,SAAS,GAAG,CAAC;AAAA,EAC7G;AACA,QAAM,UAAU,cAAc,QAAQ,UAAU;AAChD,SACE,+CAAC,SAAI,WAAU,qBAAoB,eAAa,QAAQ,IACrD;AAAA,YAAQ,QAAQ,CAAC,QAAQ,qBAAqB,CAAC,QAAQ,mBAAmB,8CAAC,YAAS,MAAM,QAAQ,MAAM,IAAK;AAAA,IAC7G,QAAQ,qBAAqB,CAAC,QAAQ,mBAAmB,8CAAC,qBAAkB,WAAW,QAAQ,mBAAmB,OAAc,WAAW,IAAI,WAAW,IAAK;AAAA,IAC/J,QAAQ,mBAAmB,8CAAC,oBAAiB,WAAW,QAAQ,kBAAkB,OAAO,mBAAmB,IAAQ,IAAK;AAAA,IAC1H,8CAAC,kBAAe,OAAO,QAAQ,OAAO,UAAoB,eAAe,IAAI,UAAU,eAAe,IAAI,UAAU;AAAA,IACpH,8CAAC,sBAAmB,UAAU,QAAQ,UAAU,IAAQ,MAAY,SAAkB;AAAA,IACtF,8CAAC,iBAAc,OAAO,QAAQ,cAAc,CAAC,GAAG,IAAQ,MAAY,SAAkB;AAAA,IACrF,UACG,8CAAC,mBAAgB,MAAM,SAAS,IAAQ,MAAY,SAAkB,IACtE,8CAAC,sBAAmB,OAAO,QAAQ,YAAY,IAAQ,MAAY,SAAkB;AAAA,IACzF,8CAAC,wBAAqB,OAAO,QAAQ,cAAc,IAAQ,SAAkB;AAAA,IAC7E,8CAAC,iBAAc,SAAS,QAAQ,SAAS,SAAS,OAAO,UAAoB,OAAc;AAAA,KAC7F;AAEJ;;;AC9CQ,IAAAC,uBAAA;AALD,SAAS,YAAY,EAAE,OAAO,OAAO,GAA4E;AACtH,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SACE,8CAAC,SAAI,WAAU,cACZ,gBAAM,IAAI,CAAC,GAAG,MACb,8CAAC,YAA8B,MAAK,UAAS,WAAU,aAAY,SAAS,MAAM,OAAO,EAAE,IAAI,GAAI,YAAE,QAAxF,GAAG,EAAE,IAAI,IAAI,CAAC,EAA+E,CAC3G,GACH;AAEJ;;;ACRO,IAAM,gBAAgB;AAQtB,SAAS,iBAAiB,IAAsE,YAAY,eAAwB;AACzI,SAAO,GAAG,eAAe,GAAG,YAAY,GAAG,gBAAgB;AAC7D;;;AhDyEQ,IAAAC,uBAAA;AApER,SAAS,WAAW,UAAkE;AACpF,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,MAAI,CAAC,QAAQ,KAAK,SAAS,YAAa,QAAO;AAC/C,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,SAAO,EAAE,QAAQ,KAAK,IAAI,UAAU,QAAQ,KAAK,SAAS,SAAS,KAAK,KAAK,KAAK,GAAG;AACvF;AAEO,SAAS,YAAY,EAAE,YAAY,IAAI,MAAM,gBAAgB,QAAQ,GAM5D;AACd,QAAM,EAAE,OAAO,KAAK,IAAI;AACxB,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,aAAS,uBAAuB,IAAI;AAI1C,QAAM,gBAAY,uBAAO,IAAI;AAI7B,QAAM,sBAAkB,uBAAsB,IAAI;AAClD,gCAAU,MAAM;AACd,UAAM,SAAS,WAAW,MAAM,QAAQ;AACxC,UAAM,OAAO,QAAQ;AACrB,QAAI,UAAU,OAAO,WAAW,gBAAgB,SAAS;AACvD,sBAAgB,UAAU,OAAO;AAajC,UAAI,OAAO,WAAW,KAAM,QAAO,QAAQ,MAAM,SAAS,MAAM,cAAc,GAAG,KAAK,YAAY,OAAO;AAGzG,gBAAU,UAAU;AACpB,YAAM,cAAc,iBAAiB,OAAO,QAAQ,IAAI,GAAG,eAAe,EAAE,OAAO,QAAQ,CAAC;AAC5F;AAAA,IACF;AAGA,QAAI,CAAC,MAAM,eAAe,OAAO,QAAS,QAAO,QAAQ,MAAM,SAAS;AACxE,QAAI,UAAU,QAAS,QAAO,SAAS,eAAe,EAAE,OAAO,MAAM,CAAC;AAAA,EACxE,GAAG,CAAC,MAAM,UAAU,MAAM,QAAQ,MAAM,WAAW,CAAC;AAKpD,QAAM,iBAAiB,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACnE,QAAM,eAAe,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB;AACrH,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,aAAU;AAAA,MACV,KAAK;AAAA,MACL,UAAU,MAAM;AAAE,YAAI,QAAQ,QAAS,WAAU,UAAU,iBAAiB,QAAQ,OAAO;AAAA,MAAE;AAAA,MAE5F;AAAA,cAAM,SAAS,IAAI,CAAC,MACnB;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS;AAAA,YACT,UAAU,MAAM,eAAe,SAAS,MAAM,KAAK;AAAA,YACnD,OAAO,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,WAAW,EAAE,WAAW,aAAa,EAAE,MAAM,CAAC;AAAA,YACpG,OAAO,CAAC,MAAM,UAAU;AACtB,oBAAM,cAAc,gBAAgB,IAAI;AACxC,mBAAK,KAAK,aAAa,KAAK,YAAY,EAAE,WAAW,KAAK,WAAW,YAAY,IAAI,EAAE,YAAY,CAAC;AAIpG,kBAAI,EAAE,SAAS,eAAe,EAAE,kBAAmB,kBAAiB,MAAM,OAAO,EAAE,kBAAkB,MAAM;AAAA,YAC7G;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,UAdK,EAAE;AAAA,QAeT,CACD;AAAA,QACA,MAAM,eAAe,MAAM,iBAAiB,8CAAC,iBAAc,SAAS,CAAC,GAAG,SAAO,MAAC,OAAO,MAAM;AAAA,QAAC,GAAG,IAAK;AAAA,QACtG,MAAM,SAAS,8CAAC,SAAI,WAAU,eAAe,gBAAM,QAAO,IAAS;AAAA,QACnE,MAAM,QACL,+CAAC,SAAI,WAAU,cAAa,MAAK,SAC/B;AAAA,wDAAC,UAAM,uBAAa,MAAM,QAAQ,MAAM,MAAM,UAAU,GAAG,oBAAmB;AAAA,UAC9E,8CAAC,YAAO,MAAK,UAAS,WAAU,cAAa,SAAS,MAAM,WAAW,MAAM,GAAI,aAAG,OAAM;AAAA,WAC5F,IACE;AAAA,QACH,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,SAAS,MAAM,KAAK,IAAI,8CAAC,eAAY,OAAO,MAAM,UAAU,QAAQ,CAAC,MAAM,KAAK,CAAC,GAAG,IAAK;AAAA,QAC/H,8CAAC,SAAI,KAAK,QAAQ,WAAU,oBAAmB,eAAY,QAAO;AAAA;AAAA;AAAA,EACpE;AAEJ;;;AiDpHA,IAAAC,iBAAiG;AA0D7F,IAAAC,uBAAA;AApCG,IAAM,gBAAY,2BAA4C,SAASC,WAC5E,EAAE,aAAa,WAAW,QAAQ,QAAQ,YAAY,iBAAiB,YAAY,gBAAgB,WAAW,OAAO,OAAO,GAC5H,KACA;AACA,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,kBAAc,uBAA4B,IAAI;AACpD,QAAM,cAAU,uBAA0B,IAAI;AAC9C,QAAM,2BAAuB,uBAAO,KAAK;AACzC,QAAM,SAAS,MAAM;AAAE,QAAI,SAAU;AAAQ,UAAM,IAAI,MAAM,KAAK;AAAG,QAAI,CAAC,EAAG;AAAQ,WAAO,CAAC;AAAG,aAAS,EAAE;AAAA,EAAE;AAC7G,QAAM,YAAY,CAAC,MAA0C;AAC3D,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AAAE,QAAE,eAAe;AAAG,aAAO;AAAA,IAAE;AAAA,EACvE;AAEA,0CAAoB,KAAK,OAAO;AAAA,IAC9B,QAAQ;AACN,YAAM,MAAM,YAAY;AACxB,UAAI,OAAO,CAAC,IAAI,UAAU;AAAE,6BAAqB,UAAU;AAAO,YAAI,MAAM;AAAG;AAAA,MAAO;AACtF,2BAAqB,UAAU;AAC/B,cAAQ,SAAS,MAAM;AAAA,IACzB;AAAA,EACF,IAAI,CAAC,CAAC;AAIN,gCAAU,MAAM;AACd,QAAI,aAAa,YAAY,CAAC,qBAAqB,QAAS;AAC5D,yBAAqB,UAAU;AAC/B,UAAM,MAAM,YAAY;AACxB,QAAI,CAAC,IAAK;AACV,UAAM,SAAU,IAAI,YAAY,EAA4B;AAC5D,UAAM,QAAQ,IAAI,QAAQ,aAAa;AACvC,UAAM,oBAAoB,OAAO,SAAS,MAAc;AACxD,QAAI,CAAC,UAAU,WAAW,IAAI,cAAc,QAAQ,kBAAmB,KAAI,MAAM;AAAA,EACnF,GAAG,CAAC,WAAW,QAAQ,CAAC;AAExB,SACE,+CAAC,SAAI,WAAU,cACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QAAa,WAAU;AAAA,QAAgB,MAAM;AAAA,QAAG;AAAA,QAA0B;AAAA,QAC/E,UAAU,aAAa;AAAA,QACvB,UAAU,CAAC,MAAM;AAAE,mBAAS,EAAE,OAAO,KAAK;AAAG,mBAAS;AAAA,QAAE;AAAA,QACxD;AAAA;AAAA,IACF;AAAA,IACC,YACC,8CAAC,YAAO,KAAK,SAAS,MAAK,UAAS,WAAU,uBAAsB,cAAY,WAAW,UAAoB,SAAS,QAAQ,wDAAC,UAAK,WAAU,mBAAkB,GAAE,IAEpK,8CAAC,YAAO,MAAK,UAAS,WAAU,aAAY,cAAY,WAAW,UAAoB,SAAS,QAAQ,wDAAC,YAAS,GAAE;AAAA,KAExH;AAEJ,CAAC;;;ACxED,IAAAC,iBAAkC;AAkDxB,IAAAC,uBAAA;AA9CH,SAAS,OAAO,EAAE,SAAS,IAAI,YAAY,WAAW,YAAY,UAAU,cAAc,YAAY,GAWtF;AACrB,QAAM,OAA0E;AAAA,IAC9E,EAAE,KAAK,QAAQ,OAAO,GAAG,SAAS,OAAO,GAAG,KAAK,QAAQ,QAAQ;AAAA,IACjE,GAAI,cACA;AAAA,MACE,EAAE,KAAK,YAA0B,OAAO,GAAG,aAAa,OAAO,GAAG,KAAK,MAAM;AAAA,MAC7E,EAAE,KAAK,aAA2B,OAAO,GAAG,cAAc,OAAO,GAAG,KAAK,MAAM;AAAA,MAC/E,EAAE,KAAK,SAAuB,OAAO,GAAG,UAAU,OAAO,GAAG,KAAK,MAAM;AAAA,IACzE,IACA;AAAA,MACE,GAAI,WAAW,CAAC,EAAE,KAAK,SAAuB,OAAO,GAAG,UAAU,OAAO,YAAY,KAAK,QAAQ,SAAS,CAAC,IAAI,CAAC;AAAA,MACjH,GAAI,aAAa,IAAI,CAAC,EAAE,KAAK,aAA2B,OAAO,GAAG,cAAc,OAAO,YAAY,KAAK,QAAQ,WAAW,CAAC,IAAI,CAAC;AAAA,MACjI,GAAI,YAAY,IAAI,CAAC,EAAE,KAAK,QAAsB,OAAO,GAAG,SAAS,OAAO,WAAW,KAAK,QAAQ,QAAQ,CAAC,IAAI,CAAC;AAAA,IACpH;AAAA,IACJ,GAAI,eAAe,CAAC,EAAE,KAAK,SAAuB,OAAO,GAAG,UAAU,OAAO,GAAG,KAAK,MAAM,CAAC,IAAI,CAAC;AAAA,EACnG;AAEA,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,YAAY,QAAQ;AAC1B,gCAAU,MAAM;AACd,UAAM,KAAK,QAAQ,SAAS,cAA2B,WAAW;AAClE,QAAI,CAAC,MAAM,OAAO,GAAG,mBAAmB,WAAY;AACpD,UAAM,SAAS,OAAO,OAAO,eAAe,cAAc,OAAO,WAAW,kCAAkC,EAAE;AAChH,OAAG,eAAe,EAAE,OAAO,WAAW,QAAQ,WAAW,UAAU,SAAS,SAAS,SAAS,CAAC;AAAA,EACjG,GAAG,CAAC,SAAS,CAAC;AAId,MAAI,KAAK,SAAS,EAAG,QAAO;AAE5B,SACE,8CAAC,SAAI,WAAU,aAAY,MAAK,WAAU,KAAK,SAC5C,eAAK,IAAI,CAAC,EAAE,KAAK,OAAO,OAAO,IAAI,MAAM;AACxC,UAAM,SAAS,QAAQ,cAAc;AACrC,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,WAAS,SAAS,KAAK;AAAA,QACvB,WAAU;AAAA,QACV,SAAS,MAAM,QAAQ,aAAa,GAAG;AAAA,QAEtC;AAAA;AAAA,UACA,QAAQ,KAAK,8CAAC,UAAK,WAAU,kBAAkB,iBAAM;AAAA,UACrD,OAAO,CAAC,UAAU,8CAAC,UAAK,WAAU,gBAAe,eAAY,QAAO;AAAA;AAAA;AAAA,MAVhE;AAAA,IAWP;AAAA,EAEJ,CAAC,GACH;AAEJ;;;ACnCc,IAAAC,uBAAA;AAxBP,SAAS,gBAAgB,EAAE,OAAO,SAAS,IAAI,KAAK,GAKpC;AACrB,QAAM,YAAY,aAAa;AAC/B,QAAM,UAAU,MAAM,oBAAoB,CAAC;AAC3C,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,OAAO,QAAQ,WAAW,MAAM,OAAO,KAAK;AAElD,SACE,8CAAC,SAAI,WAAU,YACZ,kBAAQ,IAAI,CAAC,MAAM;AAKlB,UAAM,SAAS,SAAS,EAAE,uBAAuB,CAAC,EAAE;AACpD,UAAM,MAAM,GAAG,MAAM,OAAO,IAAI,EAAE,mBAAmB;AACrD,UAAM,QAAQ,QAAQ,WAAW,GAAG;AACpC,WACE,+CAAC,SAAgC,WAAW,SAAS,mCAAmC,gBACtF;AAAA,oDAAC,SAAI,WAAU,iBACb;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,EAAE,YAAY,0CAA0C;AAAA,UACnE,iBAAe;AAAA,UACf,UAAU,EAAE;AAAA,UACZ,SAAS,MAAM,QAAQ,aAAa,MAAM,SAAS,EAAE,mBAAmB;AAAA,UAExE;AAAA,0DAAC,UAAK,WAAU,oBAAoB,YAAE,YAAY,KAAK,SAAS,WAAM,UAAI;AAAA,YAC1E,8CAAC,UAAK,WAAU,kBAAkB,YAAE,aAAY;AAAA,YAC/C,EAAE,cAAc,8CAAC,UAAK,WAAU,kBAAiB,oBAAC;AAAA,YAClD,EAAE,aAAa,8CAAC,UAAK,WAAU,iBAAiB,aAAG,oBAAmB;AAAA;AAAA;AAAA,MACzE,GACF;AAAA,MACC,UACC,+CAAC,SAAI,WAAU,kBACZ;AAAA,eAAO,SACN;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,MAAM,QAAQ,YAAY,MAAM,SAAS,EAAE,mBAAmB;AAAA,YAEtE,aAAG;AAAA;AAAA,QACN;AAAA,QAED,OAAO,OAAO,SAAS,QACtB,8CAAC,SAAI,WAAU,oBAAoB,gBAAM,MAAM,QAAQ,MAAK;AAAA,QAE7D,OAAO,OAAO,QACb;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,CAAC,eAAe,MAAM,MAAM,IAAI,CAAC;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAW,WAAW;AAAA,YACtB,YAAU;AAAA;AAAA,QACZ;AAAA,SAEJ;AAAA,SAtCM,EAAE,mBAwCZ;AAAA,EAEJ,CAAC,GACH;AAEJ;;;AC3EA,IAAAC,iBAAyB;AAwBjB,IAAAC,uBAAA;AAdD,SAAS,cAAc,EAAE,OAAO,SAAS,IAAI,MAAM,MAAM,GAMzC;AACrB,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,CAAC,SAAS,GAAG,OAAO,IAAI;AAC9B,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,IAAI,QAAQ;AAClB,SACE,+CAAC,aAAQ,WAAU,aAAY,cAAY,GAAG,eAC5C;AAAA,mDAAC,SAAI,WAAU,eACb;AAAA,oDAAC,UAAM,aAAG,eAAc;AAAA,MACxB,+CAAC,UAAK,WAAU,iBAAgB;AAAA;AAAA,QAAG,QAAQ;AAAA,SAAY;AAAA,MACvD,8CAAC,UAAK,WAAU,kBAAkB,kBAAQ,cAAa;AAAA,OACzD;AAAA,IACA,8CAAC,OAAE,WAAU,kBAAkB,kBAAQ,MAAK;AAAA,IAC5C,8CAAC,SAAI,WAAU,mBAAmB,kBAAQ,OAAM;AAAA,IAC/C,KAAK,CAAC,EAAE,eACP,+CAAC,SAAI,WAAU,iBACb;AAAA,qDAAC,UAAM;AAAA,UAAE;AAAA,QAAY;AAAA,QAAI,EAAE;AAAA,SAAe;AAAA,MAC1C,+CAAC,UAAK,WAAU,2BACb;AAAA,eAAO,EAAE,UAAU,YAAY,8CAAC,UAAK,WAAU,kBAAkB,YAAE,MAAM,QAAQ,CAAC,GAAE;AAAA,QACrF;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,cAAc,GAAG,SAAS,KAAK,cAAc;AAAA,YACxD,WAAW,OAAO,EAAE,UAAU,WAAW,EAAE,MAAM,QAAQ,CAAC,IAAI;AAAA,YAC9D,qBAAqB,EAAE;AAAA,YACvB,gBAAgB,EAAE;AAAA,YAClB;AAAA,YACA;AAAA;AAAA,QACF;AAAA,SACF;AAAA,OACF;AAAA,IAED,YAAY,QAAQ,SAAS,KAC5B,8CAAC,QAAG,WAAU,kBACX,kBAAQ,IAAI,CAAC,MACZ,+CAAC,QACC;AAAA,oDAAC,UAAK,WAAU,kBAAkB,YAAE,aAAY;AAAA,MAChD,+CAAC,SACC;AAAA,sDAAC,OAAE,WAAU,mBAAmB,YAAE,MAAK;AAAA,QACvC,8CAAC,SAAI,WAAU,mBAAmB,YAAE,OAAM;AAAA,SAC5C;AAAA,SALO,EAAE,EAMX,CACD,GACH;AAAA,IAEF,+CAAC,SAAI,WAAU,kBACZ;AAAA,eACC;AAAA,QAAC;AAAA;AAAA,UAAO,MAAK;AAAA,UAAS,WAAU;AAAA,UAC9B,SAAS,MAAM,MAAM,QAAQ,MAAM,EAAE,MAAM,YAAY,SAAS,SAAS,QAAQ,KAAK,MAAM,GAAG,GAAG,EAAE,CAAC;AAAA,UACpG,aAAG;AAAA;AAAA,MACN;AAAA,MAED,QAAQ,SAAS,KAChB;AAAA,QAAC;AAAA;AAAA,UAAO,MAAK;AAAA,UAAS,WAAU;AAAA,UAAuC,iBAAe;AAAA,UACpF,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,UACnC,qBAAW,GAAG,sBAAsB,GAAG,gBAAgB,QAAQ,MAAM;AAAA;AAAA,MACxE;AAAA,OAEJ;AAAA,KACF;AAEJ;;;AC3EA,IAAAC,iBAAyB;AAoBjB,IAAAC,uBAAA;AAhBR,SAASC,aAAY,QAAqC;AACxD,MAAI,WAAW,IAAK,QAAO;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAEA,SAAS,YAAY,QAA6B,IAAsB;AACtE,MAAI,WAAW,IAAK,QAAO,GAAG;AAC9B,MAAI,WAAW,IAAK,QAAO,GAAG;AAC9B,SAAO,GAAG;AACZ;AAEA,SAAS,SAAS,EAAE,MAAM,GAAG,GAAqD;AAChF,SACE,8CAAC,SAAI,WAAU,iBACZ,eAAK,IAAI,CAAC,GAAG,MACZ,8CAAC,UAAa,WAAW,mBAAmBA,aAAY,EAAE,MAAM,CAAC,IAAK,sBAAY,EAAE,QAAQ,EAAE,KAAnF,CAAqF,CACjG,GACH;AAEJ;AAEO,SAAS,eAAe,EAAE,YAAY,cAAc,cAAc,GAAG,GAK5D;AACd,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,EAAE,UAAU,UAAU,KAAK,eAAe,cAAc,IAAI;AAClE,MAAI,SAAS,WAAW,KAAK,SAAS,WAAW,KAAK,CAAC,KAAK;AAC1D,WAAO,+EAAE;AAAA,EACX;AACA,QAAM,YAAY,iBAAiB;AACnC,QAAM,YAAY,iBAAiB;AACnC,QAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,QAAQ,IAAI,SAAS;AACxD,QAAM,UAAU,QAAQ,KAAK,MAAO,IAAI,OAAO,QAAS,MAAM;AAC9D,QAAM,WAAW,QAAQ,KAAK,MAAO,IAAI,QAAQ,QAAS,MAAM;AAChE,QAAM,YAAY,QAAQ,KAAK,MAAO,IAAI,SAAS,QAAS,MAAM;AAElE,SACE,+CAAC,SAAI,WAAU,YACb;AAAA,mDAAC,YAAO,MAAK,UAAS,WAAU,iBAAgB,iBAAe,UAAU,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,GAC3G;AAAA,qDAAC,UAAK,WAAU,mBACd;AAAA,sDAAC,UAAK,WAAU,gBAAe,eAAY,QAAO;AAAA,QAClD,8CAAC,UAAK,WAAU,kBAAkB,aAAG,iBAAgB;AAAA,SACvD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,WAAW,4CAA4C;AAAA,UAClE,OAAM;AAAA,UAAK,QAAO;AAAA,UAAK,SAAQ;AAAA,UAAY,MAAK;AAAA,UAAO,QAAO;AAAA,UAC9D,aAAY;AAAA,UAAI,eAAc;AAAA,UAAQ,gBAAe;AAAA,UAAQ,eAAY;AAAA,UAEzE,wDAAC,UAAK,GAAE,gBAAe;AAAA;AAAA,MACzB;AAAA,OACF;AAAA,IAEC,YACC,+CAAC,SAAI,WAAU,iBACb;AAAA,qDAAC,SAAI,WAAU,kBACb;AAAA,uDAAC,SAAI,WAAU,qBACb;AAAA,wDAAC,UAAK,WAAU,sBAAsB,qBAAU;AAAA,UAChD,8CAAC,YAAS,MAAM,UAAU,IAAQ;AAAA,WACpC;AAAA,QACA,+CAAC,SAAI,WAAU,6CACb;AAAA,wDAAC,UAAK,WAAU,sBAAsB,qBAAU;AAAA,UAChD,8CAAC,YAAS,MAAM,UAAU,IAAQ;AAAA,WACpC;AAAA,SACF;AAAA,MAEC,OACC,+CAAC,SAAI,WAAU,mBACb;AAAA,sDAAC,UAAK,WAAU,iBAAiB,cAAI,OAAM;AAAA,QAC3C,+CAAC,SAAI,WAAU,gBACb;AAAA,wDAAC,UAAK,WAAU,0CAAyC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,GAAG;AAAA,UAC1F,8CAAC,UAAK,WAAU,2CAA0C,OAAO,EAAE,OAAO,GAAG,QAAQ,IAAI,GAAG;AAAA,UAC5F,8CAAC,UAAK,WAAU,2CAA0C,OAAO,EAAE,OAAO,GAAG,SAAS,IAAI,GAAG;AAAA,WAC/F;AAAA,QACA,+CAAC,SAAI,WAAU,mBACb;AAAA,yDAAC,UAAK,WAAU,wBACd;AAAA,0DAAC,UAAK,WAAU,gDAA+C,eAAY,QAAO;AAAA,YACjF,IAAI;AAAA,YAAK;AAAA,YAAE,IAAI;AAAA,aAClB;AAAA,UACA,+CAAC,UAAK,WAAU,wBACd;AAAA,0DAAC,UAAK,WAAU,iDAAgD,eAAY,QAAO;AAAA,YAClF,IAAI;AAAA,YAAM;AAAA,YAAE,IAAI;AAAA,aACnB;AAAA,UACA,+CAAC,UAAK,WAAU,wBACd;AAAA,0DAAC,UAAK,WAAU,iDAAgD,eAAY,QAAO;AAAA,YAClF,IAAI;AAAA,YAAO;AAAA,YAAE,IAAI;AAAA,aACpB;AAAA,WACF;AAAA,SACF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AC1BU,IAAAC,uBAAA;AA1DV,SAAS,WAAW,KAAyB,cAA0C;AACrF,QAAM,OAAO,IAAI;AACjB,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,aAAa,KAAK,CAAC,QACxB,IAAI,wBAAwB,KAAK,uBAChC,KAAK,eAAe,QAAQ,IAAI,gBAAgB,KAAK,WAAY;AACtE;AAEA,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AACpF;AAQA,SAAS,aAAa,OAA2B,cAAoC;AACnF,QAAM,QAAkB,CAAC;AACzB,QAAM,kBAAkB,oBAAI,IAAsB;AAClD,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,EAAE,UAAU;AACzB,UAAM,SAAS,EAAE,UAAU,GAAG,EAAE,WAAW,KAAK,YAAY,MAAM,EAAE;AACpE,QAAI,CAAC,gBAAgB,IAAI,IAAI,GAAG;AAC9B,sBAAgB,IAAI,MAAM,CAAC,CAAC;AAC5B,YAAM,KAAK,IAAI;AAAA,IACjB;AACA,oBAAgB,IAAI,IAAI,EAAG,KAAK,MAAM;AAAA,EACxC;AACA,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,UAAU,gBAAgB,IAAI,IAAI,EAAG,KAAK,IAAI;AACpD,WAAO,EAAE,QAAQ,MAAM,OAAO,OAAO,GAAG,IAAI,IAAI,OAAO,KAAK,QAAQ;AAAA,EACtE,CAAC;AACH;AAEO,SAAS,iBAAiB,EAAE,OAAO,cAAc,SAAS,IAAI,MAAM,MAAM,GAQjE;AACd,QAAM,OAAO,MAAM,UAAU;AAC7B,QAAM,QAAQ,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAC1D,QAAM,cAAc,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,GAAG,YAAY;AACxF,QAAM,cAAc,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,GAAG,YAAY;AACxF,QAAM,eAAe,MAAM,SAAS,OAAO,CAAC,QAAQ,WAAW,KAAK,YAAY,CAAC;AACjF,QAAM,YAAY,MAAM,SAAS,OAAO,CAAC,QAAQ,CAAC,WAAW,KAAK,YAAY,CAAC;AAC/E,QAAM,cAAc,CAAC,GAAG,cAAc,GAAG,SAAS;AAClD,QAAM,UAAU,MAAM,UAAU,cAAc,MAAM,aAAa,GAAG,eAAe,MAAM,UAAU,IAAI;AAEvG,SACE,+CAAC,SAAI,WAAU,YACb;AAAA,mDAAC,SAAI,WAAU,gBACZ;AAAA,cACC,+CAAC,UAAK,WAAU,0BACd;AAAA,sDAAC,UAAK,WAAU,yBAAwB,eAAY,QAAO;AAAA,QAC1D,GAAG;AAAA,SACN;AAAA,MAED,MAAM,UAAU,cAAc,8CAAC,UAAK,WAAU,iBAAiB,aAAG,eAAc;AAAA,MAChF,WAAW,+CAAC,UAAK,WAAU,iBAAiB;AAAA,gBAAQ;AAAA,QAAS;AAAA,QAAI,QAAQ;AAAA,SAAK;AAAA,MAC9E,QAAQ,MAAM,eAAe,8CAAC,UAAK,WAAU,gBAAgB,gBAAM,aAAY;AAAA,MAC/E,MAAM,mBAAmB,8CAAC,UAAK,WAAU,iBAAiB,gBAAM,iBAAgB;AAAA,MACjF,8CAAC,aAAU,IAAQ,SAAkB,KAAK,EAAE,MAAM,SAAS,SAAS,MAAM,QAAQ,GAAG;AAAA,OACvF;AAAA,IACA,+CAAC,SAAI,WAAU,iBACb;AAAA,qDAAC,UAAK,WAAU,iBACd;AAAA,sDAACC,QAAA,EAAM,MAAK,QAAO,KAAK,MAAM,gBAAgB,QAAW,MAAM,MAAM,gBAAgB,QAAW;AAAA,QAChG,8CAAC,UAAK,WAAU,iBAAiB,gBAAM,cAAa;AAAA,SACtD;AAAA,MACC,MAAM,UAAU,aACf,8CAAC,UAAK,WAAU,eAAc,gBAAE,IAEhC,+CAAC,UAAK,WAAU,kBAAkB;AAAA,cAAM;AAAA,QAAU,8CAAC,OAAE,oBAAC;AAAA,QAAK,MAAM;AAAA,SAAU;AAAA,MAE7E,+CAAC,UAAK,WAAU,qCACd;AAAA,sDAACA,QAAA,EAAM,MAAK,QAAO,KAAK,MAAM,gBAAgB,QAAW,MAAM,MAAM,gBAAgB,QAAW;AAAA,QAChG,8CAAC,UAAK,WAAU,iBAAiB,gBAAM,cAAa;AAAA,SACtD;AAAA,OACF;AAAA,IACC,MAAM,UAAU,cAAc,MAAM,cACnC;AAAA,MAAC;AAAA;AAAA,QACC,YAAY,MAAM;AAAA,QAClB,cAAc,MAAM;AAAA,QACpB,cAAc,MAAM;AAAA,QACpB;AAAA;AAAA,IACF;AAAA,KAEA,YAAY,SAAS,KAAK,YAAY,SAAS,MAC/C,+CAAC,SAAI,WAAU,oBACb;AAAA,oDAAC,QAAG,WAAU,8CACX,sBAAY,IAAI,CAAC,GAAG,MAAM,8CAAC,QAA6B,YAAE,SAAvB,GAAG,EAAE,MAAM,IAAI,CAAC,EAAa,CAAK,GACxE;AAAA,MACA,8CAAC,UAAK,WAAU,yBAAwB,eAAY,QAAO,oBAAC;AAAA,MAC5D,8CAAC,QAAG,WAAU,8CACX,sBAAY,IAAI,CAAC,GAAG,MAAM,8CAAC,QAA6B,YAAE,SAAvB,GAAG,EAAE,MAAM,IAAI,CAAC,EAAa,CAAK,GACxE;AAAA,OACF;AAAA,IAED,QAAQ,MAAM,SAAS,MAAM,MAAM,SAAS,KAC3C,8CAAC,iBAAc,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,IAAQ,MAAY,OAAc;AAAA,IAE/F,8CAAC,SAAI,WAAU,kBACZ,sBAAY,IAAI,CAAC,QAAQ;AACxB,YAAM,QAAQ,IAAI,UAAU,IAAI;AAChC,YAAM,UAAU,QAAQ,IAAK,IAAI,UAAU,QAAS,KAAK;AACzD,YAAM,UAAU,QAAQ,IAAK,IAAI,UAAU,QAAS,KAAK;AACzD,YAAM,WAAW,WAAW,KAAK,YAAY;AAC7C,YAAM,YAAY,cAAc,IAAI,QAAQ,MAAM,SAAS,KAAK,cAAc;AAC9E,aACE,+CAAC,SAAI,WAAW,WAAW,kCAAkC,iBAC3D;AAAA,uDAAC,SAAI,WAAU,qBACb;AAAA,wDAAC,UAAK,WAAU,yCAAyC,cAAI,WAAU;AAAA,UACvE,8CAAC,UAAK,WAAU,mBAAmB,cAAI,OAAM;AAAA,UAC7C,8CAAC,UAAK,WAAU,yCAAyC,cAAI,WAAU;AAAA,WACzE;AAAA,QACA,+CAAC,SAAI,WAAU,gBACb;AAAA,wDAAC,OAAE,WAAU,qBAAoB,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,GAAG;AAAA,UAClE,8CAAC,OAAE,WAAU,qBAAoB,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,GAAG;AAAA,WACpE;AAAA,QAQC,IAAI,UAAU,CAAC,IAAI,OAAO,eACzB,+CAAC,SAAI,WAAW,WAAW,mCAAmC,qBAC5D;AAAA,yDAAC,UAAM;AAAA,gBAAI,OAAO;AAAA,YAAY;AAAA,YAAI,IAAI,OAAO;AAAA,aAAe;AAAA,UAC5D,+CAAC,UAAK,WAAU,2BACb;AAAA,mBAAO,IAAI,OAAO,UAAU,YAAY,8CAAC,UAAK,WAAU,kBAAkB,cAAI,OAAO,MAAM,QAAQ,CAAC,GAAE;AAAA,YACvG;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA,WAAW,OAAO,IAAI,OAAO,UAAU,WAAW,IAAI,OAAO,MAAM,QAAQ,CAAC,IAAI;AAAA,gBAChF,qBAAqB,IAAI,OAAO;AAAA,gBAChC,gBAAgB,IAAI,OAAO;AAAA,gBAC3B;AAAA,gBACA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,WA/B+E,IAAI,KAiCvF;AAAA,IAEJ,CAAC,GACH;AAAA,IACC,MAAM,WAAW,WAAW,8CAAC,UAAK,WAAU,iBAAiB,aAAG,KAAK,WAAW,MAAM,OAAO,CAAC,GAAE;AAAA,IAChG,MAAM,SAAS,SAAS,KACvB,+CAAC,SAAI,WAAU,gBAKb;AAAA,oDAAC,UAAK,WAAU,mBAAmB,aAAG,eAAc;AAAA,MACpD,8CAAC,gBAAa,QAAQ,MAAM,UAAU,YAAY,MAAM;AAAA,OAC1D;AAAA,IAED,MAAM,UAAU,cAAc,8CAAC,SAAI,WAAU,kBAAkB,aAAG,WAAU;AAAA,KAC/E;AAEJ;;;AC9JQ,IAAAC,uBAAA;AAPR,SAAS,cAAc,EAAE,GAAG,GAAG,GAA+D;AAC5F,QAAM,YAAY,EAAE,UAAU,cAAc,OAAO,EAAE,cAAc;AACnE,QAAM,QAAQ,EAAE,WAAW;AAC3B,MAAI,CAAC,aAAa,CAAC,EAAE,eAAe,EAAE,EAAE,eAAe,CAAC,EAAE,cAAc,CAAC,EAAE,aAAa,CAAC,MAAO,QAAO;AACvG,SACE,+CAAC,SAAI,WAAU,gBACZ;AAAA,iBACC,+CAAC,OAAE,WAAU,sBAAsB;AAAA,QAAE;AAAA,MAAa;AAAA,MAAE,EAAE;AAAA,MAAU;AAAA,MAAE,EAAE;AAAA,MAAU;AAAA,MAAE,EAAE;AAAA,OAAa;AAAA,IAEhG,EAAE,eAAe,8CAAC,UAAK,WAAU,gBAAgB,YAAE,aAAY;AAAA,IAC/D,EAAE,eAAe,CAAC,EAAE,aAAa,8CAAC,UAAK,WAAU,iBAAiB,aAAG,gBAAe;AAAA,IACpF,EAAE,aAAa,8CAAC,UAAK,WAAU,iBAAiB,aAAG,eAAc;AAAA,IACjE,SACC,8CAAC,UAAK,WAAU,iBAAiB,aAAG,KAAK,IAAI,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,CAAC,GAAE;AAAA,KAEjI;AAEJ;AAEO,SAAS,aAAa,EAAE,SAAS,IAAI,MAAM,MAAM,GAA8G;AAIpK,QAAM,WAAW,QAAQ,UAAU,WAAW,CAAC,GAAG,OAAO,CAAC,MACxD,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC;AACzE,MAAI,QAAQ,WAAW,GAAG;AAExB,WAAO,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI,8CAAC,SAAI,WAAU,iBAAgB,IAAK,8CAAC,SAAI,WAAU,kBAAkB,aAAG,iBAAgB;AAAA,EAChJ;AACA,SACE,8CAAC,SAAI,WAAU,iBACZ,kBAAQ,IAAI,CAAC,MACZ,+CAAC,SAAoB,WAAU,iBAC7B;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QAEP,cAAc,QAAQ,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,YAAY,EAAE,OAAO;AAAA,QACtF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IACA,8CAAC,mBAAgB,OAAO,GAAG,SAAkB,IAAQ,MAAY;AAAA,OAVzD,EAAE,OAWZ,CACD,GACH;AAEJ;AAOA,SAAS,sBAAsB,IAAkB,MAAwC;AACvF,QAAM,UAAU,GAAG,SAAS,CAAC;AAC7B,MAAI,SAAS,UAAa,CAAC,WAAW,QAAQ,gBAAgB,UAAa,QAAQ,gBAAgB,KAAM,QAAO;AAChH,QAAM,iBAAkC;AAAA,IACtC,GAAG;AAAA,IACH,cAAc,KAAK,QAAQ,CAAC;AAAA,IAC5B,mBAAmB,QAAQ,cAAc,OAAO,cAAc;AAAA,EAChE;AACA,SAAO,EAAE,GAAG,IAAI,UAAU,CAAC,gBAAgB,GAAG,GAAG,SAAS,MAAM,CAAC,CAAC,EAAE;AACtE;AAEO,SAAS,UAAU,EAAE,SAAS,IAAI,KAAK,GAA0F;AACtI,QAAM,YAAY,aAAa;AAG/B,QAAM,WAAW,QAAQ,UAAU,WAAW,CAAC,GAAG,OAAO,CAAC,MACxD,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC;AAC3C,MAAI,QAAQ,WAAW,EAAG,QAAO,8CAAC,SAAI,WAAU,kBAAkB,aAAG,cAAa;AAClF,SACE,8CAAC,SAAI,WAAU,iBACZ,kBAAQ,IAAI,CAAC,MAAM;AAIlB,UAAM,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG;AACpD,WACA,+CAAC,SAAI,WAAU,oBAA+B,gBAAc,EAAE,aAAa,QACzE;AAAA,oDAAC,iBAAc,GAAM,IAAQ;AAAA,MAI5B,EAAE,QACD;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,CAAC,sBAAsB,eAAe,EAAE,IAAI,GAAG,QAAQ,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAAA,UACtF;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,WAAW,WAAW;AAAA;AAAA,MACxB;AAAA,MAED,EAAE,WAAW,8CAAC,wBAAqB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,GAAG,IAAQ;AAAA,MACjF,CAAC,EAAE,QAAQ,CAAC,EAAE,WAAW,8CAAC,SAAI,WAAU,uBAAuB,aAAG,iBAAgB;AAAA,SAhB9C,EAAE,GAiBzC;AAAA,EAEF,CAAC,GACH;AAEJ;;;ACvHA,IAAAC,iBAAoD;;;ACU7C,SAAS,aAAa,SAAmC,gBAAoD;AAClH,QAAM,aAA8B,CAAC;AACrC,QAAM,eAAe,oBAAI,IAAY;AAErC,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,WAAW;AAAE,iBAAW,KAAK,CAAC;AAAG,mBAAa,IAAI,EAAE,aAAa;AAAA,IAAE;AAAA,EAC3E;AAEA,MAAI,SAAS;AACb,QAAM,SAAS,QAAQ;AAAA,IACrB,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,aAAa,KAAK,EAAE,QAAQ,KAAK,CAAC,MAAM,eAAe,SAAS,EAAE,OAAO,CAAC;AAAA,EACvG,KAAK;AACL,MAAI,UAAU,SAAS,GAAG;AACxB,eAAW,KAAK,MAAM;AAAG,iBAAa,IAAI,OAAO,aAAa;AAAG,cAAU;AAAA,EAC7E;AAEA,QAAM,UAAU,QACb,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,IAAI,EAAE,aAAa,CAAC,EAC/D,KAAK,CAAC,GAAG,OAAO,EAAE,eAAe,OAAO,qBAAqB,EAAE,eAAe,OAAO,iBAAiB;AACzG,aAAW,KAAK,SAAS;AACvB,QAAI,UAAU,EAAG;AACjB,eAAW,KAAK,CAAC;AAAG,iBAAa,IAAI,EAAE,aAAa;AAAG,cAAU;AAAA,EACnE;AAEA,QAAM,WAAW,WAAW,SAAS;AACrC,QAAM,OAAO,WAAW,aAAa,QAAQ,MAAM,GAAG,CAAC;AACvD,QAAM,UAAU,WAAW,eAAe,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC;AAClF,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,aAAa,CAAC;AAElE,SAAO,EAAE,UAAU,YAAY,MAAM,QAAQ,OAAO,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,qBAAqB,QAAQ,iBAAiB,KAAK;AAC/H;AAIO,SAAS,cAAc,OAAsB,qBAA6C;AAC/F,SAAO,MAAM,aAAa,MAAM,kBAAkB;AACpD;;;ACzCO,SAAS,eAAe,GAAmB;AAChD,SAAO,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,EAAE,UAAU,KAAK,EAAE,QAAQ,UAAU,EAAE,EAAE,YAAY;AACpG;AAEA,SAAS,wBAAwB,OAAsB,GAAoB;AACzE,MAAI,eAAe,MAAM,eAAe,EAAE,SAAS,CAAC,EAAG,QAAO;AAC9D,SAAO,CAAC,CAAC,MAAM,sBAAsB,eAAe,MAAM,kBAAkB,EAAE,SAAS,CAAC;AAC1F;AAEO,SAAS,aAAa,OAAsB,OAAwB;AACzE,QAAM,IAAI,eAAe,MAAM,KAAK,CAAC;AACrC,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,wBAAwB,OAAO,CAAC,EAAG,QAAO;AAC9C,SAAO,MAAM,QAAQ;AAAA,IACnB,CAAC,MAAM,eAAe,EAAE,YAAY,EAAE,SAAS,CAAC,KAAK,eAAe,EAAE,YAAY,EAAE,SAAS,CAAC;AAAA,EAChG;AACF;AAIO,SAAS,iBAAiB,OAAsB,OAAyC;AAC9F,QAAM,IAAI,eAAe,MAAM,KAAK,CAAC;AACrC,MAAI,CAAC,KAAK,wBAAwB,OAAO,CAAC,EAAG,QAAO,MAAM;AAC1D,SAAO,MAAM,QAAQ;AAAA,IACnB,CAAC,MAAM,eAAe,EAAE,YAAY,EAAE,SAAS,CAAC,KAAK,eAAe,EAAE,YAAY,EAAE,SAAS,CAAC;AAAA,EAChG;AACF;;;AC/BA,IAAAC,iBAA8C;AAMvC,SAAS,WAAW,YAGzB;AACA,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAwB,IAAI;AAI9D,QAAM,iBAAa,uBAAsB,IAAI;AAE7C,QAAM,UAAM,4BAAY,OAAO,eAAuB,SAAoC;AACxF,QAAI,WAAW,YAAY,KAAM,QAAO;AACxC,eAAW,UAAU;AACrB,iBAAa,aAAa;AAC1B,QAAI;AACF,aAAO,MAAM,WAAW,eAAe,IAAI;AAAA,IAC7C,UAAE;AACA,iBAAW,UAAU;AACrB,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO,EAAE,WAAW,IAAI;AAC1B;;;ACLQ,IAAAC,uBAAA;AAjBR,IAAM,YAAY;AAEX,SAAS,WAAW,EAAE,OAAO,eAAAC,gBAAe,cAAc,QAAQ,SAAS,GAAG,GAOrE;AACd,QAAM,cAAc,MAAY;AAC9B,SAAK,QAAQ,IAAI,MAAM,eAAe,CAAC,MAAM,SAAS;AAAA,EACxD;AAEA,SACE,+CAAC,SAAI,WAAU,mBACb;AAAA,mDAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,QAC9D;AAAA,oDAACC,QAAA,EAAM,KAAK,MAAM,wBAAwB,QAAW,MAAM,MAAM,iBAAiB,MAAK,QAAO;AAAA,MAC9F,+CAAC,UAAK,WAAU,wBACb;AAAA,cAAM;AAAA,QACN,gBAAgB,MAAM,qBACnB,+CAAC,UAAK,WAAU,2BAA0B;AAAA;AAAA,UAAG,MAAM;AAAA,UAAmB;AAAA,WAAC,IACvE;AAAA,SACN;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,gBAAc,MAAM;AAAA,QACpB,cAAY,MAAM,YAAY,GAAG,eAAe,GAAG;AAAA,QACnD,UAAU,CAACD,kBAAiB,QAAQ,cAAc;AAAA,QAClD,SAAS;AAAA,QAET,wDAAC,SAAI,SAAQ,aAAY,eAAY,QACnC;AAAA,UAAC;AAAA;AAAA,YACC,GAAG;AAAA,YACH,MAAM,MAAM,YAAY,iBAAiB;AAAA,YACzC,QAAQ,MAAM,YAAY,SAAS;AAAA,YACnC,aAAa;AAAA,YACb,gBAAe;AAAA,YACf,eAAc;AAAA;AAAA,QAChB,GACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;ACrDA,IAAAE,iBAAoC;;;ACgBhC,IAAAC,uBAAA;AAXJ,SAAS,aAAa,aAA6B;AACjD,QAAM,IAAI,IAAI,KAAK,cAAc,GAAI;AACrC,SAAO,GAAG,GAAG,EAAE,SAAS,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,WAAW,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC;AACtF;AAMA,SAAS,KAAK,EAAE,MAAM,OAAO,OAAO,MAAM,GAAyE;AACjH,SACE,+CAAC,UAAK,WAAW,OAAO,wCAAwC,kBAC7D;AAAA,YAAQ,8CAAC,SAAI,WAAU,mBAAkB,KAAK,OAAO,KAAI,IAAG,IAAK;AAAA,IAClE,8CAAC,UAAK,WAAU,gBAAgB,gBAAK;AAAA,KACvC;AAEJ;AAEO,SAAS,WAAW,EAAE,OAAO,OAAO,OAAO,IAAI,QAAQ,GAM9C;AAOd,QAAM,SAAS,OAAO,UAAU,UAAU,CAAC;AAK3C,QAAM,YAAY,OAAO,UAAU,UAAU,OAAO,UAAU,eACzD,OAAO,MAAM,cAAc,YAAY,OAAO,MAAM,cAAc;AACvE,QAAM,QAAQ,WAAW,GAAG,MAAO,SAAS,SAAI,MAAO,SAAS,KAAK;AAMrE,QAAM,SAAS,OAAO,UAAU,SAAU,MAAM,eAAe,OAAQ;AACvE,QAAM,OAAO,OAAO,cAAc,CAAC,QAC/B,GAAG,WACH,SACG,UAAU,WACX,OAAO,UAAU,SACf,WACA,aAAa,MAAM,WAAW;AAEtC,SACE,+CAAC,SAAI,WAAW,UAAU,OAAO,aAAa,8BAA8B,aAC1E;AAAA,kDAAC,UAAK,WAAW,UAAU,OAAO,aAAa,wCAAwC,kBAAmB,gBAAK;AAAA,IAC/G,+CAAC,UAAK,WAAU,gBACd;AAAA,oDAAC,QAAK,MAAM,MAAM,cAAc,OAAO,MAAM,mBAAmB;AAAA,MAGhE,8CAAC,UAAK,WAAW,WAAW,iBAAiB,mCAC1C,mBAAS,UACZ;AAAA,MACA,8CAAC,QAAK,MAAM,MAAM,cAAc,OAAO,MAAM,mBAAmB,MAAI,MAAC;AAAA,OACvE;AAAA,IACA,8CAAC,aAAU,IAAQ,SAAkB,KAAK,EAAE,MAAM,SAAS,SAAS,MAAM,QAAQ,GAAG;AAAA,KACvF;AAEJ;;;ADdM,IAAAC,uBAAA;AA/CN,IAAMC,aAAY;AAEX,SAAS,aAAa,EAAE,OAAO,UAAU,QAAQ,OAAO,IAAI,SAAS,SAAS,QAAQ,QAAQ,OAAO,GAW5F;AACd,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAwB,IAAI;AAMtD,gCAAU,MAAM;AACd,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,MAAM,aAAa,CAAC;AACxB,gCAAU,MAAM;AACd,QAAI,UAAU,KAAM;AACpB,UAAM,KAAK,WAAW,MAAM,SAAS,IAAI,GAAG,GAAI;AAChD,WAAO,MAAM,aAAa,EAAE;AAAA,EAC9B,GAAG,CAAC,KAAK,CAAC;AAMV,QAAM,MAAM,MAAM,QAAQ,OAAO,CAAC,MAAM,CAAC,cAAc,OAAO,EAAE,OAAO,GAAG,KAAK,CAAC;AAKhF,QAAM,cAAc,MAAY;AAC9B,UAAM,OAAO,CAAC,MAAM;AACpB,SAAK,QAAQ,IAAI,MAAM,eAAe,IAAI,EAAE,KAAK,CAAC,OAAO;AACvD,UAAI,GAAI,UAAS,OAAO,GAAG,eAAe,GAAG,cAAc;AAAA,IAC7D,CAAC;AAAA,EACH;AAEA,SACE,+CAAC,SAAI,WAAU,qBACb;AAAA,mDAAC,SAAI,WAAU,0BACb;AAAA,oDAAC,YAAO,MAAK,UAAS,WAAU,0BAAyB,cAAY,GAAG,MAAM,SAAS,QACrF,wDAAC,eAAY,GACf;AAAA,MACA,8CAACC,QAAA,EAAM,KAAK,MAAM,wBAAwB,QAAW,MAAM,MAAM,iBAAiB,MAAK,QAAO;AAAA,MAC9F,8CAAC,UAAK,WAAU,0BAA0B,gBAAM,iBAAgB;AAAA,MAChE;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,gBAAc,MAAM;AAAA,UACpB,cAAY,MAAM,YAAY,GAAG,eAAe,GAAG;AAAA,UACnD,UAAU,QAAQ,cAAc;AAAA,UAChC,SAAS;AAAA,UAET,wDAAC,SAAI,SAAQ,aAAY,eAAY,QACnC;AAAA,YAAC;AAAA;AAAA,cACC,GAAGD;AAAA,cACH,MAAM,MAAM,YAAY,iBAAiB;AAAA,cACzC,QAAQ,MAAM,YAAY,SAAS;AAAA,cACnC,aAAa;AAAA,cACb,gBAAe;AAAA,cACf,eAAc;AAAA;AAAA,UAChB,GACF;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IAEA,+CAAC,SAAI,WAAU,yBACb;AAAA;AAAA,QAAC;AAAA;AAAA,UAAO,MAAK;AAAA,UAAS,WAAU;AAAA,UAAyB,cAAY,GAAG;AAAA,UACtE,UAAU,SAAS,SAAS;AAAA,UAAG,SAAS;AAAA,UACxC,wDAAC,eAAY;AAAA;AAAA,MACf;AAAA,MACA,8CAAC,UAAK,WAAU,yBAAyB,aAAG,qBAAqB,SAAS,OAAO,SAAS,KAAK,GAAE;AAAA,MACjG;AAAA,QAAC;AAAA;AAAA,UAAO,MAAK;AAAA,UAAS,WAAU;AAAA,UAAyB,cAAY,GAAG;AAAA,UACtE,UAAU,SAAS,SAAS,SAAS;AAAA,UAAO,SAAS;AAAA,UACrD,wDAAC,eAAY;AAAA;AAAA,MACf;AAAA,OACF;AAAA,IAEA,+CAAC,SAAI,WAAU,0BACb;AAAA,oDAAC,UAAK,WAAU,2BAA2B,cAAI,QAAO;AAAA,MACrD,IAAI,IAAI,CAAC,MACR,8CAAC,cAA2B,OAAO,GAAG,OAAO,OAAO,EAAE,OAAO,GAAG,OAAc,IAAQ,WAArE,EAAE,OAAqF,CACzG;AAAA,OACH;AAAA,IAIC,UAAU,QACT,8CAAC,OAAE,WAAU,oBAAmB,MAAK,UAAS,aAAU,UAAU,iBAAM;AAAA,KAE5E;AAEJ;;;AE1DU,IAAAE,uBAAA;AA9CH,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAK3B,SAAS,QAAQ,OAAsB,QAAoC,OAAwB;AACxG,QAAM,UAAU,MAAM,QAAQ,OAAO,CAAC,MAAM,CAAC,cAAc,OAAO,EAAE,OAAO,GAAG,KAAK,CAAC,EAAE;AACtF,SAAO,KAAK,IAAI,SAAS,kBAAkB;AAC7C;AAIA,IAAMC,aAAY;AAEX,SAAS,eAAe,EAAE,OAAO,QAAQ,OAAO,KAAK,eAAAC,gBAAe,cAAc,QAAQ,SAAS,IAAI,QAAQ,GAW/F;AACrB,QAAM,SAAS,MAAM,QAClB,OAAO,CAAC,MAAM,CAAC,cAAc,OAAO,EAAE,OAAO,GAAG,KAAK,CAAC,EACtD,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE,WAAW;AAI/C,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,QAAQ,OAAO,MAAM,GAAG,GAAG;AACjC,QAAM,WAAW,OAAO,SAAS,MAAM;AAEvC,QAAM,cAAc,MAAY;AAC9B,SAAK,QAAQ,IAAI,MAAM,eAAe,CAAC,MAAM,SAAS;AAAA,EACxD;AAEA,SACE,+CAAC,SAAI,WAAU,uBACb;AAAA,mDAAC,SAAI,WAAU,4BACb;AAAA,qDAAC,YAAO,MAAK,UAAS,WAAU,iCAAgC,SAAS,QACvE;AAAA,sDAACC,QAAA,EAAM,KAAK,MAAM,wBAAwB,QAAW,MAAM,MAAM,iBAAiB,MAAK,QAAO;AAAA,QAC9F,+CAAC,UAAK,WAAU,4BACb;AAAA,gBAAM;AAAA,UACN,gBAAgB,MAAM,qBACnB,+CAAC,UAAK,WAAU,2BAA0B;AAAA;AAAA,YAAG,MAAM;AAAA,YAAmB;AAAA,aAAC,IACvE;AAAA,WACN;AAAA,SACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,gBAAc,MAAM;AAAA,UACpB,cAAY,MAAM,YAAY,GAAG,eAAe,GAAG;AAAA,UACnD,UAAU,CAACD,kBAAiB,QAAQ,cAAc;AAAA,UAClD,SAAS;AAAA,UAET,wDAAC,SAAI,SAAQ,aAAY,eAAY,QACnC;AAAA,YAAC;AAAA;AAAA,cACC,GAAGD;AAAA,cACH,MAAM,MAAM,YAAY,iBAAiB;AAAA,cACzC,QAAQ,MAAM,YAAY,SAAS;AAAA,cACnC,aAAa;AAAA,cACb,gBAAe;AAAA,cACf,eAAc;AAAA;AAAA,UAChB,GACF;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IACA,8CAAC,SAAI,WAAU,4BACZ,gBAAM,IAAI,CAAC,MACV,8CAAC,cAA2B,OAAO,GAAG,OAAO,OAAO,EAAE,OAAO,GAAG,OAAc,IAAQ,WAArE,EAAE,OAAqF,CACzG,GACH;AAAA,IACC,WAAW,KACV,8CAAC,YAAO,MAAK,UAAS,WAAU,8BAA6B,SAAS,QACnE,aAAG,oBAAoB,OAAO,MAAM,GACvC;AAAA,KAEJ;AAEJ;;;AC9FA,IAAAG,iBAAoC;;;ACElC,IAAAC,uBAAA;AADF,IAAM,MAAM,CAAC,MAAc,UAAuC,OAAO,UACvE;AAAA,EAAC;AAAA;AAAA,IAAI,OAAO;AAAA,IAAM,QAAQ;AAAA,IAAM,SAAQ;AAAA,IAAY,MAAM,OAAO,iBAAiB;AAAA,IAAQ,QAAQ,OAAO,SAAS;AAAA,IAChH,aAAa;AAAA,IAAK,eAAc;AAAA,IAAQ,gBAAe;AAAA,IAAQ,eAAY;AAAA,IAAQ;AAAA;AAAS;AAEzF,IAAM,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,mBAAkB,CAAE;AACpF,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,CAAC,8CAAC,UAAa,GAAE,KAAI,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,OAA3C,GAA+C,GAAI,8CAAC,UAAa,GAAE,6BAAN,GAAgC,CAAE,CAAC;AAC5J,IAAM,YAAY,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,kBAAiB,CAAE;AAC7E,IAAM,YAAY,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,wBAAuB,CAAE;AACnF,IAAM,aAAa,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,CAAC,8CAAC,YAAe,IAAG,MAAK,IAAG,MAAK,GAAE,OAAtB,GAA0B,GAAI,8CAAC,UAAa,GAAE,qBAAN,GAAwB,CAAE,CAAC;AACnI,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,oBAAmB,CAAE;AAE9E,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,CAAC,8CAAC,UAAa,GAAE,qBAAN,GAAwB,GAAI,8CAAC,UAAa,GAAE,wDAAN,GAA2D,CAAE,CAAC;AAChK,IAAM,cAAc,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,yBAAwB,CAAE;AACtF,IAAM,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,2BAA0B,CAAE;AAC1F,IAAM,eAAe,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,CAAC,8CAAC,UAAa,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,OAA1C,GAA8C,GAAI,8CAAC,UAAa,GAAE,2BAAN,GAA8B,CAAE,CAAC;AAC7J,IAAM,aAAa,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,0CAAyC,CAAE;AACtG,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,6BAA4B,CAAE;AACvF,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,CAAC,8CAAC,YAAe,IAAG,MAAK,IAAG,MAAK,GAAE,OAAtB,GAA0B,GAAI,8CAAC,UAAa,GAAE,gCAAN,GAAmC,CAAE,CAAC;AAC5I,IAAM,WAAW,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,uBAAsB,CAAE;AACjF,IAAM,aAAa,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,mHAAkH,CAAE;AAC/K,IAAM,YAAY,CAAC,EAAE,OAAO,GAAG,MAAS,IAAI,MAAM,8CAAC,UAAK,GAAE,4EAA2E,GAAI,IAAI;;;ADJ9I,IAAAC,uBAAA;AAbC,SAAS,YAAY,EAAE,IAAI,OAAO,cAAc,OAAO,aAAa,OAAO,UAAU,UAAU,UAAU,WAAW,WAAW,GAItH;AACd,QAAM,eAAW,uBAAgC,IAAI;AACrD,QAAM,kBAAc,4BAAY,CAAC,SAAkC;AACjE,aAAS,UAAU;AACnB,QAAI,OAAO,aAAa,WAAY,UAAS,IAAI;AAAA,aACxC,SAAU,CAAC,SAAuD,UAAU;AAAA,EACvF,GAAG,CAAC,QAAQ,CAAC;AACb,SACE,+CAAC,SAAI,WAAU,eACb;AAAA,kDAAC,WAAM,SAAS,IAAI,WAAW,cAAc,YAAY,qBAAsB,iBAAM;AAAA,IACrF,+CAAC,SAAI,WAAU,mBACb;AAAA,oDAAC,cAAW;AAAA,MACZ;AAAA,QAAC;AAAA;AAAA,UAAM;AAAA,UAAQ,KAAK;AAAA,UAAa,MAAK;AAAA,UAAO,cAAa;AAAA,UAAM;AAAA,UAA0B;AAAA,UACxF;AAAA,UAAoB;AAAA,UAAsB,UAAU,OAAK,SAAS,EAAE,OAAO,KAAK;AAAA;AAAA,MAAG;AAAA,MACpF,cAAc,MAAM,SAAS,IAC5B;AAAA,QAAC;AAAA;AAAA,UAAO,MAAK;AAAA,UAAS,WAAU;AAAA,UAAoB,cAAY;AAAA,UAC9D,SAAS,MAAM;AAAE,qBAAS,EAAE;AAAG,qBAAS,SAAS,MAAM;AAAA,UAAE;AAAA,UACzD,wDAAC,aAAU,MAAM,IAAI;AAAA;AAAA,MACvB,IACE;AAAA,OACN;AAAA,KACF;AAEJ;;;ARwFI,IAAAC,uBAAA;AAxGG,SAAS,WAAW,EAAE,WAAW,IAAI,QAAQ,GAIpC;AACd,QAAM,EAAE,QAAQ,QAAQ,OAAO,WAAW,IAAI;AAE9C,QAAM,eAAW,sBAAM;AACvB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,CAAC,uBAAuB,wBAAwB,QAAI,yBAAwB,IAAI;AACtF,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAyC,IAAI;AAIvE,gCAAU,MAAM;AACd,QAAI,UAAU,KAAM;AACpB,UAAM,KAAK,WAAW,MAAM,SAAS,IAAI,GAAG,GAAI;AAChD,WAAO,MAAM,aAAa,EAAE;AAAA,EAC9B,GAAG,CAAC,KAAK,CAAC;AAMV,QAAM,gBAAgB,gBAAgB,QAAQ,MAAM;AAIpD,QAAM,qBAAiB;AAAA,IACrB,MAAM,QAAQ,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,IACzE,CAAC,QAAQ,IAAI;AAAA,EACf;AAEA,QAAM,gBAAY,wBAAQ,MAAM,aAAa,eAAe,cAAc,GAAG,CAAC,eAAe,cAAc,CAAC;AAK5G,QAAM,UAAU,WAAW,UAAU;AAErC,QAAM,kBAAc,wBAAQ,OAAO;AAAA,IACjC,WAAW,QAAQ;AAAA,IACnB,KAAK,OAAO,eAAuB,SAAoC;AACrE,YAAM,KAAK,MAAM,QAAQ,IAAI,eAAe,IAAI;AAChD,UAAI,GAAI,UAAS,OAAO,YAAY,WAAW;AAC/C,aAAO;AAAA,IACT;AAAA,EACF,IAAI,CAAC,SAAS,QAAQ,SAAS,CAAC;AAIhC,QAAM,aAAa,cAAc,OAA+B,CAAC,KAAK,MAAM;AAC1E,QAAI,EAAE,eAAe,KAAK,IAAI,EAAE,eAAe,KAAK,KAAK;AACzD,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAML,QAAM,kBAA+C,CAAC;AACtD,QAAM,kBAA+C,CAAC;AACtD;AACE,QAAI,SAAS;AACb,QAAI,aAAa;AACjB,eAAW,SAAS,UAAU,YAAY;AACxC,YAAM,OAAO,QAAQ,OAAO,QAAQ,KAAK;AACzC,UAAI,SAAS,GAAG;AAAE,wBAAgB,KAAK,KAAK;AAAG;AAAA,MAAS;AACxD,UAAI,CAAC,cAAc,QAAQ,QAAQ;AAAE,wBAAgB,KAAK,KAAK;AAAG,kBAAU;AAAA,MAAK,OAAO;AAAE,qBAAa;AAAM,wBAAgB,KAAK,KAAK;AAAA,MAAE;AAAA,IAC3I;AAAA,EACF;AAEA,QAAM,YAAY,0BAA0B,OACxC,KACA,UAAU,MAAM,UAAU,CAAC,MAAM,EAAE,kBAAkB,qBAAqB;AAC9E,QAAM,YAAY,cAAc,KAAK,SAAY,UAAU,MAAM,SAAS;AAK1E,gCAAU,MAAM;AACd,QAAI,0BAA0B,QAAQ,cAAc,OAAW,0BAAyB,IAAI;AAAA,EAC9F,GAAG,CAAC,uBAAuB,SAAS,CAAC;AAQrC,QAAM,WAAW,QACb,CAAC,IACD,cACG,QAAQ,CAAC,UACR,MAAM,QACH,OAAO,CAAC,MAAM,cAAc,OAAO,EAAE,OAAO,GAAG,KAAK,CAAC,EACrD,IAAI,CAAC,WAAW,EAAE,OAAO,MAAM,MAAM,KAAK,EAAE,CAAC,EACjD,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAMrC,QAAM,WAAW,SAAS,SAAS,KACjC,gFACE;AAAA,mDAAC,SAAI,WAAU,iBACb;AAAA,oDAAC,UAAK,WAAU,gBAAe,eAAY,QAAO;AAAA,MACjD,GAAG;AAAA,OACN;AAAA,IACA,8CAAC,SAAI,WAAU,mBACZ,mBAAS,IAAI,CAAC,EAAE,MAAM,MACrB;AAAA,MAAC;AAAA;AAAA,QAA+B;AAAA,QAAc,OAAO,OAAO,MAAM,OAAO;AAAA,QACvE;AAAA,QAAc;AAAA,QAAQ;AAAA;AAAA,MADP,MAAM;AAAA,IACmB,CAC3C,GACH;AAAA,KACF;AAGF,MAAI,cAAc,QAAW;AAC3B,WACE,8CAAC,SAAI,WAAU,mBACb,yDAAC,SAAI,WAAU,iBACZ;AAAA,eAAS,8CAAC,SAAI,WAAU,cAAc,aAAG,aAAY;AAAA,MACrD;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,EAAE,OAAO,YAAY,GAAG,OAAO,UAAU,MAAM,OAAO;AAAA,UAChE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,MAAM,yBAAyB,IAAI;AAAA,UAC3C,QAAQ,MAAM,yBAAyB,UAAU,MAAM,KAAK,IAAI,GAAG,YAAY,CAAC,CAAC,EAAG,aAAa;AAAA,UACjG,QAAQ,MAAM;AAAA,YACZ,UAAU,MAAM,KAAK,IAAI,UAAU,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,EAAG;AAAA,UACxE;AAAA;AAAA,MACF;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,QAAM,YAAY,MAAM,KAAK,EAAE,SAAS;AACxC,QAAM,gBAAgB,YAAY,UAAU,MAAM,OAAO,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC;AAE3F,SACE,+CAAC,SAAI,WAAU,mBACb;AAAA,mDAAC,SAAI,WAAU,iBACZ;AAAA,eAAS,8CAAC,SAAI,WAAU,cAAc,aAAG,aAAY;AAAA,MAErD,CAAC,aAAa;AAAA,MAEf;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,OAAO,GAAG;AAAA,UACV,aAAW;AAAA,UACX,aAAa,GAAG;AAAA,UAChB,OAAO;AAAA,UACP,UAAU;AAAA,UACV,YAAY,GAAG;AAAA;AAAA,MACjB;AAAA,MAEC,YACC,cAAc,WAAW,IACvB,8CAAC,SAAI,WAAU,oBAAoB,aAAG,iBAAgB,IAEtD,+EACG,wBAAc,IAAI,CAAC,UAClB,+CAAC,SAA8B,WAAU,2BACvC;AAAA,uDAAC,SAAI,WAAU,2BACb;AAAA,wDAACC,QAAA,EAAM,KAAK,MAAM,wBAAwB,QAAW,MAAM,MAAM,iBAAiB,MAAK,QAAO;AAAA,UAC9F,+CAAC,UAAK,WAAU,gCACb;AAAA,kBAAM;AAAA,aACL,WAAW,MAAM,eAAe,KAAK,KAAK,KAAK,MAAM,qBACnD,+CAAC,UAAK,WAAU,2BAA0B;AAAA;AAAA,cAAG,MAAM;AAAA,cAAmB;AAAA,eAAC,IACvE;AAAA,aACN;AAAA,WACF;AAAA,QACC,iBAAiB,OAAO,KAAK,EAAE,IAAI,CAAC,UACnC;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,UAAU;AAAA,YACV,WAAU;AAAA,YACV,SAAS,MAAM,yBAAyB,MAAM,aAAa;AAAA,YAC3D,WAAW,CAAC,MAAM;AAChB,kBAAI,EAAE,WAAW,EAAE,cAAe;AAClC,kBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,kBAAE,eAAe;AACjB,yCAAyB,MAAM,aAAa;AAAA,cAC9C;AAAA,YACF;AAAA,YAEA,wDAAC,cAAW,OAAc,OAAO,OAAO,MAAM,OAAO,GAAG,OAAc,IAAQ,SAAkB;AAAA;AAAA,UAb3F,MAAM;AAAA,QAcb,CACD;AAAA,WA3BO,MAAM,aA4BhB,CACD,GACH,IAGF,gFACE;AAAA,uDAAC,SAAI,WAAU,kBACZ;AAAA,oBAAU,WAAW,GAAG,cAAc,GAAG;AAAA,UACzC,CAAC,UAAU,YAAY,8CAAC,UAAK,WAAU,sBAAsB,aAAG,eAAc;AAAA,WACjF;AAAA,QACA,+CAAC,SAAI,WAAU,yBACZ;AAAA,0BAAgB,IAAI,CAAC,UACpB;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL,eAAe,cAAc,OAAO,UAAU,mBAAmB;AAAA,cACjE,eAAe,WAAW,MAAM,eAAe,KAAK,KAAK;AAAA,cACzD,QAAQ,MAAM,yBAAyB,MAAM,aAAa;AAAA,cAC1D,SAAS;AAAA,cACT;AAAA,cACA;AAAA;AAAA,YAVK,MAAM;AAAA,UAWb,CACD;AAAA,UACA,gBAAgB,SAAS,KACxB,8CAAC,SAAI,WAAU,oBACZ,0BAAgB,IAAI,CAAC,UACpB;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA,eAAe,cAAc,OAAO,UAAU,mBAAmB;AAAA,cACjE,eAAe,WAAW,MAAM,eAAe,KAAK,KAAK;AAAA,cACzD,QAAQ,MAAM,yBAAyB,MAAM,aAAa;AAAA,cAC1D,SAAS;AAAA,cACT;AAAA;AAAA,YANK,MAAM;AAAA,UAOb,CACD,GACH;AAAA,WAEJ;AAAA,QAEA,8CAAC,SAAI,WAAU,kBAAkB,aAAG,YAAW;AAAA,QAC/C,8CAAC,SAAI,WAAU,oBACZ,oBAAU,OAAO,IAAI,CAAC,UACrB;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA,eAAe,cAAc,OAAO,UAAU,mBAAmB;AAAA,YACjE,eAAe,WAAW,MAAM,eAAe,KAAK,KAAK;AAAA,YACzD,QAAQ,MAAM,yBAAyB,MAAM,aAAa;AAAA,YAC1D,SAAS;AAAA,YACT;AAAA;AAAA,UANK,MAAM;AAAA,QAOb,CACD,GACH;AAAA,SACF;AAAA,OAEJ;AAAA,IAEC,UAAU,QACT,8CAAC,OAAE,WAAU,oBAAmB,MAAK,UAAS,aAAU,UACrD,oBAAU,YAAY,GAAG,eAAe,GAAG,gBAC9C;AAAA,KAEJ;AAEJ;;;AUxRA,IAAAC,iBAAoC;;;ACM5B,IAAAC,uBAAA;AAJD,SAAS,eAAe,EAAE,GAAG,GAAkC;AACpE,SACE,8CAAC,SAAI,WAAU,iBACb,wDAAC,SAAI,WAAU,mBACb,wDAAC,OAAG,aAAG,oBAAmB,GAC5B,GACF;AAEJ;;;ACVA,IAAAC,iBAAoC;;;ACApC,SAAS,eAAe,QAAwB;AAC9C,SAAO,OAAO,MAAM,GAAG,EAAE,IAAI,OAAM,IAAI,EAAE,CAAC,EAAG,YAAY,IAAI,EAAE,MAAM,CAAC,IAAI,CAAE,EAAE,KAAK,GAAG;AACxF;AAIO,SAAS,UAAU,GAA8C,QAAwC;AAC9G,SAAO,EAAE,SAAS,OAAO,EAAE,MAAM,KAAK,eAAe,EAAE,MAAM;AAC/D;AAGO,SAAS,UAAU,MAA+C;AACvE,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACrD,MAAI,MAAM,UAAU,EAAG,QAAO,EAAE,OAAO,IAAI,MAAM,MAAM,CAAC,KAAK,GAAG;AAChE,SAAO,EAAE,OAAO,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,GAAG,MAAM,MAAM,MAAM,SAAS,CAAC,EAAG;AAC/E;;;ACbI,IAAAC,uBAAA;AAFG,SAAS,YAAY,EAAE,OAAO,GAAoC;AACvE,SACE,8CAAC,SAAI,WAAU,YAAW,SAAQ,cAAa,eAAY,QAAQ,cAAI,MAAM,KAAK,IAAI,SAAQ;AAElG;AAEA,IAAM,OAAO,CAAC,IAAY,IAAY,GAAW,MAAM,kBACrD,+CAAC,OAAE,WAAW,KAAK;AAAA,gDAAC,YAAO,IAAQ,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,MAAM;AAAA,EAAE,8CAAC,UAAK,GAAG,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK;AAAA,GAAE;AAG9L,IAAM,MAAmC;AAAA,EACvC,iBAAiB,gFAAG;AAAA,SAAK,IAAI,IAAI,IAAI,aAAa;AAAA,IAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,WAAU,cAAa,YAAW,UAAS,eAAC;AAAA,KAAO;AAAA,EAC3H,mBAAmB,gFAAG;AAAA,SAAK,IAAI,IAAI,EAAE;AAAA,IAAG,KAAK,IAAI,IAAI,EAAE;AAAA,IAAE,8CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,WAAU,mBAAkB;AAAA,IAAE,8CAAC,UAAK,GAAE,gCAA+B,WAAU,gBAAe;AAAA,KAAE;AAAA,EACxL,gBAAgB,gFAAE;AAAA,kDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,OAAM,QAAO,MAAK,IAAG,KAAI,WAAU,kBAAiB;AAAA,IAAG,CAAC,CAAC,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,8CAAC,YAAe,IAAI,GAAa,IAAI,GAAa,GAAE,KAAI,WAAW,IAAI,oBAAoB,kBAA9E,CAA8F,CAAE;AAAA,KAAE;AAAA,EAC1V,cAAc,+EAAG,WAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,8CAAC,UAAa,GAAM,GAAM,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,WAAW,MAAM,IAAI,qBAAqB,oBAAvF,CAAyG,CAAE,GAAE;AAAA,EACnM,eAAe,gFAAE;AAAA,kDAAC,UAAK,GAAE,+CAA8C,WAAU,eAAc;AAAA,IAAE,8CAAC,UAAK,GAAE,oBAAmB,WAAU,iBAAgB;AAAA,IAAE,8CAAC,UAAK,GAAE,+CAA8C,WAAU,eAAc;AAAA,IAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,WAAU,iBAAgB;AAAA,IAAE,8CAAC,UAAK,GAAE,OAAM,GAAE,MAAK,WAAU,cAAa,YAAW,UAAS,eAAC;AAAA,KAAO;AAAA,EAC9X,iBAAiB,+EAAG,WAAC,GAAG,GAAG,CAAC,EAAE,QAAQ,OAAK,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,OAAK,8CAAC,UAAsB,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,YAAY,IAAI,KAAK,MAAM,IAAI,oBAAoB,oBAA7H,GAAG,CAAC,GAAG,CAAC,EAAuI,CAAE,CAAC,GAAE;AAAA,EAC7N,sBAAsB,gFAAE;AAAA,kDAAC,UAAK,GAAE,6CAA4C,WAAU,eAAc;AAAA,IAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,WAAU,0BAAyB;AAAA,IAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,WAAU,iBAAgB;AAAA,IAAE,8CAAC,UAAK,GAAE,6CAA4C,WAAU,eAAc;AAAA,KAAE;AAAA,EACzV,eAAe,gFAAE;AAAA,kDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,OAAM,QAAO,MAAK,IAAG,KAAI,WAAU,kBAAiB;AAAA,IAAG,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,8CAAC,YAAe,IAAI,GAAG,IAAI,GAAG,GAAE,KAAI,WAAW,IAAI,IAAI,oBAAoB,mBAA9D,CAA+E,CAAE;AAAA,KAAE;AAAA,EACxT,eAAe,+EAAG,WAAC,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,8CAAC,UAAa,GAAE,MAAK,GAAM,OAAO,GAAG,QAAO,MAAK,IAAG,KAAI,WAAW,MAAM,IAAI,oBAAoB,oBAAtF,CAAwG,CAAE,GAAE;AAAA,EAC3L,YAAY,gFAAE;AAAA,kDAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,WAAU,0BAAyB;AAAA,IAAG,KAAK,IAAI,IAAI,EAAE;AAAA,IAAE,8CAAC,UAAK,GAAE,yEAAwE,WAAU,mBAAkB;AAAA,KAAE;AAAA,EAClN,SAAS,8CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,WAAU,eAAc;AAClE;;;ACdI,IAAAC,uBAAA;AAJG,SAAS,KAAK,EAAE,UAAU,WAAW,MAAM,UAAU,UAAU,GAEtD;AACd,SACE,+CAAC,UAAK,WAAW,wBAAwB,OAAO,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE,IAChF;AAAA;AAAA,IAAM;AAAA,KACT;AAEJ;AAEO,SAAS,UAAU,EAAE,OAAO,MAAM,GAAqD;AAC5F,SACE,+CAAC,UAAK,WAAU,kBACd;AAAA,kDAAC,UAAK,WAAU,oBAAoB,iBAAM;AAAA,IAC1C,8CAAC,UAAK,WAAU,oBAAoB,iBAAM;AAAA,KAC5C;AAEJ;;;ACiBI,IAAAC,uBAAA;AA5BG,SAAS,WAAW,MAAmB,IAAgD;AAC5F,UAAQ,KAAK,QAAQ;AAAA,IACnB,KAAK;AAAU,aAAO,EAAE,MAAM,GAAG,YAAY,MAAM,QAAQ;AAAA,IAC3D,KAAK;AAAU,aAAO,EAAE,MAAM,GAAG,YAAY,MAAM,QAAQ;AAAA,IAC3D,KAAK;AAAe,aAAO,EAAE,MAAM,GAAG,MAAM,QAAQ,MAAM,SAAS;AAAA,IACnE,KAAK;AAAA,IACL,KAAK;AACH,aAAO,KAAK,SACR,EAAE,MAAM,GAAG,MAAM,cAAc,KAAK,SAAS,CAAC,GAAG,MAAM,UAAU,IACjE,EAAE,MAAM,GAAG,MAAM,MAAM,MAAM,UAAU;AAAA,IAC7C;AACE,UAAI,KAAK,SAAS,aAAa,KAAK,aAAa,IAAI,KAAK,KAAK,SAAS,EAAE,QAAQ,IAAI,KAAK,IAAI,GAAG;AAChG,eAAO,EAAE,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,cAAc,KAAK,SAAS,CAAC,GAAG,MAAM,SAAS;AAAA,MAC1F;AACA,aAAO,EAAE,MAAM,GAAG,MAAM,SAAS,KAAK,MAAM,KAAK,GAAG,UAAU,MAAM,MAAM;AAAA,EAC9E;AACF;AAEA,IAAM,WAAW,oBAAI,IAA2B,CAAC,UAAU,QAAQ,CAAC;AAE7D,SAAS,SAAS,EAAE,MAAM,QAAQ,IAAI,UAAU,OAAO,GAE9C;AACd,QAAM,SAAS,WAAW,MAAM,EAAE;AAClC,QAAM,WAAW,SAAS,IAAI,KAAK,MAAM;AACzC,QAAM,QAAQ,UAAU,MAAM,GAAG,MAAM,MAAM;AAE7C,QAAM,OAAO,YAAY,SACvB,gFACE;AAAA,mDAAC,UAAK,WAAU,kBACd;AAAA,oDAAC,UAAK,WAAU,qBAAqB,aAAG,MAAM,gBAAe;AAAA,MAC5D,OAAO,SAAS,SAAS,8CAAC,QAAK,SAAQ,SAAS,aAAG,MAAM,UAAS;AAAA,MACnE,8CAAC,UAAK,WAAU,mBAAmB,iBAAM;AAAA,MACzC,8CAAC,UAAK,WAAU,iBAAiB,aAAG,MAAM,SAAS,KAAK,MAAM,KAAK,IAAG;AAAA,MACrE,OAAO,SAAS,YACb,8CAAC,UAAK,WAAU,oBAAmB,aAAU,WAAW,iBAAO,MAAK,IACpE,+CAAC,UAAK,WAAU,iBAAiB;AAAA,eAAO,SAAS,WAAW,GAAG,MAAM,SAAS,GAAG,MAAM;AAAA,QAAQ;AAAA,SAAE;AAAA,OACvG;AAAA,IACA,8CAAC,UAAK,WAAU,iBAAgB,wDAAC,eAAY,QAAQ,KAAK,QAAQ,GAAE;AAAA,KACtE,IACE,YAAY,SACd,gFACE;AAAA,kDAAC,UAAK,WAAU,iBAAgB,wDAAC,eAAY,QAAQ,KAAK,QAAQ,GAAE;AAAA,IACpE,+CAAC,UAAK,WAAU,kBACd;AAAA,oDAAC,UAAK,WAAU,mBAAmB,iBAAM;AAAA,MACzC,8CAAC,UAAK,WAAU,oBAAmB,aAAW,OAAO,MAAO,iBAAO,MAAK;AAAA,MACvE,OAAO,SAAS,SAAS,8CAAC,QAAK,SAAQ,SAAS,aAAG,MAAM,UAAS;AAAA,OACrE;AAAA,IACA,8CAAC,UAAK,WAAU,kBAAiB,wDAAC,mBAAgB,MAAM,IAAI,GAAE;AAAA,KAChE,IAEA,gFACE;AAAA,kDAAC,UAAK,WAAU,iBAAgB,wDAAC,eAAY,QAAQ,KAAK,QAAQ,GAAE;AAAA,IACpE,8CAAC,UAAK,WAAU,mBAAmB,iBAAM;AAAA,IACzC,8CAAC,UAAK,WAAU,oBAAmB,aAAW,OAAO,MAAO,iBAAO,MAAK;AAAA,KAC1E;AAGF,QAAM,MAAM,wBAAwB,OAAO;AAC3C,MAAI,SAAU,QAAO,8CAAC,SAAI,WAAW,KAAK,iBAAa,MAAC,iBAAc,QAAQ,gBAAK;AACnF,SAAO,8CAAC,YAAO,MAAK,UAAS,WAAW,KAAK,cAAY,GAAG,KAAK,WAAM,OAAO,IAAI,IAAI,SAAS,MAAM,OAAO,IAAI,GAAI,gBAAK;AAC3H;;;AJxBmC,IAAAC,uBAAA;AAxCnC,IAAM,WAAW,oBAAI,IAA2B,CAAC,aAAa,aAAa,CAAC;AAC5E,IAAM,OAAO,oBAAI,IAA2B,CAAC,UAAU,QAAQ,CAAC;AAEzD,SAAS,aAAa,OAA0C;AACrE,QAAM,QAAQ,MAAM,OAAO,OAAK,EAAE,SAAS,OAAO;AAClD,QAAM,QAAQ,MAAM,KAAK,OAAK,EAAE,WAAW,eAAe;AAC1D,MAAI,SAAS,SAAS,IAAI,MAAM,MAAM,EAAG,QAAO;AAChD,QAAM,gBAAgB,MAAM,KAAK,OAAK,SAAS,IAAI,EAAE,MAAM,CAAC;AAC5D,MAAI,cAAe,QAAO;AAC1B,SAAO,SAAS,MAAM,CAAC,KAAK;AAC9B;AAGO,IAAM,UAAU,CAAC,MAA2B,GAAG,EAAE,MAAM,IAAI,EAAE,OAAO,IAAI,EAAE,SAAS;AAEnF,SAAS,SAAS,EAAE,OAAO,aAAa,aAAa,QAAQ,GAAG,GAMvD;AACd,QAAM,CAAC,EAAE,OAAO,QAAI,yBAAS,CAAC;AAC9B,gCAAU,MAAM;AACd,UAAM,KAAK,YAAY,MAAM,QAAQ,OAAK,IAAI,CAAC,GAAG,GAAM;AACxD,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,aAAa,KAAK;AAC/B,QAAM,QAAQ,MAAM,OAAO,OAAK,EAAE,SAAS,WAAW,MAAM,IAAI;AAChE,QAAM,OAAO,MAAM,OAAO,OAAK,EAAE,WAAW,eAAe;AAC3D,QAAM,OAAO,MAAM,KAAK,OAAK,EAAE,WAAW,eAAe;AACzD,QAAM,WAAW,MAAM,OAAO,OAAK,EAAE,SAAS,SAAS;AACvD,QAAM,WAAW,SAAS,IAAI,OAAK,EAAE,UAAU,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC,EAAE,KAAK;AACtF,QAAM,WAAW,MAAM,OAAO,OAAK,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,SAAS,IAAI,CAAC;AAC7F,QAAM,OAAO;AAEb,SACE,+CAAC,SAAI,WAAU,YACb;AAAA,mDAAC,SAAI,WAAU,cACb;AAAA,qDAAC,SAAI,WAAU,aAAY;AAAA,sDAAC,UAAK,WAAU,eAAe,aAAG,MAAM,YAAW;AAAA,QAC5E,+CAAC,UAAK,WAAU,eAAc,eAAY,eACvC;AAAA,wBAAc,gFAAE;AAAA,0DAAC,aAAU;AAAA,YAAG,YAAY;AAAA,aAAc,IAAM;AAAA,UAC9D,eAAe,8CAAC,WAAO,aAAG,MAAM,UAAS;AAAA,WAC5C;AAAA,SAAO;AAAA,MACT,+CAAC,SAAI,WAAU,aAAY;AAAA,sDAAC,UAAK,WAAU,eAAe,aAAG,MAAM,WAAU;AAAA,QAC3E,+CAAC,UAAK,WAAU,mCAAkC,eAAY,cAAc;AAAA,aAAG,MAAM,UAAU,QAAQ;AAAA,UAAE,8CAAC,WAAO,aAAG,MAAM,SAAQ;AAAA,WAAQ;AAAA,SAAO;AAAA,MACnJ,+CAAC,SAAI,WAAU,aAAY;AAAA,sDAAC,UAAK,WAAU,eAAe,aAAG,MAAM,UAAS;AAAA,QAC1E,+CAAC,UAAK,WAAU,eAAc,eAAY,aAAa;AAAA,wBAAc,IAAI,YAAY,IAAI,KAAK;AAAA,UAC3F,eAAe,8CAAC,WAAO,aAAG,MAAM,UAAS;AAAA,WAAS;AAAA,SAAO;AAAA,OAChE;AAAA,IAEC,eAAe,8CAAC,QAAK,SAAQ,UAAS,WAAU,cAAc,uBAAY;AAAA,IAE1E,QAAQ,8CAAC,YAAS,MAAM,MAAM,QAAgB,IAAQ,SAAQ,QAAO;AAAA,KAEpE,KAAK,SAAS,KAAK,SACnB,+CAAC,aAAQ,WAAU,YACjB;AAAA,qDAAC,SAAI,WAAU,iBAAgB;AAAA,sDAAC,QAAI,aAAG,MAAM,YAAW;AAAA,QAAK,8CAAC,UAAM,aAAG,MAAM,kBAAiB;AAAA,SAAO;AAAA,MACpG,KAAK,SAAS,KAAK,8CAAC,SAAI,WAAU,aAAa,eAAK,IAAI,OAAK,8CAAC,YAA0B,MAAM,GAAG,QAAgB,MAArC,QAAQ,CAAC,CAAoC,CAAE,GAAE;AAAA,MAC7H,QAAQ,8CAAC,YAAS,MAAM,MAAM,QAAgB,IAAQ,SAAQ,QAAO;AAAA,OACxE;AAAA,IAGD,SAAS,SAAS,KACjB,+CAAC,aAAQ,WAAU,YACjB;AAAA,qDAAC,SAAI,WAAU,iBAAgB;AAAA,sDAAC,QAAI,aAAG,MAAM,eAAc;AAAA,QACxD,SAAS,CAAC,KAAK,8CAAC,UAAM,aAAG,MAAM,UAAU,GAAG,MAAM,cAAc,SAAS,CAAC,CAAC,CAAC,GAAE;AAAA,SAAQ;AAAA,MACzF,8CAAC,SAAI,WAAU,aAAa,mBAAS,IAAI,OAAK,8CAAC,YAA0B,MAAM,GAAG,QAAgB,MAArC,QAAQ,CAAC,CAAoC,CAAE,GAAE;AAAA,OAChH;AAAA,KAEJ;AAEJ;;;AKhFA,IAAAC,iBAA4C;;;ACA5C,IAAAC,iBAA8C;AA2B9C,SAAS,eAAe,SAA8C;AACpE,SAAO;AAAA;AAAA,IAEL,eAAe,QAAQ,WAAW,YAAY,QAAQ,WAAW,YAAY,QAAQ,WAAW;AAAA,IAChG,OAAO,QAAQ;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,IACzB,cAAc,QAAQ;AAAA,EACxB;AACF;AAEO,SAAS,YACd,cACA,EAAE,QAAQ,SAAS,WAAW,QAAQ,QAAQ,GAC3B;AACnB,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAkC,IAAI;AAClE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAClD,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAwB,IAAI;AAE9D,QAAM,kBAAc,uBAAO,KAAK;AAChC,QAAM,cAAU,uBAAO,YAAY;AACnC,UAAQ,UAAU;AAClB,QAAM,cAAU,uBAAO,EAAE,QAAQ,SAAS,WAAW,QAAQ,QAAQ,CAAC;AACtE,UAAQ,UAAU,EAAE,QAAQ,SAAS,WAAW,QAAQ,QAAQ;AAGhE,QAAM,gBAAY,uBAAgC,IAAI;AACtD,YAAU,UAAU;AAEpB,QAAM,cAAU,4BAAY,YAA2B;AACrD,UAAM,OAAO,QAAQ;AACrB,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,QAAQ;AACrB,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,cAAc,KAAK,QAAQ,KAAK,WAAW,KAAK,SAAS,KAAK,MAAM;AAC/F,UAAI,YAAY,KAAM;AAItB,UAAI,QAAQ,mBAAmB,QAAQ,UAAU,SAAS,mBAAmB,MAAM;AACjF,qBAAa,QAAQ,MAAM;AAC3B;AAAA,MACF;AACA,gBAAU,eAAe,OAAO,CAAC;AACjC,mBAAa,QAAQ,MAAM;AAAA,IAC7B,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,aAAS,4BAAY,OAAO,eAAsC;AACtE,UAAM,OAAO,QAAQ;AACrB,QAAI,CAAC,QAAQ,YAAY,QAAS;AAClC,gBAAY,UAAU;AACtB,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,OAAO,QAAQ;AACrB,YAAM,aAAa,MAAM,KAAK,SAAS,KAAK,QAAQ,YAAY,KAAK,SAAS,KAAK,WAAW,KAAK,MAAM;AACzG,UAAI,eAAe,MAAM;AAIvB,cAAM,gBAAgB,WAAW,mBAAmB;AACpD,cAAMC,cAAa,WAAW,kBAAkB;AAChD,cAAM,aAAa,UAAU,SAAS,mBAAmB;AACzD,YAAI,CAAC,iBAAiB,CAACA,eAAc,YAAY;AAC/C,gBAAM,QAAQ;AAAA,QAChB,OAAO;AACL,oBAAU,UAAU;AAAA,QACtB;AACA,YAAI,WAAW,eAAe,MAAM;AAClC,eAAK,UAAU;AAAA,QACjB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER,UAAE;AACA,kBAAY,UAAU;AACtB,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,cAAU,4BAAY,MAAY;AACtC,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,OAAO,CAAC;AAEZ,SAAO,EAAE,QAAQ,YAAY,QAAQ,SAAS,UAAU;AAC1D;;;AClHA,IAAAC,iBAAgC;;;ACIhC,IAAM,QAAgC;AAAA;AAAA,EAEpC,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,SAAS;AAAA,EACT,kBAAkB;AAAA;AAAA,EAGlB,QAAQ;AAAA,EAAQ,OAAO;AAAA,EAAQ,UAAU;AAAA,EAAQ,SAAS;AAAA,EAAQ,OAAO;AAAA,EACzE,aAAa;AAAA,EAAQ,SAAS;AAAA,EAAQ,aAAa;AAAA,EAAQ,SAAS;AAAA,EACpE,YAAY;AAAA,EAAQ,OAAO;AAAA,EAAQ,QAAQ;AAAA,EAC3C,SAAS;AAAA,EAAQ,eAAe;AAAA,EAAQ,cAAc;AAAA,EAAQ,QAAQ;AAAA;AAAA,EAGtE,SAAS;AAAA,EAAQ,QAAQ;AAAA,EAAQ,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA;AAAA,EAG3E,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,kBAAkB;AAAA,EAAQ,SAAS;AAAA,EACpE,QAAQ;AAAA,EAAQ,0BAA0B;AAAA,EAAQ,QAAQ;AAAA,EAC1D,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA,EAAQ,QAAQ;AAAA,EAC1D,SAAS;AAAA,EAAQ,UAAU;AAAA,EAAQ,UAAU;AAAA,EAAQ,UAAU;AAAA,EAC/D,WAAW;AAAA,EAAQ,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA;AAAA,EAG9E,QAAQ;AAAA,EAAQ,cAAS;AAAA,EAAQ,SAAS;AAAA,EAAQ,mBAAmB;AAAA,EACrE,QAAQ;AAAA,EAAQ,YAAY;AAAA;AAAA,EAG5B,SAAS;AAAA,EAAQ,SAAS;AAAA,EAAQ,YAAY;AAAA,EAC9C,YAAY;AAAA,EAAQ,YAAY;AAAA,EAAQ,YAAY;AAAA,EACpD,YAAY;AAAA,EAAQ,cAAc;AAAA;AAAA,EAGlC,QAAQ;AAAA,EAAQ,WAAW;AAAA,EAAQ,SAAS;AAAA,EAAQ,UAAU;AAAA,EAAQ,OAAO;AAAA,EAC7E,MAAM;AAAA,EAAQ,SAAS;AAAA,EAAQ,UAAU;AAAA,EAAQ,WAAW;AAAA,EAAQ,SAAS;AAAA,EAC7E,QAAQ;AAAA,EAAQ,UAAU;AAAA;AAAA,EAG1B,QAAQ;AAAA,EAAQ,iBAAiB;AAAA,EAAQ,KAAK;AAAA,EAAQ,QAAQ;AAAA,EAC9D,cAAc;AAAA,EAAQ,QAAQ;AAAA,EAAQ,UAAU;AAAA,EAAQ,eAAe;AAAA,EACvE,WAAW;AAAA,EAAQ,WAAW;AAAA;AAAA,EAG9B,SAAS;AAAA,EAAQ,MAAM;AAAA,EAAQ,OAAO;AAAA,EAAQ,sBAAsB;AAAA,EACpE,uBAAuB;AAAA,EAAQ,UAAU;AAAA,EACzC,cAAW;AAAA,EAAQ,SAAS;AAAA,EAC5B,UAAU;AAAA;AAAA,EAGV,SAAS;AAAA,EAAQ,OAAO;AAAA,EAAQ,SAAS;AAAA,EACzC,YAAY;AAAA,EAAQ,iBAAiB;AAAA,EAAQ,oBAAiB;AAAA,EAAQ,eAAe;AAAA,EACrF,UAAU;AAAA,EAAQ,MAAM;AAAA,EAAQ,QAAQ;AAAA,EAAQ,iBAAiB;AAAA,EACjE,gBAAgB;AAAA,EAAQ,SAAS;AAAA,EAAQ,cAAc;AAAA,EAAQ,UAAU;AAAA,EACzE,YAAY;AAAA,EAAQ,MAAM;AAAA,EAAQ,OAAO;AAAA,EAAQ,gBAAgB;AAAA,EAAQ,OAAO;AAAA;AAAA,EAGhF,YAAY;AAAA,EAAQ,oCAAoC;AAAA,EAAQ,YAAY;AAAA,EAC5E,yBAAyB;AAAA,EAAQ,OAAO;AAAA,EAAQ,kBAAkB;AAAA,EAAQ,qBAAqB;AAAA,EAC/F,4BAA4B;AAAA,EAAQ,OAAO;AAAA,EAAQ,qBAAqB;AAAA,EACxE,gBAAgB;AAAA,EAAQ,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,UAAU;AAAA,EACnE,UAAU;AAAA,EAAQ,QAAQ;AAAA,EAAQ,QAAQ;AAAA,EAAQ,YAAY;AAAA,EAC9D,UAAU;AAAA,EAAQ,OAAO;AAAA,EAAQ,QAAQ;AAAA,EAAQ,QAAQ;AAAA,EACzD,UAAU;AAAA,EAAQ,SAAS;AAAA,EAAQ,UAAU;AAAA,EAAQ,SAAS;AAAA,EAC9D,OAAO;AAAA,EAAQ,eAAe;AAAA,EAAQ,MAAM;AAAA,EAC5C,SAAS;AAAA,EAAQ,UAAU;AAAA,EAAQ,WAAW;AAAA,EAC9C,YAAY;AAAA,EAAQ,WAAW;AAAA,EAAQ,SAAS;AAAA,EAAQ,YAAY;AAAA;AAAA,EAGpE,OAAO;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA,EAAQ,SAAS;AAAA;AAAA,EAG1D,gBAAgB;AAAA,EAAQ,MAAM;AAAA,EAAQ,MAAM;AAAA,EAAQ,SAAS;AAAA,EAC7D,OAAO;AAAA,EAAQ,QAAQ;AAAA,EAAQ,OAAO;AAAA,EAAQ,wBAAwB;AAAA,EAAQ,KAAK;AAAA,EACnF,QAAQ;AAAA,EAAQ,SAAS;AAAA,EAAQ,MAAM;AAAA,EAAQ,OAAO;AAAA,EACtD,QAAQ;AAAA,EAAQ,WAAW;AAAA;AAAA,EAG3B,OAAO;AAAA,EAAQ,eAAe;AAAA,EAAQ,OAAO;AAAA,EAAQ,OAAO;AAAA,EAC5D,OAAO;AAAA,EAAQ,UAAU;AAAA,EAAQ,WAAW;AAAA,EAAQ,UAAU;AAAA,EAC9D,aAAa;AAAA,EAAQ,SAAS;AAAA;AAAA,EAG9B,WAAW;AAAA,EAAQ,eAAe;AAAA,EAAQ,MAAM;AAClD;AAEO,SAAS,gBAAgB,aAAgD;AAC9E,MAAI,CAAC,YAAa,QAAO;AACzB,QAAM,MAAM,YAAY,KAAK,EAAE,YAAY;AAC3C,SAAO,MAAM,GAAG,KAAK,YAAY,MAAM,GAAG,CAAC,EAAE,YAAY;AAC3D;AAIO,SAAS,aAAa,MAAuB;AAClD,SAAO,eAAe,KAAK,IAAI;AACjC;;;ACtGA,IAAAC,iBAAyB;AAoCjB,IAAAC,uBAAA;AAhCD,SAAS,WAAW,MAAsB;AAC/C,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACrD,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,MAAI,MAAM,WAAW,KAAK,CAAC,KAAM,QAAO,MAAM,MAAM,GAAG,CAAC,EAAE,YAAY;AACtE,WAAS,MAAM,CAAC,KAAK,OAAO,KAAK,CAAC,KAAK,KAAK,YAAY;AAC1D;AAIO,SAAS,mBAAmB,KAAyC;AAC1E,SAAO,CAAC,CAAC,OAAO,6CAA6C,KAAK,GAAG;AACvE;AAIO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIgB;AACd,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,YAAY,QAAQ,SAAS,KAAK,CAAC,mBAAmB,SAAS,KAAK,CAAC;AAE3E,SACE,8CAAC,SAAI,WAAsB,eAAY,QACpC,sBACC,8CAAC,SAAI,KAAK,WAAW,KAAI,IAAG,SAAQ,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG,IAE3E,8CAAC,UAAK,WAAU,oBAAoB,qBAAW,IAAI,GAAE,GAEzD;AAEJ;;;AChCU,IAAAC,uBAAA;AAPH,SAAS,WAAW,EAAE,OAAO,SAAS,OAAO,QAAQ,UAAU,GAEtD;AACd,SACE,+CAAC,SAAI,WAAU,aACZ;AAAA,cACC,8CAAC,YAAO,MAAK,UAAS,WAAU,aAAY,cAAY,WAAW,SAAS,QAC1E,wDAAC,mBAAgB,GACnB;AAAA,IAEF,+CAAC,SAAI,WAAU,kBACZ;AAAA,iBAAW,8CAAC,UAAK,WAAU,gBAAgB,mBAAQ;AAAA,MACpD,8CAAC,QAAG,WAAU,cAAc,iBAAM;AAAA,OACpC;AAAA,IACC,SAAS,8CAAC,SAAI,WAAU,mBAAmB,iBAAM;AAAA,KACpD;AAEJ;;;ACTU,IAAAC,uBAAA;AAPH,SAAS,gBAAgB,EAAE,UAAU,WAAW,WAAW,YAAY,MAAM,GAEpE;AACd,SACE,+CAAC,SAAI,WAAU,iBACb;AAAA,mDAAC,SAAI,WAAU,sBACX;AAAA,oBAAa,eACb,+CAAC,SAAI,WAAU,wBACb;AAAA,sDAAC,UAAM,qBAAU;AAAA,QAAO,8CAAC,UAAK,WAAU,oBAAoB,sBAAW;AAAA,SACzE;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UAAI,WAAU;AAAA,UAAY,MAAK;AAAA,UAAM,cAAY;AAAA,UAChD,OAAO,EAAE,qBAAqB,UAAU,SAAS,MAAM,oBAAoB;AAAA,UAC1E,mBAAS,IAAI,CAAC,GAAG,MAAM,8CAAC,UAAa,WAAU,YAAW,cAAY,KAApC,CAAuC,CAAE;AAAA;AAAA,MAC9E;AAAA,OACF;AAAA,IACC;AAAA,KACH;AAEJ;;;ACLI,IAAAC,uBAAA;AAVG,SAAS,WAAW,EAAE,IAAI,OAAO,aAAa,cAAc,SAAS,OAAO,SAAS,QAAQ,UAAU,WAAW,EAAE,GAM3G;AACd,QAAM,SAAS,MAAM,KAAK,EAAE,YAAY;AACxC,QAAM,QAAQ,OAAO,SAAS,WAAW,CAAC,IAAI,SAAS,QAAQ,OAAO,OAAK,EAAE,KAAK,YAAY,EAAE,SAAS,MAAM,CAAC,IAAI;AACpH,SACE,gFACE;AAAA;AAAA,MAAC;AAAA;AAAA,QAAY;AAAA,QAAQ;AAAA,QAAc,aAAW;AAAA,QAAC;AAAA,QAA0B,OAAO;AAAA,QAC9E,UAAU;AAAA,QAAS;AAAA;AAAA,IAAoB;AAAA,IACxC,MAAM,SAAS,KAAK,8CAAC,SAAI,WAAU,aAAY,MAAK,WAAU,cAAY,cACxE,gBAAM,IAAI,OAAK;AACd,YAAM,EAAE,OAAO,KAAK,IAAI,UAAU,EAAE,IAAI;AACxC,aACE;AAAA,QAAC;AAAA;AAAA,UAAkB,MAAK;AAAA,UAAS,MAAK;AAAA,UAAS,iBAAe;AAAA,UAAO,cAAY,EAAE;AAAA,UACjF,WAAU;AAAA,UAAiB;AAAA,UAAoB,SAAS,MAAM,OAAO,EAAE,EAAE;AAAA,UACzE;AAAA,0DAAC,gBAAa,WAAU,gBAAe,MAAM,EAAE,MAAM,WAAW,EAAE,WAAW;AAAA,YAC7E,+CAAC,UAAK,WAAU,kBAAiB,eAAY,QAC1C;AAAA,uBAAS,8CAAC,UAAK,WAAU,mBAAmB,iBAAM;AAAA,cACnD,8CAAC,UAAK,WAAU,kBAAkB,gBAAK;AAAA,eACzC;AAAA;AAAA;AAAA,QANW,EAAE;AAAA,MAOf;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;;;ACpCS,IAAAC,uBAAA;AADF,SAAS,UAAU,EAAE,SAAS,GAAyC;AAC5E,SAAO,8CAAC,SAAI,WAAU,eAAe,UAAS;AAChD;;;ACAM,IAAAC,uBAAA;AAHC,SAAS,WAAW,EAAE,MAAM,UAAU,UAAU,GAAgF;AACrI,SACE,+CAAC,UAAK,WAAW,sBAAsB,OAAO,IAAI,OAAO,EAAE,OAAO,MAAM,QAAQ,KAAK,GAAG,eAAY,QAClG;AAAA,mDAAC,SAAI,OAAO,OAAO,MAAM,QAAQ,OAAO,MAAM,SAAQ,eACpD;AAAA,oDAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,MAAK,gBAAe;AAAA,MACnD,8CAAC,UAAK,GAAE,yCAAwC,MAAK,gBAAe;AAAA,OACtE;AAAA,IACC,YAAY,aAAa,8CAAC,UAAK,WAAU,cAAa,eAAC;AAAA,KAC1D;AAEJ;;;ACHS,IAAAC,uBAAA;AAHF,SAAS,WAAW,EAAE,UAAU,WAAW,QAAQ,OAAO,WAAW,OAAO,UAAU,GAAG,KAAK,GACM;AACzG,QAAM,MAAM,sBAAsB,OAAO,GAAG,QAAQ,qBAAqB,EAAE,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAC9G,SAAO,8CAAC,YAAO,MAAY,WAAW,KAAM,GAAG,MAAM;AACvD;;;ACGM,IAAAC,uBAAA;AALC,SAAS,WAAW,EAAE,MAAM,OAAO,OAAO,QAAQ,QAAQ,GAAG,GAEpD;AACd,SACE,+CAAC,SAAI,WAAU,eAAc,aAAW,MAAM,MAAK,UACjD;AAAA,kDAAC,UAAK,WAAU,qBAAqB,iBAAM;AAAA,IAC1C,UAAU,UACT,+CAAC,UAAK,WAAU,qBAAoB;AAAA,oDAAC,UAAK,WAAU,mBAAmB,iBAAM;AAAA,MAAQ,GAAG,MAAM;AAAA,OAAQ;AAAA,IAEvG,UAAU,8CAAC,UAAK,WAAU,sBAAsB,kBAAO;AAAA,IACvD,UAAU,8CAAC,cAAW,SAAQ,WAAU,SAAS,QAAS,aAAG,MAAM,aAAY;AAAA,KAClF;AAEJ;;;ACRI,IAAAC,uBAAA;AARG,SAAS,gBAAgB,EAAE,QAAQ,aAAa,GAAG,GAEnC;AACrB,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,QAAM,MAAM,OAAO,KAAK,IAAI,aAAa,OAAO,SAAS,CAAC,CAAC;AAC3D,QAAM,OAAO,OAAO,cAAc,CAAC;AACnC,MAAI,QAAQ,OAAW,QAAO;AAC9B,SACE,+CAAC,SAAI,WAAU,cAAa,eAAY,iBACtC;AAAA,kDAAC,UAAK,WAAU,kBAAkB,aAAG,MAAM,SAAS,GAAG,GAAE;AAAA,IACxD,SAAS,UAAa,SAAS,OAAO,8CAAC,UAAK,WAAU,mBAAmB,aAAG,MAAM,eAAe,IAAI,GAAE;AAAA,KAC1G;AAEJ;;;AVgII,IAAAC,uBAAA;AAjIJ,SAAS,iBAAiB,MAAiE;AACzF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,IAAM,YAAyB,CAAC,YAAY,eAAe,OAAO,eAAe,MAAM;AACvF,IAAM,eAAuC,oBAAI,IAAe,CAAC,OAAO,eAAe,MAAM,CAAC;AAE9F,IAAM,cAAc;AAEpB,SAAS,aAAa,GAAyC;AAC7D,MAAI,EAAE,YAAY,QAAS,QAAO;AAClC,MAAI,EAAE,YAAY,OAAQ,QAAO;AACjC,MAAI,EAAE,cAAc,KAAM,QAAO;AACjC,MAAI,EAAE,cAAc,OAAQ,QAAO;AACnC,SAAO;AACT;AAGA,SAAS,eAAe,GAAyC;AAC/D,MAAI,EAAE,cAAc,KAAM,QAAO;AACjC,MAAI,EAAE,cAAc,OAAQ,QAAO;AACnC,SAAO;AACT;AAIA,IAAM,iBAAyC;AAAA,EAC7C,YAAY;AAAA,EAAM,QAAQ;AAAA,EAC1B,UAAU;AAAA,EAAO,eAAe;AAAA,EAAM,eAAe;AAAA,EAAM,eAAe;AAAA,EAAM,eAAe;AAAA,EAC/F,aAAa;AAAA,EAAM,cAAc;AAAA,EAAM,kBAAkB;AAAA,EAAO,mBAAmB;AAAA,EAAO,SAAS;AAAA,EACnG,YAAY;AAAA,EAAO,sBAAsB;AAAA,EAAM,oBAAoB;AAAA,EAAM,mBAAmB;AAAA,EAC5F,sBAAsB;AAAA,EAAM,iBAAiB;AAAA,EAAM,kBAAkB;AAAA,EACrE,aAAa;AAAA,EAAM,cAAc;AAAA,EAAM,eAAe;AAAA,EAAM,gBAAgB;AAAA,EAC5E,SAAS;AAAA,EAAO,UAAU;AAAA,EAAO,SAAS;AAAA,EAAM,kBAAkB;AAAA,EAClE,kBAAkB;AAAA,EAAM,kBAAkB;AAAA,EAAM,kBAAkB;AACpE;AAEA,SAAS,cAAc,OAAuB;AAC5C,QAAM,SAAS,eAAe,MAAM,KAAK,EAAE,YAAY,CAAC;AACxD,MAAI,OAAQ,QAAO;AACnB,MAAI,MAAM,UAAU,EAAG,QAAO,MAAM,YAAY;AAChD,SAAO,MAAM,MAAM,QAAQ,EAAE,OAAO,OAAO,EAAE,IAAI,QAAM,EAAE,CAAC,KAAK,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,CAAC;AACvG;AAIA,SAAS,SAAS,KAAgB,GAAyC;AACzE,MAAI,CAAC,EAAE,MAAO,QAAO,aAAa,CAAC;AACnC,MAAI,QAAQ,cAAe,QAAO,gBAAgB,EAAE,KAAK;AACzD,MAAI,QAAQ,WAAY,QAAO,cAAc,EAAE,KAAK;AACpD,SAAO,EAAE;AACX;AAOO,SAAS,sBAAsB,SAAoC,MAAqC;AAC7G,SAAO,KAAK,IAAI,CAAC,QAAwB;AACvC,UAAM,QAAQ,QAAQ,KAAK,OAAK,EAAE,GAAG,EAAE,YAAY,OAAO;AAC1D,QAAI,MAAO,QAAO,EAAE,KAAK,OAAO,SAAS,MAAM,SAAS,KAAK,MAAM,GAAG,CAAC,EAAE;AACzE,QAAI,CAAC,aAAa,IAAI,GAAG,EAAG,QAAO,EAAE,KAAK,OAAO,WAAW,MAAM,IAAI;AACtE,QAAI,QAAuB;AAC3B,QAAI,UAAyB;AAC7B,eAAW,KAAK,SAAS;AACvB,YAAM,IAAI,EAAE,GAAG;AACf,UAAI,CAAC,EAAE,SAAS,CAAC,EAAE,UAAW;AAC9B,YAAM,IAAI,OAAO,EAAE,KAAK;AACxB,UAAI,CAAC,OAAO,SAAS,CAAC,EAAG;AACzB,UAAI,EAAE,cAAc,KAAM,SAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,OAAO,CAAC;AAAA,UACnE,WAAU,YAAY,OAAO,IAAI,KAAK,IAAI,SAAS,CAAC;AAAA,IAC3D;AACA,QAAI,UAAU,QAAQ,YAAY,MAAM;AACtC,YAAM,KAAK,QAAQ;AACnB,YAAM,KAAK,UAAU;AACrB,aAAO,EAAE,KAAK,OAAO,SAAS,MAAM,MAAM,KAAK,OAAO,EAAE,IAAI,GAAG,EAAE,SAAI,EAAE,GAAG;AAAA,IAC5E;AACA,QAAI,YAAY,KAAM,QAAO,EAAE,KAAK,OAAO,SAAS,MAAM,KAAK,OAAO,GAAG;AACzE,QAAI,UAAU,KAAM,QAAO,EAAE,KAAK,OAAO,SAAS,MAAM,KAAK,KAAK,GAAG;AACrE,WAAO,EAAE,KAAK,OAAO,WAAW,MAAM,IAAI;AAAA,EAC5C,CAAC;AACH;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqD;AACnD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,cAAU,sBAAM;AAEtB,QAAM,cAAc,iBAAiB,QAAQ,eAAe;AAC5D,QAAM,eAAe,aAAa,gBAAgB,CAAC;AACnD,QAAM,oBAAoB,IAAI,IAAY,aAAa,IAAI,OAAK,EAAE,QAAQ,CAAC;AAC3E,QAAM,eAAe,QAAQ,oBAAoB,aAAa,oBAAoB;AAClF,QAAM,OAAO,UAAU,OAAO,OAAK,MAAM,iBAAiB,YAAY;AAEtE,QAAM,SACJ,QAAQ,kBAAkB,QAC1B,aAAa,WAAW,QACxB,aAAa,WAAW;AAE1B,QAAM,cAAc,aAAa,eAAe,aAAa;AAC7D,QAAM,eAAe,cAAc,YAAY,cAAc,YAAY,mBAAmB;AAC5F,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,aAAa,SAAS,aAAa,qBAAqB;AAE9D,QAAM,OAAO,UAAU,CAAC,SAAS,OAAO,aAAa,OAAO,OAAK,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;AAElG,WAAS,aAAa,UAAkB;AACtC,QAAI,CAAC,UAAU,UAAU,WAAY;AACrC,UAAM,cAAc,aAAa,IAAI,OAAK,EAAE,QAAQ;AACpD,UAAM,aAAa,CAAC,GAAG,aAAa,QAAQ;AAC5C,aAAS,EAAE;AACX,aAAS,KAAK,UAAU,EAAE,SAAS,WAAW,CAAC,CAAC;AAAA,EAClD;AAEA,QAAM,cAAc,CAAC,SAAS,SAAY,SACxC,+CAAC,QAAK,SAAQ,UAAU;AAAA;AAAA,IAAM;AAAA,IAAE,GAAG,MAAM;AAAA,KAAQ,IAEjD,8CAAC,UAAK,eAAY,WAChB,yDAAC,QAAM;AAAA,OAAG,MAAM;AAAA,IAAM;AAAA,IAAC,8CAAC,UAAK,WAAU,YAAY,wBAAc,GAAE;AAAA,IAAO;AAAA,IAAI;AAAA,KAAa,GAC7F;AAGF,QAAM,WAA2B,MAAM,KAAK,EAAE,QAAQ,aAAa,GAAG,CAAC,GAAG,MACxE,IAAI,cAAc,SAAS,MAAM,cAAc,YAAY,MAAM;AACnE,QAAM,OAAO,EAAE,qBAAqB,yBAAyB,KAAK,MAAM,UAAU;AAClF,QAAM,QAAQ,sBAAsB,cAAc,IAAI;AAEtD,SACE,+CAAC,SAAI,WAAU,uBAAsB,aAAU,iBAAgB,eAAY,6BACzE;AAAA;AAAA,MAAC;AAAA;AAAA,QAAW,OAAO,UAAU,EAAE,QAAQ,gBAAgB,GAAG,GAAG,MAAM,MAAM;AAAA,QAAG,SAAS,EAAE;AAAA,QAAS,OAAO;AAAA,QACrG;AAAA,QAAgB,WAAW,GAAG;AAAA;AAAA,IAAM;AAAA,IAErC,CAAC,UAAU,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,IAErE,UACC,gFACE;AAAA,qDAAC,SAAI,WAAU,aACZ;AAAA,SAAC,UAAU,8CAAC,mBAAgB,QAAQ,OAAO,cAAc,aAA0B,IAAQ;AAAA,QAC5F,+CAAC,SAAI,WAAW,eAAe,SAAS,0BAA0B,EAAE,IAClE;AAAA,yDAAC,SAAI,WAAU,oBACZ;AAAA,yBACC,8CAAC,gBAAa,WAAU,iBAAgB,MAAM,YAAY,WAAW,aAAa,yBAAyB,IAE3G,8CAAC,cAAW,MAAM,KAAK,SAAQ,WAAU;AAAA,YAE1C,cAAc,8CAAC,UAAK,WAAU,uBAAuB,sBAAW;AAAA,aACnE;AAAA,UACA,8CAAC,SAAI,WAAU,iBAAgB,OAAO,EAAE,qBAAqB,UAAU,KAAK,MAAM,oBAAoB,GACnG,gBAAM,IAAI,OACT,+CAAC,SAAgB,WAAU,sBACzB;AAAA,0DAAC,UAAK,WAAU,eAAe,YAAE,OAAO,EAAE,GAAG,GAAE;AAAA,YAC/C,8CAAC,UAAK,WAAU,mBAAkB,cAAY,EAAE,OAAO,eAAa,SAAS,EAAE,GAAG,IAAK,YAAE,MAAK;AAAA,eAFtF,EAAE,GAGZ,CACD,GACH;AAAA,WACF;AAAA,QAEC,CAAC,UAAU,8CAAC,mBAAgB,UAAoB,WAAW,EAAE,SAAS,aAAa,YAAY,GAAG;AAAA,QAElG,aAAa,SAAS,KACrB,+CAAC,SAAI,WAAU,iBACb;AAAA,yDAAC,SAAI,WAAU,iBAAgB,OAAO,MACpC;AAAA,0DAAC,UAAM,YAAE,aAAY;AAAA,YACpB,KAAK,IAAI,OAAK,8CAAC,UAAc,YAAE,OAAO,CAAC,KAAd,CAAgB,CAAO;AAAA,aACnD;AAAA,UACC,aAAa,IAAI,CAAC,IAAI,MAAM;AAC3B,kBAAM,OAAO,OAAO,aAAa,KAAK,OAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,IAAI,GAAG,QAAQ;AACzF,kBAAM,EAAE,OAAO,KAAK,IAAI,UAAU,IAAI;AACtC,mBACE,+CAAC,SAAsB,WAAU,eAAc,OAAO,MACpD;AAAA,6DAAC,SAAI,WAAU,eACb;AAAA,8DAAC,gBAAa,WAAU,cAAa,MAAY;AAAA,gBACjD,+CAAC,UAAK,WAAU,iBACb;AAAA,2BAAS,8CAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,kBACjD,8CAAC,UAAK,WAAU,gBAAgB,gBAAK;AAAA,mBACvC;AAAA,iBACF;AAAA,cACC,KAAK,IAAI,SAAO;AACf,sBAAM,IAAI,GAAG,GAAG;AAChB,sBAAM,QAAQ,eAAe,CAAC;AAC9B,uBACE;AAAA,kBAAC;AAAA;AAAA,oBAEC,WAAU;AAAA,oBACV,eAAa,WAAW,GAAG,IAAI,CAAC;AAAA,oBAChC,gBAAc,EAAE;AAAA,oBAChB,cAAY,GAAG,EAAE,OAAO,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAG,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE;AAAA,oBAE5F;AAAA,oEAAC,UAAK,WAAU,kBAAiB,eAAY,QAAQ,mBAAS,KAAK,CAAC,GAAE;AAAA,sBACrE,SAAS,8CAAC,UAAK,WAAU,oBAAmB,eAAY,QAAQ,iBAAM;AAAA;AAAA;AAAA,kBAPlE;AAAA,gBAQP;AAAA,cAEJ,CAAC;AAAA,iBAvBO,GAAG,QAwBb;AAAA,UAEJ,CAAC;AAAA,WACH;AAAA,QAGD,CAAC,UACA,+CAAC,SAAI,WAAU,kBACb;AAAA,yDAAC,UAAK;AAAA,0DAAC,OAAE,WAAU,cAAa,gBAAa,SAAQ;AAAA,YAAG,EAAE;AAAA,aAAY;AAAA,UACtE,+CAAC,UAAK;AAAA,0DAAC,OAAE,WAAU,cAAa,gBAAa,QAAO;AAAA,YAAG,EAAE;AAAA,aAAY;AAAA,UACrE,+CAAC,UAAK;AAAA;AAAA,YAAG,EAAE;AAAA,aAAa;AAAA,WAC1B;AAAA,QAGD,aAAa,YAAY,CAAC,UACzB,+CAAC,SAAI,WAAU,gBAAe;AAAA,wDAAC,YAAS;AAAA,UAAE,8CAAC,UAAM,sBAAY,UAAS;AAAA,WAAO;AAAA,QAG9E,UACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,aAAa,SAAS,QAAQ,aAAa,SAAS,SAAS;AAAA,YACnE,OAAO,aAAa,SAAS,EAAE,SAAS,aAAa,SAAS,EAAE,SAAS,GAAG,MAAM;AAAA,YAClF;AAAA,YACA,QAAQ,cAAc,EAAE,OAAO,YAAY,WAAW,IAAI;AAAA,YAC1D;AAAA,YACA;AAAA;AAAA,QACF;AAAA,SAEJ;AAAA,MAEC,CAAC,UACA,8CAAC,aACC;AAAA,QAAC;AAAA;AAAA,UAAW,IAAI;AAAA,UAAS,OAAO,EAAE;AAAA,UAAa,aAAa,EAAE;AAAA,UAC5D,cAAc,EAAE;AAAA,UAAc,SAAS;AAAA,UAAM;AAAA,UAAc,SAAS;AAAA,UACpE,QAAQ;AAAA,UAAc,UAAU;AAAA;AAAA,MAAY,GAChD;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AWvOY,IAAAC,uBAAA;AAnBZ,IAAM,qBAAqB;AAE3B,SAASC,kBAAiB,MAAwD;AAChF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,EAAE,MAAM,WAAW,WAAW,SAAS,GAE3C;AACd,QAAM,EAAE,OAAO,KAAK,IAAI,UAAU,IAAI;AACtC,SACE,+CAAC,SAAI,WAAW,eAAe,YAAY,qBAAqB,EAAE,IAChE;AAAA,kDAAC,SAAI,WAAU,sBACZ,sBACG,8CAAC,gBAAa,WAAU,iBAAgB,MAAY,WAAsB,IAC1E,8CAAC,cAAW,MAAM,KAAK,GAC7B;AAAA,IACA,+CAAC,SAAI,WAAU,gBACZ;AAAA,eAAS,8CAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,MACjD,8CAAC,UAAK,WAAU,mBAAmB,gBAAK;AAAA,MACvC;AAAA,OACH;AAAA,KACF;AAEJ;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4C;AAC1C,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAE5D,QAAM,gBAAgB,aAAa,iBAAiB,CAAC;AACrD,QAAM,gBAAgB,cAAc;AACpC,QAAM,gBAAgB,cAAc,KAAK,OAAK,CAAC,EAAE,UAAU;AAC3D,QAAM,mBAAmB,UAAU,QAAQ,iBAAiB,OAAO,MAAM;AACzE,QAAM,SAAS,QAAQ,kBAAkB,QAAQ,iBAAiB;AAElE,QAAM,cAAc,UAAU,CAAC,SAAS,OAAO,MAAM,aAAa,KAAK,OAAO;AAE9E,QAAM,eAAe,cAAc,OAAO,OAAK,EAAE,UAAU,EAAE;AAE7D,QAAM,QAAQ,aAAa,SAAS,QAAQ,SAAS;AACrD,QAAM,YAAY,aAAa,aAAa;AAE5C,QAAM,aAAa,cAAc,cAAc,SAAS,CAAC;AACzD,QAAM,iBAAiB,aAAa,QAAQ,MAAM,KAAK,OAAK,EAAE,cAAc,WAAW,SAAS,IAAI;AAEpG,WAAS,WAAW,MAA0B;AAC5C,QAAI,CAAC,UAAU,UAAU,cAAc,CAAC,YAAa;AACrD,UAAM,cAAc,cAAc,IAAI,QAAM,EAAE,WAAW,EAAE,WAAW,MAAM,EAAE,KAAK,EAAE;AACrF,UAAM,aAAa,CAAC,GAAG,aAAa,EAAE,WAAW,YAAY,WAAW,KAAK,CAAC;AAC9E,aAAS,KAAK,UAAU,EAAE,SAAS,WAAW,CAAC,CAAC;AAAA,EAClD;AAEA,SACE,+CAAC,SAAI,WAAU,uBAAsB,aAAU,mBAAkB,eAAY,+BAC3E;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,UAAU,EAAE,QAAQ,kBAAkB,GAAG,GAAG,MAAM,MAAM;AAAA,QAC/D,SAAS,EAAE,QAAQ,kBAAkB;AAAA,QACrC,OAAO,SAAS,8CAAC,aAAU,OAAO,WAAW,OAAO,EAAE,QAAQ,IAAK;AAAA,QACnE;AAAA,QACA,WAAW,GAAG;AAAA;AAAA,IAChB;AAAA,IAEC,CAAC,UAAU,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,IAErE,UACC,gFACE;AAAA,qDAAC,SAAI,WAAU,aACb;AAAA,uDAAC,SAAI,WAAU,kBAAiB,eAAY,cAC1C;AAAA,wDAAC,UAAK,WAAU,oBAAoB,YAAE,YAAW;AAAA,UACjD,8CAAC,UAAK,WAAU,uBAAuB,iBAAO,WAAU;AAAA,UACxD,8CAAC,UAAK,WAAU,yBAAyB,YAAE,OAAO,OAAO,WAAW,GAAE;AAAA,WACxE;AAAA,QAEC,eACC,+CAAC,SAAI,WAAU,gBACb;AAAA,yDAAC,cAAW,MAAM,YAAY,aAAa,WAAW,YAAY,kBAChE;AAAA,0DAAC,UAAK,WAAU,iBAAiB,sBAAY,cAAa;AAAA,YAC1D,8CAAC,UAAK,WAAU,gBAAgB,iBAAO,WAAU;AAAA,aACnD;AAAA,UACA,8CAAC,UAAK,WAAU,cAAa,eAAY,QAAQ,YAAE,IAAG;AAAA,UACtD,8CAAC,cAAW,MAAM,YAAY,aAAa,WAAW,YAAY,kBAAkB,WAAS,MAC3F,yDAAC,SAAI,WAAU,gBACb;AAAA,2DAAC,cAAW,SAAQ,WAAU,UAAU,YAAY,SAAS,MAAM,WAAW,QAAQ,GACpF;AAAA,4DAAC,eAAY,MAAM,IAAI;AAAA,cAAG,EAAE;AAAA,eAC9B;AAAA,YACA,+CAAC,cAAW,SAAQ,WAAU,UAAU,YAAY,SAAS,MAAM,WAAW,OAAO,GACnF;AAAA,4DAAC,iBAAc,MAAM,IAAI;AAAA,cAAG,EAAE;AAAA,eAChC;AAAA,aACF,GACF;AAAA,WACF;AAAA,QAGD,cAAc,kBACb,+CAAC,OAAE,WAAU,oBAAmB,eAAY,YAAW,gBAAc,WAAW,aAAa,SAAS,SACnG;AAAA,qBAAW,aAAa,8CAAC,aAAU,IAAK,8CAAC,aAAU;AAAA,UACnD,EAAE,WAAW,UAAU,eAAe,WAAW,EAAE,MAAM,WAAW,YAAY;AAAA,WACnF;AAAA,QAGD,UACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,gBAAgB,SAAS,mBAAmB,QAAQ;AAAA,YAC1D,OAAO,gBAAgB,EAAE,UAAU,mBAAmB,EAAE,aAAa,GAAG,MAAM;AAAA,YAC9E;AAAA,YACA,QAAQ,cAAc,EAAE,UAAU,YAAY,IAAI;AAAA,YAClD;AAAA,YACA;AAAA;AAAA,QACF;AAAA,SAEJ;AAAA,MAEC,CAAC,UACA,8CAAC,aACC,yDAAC,SAAI,WAAU,gBACb;AAAA,sDAAC,SAAI,WAAU,gBAAe,MAAK,OAAM,cAAY,EAAE,aAAa,eAAe,OAAO,MAAM,MAAM,GACnG,iBAAO,MAAM,IAAI,CAAC,GAAG,MAAM;AAC1B,gBAAM,IAAI,cAAc,CAAC;AACzB,iBAAO,8CAAC,UAAuB,WAAU,eAAc,cAAY,IAAK,EAAE,aAAa,YAAY,UAAW,UAA5F,EAAE,SAAkG;AAAA,QACxH,CAAC,GACH;AAAA,QACA,+CAAC,UAAK,WAAU,eACd;AAAA,wDAAC,UAAK,eAAY,aAAa,iBAAM;AAAA,UAAO;AAAA,UAAC,8CAAC,UAAK,WAAU,oBAAoB,aAAG,MAAM,SAAQ;AAAA,WACpG;AAAA,SACF,GACF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AC7JA,IAAAC,iBAAgC;;;ACAhC,IAAAC,iBAAyB;AAMd,IAAAC,uBAAA;AAHJ,SAAS,YAAY,EAAE,KAAK,MAAM,OAAO,GAAG,GAAsE;AACvH,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,MAAI,OAAO,CAAC,mBAAmB,GAAG,KAAK,CAAC,QAAQ;AAC9C,WAAO,8CAAC,SAAI,WAAU,cAAa,KAAU,KAAK,MAAM,OAAO,MAAM,QAAQ,MAAM,SAAQ,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAAA,EACpI;AACA,SACE,8CAAC,SAAI,WAAU,6BAA4B,OAAO,MAAM,QAAQ,OAAO,KAAK,IAAI,SAAQ,aAAY,MAAK,OAAM,cAAY,MACzH,wDAAC,UAAK,GAAE,6CAA4C,MAAK,gBAAe,GAC1E;AAEJ;;;ADwCM,IAAAC,uBAAA;AAvCN,SAASC,kBAAiB,MAA+D;AACvF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,WAAW,OAAoC;AAC7D,MAAI,CAAC,MAAM,UAAW,QAAO;AAC7B,MAAI,MAAM,WAAW,MAAM,YAAY,MAAM,UAAW,QAAO,GAAG,MAAM,SAAS,SAAI,MAAM,OAAO;AAClG,SAAO,OAAO,MAAM,SAAS;AAC/B;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,QAAQ,UAAU,EAAE,QAAQ,cAAc,GAAG,GAAG,MAAM,MAAM;AAClE,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,cAAU,sBAAM;AAEtB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,oBAAoB,IAAI,IAAY,aAAa,aAAa,IAAI,OAAK,EAAE,QAAQ,KAAK,CAAC,CAAC;AAE9F,QAAM,SACJ,QAAQ,kBAAkB,QAC1B,aAAa,WAAW,QACxB,aAAa,WAAW;AAE1B,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC/D;AAAA,oDAAC,cAAW,OAAc,SAAS,EAAE,SAAS,QAAgB,WAAW,GAAG,MAAM;AAAA,MAClF,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,cAAc,aAAa,eAAe,OAAO;AACvD,QAAM,aAAa,aAAa,cAAc,OAAO;AACrD,QAAM,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,aAAa,YAAY,MAAM;AAEvE,QAAM,OAAO,CAAC,SAAS,OAAO,cAAc,OAAO,OAAK,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;AAEzF,WAAS,aAAa,UAAwB;AAC5C,QAAI,CAAC,UAAU,UAAU,WAAY;AACrC,UAAM,cAAc,aAAa,aAAa,IAAI,OAAK,EAAE,QAAQ,KAAK,CAAC;AACvE,UAAM,aAAa,CAAC,GAAG,aAAa,QAAQ;AAC5C,aAAS,EAAE;AACX,aAAS,KAAK,UAAU,EAAE,SAAS,WAAW,CAAC,CAAC;AAAA,EAClD;AAEA,QAAM,QAAQ,CAAC,UAAU,cAEnB,8CAAC,UAAK,eAAY,iBAChB,yDAAC,QAAK,SAAQ,WACX;AAAA,OAAG,MAAM;AAAA,IAAM;AAAA,IAAC,8CAAC,UAAK,WAAU,YAAY,sBAAY,cAAc,GAAE;AAAA,IAAO;AAAA,IAAI,YAAY,cAAc,YAAY;AAAA,KAC5H,GACF,IAEF;AAEJ,QAAM,UAAU,aAAa,SAAS,EAAE,SAAS,aAAa,SAAS,EAAE,SAAS,GAAG,MAAM;AAE3F,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC/D;AAAA,kDAAC,cAAW,OAAc,SAAS,EAAE,SAAS,OAAc,QAAgB,WAAW,GAAG,MAAM;AAAA,IAEhG,+CAAC,SAAI,WAAU,aACZ;AAAA,OAAC,UAAU,8CAAC,mBAAgB,QAAQ,OAAO,cAAc,aAAa,aAAa,eAAe,GAAG,IAAQ;AAAA,MAC9G,+CAAC,SAAI,WAAU,gBACZ;AAAA,kBAAU,aAAa,qBACtB,8CAAC,gBAAa,WAAU,iBAAgB,MAAM,YAAY,oBAAoB,WAAW,YAAY,yBAAyB,IAE9H,8CAAC,cAAW,MAAM,IAAI,SAAS,SAAS,YAAY,WAAW;AAAA,QAEjE,+CAAC,SAAI,WAAU,qBACb;AAAA,wDAAC,UAAK,WAAU,sBACb,oBAAU,aAAa,qBAAqB,YAAY,qBAAqB,EAAE,eAClF;AAAA,UACC,aAAa,WACZ,8CAAC,UAAK,WAAU,gBAAgB,sBAAY,UAAS,IACnD,CAAC,SACH,+CAAC,UAAK,WAAU,iBACd;AAAA,0DAAC,QAAK,SAAQ,QAAO,MAAM,8CAAC,YAAS,MAAM,IAAI,GAAK,YAAE,cAAa;AAAA,YACnE,8CAAC,QAAK,SAAQ,QAAO,MAAM,8CAAC,YAAS,MAAM,IAAI,GAAK,YAAE,iBAAgB;AAAA,aACxE,IACE;AAAA,WACN;AAAA,SACF;AAAA,MAEA,+CAAC,QAAG,WAAU,gBACX;AAAA,oBAAY,IAAI,CAAC,OAAO,MAAM;AAC7B,gBAAM,QAAQ,MAAM,IAAI,EAAE,YAAY,WAAW,KAAK;AACtD,iBACE,+CAAC,QAAkC,WAAU,gBAC3C;AAAA,2DAAC,UAAK,WAAU,gBACd;AAAA,4DAAC,UAAK,WAAU,gBAAe,wDAAC,eAAY,KAAK,MAAM,UAAU,MAAM,MAAM,UAAU,MAAM,IAAI,GAAE;AAAA,cACnG,8CAAC,UAAK,WAAU,gBAAe,eAAY,QAAO;AAAA,eACpD;AAAA,YACA,+CAAC,UAAK,WAAU,qBACd;AAAA,4DAAC,UAAK,WAAU,gBAAgB,gBAAM,UAAS;AAAA,cAC/C,+CAAC,UAAK,WAAU,eACd;AAAA,8DAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,gBACtC,MAAM,UACL,gFACG;AAAA,0BAAQ,WAAQ;AAAA,kBACjB,8CAAC,UAAK,WAAU,gBAAgB,YAAE,MAAK;AAAA,mBACzC;AAAA,iBAEJ;AAAA,eACF;AAAA,eAhBO,GAAG,MAAM,QAAQ,IAAI,CAAC,EAiB/B;AAAA,QAEJ,CAAC;AAAA,QACA,SAAS,KACR,+CAAC,QAAG,WAAU,qCACZ;AAAA,yDAAC,UAAK,WAAU,gBACd;AAAA,0DAAC,UAAK,WAAU,qCAAoC,wDAAC,YAAS,MAAM,IAAI,GAAE;AAAA,YACzE,SAAS,KAAK,8CAAC,UAAK,WAAU,oCAAmC,eAAY,QAAO;AAAA,aACvF;AAAA,UACA,8CAAC,UAAK,WAAU,qBAAoB,wDAAC,UAAK,WAAU,eAAe,YAAE,gBAAe,GAAO;AAAA,WAC7F;AAAA,QAED,SAAS,KACR,+CAAC,QAAG,WAAU,mCACZ;AAAA,wDAAC,UAAK,WAAU,gBACd,wDAAC,UAAK,WAAU,oCAAmC,wDAAC,YAAS,MAAM,IAAI,GAAE,GAC3E;AAAA,UACA,8CAAC,UAAK,WAAU,qBAAoB,wDAAC,UAAK,WAAU,eAAe,YAAE,UAAU,SAAS,CAAC,GAAE,GAAO;AAAA,WACpG;AAAA,SAEJ;AAAA,MAEC,UACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,aAAa,SAAS,QAAQ,aAAa,SAAS,SAAS;AAAA,UACnE,OAAO;AAAA,UACP,OAAO,QAAQ;AAAA,UACf,QAAQ,cAAc,EAAE,YAAY,YAAY,WAAW,IAAI;AAAA,UAC/D;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,IAEC,CAAC,UACA,8CAAC,aACC;AAAA,MAAC;AAAA;AAAA,QAAW,IAAI;AAAA,QAAS,OAAO,EAAE;AAAA,QAAa,aAAa,EAAE;AAAA,QAC5D,cAAc,EAAE;AAAA,QAAa,SAAS;AAAA,QAAM;AAAA,QAAc,SAAS;AAAA,QACnE,QAAQ;AAAA,QAAc,UAAU;AAAA,QAAY,UAAU;AAAA;AAAA,IAAG,GAC7D;AAAA,KAEJ;AAEJ;;;AEjLA,IAAAC,iBAA0D;;;ACWlD,IAAAC,uBAAA;AAND,SAAS,WAAW,EAAE,OAAO,SAAS,OAAO,GAEpC;AACd,SACE,8CAAC,SAAI,WAAU,aAAY,MAAK,WAAU,cAAY,OACnD,kBAAQ,IAAI,OACX,8CAAC,YAAmB,MAAK,UAAS,MAAK,UAAS,iBAAe,OAAO,WAAU,YAAW,SAAS,MAAM,OAAO,EAAE,GAAG,GACnH,YAAE,WADQ,EAAE,GAEf,CACD,GACH;AAEJ;;;ADyC4B,IAAAC,uBAAA;AApBrB,SAAS,kBAAkB,OAAe,KAAiC;AAChF,QAAM,KAAK,OAAO,OAAO,YAAY;AACrC,MAAI,EAAE,SAAS,KAAK,EAAG,QAAO;AAC9B,MAAI,EAAE,SAAS,MAAM,EAAG,QAAO;AAC/B,MAAI,EAAE,SAAS,QAAQ,EAAG,QAAO;AACjC,MAAI,EAAE,SAAS,OAAO,EAAG,QAAO;AAChC,MAAI,EAAE,SAAS,QAAQ,EAAG,QAAO;AACjC,SAAO;AACT;AAIO,SAAS,UAAU,OAAe,KAA6B,KAAsB;AAC1F,QAAM,SAAS,KAAK,MAAM,GAAG,EAAE,IAAI;AACnC,QAAM,UAAU,SAAS,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC,IAAI;AAC5E,SAAO,IAAI,OAAO,KAAK,IAAI,KAAK,KAAK;AACvC;AAEA,SAAS,cAAc,EAAE,KAAK,GAA6C;AACzE,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAY,aAAO,8CAAC,gBAAa;AAAA,IACtC,KAAK;AAAQ,aAAO,8CAAC,YAAS;AAAA,IAC9B,KAAK;AAAQ,aAAO,8CAAC,YAAS;AAAA,IAC9B,KAAK;AAAU,aAAO,8CAAC,cAAW;AAAA,IAClC,KAAK;AAAU,aAAO,8CAAC,cAAW;AAAA,IAClC;AAAS,aAAO,8CAAC,YAAS;AAAA,EAC5B;AACF;AAIA,SAAS,aAAa,EAAE,OAAO,SAAS,MAAM,KAAK,GAA8E;AAC/H,MAAI,CAAC,MAAM;AACT,WAAO,8CAAC,iBAAc,MAAM,kBAAkB,OAAO,IAAI,GAAG;AAAA,EAC9D;AACA,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,8CAAC,eAAY,KAAK,KAAK,UAAU,MAAM,OAAO,MAAM,IAAI;AAAA,IACjE,KAAK;AACH,aAAO,8CAAC,gBAAa,MAAM,OAAO,WAAW,KAAK,UAAU,WAAU,qBAAoB;AAAA,IAC5F,KAAK;AACH,aAAO,8CAAC,UAAK,WAAU,qBAAoB,eAAY,QAAQ,0BAAgB,KAAK,WAAW,KAAK,GAAE;AAAA,IACxG,KAAK;AAEH,aAAO,+EAAE;AAAA,IACX;AACE,aAAO,8CAAC,iBAAc,MAAM,kBAAkB,OAAO,IAAI,GAAG;AAAA,EAChE;AACF;AAEA,SAASC,kBAAiB,MAAwD;AAChF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,OAAwB,KAAa,KAAwC;AACnG,SAAO,MAAM,KAAK,OAAK,EAAE,QAAQ,OAAO,EAAE,QAAQ,GAAG;AACvD;AAIA,SAAS,UAAU,MAAkC;AACnD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACrD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,SAAO,GAAG,MAAM,OAAO,CAAC,CAAC,KAAK,IAAI;AACpC;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUgB;AACd,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,cAAU,sBAAM;AACtB,QAAM,eAAW,uBAAyB,IAAI;AAE9C,gCAAU,MAAM;AAAE,aAAS,SAAS,MAAM;AAAA,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;AAEzD,QAAM,WAAW,WAAW;AAAA,IAC1B,OAAK,CAAC,iBAAiB,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC;AAAA,EACvF;AAEA,SACE,+CAAC,SAAI,WAAU,kBAAiB,eAAY,oBAC1C;AAAA,mDAAC,SAAI,WAAU,sBACb;AAAA,oDAAC,QAAK,SAAQ,WAAW,oBAAS;AAAA,MAClC,8CAAC,UAAK,WAAU,oBAAmB,eAAY,QAAO,wDAAC,aAAU,MAAM,IAAI,GAAE;AAAA,MAC7E,8CAAC,QAAK,SAAQ,UAAU,oBAAS;AAAA,MACjC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,eAAY;AAAA,UACZ,cAAY,EAAE;AAAA,UACd,SAAS;AAAA,UAET,wDAAC,aAAU;AAAA;AAAA,MACb;AAAA,OACF;AAAA,IACC,WAAW,WAAW,IACrB,8CAAC,SAAI,WAAU,wBAAwB,YAAE,WAAU,IAEnD,gFACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,OAAO,EAAE,YAAY,UAAU,QAAQ;AAAA,UACvC,aAAW;AAAA,UACX,aAAa,EAAE;AAAA,UACf,OAAO;AAAA,UACP,UAAU;AAAA,UACV;AAAA;AAAA,MACF;AAAA,MACC,MAAM,SAAS,KAAK,SAAS,SAAS,KACrC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,EAAE,YAAY,UAAU,QAAQ;AAAA,UACvC,SAAS,SAAS,IAAI,QAAM;AAAA,YAC1B,KAAK,EAAE;AAAA,YACP,SACE,gFACE;AAAA,4DAAC,gBAAa,MAAM,EAAE,MAAM,WAAW,EAAE,WAAW,WAAU,eAAc;AAAA,cAC5E,8CAAC,UAAK,WAAU,wBAAwB,YAAE,MAAK;AAAA,cAC/C,8CAAC,UAAK,WAAU,wBAAuB,eAAY,QAAO,wDAAC,YAAS,MAAM,IAAI,GAAE;AAAA,eAClF;AAAA,UAEJ,EAAE;AAAA,UACF,QAAQ,OAAK,OAAO,KAAK,KAAK,OAAO,CAAC,CAAC;AAAA;AAAA,MACzC;AAAA,OAEJ;AAAA,KAEJ;AAEJ;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsC;AACpC,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,QAAQ,UAAU,EAAE,QAAQ,gBAAgB,GAAG,GAAG,MAAM,MAAM;AACpE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAA4B,IAAI;AAEpE,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,cAAc,aAAa,SAAS,CAAC;AAE3C,QAAMC,YACJ,QAAQ,kBAAkB,QAC1B,aAAa,eAAe;AAE9B,QAAM,mBAAmB,IAAI,IAAY,YAAY,IAAI,OAAK,EAAE,QAAQ,CAAC;AAEzE,WAAS,gBAAgB,KAAa,KAAmB;AACvD,QAAIA,aAAY,WAAY;AAC5B,UAAM,gBAAgB,eAAe,aAAa,KAAK,GAAG;AAC1D,QAAI,cAAe;AACnB,kBAAc,EAAE,KAAK,IAAI,CAAC;AAAA,EAC5B;AAEA,WAAS,WAAW,KAAa,KAAa,UAAwB;AACpE,kBAAc,IAAI;AAClB,UAAM,YAAY,YAAY,IAAI,QAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE;AACzF,UAAM,WAAW,CAAC,GAAG,WAAW,EAAE,KAAK,KAAK,SAAS,CAAC;AACtD,aAAS,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC,CAAC;AAAA,EAC9C;AAEA,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,iBAAgB,eAAY,6BACjE;AAAA,oDAAC,cAAW,OAAc,SAAS,EAAE,SAAS,QAAgB,WAAW,GAAG,MAAM;AAAA,MAClF,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,OAAO,OAAO;AACpB,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,KAAK,SAAS,KAAK;AACjC,QAAM,eAAe,YAAY,OAAO,OAAK,EAAE,SAAS,EAAE;AAC1D,QAAM,aAAa,YAAY,SAAS;AACxC,QAAM,WAA2B,MAAM;AAAA,IAAK,EAAE,QAAQ,MAAM;AAAA,IAAG,CAAC,GAAG,MACjE,IAAI,eAAe,YAAY,IAAI,eAAe,aAAa,UAAU;AAAA,EAC3E;AAEA,QAAM,aAAa,aAAa,cAAc,QAAQ,SAAS;AAE/D,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,iBAAgB,eAAY,6BACjE;AAAA,kDAAC,cAAW,OAAc,SAAS,EAAE,SAAS,QAAgB,WAAW,GAAG,MAAM;AAAA,IAClF;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,EAAE,aAAa,YAAY,QAAQ,KAAK;AAAA,QACnD,WAAW,EAAE,OAAO,YAAY,QAAQ,KAAK;AAAA,QAC7C,YAAY,EAAE,KAAK,KAAK,IAAI,GAAG,QAAQ,YAAY,MAAM,CAAC;AAAA,QAC1D,OAAO,8CAAC,QAAK,SAAQ,UAAU,aAAG,UAAU,IAAI,GAAG,MAAM,OAAO,IAAG;AAAA;AAAA,IACrE;AAAA,IAEA,+CAAC,SAAI,WAAU,aACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,eAAe,OAAO,qCAAqC;AAAA,UACtE,OAAO;AAAA,YACL,qBAAqB,eAAe,KAAK,MAAM;AAAA,YAC/C,kBAAkB,6BAA6B,KAAK,MAAM;AAAA,UAC5D;AAAA,UACA,MAAK;AAAA,UAEL;AAAA,0DAAC,SAAI,WAAU,mBAAkB;AAAA,YAChC,KAAK,IAAI,CAAC,KAAK,WAAW;AACzB,oBAAM,UAAU,OAAO,WAAW,MAAM;AACxC,qBACE,+CAAC,SAAc,WAAU,mBAAkB,aAAW,UAAU,SAAS,QACvE;AAAA,8DAAC,gBAAa,OAAO,KAAK,SAAS,OAAO,WAAW,MAAM,GAAG,KAAK,MAAM,SAAS;AAAA,gBAClF,8CAAC,UAAM,eAAI;AAAA,mBAFH,GAGV;AAAA,YAEJ,CAAC;AAAA,YACA,KAAK,IAAI,CAAC,UAAU,WAAW;AAC9B,oBAAM,UAAU,OAAO,WAAW,MAAM;AACxC,oBAAM,OAAO,UAAU,UAAU,EAAE,WAAW,OAAO,WAAW,MAAM,GAAG,GAAG;AAG5E,oBAAM,mBAAmB,UACvB,gFACE;AAAA,8DAAC,gBAAa,OAAO,UAAU,SAAS,OAAO,WAAW,MAAM,GAAG,KAAK,MAAM,SAAS;AAAA,gBACvF,8CAAC,UAAM,oBAAS;AAAA,iBAClB,IACE,SAAS,WACX,8CAAC,UAAM,oBAAS,IAEhB,gFACE;AAAA,8DAAC,UAAK,eAAY,QAAQ,gBAAK;AAAA,gBAC/B,8CAAC,UAAK,WAAU,WAAW,oBAAS;AAAA,iBACtC;AAEF,qBACE,+CAAC,eAAAC,QAAM,UAAN,EACC;AAAA,8DAAC,SAAI,WAAU,mBAAkB,aAAW,UAAU,SAAS,QAC5D,4BACH;AAAA,gBACC,KAAK,IAAI,CAAC,UAAU,WAAW;AAC9B,wBAAM,SAAS,eAAe,aAAa,QAAQ,MAAM;AACzD,wBAAM,WAAW,YAAY,QAAQ,UAAU,YAAY,QAAQ;AACnE,wBAAM,QAAQ,SAAU,OAAO,YAAY,YAAY,UAAW,WAAW,WAAW;AACxF,yBACE;AAAA,oBAAC;AAAA;AAAA,sBAEC,MAAK;AAAA,sBACL,eAAa,YAAY,MAAM,IAAI,MAAM;AAAA,sBACzC,cAAY;AAAA,sBACZ,cACE,SACI,EAAE,WAAW,UAAU,UAAU,WAAW,KAAK,OAAK,EAAE,OAAO,OAAO,QAAQ,GAAG,QAAQ,IAAI,OAAO,YAAY,EAAE,UAAU,EAAE,KAAK,IACnI,EAAE,SAAS,UAAU,QAAQ;AAAA,sBAEnC,gBAAc;AAAA,sBACd,WAAU;AAAA,sBACV,UAAUD,aAAY;AAAA,sBACtB,SAAS,MAAM,gBAAgB,QAAQ,MAAM;AAAA,sBAE5C,mBACC,gFACE;AAAA;AAAA,0BAAC;AAAA;AAAA,4BACC,WAAW,kCAAkC,OAAO,YAAY,YAAY,OAAO;AAAA,4BACnF,MAAK;AAAA,4BACL,cAAY,OAAO,YAAY,EAAE,UAAU,EAAE;AAAA,4BAE5C,iBAAO,YAAY,8CAAC,aAAU,MAAM,IAAI,IAAK,8CAAC,aAAU,MAAM,IAAI;AAAA;AAAA,wBACrE;AAAA,wBACA,8CAAC,UAAK,WAAU,mBAAmB,iBAAO,aAAY;AAAA,yBACpD,MAAM;AACN,gCAAM,QAAQ,WAAW,KAAK,OAAK,EAAE,OAAO,OAAO,QAAQ;AAC3D,iCACE;AAAA,4BAAC;AAAA;AAAA,8BACC,MAAM,OAAO,QAAQ;AAAA,8BACrB,WAAW,OAAO;AAAA,8BAClB,WAAU;AAAA;AAAA,0BACZ;AAAA,wBAEJ,GAAG;AAAA,wBACH,8CAAC,UAAK,WAAU,iBACb,oBAAU,WAAW,KAAK,OAAK,EAAE,OAAO,OAAO,QAAQ,GAAG,IAAI,GACjE;AAAA,yBACF,IAEA,8CAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO,wDAAC,YAAS,MAAM,IAAI,GAAE;AAAA;AAAA,oBAvCtE,QAAQ,MAAM,IAAI,MAAM;AAAA,kBAyC/B;AAAA,gBAEJ,CAAC;AAAA,mBArDkB,MAsDrB;AAAA,YAEJ,CAAC;AAAA;AAAA;AAAA,MACH;AAAA,MAECA,aACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,EAAE;AAAA,UACT,OAAO;AAAA,UACP,QAAQ,EAAE,QAAQ,cAAc,YAAY,MAAM;AAAA,UAClD;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,IAEC,eAAe,QACd,8CAAC,SAAI,WAAU,gBACb;AAAA,MAAC;AAAA;AAAA,QAEC,KAAK,WAAW;AAAA,QAChB,KAAK,WAAW;AAAA,QAChB,UAAU,KAAK,WAAW,GAAG,KAAK;AAAA,QAClC,UAAU,KAAK,WAAW,GAAG,KAAK;AAAA,QAClC;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,WAAW,MAAM,cAAc,IAAI;AAAA,QACnC;AAAA;AAAA,MATK,GAAG,WAAW,GAAG,IAAI,WAAW,GAAG;AAAA,IAU1C,GACF;AAAA,KAEJ;AAEJ;;;AEtYA,IAAAE,iBAAgC;;;ACG1B,IAAAC,uBAAA;AAHC,SAAS,SAAS,EAAE,QAAQ,GAA8C;AAC/E,SACE,+CAAC,SAAI,WAAU,kBAAiB,SAAS,YAAY,SAAS,gBAAgB,eAAe,qBAAoB,QAAO,eAAY,QAClI;AAAA,kDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAQ,YAAY,SAAS,MAAM,IAAI,MAAK,QAAO;AAAA,IAC/E,YAAY,SACX,gFACE;AAAA,oDAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA,MAAE,8CAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,MAAK,QAAO;AAAA,MAClF,8CAAC,UAAK,GAAE,MAAK,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,MAAK,QAAO;AAAA,MAAE,8CAAC,UAAK,GAAE,MAAK,GAAE,OAAM,OAAM,MAAK,QAAO,MAAK,MAAK,QAAO;AAAA,OAClH,IAEA,gFACE;AAAA,oDAAC,UAAK,GAAE,0BAAyB,MAAK,QAAO;AAAA,MAC7C,8CAAC,UAAK,GAAE,MAAK,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,MAAK,QAAO;AAAA,OACzD;AAAA,KAEJ;AAEJ;;;ACNO,SAAS,OAAO,WAA2C;AAChE,QAAM,QAAQ,oBAAI,IAA2B;AAC7C,YAAU,QAAQ,CAAC,GAAG,MAAM;AAC1B,UAAM,SAAS,OAAO,EAAE,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,IAAI;AACpD,UAAM,SAAS,MAAM,IAAI,MAAM,KAAK,CAAC;AACrC,WAAO,KAAK,CAAC;AACb,UAAM,IAAI,QAAQ,MAAM;AAAA,EAC1B,CAAC;AACD,QAAM,MAAM,CAAC,MAA2B,OAAO,EAAE,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK;AAEzE,SAAO,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,IAAI,OAAK,CAAC,GAAG,MAAM,IAAI,CAAC,CAAE,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC5G;AAKO,SAAS,eAAe,iBAA0C;AACvE,MAAI,gBAAgB,SAAS,EAAG,QAAO;AACvC,QAAM,UAAU,CAAC,GAAG,eAAe,EAAE,QAAQ;AAC7C,SAAO,QAAQ,MAAM,CAAC,EAAE,IAAI,OAAK,EAAE,MAAM,EAAE,KAAK,GAAG;AACrD;AAKO,IAAM,sBAAkD;AAAA,EAC7D,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC;AAAA,EAClF,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC;AAAA,EAClF,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC;AAAA,EACzF,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC;AAAA,EACvF,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC;AAAA,EAClF,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC;AAAA,EACvF,aAAa,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC;AAAA,EAC5F,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,MAAM,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC;AAAA,EACpF,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC;AAAA,EAClF,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,MAAM,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC;AAAA,EACpF,SAAS,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,MAAM,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC;AACtF;AAKO,SAAS,aAAa,SAAiB,YAA4B;AACxE,MAAI,YAAY,EAAG,QAAO;AAC1B,MAAI,YAAY,aAAa,EAAG,QAAO;AACvC,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO;AACT;AAGO,SAAS,gBAAgB,WAAmB,iBAAuD;AACxG,QAAM,UAAU,CAAC,GAAG,eAAe,EAAE,QAAQ;AAC7C,QAAM,WAAW,oBAAoB,SAAS;AAC9C,QAAM,MAAM,oBAAI,IAAoB;AACpC,UAAQ,QAAQ,CAAC,MAAM,OAAO;AAC5B,SAAK,QAAQ,CAAC,OAAO,OAAO;AAC1B,UAAI,CAAC,MAAM,KAAM;AACjB,YAAM,QAAQ,WAAW,EAAE,IAAI,EAAE,KAAK,aAAa,IAAI,QAAQ,MAAM;AACrE,UAAI,IAAI,MAAM,MAAM,KAAK;AAAA,IAC3B,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AACT;;;AFgB2B,IAAAC,uBAAA;AAxE3B,IAAMC,eAAc;AAEpB,SAASC,kBAAiB,MAAuD;AAC/E,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,cAAU,sBAAM;AAEtB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAE5D,QAAM,SACJ,QAAQ,kBAAkB,QAC1B,aAAa,WAAW,YACxB,aAAa,WAAW;AAC1B,QAAM,SAAS,aAAa,WAAW;AACvC,QAAM,SAAS,aAAa,WAAW;AAEvC,QAAM,iBAAiB,IAAI,IAAY,aAAa,aAAa,IAAI,OAAK,EAAE,MAAM,KAAK,CAAC,CAAC;AACzF,QAAM,OAAO,SAAS,OAAO,OAAO,SAAS,IAAI,CAAC;AAElD,QAAM,YAAY,QAAQ,mBAAmB,eAAe,IAAI,IAAI;AAEpE,QAAM,YAAY,QAAQ,mBAAmB,gBAAgB,WAAW,IAAI,IAAI,oBAAI,IAAoB;AAIxG,QAAM,aAAa,oBAAI,IAAoB;AAC1C,GAAC,aAAa,iBAAiB,CAAC,GAAG,QAAQ,OAAK;AAAE,QAAI,EAAE,QAAQ,EAAE,SAAS,WAAY,YAAW,IAAI,EAAE,MAAM,EAAE,KAAK;AAAA,EAAE,CAAC;AAGzH,QAAM,eAAe,oBAAI,IAAkD;AAC1E,GAAC,aAAa,UAAU,CAAC,GAAG,QAAQ,OAAK;AAAE,iBAAa,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAAW,EAAE,UAAU,CAAC;AAAA,EAAE,CAAC;AAEhH,QAAM,WACJ,UAAU,CAAC,SACP,OAAO,SAAS;AAAA,IACd,QAAM,CAAC,eAAe,IAAI,GAAG,MAAM,KAAK,GAAG,SAAS,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC;AAAA,EAChG,IACA,CAAC;AAEP,WAAS,WAAW,QAAsB;AACxC,QAAI,CAAC,UAAU,UAAU,WAAY;AACrC,UAAM,cAAc,aAAa,aAAa,IAAI,QAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC;AACnF,UAAM,aAAa,CAAC,GAAG,aAAa,EAAE,OAAO,CAAC;AAC9C,aAAS,EAAE;AACX,aAAS,KAAK,UAAU,EAAE,SAAS,WAAW,CAAC,CAAC;AAAA,EAClD;AAEA,QAAM,gBAAgB,aAAa,gBAAgB,CAAC,GAAG,OAAO,OAAK,CAAC,EAAE,UAAU;AAChF,QAAM,cAAc,KAAK,IAAI,GAAGD,gBAAe,aAAa,eAAe,EAAE;AAC7E,QAAM,WAAW,CAAC,OAAuB,QAAQ,SAAS,KAAK,QAAM,GAAG,WAAW,EAAE,GAAG,YAAY,IAAI,EAAE;AAE1G,SACE,+CAAC,SAAI,WAAU,wBAAuB,aAAU,gBAAe,eAAY,4BACzE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,UAAU,EAAE,QAAQ,eAAe,GAAG,GAAG,MAAM,MAAM;AAAA,QAC5D,SAAS,QAAQ;AAAA,QACjB,OAAO,YAAY,8CAAC,QAAK,SAAQ,UAAU,qBAAU,IAAU;AAAA,QAC/D;AAAA,QACA,WAAW,GAAG;AAAA;AAAA,IAChB;AAAA,IAEC,CAAC,UAAU,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,IAErE,UACC,gFACE;AAAA,qDAAC,SAAI,WAAU,aACZ;AAAA,SAAC,UAAU,8CAAC,mBAAgB,QAAQ,OAAO,cAAc,aAAa,aAAa,aAAa,UAAU,GAAG,IAAQ;AAAA,QACrH,KAAK,SAAS,KACb,+CAAC,SAAI,WAAU,kBAAiB,MAAK,SAAQ,cAAY,EAAE,YACzD;AAAA,wDAAC,YAAS,SAAQ,QAAO;AAAA,UACzB,8CAAC,SAAI,WAAU,iBACZ,eAAK,IAAI,CAAC,KAAK,MACd,8CAAC,SAAY,WAAU,gBACpB,cAAI,IAAI,CAAC,KAAK,MAAM;AACnB,kBAAM,WAAW,IAAI,OAAO,UAAU,IAAI,IAAI,IAAI,KAAK,KAAK;AAC5D,kBAAM,OAAO,IAAI,OAAO,WAAW,IAAI,IAAI,IAAI,IAAI;AACnD,kBAAM,cAAc,IAAI,OAAO,aAAa,IAAI,IAAI,IAAI,IAAI;AAC5D,kBAAM,OAAO,gBAAgB,IAAI,WAAW;AAE5C,gBAAI,aAAa;AACf,qBACE,+CAAC,SAA6B,WAAU,iBAAgB,iBAAc,QACpE;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAM,YAAY;AAAA,oBAClB,WAAW,YAAY;AAAA,oBACvB,WAAU;AAAA;AAAA,gBACZ;AAAA,gBACA,8CAAC,UAAK,WAAU,mCAAmC,oBAAU,YAAY,IAAI,EAAE,MAAK;AAAA,mBAN5E,GAAG,IAAI,IAAI,IAAI,CAAC,EAO1B;AAAA,YAEJ;AACA,mBACE,+CAAC,SAA6B,WAAU,iBAAgB,iBAAe,OAAO,SAAS,QACrF;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,aAAW,aAAa,IAAI,IAAI,SAAS;AAAA,kBACzC,MAAK;AAAA,kBACL,OAAO,IAAI;AAAA,kBACX,cAAY,GAAG,WAAW,WAAW,aAAQ,EAAE,GAAG,IAAI,WAAW,GAAG,OAAO,aAAQ,OAAO,EAAE;AAAA,kBAE3F;AAAA;AAAA,cACH;AAAA,cACC,OACG,8CAAC,UAAK,WAAU,mCAAmC,oBAAU,IAAI,EAAE,MAAK,IACxE,YAAY,8CAAC,UAAK,WAAU,gBAAgB,oBAAS;AAAA,iBAZjD,GAAG,IAAI,IAAI,IAAI,CAAC,EAa1B;AAAA,UAEJ,CAAC,KAnCO,CAoCV,CACD,GACH;AAAA,WACF;AAAA,QAGD,CAAC,UAAU,aAAa,SAAS,KAChC,+CAAC,SAAI,WAAU,kBACb;AAAA,wDAAC,UAAK,WAAU,oBAAoB,YAAE,SAAQ;AAAA,UAC7C,aAAa,IAAI,OAAK;AACrB,kBAAM,WAAW,QAAQ,SAAS,KAAK,QAAM,GAAG,WAAW,EAAE,MAAM,GAAG;AACtE,mBACE,+CAAC,UAAoB,WAAU,uBAC7B;AAAA,4DAAC,eAAY,KAAK,UAAU,MAAM,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI;AAAA,cAChE,8CAAC,OAAG,mBAAS,EAAE,MAAM,GAAE;AAAA,iBAFd,EAAE,MAGb;AAAA,UAEJ,CAAC;AAAA,WACH;AAAA,QAGD,UACC,gFACE;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,SAAS,QAAQ,SAAS,SAAS;AAAA,cACzC,OAAO,SAAS,EAAE,SAAS,SAAS,EAAE,SAAS,GAAG,MAAM;AAAA,cACxD,OAAO,aAAa,SAAS,QAAQ,SAAS;AAAA,cAC9C,QAAQ,cAAc,EAAE,OAAO,YAAY,WAAW,IAAI;AAAA,cAC1D;AAAA,cACA;AAAA;AAAA,UACF;AAAA,WACE,UAAU,WAAW,aAAa,UAClC,+CAAC,SAAI,WAAU,mBAAkB,eAAY,qBAC3C;AAAA,0DAAC,UAAK,WAAU,yBAAyB,YAAE,WAAU;AAAA,YACrD,8CAAC,eAAY,KAAK,YAAY,OAAO,UAAU,MAAM,YAAY,OAAO,UAAU,MAAM,IAAI;AAAA,YAC5F,8CAAC,UAAK,WAAU,wBAAwB,sBAAY,OAAO,UAAS;AAAA,aACtE;AAAA,WAEJ;AAAA,SAEJ;AAAA,MAEC,CAAC,UACA,+CAAC,aACE;AAAA,cAAM,SAAS,KAAK,SAAS,SAAS,KACrC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,EAAE;AAAA,YACT,SAAS,SAAS,IAAI,SAAO;AAAA,cAC3B,KAAK,GAAG;AAAA,cACR,SAAS,gFAAE;AAAA,8DAAC,eAAY,KAAK,GAAG,UAAU,MAAM,GAAG,UAAU,MAAM,IAAI;AAAA,gBAAE,8CAAC,UAAM,aAAG,UAAS;AAAA,iBAAO;AAAA,YACrG,EAAE;AAAA,YACF,QAAQ,OAAK,WAAW,OAAO,CAAC,CAAC;AAAA;AAAA,QACnC;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YAAY,IAAI;AAAA,YAAS,OAAO,EAAE,UAAU,WAAW;AAAA,YAAG,aAAa,EAAE;AAAA,YACxE,OAAO;AAAA,YAAO,UAAU;AAAA,YAAU,UAAU;AAAA;AAAA,QAAY;AAAA,SAC5D;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AG3MA,IAAAE,iBAAyB;AAqCjB,IAAAC,uBAAA;AAzBR,SAASC,kBAAiB,MAA8D;AACtF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,SAA4B,OAA4C;AAC1F,SAAO,QAAQ,KAAK,OAAK,EAAE,UAAU,KAAK;AAC5C;AAEA,IAAM,iBAAiB;AACvB,IAAM,aAAa;AAEnB,SAAS,WAAW,EAAE,KAAK,GAAkC;AAC3D,QAAM,QAAQ,eAAe,KAAK,IAAI;AACtC,QAAM,OAAO,QAAQ,KAAK,MAAM,GAAG,MAAM,KAAK,EAAE,KAAK,IAAI,KAAK,KAAK;AACnE,QAAM,SAAS,QAAQ,CAAC,GAAG,KAAK,KAAK;AACrC,QAAM,SAAS,KAAK,MAAM,KAAK,EAAE,OAAO,OAAO;AAC/C,QAAM,cAAc,OAAO,UAAU,KAAK,OAAO,UAAU,KAAK,OAAO,MAAM,OAAK,WAAW,KAAK,CAAC,CAAC;AACpG,MAAI,CAAC,eAAe,SAAS,IAAI;AAC/B,WACE,8CAAC,UAAK,WAAU,oBACd,wDAAC,UAAK,WAAU,oBAAoB,gBAAK,GAC3C;AAAA,EAEJ;AACA,QAAM,EAAE,OAAO,KAAK,IAAI,UAAU,IAAI;AACtC,SACE,+CAAC,UAAK,WAAU,oBACb;AAAA,aAAS,8CAAC,UAAK,WAAU,qBAAqB,iBAAM;AAAA,IACrD,8CAAC,UAAK,WAAU,oBAAoB,gBAAK;AAAA,IACxC,UAAU,8CAAC,UAAK,WAAU,sBAAsB,kBAAO;AAAA,KAC1D;AAEJ;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkD;AAChD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,QAAQ,UAAU,EAAE,QAAQ,aAAa,GAAG,GAAG,MAAM,MAAM;AAEjE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAA8B,oBAAI,IAAI,CAAC;AAC3E,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAS,CAAC;AAElC,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,UAAU,aAAa,WAAW,CAAC;AACzC,QAAM,aAAa,QAAQ,SAAS,KAAK,QAAQ,kBAAkB;AAEnE,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,cAAa,eAAY,0BAC9D;AAAA,oDAAC,cAAW,OAAc,QAAgB,WAAW,GAAG,MAAM;AAAA,MAC9D,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,YAAY,OAAO;AACzB,QAAM,QAAQ,UAAU;AACxB,QAAM,UAAU,UAAU,KAAK,IAAI,MAAM,QAAQ,CAAC,CAAC;AACnD,QAAM,SAAS,QAAQ,QAAQ;AAC/B,QAAM,kBAAkB,YAAY,UAAa,WAAW,IAAI,QAAQ,KAAK;AAC7E,QAAM,cAAc,WAAW,SAAS;AAExC,WAAS,aAAa,eAAuB,aAA2B;AACtE,QAAI,cAAc,WAAY;AAC9B,kBAAc,UAAQ,IAAI,IAAI,IAAI,EAAE,IAAI,eAAe,WAAW,CAAC;AAAA,EACrE;AAEA,WAAS,SAAe;AACtB,QAAI,CAAC,mBAAmB,OAAQ;AAChC,YAAQ,OAAK,IAAI,CAAC;AAAA,EACpB;AAEA,WAAS,SAAe;AACtB,YAAQ,OAAK,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAAA,EACjC;AAEA,WAAS,eAAqB;AAC5B,QAAI,CAAC,UAAU,CAAC,eAAe,cAAc,WAAY;AACzD,UAAM,UAAU,OAAO,UAAU,IAAI,QAAM;AAAA,MACzC,OAAO,EAAE;AAAA,MACT,qBAAqB,WAAW,IAAI,EAAE,KAAK,KAAK;AAAA,IAClD,EAAE;AACF,aAAS,KAAK,UAAU,EAAE,QAAQ,CAAC,CAAC;AAAA,EACtC;AAEA,MAAI,YAAY;AACd,UAAMC,YAA2B,UAAU,IAAI,OAAK;AAClD,YAAM,IAAI,WAAW,SAAS,EAAE,KAAK;AACrC,UAAI,CAAC,EAAG,QAAO;AACf,aAAO,EAAE,YAAY,YAAY;AAAA,IACnC,CAAC;AACD,UAAM,eAAe,QAAQ,OAAO,OAAK,EAAE,SAAS,EAAE;AACtD,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,cAAa,eAAY,0BAC9D;AAAA,oDAAC,cAAW,OAAc,SAAS,EAAE,SAAS,QAAgB,WAAW,GAAG,MAAM;AAAA,MAClF,8CAAC,mBAAgB,UAAUA,WAAU,WAAW,EAAE,SAAS;AAAA,MAC3D,+CAAC,SAAI,WAAU,aACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAO,QAAQ,SAAS,IAAI,EAAE,UAAU,cAAc,KAAK,IAAI,GAAG,MAAM;AAAA,YACxE,OAAO,QAAQ;AAAA,YACf;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QACC,UAAU,IAAI,OAAK;AAClB,gBAAM,IAAI,WAAW,SAAS,EAAE,KAAK;AACrC,gBAAM,SAAS,WAAW,IAAI,EAAE,KAAK;AACrC,iBACE,+CAAC,SAAkB,WAAU,cAC3B;AAAA,0DAAC,SAAI,WAAU,mBAAmB,YAAE,MAAK;AAAA,YACxC,KACC,8CAAC,SAAI,WAAU,mBACZ,YAAE,QAAQ,IAAI,CAAC,KAAK,WAAW;AAC9B,kBAAI,MAAM;AACV,kBAAI,WAAW,EAAE,mBAAoB,QAAO;AAAA,uBACnC,WAAW,UAAU,CAAC,EAAE,UAAW,QAAO;AACnD,qBAAO,8CAAC,UAAkB,WAAW,KAAM,iBAAzB,MAA6B;AAAA,YACjD,CAAC,GACH;AAAA,YAED,GAAG,cAAc,8CAAC,SAAI,WAAU,eAAe,YAAE,YAAW;AAAA,eAZrD,EAAE,KAaZ;AAAA,QAEJ,CAAC;AAAA,SACH;AAAA,OACF;AAAA,EAEJ;AAEA,QAAM,WAA2B,UAAU,IAAI,CAAC,GAAG,MAAO,IAAI,OAAO,SAAS,MAAM,OAAO,YAAY,MAAO;AAC9G,QAAM,cAAc,UAAU,WAAW,IAAI,QAAQ,KAAK,IAAI;AAE9D,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,cAAa,eAAY,0BAC9D;AAAA,kDAAC,cAAW,OAAc,SAAS,EAAE,WAAW,OAAO,GAAG,KAAK,GAAG,QAAgB,WAAW,GAAG,MAAM;AAAA,IACtG,8CAAC,mBAAgB,UAAoB,WAAW,EAAE,aAAa,OAAO,GAAG,KAAK,GAAG;AAAA,IACjF,8CAAC,SAAI,WAAU,aACZ,qBACC,gFACE;AAAA,oDAAC,QAAG,WAAU,gBAAgB,kBAAQ,MAAK;AAAA,MAC3C,8CAAC,SAAI,WAAU,gBACZ,kBAAQ,QAAQ,IAAI,CAAC,KAAK,WAAW;AACpC,cAAM,WAAW,WAAW;AAC5B,cAAM,YAAY,QAAQ,mBAAmB,MAAM,KAAK;AACxD,cAAM,aAAa;AACnB,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,gBAAc;AAAA,YACd,UAAU;AAAA,YACV,SAAS,MAAM,aAAa,QAAQ,OAAO,MAAM;AAAA,YAEhD;AAAA,sBAAQ,oBACP,8CAAC,gBAAa,MAAM,YAAY,WAAsB,WAAU,kBAAiB;AAAA,cAEnF,8CAAC,UAAK,WAAU,iBAAgB,eAAY,QACzC,qBAAW,8CAAC,aAAU,IAAK,OAAO,aAAa,KAAK,MAAM,GAC7D;AAAA,cACA,8CAAC,cAAW,MAAM,KAAK;AAAA;AAAA;AAAA,UAblB;AAAA,QAcP;AAAA,MAEJ,CAAC,GACH;AAAA,OACF,GAEJ;AAAA,IACA,8CAAC,aACC,yDAAC,SAAI,WAAU,eACZ;AAAA,aAAO,KACN,8CAAC,cAAW,SAAQ,WAAU,SAAS,QAAQ,UAAU,YAAa,YAAE,UAAS;AAAA,MAElF,SACC,8CAAC,cAAW,SAAQ,WAAU,OAAK,MAAC,SAAS,cAAc,UAAU,CAAC,mBAAmB,CAAC,eAAe,YACtG,uBAAa,EAAE,aAAa,EAAE,QACjC,IAEA,8CAAC,cAAW,SAAQ,WAAU,OAAK,MAAC,SAAS,QAAQ,UAAU,CAAC,mBAAmB,YAChF,YAAE,MACL;AAAA,OAEJ,GACF;AAAA,KACF;AAEJ;;;ACjNA,IAAAC,iBAAgC;AA6Ce,IAAAC,uBAAA;AAzB/C,IAAM,0BAA0B;AAKhC,SAASC,kBAAiB,MAAsE;AAC9F,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,YAA6B;AAC7C,MAAI;AACF,WAAO,IAAI,KAAK,UAAU,EAAE,QAAQ,KAAK,KAAK,IAAI;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAyB;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MAAI,OAAO;AAAA,MAAI,QAAQ;AAAA,MAAI,SAAQ;AAAA,MAAY,MAAK;AAAA,MAAO,QAAO;AAAA,MAAe,aAAa;AAAA,MAC7F,eAAc;AAAA,MAAQ,eAAY;AAAA,MAAO,wDAAC,UAAK,GAAE,YAAW;AAAA;AAAA,EAAE;AAEpE;AAEA,SAAS,UAAU,EAAE,MAAM,MAAM,GAAgE;AAC/F,SACE,+CAAC,SAAI,WAAU,gBACb;AAAA,kDAAC,eAAY,MAAM,KAAK,MAAM,MAAM,IAAI;AAAA,IACxC,8CAAC,UAAK,WAAU,qBAAqB,eAAK,MAAK;AAAA,IAC/C,8CAAC,UAAK,WAAU,qBAAqB,iBAAM;AAAA,KAC7C;AAEJ;AAEA,SAAS,UAAU,EAAE,MAAM,MAAM,GAAG,GAAG,GAAG,KAAK,GAO/B;AACd,QAAM,MAAM,CAAC,MAAY,MAA6B,UACpD,+CAAC,SAAI,WAAU,eACZ;AAAA,YACC;AAAA,MAAC;AAAA;AAAA,QAAO,MAAK;AAAA,QAAS,WAAU;AAAA,QAAe,cAAY,EAAE,QAAQ,KAAK,IAAI;AAAA,QAC5E,UAAU,KAAK;AAAA,QAAU,SAAS,MAAM,KAAK,OAAO,MAAM,CAAC;AAAA,QAC3D,wDAAC,YAAS,MAAM,IAAI;AAAA;AAAA,IACtB;AAAA,IAEF,8CAAC,UAAK,WAAU,iBAAgB,eAAY,YAAW,eAAa,OAAO,OAAO,KAAK,WAAW,IAAI,IAAI,SACvG,iBACH;AAAA,IACC,QACC;AAAA,MAAC;AAAA;AAAA,QAAO,MAAK;AAAA,QAAS,WAAU;AAAA,QAAe,cAAY,EAAE,UAAU,KAAK,IAAI;AAAA,QAC9E,UAAU,KAAK,YAAY,SAAS;AAAA,QAAG,SAAS,MAAM,KAAK,OAAO,MAAM,EAAE;AAAA,QAC1E,wDAAC,aAAU;AAAA;AAAA,IACb;AAAA,KAEJ;AAEF,SACE,+CAAC,SAAI,WAAU,gBACb;AAAA,kDAAC,aAAU,MAAM,MAAM,OAAO,EAAE,MAAM;AAAA,IACtC,+CAAC,SAAI,WAAU,kBACZ;AAAA,UAAI,QAAQ,MAAM,CAAC;AAAA,MACpB,8CAAC,UAAK,WAAU,gBAAe,eAAY,QAAO,oBAAC;AAAA,MAClD,IAAI,QAAQ,MAAM,CAAC;AAAA,OACtB;AAAA,IACA,8CAAC,aAAU,MAAM,MAAM,OAAO,EAAE,MAAM;AAAA,KACxC;AAEJ;AAEA,SAAS,WAAW,EAAE,OAAO,IAAI,QAAQ,EAAE,GAA6F;AACtI,SACE,+CAAC,QAAG,WAAU,eAAc,eAAY,UAAS,WAAS,OAAO,EAAE,GACjE;AAAA,kDAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,IACvC,+CAAC,UAAK,WAAU,iBACb;AAAA,WAAK,8CAAC,aAAU,IAAK,8CAAC,aAAU,MAAM,IAAI;AAAA,MAC3C,8CAAC,UAAK,WAAU,WAAW,eAAK,EAAE,UAAU,EAAE,WAAU;AAAA,MACvD,SAAS,8CAAC,UAAK,WAAU,iBAAiB,kBAAO,IAAU;AAAA,OAC9D;AAAA,KACF;AAEJ;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0D;AACxD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,CAAC;AAC5C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,CAAC;AAC5C,QAAM,CAAC,qBAAqB,sBAAsB,QAAI,yBAAwB,IAAI;AAClF,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAe,MAAM;AACzD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,eAAW,sBAAM;AAEvB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,gBAAgB,QAAQ,kBAAkB;AAEhD,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,UAAU,EAAE,QAAQ,qBAAqB,GAAG,GAAG,MAAM,MAAM;AAAA,MAClE,SAAS,SAAS,EAAE,QAAQ,OAAO,SAAS,MAAM,OAAO,SAAS,IAAI,IAAI;AAAA,MAC1E,OAAO,SAAS,8CAAC,QAAK,MAAM,8CAAC,YAAS,GAAK,aAAG,MAAM,cAAc,OAAO,UAAU,GAAE,IAAU;AAAA,MAC/F;AAAA,MACA,WAAW,GAAG;AAAA;AAAA,EAChB;AAIF,MAAI,iBAAiB,aAAa;AAChC,QAAI,CAAC,YAAY,QAAQ;AACvB,YAAM,SAAS,QAAQ,WAAW,KAAK,OAAK,EAAE,aAAa,YAAY,4BAA4B,KAAK;AACxG,aACE,+CAAC,SAAI,WAAU,eAAc,aAAU,sBAAqB,eAAY,kCACrE;AAAA;AAAA,QACD,+CAAC,SAAI,WAAU,aACZ;AAAA,oBACC;AAAA,YAAC;AAAA;AAAA,cAAU,MAAM,OAAO;AAAA,cAAU,MAAM,OAAO;AAAA,cAC7C,GAAG,YAAY;AAAA,cAAoB,GAAG,YAAY;AAAA,cAAoB;AAAA;AAAA,UAAM;AAAA,UAEhF;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO,EAAE;AAAA,cACT,QAAQ,EAAE,YAAY;AAAA,gBACpB,MAAM,QAAQ,SAAS,QAAQ;AAAA,gBAC/B,MAAM,QAAQ,SAAS,QAAQ;AAAA,gBAC/B,GAAG,YAAY;AAAA,gBACf,GAAG,YAAY;AAAA,gBACf,QAAQ,SAAS,UAAU,OAAO,UAAU,EAAE,OAAO;AAAA,cACvD,CAAC;AAAA,cACD;AAAA,cACA;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QACA,8CAAC,aACC,wDAAC,OAAE,WAAU,eAAe,YAAE,QAAO,GACvC;AAAA,SACF;AAAA,IAEJ;AAEA,UAAM,IAAI,YAAY;AACtB,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,sBAAqB,eAAY,kCACrE;AAAA;AAAA,MACD,+CAAC,SAAI,WAAU,aACZ;AAAA,kBAAU,8CAAC,aAAU,MAAM,OAAO,UAAU,MAAM,OAAO,UAAU,GAAG,EAAE,WAAW,GAAG,EAAE,WAAW,GAAM;AAAA,QAC1G,8CAAC,cAAW,MAAK,WAAU,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,GAAG,QAAgB,IAAQ;AAAA,QAChG,+CAAC,QAAG,WAAU,gBACZ;AAAA,wDAAC,cAAW,OAAO,EAAE,YAAY,IAAI,YAAY,mBAAmB,GAAM;AAAA,UAC1E,8CAAC,cAAW,OAAO,EAAE,SAAS,IAAI,YAAY,gBAAgB,GAAM;AAAA,UACnE,CAAC,YAAY,mBACZ,8CAAC,cAAW,OAAO,EAAE,gBAAgB,IAAI,YAAY,oBAAoB,QAAQ,EAAE,iBAAiB,GAAM;AAAA,WAE9G;AAAA,SACF;AAAA,MACA,8CAAC,aACC,wDAAC,OAAE,WAAU,eAAe,YAAE,QAAO,GACvC;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,sBAAqB,eAAY,kCACrE;AAAA;AAAA,MACD,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,SAAS,SAAS,OAAO,UAAU;AACzC,QAAM,WAAW,UAAU;AAE3B,WAAS,KAAK,MAAY,OAAqB;AAC7C,kBAAc,IAAI;AAClB,QAAI,SAAS,OAAQ,cAAa,OAAK,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,QACxD,cAAa,OAAK,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,EAC/C;AAEA,WAAS,eAAqB;AAC5B,QAAI,YAAY,CAAC,OAAQ;AACzB;AAAA,MACE,KAAK,UAAU;AAAA,QACb;AAAA,QACA;AAAA,QACA,GAAI,wBAAwB,OAAO,EAAE,oBAAoB,IAAI,CAAC;AAAA,MAChE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,OAAO,OAAO;AACpB,QAAM,aAAa,KAAK,SAAS;AACjC,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,QAAM,UAAU,cAAc,IAAI,KAAK,OAAO,OAAK,EAAE,WAAW,YAAY,EAAE,SAAS,CAAC,CAAC,IAAI;AAE7F,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,sBAAqB,eAAY,kCACrE;AAAA;AAAA,IACD,+CAAC,SAAI,WAAU,aACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,UACb,GAAG;AAAA,UACH,GAAG;AAAA,UACH;AAAA,UACA,MAAM,EAAE,UAAU,QAAQ,YAAY,QAAQ,KAAK;AAAA;AAAA,MACrD;AAAA,MAEC,KAAK,SAAS,KACb,+CAAC,aAAQ,WAAU,kBACjB;AAAA,uDAAC,SAAI,WAAU,oBACb;AAAA,wDAAC,QAAI,YAAE,aAAY;AAAA,UACnB,8CAAC,UAAM,YAAE,UAAS;AAAA,WACpB;AAAA,QACC,cACC;AAAA,UAAC;AAAA;AAAA,YAAY,IAAI;AAAA,YAAU,OAAO,EAAE;AAAA,YAAa,aAAW;AAAA,YAAC,aAAa,EAAE;AAAA,YAC1E,OAAO;AAAA,YAAO,UAAU;AAAA,YAAU;AAAA;AAAA,QAAoB;AAAA,QAE1D,8CAAC,SAAI,WAAU,gBACZ,kBAAQ,IAAI,OAAK;AAChB,gBAAM,WAAW,wBAAwB,EAAE;AAC3C,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,gBAAc;AAAA,cACd,cAAY,EAAE;AAAA,cACd;AAAA,cACA,SAAS,MAAM,uBAAuB,QAAO,OAAO,EAAE,WAAW,OAAO,EAAE,QAAS;AAAA,cAElF;AAAA,4BAAY,8CAAC,UAAK,WAAU,kBAAiB,wDAAC,aAAU,MAAM,IAAI,GAAE;AAAA,gBACrE,8CAAC,cAAW,MAAM,IAAI,SAAS,WAAW,aAAa,WAAW;AAAA,gBAClE,8CAAC,UAAK,WAAU,iBAAiB,oBAAU,EAAE,UAAU,EAAE,MAAK;AAAA;AAAA;AAAA,YAVzD,EAAE;AAAA,UAWT;AAAA,QAEJ,CAAC,GACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,gBAAc,wBAAwB;AAAA,YACtC;AAAA,YACA,SAAS,MAAM,uBAAuB,IAAI;AAAA,YAE1C;AAAA,4DAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO;AAAA,cAClD,EAAE;AAAA;AAAA;AAAA,QACL;AAAA,SACF;AAAA,MAGD,UAAU,8CAAC,OAAE,WAAU,kBAAkB,YAAE,QAAO;AAAA,OACrD;AAAA,IAEA,+CAAC,aACC;AAAA,oDAAC,cAAW,SAAQ,WAAU,OAAK,MAAC,UAAoB,SAAS,cAC9D,uBAAa,EAAE,SAAS,EAAE,MAC7B;AAAA,MACA,8CAAC,OAAE,WAAU,eAAe,YAAE,QAAO;AAAA,OACvC;AAAA,KACF;AAEJ;;;ACzSA,IAAAC,iBAAgC;AA2FnB,IAAAC,uBAAA;AAtEb,IAAM,qBAAqB;AAC3B,IAAM,UAAU;AAChB,IAAM,oBAAoB;AAS1B,SAASC,kBAAiB,MAA+D;AACvF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,eAAe,WAA2D;AACxF,QAAM,QAAQ,UAAU,MAAM,GAAG,EAAE,IAAI,MAAM,EAAE,OAAO,OAAK,IAAI,CAAC;AAChE,QAAM,QAAQ,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,UAAU;AAC7D,QAAM,OAAO,QAAQ,YAAY;AACjC,QAAM,WAAW,QAAQ,QAAQ,kBAAkB,MAAM,GAAG,EAAE,IAAI,MAAM;AACxE,QAAM,QAAQ,CAAC,GAAG,GAAG,QAAQ;AAC7B,QAAM,WAAW,oBAAoB,IAAI;AACzC,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAQ,CAAC,OAAO,OAAO;AAC3B,UAAM,MAAM,KAAK,MAAM,MAAM,MAAM,SAAS;AAC5C,aAAS,KAAK,GAAG,KAAK,OAAO,MAAM;AACjC,YAAM,OAAO,UAAU,IAAI,KAAK,KAAK,MAAM,MAAM,QAAQ;AACzD,YAAM,KAAK,EAAE,OAAO,MAAM,QAAQ,OAAO,WAAW,EAAE,IAAI,EAAE,KAAK,aAAa,IAAI,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;AAAA,IAC9G;AAAA,EACF,CAAC;AACD,SAAO,EAAE,WAAW,MAAM,MAAM;AAClC;AAEA,SAAS,WAAW,aAA+C;AACjE,QAAM,IAAI,YAAY,UAAU,OAAK,MAAM,IAAI;AAC/C,SAAO,MAAM,KAAK,OAAO;AAC3B;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,aAAa,cAAc,QAAI,yBAA4B,MAAM,MAAqB,OAAO,EAAE,KAAK,IAAI,CAAC;AAChH,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAwB,CAAC;AACrD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,eAAW,sBAAM;AAEvB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,gBAAgB,QAAQ,kBAAkB;AAEhD,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,UAAU,EAAE,QAAQ,cAAc,GAAG,GAAG,MAAM,MAAM;AAAA,MAC3D,SAAS,EAAE;AAAA,MACX,OAAO,8CAAC,QAAK,SAAQ,UAAU,YAAE,WAAW,kBAAkB,GAAE;AAAA,MAChE;AAAA,MACA,WAAW,GAAG;AAAA;AAAA,EAChB;AAIF,WAAS,aAAa,OAAe,OAA6B;AAChE,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC9D;AAAA;AAAA,MACD,8CAAC,SAAI,WAAU,aACb,wDAAC,cAAW,MAAK,WAAU,OAAc,OAAc,QAAgB,IAAQ,GACjF;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,eAAe;AACjB,QAAI,CAAC,YAAa,QAAO,aAAa,EAAE,MAAM;AAC9C,QAAI,YAAY,WAAW,UAAW,QAAO,aAAa,EAAE,QAAQ,YAAY,cAAc,CAAC;AAC/F,QAAI,YAAY,WAAW,SAAU,QAAO,aAAa,EAAE,WAAW,YAAY,YAAY,GAAG,YAAY,KAAK;AAAA,EACpH;AAEA,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC9D;AAAA;AAAA,MACD,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,EAAE,WAAW,MAAM,IAAI,eAAe,OAAO,SAAS;AAC5D,QAAM,OAAO,IAAI,IAAkC,OAAO,WAAW,IAAI,OAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC9F,QAAM,cAAc,YAAY,OAAO,OAAK,MAAM,IAAI,EAAE;AACxD,QAAM,YAAY,gBAAgB,WAAW,CAAC;AAC9C,QAAM,YAAY,IAAI,IAAI,YAAY,OAAO,CAAC,MAAmB,MAAM,IAAI,CAAC;AAC5E,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,QAAM,YAAY,OAAO,WAAW;AAAA,IAClC,OAAK,CAAC,UAAU,IAAI,EAAE,QAAQ,MAAM,CAAC,MAAM,EAAE,cAAc,IAAI,YAAY,EAAE,SAAS,CAAC;AAAA,EACzF;AACA,QAAM,aAAa,WAAW,OAAO,MAAM,MAAM,KAAK,OAAO;AAE7D,WAAS,KAAK,UAAwB;AACpC,QAAI,cAAc,WAAW,KAAM;AACnC,UAAM,OAAO,CAAC,GAAG,WAAW;AAC5B,SAAK,MAAM,IAAI;AACf,mBAAe,IAAI;AACnB,cAAU,WAAW,IAAI,CAAC;AAC1B,aAAS,EAAE;AAAA,EACb;AAEA,WAAS,QAAQ,OAAqB;AACpC,QAAI,WAAY;AAChB,QAAI,YAAY,KAAK,MAAM,MAAM;AAC/B,YAAM,OAAO,CAAC,GAAG,WAAW;AAC5B,WAAK,KAAK,IAAI;AACd,qBAAe,IAAI;AAAA,IACrB;AACA,cAAU,KAAK;AAAA,EACjB;AAEA,WAAS,eAAqB;AAC5B,QAAI,CAAC,UAAW;AAChB,aAAS,KAAK,UAAU,EAAE,oBAAoB,YAAY,CAAC,CAAC;AAAA,EAC9D;AAEA,QAAM,WAA2B,YAAY,IAAI,OAAM,MAAM,OAAO,YAAY,MAAO;AAEvF,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC9D;AAAA;AAAA,IACD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,EAAE,OAAO,WAAW;AAAA,QAC/B,WAAW,EAAE,OAAO,WAAW;AAAA,QAC/B,YAAY,EAAE,KAAK,UAAU,WAAW;AAAA,QACxC,OAAO,8CAAC,QAAM,qBAAU;AAAA;AAAA,IAC1B;AAAA,IACA,+CAAC,SAAI,WAAU,aACb;AAAA,qDAAC,SAAI,WAAU,iBACb;AAAA,sDAAC,YAAS,SAAQ,QAAO;AAAA,QACxB,MAAM,IAAI,OAAK;AACd,gBAAM,WAAW,YAAY,EAAE,KAAK,KAAK;AACzC,gBAAM,SAAS,aAAa,OAAO,KAAK,IAAI,QAAQ,KAAK,OAAO;AAChE,gBAAM,OAAO,QAAQ,cAAc;AACnC,gBAAM,QAAQ,SAAS,WAAW,WAAW,EAAE,QAAQ,WAAW;AAClE,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,cAAY;AAAA,cACZ,OAAO,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK,KAAK,GAAG,EAAE,GAAG,IAAI;AAAA,cAC9C,gBAAc,WAAW,EAAE;AAAA,cAC3B,cAAY,SAAS,EAAE,UAAU,EAAE,OAAO,IAAI,IAAI,EAAE,SAAS,EAAE,KAAK;AAAA,cACpE,UAAU;AAAA,cACV,SAAS,MAAM,QAAQ,EAAE,KAAK;AAAA,cAE9B;AAAA,8DAAC,UAAK,WAAU,gBAAe,eAAY,QACxC,mBAAU,OAAO,gBAAgB,KAAM,8CAAC,YAAS,MAAM,IAAI,GAC9D;AAAA,gBACA,8CAAC,UAAK,WAAU,eAAc,eAAY,QAAQ,mBAAS,UAAU,IAAI,EAAE,OAAO,EAAE,OAAM;AAAA;AAAA;AAAA,YAbrF,EAAE;AAAA,UAcT;AAAA,QAEJ,CAAC;AAAA,SACH;AAAA,MAEA,+CAAC,SAAI,WAAU,kBACb;AAAA,sDAAC,SAAI,WAAU,uBACZ,uBACC,gFACE;AAAA,wDAAC,QAAK,SAAQ,SAAS,qBAAW,OAAM;AAAA,UACxC,8CAAC,YAAQ,YAAE,QAAQ,WAAW,KAAK,GAAE;AAAA,WACvC,IAEA,8CAAC,YAAQ,YAAE,WAAU,GAEzB;AAAA,QACC,cACC,gFACE;AAAA;AAAA,YAAC;AAAA;AAAA,cAAY,IAAI;AAAA,cAAU,OAAO,EAAE;AAAA,cAAa,aAAW;AAAA,cAAC,aAAa,EAAE;AAAA,cAC1E,OAAO;AAAA,cAAO,UAAU;AAAA,cAAU,UAAU;AAAA;AAAA,UAAY;AAAA,UAC1D,8CAAC,QAAG,WAAU,gBACX,oBAAU,IAAI,OACb,8CAAC,QACC,yDAAC,YAAO,MAAK,UAAS,WAAU,eAAc,UAAU,YAAY,SAAS,MAAM,KAAK,EAAE,QAAQ,GAChG;AAAA,0DAAC,UAAK,WAAU,kBAAiB,eAAY,QAAQ,YAAE,gBAAgB,IAAG;AAAA,YAC1E,8CAAC,UAAK,WAAU,oBAAoB,YAAE,YAAW;AAAA,YACjD,8CAAC,UAAK,WAAU,mBAAmB,YAAE,cAAa;AAAA,aACpD,KALO,EAAE,QAMX,CACD,GACH;AAAA,WACF;AAAA,SAEJ;AAAA,OACF;AAAA,IACA,+CAAC,aACC;AAAA,oDAAC,cAAW,SAAQ,WAAU,OAAK,MAAC,UAAU,CAAC,WAAW,SAAS,cAChE,uBAAa,EAAE,aAAa,EAAE,QACjC;AAAA,MACA,+CAAC,OAAE,WAAU,gBACX;AAAA,sDAAC,YAAS;AAAA,QACT,YAAY,EAAE,QAAQ,GAAG,MAAM,cAAc,SAAS,CAAC,IAAI,EAAE;AAAA,SAChE;AAAA,OACF;AAAA,KACF;AAEJ;;;ACjPA,IAAAC,iBAAgC;AAkD5B,IAAAC,uBAAA;AAxBG,SAAS,WAAW,QAA6C;AACtE,QAAM,UAAU,OAAO,KAAK,OAAK,EAAE,SAAS,CAAC;AAC7C,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,QAAQ,OAAO,KAAK,OAAK,EAAE,SAAS,CAAC;AAC3C,QAAM,QAAQ,OAAO,KAAK,OAAK,EAAE,SAAS,CAAC;AAC3C,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,OAAO,OAAO,aAAa,EAAE,MAAM,MAAM,YAAY,MAAM,MAAM,YAAY,QAAQ,UAAU,IAAI;AAAA,IACnG,OAAO,OAAO,aAAa,EAAE,MAAM,MAAM,YAAY,MAAM,QAAQ,YAAY,MAAM,UAAU,IAAI;AAAA,EACrG;AACF;AAEA,SAASC,kBAAiB,MAA+D;AACvF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,EAAE,KAAK,GAAkC;AAC1D,QAAM,EAAE,OAAO,KAAK,IAAI,UAAU,IAAI;AACtC,SACE,+CAAC,UAAK,WAAU,gBACb;AAAA,aAAS,8CAAC,WAAO,aAAG,MAAM,CAAC,CAAC,KAAI;AAAA,IACjC,8CAAC,OAAG,gBAAK;AAAA,KACX;AAEJ;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAwB,IAAI;AAChE,QAAM,eAAW,sBAAM;AAEvB,QAAM,cAAcA,kBAAiB,QAAQ,eAAe;AAC5D,QAAM,WAAW,eAAe;AAEhC,QAAM,SACJ,8CAAC,cAAW,OAAO,UAAU,EAAE,QAAQ,cAAc,GAAG,GAAG,MAAM,MAAM,GAAG,SAAS,EAAE,SAAS,QAAgB,WAAW,GAAG,MAAM;AAGpI,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC9D;AAAA;AAAA,MACD,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,WAAW,EAAE,SAAS,OAAO,SAAS;AAC5C,QAAM,OAAO,WAAW,OAAO,WAAW,OAAO,MAAM;AACvD,QAAM,QAAQ,CAAC,GAAG,OAAO,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAC/D,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,QAAM,OAAO,IAAI,OAAO,WAAW,OAAO,OAAK,EAAE,WAAW,YAAY,EAAE,SAAS,CAAC,CAAC,IAAI,OAAO;AAEhG,WAAS,QAAc;AACrB,QAAI,eAAe,QAAQ,cAAc,SAAU;AACnD,aAAS,KAAK,UAAU,EAAE,iBAAiB,WAAW,CAAC,CAAC;AAAA,EAC1D;AAEA,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,eAAc,eAAY,2BAC9D;AAAA;AAAA,IACD,+CAAC,SAAI,WAAU,aACZ;AAAA,OAAC,YAAY,8CAAC,mBAAgB,QAAQ,OAAO,cAAc,aAAa,GAAG,IAAQ;AAAA,MACpF,+CAAC,SAAI,WAAU,kBACb;AAAA,sDAAC,QAAK,SAAQ,UAAS,MAAM,8CAAC,cAAW,MAAM,IAAI,GAAI,WAAU,gBAAgB,iBAAO,WAAU;AAAA,QAClG,+CAAC,QAAG,WAAU,aACX;AAAA,mBAAS;AAAA,UAAI,8CAAC,QAAI,mBAAS,MAAK;AAAA,UAAM,SAAS;AAAA,WAClD;AAAA,SACF;AAAA,MAEA,8CAAC,QAAG,WAAU,iBACX,gBAAM;AAAA,QAAI,UACT,KAAK,SAAS,IACZ;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,eAAa,WAAY,YAAa,YAAY,YAAY,UAAW;AAAA,YAEzE;AAAA,4DAAC,UAAK,WAAU,gBAAe,eAAC;AAAA,cAC/B,WACG,8CAAC,gBAAa,MAAM,YAAa,cAAc,YAAY,WAAU,cAAa,IAClF,8CAAC,cAAW,MAAM,IAAI,SAAQ,WAAU;AAAA,cAC3C,WACG,8CAAC,aAAU,MAAM,YAAa,cAAc,YAAY,IACxD,8CAAC,UAAK,WAAU,eAAe,YAAE,WAAU;AAAA,cAC/C,8CAAC,UAAK,WAAU,oCAAoC,eAAK,WAAU;AAAA;AAAA;AAAA,UAZ9D,KAAK;AAAA,QAaZ,IAEA,+CAAC,QAAmB,WAAU,gBAC5B;AAAA,wDAAC,UAAK,WAAU,gBAAgB,eAAK,MAAK;AAAA,UAC1C,8CAAC,gBAAa,MAAM,KAAK,cAAc,KAAK,WAAU,cAAa;AAAA,UACnE,8CAAC,aAAU,MAAM,KAAK,cAAc,KAAK;AAAA,UACzC,8CAAC,UAAK,WAAU,eAAe,eAAK,WAAU;AAAA,aAJvC,KAAK,IAKd;AAAA,MAEJ,GACF;AAAA,MAEC,QACC,+CAAC,OAAE,WAAU,gBACX;AAAA,sDAAC,YAAS;AAAA,QACV,8CAAC,UAAM,YAAE,KAAK,MAAM,OAAO,SAAS,GAAE;AAAA,SACxC;AAAA,MAGD,CAAC,YACA,8CAAC,QAAG,WAAU,gBACX,eAAK,IAAI,OACR,8CAAC,QACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,cAAY,EAAE;AAAA,UACd,gBAAc,eAAe,EAAE;AAAA,UAC/B,UAAU;AAAA,UACV,SAAS,MAAM;AAAE,0BAAc,EAAE,QAAQ;AAAG,qBAAS,EAAE,UAAU;AAAA,UAAE;AAAA,UAEnE;AAAA,0DAAC,gBAAa,MAAM,EAAE,YAAY,WAAU,kBAAiB;AAAA,YAC7D,8CAAC,UAAK,WAAU,oBAAoB,YAAE,YAAW;AAAA,YAChD,eAAe,EAAE,YAAY,8CAAC,aAAU;AAAA;AAAA;AAAA,MAC3C,KAZO,EAAE,QAaX,CACD,GACH;AAAA,MAGD,YACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,YAAa,YAAY,QAAQ;AAAA,UACvC,OAAO,YAAa,YAAY,EAAE,UAAU,EAAE,MAAM,YAAa,cAAc,UAAU;AAAA,UACzF,OAAO,QAAQ;AAAA,UACf;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,IAEC,CAAC,YACA,8CAAC,aACC,yDAAC,SAAI,WAAU,iBACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,OAAO,EAAE;AAAA,UACT,aAAW;AAAA,UACX,aAAa,EAAE;AAAA,UACf,OAAO;AAAA,UACP,UAAU,OAAK;AAAE,qBAAS,CAAC;AAAG,0BAAc,IAAI;AAAA,UAAE;AAAA,UAClD,UAAU;AAAA;AAAA,MACZ;AAAA,MACA,8CAAC,cAAW,SAAQ,WAAU,UAAU,eAAe,QAAQ,YAAY,SAAS,OACjF,YAAE,OACL;AAAA,OACF,GACF;AAAA,KAEJ;AAEJ;;;AC/J0D,IAAAC,uBAAA;AA1B1D,SAASC,mBAAiB,MAA4D;AACpF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAgD;AAC9C,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,cAAcA,mBAAiB,QAAQ,eAAe;AAC5D,QAAM,eAAe,QAAQ,kBAAkB;AAC/C,QAAM,WAAW,aAAa,kBAAkB;AAEhD,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE;AAAA,MACT,SAAS,EAAE;AAAA,MACX,OAAO,eAAe,8CAAC,QAAK,SAAQ,WAAU,MAAM,8CAAC,aAAU,GAAK,YAAE,OAAM,IAAU;AAAA,MACtF;AAAA,MACA,WAAW,GAAG;AAAA;AAAA,EAChB;AAGF,MAAI,CAAC,QAAQ;AACX,WACE,+CAAC,SAAI,WAAU,eAAc,aAAU,YAAW,eAAY,wBAC3D;AAAA;AAAA,MACD,8CAAC,SAAI,WAAU,0BAA0B,aAAG,MAAM,SAAQ;AAAA,OAC5D;AAAA,EAEJ;AAEA,QAAM,SAAS,OAAO,WAAW,KAAK,OAAK,EAAE,aAAa,QAAQ,KAAK;AAEvE,WAAS,WAAW,aAA2B;AAC7C,QAAI,gBAAgB,WAAY;AAChC,aAAS,KAAK,UAAU,EAAE,gBAAgB,YAAY,CAAC,CAAC;AAAA,EAC1D;AAEA,SACE,+CAAC,SAAI,WAAU,eAAc,aAAU,YAAW,eAAY,wBAC3D;AAAA;AAAA,IACD,+CAAC,SAAI,WAAU,aACb;AAAA,oDAAC,QAAG,WAAU,kBACX,iBAAO,WAAW,IAAI,OAAK;AAC1B,cAAM,UAAU,gBAAgB,aAAa,EAAE;AAC/C,eACE,8CAAC,QACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAW,gBAAgB,UAAU,0BAA0B,EAAE;AAAA,YACjE,eAAa,kBAAkB,EAAE,QAAQ;AAAA,YACzC,UAAU,gBAAgB;AAAA,YAC1B,SAAS,MAAM,WAAW,EAAE,QAAQ;AAAA,YAEpC;AAAA,4DAAC,gBAAa,MAAM,EAAE,YAAY,WAAU,gBAAe;AAAA,cAC3D,8CAAC,UAAK,WAAU,kBAAkB,YAAE,YAAW;AAAA,cAC9C,WAAW,8CAAC,QAAK,SAAQ,UAAS,WAAU,kBAAkB,YAAE,UAAS;AAAA;AAAA;AAAA,QAC5E,KAXO,EAAE,QAYX;AAAA,MAEJ,CAAC,GACH;AAAA,MACC,gBAAgB,UACf,8CAAC,cAAW,MAAK,WAAU,OAAO,EAAE,SAAS,OAAO,UAAU,GAAG,QAAQ,EAAE,QAAQ,QAAgB,IAAQ;AAAA,OAE/G;AAAA,IACA,+CAAC,aACE;AAAA,OAAC,gBAAgB,8CAAC,OAAE,WAAU,kBAAkB,YAAE,WAAU;AAAA,MAC7D,8CAAC,OAAE,WAAU,iBAAiB,YAAE,QAAO;AAAA,OACzC;AAAA,KACF;AAEJ;;;AzBqCU,IAAAC,uBAAA;AApGV,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,2BAA2B;AAEjC,SAAS,gBAAmB,MAA2C;AACrE,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOgB;AACd,QAAM,EAAE,QAAQ,WAAW,UAAU,IAAI,YAAY,KAAK,IAAI;AAG9D,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAwB,IAAI;AAEhE,gCAAU,MAAM;AACd,kBAAc,IAAI;AAClB,QAAI,CAAC,aAAc;AACnB,QAAI,YAAY;AAChB,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,UAAU,MAAM,aAAa,cAAc,QAAQ,WAAW,WAAW,QAAW,GAAG,MAAM,IAAI;AACvG,YAAI,CAAC,aAAa,SAAS,YAAY;AACrC,wBAAc,QAAQ,UAAU;AAAA,QAClC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,cAAc,QAAQ,WAAW,SAAS,GAAG,MAAM,IAAI,CAAC;AAG5D,QAAM,EAAE,QAAQ,YAAY,QAAQ,SAAS,UAAU,IAAI,YAAY,cAAc;AAAA,IACnF;AAAA,IACA;AAAA,IACA,WAAW,aAAa;AAAA,IACxB,QAAQ,GAAG,MAAM;AAAA,EACnB,CAAC;AAGD,gCAAU,MAAM;AACd,QAAI,aAAc,SAAQ;AAAA,EAE5B,GAAG,CAAC,cAAc,MAAM,CAAC;AAIzB,QAAM,iBAAa,uBAAO,OAAO;AACjC,aAAW,UAAU;AAErB,gCAAU,MAAM;AACd,QAAI,CAAC,iBAAiB,IAAI,MAAM,EAAG;AACnC,QAAI,cAAc,UAAW;AAE7B,UAAM,UAAU,YAAY,MAAM;AAChC,iBAAW,QAAQ;AAAA,IACrB,GAAG,wBAAwB;AAE3B,WAAO,MAAM,cAAc,OAAO;AAAA,EACpC,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA;AAAA;AAAA,IAGA,UAAU,CAAC,eAAuB;AAAE,WAAK,OAAO,UAAU,EAAE,KAAK,MAAM,WAAW,CAAC;AAAA,IAAE;AAAA,IACrF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,WAAS,eAA4B;AACnC,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAoC,UAAU;AAAA;AAAA,QACxD;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAA2B,UAAU;AAAA;AAAA,QAC/C;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAkC,UAAU;AAAA;AAAA,QACtD;AAAA,MAEJ,KAAK,iBAAiB;AACpB,cAAM,YAAY,gBAAmC,UAAU;AAC/D,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ;AAAA,YACR,YAAY,WAAW,cAAc,CAAC;AAAA;AAAA,QACxC;AAAA,MAEJ;AAAA,MACA,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAkC,UAAU;AAAA;AAAA,QACtD;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAiC,UAAU;AAAA;AAAA,QACrD;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAyC,UAAU;AAAA;AAAA,QAC7D;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAkC,UAAU;AAAA;AAAA,QACtD;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAAkC,UAAU;AAAA;AAAA,QACtD;AAAA,MAEJ,KAAK;AACH,eACE;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,QAAQ,gBAA+B,UAAU;AAAA;AAAA,QACnD;AAAA,MAEJ;AACE,eACE,8CAAC,SAAI,WAAU,eAAc,eAAa,eAAe,MAAM,IAC7D,wDAAC,cAAW,OAAO,UAAU,EAAE,OAAO,GAAG,GAAG,MAAM,MAAM,GAAG,QAAgB,WAAW,GAAG,MAAM,GACjG;AAAA,IAEN;AAAA,EACF;AAEA,SACE,8CAAC,SAAI,WAAU,gBAAe,eAAY,WAAU,gBAAc,aAAa,QAC5E,uBAAa,GAChB;AAEJ;;;A0BxNA,IAAAC,iBAAyB;;;ACiBnB,IAAAC,uBAAA;AAdC,SAAS,aAAa,GAAmB;AAC9C,SAAO,EAAE,eAAe,IAAI;AAC9B;AAEO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAGgB;AACd,QAAM,YAAY,gBAAgB,IAAI,QAAQ,IAAI,yBAAyB,EAAE;AAC7E,SACE,+CAAC,SAAI,WAAW,eAAe,OAAO,uBAAuB,EAAE,IAC7D;AAAA,mDAAC,UAAK,WAAW,WAAW;AAAA;AAAA,MAAE,IAAI;AAAA,OAAK;AAAA,IACvC,8CAAC,UAAK,WAAU,mBAAmB,cAAI,QAAO;AAAA,IAC9C,8CAAC,UAAK,WAAU,mBAAmB,uBAAa,IAAI,MAAM,GAAE;AAAA,IAC3D,IAAI,gBAAgB,KACnB,+CAAC,UAAK,WAAU,mBAAkB;AAAA;AAAA,MAAI,IAAI;AAAA,OAAc;AAAA,KAE5D;AAEJ;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAGgB;AACd,QAAM,YAAY,gBAAgB,IAAI,QAAQ,IAAI,yBAAyB,EAAE;AAC7E,SACE,+CAAC,SAAI,WAAW,eAAe,OAAO,uBAAuB,EAAE,IAC7D;AAAA,mDAAC,UAAK,WAAW,WAAW;AAAA;AAAA,MAAE,IAAI;AAAA,OAAK;AAAA,IACvC,8CAAC,UAAK,WAAU,mBAAmB,cAAI,QAAO;AAAA,IAC9C,8CAAC,UAAK,WAAU,mBAAmB,uBAAa,IAAI,aAAa,GAAE;AAAA,KACrE;AAEJ;;;ACdM,IAAAC,uBAAA;AAfC,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMgB;AACd,MAAI,YAAY,WAAW;AACzB,WACE,+CAAC,SAAI,WAAU,wCACb;AAAA,oDAAC,SAAI,WAAU,sBAAqB,eAAY,QAAO,uBAAE;AAAA,MACzD,8CAAC,OAAE,WAAU,sBAAsB,aAAG,yBAAwB;AAAA,OAChE;AAAA,EAEJ;AAEA,QAAM,QAAQ,YAAY;AAC1B,QAAM,QAAQ,QAAQ,GAAG,6BAA6B,GAAG;AACzD,QAAM,OAAO,QAAQ,GAAG,4BAA4B,GAAG;AAEvD,SACE,+CAAC,SAAI,WAAU,iBACZ;AAAA,mBACC,+CAAC,SAAI,WAAU,cACb;AAAA,oDAAC,UAAK,WAAU,mBAAkB,eAAY,QAAO,uBAAE;AAAA,MACvD,8CAAC,SAAI,WAAU,mBACb,wDAAC,UAAK,WAAU,mBAAmB,uBAAY,GACjD;AAAA,OACF;AAAA,IAGF,+CAAC,SAAI,WAAU,sBACb;AAAA,oDAAC,SAAI,WAAU,sBAAqB,eAAY,QAAQ,kBAAQ,cAAO,aAAK;AAAA,MAC5E,8CAAC,QAAG,WAAU,uBAAuB,iBAAM;AAAA,MAC3C,8CAAC,OAAE,WAAU,sBAAsB,gBAAK;AAAA,MACvC,UACC,8CAAC,YAAO,MAAK,UAAS,WAAU,qBAAoB,SAAS,QAC1D,aAAG,qBACN;AAAA,OAEJ;AAAA,IAEC,SAAS,YACR,+CAAC,SAAI,WAAU,gBACb;AAAA,oDAAC,UAAK,WAAU,sBAAsB,aAAG,0BAAyB;AAAA,MAClE,8CAAC,UAAK,WAAU,sBAAqB,eAAY,QAAO,uBAAE;AAAA,MAC1D,8CAAC,UAAK,WAAU,uBAAuB,mBAAS,QAAO;AAAA,MACvD,8CAAC,UAAK,WAAU,uBAAuB,uBAAa,SAAS,MAAM,GAAE;AAAA,OACvE;AAAA,KAEJ;AAEJ;;;AF3CM,IAAAC,uBAAA;AApBC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAKgB;AACd,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAkB,QAAQ;AAExD,QAAM,QAAQ,YAAY,WAAW,KAAK,cAAc,KAAK;AAC7D,QAAM,WAAW,UAAU,QAAQ,UAAU,UAAa,MAAM,SAAS;AACzE,QAAM,UAAU,YAAY,WACxB,KAAK,UAAU,WAAW,IAC1B,KAAK,WAAW,WAAW;AAE/B,SACE,+CAAC,SAAI,WAAU,YACb;AAAA,mDAAC,SAAI,WAAU,YACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACT,GAAI,YAAY,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;AAAA,UACjD,SAAS,MAAM,WAAW,QAAQ;AAAA,UAEjC,aAAG;AAAA;AAAA,MACN;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACT,GAAI,YAAY,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;AAAA,UAClD,SAAS,MAAM,WAAW,SAAS;AAAA,UAElC,aAAG;AAAA;AAAA,MACN;AAAA,OACF;AAAA,IAEC,UACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU,KAAK;AAAA,QACf,aAAa,KAAK;AAAA,QAClB;AAAA,QACA;AAAA;AAAA,IACF,IAEA,gFACE;AAAA,oDAAC,SAAI,WAAU,iBACZ,sBAAY,WACT,KAAK,UAAU,IAAI,CAAC,QAClB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,MAAM,IAAI,mBAAmB,KAAK,aAAa;AAAA;AAAA,QAF1C,IAAI;AAAA,MAGX,CACD,IACD,KAAK,WAAW,IAAI,CAAC,QACnB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,MAAM,IAAI,mBAAmB,KAAK,cAAc;AAAA;AAAA,QAF3C,IAAI;AAAA,MAGX,CACD,GACP;AAAA,MAGA,8CAAC,SAAI,WAAU,gBAAe,uBAAE;AAAA,MAG/B,SAAS,SACR,WACE,8CAAC,SAAI,WAAU,cAAc,aAAG,qBAAoB,IAEpD,+CAAC,SAAI,WAAU,iBACZ;AAAA,oBAAY,YAAY,KAAK,eAC5B,8CAAC,wBAAqB,KAAK,KAAK,aAAa,MAAI,MAAC;AAAA,QAEnD,YAAY,aAAa,KAAK,gBAC7B,8CAAC,yBAAsB,KAAK,KAAK,cAAc,MAAI,MAAC;AAAA,SAExD;AAAA,MAKH,YAAY,aAAa,KAAK,gBAAgB,CAAC,YAC9C,8CAAC,SAAI,WAAU,iBACb,wDAAC,SAAI,WAAU,gBACb,wDAAC,UAAK,WAAU,mBACb,uBAAa,KAAK,WAAW,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,eAAe,CAAC,CAAC,GACxE,GACF,GACF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AGrFwB,IAAAC,uBAAA;AAjBxB,IAAM,gBAAoC;AAAA,EACxC,MAAM;AAAA,EACN,WAAW,CAAC;AAAA,EACZ,aAAa;AAAA,EACb,YAAY,CAAC;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,UAAU;AACZ;AAEO,SAAS,iBAAiB,EAAE,UAAU,MAAM,SAAS,QAAQ,GAAG,GAMvD;AACd,MAAI,CAAC,SAAU,QAAO,8CAAC,kBAAe,IAAQ;AAE9C,MAAI,SAAS,QAAQ,QAAS,QAAO,8CAAC,SAAI,WAAU,iBAAgB;AACpE,SACE,8CAAC,SAAI,WAAU,iBACb,wDAAC,eAAY,MAAM,QAAQ,eAAe,IAAQ,QAAgB,GACpE;AAEJ;;;AC/BA,IAAM,gBAAgB;AACtB,IAAM,aACJ;AAIK,SAAS,iBAAiB,MAAgB,UAAgB;AAC/D,MAAI,CAAC,IAAI,KAAM;AACf,MAAI,IAAI,eAAe,aAAa,EAAG;AACvC,QAAM,OAAO,IAAI,cAAc,MAAM;AACrC,OAAK,KAAK;AACV,OAAK,MAAM;AACX,OAAK,OAAO;AACZ,MAAI,KAAK,YAAY,IAAI;AAC3B;;;ArCmBwB,IAAAC,uBAAA;AAvBjB,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASgB;AACd,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAkG,IAAI;AACtI,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAiC,MAAM;AAErE,gCAAU,MAAM;AAAE,qBAAiB;AAAA,EAAE,GAAG,CAAC,CAAC;AAE1C,MAAI,CAAC,SAAU,QAAO,8CAAC,kBAAe,IAAQ;AAE9C,MAAI,aAAa,MAAM;AACrB,WACE,8CAAC,SAAI,WAAU,qBAAoB,MAAM,GAAG,MAAM,MAChD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,QAAQ,MAAM;AAAE,sBAAY,IAAI;AAAG,uBAAa;AAAA,QAAE;AAAA,QAClD,UAAU;AAAA,QACV,cAAc,gBAAgB;AAAA,QAC9B;AAAA;AAAA,IACF,GACF;AAAA,EAEJ;AAEA,SACE,+CAAC,SAAI,WAAU,iBAAgB,MAAM,GAAG,MAAM,MAC5C;AAAA,mDAAC,SAAI,WAAU,YACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACT,GAAI,YAAY,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;AAAA,UAC/C,SAAS,MAAM,WAAW,MAAM;AAAA,UAE/B,aAAG;AAAA;AAAA,MACN;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACT,GAAI,YAAY,gBAAgB,EAAE,WAAW,GAAG,IAAI,CAAC;AAAA,UACtD,SAAS,MAAM,WAAW,aAAa;AAAA,UAEtC,aAAG;AAAA;AAAA,MACN;AAAA,OACF;AAAA,IACC,YAAY,SACX,8CAAC,SAAI,eAAY,aAAY,MAAM,GAAG,MAAM,MAC1C;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,QAAQ,CAAC,MAAmB,YAAY,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,SAAS,EAAE,SAAS,WAAW,EAAE,aAAa,KAAK,CAAC;AAAA,QACxI,aAAa,aAAa,eAAe;AAAA,QACzC;AAAA;AAAA,IACF,GACF,IAEA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,eAAe;AAAA,QACrB,SAAS,sBAAsB;AAAA,QAC/B,QAAQ,MAAM,WAAW,MAAM;AAAA,QAC/B;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;;;AsCrEwB,IAAAC,uBAAA;AAjBxB,SAAS,aAAa,UAA2E;AAC/F,QAAM,SAA2D,CAAC;AAClE,aAAW,MAAM,UAAU;AACzB,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,KAAK,UAAU,GAAG,MAAO,MAAK,MAAM,KAAK,EAAE;AAAA,QAClD,QAAO,KAAK,EAAE,OAAO,GAAG,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,EACnD;AACA,SAAO;AACT;AAEO,SAAS,SAAS,EAAE,UAAU,SAAS,GAAG,GAIjC;AACd,MAAI,SAAS,WAAW,GAAG;AAEzB,QAAI,QAAS,QAAO,8CAAC,SAAI,WAAU,iBAAgB;AACnD,WAAO,8CAAC,SAAI,WAAU,kBAAkB,aAAG,mBAAkB;AAAA,EAC/D;AAEA,SACE,8CAAC,SAAI,WAAU,iBACZ,uBAAa,QAAQ,EAAE,IAAI,CAAC,OAAO,OAClC,+CAAC,SACE;AAAA,UAAM,SAAS,8CAAC,SAAI,WAAU,qBAAqB,gBAAM,OAAM;AAAA,IAC/D,MAAM,MAAM,IAAI,CAAC,OAAO;AACvB,YAAM,SAAS,GAAG,cAAc,QAAQ,GAAG,cAAc;AACzD,YAAM,UAAU,GAAG,gBAAgB,GAAG,eAAe,GAAG,aAAa,IAAI;AACzE,aACE,+CAAC,SAAI,WAAU,YACb;AAAA,uDAAC,SAAI,WAAU,gBACZ;AAAA,aAAG,mBAAmB,8CAAC,UAAK,WAAU,iBAAiB,aAAG,iBAAgB;AAAA,UAC1E,CAAC,UAAU,WAAW,+CAAC,UAAK,WAAU,iBAAiB;AAAA,oBAAQ;AAAA,YAAS;AAAA,YAAI,QAAQ;AAAA,aAAK;AAAA,WAC5F;AAAA,QACA,+CAAC,SAAI,WAAU,iBACb;AAAA,wDAAC,UAAK,WAAU,iBACd,wDAAC,UAAK,WAAU,iBAAiB,aAAG,cAAa,GACnD;AAAA,UACC,SACC,+CAAC,UAAK,WAAU,kBAAkB;AAAA,eAAG;AAAA,YAAU,8CAAC,OAAE,eAAC;AAAA,YAAK,GAAG;AAAA,aAAU,IAErE,8CAAC,UAAK,WAAU,eAAc,gBAAE;AAAA,UAElC,8CAAC,UAAK,WAAU,qCACd,wDAAC,UAAK,WAAU,iBAAiB,aAAG,cAAa,GACnD;AAAA,WACF;AAAA,WAjB6B,GAAG,EAkBlC;AAAA,IAEJ,CAAC;AAAA,OA1BO,GAAG,EAAE,IAAI,MAAM,SAAS,MAAM,EA2BxC,CACD,GACH;AAEJ;;;ACvC4C,IAAAC,uBAAA;AAhB5C,SAAS,aAAa,MAA+E;AACnG,QAAM,SAA+D,CAAC;AACtE,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,KAAK,UAAU,IAAI,MAAO,MAAK,MAAM,KAAK,GAAG;AAAA,QACpD,QAAO,KAAK,EAAE,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,UAAU,EAAE,WAAW,SAAS,GAAG,GAInC;AAEd,MAAI,cAAc,QAAQ,QAAS,QAAO,8CAAC,SAAI,WAAU,iBAAgB;AACzE,MAAI,cAAc,QAAQ,UAAU,WAAW,EAAG,QAAO,8CAAC,SAAI,WAAU,kBAAkB,aAAG,oBAAmB;AAEhH,SACE,8CAAC,SAAI,WAAU,iBACZ,uBAAa,SAAS,EAAE,IAAI,CAAC,OAAO,OACnC,+CAAC,SAAI,WAAU,mBACZ;AAAA,UAAM,SAAS,8CAAC,SAAI,WAAU,qBAAqB,gBAAM,OAAM;AAAA,IAChE,+CAAC,WAAM,WAAU,iBACf;AAAA,oDAAC,WACC,yDAAC,QACC;AAAA,sDAAC,QAAG,eAAC;AAAA,QACL,8CAAC,QAAI,aAAG,kBAAiB;AAAA,QACzB,8CAAC,QAAI,aAAG,oBAAmB;AAAA,QAC3B,8CAAC,QAAI,aAAG,iBAAgB;AAAA,QACxB,8CAAC,QAAI,aAAG,mBAAkB;AAAA,QAC1B,8CAAC,QAAI,aAAG,kBAAiB;AAAA,QACzB,8CAAC,QAAI,aAAG,sBAAqB;AAAA,QAC7B,8CAAC,QAAI,aAAG,oBAAmB;AAAA,SAC7B,GACF;AAAA,MACA,8CAAC,WACE,gBAAM,MAAM,IAAI,CAAC,QAChB,+CAAC,QACC;AAAA,sDAAC,QAAI,cAAI,UAAS;AAAA,QAClB,8CAAC,QAAI,cAAI,UAAS;AAAA,QAClB,8CAAC,QAAI,cAAI,aAAY;AAAA,QACrB,8CAAC,QAAI,cAAI,MAAK;AAAA,QACd,8CAAC,QAAI,cAAI,OAAM;AAAA,QACf,8CAAC,QAAI,cAAI,QAAO;AAAA,QAChB,8CAAC,QAAI,cAAI,gBAAe;AAAA,QACxB,8CAAC,QAAI,cAAI,QAAO;AAAA,WART,IAAI,MASb,CACD,GACH;AAAA,OACF;AAAA,OA7BoC,GAAG,EAAE,IAAI,MAAM,SAAS,MAAM,EA8BpE,CACD,GACH;AAEJ;;;AC3DO,SAAS,gBAA2D,SAA6D;AACtI,QAAM,SAAwD,CAAC;AAC/D,aAAW,KAAK,SAAS;AACvB,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,KAAK,iBAAiB,EAAE,aAAc,MAAK,MAAM,KAAK,CAAC;AAAA,QAC9D,QAAO,KAAK,EAAE,cAAc,EAAE,cAAc,OAAO,CAAC,CAAC,EAAE,CAAC;AAAA,EAC/D;AACA,SAAO;AACT;;;ACNO,SAAS,cAAc,IAAc,MAAoC;AAC9E,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAc,aAAO,GAAG;AAAA,IAC7B,KAAK;AAAY,aAAO,GAAG;AAAA,IAC3B,KAAK;AAAc,aAAO,GAAG;AAAA,IAC7B,KAAK;AAAY,aAAO,GAAG;AAAA,IAC3B;AAAS,aAAO;AAAA,EAClB;AACF;AAEO,SAAS,UAAU,IAAc,MAAoC;AAC1E,QAAM,IAAI,MAAM,KAAK,KAAK;AAC1B,MAAI,MAAM,MAAM,EAAE,YAAY,MAAM,MAAO,QAAO;AAClD,UAAQ,EAAE,YAAY,GAAG;AAAA,IACvB,KAAK;AAAS,aAAO,GAAG;AAAA,IACxB,KAAK;AAAQ,aAAO,GAAG;AAAA,IACvB,KAAK;AAAQ,aAAO,GAAG;AAAA,IACvB;AAAS,aAAO;AAAA,EAClB;AACF;AAEA,IAAM,aAAqC,EAAE,YAAY,MAAM,UAAU,MAAM,YAAY,MAAM,UAAU,KAAK;AAEzG,SAAS,cAAc,MAAiC,cAAqC;AAClG,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY,KAAK;AACxC,MAAI,MAAM,GAAI,QAAO,MAAM,QAAQ,MAAM,OAAO,OAAO;AACvD,SAAQ,iBAAiB,QAAQ,WAAW,YAAY,KAAM;AAChE;AAEO,SAAS,aAAa,IAAc,QAAuB,aAA4B,SAAuC;AACnI,MAAI,WAAW,QAAQ,gBAAgB,QAAQ,YAAY,QAAQ,WAAW,EAAG,QAAO;AACxF,SAAO,GAAG,kBAAkB,QAAQ,aAAa,OAAO;AAC1D;;;ACVwC,IAAAC,uBAAA;AApBxC,SAAS,OAAO,OAAgC,MAA0E;AACxH,MAAI,OAAqC;AACzC,aAAW,KAAK,OAAO;AACrB,QAAI,KAAK,CAAC,KAAK,EAAG;AAClB,QAAI,SAAS,QAAQ,KAAK,CAAC,IAAI,KAAK,IAAI,KAAM,KAAK,CAAC,MAAM,KAAK,IAAI,KAAK,EAAE,gBAAgB,KAAK,cAAgB,QAAO;AAAA,EACxH;AACA,SAAO;AACT;AAEA,SAAS,YAAY,QAA+B;AAClD,MAAI,WAAW,KAAM,QAAO;AAC5B,SAAO,OAAO,OAAO,QAAQ,CAAC,CAAC,KAAK,IAAI,yCAAyC;AACnF;AAEO,SAAS,WAAW,EAAE,OAAO,SAAS,IAAI,eAAe,GAKhD;AACd,MAAI,UAAU,QAAQ,QAAS,QAAO,8CAAC,SAAI,WAAU,iBAAgB;AACrE,MAAI,UAAU,QAAQ,MAAM,WAAW,EAAG,QAAO,8CAAC,SAAI,WAAU,kBAAkB,aAAG,qBAAoB;AAEzG,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK;AAC3C,QAAM,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO;AAC/C,QAAM,SAAS;AAAA,IACb,UAAU,GAAG,eAAe,OAAO,YAAY,OAAO,KAAK;AAAA,IAC3D,YAAY,GAAG,gBAAgB,SAAS,YAAY,SAAS,OAAO;AAAA,EACtE,EAAE,OAAO,CAAC,SAAyB,CAAC,CAAC,IAAI,EAAE,KAAK,QAAK;AAErD,SACE,+CAAC,SAAI,WAAU,+BACb;AAAA,mDAAC,SAAI,WAAU,gBACf;AAAA,qDAAC,SAAI,WAAU,4BAA2B,eAAY,QACpD;AAAA,sDAAC,UAAK,WAAU,gBAAe;AAAA,QAC/B,8CAAC,UAAK,WAAU,eAAe,aAAG,aAAY;AAAA,QAC9C,8CAAC,UAAK,WAAU,eAAe,aAAG,aAAY;AAAA,QAC9C,8CAAC,UAAK,WAAU,eAAe,aAAG,cAAa;AAAA,QAC/C,8CAAC,UAAK,WAAU,eAAe,aAAG,eAAc;AAAA,QAChD,8CAAC,UAAK,WAAU,eAAe,aAAG,iBAAgB;AAAA,QAClD,8CAAC,UAAK,WAAU,0BAA0B,aAAG,gBAAe;AAAA,QAC5D,8CAAC,UAAK,WAAU,0BAA0B,aAAG,aAAY;AAAA,QACzD,8CAAC,UAAK,WAAU,eAAe,aAAG,gBAAe;AAAA,SACnD;AAAA,MACC,MAAM,IAAI,CAAC,MACV,+CAAC,YAAO,MAAK,UAAS,WAAU,2BAA2C,SAAS,MAAM,eAAe,EAAE,QAAQ,GACjH;AAAA,uDAAC,UAAK,WAAU,kBACb;AAAA,YAAE,iBAAiB,QAAQ,8CAAC,UAAK,WAAU,iBAAiB,YAAE,cAAa;AAAA,UAC5E,8CAAC,UAAK,WAAU,+BAA+B,YAAE,YAAW;AAAA,WAC9D;AAAA,QACA,8CAAC,UAAK,WAAU,eAAe,wBAAc,EAAE,cAAc,EAAE,YAAY,GAAE;AAAA,QAC7E,8CAAC,UAAK,WAAU,eAAe,YAAE,aAAY;AAAA,QAC7C,8CAAC,UAAK,WAAU,eAAe,YAAE,eAAc;AAAA,QAC/C,8CAAC,UAAK,WAAU,eAAe,YAAE,OAAM;AAAA,QACvC,8CAAC,UAAK,WAAU,eAAe,YAAE,SAAQ;AAAA,QACzC,8CAAC,UAAK,WAAU,0BAA0B,YAAE,aAAY;AAAA,QACxD,8CAAC,UAAK,WAAU,0BAA0B,YAAE,UAAS;AAAA,QACrD,8CAAC,UAAK,WAAW,YAAY,EAAE,aAAa,GACzC,YAAE,kBAAkB,OAAO,WAAM,EAAE,cAAc,QAAQ,CAAC,GAC7D;AAAA,WAd6D,EAAE,QAejE,CACD;AAAA,OACD;AAAA,IACC,WAAW,MAAM,8CAAC,SAAI,WAAU,gBAAgB,kBAAO;AAAA,KAC1D;AAEJ;;;ACjDI,IAAAC,uBAAA;AAfG,SAAS,MAAM,EAAE,OAAO,SAAS,IAAI,MAAM,cAAc,OAAO,cAAc,aAAa,MAAM,kBAAkB,MAAM,gBAAgB,MAAM,eAAe,GAYrJ;AACd,QAAM,UAAU,SAAS,UAAU,aAAa,IAAI,YAAY,iBAAiB,aAAa,IAAI;AAClG,QAAM,SACJ,+CAAC,SAAI,WAAU,eACZ;AAAA,gBAAY,QAAQ,8CAAC,SAAI,WAAU,mBAAmB,mBAAQ;AAAA,IACjE,8CAAC,SAAI,WAAU,eAAc,MAAK,SAC9B,WAAC,UAAU,OAAO,EAAY,IAAI,CAAC,MACnC;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,gBAAc,SAAS;AAAA,QACvB,SAAS,MAAM;AAAE,cAAI,SAAS,EAAG,cAAa;AAAA,QAAE;AAAA,QAE/C,gBAAM,WAAW,GAAG,kBAAkB,GAAG;AAAA;AAAA,MANrC;AAAA,IAOP,CACD,GACH;AAAA,KACA;AAGF,MAAI,SAAS,SAAS;AACpB,WACE,gFACG;AAAA;AAAA,MACD,8CAAC,cAAW,OAAc,SAAS,cAAc,IAAQ,gBAAgC;AAAA,OAC3F;AAAA,EAEJ;AAGA,MAAI,UAAU,QAAQ,QAAS,QAAO,gFAAG;AAAA;AAAA,IAAO,8CAAC,SAAI,WAAU,iBAAgB;AAAA,KAAE;AACjF,MAAI,UAAU,QAAQ,MAAM,WAAW,EAAG,QAAO,gFAAG;AAAA;AAAA,IAAO,8CAAC,SAAI,WAAU,kBAAkB,aAAG,gBAAe;AAAA,KAAM;AAEpH,SACE,gFACG;AAAA;AAAA,IACD,8CAAC,SAAI,WAAU,iBACZ,0BAAgB,KAAK,EAAE,IAAI,CAAC,OAAO,OAClC,+CAAC,SACE;AAAA,YAAM,gBAAgB,8CAAC,SAAI,WAAU,qBAAqB,wBAAc,IAAI,MAAM,YAAY,GAAE;AAAA,MAChG,MAAM,MAAM,IAAI,CAAC,MAChB,+CAAC,YAAO,MAAK,UAAS,WAAU,2BAA2C,SAAS,MAAM,eAAe,EAAE,QAAQ,GACjH;AAAA,sDAAC,UAAK,WAAU,eAAe,YAAE,gBAAgB,IAAG;AAAA,QACpD,8CAAC,UAAK,WAAU,gBAAgB,YAAE,YAAW;AAAA,WAFgB,EAAE,QAGjE,CACD;AAAA,SAPO,GAAG,EAAE,IAAI,MAAM,gBAAgB,MAAM,EAQ/C,CACD,GACH;AAAA,KACF;AAEJ;;;ACtEA,IAAAC,iBAAyB;AAUd,IAAAC,wBAAA;AARJ,SAAS,YAAY,EAAE,UAAU,cAAc,KAAK,GAI3C;AACd,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,MAAM,EAAE,OAAO,MAAM,QAAQ,KAAK;AACxC,MAAI,YAAY,CAAC,QAAQ;AACvB,WAAO,+CAAC,SAAI,WAAU,iBAAgB,OAAO,KAAK,KAAK,UAAU,KAAI,IAAG,eAAY,QAAO,SAAS,MAAM,UAAU,IAAI,GAAG;AAAA,EAC7H;AACA,SACE,+CAAC,UAAK,WAAU,gCAA+B,OAAO,EAAE,GAAG,KAAK,UAAU,KAAK,MAAM,OAAO,IAAI,EAAE,GAAG,eAAY,QAC9G,0BAAgB,IACnB;AAEJ;;;ACOM,IAAAC,wBAAA;AAxBN,IAAM,OAAkD;AAAA,EACtD,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,KAAK,CAAC,IAAI,EAAE;AAAA,EACZ,KAAK,CAAC,IAAI,EAAE;AAAA,EACZ,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AACb;AAEO,SAAS,UAAU,EAAE,aAAa,GAAoE;AAC3G,QAAM,OAAO,KAAK,cAAc,KAAK,EAAE,YAAY,KAAK,EAAE;AAC1D,MAAI,SAAS,OAAW,QAAO;AAC/B,SACE,+CAAC,SAAI,WAAU,iBAAgB,eAAY,QACzC,yDAAC,SAAI,WAAU,qBAAoB,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,KAAK,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,GACzF;AAEJ;;;AC3BA,IAAAC,iBAAyB;AAuEjB,IAAAC,wBAAA;AAhER,IAAM,SAA2B,CAAC,YAAY,WAAW,cAAc,WAAW;AAElF,SAASC,QAAO,GAA6C;AAC3D,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D;AAEA,SAAS,QAAQ,GAA0B,MAA2B;AACpE,SAAOA,QAAO,SAAS,UAAU,EAAE,QAAQ,EAAE,KAAK;AACpD;AAEA,SAAS,OAAO,GAA0B,MAA2B;AACnE,QAAM,IAAIA,QAAO,SAAS,UAAU,EAAE,YAAY,EAAE,SAAS;AAC7D,SAAO,MAAM,OAAO,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC;AACrE;AAEA,SAAS,OAAO,GAA0B,GAAW,MAAoB;AACvE,MAAI,EAAE,UAAW,QAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;AACvC,MAAI,SAAS,WAAW,EAAE,QAAQ,KAAM,QAAO,EAAE,QAAQ,CAAC;AAC1D,SAAO,OAAO,KAAK,MAAM,CAAC,CAAC;AAC7B;AAEA,SAAS,KAAK,MAAsC;AAClD,MAAI,QAAQ,GAAI,QAAO;AACvB,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO;AACT;AAEA,SAAS,WAAW,IAAc,GAAkB;AAClD,UAAQ,GAAG;AAAA,IACT,KAAK;AAAY,aAAO,GAAG;AAAA,IAC3B,KAAK;AAAW,aAAO,GAAG;AAAA,IAC1B,KAAK;AAAc,aAAO,GAAG;AAAA,IAC7B,KAAK;AAAa,aAAO,GAAG;AAAA,EAC9B;AACF;AAEA,SAAS,aAAa,IAAc,QAAyD;AAC3F,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAU,aAAO,GAAG;AAAA,IACzB,KAAK;AAAY,aAAO,GAAG;AAAA,IAC3B;AAAS,aAAO,GAAG;AAAA,EACrB;AACF;AAEO,SAAS,gBAAgB,EAAE,aAAa,iBAAiB,QAAQ,GAIjD;AACrB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAe,OAAO;AAC9C,QAAM,WAAW,YAAY,QAAQ,OAAO,CAAC,MAAM,OAAO,UAAU,eAAe,KAAK,QAAQ,YAAY,EAAE,GAAG,CAAC;AAClH,MAAI,CAAC,SAAS,KAAK,CAAC,MAAM,QAAQ,GAAG,OAAO,MAAM,QAAQ,QAAQ,GAAG,OAAO,MAAM,IAAI,EAAG,QAAO;AAEhG,QAAM,WAAW,CAAC,YAAY,SAC1B,aAAa,SAAS,YAAY,cAAc,IAChD,kBACE,QAAQ,kBAAkB,iBAAiB,YAAY,aAAa,IACpE;AAEN,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM;AAC9B,UAAM,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK,QAAQ,GAAG,IAAI,MAAM,IAAI;AAC9E,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,WACE,gDAAC,SAAY,WAAU,kCACrB;AAAA,qDAAC,SAAI,WAAU,sBAAsB,qBAAW,SAAS,CAAC,GAAE;AAAA,MAC3D,KAAK,IAAI,CAAC,MAAM;AACf,cAAM,IAAI,QAAQ,GAAG,IAAI;AACzB,cAAM,OAAO,YAAY,SAAS,OAAO,GAAG,IAAI,IAAI;AACpD,eACE,gDAAC,SAAgB,WAAU,mBACzB;AAAA,0DAAC,SAAI,WAAU,mBACb;AAAA,2DAAC,UAAK,WAAU,qBAAqB,kBAAQ,WAAW,EAAE,GAAG,GAAE;AAAA,YAC/D,+CAAC,UAAK,WAAU,qBAAqB,iBAAO,GAAG,GAAG,IAAI,GAAE;AAAA,aAC1D;AAAA,UACC,SAAS,QACR,+CAAC,SAAI,WAAU,iBACb,yDAAC,SAAI,WAAW,8BAA8B,KAAK,IAAI,CAAC,IAAI,OAAO,EAAE,OAAO,GAAG,IAAI,IAAI,GAAG,GAC5F;AAAA,aARM,EAAE,GAUZ;AAAA,MAEJ,CAAC;AAAA,SAlBO,CAmBV;AAAA,EAEJ,CAAC;AAED,SACE,gDAAC,SACC;AAAA,oDAAC,SAAI,WAAU,qBACb;AAAA,qDAAC,SAAI,WAAU,mBAAmB,kBAAQ,WAAU;AAAA,MACpD,+CAAC,SAAI,WAAU,eAAc,MAAK,SAC9B,WAAC,SAAS,OAAO,EAAY,IAAI,CAAC,MAClC,+CAAC,YAAe,MAAK,UAAS,WAAU,mBAAkB,gBAAc,SAAS,GAAG,SAAS,MAAM,QAAQ,CAAC,GACzG,gBAAM,UAAU,QAAQ,YAAY,QAAQ,aADlC,CAEb,CACD,GACH;AAAA,OACF;AAAA,IACC,aAAa,QAAQ,+CAAC,SAAI,WAAU,oBAAoB,oBAAS;AAAA,IAClE,+CAAC,SAAI,WAAU,sBAAsB,iBAAM;AAAA,KAC7C;AAEJ;;;AC5EI,IAAAC,wBAAA;AA1BJ,IAAM,OAAO;AAEb,SAAS,QAAQ,OAA8B;AAC7C,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,MAAM,IAAI,eAAe,IAAI,IAAI,eAAe;AACpD,QAAM,iBACJ,IAAI,YAAY,IAAI,IAAI,YAAY,KACnC,IAAI,YAAY,MAAM,IAAI,YAAY,KAAK,IAAI,WAAW,IAAI,IAAI,WAAW;AAChF,MAAI,eAAgB;AACpB,SAAO,OAAO,GAAG;AACnB;AAEA,SAAS,QAAQ,IAA8C;AAC7D,SAAO,OAAO,OAAO,YAAY,OAAO,SAAS,EAAE,KAAK,KAAK,IAAI,KAAK;AACxE;AAEA,SAAS,WAAW,SAAyC;AAC3D,MAAI,WAAW,EAAG,QAAO;AACzB,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO;AACT;AAEA,SAAS,IAAI,EAAE,OAAO,MAAM,GAAkD;AAC5E,SACE,gDAAC,SAAI,WAAU,oBACb;AAAA,mDAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,IAAO;AAAA,IAAC,+CAAC,UAAM,iBAAM;AAAA,KAC9D;AAEJ;AAEA,SAAS,KAAK,EAAE,OAAO,OAAO,IAAI,GAAiE;AACjG,SACE,gDAAC,SAAI,WAAU,gBACb;AAAA,mDAAC,SAAI,WAAU,sBAAsB,iBAAM;AAAA,IAC3C,+CAAC,SAAI,WAAW,MAAM,uCAAuC,sBAAuB,iBAAM;AAAA,KAC5F;AAEJ;AAEA,SAAS,iBAAiB,EAAE,IAAI,MAAM,aAAa,GAInC;AACd,MAAI,OAAsB;AAC1B,MAAI,OAA8D;AAClE,MAAI,iBAAiB,MAAM;AACzB,QAAI,aAAa,WAAW,aAAa;AACvC,aAAO,GAAG;AACV,aAAO,EAAE,MAAM,GAAG,uBAAuB,MAAM,MAAM;AAAA,IACvD,OAAO;AACL,YAAM,OAAO,QAAQ,aAAa,oBAAoB;AACtD,aAAO,CAAC,aAAa,QAAQ,KAAK,KAAK,MAAM,SAAS,OAAO,OAAO,GAAG,iBAAiB,IAAI,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK;AAC9H,aAAO,aAAa,WAAW,YAC3B,EAAE,MAAM,GAAG,qBAAqB,MAAM,MAAM,IAC5C,aAAa,WAAW,cACtB,EAAE,MAAM,GAAG,uBAAuB,MAAM,OAAO,IAC/C,EAAE,MAAM,GAAG,yBAAyB,MAAM,OAAO;AAAA,IACzD;AAAA,EACF;AACA,SACE,gDAAC,SAAI,WAAU,8BACb;AAAA,oDAAC,SAAI,WAAU,sBACZ;AAAA,eAAS,QAAQ,+CAAC,SAAI,WAAU,sBAAsB,aAAG,iBAAiB,KAAK,cAAc,KAAK,QAAQ,QAAQ,KAAK,aAAa,CAAC,GAAE;AAAA,MACvI,SAAS,QAAQ,+CAAC,SAAI,WAAU,sBAAsB,gBAAK;AAAA,OAC9D;AAAA,IACC,SAAS,QAAQ,+CAAC,SAAI,WAAW,8BAA8B,KAAK,IAAI,IAAK,eAAK,MAAK;AAAA,KAC1F;AAEJ;AAEA,SAAS,SAAS,EAAE,IAAI,IAAI,GAAwD;AAClF,QAAM,OAAO,QAAQ,IAAI,aAAa;AACtC,QAAM,SAAS;AAAA,IACb,IAAI,QAAQ,IAAI,GAAG,IAAI,KAAK,GAAG,GAAG,aAAa,KAAK;AAAA,IACpD,IAAI,UAAU,IAAI,GAAG,IAAI,OAAO,GAAG,GAAG,eAAe,KAAK;AAAA,IAC1D,IAAI,cAAc,IAAI,GAAG,IAAI,WAAW,GAAG,GAAG,cAAc,KAAK;AAAA,IACjE,IAAI,UAAU,GAAG,cAAc;AAAA,EACjC,EAAE,OAAO,CAAC,MAAmB,MAAM,IAAI;AACvC,QAAM,MAAM,CAAC,GAAG,GAAG,aAAa,IAAI,MAAM,CAAC,IAAI,IAAI,QAAQ,SAAI,IAAI,YAAY,IAAI,GAAG,IAAI,OAAO,UAAK,GAAG,MAAM,EAAE,KAAK,QAAK;AAC3H,QAAM,SAAS,OAAO,IAAI,WAAW,YAAY,OAAO,SAAS,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI,SAAS,EAAE,IAAI,KAAK;AAClH,QAAM,WAAW,IAAI,WAAW,MAAM,QAAQ,IAAI,WAAW,MAAM,QAAQ;AAC3E,SACE,gDAAC,SAAI,WAAU,iBACb;AAAA,mDAAC,SAAI,WAAU,sBAAsB,mBAAS,OAAO,KAAK,GAAG,aAAa,IAAI,GAAE;AAAA,IAChF,gDAAC,SAAI,WAAU,sBACb;AAAA,qDAAC,SAAI,WAAU,qBAAqB,aAAG,iBAAiB,IAAI,cAAc,IAAI,MAAM,GAAE;AAAA,MACtF,+CAAC,SAAI,WAAU,qBAAqB,eAAI;AAAA,OAC1C;AAAA,IACA,+CAAC,SAAI,WAAW,8BAA8B,QAAQ,IAAK,aAAG,aAAa,IAAI,MAAM,GAAE;AAAA,IACtF,WAAW,OACR,+CAAC,SAAI,WAAU,sBAAqB,IACpC,+CAAC,SAAI,WAAW,8BAA8B,WAAW,MAAM,CAAC,IAAK,iBAAO,QAAQ,CAAC,GAAE;AAAA,KAC7F;AAEJ;AAEO,SAAS,aAAa,EAAE,QAAQ,SAAS,IAAI,YAAY,QAAQ,GAMxD;AACd,QAAM,OACJ,gDAAC,YAAO,MAAK,UAAS,WAAU,gBAAe,SAAS,SACtD;AAAA,mDAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAY,QAAO,yDAAC,UAAK,GAAE,mBAAkB,GAAE;AAAA,IAC7L,GAAG;AAAA,KACN;AAGF,MAAI,WAAW,MAAM;AACnB,WAAO,UACH,kFAAE;AAAA,qDAAC,SAAI,WAAU,eAAe,gBAAK;AAAA,MAAM,+CAAC,SAAI,WAAU,iBAAgB;AAAA,OAAE,IAC5E,kFAAE;AAAA,qDAAC,SAAI,WAAU,eAAe,gBAAK;AAAA,MAAM,+CAAC,SAAI,WAAU,kBAAkB,aAAG,uBAAsB;AAAA,OAAM;AAAA,EACjH;AAEA,QAAM,IAAI,OAAO;AACjB,QAAM,OAAO,UAAU,IAAI,OAAO,IAAI;AACtC,QAAM,WAAW,cAAc,IAAI,OAAO,YAAY;AACtD,QAAM,UAAU,CAAC,OAAO,UAAU,KAAK,KAAK,MAAM,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK;AACtF,QAAM,cAAc,OAAO,iBAAiB,KAAK,KAAK;AACtD,QAAM,UAAU,eAAe,OAC3B,OACA,gBAAgB,OAAO,GAAG,aAAa,QAAQ,YAAY,UAAU,IAAI,GAAG,UAAU,IAAI,WAAW;AACzG,QAAM,SAAS,OAAO,EAAE,kBAAkB,YAAY,OAAO,SAAS,EAAE,aAAa,IAAI,EAAE,gBAAgB;AAC3G,QAAM,OAAO,OAAO,eAAe;AACnC,QAAM,eAAe,OAAO,gBAAgB;AAC5C,QAAM,MAAM,OAAO,YAAY,CAAC;AAEhC,SACE,kFACE;AAAA,mDAAC,SAAI,WAAU,eAAe,gBAAK;AAAA,IACnC,gDAAC,SAAI,WAAU,8BACb;AAAA,sDAAC,SAAI,WAAU,gCACb;AAAA,uDAAC,eAAwC,UAAU,OAAO,UAAU,cAAc,OAAO,cAAc,MAAM,MAA3F,OAAO,YAAY,EAA4E;AAAA,QACjH,gDAAC,SAAI,WAAU,wBACb;AAAA,yDAAC,SAAI,WAAU,gBAAgB,iBAAO,YAAW;AAAA,UAChD,YAAY,MAAM,+CAAC,SAAI,WAAU,eAAe,mBAAQ;AAAA,UACzD,gDAAC,SAAI,WAAU,eACb;AAAA,2DAAC,OAAI,OAAO,GAAG,WAAW,OAAO,QAAQ,OAAO,iBAAiB,GAAG;AAAA,YACpE,+CAAC,OAAI,OAAO,GAAG,cAAc,OAAO,OAAO,aAAa,OAAO,OAAO,GAAG,OAAO,QAAQ,OAAO;AAAA,YAC9F,SAAS,QAAQ,+CAAC,OAAI,OAAO,GAAG,YAAY,OAAO,MAAM;AAAA,YAC1D,+CAAC,OAAI,OAAO,GAAG,gBAAgB,OAAO,OAAO,eAAe,MAAM;AAAA,aACpE;AAAA,WACF;AAAA,QACA,+CAAC,aAAU,cAAc,OAAO,cAAc;AAAA,SAChD;AAAA,OAEE,SAAS,QAAQ,iBAAiB,SAAS,+CAAC,oBAAiB,IAAQ,MAAY,cAA4B;AAAA,MAE/G,gDAAC,SACE;AAAA,oBAAY,QAAQ,+CAAC,SAAI,WAAU,0CAA0C,mBAAQ;AAAA,QACtF,gDAAC,SAAI,WAAU,iBACb;AAAA,yDAAC,QAAK,OAAO,GAAG,cAAc,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,UACtD,+CAAC,QAAK,OAAO,GAAG,gBAAgB,OAAO,OAAO,EAAE,OAAO,GAAG;AAAA,UACzD,OAAO,EAAE,WAAW,YAAY,+CAAC,QAAK,OAAO,GAAG,eAAe,OAAO,OAAO,EAAE,MAAM,GAAG;AAAA,UACzF,+CAAC,QAAK,OAAO,GAAG,eAAe,OAAO,OAAO,EAAE,WAAW,GAAG;AAAA,UAC7D,+CAAC,QAAK,OAAO,GAAG,gBAAgB,OAAO,OAAO,EAAE,aAAa,GAAG;AAAA,UAC/D,WAAW,QAAQ,+CAAC,QAAK,OAAO,GAAG,eAAe,OAAO,OAAO,QAAQ,CAAC,GAAG,KAAK,KAAK,MAAM,SAAS,GAAG,IAAI,OAAO,GAAG;AAAA,UACvH,+CAAC,QAAK,OAAO,GAAG,eAAe,OAAO,OAAO,EAAE,WAAW,GAAG;AAAA,UAC7D,+CAAC,QAAK,OAAO,GAAG,YAAY,OAAO,OAAO,EAAE,QAAQ,GAAG;AAAA,WACzD;AAAA,SACF;AAAA,MAEC,OAAO,eAAe,QACrB,+CAAC,mBAAgB,aAAa,OAAO,aAAa,iBAAiB,aAAa,SAAS,IAAI;AAAA,MAG9F,IAAI,SAAS,KACZ,gDAAC,SACC;AAAA,uDAAC,SAAI,WAAU,0CAA0C,aAAG,eAAc;AAAA,QAC1E,+CAAC,SAAI,WAAU,4BACZ,cAAI,IAAI,CAAC,QAAQ,+CAAC,YAA2B,IAAQ,OAArB,IAAI,OAA2B,CAAE,GACpE;AAAA,SACF;AAAA,OAEJ;AAAA,KACF;AAEJ;;;AC7LA,IAAAC,iBAAsC;AAwBhC,IAAAC,wBAAA;AAbC,SAAS,gBAAgB,EAAE,UAAU,SAAS,SAAS,UAAU,QAAQ,SAAS,UAAU,GAQnF;AACd,QAAM,cAAU,sBAAM;AACtB,QAAM,WAAW,WAAW,IAAI;AAChC,SACE,gDAAC,SAAI,KAAK,SAAS,WAAU,aAC3B;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QAAW,MAAK;AAAA,QAAS,WAAU;AAAA,QACxC,iBAAe;AAAA,QAAU,iBAAe;AAAA,QAAS,cAAY,QAAQ;AAAA,QAAU,SAAS;AAAA,QAExF;AAAA,yDAAC,UAAK,WAAU,uCAAsC,yDAAC,eAAY,GAAE;AAAA,UACrE,+CAAC,UAAK,WAAU,wCAAuC,yDAAC,aAAU,GAAE;AAAA,UACnE,WAAW,CAAC,WAAW,+CAAC,UAAK,WAAU,iBAAgB,eAAY,QAAO,IAAK;AAAA;AAAA;AAAA,IAClF;AAAA,IACA,gDAAC,SAAI,IAAI,SAAS,WAAU,mBAAkB,aAAW,WAAW,KAAK,QACvE;AAAA,sDAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,UAAoB,SAAS,MAAM,OAAO,SAAS,GAClG;AAAA,uDAAC,eAAY;AAAA,QAAE,+CAAC,UAAK,WAAU,wBAAwB,kBAAQ,YAAW;AAAA,SAC5E;AAAA,MACA,gDAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,UAAoB,SAAS,MAAM,OAAO,OAAO,GAChG;AAAA,uDAAC,aAAU;AAAA,QAAE,+CAAC,UAAK,WAAU,wBAAwB,kBAAQ,YAAW;AAAA,SAC1E;AAAA,OACF;AAAA,KACF;AAEJ;;;AC1CA,IAAAC,iBAAiG;AAwDzF,IAAAC,wBAAA;AA5CR,IAAM,YAAY;AAKX,SAAS,gBAAgB,EAAE,OAAO,YAAY,SAAS,UAAU,OAAO,GAM/D;AACd,QAAM,gBAAY,uBAAuB,IAAI;AAC7C,QAAM,cAAU,sBAAM;AAEtB,gCAAU,MAAM;AAAE,cAAU,SAAS,MAAM;AAAA,EAAE,GAAG,CAAC,CAAC;AAElD,gCAAU,MAAM;AACd,UAAM,QAAQ,CAAC,MAAsC;AACnD,UAAI,EAAE,QAAQ,SAAU;AACxB,QAAE,gBAAgB;AAClB,QAAE,eAAe;AACjB,cAAQ;AAAA,IACV;AACA,WAAO,iBAAiB,WAAW,OAAO,IAAI;AAC9C,WAAO,MAAM,OAAO,oBAAoB,WAAW,OAAO,IAAI;AAAA,EAChE,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,UAAU,CAAC,MAA2C;AAC1D,QAAI,EAAE,QAAQ,MAAO;AACrB,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,MAAM,KAAK,OAAO,iBAA8B,SAAS,CAAC;AACxE,UAAM,QAAQ,MAAM,CAAC;AACrB,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,QAAI,CAAC,SAAS,CAAC,MAAM;AAAE,QAAE,eAAe;AAAG;AAAA,IAAO;AAClD,UAAM,SAAU,OAAO,YAAY,EAA4B;AAC/D,QAAI,EAAE,aAAa,WAAW,SAAS,WAAW,SAAS;AAAE,QAAE,eAAe;AAAG,WAAK,MAAM;AAAA,IAAE,WACrF,CAAC,EAAE,YAAY,WAAW,MAAM;AAAE,QAAE,eAAe;AAAG,YAAM,MAAM;AAAA,IAAE;AAAA,EAC/E;AAEA,SACE,+CAAC,SAAI,WAAU,sBACb,0DAAC,SAAI,KAAK,WAAW,WAAU,aAAY,MAAK,UAAS,cAAW,QAAO,mBAAiB,SAAS,UAAU,IAAI,WAAW,SAC5H;AAAA,oDAAC,SAAI,WAAU,kBACb;AAAA,qDAAC,QAAG,IAAI,SAAS,WAAU,mBAAmB,iBAAM;AAAA,MACpD,+CAAC,YAAO,MAAK,UAAS,WAAU,mBAAkB,cAAY,YAAY,SAAS,SAAS,yDAAC,aAAU,GAAE;AAAA,OAC3G;AAAA,IACA,+CAAC,SAAI,WAAU,kBAAkB,UAAS;AAAA,IACzC,SAAS,+CAAC,SAAI,WAAU,kBAAkB,kBAAO,IAAS;AAAA,KAC7D,GACF;AAEJ;AAGA,SAAS,aAAa,UAAkB,OAA+C;AACrF,SAAO,SAAS,MAAM,cAAc,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,IAAI,CAAC,MAAM,MAAM;AACnF,UAAM,MAAM,iBAAiB,KAAK,IAAI,IAAI,CAAC;AAC3C,WAAO,+CAAC,2BAAkB,kBAAQ,UAAa,OAAO,QAAQ,MAAM,GAAG,IAAI,QAArD,CAA0D;AAAA,EAClF,CAAC;AACH;AAMA,SAAS,aAAa,EAAE,SAAS,SAAAC,UAAS,OAAO,UAAU,YAAY,MAAM,SAAS,GAQtE;AACd,QAAM,WAAW,KAAK,IAAI,GAAGA,SAAQ,UAAU,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AACzE,SACE,gDAAC,UAAK,WAAU,iBACd;AAAA,mDAAC,UAAK,WAAU,sBAAqB,eAAY,QAAQ,mBAAQ;AAAA,IACjE,+CAAC,YAAO,WAAU,wBAAuB,cAAY,OAAO,OAAO,OAAO,QAAQ,GAAG,UAAU,CAAC,MAAM;AAAE,YAAM,IAAIA,SAAQ,OAAO,EAAE,OAAO,KAAK,CAAC;AAAG,UAAI,EAAG,UAAS,EAAE,KAAK;AAAA,IAAE,GACzK,UAAAA,SAAQ,IAAI,CAAC,GAAG,MACf,+CAAC,YAAe,OAAO,OAAO,CAAC,GAAG,UAAU,aAAa,CAAC,EAAE,aAAa,MAAM,UAAW,YAAE,YAAY,EAAE,OAAO,GAAG,EAAE,IAAI,GAAG,QAAQ,MAAxH,CAA2H,CACzI,GACH;AAAA,KACF;AAEJ;AAKA,SAAS,aAAa,EAAE,YAAY,YAAY,cAAc,OAAO,SAAS,GAQ9D;AACd,QAAM,WAAW,WAAW,UAAU,KAAK;AAC3C,SACE,gDAAC,UAAK,WAAU,iBACd;AAAA,mDAAC,UAAK,WAAU,sBAAqB,eAAY,QAAQ,oBAAS;AAAA,IAClE,+CAAC,YAAO,WAAU,wBAAuB,cAAY,OAAO,OAAO,OAAO,UAAU,GAAG,UAAU,CAAC,MAAM,SAAS,OAAO,EAAE,OAAO,KAAK,CAAC,GACpI,uBAAa,IAAI,CAAC,KAAK,MAAM,+CAAC,YAAe,OAAO,OAAO,CAAC,GAAI,iBAAtB,CAA0B,CAAS,GAChF;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW,EAAE,OAAO,SAAS,UAAU,QAAQ,GAA4F;AAClJ,SAAO,+CAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,cAAY,GAAG,KAAK,KAAK,OAAO,IAAI,UAAoB,SAAmB,iBAAM;AAC3I;AAIA,SAAS,SAAS,EAAE,OAAO,cAAc,GAAwF;AAC/H,SACE,+CAAC,QAAG,WAAU,mBAAkB,MAAK,QAClC,gBAAM,IAAI,CAAC,MACV,gDAAC,QAAuB,WAAU,kBAChC;AAAA,oDAAC,UAAK,WAAU,wBAAwB;AAAA,QAAE;AAAA,MAAa;AAAA,MAAI,EAAE;AAAA,OAAa;AAAA,IAC1E,gDAAC,UAAK,WAAU,sBAAsB;AAAA,QAAE;AAAA,MAAY;AAAA,MAAG,EAAE;AAAA,MAAgB,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK;AAAA,OAAG;AAAA,IACpG,+CAAC,UAAK,WAAU,uBAAuB,wBAAc,EAAE,UAAU,GAAE;AAAA,IACnE,+CAAC,UAAK,WAAU,wBAAwB,YAAE,MAAM,QAAQ,CAAC,GAAE;AAAA,OAJpD,EAAE,WAKX,CACD,GACH;AAEJ;AAEA,SAAS,aAAa,EAAE,MAAM,cAAc,GAA0F;AACpI,SACE,kFACE;AAAA,mDAAC,YAAS,OAAO,KAAK,MAAM,MAAM,eAA8B;AAAA,IAChE,+CAAC,SAAI,WAAU,kBAAkB,eAAK,MAAM,gBAAe;AAAA,KAC7D;AAEJ;AAEA,SAAS,YAAY,EAAE,KAAK,GAAkC;AAC5D,SAAO,+CAAC,OAAE,WAAU,yBAAyB,gBAAK;AACpD;AAIA,SAAS,OAAO,EAAE,MAAM,KAAK,OAAO,KAAK,GAAyF;AAChI,SACE,gDAAC,aAAQ,WAAU,oCACjB;AAAA,mDAAC,UAAK,WAAU,kBAAiB,eAAY,QAAQ,gBAAK;AAAA,IAC1D,gDAAC,SAAI,WAAU,kBACb;AAAA,qDAAC,OAAE,WAAU,iBAAiB,eAAI;AAAA,MACjC,QAAQ,+CAAC,UAAK,WAAU,mBAAmB,iBAAM,IAAU;AAAA,OAC9D;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,SAAS,UAAU,QAAQ,GAA4F;AACjJ,SAAO,+CAAC,YAAO,MAAK,UAAS,WAAU,gBAAe,cAAY,GAAG,KAAK,KAAK,OAAO,IAAI,UAAoB,SAAkB,yDAAC,YAAS,GAAE;AAC9I;AAGA,IAAM,YAAY,EAAE,OAAO,IAAI,MAAM,EAAE;AAEhC,SAAS,eAAe,EAAE,MAAM,SAAS,WAAW,QAAQ,QAAQ,GAM3D;AACd,QAAM,SAAS,cAAc,IAAI;AACjC,QAAM,SAAS,cAAc,IAAI;AACjC,QAAM,SAAS,YAAY,IAAI;AAC/B,QAAM,aAAa,gBAAgB,IAAI;AACvC,QAAM,QAAQ;AACd,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,MAAM,aAAa,KAAK,SAAS,QAAQ,MAAM,UAAU,KAAK,CAAC;AACxG,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,MAAM,aAAa,KAAK,aAAa,QAAQ,MAAM,UAAU,KAAK,CAAC;AAC5G,QAAM,CAAC,KAAK,QAAI,yBAAS,MAAM,WAAW,MAAM,QAAQ,YAAY,MAAM,YAAY,MAAM,SAAS,CAAC;AACtG,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,MAAM,KAAK;AAC9C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAS,MAAM,IAAI;AAC3C,QAAM,CAAC,QAAQ,QAAI,yBAAS,MAAM,WAAW,MAAM,QAAQ,YAAY,UAAU,OAAO,UAAU,IAAI,CAAC;AACvG,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,SAAS,KAAK;AACvD,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,SAAS,IAAI;AACpD,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,EAAE;AACnD,QAAM,UAAU,YAAY,KAAK,SAAS,UAAU,KAAK;AACzD,QAAM,UAAU,YAAY,KAAK,aAAa,UAAU,KAAK;AAC7D,QAAM,YAAY,UAAU,MAAM,OAAO,IAAI;AAC7C,QAAM,UAAU,UAAU,MAAM,UAAU,OAAO;AACjD,QAAM,WAAW,CAAC,SAAiB,cAA6B,gBAAgB,YAAY,UAAU,GAAG,OAAO,KAAK,QAAQ,WAAW,EAAE;AAE1I,QAAM,eAAe,CAAC,QAAsB;AAC1C,iBAAa,GAAG;AAChB,UAAM,OAAO,QAAQ,GAAG;AACxB,QAAI,KAAM,UAAS,cAAc,MAAM,OAAO,GAAG,KAAK,QAAQ,CAAC;AAAA,EACjE;AACA,QAAM,YAAY,CAAC,MAAoB;AAAE,gBAAY,CAAC;AAAG,aAAS,QAAQ,gBAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,KAAK,SAAS,GAAG,KAAK,CAAC;AAAA,EAAE;AAC5I,QAAM,YAAY,CAAC,MAAoB;AAAE,gBAAY,CAAC;AAAG,aAAS,QAAQ,gBAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,KAAK,aAAa,GAAG,KAAK,CAAC;AAAA,EAAE;AAChJ,QAAM,aAAa,CAAC,MAAoB;AAAE,YAAQ,CAAC;AAAG,aAAS,QAAQ,aAAa,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU,MAAM,OAAO,CAAC,CAAC;AAAA,EAAE;AAC5H,QAAM,cAAc,CAAC,MAAoB;AAAE,UAAM,IAAI,aAAa,MAAM,GAAG,IAAI;AAAG,aAAS,CAAC;AAAG,YAAQ,CAAC;AAAG,aAAS,QAAQ,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,MAAM,GAAG,CAAC,CAAC;AAAA,EAAE;AACzK,QAAM,gBAAgB,CAAC,MAAoB;AAAE,eAAW,CAAC;AAAG,aAAS,QAAQ,aAAa,GAAG,QAAQ,GAAG,CAAC,CAAC,UAAU,MAAM,UAAU,CAAC,CAAC;AAAA,EAAE;AACxI,QAAM,iBAAiB,CAAC,MAAoB;AAAE,UAAM,IAAI,aAAa,MAAM,GAAG,OAAO;AAAG,gBAAY,CAAC;AAAG,eAAW,CAAC;AAAG,aAAS,QAAQ,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,MAAM,GAAG,CAAC,CAAC;AAAA,EAAE;AACrL,QAAM,aAAa,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,YAAY,KAAK,SAAS,GAAG,KAAK,EAAE,EAAE;AACzH,QAAM,aAAa,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,YAAY,KAAK,aAAa,GAAG,KAAK,EAAE,EAAE;AAC7H,QAAM,eAAe,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,QAAQ,CAAC,GAAG,WAAW,WAAW,KAAK,CAAC,MAAM,CAAC,CAAC,UAAU,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE;AACrI,QAAM,gBAAgB,CAAC,MAA8B,WAAW,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,UAAU,MAAM,GAAG,CAAC,EAAE,EAAE;AAC9I,QAAM,UAAU,KAAK,WAAW,CAAC;AACjC,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAS,CAAC;AAC5C,QAAM,aAAa,QAAQ,SAAS,KAAK;AAEzC,QAAM,eAAe,QAAQ,IAAI,CAAC,MAAM,QAAQ,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,kBAAkB,IAAI,CAAC;AAC3H,QAAM,eAAe,CAAC,SAA4C,OAAO,QAAQ,WAAW,KAAK,MAAM,MAAM,IAAI,QAAQ;AACzH,QAAM,aAAa,CAAC,SAA0C,OAAO,QAAQ,QAAQ,KAAK,MAAM,KAAK,IAAI,QAAQ;AAEjH,SACE,gDAAC,mBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,OAAO,SACrE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,KAAK,aAAa,QAAQ,aAAa;AAAA,UACrC,OAAO,OAAO,KAAK;AAAA,UACnB,OAAO,+CAAC,gBAAa,SAAS,SAAS,QAAQ,CAAC,GAAG,SAAS,YAAY,OAAO,QAAQ,cAAc,UAAU,QAAQ,UAAU,UAAU,WAAW;AAAA,QACxJ,CAAC;AAAA,QACD,OAAO,aAAa,OAAO;AAAA,QAC3B,MAAM,+CAAC,aAAU,OAAO,QAAQ,MAAM,SAAS,QAAQ,gBAAgB,OAAO,QAAQ,GAAG,UAAU,CAAC,WAAW,WAAW,SAAS,MAAM;AAAE,cAAI,QAAS,QAAO,YAAY,SAAS,OAAO,CAAC;AAAA,QAAE,GAAG;AAAA;AAAA,IACnM;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,KAAK,aAAa,QAAQ,aAAa;AAAA,UACrC,OAAO,OAAO,KAAK;AAAA,UACnB,OAAO,+CAAC,gBAAa,SAAS,SAAS,QAAQ,CAAC,GAAG,SAAS,YAAY,OAAO,QAAQ,cAAc,UAAU,QAAQ,UAAU,UAAU,WAAW;AAAA,QACxJ,CAAC;AAAA,QACD,OAAO,aAAa,OAAO;AAAA,QAC3B,MAAM,+CAAC,aAAU,OAAO,QAAQ,MAAM,SAAS,QAAQ,gBAAgB,OAAO,QAAQ,GAAG,UAAU,CAAC,WAAW,WAAW,SAAS,MAAM;AAAE,cAAI,QAAS,QAAO,YAAY,SAAS,OAAO,CAAC;AAAA,QAAE,GAAG;AAAA;AAAA,IACnM;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,KAAK,aAAa,QAAQ,UAAU;AAAA,UAClC,MAAM,+CAAC,gBAAa,SAAS,OAAO,IAAI,GAAG,SAAS,cAAc,KAAK,GAAG,OAAO,QAAQ,cAAc,UAAU,QAAQ,UAAU,WAAW,OAAO,UAAU,YAAY;AAAA,UAC3K,OAAO,+CAAC,gBAAa,SAAS,MAAM,QAAQ,CAAC,GAAG,SAAS,cAAc,OAAO,QAAQ,YAAY,UAAU,QAAQ,UAAU,UAAU,aAAa;AAAA,QACvJ,CAAC;AAAA,QACD,OAAO,WAAW,SAAS;AAAA,QAC3B,MAAM,+CAAC,aAAU,OAAO,QAAQ,MAAM,SAAS,QAAQ,aAAa,MAAM,KAAK,GAAG,UAAU,CAAC,aAAa,WAAW,SAAS,MAAM;AAAE,cAAI,UAAW,QAAO,SAAS,WAAW,OAAO,CAAC;AAAA,QAAE,GAAG;AAAA;AAAA,IAC/L;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,KAAK,aAAa,QAAQ,aAAa;AAAA,UACrC,MAAM,+CAAC,gBAAa,SAAS,OAAO,OAAO,GAAG,SAAS,cAAc,QAAQ,GAAG,OAAO,QAAQ,cAAc,UAAU,QAAQ,UAAU,WAAW,OAAO,UAAU,eAAe;AAAA,UACpL,OAAO,+CAAC,gBAAa,SAAS,SAAS,QAAQ,CAAC,GAAG,SAAS,cAAc,OAAO,QAAQ,YAAY,UAAU,QAAQ,UAAU,UAAU,gBAAgB;AAAA,QAC7J,CAAC;AAAA,QACD,OAAO,WAAW,OAAO;AAAA,QACzB,MAAM,+CAAC,aAAU,OAAO,QAAQ,MAAM,SAAS,QAAQ,aAAa,SAAS,QAAQ,GAAG,UAAU,CAAC,WAAW,WAAW,SAAS,MAAM;AAAE,cAAI,QAAS,QAAO,SAAS,SAAS,OAAO,CAAC;AAAA,QAAE,GAAG;AAAA;AAAA,IAC/L;AAAA,IACC,QAAQ,SAAS,KAChB;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,KAAK,aAAa,QAAQ,WAAW;AAAA,UACnC,QAAQ,+CAAC,gBAAa,YAAY,WAAW,YAAY,cAAc,cAAc,cAAc,OAAO,QAAQ,YAAY,UAAU,cAAc;AAAA,QACxJ,CAAC;AAAA,QACD,OAAO,aAAa,QAAQ,WAAW,WAAW,KAAK,IAAI;AAAA,QAC3D,MAAM,+CAAC,aAAU,OAAO,QAAQ,MAAM,SAAS,aAAa,cAAc,YAAY,OAAO,IAAI,IAAI,UAAU,CAAC,cAAc,WAAW,SAAS,MAAM;AAAE,cAAI,WAAY,QAAO,UAAU,YAAY,OAAO,CAAC;AAAA,QAAE,GAAG;AAAA;AAAA,IACtN;AAAA,IAEF,+CAAC,OAAE,WAAU,WAAU,aAAU,UAAU,wBAAa;AAAA,KAC1D;AAEJ;AAEO,SAAS,eAAe,EAAE,MAAM,SAAS,WAAW,eAAe,cAAc,aAAa,QAAQ,QAAQ,GAUrG;AACd,QAAM,SAAS,YAAY,IAAI;AAC/B,QAAM,aAAa,gBAAgB,IAAI;AACvC,QAAM,CAAC,KAAK,QAAI,yBAAS,MAAO,iBAAiB,SAAY,WAAW,MAAM,QAAQ,YAAY,MAAM,YAAY,MAAM,SAAS,IAAI,IAAK;AAC5I,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,MAAO,iBAAiB,SAAY,QAAQ,QAAQ,YAAY,IAAI,MAAO,KAAM;AACpH,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAS,MAAM;AACrC,QAAI,iBAAiB,OAAW,QAAO,gBAAgB,SAAY,UAAU,YAAY,WAAW,IAAI,MAAO;AAC/G,UAAM,OAAO,gBAAgB,SAAY,UAAU,YAAY,WAAW,IAAI,WAAW,YAAY,MAAM,SAAS;AACpH,WAAO,aAAa,MAAM,QAAQ,QAAQ,YAAY,GAAG,IAAI;AAAA,EAC/D,CAAC;AACD,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,EAAE;AACnD,QAAM,OAAO,UAAU,MAAM,OAAO,IAAI;AACxC,QAAM,UAAU,WAAW,CAAC,KAAK;AACjC,QAAM,UAAU,WAAW,WAAW,SAAS,CAAC,KAAK;AACrD,QAAM,UAAU,QAAQ,aAAa,MAAM,KAAK;AAEhD,QAAM,SAAS,CAAC,WAAmB,aAA2B;AAC5D,aAAS,SAAS;AAClB,YAAQ,QAAQ;AAChB,UAAM,IAAI,QAAQ,aAAa,UAAU,SAAS;AAClD,oBAAgB,UAAU,MAAM,WAAW,QAAQ,IAAI,IAAI,GAAG,CAAC,KAAK,QAAQ,WAAW,EAAE;AAAA,EAC3F;AAEA,QAAM,SACJ,+CAAC,cAAW,OAAO,QAAQ,MAAM,SAAkB,UAAU,CAAC,QAAQ,WAAW,SAAS,MAAM;AAAE,QAAI,KAAM,QAAO,SAAS,MAAM,OAAO,CAAC;AAAA,EAAE,GAAG;AAGjJ,SACE,gDAAC,mBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,OAAO,SAAkB,QACvF;AAAA,oDAAC,SAAI,WAAU,qBAAoB,MAAK,SAAQ,cAAY,QAAQ,YAClE;AAAA,qDAAC,UAAK,WAAU,mBAAkB,eAAY,QAAQ,kBAAQ,YAAW;AAAA,MACzE,+CAAC,SAAI,WAAU,mBACZ,iBAAO,IAAI,CAAC,MACX,+CAAC,YAAe,MAAK,UAAS,WAAU,kBAAiB,gBAAc,UAAU,GAAG,KAAK,GAAG,SAAS,MAAM,OAAO,GAAG,UAAU,GAAG,KAAK,IAAI,OAAO,aAAa,MAAM,GAAG,IAAI,CAAC,GAAI,YAAE,QAAQ,CAAC,KAA/K,CAAiL,CAC/L,GACH;AAAA,OACF;AAAA,IACA,gDAAC,SAAI,WAAU,qBAAoB,MAAK,SAAQ,cAAY,QAAQ,cAClE;AAAA,qDAAC,UAAK,WAAU,mBAAkB,eAAY,QAAQ,kBAAQ,cAAa;AAAA,MAC3E,gDAAC,SAAI,WAAU,qBACb;AAAA,uDAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,cAAY,QAAQ,cAAc,UAAU,QAAQ,SAAS,SAAS,MAAM,OAAO,OAAO,OAAO,CAAC,GAAG,oBAAC;AAAA,QACvJ,+CAAC,UAAK,WAAU,mBAAmB,gBAAK;AAAA,QACxC,+CAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,cAAY,QAAQ,aAAa,UAAU,QAAQ,SAAS,SAAS,MAAM,OAAO,OAAO,OAAO,CAAC,GAAG,eAAC;AAAA,SACxJ;AAAA,OACF;AAAA,IACC,OAAO,+CAAC,gBAAa,MAAY,eAA8B,IAAK,+CAAC,eAAY,MAAM,QAAQ,aAAa;AAAA,IAC7G,+CAAC,OAAE,WAAU,WAAU,aAAU,UAAU,wBAAa;AAAA,KAC1D;AAEJ;;;ACtVA,IAAAC,iBAAyE;AAKlE,SAAS,aAAa,UAAqB,aAA+B;AAC/E,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,SAAO,eAAe,CAAC,CAAC,QAAQ,KAAK,SAAS,eAAe,CAAC,KAAK,QAAQ,CAAC,KAAK;AACnF;AAEO,SAAS,WAAW,UAAoC;AAC7D,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,KAAK,EAAE,SAAS,OAAQ,QAAO,EAAE;AAAA,EACvC;AACA,SAAO;AACT;AAGA,IAAM,cAAc,oBAAI,IAAI,CAAC,WAAW,aAAa,UAAU,YAAY,QAAQ,OAAO,GAAG,CAAC;AAcvF,SAAS,cAAc,EAAE,UAAU,SAAS,eAAe,UAAU,aAAa,UAAU,GAOpF;AACb,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,MAAM,CAAC,aAAa,UAAU,WAAW,CAAC;AACnF,QAAM,WAAO,4BAAY,MAAM,YAAY,KAAK,GAAG,CAAC,CAAC;AACrD,QAAM,aAAS,4BAAY,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;AAE3D,QAAM,gBAAgB,WAAW,QAAQ;AACzC,QAAM,gBAAY,uBAAO,aAAa;AACtC,gCAAU,MAAM;AACd,QAAI,kBAAkB,UAAU,QAAS;AACzC,cAAU,UAAU;AACpB,gBAAY,KAAK;AAAA,EACnB,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,aAAS,uBAAO,SAAS;AAC/B,gCAAU,MAAM;AACd,QAAI,cAAc,OAAO,QAAS;AAClC,WAAO,UAAU;AACjB,gBAAY,KAAK;AAAA,EACnB,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,kBAAc,uBAAO,QAAQ;AACnC,cAAY,UAAU;AAGtB,gCAAU,MAAM;AACd,UAAM,WAAW,CAAC,MAA2B;AAC3C,YAAM,OAAO,QAAQ;AACrB,UAAI,EAAE,QAAQ,YAAY,CAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,SAAS,IAAI,EAAG;AACrE,QAAE,gBAAgB;AAClB,QAAE,eAAe;AACjB,UAAI,CAAC,YAAY,QAAS;AAC1B,kBAAY,KAAK;AACjB,oBAAc,SAAS,MAAM;AAAA,IAC/B;AACA,WAAO,iBAAiB,WAAW,UAAU,IAAI;AACjD,WAAO,MAAM,OAAO,oBAAoB,WAAW,UAAU,IAAI;AAAA,EACnE,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,gCAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,QAAQ,SAAS;AACvB,UAAM,SAAS,CAAC,MAAsB;AACpC,YAAM,OAAO,QAAQ;AACrB,aAAO,CAAC,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,IAAI;AAAA,IACjD;AACA,UAAM,SAAS,CAAC,MACd,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,aAAa,WAAW,EAAE,UAAU,SAAS,WAAW,CAAC;AACxF,UAAM,UAAU,CAAC,MAAmB;AAAE,UAAI,CAAC,OAAO,CAAC,EAAG,aAAY,KAAK;AAAA,IAAE;AACzE,UAAM,kBAAkB,CAAC,MAAmB;AAAE,UAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAG,aAAY,KAAK;AAAA,IAAE;AAC9F,UAAM,QAAQ,CAAC,MAA2B;AACxC,UAAI,YAAY,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,EAAG,aAAY,KAAK;AAAA,IAC5D;AAEA,UAAM,MAAM,OAAO,iBAAiB;AACpC,QAAI,iBAAiB,eAAe,SAAS,IAAI;AACjD,WAAO,iBAAiB,SAAS,iBAAiB,EAAE,SAAS,KAAK,CAAC;AACnE,WAAO,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,KAAK,CAAC;AACvE,WAAO,iBAAiB,WAAW,OAAO,IAAI;AAC9C,WAAO,MAAM;AACX,UAAI,oBAAoB,eAAe,SAAS,IAAI;AACpD,aAAO,oBAAoB,SAAS,eAAe;AACnD,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,oBAAoB,WAAW,OAAO,IAAI;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,OAAO,CAAC;AAEhC,SAAO,EAAE,UAAU,QAAQ,KAAK;AAClC;;;ACxGA,IAAM,MAAM;AACZ,IAAI,iBAAiB;AAEd,SAAS,eAAwB;AACtC,MAAI,eAAgB,QAAO;AAC3B,MAAI;AACF,WAAO,OAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAqB;AACnC,mBAAiB;AACjB,MAAI;AACF,WAAO,aAAa,QAAQ,KAAK,GAAG;AAAA,EACtC,QAAQ;AAAA,EAER;AACF;;;AvH0MM,IAAAC,wBAAA;AAhMC,IAAM,mBAAmB;AAEhC,SAAS,aAAsB;AAC7B,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,KAAK;AACxC,gCAAU,MAAM;AACd,QAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY;AAC9E,UAAM,MAAM,OAAO,WAAW,gBAAgB;AAC9C,UAAM,OAAO,MAAY,SAAS,IAAI,OAAO;AAC7C,SAAK;AACL,QAAI,iBAAiB,UAAU,IAAI;AACnC,WAAO,MAAM,IAAI,oBAAoB,UAAU,IAAI;AAAA,EACrD,GAAG,CAAC,CAAC;AACL,SAAO;AACT;AAWA,IAAM,qBAAoC,EAAE,UAAU,YAAY,OAAO,GAAG,YAAY,UAAU,SAAS,QAAQ,eAAe,SAAS;AAE3I,IAAM,oBAAmC,EAAE,SAAS,QAAQ,eAAe,UAAU,MAAM,GAAG,WAAW,EAAE;AAIpG,SAAS,UAAU,EAAE,YAAY,IAAI,MAAM,gBAAgB,SAAS,WAAW,aAAa,mBAAmB,oBAAoB,qBAAqB,iBAAiB,sBAAsB,wBAAwB,UAAU,cAAc,WAAW,GA6BjP;AACd,QAAM,EAAE,OAAO,OAAO,MAAM,MAAM,MAAM,IAAI;AAC5C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAA6B,QAAQ;AACvE,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,yBAAwB,IAAI;AAC5E,QAAM,oBAAoB,wBAAwB;AAClD,QAAM,oBAAoB,wBAAwB;AAClD,QAAM,oBAAgB,uBAAuB,IAAI;AACjD,QAAM,qBAAiB,uBAAsB,IAAI;AACjD,QAAM,eAAe,CAAC,aAAqB;AACzC,mBAAe,UAAU,cAAc,SAAS,cAAc,gBAAgB,GAAG,aAAa;AAC9F,wBAAoB,QAAQ;AAC5B,wBAAoB,QAAQ;AAAA,EAC9B;AACA,QAAM,cAAc,MAAM;AACxB,wBAAoB,IAAI;AACxB,wBAAoB;AAAA,EACtB;AAEA,sCAAgB,MAAM;AACpB,QAAI,qBAAqB,QAAQ,eAAe,YAAY,KAAM;AAClE,UAAM,OAAO,cAAc,SAAS,cAAc,gBAAgB;AAClE,QAAI,KAAM,MAAK,YAAY,eAAe;AAC1C,mBAAe,UAAU;AAAA,EAC3B,GAAG,CAAC,gBAAgB,CAAC;AACrB,QAAM,YAAY,SAAS;AAC3B,gCAAU,MAAM;AACd,QAAI,cAAc,WAAW,qBAAqB,KAAM;AACxD,wBAAoB,IAAI;AACxB,wBAAoB;AAAA,EACtB,GAAG,CAAC,WAAW,kBAAkB,iBAAiB,CAAC;AACnD,QAAM,UAAU,WAAW;AAC3B,gCAAU,MAAM;AACd,UAAM,QAAQ,CAAC,MAAqB;AAAE,UAAI,EAAE,QAAQ,SAAU,OAAM;AAAA,IAAE;AACtE,WAAO,iBAAiB,WAAW,KAAK;AACxC,WAAO,MAAM,OAAO,oBAAoB,WAAW,KAAK;AAAA,EAC1D,GAAG,CAAC,KAAK,CAAC;AAIV,QAAM,aAAa,CAAC,SAAiB;AACnC,iBAAa,UAAU;AACvB,aAAS,aAAa,MAAM;AAC5B,SAAK,IAAI;AAAA,EACX;AAIA,QAAM,YAAwB,CAAC,MAAM,cAAc;AACjD,aAAS,aAAa,MAAM;AAC5B,SAAK,MAAM,EAAE,UAAU,CAAC;AAAA,EAC1B;AAKA,gCAAU,MAAM;AACd,QAAI,WAAW,QAAQ,cAAc,UAAU,MAAM,YAAa,SAAQ,iBAAiB;AAAA,EAC7F,GAAG,CAAC,SAAS,MAAM,aAAa,MAAM,SAAS,MAAM,CAAC;AAGtD,QAAM,YAAY,CAAC,WAAW,QAAQ,cAAc;AACpD,QAAM,eAAW,uBAAuB,IAAI;AAC5C,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,oBAAgB,uBAA0B,IAAI;AACpD,QAAM,eAAW,uBAAwB,IAAI;AAC7C,QAAM,eAAW,uBAAuB,IAAI;AAC5C,QAAM,mBAAe,uBAAO,KAAK;AACjC,QAAM,yBAAqB,uBAAmC,IAAI;AAClE,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA0B,IAAI;AACtD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,YAAY;AACrD,QAAM,OAAO,cAAc;AAAA,IACzB;AAAA,IAAU;AAAA,IAAS;AAAA,IACnB,UAAU,MAAM;AAAA,IAAU,aAAa,MAAM;AAAA,IAAa,WAAW,SAAS,aAAa;AAAA,EAC7F,CAAC;AACD,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,SAAS,SAAS,MAAM,KAAK;AACnC,QAAM,WAAW,CAAC,CAAC,cAAc,aAAa,CAAC,QAAQ,CAAC;AACxD,gCAAU,MAAM;AAAE,QAAI,OAAQ,SAAQ,IAAI;AAAA,EAAE,GAAG,CAAC,MAAM,CAAC;AAEvD,gCAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,QAAI,aAAa,QAAS,UAAS,SAAS,MAAM;AAClD,iBAAa,UAAU;AAAA,EACzB,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,eAAW,4BAAY,CAAC,SAAmB;AAC/C,SAAK;AACL,iBAAa;AACb,gBAAY,IAAI;AAChB,YAAQ,IAAI;AAAA,EACd,GAAG,CAAC,IAAI,CAAC;AACT,QAAM,aAAS,4BAAY,CAAC,SAAyB,SAAS,SAAS,YAAY,EAAE,MAAM,UAAU,IAAI,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEvI,QAAM,iBAAa;AAAA,IACjB,MAAO,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,SAAS,SAAS,EAAE,MAAM,SAAS,OAAO,KAAK,CAAC,GAAG,aAAa,GAAG,QAAQ,YAAY,IAAI;AAAA,IACjJ,CAAC,YAAY,QAAQ,UAAU,GAAG,QAAQ,WAAW;AAAA,EACvD;AACA,QAAM,gBAAY,4BAAY,MAAM;AAClC,uBAAmB,UAAU;AAC7B,YAAQ,IAAI;AAAA,EACd,GAAG,CAAC,CAAC;AACL,QAAM,cAAU,4BAAY,CAAC,QAAmB;AAC9C,uBAAmB,UAAU;AAC7B,YAAQ,IAAI;AACZ,aAAS,aAAa,MAAM;AAC5B,SAAK,IAAI,SAAS,EAAE,aAAa,IAAI,aAAa,QAAQ,IAAI,OAAO,CAAC;AAAA,EACxE,GAAG,CAAC,SAAS,IAAI,CAAC;AAGlB,QAAM,oBAAgB,4BAAY,CAAC,eAAuB;AACxD,UAAM,IAAI,GAAG,eAAe,UAAU;AACtC,WAAO,GAAG,EAAE,QAAQ,IAAI,EAAE,IAAI;AAAA,EAChC,GAAG,CAAC,EAAE,CAAC;AAGP,gCAAU,MAAM;AACd,QAAI,KAAM;AACV,UAAM,SAAS,mBAAmB;AAClC,uBAAmB,UAAU;AAC7B,QAAI,WAAW,OAAQ,eAAc,SAAS,MAAM;AAAA,aAC3C,WAAW,WAAY,UAAS,SAAS,MAAM;AAAA,EAC1D,GAAG,CAAC,IAAI,CAAC;AAIT,gCAAU,MAAM;AACd,QAAI,CAAC,QAAS,aAAa,WAAa;AACxC,uBAAmB,UAAU;AAC7B,YAAQ,IAAI;AAAA,EACd,GAAG,CAAC,MAAM,WAAW,UAAU,CAAC;AAEhC,SACE,gDAAC,SAAI,WAAU,cAAa,MAAK,UAAS,cAAY,SAAS,cAAY,GAAG,iBAC5E;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,YAAY,GAAG;AAAA,QACf,SAAS,GAAG;AAAA,QACZ,aAAa,GAAG;AAAA,QAChB,mBAAmB;AAAA,QACnB,UAAU,MAAM,SAAS,SAAS;AAAA,QAClC,sBAAsB,GAAG;AAAA,QACzB,kBAAkB,GAAG;AAAA;AAAA,IACvB;AAAA,IACC,WACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,YAAY,QAAQ,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE;AAAA,QAC3D,WAAW,QAAQ,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE;AAAA,QAC1D,YAAY,WAAW,aAAa;AAAA,QACpC,UAAU,YAAY,gBAAgB,UAAU,QAAQ,UAAU,MAAM,EAAE,SAAS,IAAI;AAAA,QACvF,cAAc,aAAa,WAAW;AAAA,QACtC,aAAa,oBAAoB,WAAW;AAAA;AAAA,IAC9C;AAAA,IAEF,gDAAC,SAAI,KAAK,UAAU,WAAU,mBAAkB,aAAW,aAAa,KAAK,QAAW,OAAO,YAAY,SAAY,oBACrH;AAAA,qDAAC,mBAAmB,UAAnB,EAA4B,OAAO,YAClC,yDAAC,eAAY,YAAwB,IAAQ,MAAY,gBAAgC,SAAkB,GAC7G;AAAA,MACC,WACC;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,KAAK;AAAA,UAAU,SAAS,CAAC;AAAA,UAAU,SAAS,GAAG;AAAA,UACzD,UAAU,KAAK;AAAA,UAAQ,QAAQ;AAAA,UAAQ,SAAS;AAAA,UAAS,WAAW;AAAA;AAAA,MACtE,IACE;AAAA,MACH,QAAQ,cAAc,aAAa,CAAC,SACnC,KAAK,SAAS,YACV,+CAAC,kBAAe,MAAM,YAAY,SAAS,GAAG,SAAS,WAAW,MAAM,aAAa,QAAQ,SAAS,SAAS,WAAW,IAC1H,+CAAC,kBAAe,MAAM,YAAY,SAAS,GAAG,SAAS,WAAW,MAAM,aAAa,eAA8B,cAAc,KAAK,OAAO,aAAa,KAAK,MAAM,QAAQ,SAAS,SAAS,WAAW,IAC5M;AAAA,OACN;AAAA,IACC,WAAW,aAAa,QAAQ,cAAc,WAAW,+CAAC,cAAW,WAAsB,IAAQ,SAAkB;AAAA,IACrH,WAAW,QAAQ,cAAc,eAAe,+CAAC,gBAAa,SAAkB,IAAQ,MAAY,OAAO,SAAS,SAAY,WAAW;AAAA,IAC3I,WAAW,QAAQ,cAAc,UAAU,+CAAC,aAAU,SAAkB,IAAQ,MAAY;AAAA,IAC5F,WAAW,QAAQ,cAAc,cAChC,+CAAC,YAAS,UAAU,oBAAoB,YAAY,CAAC,GAAG,SAAS,oBAAoB,WAAW,OAAO,IAAQ;AAAA,IAEhH,WAAW,QAAQ,cAAc,eAChC,+CAAC,aAAU,WAAW,qBAAqB,QAAQ,MAAM,SAAS,qBAAqB,WAAW,OAAO,IAAQ;AAAA,IAElH,WAAW,QAAQ,cAAc,WAChC,kFAEE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,OAAO,qBAAqB,OAAO,oBAAoB;AAAA,UACvD,eAAa,qBAAqB,OAAO,OAAO;AAAA,UAEhD;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,iBAAiB,QAAQ;AAAA,cAAM,SAAS,iBAAiB,WAAW;AAAA,cAAO;AAAA,cAClF,MAAM;AAAA,cAAW,cAAc,MAAM,aAAa,CAAC,MAAO,MAAM,WAAW,UAAU,QAAS;AAAA,cAC9F,OAAO,sBAAsB,QAAQ;AAAA,cAAM,cAAc,sBAAsB,WAAW;AAAA,cAC1F,YAAY,sBAAsB,cAAc;AAAA,cAAM,iBAAiB,sBAAsB,mBAAmB;AAAA,cAAM,eAAe,sBAAsB,iBAAiB;AAAA,cAC5K,gBAAgB;AAAA;AAAA,UAClB;AAAA;AAAA,MACF;AAAA,MACC,qBAAqB,QACpB,+CAAC,gBAAa,QAAQ,wBAAwB,QAAQ,MAAM,SAAS,wBAAwB,WAAW,OAAO,IAAQ,YAAY,sBAAsB,cAAc,MAAM,SAAS,aAAa;AAAA,OAEvM;AAAA,IAED,WAAW,QAAQ,cAAc,WAAW,eAC3C;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,CAAC;AAAA,QACZ,OAAO,YAAY;AAAA,QACnB;AAAA,QACA;AAAA,QACA,aAAa,mBAAmB,QAAQ;AAAA,QACxC,oBAAoB,mBAAmB,WAAW;AAAA,QAClD,YAAY,MAAM;AAAE,sBAAY,QAAQ;AAAG,6BAAmB,QAAQ;AAAA,QAAE;AAAA;AAAA,IAC1E;AAAA,KAGA,CAAC,WAAW,QAAQ,cAAc,YAClC,kFACE;AAAA,qDAAC,SAAI,KAAK,UAAU,WAAU,cAAa,MAAK,UAAS,UAAU,IAAK,gBAAM,QAAQ,UAAU,MAAM,OAAO,EAAE,IAAI,MAAK;AAAA,MACvH,SAAS,OACR;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UAAU,aAAa,GAAG;AAAA,UAAa,WAAW,MAAM;AAAA,UAAa,QAAQ;AAAA,UAAY,QAAQ;AAAA,UACtG,WAAW,GAAG;AAAA,UAAc,WAAW,GAAG;AAAA,UAAa,UAAU,CAAC,CAAC;AAAA,UAAM,QAAQ;AAAA;AAAA,MACnF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;;;AwHvTS,IAAAC,wBAAA;AADF,SAAS,mBAAmB,EAAE,OAAO,SAAS,GAA4D;AAC/G,SAAO,+CAAC,iBAAiB,UAAjB,EAA0B,OAAO,MAAM,WAAY,UAAS;AACtE;;;ACNO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["import_react","import_widget_sdk","read","key","isRecord","parse","browserStorage","read","import_react","import_widget_sdk","import_widget_sdk","import_widget_sdk","import_react","tile","import_react","import_react","import_react","TTL_MS","encodedUserKey","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","finite","finite","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","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_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","directionWord","import_react","import_jsx_runtime","initials","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_jsx_runtime","Crest","import_react","head","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","Crest","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","initials","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","initials","import_react","import_jsx_runtime","SHOWN","import_react","import_jsx_runtime","import_jsx_runtime","splitWidths","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","ChatInput","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","resultClass","import_jsx_runtime","Crest","import_jsx_runtime","import_react","import_react","import_jsx_runtime","starClickable","Crest","import_react","import_jsx_runtime","import_jsx_runtime","STAR_PATH","Crest","import_jsx_runtime","STAR_PATH","starClickable","Crest","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Crest","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","isTerminal","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_react","import_jsx_runtime","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","import_jsx_runtime","parseClientState","isLocked","React","import_react","import_jsx_runtime","import_jsx_runtime","MAX_GUESSES","parseClientState","import_react","import_jsx_runtime","parseClientState","segments","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_react","import_jsx_runtime","parseClientState","import_jsx_runtime","parseClientState","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","finite","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","choices","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","locale"]}