{"version":3,"sources":["../src/index.ts","../src/core/sse.ts","../src/core/providers.ts","../src/core/storage.ts","../src/core/ChatCore.ts","../src/ui/styles.ts","../src/ui/ChatUI.ts"],"sourcesContent":["/**\n * @geepers/chat — Full-featured chat UI package for multi-provider LLM APIs\n *\n * Primary API:\n *   import ChatUI from '@geepers/chat';\n *   const chat = new ChatUI('#app', { gateway: '...', apiKey: 'sk_...', provider: 'anthropic' });\n *\n * Headless (no DOM):\n *   import { ChatCore } from '@geepers/chat';\n *   const core = new ChatCore({ gateway: '...', apiKey: 'sk_...' });\n *   core.on('stream-chunk', (e) => console.log(e.accumulated));\n *   await core.send('Hello!');\n */\n\n// ---- Core exports ----\nexport { ChatUI } from './ui/ChatUI.js';\nexport { ChatCore } from './core/ChatCore.js';\nexport { ConversationStorage } from './core/storage.js';\nexport { MODELS, PROVIDER_KEYS, getProviderConfig, isKnownProvider } from './core/providers.js';\n\n// ---- Type exports ----\nexport type {\n  // Config\n  ChatConfig,\n  ThemeMode,\n  WelcomeHint,\n\n  // Messages & conversations\n  Message,\n  MessageRole,\n  ConversationRecord,\n\n  // Providers\n  Provider,\n  ProviderConfig,\n\n  // Events\n  ChatEvent,\n  ChatEventType,\n  ChatEventHandler,\n  MessageEvent,\n  StreamChunkEvent,\n  StreamStartEvent,\n  StreamEndEvent,\n  ErrorEvent,\n  ConversationChangeEvent,\n} from './types/index.js';\n\n// ---- Default export: ChatUI ----\nexport { ChatUI as default } from './ui/ChatUI.js';\n","/**\n * Internal framework-agnostic SSE streaming client for @geepers/chat.\n *\n * Handles Server-Sent Events streaming for multi-provider LLM chat APIs.\n * Parses SSE data lines, extracts content from various provider response formats,\n * and provides callbacks for streaming chunks and completion.\n *\n * @example\n * ```ts\n * import { ChatCore } from '@geepers/chat';\n *\n * const chat = new ChatCore({ gateway: 'https://api.example.com/v1' });\n * await chat.send('Hello!');\n * ```\n */\n\nexport interface SSEChatOptions {\n  /** API endpoint URL for chat completions */\n  apiUrl: string;\n  /** API key sent as X-API-Key header */\n  apiKey?: string;\n  /** Additional headers to include in requests */\n  headers?: Record<string, string>;\n}\n\nexport interface ChatMessage {\n  role: 'system' | 'user' | 'assistant';\n  content: string;\n}\n\nexport interface SendOptions {\n  /** LLM provider name */\n  provider: string;\n  /** Model identifier */\n  model: string;\n  /** Conversation messages */\n  messages: ChatMessage[];\n  /** Called with each text chunk as it streams in */\n  onChunk?: (chunk: string, accumulated: string) => void;\n  /** Called when streaming is complete */\n  onDone?: (fullText: string) => void;\n  /** Called on error */\n  onError?: (error: Error) => void;\n  /** Optional AbortSignal for cancellation */\n  signal?: AbortSignal;\n  /** Additional body parameters to include in the request */\n  extraParams?: Record<string, unknown>;\n}\n\n/**\n * Extract content from various SSE JSON formats used by different providers.\n * Handles OpenAI, Anthropic, xAI, and custom gateway formats.\n */\nfunction extractContent(parsed: Record<string, unknown>): string {\n  // Direct content field (custom gateways)\n  if (typeof parsed.content === 'string') return parsed.content;\n\n  // OpenAI format: choices[0].delta.content\n  const choices = parsed.choices as Array<Record<string, unknown>> | undefined;\n  if (choices?.[0]) {\n    const delta = choices[0].delta as Record<string, string> | undefined;\n    if (delta?.content) return delta.content;\n  }\n\n  // Anthropic format: message.content or content_block.text\n  const message = parsed.message as Record<string, string> | undefined;\n  if (message?.content) return message.content;\n\n  const contentBlock = parsed.content_block as Record<string, string> | undefined;\n  if (contentBlock?.text) return contentBlock.text;\n\n  // Delta text (Anthropic streaming)\n  const delta = parsed.delta as Record<string, string> | undefined;\n  if (delta?.text) return delta.text;\n\n  return '';\n}\n\nexport class SSEChat {\n  private apiUrl: string;\n  private apiKey?: string;\n  private headers: Record<string, string>;\n\n  constructor(options: SSEChatOptions) {\n    this.apiUrl = options.apiUrl;\n    this.apiKey = options.apiKey;\n    this.headers = options.headers ?? {};\n  }\n\n  /** Update the API key at runtime */\n  setApiKey(key: string): void {\n    this.apiKey = key;\n  }\n\n  /**\n   * Send a chat message and stream the response via SSE.\n   * Returns a promise that resolves with the full response text.\n   */\n  async send(options: SendOptions): Promise<string> {\n    const { provider, model, messages, onChunk, onDone, onError, signal, extraParams } = options;\n\n    const headers: Record<string, string> = {\n      'Content-Type': 'application/json',\n      'Accept': 'text/event-stream',\n      ...this.headers,\n    };\n\n    if (this.apiKey) {\n      headers['X-API-Key'] = this.apiKey;\n    }\n\n    let fullContent = '';\n\n    try {\n      const response = await fetch(this.apiUrl, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify({\n          provider,\n          model,\n          messages,\n          stream: true,\n          ...extraParams,\n        }),\n        signal,\n      });\n\n      if (!response.ok) {\n        const errorText = await response.text();\n        const error = new Error(\n          response.status === 401 ? 'Invalid API key' :\n          response.status === 429 ? 'Rate limit exceeded' :\n          `HTTP ${response.status}: ${errorText}`\n        );\n        onError?.(error);\n        throw error;\n      }\n\n      const reader = response.body!.getReader();\n      const decoder = new TextDecoder();\n      let buffer = '';\n\n      while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n\n        buffer += decoder.decode(value, { stream: true });\n        const lines = buffer.split('\\n');\n        buffer = lines.pop() ?? '';\n\n        for (const line of lines) {\n          if (line.trim() === '' || !line.startsWith('data: ')) continue;\n\n          const data = line.slice(6);\n          if (data === '[DONE]') continue;\n\n          try {\n            const parsed = JSON.parse(data) as Record<string, unknown>;\n            const chunk = extractContent(parsed);\n\n            if (chunk) {\n              fullContent += chunk;\n              onChunk?.(chunk, fullContent);\n            }\n          } catch {\n            // Skip malformed JSON lines\n          }\n        }\n      }\n\n      onDone?.(fullContent);\n      return fullContent;\n    } catch (error) {\n      if (error instanceof Error && error.name === 'AbortError') {\n        onDone?.(fullContent);\n        return fullContent;\n      }\n      const err = error instanceof Error ? error : new Error(String(error));\n      onError?.(err);\n      throw err;\n    }\n  }\n}\n\nexport default SSEChat;\n","/**\n * Provider configurations for @geepers/chat\n *\n * Model names match what the API Gateway (api-gateway/app.py) expects.\n * Sourced from Slate's MODELS constant and verified against the gateway.\n */\n\nimport type { Provider, ProviderConfig } from '../types/index.js';\n\nexport const MODELS: Record<Provider, ProviderConfig> = {\n  xai: {\n    model: 'grok-4',\n    label: 'xAI Grok 4',\n  },\n  anthropic: {\n    model: 'claude-sonnet-4-6',\n    label: 'Claude Sonnet 4.6',\n  },\n  openai: {\n    model: 'gpt-5.4',\n    label: 'OpenAI GPT-5.4',\n  },\n  cohere: {\n    model: 'command-r-plus-08-2024',\n    label: 'Cohere Command R+',\n  },\n  mistral: {\n    model: 'mistral-large-latest',\n    label: 'Mistral Large',\n  },\n  perplexity: {\n    model: 'sonar-pro',\n    label: 'Perplexity Sonar Pro',\n  },\n  huggingface: {\n    model: 'Qwen/Qwen3.5-9B',\n    label: 'HuggingFace Qwen 3.5',\n  },\n  gemini: {\n    model: 'gemini-2.5-flash',\n    label: 'Google Gemini 2.5',\n  },\n  ollama: {\n    model: 'llama3.2:3b',\n    label: 'Ollama (Local)',\n  },\n};\n\n/** Array of all valid provider keys, useful for validation and UI rendering */\nexport const PROVIDER_KEYS: Provider[] = Object.keys(MODELS) as Provider[];\n\n/**\n * Validate that a string is a known provider key.\n * Logs a console warning for unknown providers but does not throw.\n */\nexport function isKnownProvider(value: string): value is Provider {\n  const known = PROVIDER_KEYS.includes(value as Provider);\n  if (!known) {\n    console.warn(`[@geepers/chat] Unknown provider: \"${value}\". Known providers: ${PROVIDER_KEYS.join(', ')}`);\n  }\n  return known;\n}\n\n/**\n * Get the model config for a provider, falling back to xai if unknown.\n */\nexport function getProviderConfig(provider: string): ProviderConfig {\n  if (isKnownProvider(provider)) {\n    return MODELS[provider];\n  }\n  return MODELS.xai;\n}\n","/**\n * Conversation persistence for @geepers/chat\n * localStorage-backed with max 20 conversations, sorted by updatedAt.\n */\n\nimport type { ConversationRecord, Message, Provider } from '../types/index.js';\n\nconst DEFAULT_KEY = 'gchat_conversations';\nconst MAX_CONVOS = 20;\n\nexport class ConversationStorage {\n  private readonly key: string;\n\n  constructor(storageKey = DEFAULT_KEY) {\n    this.key = storageKey;\n  }\n\n  private read(): Record<string, ConversationRecord> {\n    try {\n      return JSON.parse(localStorage.getItem(this.key) || '{}');\n    } catch {\n      return {};\n    }\n  }\n\n  private write(data: Record<string, ConversationRecord>): void {\n    try {\n      localStorage.setItem(this.key, JSON.stringify(data));\n    } catch {\n      // Storage full or unavailable — skip silently\n    }\n  }\n\n  all(): ConversationRecord[] {\n    const data = this.read();\n    return Object.values(data).sort((a, b) => b.updatedAt - a.updatedAt);\n  }\n\n  get(id: string): ConversationRecord | undefined {\n    return this.read()[id];\n  }\n\n  save(record: ConversationRecord): void {\n    const data = this.read();\n    data[record.id] = record;\n\n    // Trim to max\n    const sorted = Object.keys(data).sort(\n      (a, b) => data[b].updatedAt - data[a].updatedAt\n    );\n    if (sorted.length > MAX_CONVOS) {\n      sorted.slice(MAX_CONVOS).forEach(k => delete data[k]);\n    }\n\n    this.write(data);\n  }\n\n  delete(id: string): void {\n    const data = this.read();\n    delete data[id];\n    this.write(data);\n  }\n\n  /** Create a new ConversationRecord from the given messages */\n  static build(\n    id: string,\n    messages: Message[],\n    provider: Provider,\n    systemPrompt: string\n  ): ConversationRecord {\n    const first = messages.find(m => m.role === 'user');\n    const title = first\n      ? first.content.slice(0, 50) + (first.content.length > 50 ? '…' : '')\n      : 'New conversation';\n\n    return {\n      id,\n      title,\n      messages,\n      provider,\n      systemPrompt,\n      createdAt: Date.now(),\n      updatedAt: Date.now(),\n    };\n  }\n}\n","/**\n * ChatCore — Headless chat state controller for @geepers/chat\n *\n * Manages conversation state, localStorage persistence, and SSE streaming.\n * Emits typed events so any UI layer (or no UI at all) can consume state changes.\n *\n * Uses the package's internal SSE client for actual streaming; this class\n * handles state, persistence, and orchestration.\n */\n\nimport { SSEChat } from './sse.js';\nimport type { ChatMessage as SSEChatMessage } from './sse.js';\nimport {\n  MODELS,\n  isKnownProvider,\n} from './providers.js';\nimport { ConversationStorage } from './storage.js';\nimport type {\n  ChatConfig,\n  ChatEvent,\n  ChatEventHandler,\n  ChatEventType,\n  ConversationRecord,\n  Message,\n  MessageRole,\n  Provider,\n} from '../types/index.js';\n\nconst DEFAULT_GATEWAY = 'https://api.dr.eamer.dev/v1';\nconst DEFAULT_STORAGE_KEY = 'gchat_conversations';\n\n// ========== Helpers ==========\n\nfunction generateId(): string {\n  // crypto.randomUUID() is available in all modern browsers and Node 15+\n  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n    return crypto.randomUUID();\n  }\n  // Fallback for very old environments\n  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction generateMessageId(): string {\n  return generateId();\n}\n\nfunction now(): number {\n  return Date.now();\n}\n\n// ========== Event Emitter (minimal, typed) ==========\n\ntype HandlerMap = Map<string, Set<ChatEventHandler<ChatEvent>>>;\n\nclass EventEmitter {\n  private handlers: HandlerMap = new Map();\n\n  on<T extends ChatEvent>(type: ChatEventType, handler: ChatEventHandler<T>): void {\n    if (!this.handlers.has(type)) {\n      this.handlers.set(type, new Set());\n    }\n    this.handlers.get(type)!.add(handler as ChatEventHandler<ChatEvent>);\n  }\n\n  off<T extends ChatEvent>(type: ChatEventType, handler: ChatEventHandler<T>): void {\n    this.handlers.get(type)?.delete(handler as ChatEventHandler<ChatEvent>);\n  }\n\n  emit(event: ChatEvent): void {\n    this.handlers.get(event.type)?.forEach(h => h(event));\n  }\n}\n\n// ========== ChatCore ==========\n\nexport class ChatCore {\n  private config: Required<Pick<ChatConfig, 'gateway' | 'storageKey' | 'theme'>> & ChatConfig;\n  private emitter: EventEmitter;\n  private sseClient: SSEChat;\n  private storage: ConversationStorage;\n\n  /** Current active provider */\n  private _provider: Provider;\n\n  /** Current active model (can override per-provider default) */\n  private _model: string;\n\n  /** System prompt for the current conversation */\n  private _systemPrompt: string;\n\n  /** Ordered message history for the current conversation (excludes system) */\n  private _messages: Message[];\n\n  /** ID of the current conversation (UUID) */\n  private _conversationId: string | null;\n\n  /** Whether a stream is currently active */\n  private _isStreaming: boolean;\n\n  /** AbortController for the current stream */\n  private _abortController: AbortController | null;\n\n  constructor(config: ChatConfig = {}) {\n    this.config = {\n      gateway: DEFAULT_GATEWAY,\n      storageKey: DEFAULT_STORAGE_KEY,\n      theme: 'auto',\n      ...config,\n    };\n\n    this.emitter = new EventEmitter();\n\n    // Resolve provider\n    const initialProvider: Provider = (config.provider && isKnownProvider(config.provider))\n      ? config.provider\n      : 'xai';\n    this._provider = initialProvider;\n    this._model = config.model ?? MODELS[initialProvider].model;\n    this._systemPrompt = config.systemPrompt ?? '';\n    this._messages = [];\n    this._conversationId = null;\n    this._isStreaming = false;\n    this._abortController = null;\n\n    // Build SSE client\n    this.sseClient = new SSEChat({\n      apiUrl: `${this.config.gateway}/llm/chat`,\n      apiKey: this._resolveApiKey(),\n    });\n\n    // Persistence layer\n    this.storage = new ConversationStorage(this.config.storageKey);\n\n    // Restore conversation if requested\n    if (config.conversationId) {\n      this.loadConversation(config.conversationId);\n    } else {\n      // Start a fresh conversation\n      this._conversationId = generateId();\n    }\n  }\n\n  // ========== Getters ==========\n\n  get provider(): Provider { return this._provider; }\n  get model(): string { return this._model; }\n  get systemPrompt(): string { return this._systemPrompt; }\n  get messages(): Readonly<Message[]> { return this._messages; }\n  get conversationId(): string | null { return this._conversationId; }\n  get isStreaming(): boolean { return this._isStreaming; }\n\n  // ========== Event subscriptions ==========\n\n  on<T extends ChatEvent>(type: ChatEventType, handler: ChatEventHandler<T>): void {\n    this.emitter.on(type, handler);\n  }\n\n  off<T extends ChatEvent>(type: ChatEventType, handler: ChatEventHandler<T>): void {\n    this.emitter.off(type, handler);\n  }\n\n  // ========== Configuration mutations ==========\n\n  setProvider(provider: string): void {\n    if (!isKnownProvider(provider)) return;\n    this._provider = provider;\n    this._model = MODELS[provider].model;\n    this.sseClient.setApiKey(this._resolveApiKey());\n  }\n\n  setModel(model: string): void {\n    this._model = model;\n  }\n\n  setSystemPrompt(prompt: string): void {\n    this._systemPrompt = prompt;\n  }\n\n  setApiKey(key: string): void {\n    this.sseClient.setApiKey(key);\n  }\n\n  // ========== Core actions ==========\n\n  /**\n   * Send a user message and stream the assistant response.\n   * Rejects if a stream is already active.\n   */\n  async send(content: string): Promise<void> {\n    if (this._isStreaming) {\n      throw new Error('A stream is already in progress. Call stop() first.');\n    }\n    if (!content.trim()) return;\n\n    // Add user message to state\n    const userMessage = this._addMessage('user', content);\n    this.emitter.emit({ type: 'message', message: userMessage });\n\n    // Create placeholder for assistant response\n    const assistantId = generateMessageId();\n    const assistantPlaceholder: Message = {\n      id: assistantId,\n      role: 'assistant',\n      content: '',\n      timestamp: now(),\n      provider: this._provider,\n    };\n    this._messages.push(assistantPlaceholder);\n\n    this._isStreaming = true;\n    this._abortController = new AbortController();\n    this.emitter.emit({ type: 'stream-start', messageId: assistantId });\n\n    // Notify lifecycle callback\n    this.config.onStreamStart?.(assistantId);\n\n    // Build messages array for the API (includes optional system prompt)\n    const apiMessages: SSEChatMessage[] = [];\n    if (this._systemPrompt.trim()) {\n      apiMessages.push({ role: 'system', content: this._systemPrompt.trim() });\n    }\n    // Only send user/assistant turns (no system messages in history)\n    for (const m of this._messages) {\n      if (m.role !== 'system' && m.id !== assistantId) {\n        apiMessages.push({ role: m.role as 'user' | 'assistant', content: m.content });\n      }\n    }\n\n    let accumulated = '';\n\n    try {\n      await this.sseClient.send({\n        provider: this._provider,\n        model: this._model,\n        messages: apiMessages,\n        signal: this._abortController.signal,\n\n        onChunk: (chunk: string, acc: string) => {\n          accumulated = acc;\n          // Update the placeholder in-place\n          assistantPlaceholder.content = acc;\n          this.emitter.emit({\n            type: 'stream-chunk',\n            chunk,\n            accumulated: acc,\n            messageId: assistantId,\n          });\n        },\n\n        onDone: (fullText: string) => {\n          assistantPlaceholder.content = fullText;\n          assistantPlaceholder.timestamp = now();\n        },\n\n        onError: (error: Error) => {\n          this.emitter.emit({ type: 'error', error });\n          this.config.onError?.(error);\n        },\n      });\n    } catch (error) {\n      // AbortError is expected when stop() is called — treat as graceful end\n      if (!(error instanceof Error && error.name === 'AbortError')) {\n        const err = error instanceof Error ? error : new Error(String(error));\n        this.emitter.emit({ type: 'error', error: err });\n        this.config.onError?.(err);\n      }\n    } finally {\n      this._isStreaming = false;\n      this._abortController = null;\n\n      // Finalise assistant message\n      const finalMessage: Message = { ...assistantPlaceholder, content: accumulated || assistantPlaceholder.content };\n      // Update in place so references stay valid\n      assistantPlaceholder.content = finalMessage.content;\n\n      this.emitter.emit({ type: 'stream-end', message: assistantPlaceholder });\n      this.config.onStreamEnd?.(assistantPlaceholder);\n      this.config.onMessage?.(assistantPlaceholder);\n\n      // Persist after every completed exchange\n      this._saveCurrentConversation();\n    }\n  }\n\n  /**\n   * Abort the current stream. The partial assistant response is kept.\n   */\n  stop(): void {\n    if (this._abortController) {\n      this._abortController.abort();\n    }\n  }\n\n  /**\n   * Clear messages and start a fresh conversation with a new UUID.\n   * Saves the current conversation before clearing if it has messages.\n   */\n  clearHistory(): void {\n    this._saveCurrentConversation();\n    this._messages = [];\n    this._conversationId = generateId();\n    this.emitter.emit({ type: 'conversation-change', conversationId: this._conversationId });\n  }\n\n  // ========== Persistence ==========\n\n  /**\n   * Load a saved conversation by ID.\n   * Saves the current conversation first.\n   */\n  loadConversation(id: string): boolean {\n    this._saveCurrentConversation();\n\n    const record = this.storage.get(id);\n    if (!record) return false;\n\n    this._conversationId = id;\n    this._messages = record.messages ?? [];\n    this._provider = isKnownProvider(record.provider) ? record.provider : 'xai';\n    this._model = MODELS[this._provider].model;\n    this._systemPrompt = record.systemPrompt ?? '';\n\n    this.emitter.emit({ type: 'conversation-change', conversationId: id });\n    return true;\n  }\n\n  /**\n   * Return all saved conversations, sorted newest first.\n   */\n  getConversations(): ConversationRecord[] {\n    return this.storage.all();\n  }\n\n  /**\n   * Delete a saved conversation by ID.\n   * If deleting the active conversation, starts a fresh one.\n   */\n  deleteConversation(id: string): void {\n    this.storage.delete(id);\n\n    if (id === this._conversationId) {\n      this.clearHistory();\n    }\n  }\n\n  // ========== Private helpers ==========\n\n  private _resolveApiKey(): string {\n    if (this.config.apiKey) return this.config.apiKey;\n    // Fall back to localStorage (mirrors IO Suite auth pattern)\n    try {\n      return localStorage.getItem('api_key') ?? '';\n    } catch {\n      return '';\n    }\n  }\n\n  private _addMessage(role: MessageRole, content: string, provider?: Provider): Message {\n    const message: Message = {\n      id: generateMessageId(),\n      role,\n      content,\n      timestamp: now(),\n      provider,\n    };\n    this._messages.push(message);\n    return message;\n  }\n\n  private _saveCurrentConversation(): void {\n    if (!this._conversationId || this._messages.length === 0) return;\n\n    const existing = this.storage.get(this._conversationId);\n    const record = ConversationStorage.build(\n      this._conversationId,\n      [...this._messages],\n      this._provider,\n      this._systemPrompt\n    );\n    // Preserve original createdAt if record already exists\n    if (existing) record.createdAt = existing.createdAt;\n\n    this.storage.save(record);\n  }\n}\n","/**\n * Auto-generated from ChatUI.css — do not edit directly.\n * Exported as a string so ChatUI can inject it without bundler ?inline support.\n */\nexport const CHAT_CSS = `\n/**\n * @geepers/chat — default UI styles\n * Self-contained: injected as a <style> tag when ChatUI mounts.\n * Uses CSS custom properties so host page can override any token.\n */\n\n/* ========== Reset & Scope ========== */\n.gchat-root,\n.gchat-root * {\n  box-sizing: border-box;\n  margin: 0;\n  padding: 0;\n}\n\n/* ========== Tokens ========== */\n.gchat-root {\n  /* Light theme defaults */\n  --gchat-bg-0:     #ffffff;\n  --gchat-bg-1:     #f4f4f5;\n  --gchat-bg-2:     #e4e4e7;\n  --gchat-text-0:   #18181b;\n  --gchat-text-1:   #3f3f46;\n  --gchat-text-2:   #71717a;\n  --gchat-border:   #d4d4d8;\n  --gchat-accent:   #6366f1;\n  --gchat-accent-h: #4f46e5;\n  --gchat-error:    #ef4444;\n  --gchat-radius:   8px;\n  --gchat-radius-sm:4px;\n  --gchat-shadow:   0 1px 3px rgba(0,0,0,0.08);\n  --gchat-font:     -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n  --gchat-mono:     'SFMono-Regular', Consolas, 'Liberation Mono', monospace;\n  --gchat-ease:     150ms ease;\n  --gchat-sidebar-w:260px;\n}\n\n/* Dark theme override */\n.gchat-root[data-theme=\"dark\"] {\n  --gchat-bg-0:   #09090b;\n  --gchat-bg-1:   #18181b;\n  --gchat-bg-2:   #27272a;\n  --gchat-text-0: #fafafa;\n  --gchat-text-1: #d4d4d8;\n  --gchat-text-2: #71717a;\n  --gchat-border: #3f3f46;\n  --gchat-shadow: 0 1px 3px rgba(0,0,0,0.4);\n}\n\n/* ========== Root Layout ========== */\n.gchat-root {\n  font-family: var(--gchat-font);\n  font-size: 14px;\n  color: var(--gchat-text-0);\n  background: var(--gchat-bg-0);\n  display: flex;\n  height: 100%;\n  min-height: 400px;\n  overflow: hidden;\n  position: relative;\n}\n\n/* ========== Sidebar ========== */\n.gchat-sidebar {\n  width: var(--gchat-sidebar-w);\n  flex-shrink: 0;\n  background: var(--gchat-bg-1);\n  border-right: 1px solid var(--gchat-border);\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n}\n\n.gchat-sidebar-header {\n  padding: 12px 14px;\n  border-bottom: 1px solid var(--gchat-border);\n  display: flex;\n  align-items: center;\n  gap: 8px;\n}\n\n.gchat-sidebar-title {\n  font-size: 0.8rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.06em;\n  color: var(--gchat-text-2);\n  flex: 1;\n}\n\n.gchat-new-btn {\n  padding: 5px 10px;\n  background: var(--gchat-accent);\n  color: #fff;\n  border: none;\n  border-radius: var(--gchat-radius-sm);\n  font-size: 0.8rem;\n  font-weight: 600;\n  cursor: pointer;\n  transition: background var(--gchat-ease);\n  white-space: nowrap;\n}\n.gchat-new-btn:hover { background: var(--gchat-accent-h); }\n\n.gchat-history {\n  flex: 1;\n  overflow-y: auto;\n  padding: 8px;\n}\n\n.gchat-history-empty {\n  padding: 16px;\n  font-size: 0.8rem;\n  color: var(--gchat-text-2);\n  text-align: center;\n}\n\n.gchat-history-item {\n  display: flex;\n  align-items: center;\n  gap: 4px;\n  padding: 8px 10px;\n  border-radius: var(--gchat-radius-sm);\n  cursor: pointer;\n  transition: background var(--gchat-ease);\n}\n.gchat-history-item:hover { background: var(--gchat-bg-2); }\n.gchat-history-item.active {\n  background: var(--gchat-accent);\n  color: #fff;\n}\n\n.gchat-history-item-title {\n  flex: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  font-size: 0.82rem;\n}\n\n.gchat-history-item-del {\n  background: none;\n  border: none;\n  cursor: pointer;\n  color: inherit;\n  opacity: 0.4;\n  font-size: 0.75rem;\n  padding: 2px 4px;\n  border-radius: 2px;\n  transition: opacity var(--gchat-ease);\n  flex-shrink: 0;\n}\n.gchat-history-item-del:hover { opacity: 1; }\n\n/* ========== Main Area ========== */\n.gchat-main {\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n  background: var(--gchat-bg-0);\n}\n\n/* ========== Top bar ========== */\n.gchat-topbar {\n  padding: 10px 14px;\n  border-bottom: 1px solid var(--gchat-border);\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  flex-shrink: 0;\n}\n\n.gchat-mobile-toggle {\n  display: none;\n  background: none;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  padding: 5px 8px;\n  cursor: pointer;\n  color: var(--gchat-text-0);\n  font-size: 0.85rem;\n}\n\n.gchat-provider-select {\n  padding: 5px 8px;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  background: var(--gchat-bg-0);\n  color: var(--gchat-text-0);\n  font-size: 0.82rem;\n  cursor: pointer;\n}\n\n.gchat-topbar-spacer { flex: 1; }\n\n.gchat-provider-badge {\n  font-size: 0.75rem;\n  font-weight: 600;\n  color: var(--gchat-accent);\n  white-space: nowrap;\n}\n\n/* System prompt toggle */\n.gchat-sys-toggle {\n  background: none;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  padding: 4px 8px;\n  font-size: 0.75rem;\n  cursor: pointer;\n  color: var(--gchat-text-2);\n  transition: all var(--gchat-ease);\n}\n.gchat-sys-toggle:hover { color: var(--gchat-text-0); border-color: var(--gchat-accent); }\n\n/* System prompt panel */\n.gchat-sysprompt-panel {\n  padding: 8px 14px;\n  border-bottom: 1px solid var(--gchat-border);\n  background: var(--gchat-bg-1);\n}\n.gchat-sysprompt-panel.hidden { display: none; }\n\n.gchat-sysprompt-input {\n  width: 100%;\n  padding: 7px 10px;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  background: var(--gchat-bg-0);\n  color: var(--gchat-text-0);\n  font-family: var(--gchat-font);\n  font-size: 0.82rem;\n  resize: vertical;\n  min-height: 60px;\n}\n.gchat-sysprompt-input:focus {\n  outline: none;\n  border-color: var(--gchat-accent);\n}\n\n/* ========== Messages ========== */\n.gchat-messages {\n  flex: 1;\n  overflow-y: auto;\n  padding: 16px 14px;\n  scroll-behavior: smooth;\n}\n\n/* Welcome screen */\n.gchat-welcome {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n  padding: 40px 24px;\n  height: 100%;\n  min-height: 200px;\n}\n\n.gchat-welcome h2 {\n  font-size: 1.5rem;\n  font-weight: 700;\n  margin-bottom: 8px;\n}\n\n.gchat-welcome p {\n  color: var(--gchat-text-2);\n  margin-bottom: 20px;\n  font-size: 0.9rem;\n}\n\n.gchat-hints {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 8px;\n  justify-content: center;\n}\n\n.gchat-hint-chip {\n  padding: 7px 14px;\n  border: 1px solid var(--gchat-border);\n  border-radius: 20px;\n  background: var(--gchat-bg-1);\n  color: var(--gchat-text-1);\n  font-size: 0.82rem;\n  cursor: pointer;\n  transition: all var(--gchat-ease);\n}\n.gchat-hint-chip:hover {\n  border-color: var(--gchat-accent);\n  color: var(--gchat-accent);\n  background: var(--gchat-bg-0);\n}\n\n/* Message bubbles */\n.gchat-msg {\n  margin-bottom: 16px;\n  max-width: 100%;\n}\n\n.gchat-msg-header {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 4px;\n}\n\n.gchat-msg-role {\n  font-size: 0.75rem;\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  color: var(--gchat-text-2);\n}\n\n.gchat-msg-actions {\n  display: flex;\n  gap: 4px;\n  margin-left: auto;\n  opacity: 0;\n  transition: opacity var(--gchat-ease);\n}\n.gchat-msg:hover .gchat-msg-actions { opacity: 1; }\n\n.gchat-msg-action-btn {\n  background: none;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  padding: 2px 7px;\n  font-size: 0.72rem;\n  cursor: pointer;\n  color: var(--gchat-text-2);\n  transition: all var(--gchat-ease);\n}\n.gchat-msg-action-btn:hover { color: var(--gchat-text-0); border-color: var(--gchat-accent); }\n\n.gchat-msg-body {\n  line-height: 1.65;\n  word-break: break-word;\n}\n\n.gchat-msg.user .gchat-msg-body {\n  white-space: pre-wrap;\n}\n\n/* Loading animation */\n.gchat-msg.loading .gchat-msg-body::after {\n  content: '▋';\n  display: inline-block;\n  animation: gchat-blink 1s step-end infinite;\n  color: var(--gchat-accent);\n  margin-left: 2px;\n}\n\n@keyframes gchat-blink {\n  0%, 100% { opacity: 1; }\n  50% { opacity: 0; }\n}\n\n/* Error message */\n.gchat-msg.error .gchat-msg-body {\n  color: var(--gchat-error);\n  font-style: italic;\n}\n\n/* Markdown content */\n.gchat-msg-body p { margin-bottom: 0.75em; }\n.gchat-msg-body p:last-child { margin-bottom: 0; }\n.gchat-msg-body ul, .gchat-msg-body ol { padding-left: 1.4em; margin-bottom: 0.75em; }\n.gchat-msg-body li { margin-bottom: 0.25em; }\n.gchat-msg-body h1, .gchat-msg-body h2, .gchat-msg-body h3 {\n  margin: 1em 0 0.4em;\n  font-weight: 700;\n}\n.gchat-msg-body h1 { font-size: 1.2em; }\n.gchat-msg-body h2 { font-size: 1.1em; }\n.gchat-msg-body h3 { font-size: 1em; }\n.gchat-msg-body code {\n  font-family: var(--gchat-mono);\n  font-size: 0.88em;\n  background: var(--gchat-bg-2);\n  padding: 0.15em 0.35em;\n  border-radius: 3px;\n}\n.gchat-msg-body pre {\n  background: var(--gchat-bg-2);\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius-sm);\n  padding: 12px 14px;\n  overflow-x: auto;\n  margin-bottom: 0.75em;\n  position: relative;\n}\n.gchat-msg-body pre code {\n  background: none;\n  padding: 0;\n  font-size: 0.85em;\n}\n.gchat-msg-body blockquote {\n  border-left: 3px solid var(--gchat-accent);\n  padding-left: 12px;\n  color: var(--gchat-text-2);\n  margin: 0.5em 0;\n}\n.gchat-msg-body a { color: var(--gchat-accent); text-decoration: underline; }\n.gchat-msg-body table { border-collapse: collapse; margin-bottom: 0.75em; width: 100%; }\n.gchat-msg-body th, .gchat-msg-body td {\n  border: 1px solid var(--gchat-border);\n  padding: 6px 10px;\n  font-size: 0.85em;\n}\n.gchat-msg-body th { background: var(--gchat-bg-1); font-weight: 600; }\n\n/* Code block copy button */\n.gchat-code-copy {\n  position: absolute;\n  top: 6px;\n  right: 8px;\n  padding: 2px 7px;\n  font-size: 0.72rem;\n  background: var(--gchat-bg-1);\n  border: 1px solid var(--gchat-border);\n  border-radius: 3px;\n  cursor: pointer;\n  color: var(--gchat-text-2);\n  transition: all var(--gchat-ease);\n  opacity: 0;\n}\n.gchat-msg-body pre:hover .gchat-code-copy { opacity: 1; }\n.gchat-code-copy:hover { color: var(--gchat-text-0); }\n\n/* ========== Input Bar ========== */\n.gchat-input-bar {\n  padding: 12px 14px;\n  border-top: 1px solid var(--gchat-border);\n  background: var(--gchat-bg-0);\n  flex-shrink: 0;\n}\n\n.gchat-input-row {\n  display: flex;\n  gap: 8px;\n  align-items: flex-end;\n}\n\n.gchat-textarea {\n  flex: 1;\n  padding: 9px 12px;\n  border: 1px solid var(--gchat-border);\n  border-radius: var(--gchat-radius);\n  background: var(--gchat-bg-1);\n  color: var(--gchat-text-0);\n  font-family: var(--gchat-font);\n  font-size: 0.9rem;\n  line-height: 1.5;\n  resize: none;\n  min-height: 44px;\n  max-height: 200px;\n  overflow-y: auto;\n  transition: border-color var(--gchat-ease);\n}\n.gchat-textarea:focus {\n  outline: none;\n  border-color: var(--gchat-accent);\n}\n.gchat-textarea::placeholder { color: var(--gchat-text-2); }\n\n.gchat-send-btn,\n.gchat-stop-btn {\n  padding: 9px 16px;\n  border: none;\n  border-radius: var(--gchat-radius);\n  font-size: 0.88rem;\n  font-weight: 600;\n  cursor: pointer;\n  transition: all var(--gchat-ease);\n  white-space: nowrap;\n  flex-shrink: 0;\n  height: 44px;\n}\n\n.gchat-send-btn {\n  background: var(--gchat-accent);\n  color: #fff;\n}\n.gchat-send-btn:hover:not(:disabled) { background: var(--gchat-accent-h); }\n.gchat-send-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n\n.gchat-stop-btn {\n  background: var(--gchat-bg-2);\n  color: var(--gchat-text-0);\n  border: 1px solid var(--gchat-border);\n}\n.gchat-stop-btn:hover { background: var(--gchat-error); color: #fff; border-color: var(--gchat-error); }\n.gchat-stop-btn.hidden { display: none; }\n\n/* ========== Sidebar overlay (mobile) ========== */\n.gchat-overlay {\n  display: none;\n  position: absolute;\n  inset: 0;\n  background: rgba(0,0,0,0.4);\n  z-index: 10;\n}\n.gchat-overlay.visible { display: block; }\n\n/* ========== Toast ========== */\n.gchat-toast {\n  position: absolute;\n  bottom: 20px;\n  left: 50%;\n  transform: translateX(-50%) translateY(10px);\n  background: var(--gchat-text-0);\n  color: var(--gchat-bg-0);\n  padding: 8px 16px;\n  border-radius: var(--gchat-radius);\n  font-size: 0.82rem;\n  font-weight: 600;\n  white-space: nowrap;\n  pointer-events: none;\n  opacity: 0;\n  transition: opacity 200ms, transform 200ms;\n  z-index: 100;\n}\n.gchat-toast.show {\n  opacity: 1;\n  transform: translateX(-50%) translateY(0);\n}\n\n/* ========== Mobile ========== */\n@media (max-width: 640px) {\n  .gchat-sidebar {\n    position: absolute;\n    top: 0;\n    left: 0;\n    height: 100%;\n    z-index: 20;\n    transform: translateX(-100%);\n    transition: transform 200ms ease;\n  }\n  .gchat-sidebar.open {\n    transform: translateX(0);\n  }\n  .gchat-mobile-toggle { display: block; }\n}\n`;\n","/**\n * ChatUI — DOM renderer for @geepers/chat\n *\n * Mounts a full chat interface into any container element.\n * Drives ChatCore for all state; pure DOM updates on events.\n *\n * Usage:\n *   const chat = new ChatUI('#chat-container', { provider: 'xai' });\n *   // or: new ChatUI(document.getElementById('chat'), config);\n */\n\nimport { ChatCore } from '../core/ChatCore.js';\nimport type {\n  ChatConfig,\n  ErrorEvent,\n  Message,\n  MessageEvent as ChatMessageEvent,\n  Provider,\n  StreamChunkEvent,\n  StreamEndEvent,\n  StreamStartEvent,\n  WelcomeHint,\n} from '../types/index.js';\nimport { MODELS, PROVIDER_KEYS } from '../core/providers.js';\nimport { CHAT_CSS } from './styles.js';\n\n// ========== Default hints ==========\n\nconst DEFAULT_HINTS: WelcomeHint[] = [\n  { label: 'How do LLMs work?', prompt: 'Explain how large language models work in plain language.' },\n  { label: 'Write a function', prompt: 'Write a Python function that finds all prime numbers up to N using the Sieve of Eratosthenes.' },\n  { label: 'REST vs GraphQL', prompt: 'Compare REST and GraphQL APIs — when should I use each?' },\n];\n\n// ========== Helpers ==========\n\nfunction escHtml(s: string): string {\n  return String(s ?? '')\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;');\n}\n\nfunction resolveTarget(target: string | HTMLElement): HTMLElement {\n  if (typeof target === 'string') {\n    const el = document.querySelector<HTMLElement>(target);\n    if (!el) throw new Error(`[@geepers/chat] Target not found: \"${target}\"`);\n    return el;\n  }\n  return target;\n}\n\nfunction renderMarkdown(text: string): string {\n  // Use window.marked if available (loaded by host page)\n  const w = globalThis as Record<string, unknown>;\n  if (w['marked'] && typeof (w['marked'] as Record<string, unknown>)['parse'] === 'function') {\n    return ((w['marked'] as Record<string, unknown>)['parse'] as (s: string) => string)(text);\n  }\n  // Minimal fallback\n  return escHtml(text).replace(/\\n/g, '<br>');\n}\n\n// ========== ChatUI ==========\n\nexport class ChatUI {\n  private core: ChatCore;\n  private container: HTMLElement;\n  private config: ChatConfig & { welcomeHints: WelcomeHint[] };\n\n  // DOM refs\n  private root!: HTMLElement;\n  private sidebar!: HTMLElement;\n  private historyEl!: HTMLElement;\n  private messagesEl!: HTMLElement;\n  private textarea!: HTMLTextAreaElement;\n  private sendBtn!: HTMLButtonElement;\n  private stopBtn!: HTMLButtonElement;\n  private providerSelect!: HTMLSelectElement;\n  private providerBadge!: HTMLElement;\n  private syspromptPanel!: HTMLElement;\n  private syspromptInput!: HTMLTextAreaElement;\n  private overlayEl!: HTMLElement;\n  private toastEl!: HTMLElement;\n  private welcomeEl: HTMLElement | null = null;\n\n  private toastTimer: ReturnType<typeof setTimeout> | null = null;\n\n  constructor(target: string | HTMLElement, config: ChatConfig = {}) {\n    this.container = resolveTarget(target);\n    this.config = {\n      ...config,\n      welcomeHints: config.welcomeHints ?? DEFAULT_HINTS,\n    };\n\n    ChatUI.injectStyles();\n    this.core = new ChatCore(config);\n    this.buildDOM();\n    this.wireEvents();\n    this.renderHistory();\n    this.showWelcome();\n\n    if (this.core.messages.length > 0) {\n      this.reRenderMessages();\n    }\n  }\n\n  // ========== Public API ==========\n\n  get chatCore(): ChatCore { return this.core; }\n\n  send(text: string): Promise<void> { return this.core.send(text); }\n  stop(): void { this.core.stop(); }\n  focus(): void { this.textarea?.focus(); }\n\n  setProvider(provider: Provider): void {\n    this.core.setProvider(provider);\n    this.providerSelect.value = provider;\n    this.providerBadge.textContent = MODELS[provider]?.label ?? provider;\n  }\n\n  setSystemPrompt(prompt: string): void {\n    this.core.setSystemPrompt(prompt);\n    this.syspromptInput.value = prompt;\n  }\n\n  newConversation(): void {\n    this.core.clearHistory();\n    this.messagesEl.innerHTML = '';\n    this.welcomeEl = null;\n    this.showWelcome();\n    this.renderHistory();\n  }\n\n  destroy(): void {\n    this.container.innerHTML = '';\n  }\n\n  // ========== Style injection ==========\n\n  private static stylesInjected = false;\n\n  private static injectStyles(): void {\n    if (ChatUI.stylesInjected || typeof document === 'undefined') return;\n    const style = document.createElement('style');\n    style.setAttribute('data-gchat', '');\n    // CSS_RAW may be undefined if bundler doesn't support ?inline — that's OK\n    style.textContent = CHAT_CSS;\n    document.head.appendChild(style);\n    ChatUI.stylesInjected = true;\n  }\n\n  // ========== DOM Construction ==========\n\n  private buildDOM(): void {\n    const theme = this.resolveTheme();\n\n    this.root = document.createElement('div');\n    this.root.className = 'gchat-root';\n    this.root.dataset['theme'] = theme;\n    this.root.style.cssText = 'width:100%;height:100%;';\n\n    // ---- Sidebar ----\n    this.sidebar = document.createElement('aside');\n    this.sidebar.className = 'gchat-sidebar';\n\n    const sidebarHeader = document.createElement('div');\n    sidebarHeader.className = 'gchat-sidebar-header';\n    const sidebarTitle = document.createElement('span');\n    sidebarTitle.className = 'gchat-sidebar-title';\n    sidebarTitle.textContent = 'History';\n    const newBtn = document.createElement('button');\n    newBtn.className = 'gchat-new-btn';\n    newBtn.type = 'button';\n    newBtn.textContent = 'New';\n    newBtn.addEventListener('click', () => this.newConversation());\n    sidebarHeader.appendChild(sidebarTitle);\n    sidebarHeader.appendChild(newBtn);\n    this.sidebar.appendChild(sidebarHeader);\n\n    this.historyEl = document.createElement('div');\n    this.historyEl.className = 'gchat-history';\n    this.sidebar.appendChild(this.historyEl);\n\n    // ---- Main ----\n    const main = document.createElement('div');\n    main.className = 'gchat-main';\n\n    // Top bar\n    const topbar = document.createElement('div');\n    topbar.className = 'gchat-topbar';\n\n    const mobileToggle = document.createElement('button');\n    mobileToggle.className = 'gchat-mobile-toggle';\n    mobileToggle.type = 'button';\n    mobileToggle.textContent = '☰';\n    mobileToggle.setAttribute('aria-label', 'Toggle history');\n    mobileToggle.addEventListener('click', () => this.toggleSidebar());\n    topbar.appendChild(mobileToggle);\n\n    this.providerSelect = document.createElement('select');\n    this.providerSelect.className = 'gchat-provider-select';\n    this.providerSelect.setAttribute('aria-label', 'Select model provider');\n    PROVIDER_KEYS.forEach(key => {\n      const opt = document.createElement('option');\n      opt.value = key;\n      opt.textContent = MODELS[key].label;\n      if (key === this.core.provider) opt.selected = true;\n      this.providerSelect.appendChild(opt);\n    });\n    this.providerSelect.addEventListener('change', () => {\n      this.core.setProvider(this.providerSelect.value as Provider);\n      this.providerBadge.textContent = MODELS[this.core.provider].label;\n    });\n    topbar.appendChild(this.providerSelect);\n\n    const spacer = document.createElement('span');\n    spacer.className = 'gchat-topbar-spacer';\n    topbar.appendChild(spacer);\n\n    this.providerBadge = document.createElement('span');\n    this.providerBadge.className = 'gchat-provider-badge';\n    this.providerBadge.textContent = MODELS[this.core.provider].label;\n    topbar.appendChild(this.providerBadge);\n\n    const sysToggle = document.createElement('button');\n    sysToggle.className = 'gchat-sys-toggle';\n    sysToggle.type = 'button';\n    sysToggle.textContent = 'System';\n    sysToggle.setAttribute('aria-label', 'Toggle system prompt');\n    sysToggle.addEventListener('click', () => {\n      this.syspromptPanel.classList.toggle('hidden');\n    });\n    topbar.appendChild(sysToggle);\n\n    main.appendChild(topbar);\n\n    // System prompt panel\n    this.syspromptPanel = document.createElement('div');\n    this.syspromptPanel.className = 'gchat-sysprompt-panel hidden';\n    this.syspromptInput = document.createElement('textarea');\n    this.syspromptInput.className = 'gchat-sysprompt-input';\n    this.syspromptInput.placeholder = 'System prompt (optional)…';\n    this.syspromptInput.value = this.core.systemPrompt;\n    this.syspromptInput.rows = 3;\n    this.syspromptInput.setAttribute('aria-label', 'System prompt');\n    this.syspromptInput.addEventListener('input', () => {\n      this.core.setSystemPrompt(this.syspromptInput.value);\n    });\n    this.syspromptPanel.appendChild(this.syspromptInput);\n    main.appendChild(this.syspromptPanel);\n\n    // Messages area\n    this.messagesEl = document.createElement('div');\n    this.messagesEl.className = 'gchat-messages';\n    this.messagesEl.setAttribute('role', 'log');\n    this.messagesEl.setAttribute('aria-live', 'polite');\n    this.messagesEl.setAttribute('aria-label', 'Chat messages');\n    main.appendChild(this.messagesEl);\n\n    // Input bar\n    const inputBar = document.createElement('div');\n    inputBar.className = 'gchat-input-bar';\n    const inputRow = document.createElement('div');\n    inputRow.className = 'gchat-input-row';\n\n    this.textarea = document.createElement('textarea');\n    this.textarea.className = 'gchat-textarea';\n    this.textarea.placeholder = 'Message… (Enter to send, Shift+Enter for newline)';\n    this.textarea.rows = 1;\n    this.textarea.setAttribute('aria-label', 'Chat message');\n    this.textarea.addEventListener('input', () => this.autoResize());\n    this.textarea.addEventListener('keydown', e => {\n      if (e.key === 'Enter' && !e.shiftKey) {\n        e.preventDefault();\n        void this.submitMessage();\n      }\n    });\n    inputRow.appendChild(this.textarea);\n\n    this.sendBtn = document.createElement('button');\n    this.sendBtn.className = 'gchat-send-btn';\n    this.sendBtn.type = 'button';\n    this.sendBtn.textContent = 'Send';\n    this.sendBtn.addEventListener('click', () => void this.submitMessage());\n    inputRow.appendChild(this.sendBtn);\n\n    this.stopBtn = document.createElement('button');\n    this.stopBtn.className = 'gchat-stop-btn hidden';\n    this.stopBtn.type = 'button';\n    this.stopBtn.textContent = 'Stop';\n    this.stopBtn.addEventListener('click', () => this.core.stop());\n    inputRow.appendChild(this.stopBtn);\n\n    inputBar.appendChild(inputRow);\n    main.appendChild(inputBar);\n\n    // Overlay\n    this.overlayEl = document.createElement('div');\n    this.overlayEl.className = 'gchat-overlay';\n    this.overlayEl.setAttribute('aria-hidden', 'true');\n    this.overlayEl.addEventListener('click', () => this.toggleSidebar());\n\n    // Toast\n    this.toastEl = document.createElement('div');\n    this.toastEl.className = 'gchat-toast';\n    this.toastEl.setAttribute('role', 'status');\n    this.toastEl.setAttribute('aria-live', 'polite');\n\n    this.root.appendChild(this.sidebar);\n    this.root.appendChild(main);\n    this.root.appendChild(this.overlayEl);\n    this.root.appendChild(this.toastEl);\n    this.container.appendChild(this.root);\n  }\n\n  // ========== Event wiring ==========\n\n  private wireEvents(): void {\n    this.core.on<ChatMessageEvent>('message', e => {\n      if (e.message.role === 'user') {\n        this.removeWelcome();\n        this.appendMessage(e.message);\n      }\n    });\n\n    this.core.on<StreamStartEvent>('stream-start', e => {\n      this.sendBtn.disabled = true;\n      this.stopBtn.classList.remove('hidden');\n      this.appendLoadingMessage(e.messageId);\n    });\n\n    this.core.on<StreamChunkEvent>('stream-chunk', e => {\n      this.updateStreamingMessage(e.messageId, e.accumulated);\n    });\n\n    this.core.on<StreamEndEvent>('stream-end', e => {\n      this.sendBtn.disabled = false;\n      this.stopBtn.classList.add('hidden');\n      this.finalizeMessage(e.message);\n      this.renderHistory();\n    });\n\n    this.core.on<ErrorEvent>('error', e => {\n      this.sendBtn.disabled = false;\n      this.stopBtn.classList.add('hidden');\n      this.showErrorMessage(e.error.message);\n    });\n\n    this.core.on('conversation-change', () => {\n      this.messagesEl.innerHTML = '';\n      this.welcomeEl = null;\n      this.showWelcome();\n      this.renderHistory();\n    });\n  }\n\n  // ========== Message rendering ==========\n\n  private appendMessage(msg: Message): HTMLElement {\n    const el = document.createElement('div');\n    el.className = `gchat-msg ${msg.role}`;\n    el.dataset['msgId'] = msg.id;\n\n    const header = document.createElement('div');\n    header.className = 'gchat-msg-header';\n\n    const roleSpan = document.createElement('span');\n    roleSpan.className = 'gchat-msg-role';\n    roleSpan.textContent = msg.role === 'user'\n      ? 'You'\n      : (MODELS[msg.provider ?? this.core.provider]?.label ?? 'Assistant');\n    header.appendChild(roleSpan);\n\n    const actions = document.createElement('div');\n    actions.className = 'gchat-msg-actions';\n    const copyBtn = this.makeCopyBtn(() => msg.content);\n    actions.appendChild(copyBtn);\n    header.appendChild(actions);\n\n    const body = document.createElement('div');\n    body.className = 'gchat-msg-body';\n    if (msg.role === 'user') {\n      body.textContent = msg.content;\n    } else {\n      body.innerHTML = renderMarkdown(msg.content);\n      this.addCodeCopyButtons(body);\n    }\n\n    el.appendChild(header);\n    el.appendChild(body);\n    this.messagesEl.appendChild(el);\n    this.scrollToBottom();\n    return el;\n  }\n\n  private appendLoadingMessage(messageId: string): void {\n    const el = document.createElement('div');\n    el.className = 'gchat-msg assistant loading';\n    el.dataset['msgId'] = messageId;\n\n    const header = document.createElement('div');\n    header.className = 'gchat-msg-header';\n    const roleSpan = document.createElement('span');\n    roleSpan.className = 'gchat-msg-role';\n    roleSpan.textContent = MODELS[this.core.provider]?.label ?? 'Assistant';\n    header.appendChild(roleSpan);\n    el.appendChild(header);\n\n    const body = document.createElement('div');\n    body.className = 'gchat-msg-body';\n    el.appendChild(body);\n\n    this.messagesEl.appendChild(el);\n    this.scrollToBottom();\n  }\n\n  private updateStreamingMessage(messageId: string, content: string): void {\n    const el = this.messagesEl.querySelector<HTMLElement>(`[data-msg-id=\"${messageId}\"]`);\n    if (!el) return;\n    el.classList.remove('loading');\n    const body = el.querySelector<HTMLElement>('.gchat-msg-body');\n    if (!body) return;\n    body.innerHTML = renderMarkdown(content);\n    this.addCodeCopyButtons(body);\n    this.scrollToBottom();\n  }\n\n  private finalizeMessage(msg: Message): void {\n    const el = this.messagesEl.querySelector<HTMLElement>(`[data-msg-id=\"${msg.id}\"]`);\n    if (!el) return;\n    el.classList.remove('loading');\n\n    // Ensure copy button exists in header\n    let actions = el.querySelector<HTMLElement>('.gchat-msg-actions');\n    if (!actions) {\n      actions = document.createElement('div');\n      actions.className = 'gchat-msg-actions';\n      el.querySelector('.gchat-msg-header')?.appendChild(actions);\n    }\n    if (!actions.querySelector('.gchat-msg-action-btn')) {\n      actions.appendChild(this.makeCopyBtn(() => msg.content));\n    }\n\n    const body = el.querySelector<HTMLElement>('.gchat-msg-body');\n    if (body) {\n      body.innerHTML = renderMarkdown(msg.content);\n      this.addCodeCopyButtons(body);\n    }\n    this.scrollToBottom();\n  }\n\n  private showErrorMessage(message: string): void {\n    // Update loading bubble if present, otherwise append\n    const loading = this.messagesEl.querySelector<HTMLElement>('.gchat-msg.loading');\n    const el = loading ?? document.createElement('div');\n    el.classList.remove('loading');\n    el.classList.add('gchat-msg', 'assistant', 'error');\n    const body = el.querySelector<HTMLElement>('.gchat-msg-body') ?? (() => {\n      const b = document.createElement('div');\n      b.className = 'gchat-msg-body';\n      el.appendChild(b);\n      return b;\n    })();\n    body.textContent = `Error: ${message}`;\n    if (!loading) this.messagesEl.appendChild(el);\n    this.scrollToBottom();\n    this.toast('Error sending message');\n  }\n\n  private reRenderMessages(): void {\n    this.messagesEl.innerHTML = '';\n    this.welcomeEl = null;\n    for (const msg of this.core.messages) {\n      this.appendMessage(msg);\n    }\n  }\n\n  // ========== Welcome ==========\n\n  private showWelcome(): void {\n    if (this.welcomeEl || this.core.messages.length > 0) return;\n\n    const el = document.createElement('div');\n    el.className = 'gchat-welcome';\n\n    const h2 = document.createElement('h2');\n    h2.textContent = 'Chat';\n    el.appendChild(h2);\n\n    const p = document.createElement('p');\n    p.textContent = 'Pick a model and start a conversation.';\n    el.appendChild(p);\n\n    const hints = this.config.welcomeHints ?? [];\n    if (hints.length > 0) {\n      const hintRow = document.createElement('div');\n      hintRow.className = 'gchat-hints';\n      hints.forEach(h => {\n        const chip = document.createElement('button');\n        chip.className = 'gchat-hint-chip';\n        chip.type = 'button';\n        chip.textContent = h.label;\n        chip.addEventListener('click', () => {\n          this.textarea.value = h.prompt;\n          void this.submitMessage();\n        });\n        hintRow.appendChild(chip);\n      });\n      el.appendChild(hintRow);\n    }\n\n    this.messagesEl.appendChild(el);\n    this.welcomeEl = el;\n  }\n\n  private removeWelcome(): void {\n    if (this.welcomeEl) {\n      this.welcomeEl.remove();\n      this.welcomeEl = null;\n    }\n  }\n\n  // ========== History sidebar ==========\n\n  private renderHistory(): void {\n    const convos = this.core.getConversations();\n    this.historyEl.innerHTML = '';\n\n    if (convos.length === 0) {\n      const empty = document.createElement('p');\n      empty.className = 'gchat-history-empty';\n      empty.textContent = 'No saved conversations';\n      this.historyEl.appendChild(empty);\n      return;\n    }\n\n    convos.forEach(convo => {\n      const item = document.createElement('div');\n      item.className = 'gchat-history-item' + (convo.id === this.core.conversationId ? ' active' : '');\n\n      const title = document.createElement('span');\n      title.className = 'gchat-history-item-title';\n      title.textContent = convo.title;\n      title.title = convo.title;\n      title.addEventListener('click', () => {\n        if (this.core.loadConversation(convo.id)) {\n          this.reRenderMessages();\n          this.renderHistory();\n          this.closeSidebar();\n          this.providerSelect.value = this.core.provider;\n          this.providerBadge.textContent = MODELS[this.core.provider].label;\n          this.syspromptInput.value = this.core.systemPrompt;\n        }\n      });\n\n      const del = document.createElement('button');\n      del.className = 'gchat-history-item-del';\n      del.textContent = '×';\n      del.setAttribute('aria-label', `Delete \"${convo.title}\"`);\n      del.addEventListener('click', e => {\n        e.stopPropagation();\n        this.core.deleteConversation(convo.id);\n        this.renderHistory();\n      });\n\n      item.appendChild(title);\n      item.appendChild(del);\n      this.historyEl.appendChild(item);\n    });\n  }\n\n  // ========== Code copy buttons ==========\n\n  private addCodeCopyButtons(container: HTMLElement): void {\n    container.querySelectorAll<HTMLPreElement>('pre').forEach(pre => {\n      if (pre.querySelector('.gchat-code-copy')) return;\n      const btn = document.createElement('button');\n      btn.className = 'gchat-code-copy';\n      btn.type = 'button';\n      btn.textContent = 'Copy';\n      btn.addEventListener('click', () => {\n        const code = pre.querySelector('code')?.textContent ?? pre.textContent ?? '';\n        navigator.clipboard.writeText(code).then(() => {\n          btn.textContent = 'Copied';\n          setTimeout(() => { btn.textContent = 'Copy'; }, 1500);\n        });\n      });\n      pre.style.position = 'relative';\n      pre.appendChild(btn);\n    });\n  }\n\n  // ========== Submit ==========\n\n  private async submitMessage(): Promise<void> {\n    const text = this.textarea.value.trim();\n    if (!text || this.core.isStreaming) return;\n    this.textarea.value = '';\n    this.textarea.style.height = 'auto';\n    await this.core.send(text);\n  }\n\n  // ========== Helpers ==========\n\n  private makeCopyBtn(getContent: () => string): HTMLButtonElement {\n    const btn = document.createElement('button');\n    btn.className = 'gchat-msg-action-btn';\n    btn.type = 'button';\n    btn.textContent = 'Copy';\n    btn.addEventListener('click', () => {\n      navigator.clipboard.writeText(getContent()).then(() => this.toast('Copied'));\n    });\n    return btn;\n  }\n\n  private autoResize(): void {\n    this.textarea.style.height = 'auto';\n    this.textarea.style.height = Math.min(this.textarea.scrollHeight, 200) + 'px';\n  }\n\n  private scrollToBottom(): void {\n    this.messagesEl.scrollTop = this.messagesEl.scrollHeight;\n  }\n\n  private toggleSidebar(): void {\n    const open = this.sidebar.classList.toggle('open');\n    this.overlayEl.classList.toggle('visible', open);\n    this.overlayEl.setAttribute('aria-hidden', open ? 'false' : 'true');\n  }\n\n  private closeSidebar(): void {\n    this.sidebar.classList.remove('open');\n    this.overlayEl.classList.remove('visible');\n    this.overlayEl.setAttribute('aria-hidden', 'true');\n  }\n\n  private toast(message: string): void {\n    this.toastEl.textContent = message;\n    this.toastEl.classList.add('show');\n    if (this.toastTimer) clearTimeout(this.toastTimer);\n    this.toastTimer = setTimeout(() => this.toastEl.classList.remove('show'), 2500);\n  }\n\n  private resolveTheme(): string {\n    const t = this.config.theme ?? 'auto';\n    if (t === 'auto') {\n      try {\n        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n      } catch {\n        return 'light';\n      }\n    }\n    return t;\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqDA,SAAS,eAAe,QAAyC;AAE/D,MAAI,OAAO,OAAO,YAAY,SAAU,QAAO,OAAO;AAGtD,QAAM,UAAU,OAAO;AACvB,MAAI,UAAU,CAAC,GAAG;AAChB,UAAMA,SAAQ,QAAQ,CAAC,EAAE;AACzB,QAAIA,QAAO,QAAS,QAAOA,OAAM;AAAA,EACnC;AAGA,QAAM,UAAU,OAAO;AACvB,MAAI,SAAS,QAAS,QAAO,QAAQ;AAErC,QAAM,eAAe,OAAO;AAC5B,MAAI,cAAc,KAAM,QAAO,aAAa;AAG5C,QAAM,QAAQ,OAAO;AACrB,MAAI,OAAO,KAAM,QAAO,MAAM;AAE9B,SAAO;AACT;AAEO,IAAM,UAAN,MAAc;AAAA,EAKnB,YAAY,SAAyB;AACnC,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ,WAAW,CAAC;AAAA,EACrC;AAAA;AAAA,EAGA,UAAU,KAAmB;AAC3B,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,SAAuC;AAChD,UAAM,EAAE,UAAU,OAAO,UAAU,SAAS,QAAQ,SAAS,QAAQ,YAAY,IAAI;AAErF,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,GAAG,KAAK;AAAA,IACV;AAEA,QAAI,KAAK,QAAQ;AACf,cAAQ,WAAW,IAAI,KAAK;AAAA,IAC9B;AAEA,QAAI,cAAc;AAElB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,QAAQ;AAAA,QACxC,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR,GAAG;AAAA,QACL,CAAC;AAAA,QACD;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,QAAQ,IAAI;AAAA,UAChB,SAAS,WAAW,MAAM,oBAC1B,SAAS,WAAW,MAAM,wBAC1B,QAAQ,SAAS,MAAM,KAAK,SAAS;AAAA,QACvC;AACA,kBAAU,KAAK;AACf,cAAM;AAAA,MACR;AAEA,YAAM,SAAS,SAAS,KAAM,UAAU;AACxC,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AAEb,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,KAAM;AAEV,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,WAAW,QAAQ,EAAG;AAEtD,gBAAM,OAAO,KAAK,MAAM,CAAC;AACzB,cAAI,SAAS,SAAU;AAEvB,cAAI;AACF,kBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,kBAAM,QAAQ,eAAe,MAAM;AAEnC,gBAAI,OAAO;AACT,6BAAe;AACf,wBAAU,OAAO,WAAW;AAAA,YAC9B;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAEA,eAAS,WAAW;AACpB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,iBAAS,WAAW;AACpB,eAAO;AAAA,MACT;AACA,YAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,gBAAU,GAAG;AACb,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC7KO,IAAM,SAA2C;AAAA,EACtD,KAAK;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AACF;AAGO,IAAM,gBAA4B,OAAO,KAAK,MAAM;AAMpD,SAAS,gBAAgB,OAAkC;AAChE,QAAM,QAAQ,cAAc,SAAS,KAAiB;AACtD,MAAI,CAAC,OAAO;AACV,YAAQ,KAAK,sCAAsC,KAAK,uBAAuB,cAAc,KAAK,IAAI,CAAC,EAAE;AAAA,EAC3G;AACA,SAAO;AACT;AAKO,SAAS,kBAAkB,UAAkC;AAClE,MAAI,gBAAgB,QAAQ,GAAG;AAC7B,WAAO,OAAO,QAAQ;AAAA,EACxB;AACA,SAAO,OAAO;AAChB;;;AChEA,IAAM,cAAc;AACpB,IAAM,aAAa;AAEZ,IAAM,sBAAN,MAA0B;AAAA,EAG/B,YAAY,aAAa,aAAa;AACpC,SAAK,MAAM;AAAA,EACb;AAAA,EAEQ,OAA2C;AACjD,QAAI;AACF,aAAO,KAAK,MAAM,aAAa,QAAQ,KAAK,GAAG,KAAK,IAAI;AAAA,IAC1D,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,MAAM,MAAgD;AAC5D,QAAI;AACF,mBAAa,QAAQ,KAAK,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,IACrD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAA4B;AAC1B,UAAM,OAAO,KAAK,KAAK;AACvB,WAAO,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAAA,EACrE;AAAA,EAEA,IAAI,IAA4C;AAC9C,WAAO,KAAK,KAAK,EAAE,EAAE;AAAA,EACvB;AAAA,EAEA,KAAK,QAAkC;AACrC,UAAM,OAAO,KAAK,KAAK;AACvB,SAAK,OAAO,EAAE,IAAI;AAGlB,UAAM,SAAS,OAAO,KAAK,IAAI,EAAE;AAAA,MAC/B,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,YAAY,KAAK,CAAC,EAAE;AAAA,IACxC;AACA,QAAI,OAAO,SAAS,YAAY;AAC9B,aAAO,MAAM,UAAU,EAAE,QAAQ,OAAK,OAAO,KAAK,CAAC,CAAC;AAAA,IACtD;AAEA,SAAK,MAAM,IAAI;AAAA,EACjB;AAAA,EAEA,OAAO,IAAkB;AACvB,UAAM,OAAO,KAAK,KAAK;AACvB,WAAO,KAAK,EAAE;AACd,SAAK,MAAM,IAAI;AAAA,EACjB;AAAA;AAAA,EAGA,OAAO,MACL,IACA,UACA,UACA,cACoB;AACpB,UAAM,QAAQ,SAAS,KAAK,OAAK,EAAE,SAAS,MAAM;AAClD,UAAM,QAAQ,QACV,MAAM,QAAQ,MAAM,GAAG,EAAE,KAAK,MAAM,QAAQ,SAAS,KAAK,WAAM,MAChE;AAEJ,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,IACtB;AAAA,EACF;AACF;;;ACzDA,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAI5B,SAAS,aAAqB;AAE5B,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,SAAO,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAC1E;AAEA,SAAS,oBAA4B;AACnC,SAAO,WAAW;AACpB;AAEA,SAAS,MAAc;AACrB,SAAO,KAAK,IAAI;AAClB;AAMA,IAAM,eAAN,MAAmB;AAAA,EAAnB;AACE,SAAQ,WAAuB,oBAAI,IAAI;AAAA;AAAA,EAEvC,GAAwB,MAAqB,SAAoC;AAC/E,QAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GAAG;AAC5B,WAAK,SAAS,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,IACnC;AACA,SAAK,SAAS,IAAI,IAAI,EAAG,IAAI,OAAsC;AAAA,EACrE;AAAA,EAEA,IAAyB,MAAqB,SAAoC;AAChF,SAAK,SAAS,IAAI,IAAI,GAAG,OAAO,OAAsC;AAAA,EACxE;AAAA,EAEA,KAAK,OAAwB;AAC3B,SAAK,SAAS,IAAI,MAAM,IAAI,GAAG,QAAQ,OAAK,EAAE,KAAK,CAAC;AAAA,EACtD;AACF;AAIO,IAAM,WAAN,MAAe;AAAA,EA2BpB,YAAY,SAAqB,CAAC,GAAG;AACnC,SAAK,SAAS;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,GAAG;AAAA,IACL;AAEA,SAAK,UAAU,IAAI,aAAa;AAGhC,UAAM,kBAA6B,OAAO,YAAY,gBAAgB,OAAO,QAAQ,IACjF,OAAO,WACP;AACJ,SAAK,YAAY;AACjB,SAAK,SAAS,OAAO,SAAS,OAAO,eAAe,EAAE;AACtD,SAAK,gBAAgB,OAAO,gBAAgB;AAC5C,SAAK,YAAY,CAAC;AAClB,SAAK,kBAAkB;AACvB,SAAK,eAAe;AACpB,SAAK,mBAAmB;AAGxB,SAAK,YAAY,IAAI,QAAQ;AAAA,MAC3B,QAAQ,GAAG,KAAK,OAAO,OAAO;AAAA,MAC9B,QAAQ,KAAK,eAAe;AAAA,IAC9B,CAAC;AAGD,SAAK,UAAU,IAAI,oBAAoB,KAAK,OAAO,UAAU;AAG7D,QAAI,OAAO,gBAAgB;AACzB,WAAK,iBAAiB,OAAO,cAAc;AAAA,IAC7C,OAAO;AAEL,WAAK,kBAAkB,WAAW;AAAA,IACpC;AAAA,EACF;AAAA;AAAA,EAIA,IAAI,WAAqB;AAAE,WAAO,KAAK;AAAA,EAAW;AAAA,EAClD,IAAI,QAAgB;AAAE,WAAO,KAAK;AAAA,EAAQ;AAAA,EAC1C,IAAI,eAAuB;AAAE,WAAO,KAAK;AAAA,EAAe;AAAA,EACxD,IAAI,WAAgC;AAAE,WAAO,KAAK;AAAA,EAAW;AAAA,EAC7D,IAAI,iBAAgC;AAAE,WAAO,KAAK;AAAA,EAAiB;AAAA,EACnE,IAAI,cAAuB;AAAE,WAAO,KAAK;AAAA,EAAc;AAAA;AAAA,EAIvD,GAAwB,MAAqB,SAAoC;AAC/E,SAAK,QAAQ,GAAG,MAAM,OAAO;AAAA,EAC/B;AAAA,EAEA,IAAyB,MAAqB,SAAoC;AAChF,SAAK,QAAQ,IAAI,MAAM,OAAO;AAAA,EAChC;AAAA;AAAA,EAIA,YAAY,UAAwB;AAClC,QAAI,CAAC,gBAAgB,QAAQ,EAAG;AAChC,SAAK,YAAY;AACjB,SAAK,SAAS,OAAO,QAAQ,EAAE;AAC/B,SAAK,UAAU,UAAU,KAAK,eAAe,CAAC;AAAA,EAChD;AAAA,EAEA,SAAS,OAAqB;AAC5B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,gBAAgB,QAAsB;AACpC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,UAAU,KAAmB;AAC3B,SAAK,UAAU,UAAU,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK,SAAgC;AACzC,QAAI,KAAK,cAAc;AACrB,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AACA,QAAI,CAAC,QAAQ,KAAK,EAAG;AAGrB,UAAM,cAAc,KAAK,YAAY,QAAQ,OAAO;AACpD,SAAK,QAAQ,KAAK,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC;AAG3D,UAAM,cAAc,kBAAkB;AACtC,UAAM,uBAAgC;AAAA,MACpC,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,WAAW,IAAI;AAAA,MACf,UAAU,KAAK;AAAA,IACjB;AACA,SAAK,UAAU,KAAK,oBAAoB;AAExC,SAAK,eAAe;AACpB,SAAK,mBAAmB,IAAI,gBAAgB;AAC5C,SAAK,QAAQ,KAAK,EAAE,MAAM,gBAAgB,WAAW,YAAY,CAAC;AAGlE,SAAK,OAAO,gBAAgB,WAAW;AAGvC,UAAM,cAAgC,CAAC;AACvC,QAAI,KAAK,cAAc,KAAK,GAAG;AAC7B,kBAAY,KAAK,EAAE,MAAM,UAAU,SAAS,KAAK,cAAc,KAAK,EAAE,CAAC;AAAA,IACzE;AAEA,eAAW,KAAK,KAAK,WAAW;AAC9B,UAAI,EAAE,SAAS,YAAY,EAAE,OAAO,aAAa;AAC/C,oBAAY,KAAK,EAAE,MAAM,EAAE,MAA8B,SAAS,EAAE,QAAQ,CAAC;AAAA,MAC/E;AAAA,IACF;AAEA,QAAI,cAAc;AAElB,QAAI;AACF,YAAM,KAAK,UAAU,KAAK;AAAA,QACxB,UAAU,KAAK;AAAA,QACf,OAAO,KAAK;AAAA,QACZ,UAAU;AAAA,QACV,QAAQ,KAAK,iBAAiB;AAAA,QAE9B,SAAS,CAAC,OAAe,QAAgB;AACvC,wBAAc;AAEd,+BAAqB,UAAU;AAC/B,eAAK,QAAQ,KAAK;AAAA,YAChB,MAAM;AAAA,YACN;AAAA,YACA,aAAa;AAAA,YACb,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AAAA,QAEA,QAAQ,CAAC,aAAqB;AAC5B,+BAAqB,UAAU;AAC/B,+BAAqB,YAAY,IAAI;AAAA,QACvC;AAAA,QAEA,SAAS,CAAC,UAAiB;AACzB,eAAK,QAAQ,KAAK,EAAE,MAAM,SAAS,MAAM,CAAC;AAC1C,eAAK,OAAO,UAAU,KAAK;AAAA,QAC7B;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AAEd,UAAI,EAAE,iBAAiB,SAAS,MAAM,SAAS,eAAe;AAC5D,cAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,aAAK,QAAQ,KAAK,EAAE,MAAM,SAAS,OAAO,IAAI,CAAC;AAC/C,aAAK,OAAO,UAAU,GAAG;AAAA,MAC3B;AAAA,IACF,UAAE;AACA,WAAK,eAAe;AACpB,WAAK,mBAAmB;AAGxB,YAAM,eAAwB,EAAE,GAAG,sBAAsB,SAAS,eAAe,qBAAqB,QAAQ;AAE9G,2BAAqB,UAAU,aAAa;AAE5C,WAAK,QAAQ,KAAK,EAAE,MAAM,cAAc,SAAS,qBAAqB,CAAC;AACvE,WAAK,OAAO,cAAc,oBAAoB;AAC9C,WAAK,OAAO,YAAY,oBAAoB;AAG5C,WAAK,yBAAyB;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB,MAAM;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAqB;AACnB,SAAK,yBAAyB;AAC9B,SAAK,YAAY,CAAC;AAClB,SAAK,kBAAkB,WAAW;AAClC,SAAK,QAAQ,KAAK,EAAE,MAAM,uBAAuB,gBAAgB,KAAK,gBAAgB,CAAC;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,IAAqB;AACpC,SAAK,yBAAyB;AAE9B,UAAM,SAAS,KAAK,QAAQ,IAAI,EAAE;AAClC,QAAI,CAAC,OAAQ,QAAO;AAEpB,SAAK,kBAAkB;AACvB,SAAK,YAAY,OAAO,YAAY,CAAC;AACrC,SAAK,YAAY,gBAAgB,OAAO,QAAQ,IAAI,OAAO,WAAW;AACtE,SAAK,SAAS,OAAO,KAAK,SAAS,EAAE;AACrC,SAAK,gBAAgB,OAAO,gBAAgB;AAE5C,SAAK,QAAQ,KAAK,EAAE,MAAM,uBAAuB,gBAAgB,GAAG,CAAC;AACrE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAyC;AACvC,WAAO,KAAK,QAAQ,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,IAAkB;AACnC,SAAK,QAAQ,OAAO,EAAE;AAEtB,QAAI,OAAO,KAAK,iBAAiB;AAC/B,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAIQ,iBAAyB;AAC/B,QAAI,KAAK,OAAO,OAAQ,QAAO,KAAK,OAAO;AAE3C,QAAI;AACF,aAAO,aAAa,QAAQ,SAAS,KAAK;AAAA,IAC5C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAY,MAAmB,SAAiB,UAA8B;AACpF,UAAM,UAAmB;AAAA,MACvB,IAAI,kBAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,WAAW,IAAI;AAAA,MACf;AAAA,IACF;AACA,SAAK,UAAU,KAAK,OAAO;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,2BAAiC;AACvC,QAAI,CAAC,KAAK,mBAAmB,KAAK,UAAU,WAAW,EAAG;AAE1D,UAAM,WAAW,KAAK,QAAQ,IAAI,KAAK,eAAe;AACtD,UAAM,SAAS,oBAAoB;AAAA,MACjC,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,SAAS;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,QAAI,SAAU,QAAO,YAAY,SAAS;AAE1C,SAAK,QAAQ,KAAK,MAAM;AAAA,EAC1B;AACF;;;AC5XO,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["delta"]}