@akropolys/kiku 1.7.16 → 1.7.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/SearchBar.tsx","../src/utils/cn.ts","../src/components/ChatWidget.tsx","../src/utils/markdown.tsx","../src/utils/icons.tsx","../src/utils/theme.ts","../src/components/VoiceButton.tsx","../src/components/VisualSearch.tsx","../src/components/KikuButton.tsx","../src/components/ComparisonMatrix.tsx","../src/components/MarkupEditor.tsx","../src/components/Sparkle.tsx"],"sourcesContent":["// @akropolys/kiku — Plug-and-play UI components for Akropolys\n// Developers must explicitly import '@akropolys/kiku/styles.css' in their entry file.\n\nexport { SearchBar } from './components/SearchBar';\nexport type { SearchBarProps } from './components/SearchBar';\nexport { ChatWidget, ChatWidget as KikuChat } from './components/ChatWidget';\nexport type { ChatWidgetProps, ChatWidgetProps as KikuChatProps } from './components/ChatWidget';\nexport { KikuButton } from './components/KikuButton';\nexport type { KikuButtonProps } from './components/KikuButton';\nexport { Sparkle } from './components/Sparkle';\nexport { ComparisonMatrix } from './components/ComparisonMatrix';\n\n// Voice & Vision — free AI input modalities\nexport { VoiceButton } from './components/VoiceButton';\nexport type { VoiceButtonProps } from './components/VoiceButton';\nexport { VisualSearch } from './components/VisualSearch';\nexport type { VisualSearchProps } from './components/VisualSearch';\n\n","import React, { useState, useEffect, useRef } from 'react';\nimport { useSearch, SearchResult, AkropolysTheme, useAkropolysContext } from '@akropolys/sdk';\nimport { cn } from '../utils/cn';\n\nexport interface SearchBarProps {\n placeholder?: string;\n limit?: number;\n /** Debounce in ms — default 150 for instant type-ahead */\n debounceMs?: number;\n onSelect?: (result: SearchResult) => void;\n className?: string;\n inputClassName?: string;\n dropdownClassName?: string;\n renderResult?: (result: SearchResult) => React.ReactNode;\n theme?: AkropolysTheme;\n classNames?: {\n root?: string;\n input?: string;\n dropdown?: string;\n row?: string;\n };\n}\n\n/* SVG search glass — pure inline so no icon dependency */\nconst SearchIcon = () => (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <circle cx=\"8.5\" cy=\"8.5\" r=\"5.5\"/>\n <line x1=\"13\" y1=\"13\" x2=\"18\" y2=\"18\"/>\n </svg>\n);\n\nexport function SearchBar({\n placeholder = 'Search products…',\n limit = 10,\n debounceMs = 150,\n onSelect,\n className,\n inputClassName,\n dropdownClassName,\n renderResult,\n theme,\n classNames = {},\n}: SearchBarProps) {\n const [query, setQuery] = useState('');\n const [open, setOpen] = useState(false);\n const { results, loading, search, clear } = useSearch({ debounceMs });\n const client = useAkropolysContext();\n const wrap = useRef<HTMLDivElement>(null);\n const ignoreNextQueryChange = useRef(false);\n\n /* useSearch debounces internally — fire on every keystroke, keep stale results visible */\n useEffect(() => {\n if (ignoreNextQueryChange.current) {\n ignoreNextQueryChange.current = false;\n return;\n }\n if (!query.trim()) {\n clear();\n setOpen(false);\n return;\n }\n setOpen(true); // open immediately (stale results show while fetching)\n search(query, limit);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [query]);\n\n /* Click-outside to close */\n useEffect(() => {\n const h = (e: MouseEvent) => {\n if (wrap.current && !wrap.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener('mousedown', h);\n return () => document.removeEventListener('mousedown', h);\n }, []);\n\n const handleSelect = (r: SearchResult) => {\n if (query.trim()) {\n // keepalive: onSelect commonly navigates the page right after this call —\n // without it the browser aborts the in-flight log request mid-navigation.\n client.api.searchVector(query, 1, undefined, true).catch(() => {});\n }\n ignoreNextQueryChange.current = true;\n setOpen(false);\n setQuery(r.entity.title ?? r.entity.name ?? '');\n onSelect?.(r);\n };\n\n const handleCommitSearch = () => {\n if (!query.trim()) return;\n client.api.searchVector(query, 1, undefined, true).catch(() => {});\n if (results.length > 0) {\n handleSelect(results[0]);\n }\n };\n\n const showDrop = open && query.trim().length > 0;\n\n const customStyles = {\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\n } as React.CSSProperties;\n\n return (\n <div className={cn(\"hsk-sb-wrap\", classNames.root, className)} ref={wrap} style={customStyles}>\n <span className=\"hsk-sb-icon\"><SearchIcon /></span>\n <input\n className={cn(\"hsk-sb-input\", classNames.input, inputClassName)}\n type=\"text\"\n value={query}\n placeholder={placeholder}\n onChange={e => setQuery(e.target.value)}\n onFocus={() => results.length > 0 && query.trim() && setOpen(true)}\n onKeyDown={e => {\n if (e.key === 'Enter') {\n handleCommitSearch();\n }\n }}\n autoComplete=\"off\"\n spellCheck={false}\n />\n {showDrop && (\n <div className={cn(\"hsk-sb-drop\", classNames.dropdown, dropdownClassName)} style={{ position: 'absolute' }}>\n {loading && <div className=\"hsk-sb-loading-bar\" />}\n\n {loading && results.length === 0 ? (\n <>\n <div className=\"hsk-sb-skeleton-row\">\n <span className=\"hsk-sb-skeleton-icon\" />\n <div className=\"hsk-sb-row-body\">\n <div className=\"hsk-sb-skeleton-text1\" />\n <div className=\"hsk-sb-skeleton-text2\" />\n </div>\n </div>\n <div className=\"hsk-sb-skeleton-row\">\n <span className=\"hsk-sb-skeleton-icon\" />\n <div className=\"hsk-sb-row-body\">\n <div className=\"hsk-sb-skeleton-text1\" style={{ width: '45%' }} />\n <div className=\"hsk-sb-skeleton-text2\" style={{ width: '25%' }} />\n </div>\n </div>\n </>\n ) : (\n <>\n {results.length === 0 && !loading && (\n <div className=\"hsk-sb-empty\">No results for &ldquo;{query}&rdquo;</div>\n )}\n\n {results.map((r, i) => {\n if (renderResult) {\n return (\n <div\n key={r.id}\n onClick={() => handleSelect(r)}\n className=\"hsk-sb-fade\"\n style={{ animationDelay: `${i * 18}ms` }}\n >\n {renderResult(r)}\n </div>\n );\n }\n const thumb = r.entity.image ?? r.entity.thumbnail ?? r.entity.images?.[0];\n return (\n <div\n key={r.id}\n className={cn(\"hsk-sb-row hsk-sb-fade\", classNames.row)}\n style={{ animationDelay: `${i * 18}ms` }}\n onClick={() => handleSelect(r)}\n >\n <span className=\"hsk-sb-row-thumb\">\n {thumb ? (\n <img\n src={thumb}\n alt=\"\"\n loading=\"lazy\"\n onError={e => { e.currentTarget.style.display = 'none'; }}\n />\n ) : (\n <SearchIcon />\n )}\n </span>\n <div className=\"hsk-sb-row-body\">\n <div className=\"hsk-sb-row-title\">{r.entity.title ?? r.entity.name}</div>\n {(r.entity.category || r.entity.brand) && (\n <div className=\"hsk-sb-row-sub\">\n {r.entity.category ?? r.entity.brand}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merges Tailwind classes intelligently, allowing overrides.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport { useKiku, ChatMessage, ChatSource } from '@akropolys/sdk';\nimport { renderMarkdown } from '../utils/markdown';\nimport { AkropolysTheme } from '@akropolys/sdk';\nimport { cn } from '../utils/cn';\nimport { ArrowUpIcon } from '../utils/icons';\nimport { resolveTheme } from '../utils/theme';\nimport { VoiceButton } from './VoiceButton';\nimport { VisualSearch } from './VisualSearch';\n\n\nexport interface ChatWidgetProps {\n title?: string;\n placeholder?: string;\n emptyStateText?: string;\n emptyStateSuggestions?: string;\n defaultCurrency?: string;\n className?: string;\n \n // Allow overriding styles via standard CSS variables\n theme?: AkropolysTheme;\n \n // Allow targeting specific elements with custom classes (e.g. Tailwind)\n classNames?: {\n root?: string;\n header?: string;\n messageBubble?: string;\n input?: string;\n };\n \n onSelectSource?: (source: ChatSource) => void;\n\n /** Enable 🎙️ voice input via browser Web Speech API (free) */\n enableVoice?: boolean;\n /** Enable 📷 visual style-match search via Gemini (requires backend GEMINI_API_KEY) */\n enableVision?: boolean;\n /** Optional category hint for visual search (e.g. 'dress', 'curtains') */\n visionCategoryHint?: string;\n}\n\n\nconst SparkleIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z\"/>\n </svg>\n);\n\nfunction SourceCard({\n source,\n defaultCurrency,\n onSelect,\n isReferenced\n}: {\n source: ChatSource;\n defaultCurrency: string;\n onSelect?: (s: ChatSource) => void;\n isReferenced?: boolean;\n}) {\n return (\n <div\n className={cn(\"hsk-source-card\", isReferenced && \"hsk-source-card--referenced\")}\n onClick={() => onSelect?.(source)}\n >\n {source.image && <img src={source.image} alt={source.name} className=\"hsk-source-img\" />}\n <div style={{ flex: 1, minWidth: 0, position: 'relative' }}>\n {isReferenced && (\n <div className=\"hsk-cb-source-ref-badge\" title=\"Featured in response\" style={{ top: '0', right: '0' }}>\n <SparkleIcon />\n </div>\n )}\n <div className=\"hsk-source-name\" style={{ paddingRight: isReferenced ? '20px' : undefined }}>{source.name}</div>\n {source.price && (\n <div className=\"hsk-source-price\">{source.currency ?? defaultCurrency} {source.price}</div>\n )}\n </div>\n </div>\n );\n}\n\ninterface ChatMessageWithVisual extends ChatMessage {\n imagePreview?: string;\n styleDNA?: any;\n visualSources?: ChatSource[];\n}\n\nexport function ChatWidget({ \n title = 'kiku',\n placeholder = 'Ask about anything in our store…', \n emptyStateText = 'Ask me anything about our products',\n emptyStateSuggestions = '\"Find me headphones under KSh 5,000\" · \"Gift ideas\"',\n defaultCurrency = 'KES',\n className,\n theme,\n classNames = {},\n onSelectSource,\n enableVoice = false,\n enableVision = false,\n visionCategoryHint\n}: ChatWidgetProps) {\n const { messages, sources, referencedIds, loading: chatLoading, streaming, error, send, reset } = useKiku();\n const [input, setInput] = useState('');\n const [visualLoading, setVisualLoading] = useState(false);\n const bottomRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n const loading = chatLoading || visualLoading;\n\n const [chatHistory, setChatHistory] = useState<ChatMessageWithVisual[]>([]);\n const lastSyncedCount = useRef(0);\n\n useEffect(() => {\n if (messages.length === 0) {\n setChatHistory([]);\n lastSyncedCount.current = 0;\n return;\n }\n\n if (messages.length > lastSyncedCount.current) {\n const newMsgs = messages.slice(lastSyncedCount.current);\n setChatHistory(prev => [...prev, ...newMsgs]);\n lastSyncedCount.current = messages.length;\n } else if (messages.length < lastSyncedCount.current) {\n setChatHistory(messages);\n lastSyncedCount.current = messages.length;\n } else {\n setChatHistory(prev => {\n const next = [...prev];\n let hookIdx = messages.length - 1;\n let historyIdx = next.length - 1;\n while (hookIdx >= 0 && historyIdx >= 0) {\n if (next[historyIdx].role === messages[hookIdx].role) {\n next[historyIdx] = {\n ...next[historyIdx],\n content: messages[hookIdx].content,\n actionType: messages[hookIdx].actionType,\n thinking: messages[hookIdx].thinking,\n thoughtForSeconds: messages[hookIdx].thoughtForSeconds,\n statusMessage: messages[hookIdx].statusMessage,\n };\n break;\n }\n historyIdx--;\n }\n return next;\n });\n }\n }, [messages]);\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [chatHistory, loading]);\n\n const handleSend = async () => {\n const q = input.trim();\n if (!q || loading) return;\n setInput('');\n if (textareaRef.current) textareaRef.current.style.height = 'auto';\n await send(q);\n };\n\n const handleKey = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInput(e.target.value);\n const t = e.target;\n t.style.height = 'auto';\n t.style.height = Math.min(t.scrollHeight, 120) + 'px';\n };\n\n const handleVisualResults = (res: any, preview: string) => {\n const userMsg: ChatMessageWithVisual = {\n role: 'user',\n content: 'Uploaded a photo for visual search',\n imagePreview: preview,\n };\n\n const dna = res.style_dna;\n let content = `I've analyzed your image! Here is the Style DNA I found:\\n`;\n if (dna) {\n if (dna.color_palette) content += `* **Palette:** ${dna.color_palette}\\n`;\n if (dna.dominant_colors && dna.dominant_colors.length > 0) {\n content += `* **Colors:** ${dna.dominant_colors.join(', ')}\\n`;\n }\n if (dna.aesthetic && dna.aesthetic.length > 0) {\n content += `* **Aesthetic:** ${dna.aesthetic.join(', ')}\\n`;\n }\n if (dna.texture) content += `* **Texture:** ${dna.texture}\\n`;\n if (dna.formality) content += `* **Formality:** ${dna.formality}\\n`;\n }\n\n const results = res.results || [];\n if (results.length > 0) {\n content += `\\nI found ${results.length} matching products in the store for you.`;\n } else {\n content += `\\nI couldn't find any matching products in the store.`;\n }\n\n const assistantMsg: ChatMessageWithVisual = {\n role: 'assistant',\n content,\n styleDNA: dna,\n visualSources: results.map((r: any) => ({\n id: r.id,\n name: r.product.name,\n price: r.product.price,\n currency: r.product.currency,\n category: r.product.category,\n url: r.product.url,\n image: r.product.images && r.product.images.length > 0 ? r.product.images[0] : undefined,\n brand: r.product.brand,\n })),\n };\n\n setChatHistory(prev => [...prev, userMsg, assistantMsg]);\n };\n\n const { vars: customStyles } = resolveTheme(theme);\n\n return (\n <div\n className={cn(\"hsk-chat-widget\", classNames.root, className)}\n style={customStyles}\n >\n <div className={cn(\"hsk-chat-header\", classNames.header)}>\n <span className=\"hsk-chat-header-icon\"><SparkleIcon /></span>\n <span className=\"hsk-chat-title\">{title}</span>\n <span className=\"hsk-chat-badge\">AI</span>\n {chatHistory.length > 0 && (\n <button className=\"hsk-chat-reset\" onClick={reset} style={{ marginLeft: 'auto' }}>Clear</button>\n )}\n </div>\n\n <div className=\"hsk-chat-messages\">\n {chatHistory.length === 0 ? (\n <div className=\"hsk-chat-empty\">\n <div className=\"hsk-chat-empty-icon\"><SparkleIcon /></div>\n <div>{emptyStateText}</div>\n <div className=\"hsk-chat-empty-suggestions\">{emptyStateSuggestions}</div>\n </div>\n ) : (\n chatHistory.map((msg, idx) => (\n <div key={idx}>\n <div className={`hsk-msg-row ${msg.role}`}>\n <div className={cn(\"hsk-msg-avatar\", msg.role === 'assistant' ? 'ai' : 'user')}>\n {msg.role === 'assistant' ? <SparkleIcon /> : 'U'}\n </div>\n <div className={cn(\"hsk-msg-bubble\", msg.role, classNames.messageBubble)}>\n {msg.imagePreview && (\n <div className=\"kiku-vs-preview-bubble\" style={{ marginBottom: '8px' }}>\n <img src={msg.imagePreview} alt=\"Uploaded Preview\" className=\"kiku-vs-preview-bubble-img\" style={{ maxWidth: '200px', borderRadius: '8px' }} />\n </div>\n )}\n {msg.thinking && (\n <details className=\"hsk-thinking-details\" open={streaming && idx === chatHistory.length - 1 && !msg.content}>\n <summary className=\"hsk-thinking-summary\">\n Thought for {msg.thoughtForSeconds ?? 1}s\n </summary>\n <div className=\"hsk-thinking-text\">{msg.thinking}</div>\n </details>\n )}\n {(!msg.content && !msg.thinking && msg.role === 'assistant' && idx === chatHistory.length - 1) && (\n <div className=\"hsk-status-live\">\n <span className=\"hsk-status-dot\" />\n <span>{msg.statusMessage || 'Thinking...'}</span>\n </div>\n )}\n {renderMarkdown(msg.content)}\n {streaming && idx === chatHistory.length - 1 && msg.role === 'assistant' && (\n <span className=\"hsk-streaming-cursor\" />\n )}\n {msg.styleDNA && (\n <div className=\"kiku-vs-preview-banner\" style={{ marginTop: '10px' }}>\n {chatHistory[idx - 1]?.imagePreview && (\n <img src={chatHistory[idx - 1].imagePreview} alt=\"Visual Search Input\" className=\"kiku-vs-preview-img\" />\n )}\n <div className=\"kiku-vs-preview-info\">\n <div className=\"kiku-vs-preview-label\">Visual Match Palette</div>\n <div className=\"kiku-vs-preview-palette\">{msg.styleDNA.color_palette || 'Detected Style DNA'}</div>\n {msg.styleDNA.style_tags && msg.styleDNA.style_tags.length > 0 && (\n <div className=\"kiku-style-tags\">\n {msg.styleDNA.style_tags.map((tag: string, ti: number) => (\n <span key={ti} className=\"kiku-style-tag\">#{tag}</span>\n ))}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n {msg.role === 'assistant' && msg.visualSources && msg.visualSources.length > 0 && (\n <div className=\"hsk-sources-container\">\n <div className=\"hsk-sources\">\n {msg.visualSources.map((src, si) => (\n <SourceCard key={si} source={src} defaultCurrency={defaultCurrency} onSelect={onSelectSource} />\n ))}\n </div>\n </div>\n )}\n {msg.role === 'assistant' && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && (() => {\n const isStreamingActive = chatLoading || streaming;\n if (isStreamingActive) {\n return (\n <div className=\"hsk-sources-container\">\n <div className=\"hsk-sources\">\n {sources.map((src, si) => {\n const isReferenced = !!(src.id && referencedIds.includes(src.id));\n return (\n <SourceCard\n key={si}\n source={src}\n defaultCurrency={defaultCurrency}\n onSelect={onSelectSource}\n isReferenced={isReferenced}\n />\n );\n })}\n </div>\n </div>\n );\n }\n\n // Streaming finished: show the products the answer actually\n // references. Only fall back to the full candidate list when the\n // answer referenced none — showing unrelated matches (a kids'\n // sandal for a \"heels to match my dress\" query) reads as a bug.\n const featured = sources.filter(src => src.id && referencedIds.includes(src.id));\n // Only fall back to the candidate list when the answer referenced\n // nothing at all. If it referenced specific items, show just those —\n // never dump unrelated matches (e.g. phones for a sofa question).\n const general = referencedIds.length > 0\n ? []\n : sources.filter(src => !src.id || !referencedIds.includes(src.id));\n\n return (\n <div className=\"hsk-sources-container\">\n {featured.length > 0 && (\n <div className=\"hsk-sources-group\" style={{ marginBottom: '10px' }}>\n <div className=\"hsk-sources-group-title\">⭐ Featured in response</div>\n <div className=\"hsk-sources\">\n {featured.map((src, si) => (\n <SourceCard\n key={`feat-${si}`}\n source={src}\n defaultCurrency={defaultCurrency}\n onSelect={onSelectSource}\n isReferenced={true}\n />\n ))}\n </div>\n </div>\n )}\n {general.length > 0 && (\n <div className=\"hsk-sources-group\">\n {featured.length > 0 && <div className=\"hsk-sources-group-title\">All matches</div>}\n <div className=\"hsk-sources\">\n {general.map((src, si) => (\n <SourceCard\n key={`gen-${si}`}\n source={src}\n defaultCurrency={defaultCurrency}\n onSelect={onSelectSource}\n isReferenced={false}\n />\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n </div>\n ))\n )}\n\n {loading && (\n <div className=\"hsk-msg-row\">\n <div className=\"hsk-msg-avatar ai\"><SparkleIcon /></div>\n <div className=\"hsk-pending\" role=\"status\" aria-live=\"polite\">\n <div className=\"hsk-pending-glyph\">\n <span className=\"hsk-pending-ring\" />\n <span className=\"hsk-pending-dot\" />\n </div>\n <div className=\"hsk-pending-text\">\n <span className=\"hsk-pending-step step-1\">Searching catalog</span>\n <span className=\"hsk-pending-step step-2\">Reasoning</span>\n <span className=\"hsk-pending-step step-3\">Composing</span>\n </div>\n </div>\n </div>\n )}\n\n {error && (\n <div className=\"hsk-chat-error\">\n {(() => {\n try {\n const parsed = JSON.parse(error);\n return parsed.error || parsed.message || error;\n } catch {\n return error;\n }\n })()}\n </div>\n )}\n <div ref={bottomRef} />\n </div>\n\n <div className=\"hsk-chat-input-area\" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n {enableVision && (\n <VisualSearch\n onResults={handleVisualResults}\n onError={(err) => console.error('[VisualSearch] error:', err)}\n categoryHint={visionCategoryHint}\n disabled={loading}\n />\n )}\n <textarea\n ref={textareaRef}\n className={cn(\"hsk-chat-input\", classNames.input)}\n value={input}\n onChange={handleInput}\n onKeyDown={handleKey}\n placeholder={placeholder}\n rows={1}\n disabled={loading}\n style={{ flex: 1 }}\n />\n {enableVoice && (\n <VoiceButton\n onTranscript={(text) => {\n setInput(text);\n send(text);\n setInput('');\n }}\n onInterim={(text) => setInput(text)}\n disabled={loading}\n />\n )}\n <button\n className=\"hsk-chat-send\"\n onClick={handleSend}\n disabled={!input.trim() || loading}\n aria-label=\"Send message\"\n >\n <ArrowUpIcon />\n </button>\n </div>\n </div>\n );\n}\n\n\n","import React from 'react';\n\n// Helper to parse inline styles (bold, images, links, and inline code) safely into React nodes\nconst parseInline = (text: string, keyPrefix: string): React.ReactNode => {\n // Regex matches: images ![alt](url), links [text](url), bold **text**, inline code `code`\n const tokenRegex = /(!\\[[^\\]]*\\]\\([^)]+\\)|\\[[^\\]]+\\]\\([^)]+\\)|\\*\\*[^*]+\\*\\*|`[^`]+`)/g;\n const parts = text.split(tokenRegex);\n\n return parts.map((part, index) => {\n if (!part) return null;\n const key = `${keyPrefix}-inline-${index}`;\n\n // Handle Inline Code\n if (part.startsWith('`') && part.endsWith('`')) {\n return (\n <code key={key} className=\"hsk-markdown-code\">\n {part.slice(1, -1)}\n </code>\n );\n }\n\n // Handle Bold\n if (part.startsWith('**') && part.endsWith('**')) {\n return <strong key={key}>{parseInline(part.slice(2, -2), key)}</strong>;\n }\n\n // Handle Images: ![alt](url)\n const imageMatch = part.match(/^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/);\n if (imageMatch) {\n const alt = imageMatch[1];\n const url = imageMatch[2];\n const isSafeUrl = /^(https?|data:image):/i.test(url);\n if (isSafeUrl) {\n return (\n <img\n key={key}\n src={url}\n alt={alt || 'Product image'}\n className=\"hsk-markdown-img\"\n loading=\"lazy\"\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n );\n }\n return null;\n }\n\n // Handle Links: [text](url)\n const linkMatch = part.match(/^\\[([^\\]]+)\\]\\(([^)]+)\\)$/);\n if (linkMatch) {\n // Basic sanitization: ensure the URL doesn't contain javascript:\n const url = linkMatch[2];\n const isSafeUrl = /^(https?|mailto|tel):/i.test(url) || url.startsWith('/');\n if (isSafeUrl) {\n return (\n <a key={key} href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"hsk-markdown-link\">\n {parseInline(linkMatch[1], key)}\n </a>\n );\n }\n return <span key={key}>{parseInline(linkMatch[1], key)}</span>; // Fallback to plain text if unsafe\n }\n\n // Return standard text\n return part;\n });\n};\n\n// A table can only START on a line beginning with \"|\"; continuations just need a \"|\".\nfunction isTableLine(line: string, inTable: boolean): boolean {\n const t = line.trim();\n if (inTable) return t.includes('|');\n return t.startsWith('|');\n}\n\n// Strips at most one leading + one trailing pipe, so a missing closing pipe never drops the last cell.\nfunction splitTableCells(rowLine: string): string[] {\n let t = rowLine.trim();\n if (t.startsWith('|')) t = t.slice(1);\n if (t.endsWith('|')) t = t.slice(0, -1);\n return t.split('|').map(c => c.trim());\n}\n\nexport function renderMarkdown(content: string, streaming = false): React.ReactNode {\n const lines = content.split('\\n');\n // While streaming, hold back a trailing table row whose closing pipe hasn't arrived yet.\n if (streaming && lines.length > 0) {\n const last = lines[lines.length - 1];\n if (last.trim().startsWith('|') && !last.trim().endsWith('|')) {\n lines.pop();\n }\n }\n const elements: React.ReactNode[] = [];\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n const key = `md-line-${i}`;\n\n // 1. Empty lines (spacing)\n if (!line.trim()) {\n i++;\n continue;\n }\n\n // 2. Standalone image lines: ![alt](url)\n const standaloneImageMatch = line.trim().match(/^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/);\n if (standaloneImageMatch) {\n const alt = standaloneImageMatch[1];\n const url = standaloneImageMatch[2];\n const isSafeUrl = /^(https?|data:image):/i.test(url);\n if (isSafeUrl) {\n elements.push(\n <div key={key} className=\"hsk-markdown-img-block\">\n <img\n src={url}\n alt={alt || 'Product image'}\n className=\"hsk-markdown-img\"\n loading=\"lazy\"\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n </div>\n );\n }\n i++;\n continue;\n }\n\n // 3. Headers\n const headerMatch = line.match(/^(#{1,3})\\s+(.*)/);\n if (headerMatch) {\n const level = headerMatch[1].length;\n const Tag = `h${level + 3}` as keyof JSX.IntrinsicElements; // Maps # to h4, ## to h5 to avoid messing up host page hierarchy\n elements.push(<Tag key={key} className={`hsk-markdown-h${level}`}>{parseInline(headerMatch[2], key)}</Tag>);\n i++;\n continue;\n }\n\n // 4. Unordered Lists\n if (line.match(/^[-*]\\s+/)) {\n const listItems: React.ReactNode[] = [];\n while (i < lines.length && lines[i].match(/^[-*]\\s+/)) {\n const itemText = lines[i].replace(/^[-*]\\s+/, '');\n listItems.push(<li key={`li-${i}`}>{parseInline(itemText, `li-${i}`)}</li>);\n i++;\n }\n elements.push(<ul key={`ul-${key}`} className=\"hsk-markdown-list\">{listItems}</ul>);\n continue;\n }\n\n // 5. Ordered Lists\n if (line.match(/^\\d+[.)]\\s+/)) {\n const listItems: React.ReactNode[] = [];\n while (i < lines.length && lines[i].match(/^\\d+[.)]\\s+/)) {\n const itemText = lines[i].replace(/^\\d+[.)]\\s+/, '');\n listItems.push(<li key={`li-${i}`}>{parseInline(itemText, `li-${i}`)}</li>);\n i++;\n }\n elements.push(<ol key={`ol-${key}`} className=\"hsk-markdown-list\">{listItems}</ol>);\n continue;\n }\n\n // 6. Tables\n if (isTableLine(line, false)) {\n const tableRows: React.ReactNode[] = [];\n let isHeader = true;\n\n while (i < lines.length && isTableLine(lines[i], true)) {\n const rowLine = lines[i].trim();\n // Skip markdown table separator (e.g., |---|---| or |---|---)\n if (rowLine.match(/^\\|?[-:| ]+\\|?$/) && rowLine.includes('-')) {\n i++;\n isHeader = false;\n continue;\n }\n\n const cells = splitTableCells(rowLine);\n const Tag = isHeader ? 'th' : 'td';\n\n tableRows.push(\n <tr key={`tr-${i}`}>\n {cells.map((cell, cIdx) => (\n <Tag key={`td-${i}-${cIdx}`}>{parseInline(cell, `td-${i}-${cIdx}`)}</Tag>\n ))}\n </tr>\n );\n i++;\n }\n \n elements.push(\n <div key={`table-wrapper-${key}`} className=\"hsk-table-wrapper\">\n <table className=\"hsk-markdown-table\">\n <tbody>{tableRows}</tbody>\n </table>\n </div>\n );\n continue;\n }\n\n // 7. Default Paragraph\n elements.push(\n <p key={key} className=\"hsk-markdown-p\">\n {parseInline(line, key)}\n </p>\n );\n i++;\n }\n\n return <>{elements}</>;\n}\n","import React from 'react';\n\nexport const ArrowUpIcon = () => (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n);\n","import type { CSSProperties } from 'react';\nimport type { AkropolysTheme } from '@akropolys/sdk';\n\nexport type ThemeProp = 'light' | 'dark' | AkropolysTheme | undefined;\n\n// A string theme ('light'/'dark') selects a preset via the data-hsk-theme\n// attribute; an object theme maps to CSS custom properties applied inline.\nexport function resolveTheme(theme: ThemeProp): {\n themeAttr: 'light' | 'dark' | undefined;\n vars: CSSProperties | undefined;\n} {\n if (typeof theme === 'string') {\n return { themeAttr: theme, vars: undefined };\n }\n if (!theme) {\n return { themeAttr: undefined, vars: undefined };\n }\n const vars: Record<string, string> = {};\n if (theme.primaryColor) vars['--hsk-primary'] = theme.primaryColor;\n if (theme.backgroundColor) {\n vars['--hsk-bg'] = theme.backgroundColor;\n vars['--hsk-chat-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n vars['--hsk-text'] = theme.textColor;\n vars['--hsk-chat-text'] = theme.textColor;\n }\n if (theme.fontFamily) vars['--hsk-font'] = theme.fontFamily;\n if (theme.fontSize) vars['--hsk-font-size'] = theme.fontSize;\n if (theme.borderRadius) vars['--hsk-border-radius'] = theme.borderRadius;\n return { themeAttr: undefined, vars: vars as CSSProperties };\n}\n","import React, { useState, useRef, useCallback } from 'react';\n\nexport interface VoiceButtonProps {\n onTranscript: (text: string) => void;\n onInterim?: (text: string) => void;\n /** BCP-47 language tag. Defaults to 'en-US'. */\n lang?: string;\n className?: string;\n disabled?: boolean;\n}\n\nconst MicIcon = ({ active }: { active: boolean }) => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"11\" rx=\"3\" fill={active ? 'currentColor' : 'none'} />\n <path d=\"M5 10a7 7 0 0 0 14 0\" />\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" />\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\" />\n </svg>\n);\n\n/**\n * VoiceButton — converts speech to text using the browser's free Web Speech API.\n * No API key, no backend call, no cost.\n *\n * @example\n * <VoiceButton onTranscript={(text) => setQuery(text)} />\n */\nexport function VoiceButton({\n onTranscript,\n onInterim,\n lang = 'en-US',\n className = '',\n disabled = false,\n}: VoiceButtonProps) {\n const [listening, setListening] = useState(false);\n const recognitionRef = useRef<any>(null);\n\n const isSupported =\n typeof window !== 'undefined' &&\n ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);\n\n const start = useCallback(() => {\n if (!isSupported || listening) return;\n\n const SR: any =\n (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;\n const recognition = new SR();\n recognition.lang = lang;\n recognition.interimResults = true;\n recognition.maxAlternatives = 1;\n recognitionRef.current = recognition;\n\n recognition.onstart = () => setListening(true);\n recognition.onend = () => setListening(false);\n recognition.onerror = () => setListening(false);\n\n recognition.onresult = (e: any) => {\n const results = Array.from(e.results as any[]);\n const transcript = results.map((r: any) => r[0].transcript).join('');\n const isFinal = (e.results[e.results.length - 1] as any).isFinal;\n if (isFinal) {\n onTranscript(transcript);\n setListening(false);\n } else {\n onInterim?.(transcript);\n }\n };\n\n recognition.start();\n }, [isSupported, listening, lang, onTranscript, onInterim]);\n\n const stop = useCallback(() => {\n recognitionRef.current?.stop();\n setListening(false);\n }, []);\n\n // Silently render nothing if the browser doesn't support Web Speech API\n if (!isSupported) return null;\n\n return (\n <button\n type=\"button\"\n className={`kiku-voice-btn${listening ? ' kiku-voice-btn--active' : ''} ${className}`}\n onClick={listening ? stop : start}\n disabled={disabled}\n title={listening ? 'Stop listening' : 'Speak your search'}\n aria-label={listening ? 'Stop voice input' : 'Start voice input'}\n >\n <MicIcon active={listening} />\n {listening && <span className=\"kiku-voice-ripple\" aria-hidden=\"true\" />}\n </button>\n );\n}\n","import React, { useRef, useState } from 'react';\nimport { useAkropolysContext } from '@akropolys/sdk';\nimport type { VisualSearchResponse } from '@akropolys/sdk';\n\nexport interface VisualSearchProps {\n /** Called with search results + the base64 preview when Gemini responds. */\n onResults: (res: VisualSearchResponse, previewBase64: string) => void;\n onError?: (err: Error) => void;\n /**\n * Category hint sent to Gemini to sharpen the match_query.\n * e.g. \"dress\", \"curtains\", \"sofa\", \"shoes\"\n */\n categoryHint?: string;\n className?: string;\n disabled?: boolean;\n}\n\nconst CameraIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\" />\n <circle cx=\"12\" cy=\"13\" r=\"4\" />\n </svg>\n);\n\nconst SpinnerIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" className=\"kiku-vs-spin\">\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n);\n\nfunction fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n}\n\n/**\n * VisualSearch — camera/image-upload button that powers style-match search.\n *\n * User picks a photo → it's base64-encoded in-browser → sent to POST /search/visual\n * → Gemini Flash extracts Style DNA → results returned via onResults().\n *\n * @example\n * <VisualSearch\n * categoryHint=\"dress\"\n * onResults={(res, preview) => setVisualResults(res)}\n * />\n */\nexport function VisualSearch({\n onResults,\n onError,\n categoryHint,\n className = '',\n disabled = false,\n}: VisualSearchProps) {\n const client = useAkropolysContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const [loading, setLoading] = useState(false);\n\n const handleFile = async (file: File) => {\n if (!file.type.startsWith('image/')) return;\n setLoading(true);\n try {\n const base64 = await fileToBase64(file);\n const res = await (client.api as any).searchByImage(base64, categoryHint);\n onResults(res as VisualSearchResponse, base64);\n } catch (e: any) {\n onError?.(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n // Reset so the same file can be picked again\n if (inputRef.current) inputRef.current.value = '';\n }\n };\n\n return (\n <label\n className={`kiku-vs-btn${loading ? ' kiku-vs-btn--loading' : ''} ${className}`}\n title=\"Search by photo\"\n aria-label=\"Search by uploading a photo\"\n style={{ cursor: disabled || loading ? 'not-allowed' : 'pointer' }}\n >\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/*\"\n capture=\"environment\"\n onChange={e => e.target.files?.[0] && handleFile(e.target.files[0])}\n disabled={disabled || loading}\n hidden\n />\n {loading ? <SpinnerIcon /> : <CameraIcon />}\n </label>\n );\n}\n","'use client';\n\nimport React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useKiku, ChatMessage, ChatSource } from '@akropolys/sdk';\nimport { useAkropolysContext } from '@akropolys/sdk';\nimport { renderMarkdown } from '../utils/markdown';\nimport { AkropolysTheme, ChatAttachment, CaptureTarget } from '@akropolys/sdk';\nimport { cn } from '../utils/cn';\nimport { resolveTheme } from '../utils/theme';\nimport { ComparisonMatrix } from './ComparisonMatrix';\nimport { MarkupEditor } from './MarkupEditor';\nimport { ArrowUpIcon } from '../utils/icons';\n\n\nexport interface KikuButtonProps {\n label?: string;\n title?: string;\n placeholder?: string;\n backdropColor?: string;\n backdropBlur?: string | number;\n className?: string;\n onSelectSource?: (source: ChatSource) => void;\n defaultCurrency?: string;\n chips?: string[];\n theme?: 'light' | 'dark' | AkropolysTheme;\n classNames?: {\n button?: string;\n overlay?: string;\n panel?: string;\n input?: string;\n sendButton?: string;\n };\n /** Enable 🎙️ voice input via browser Web Speech API (free) */\n enableVoice?: boolean;\n /** BCP-47 tag for voice transcription (e.g. 'sw-KE', 'fr-FR'). Defaults to\n the page's <html lang>, then the browser language. */\n voiceLang?: string;\n /** Enable 📷 visual style-match search via Gemini (requires backend GEMINI_API_KEY) */\n enableVision?: boolean;\n /** Optional category hint for visual search (e.g. 'dress', 'curtains') */\n visionCategoryHint?: string;\n}\n\n// ─── Icons ────────────────────────────────────────────────────────────────────\n\n// kiku brand mark — glyph extracted from public/brand/akropolys-icon.svg, fill\n// only (no background rect) so it drops into the existing colored circles/badges.\nconst KikuIcon = ({ className, size = 18 }: { className?: string; size?: number }) => (\n <svg\n className={cn(\"hsk-brand-mark\", className)}\n width={size}\n height={size}\n viewBox=\"0 0 100 100\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-label=\"kiku\"\n >\n <g transform=\"translate(22.7 19) scale(0.62)\" fill=\"currentColor\" fillRule=\"evenodd\">\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" />\n <circle cx=\"55\" cy=\"82\" r=\"3.4\" />\n </g>\n </svg>\n);\n\nconst SparkleIcon = KikuIcon;\n\nconst StopIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"5\" y=\"5\" width=\"14\" height=\"14\" rx=\"2\"/>\n </svg>\n);\n\nconst ExternalIcon = () => (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n);\n\nconst ContinueIcon = () => (\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n);\n\nconst CloseIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n);\n\nconst ChevronRightIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m9 18 6-6-6-6\"/>\n </svg>\n);\n\nconst HistoryIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/>\n <path d=\"M3 3v5h5\"/>\n <path d=\"M12 7v5l4 2\"/>\n </svg>\n);\n\nconst BookmarkIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M19 21 12 16l-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z\"/>\n </svg>\n);\n\nconst TrashIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 6h18\"/>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>\n </svg>\n);\n\nconst SecureShieldIcon = ({ className, size = 18 }: { className?: string; size?: number }) => (\n <svg\n className={className}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n <path d=\"M12 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z\" />\n <path d=\"M12 11v4\" />\n </svg>\n);\n\nconst PaperclipIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/>\n </svg>\n);\n\nconst MicIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/>\n </svg>\n);\n\nconst MicOffIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"2\" y1=\"2\" x2=\"22\" y2=\"22\"/>\n <path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\"/>\n <path d=\"M5 10v2a7 7 0 0 0 12 5\"/>\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\"/>\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\"/>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/>\n </svg>\n);\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\n// Blank canvas by default — the empty state is just the logo + a welcome line,\n// like other chat assistants. Integrators can still pass their own `chips`.\nconst DEFAULT_CHIPS: string[] = [];\n\n// Pull a first name out of a first message (\"John\", \"hey, I'm John\", \"call me\n// Jean-Paul\"). Returns null when the text reads like a real query instead, so a\n// shopper who dives straight into searching is never mistaken for giving a name.\nfunction extractName(raw: string): string | null {\n let s = raw.trim();\n if (!s || s.length > 40 || s.includes('?')) return null;\n s = s.replace(/^(hi|hey|hello|yo)[,!.\\s]+/i, '');\n s = s.replace(/^(i['’]?m|im|my name is|call me|it['’]?s|this is|name['’]?s)\\s+/i, '');\n s = s.trim().replace(/[.!,]+$/, '');\n const words = s.split(/\\s+/);\n if (words.length === 0 || words.length > 3) return null;\n if (!/^[\\p{L}][\\p{L}\\-'’ ]{0,30}$/u.test(s)) return null;\n const q = s.toLowerCase();\n const queryish = ['phone', 'laptop', 'tv', 'cheap', 'best', 'under', 'buy', 'search', 'find', 'show', 'need', 'want', 'price', 'sofa', 'shoe', 'headphone', 'camera', 'gift', 'help'];\n if (queryish.some(w => q.includes(w))) return null;\n const name = words[0];\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n// ─── @kiku Mention System ─────────────────────────────────────────────────────\n\n/**\n * Parses the user's input for an @kiku mention prefix.\n * Returns the resolved intent + a cleaned query (product name only, no @kiku prefix)\n * that gets sent as the actual search text. Returns null if not an @kiku command.\n */\nfunction parseAtKiku(raw: string): { intent: string; cleanQuery: string } | null {\n const trimmed = raw.trim();\n if (!/^@kiku\\b/i.test(trimmed)) return null;\n\n const rest = trimmed.slice(5).trim(); // everything after \"@kiku\"\n\n if (rest === '' || /^(capture|save)\\b/i.test(rest)) {\n return {\n intent: 'capture',\n cleanQuery: rest.replace(/^(capture|save)\\s*/i, '').trim() || trimmed,\n };\n }\n if (/^(history|what have you|show my|my items|what did you|saved|captures|recall)\\b/i.test(rest)) {\n return { intent: 'view_history', cleanQuery: 'show my saved items' };\n }\n if (/^(delete|forget|remove|unsave)\\b/i.test(rest)) {\n return {\n intent: 'delete',\n cleanQuery: rest.replace(/^(delete|forget|remove|unsave)\\s*/i, '').trim() || trimmed,\n };\n }\n // Bare \"@kiku <text>\" defaults to capture\n return { intent: 'capture', cleanQuery: rest || trimmed };\n}\n\n// ─── @kiku Picker Menu ────────────────────────────────────────────────────────\n\ninterface KikuPickerMenuProps {\n sources: ChatSource[];\n referencedIds: string[];\n defaultCurrency: string;\n onCapture: (product: ChatSource) => void;\n onCaptureAll: (products: ChatSource[]) => void;\n onViewHistory: () => void;\n onDelete: () => void;\n onDismiss: () => void;\n}\n\nfunction KikuPickerMenu({\n sources,\n referencedIds,\n defaultCurrency,\n onCapture,\n onCaptureAll,\n onViewHistory,\n onDelete,\n onDismiss,\n}: KikuPickerMenuProps) {\n // Show products that were actually referenced in this conversation\n const discussed = sources.filter(s => s.id && referencedIds.includes(s.id));\n\n return (\n <div\n className=\"hsk-kiku-picker\"\n role=\"menu\"\n aria-label=\"@kiku commands\"\n onMouseDown={e => e.preventDefault()} // keep textarea focused\n >\n {discussed.map((src, i) => (\n <button\n key={src.id ?? i}\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => { onCapture(src); onDismiss(); }}\n >\n <span className=\"hsk-kiku-picker-icon\">\n {src.image ? <img src={src.image} alt=\"\" /> : <BookmarkIcon />}\n </span>\n <span className=\"hsk-kiku-picker-item-name\">{src.name}</span>\n {src.price && (\n <span className=\"hsk-kiku-picker-item-price\">\n {src.currency ?? defaultCurrency} {parseFloat(String(src.price).replace(/[^0-9.]/g, '') || '0').toLocaleString()}\n </span>\n )}\n </button>\n ))}\n {discussed.length > 1 && (\n <button\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => { onCaptureAll(discussed); onDismiss(); }}\n >\n <span className=\"hsk-kiku-picker-icon\"><BookmarkIcon /></span>\n <span className=\"hsk-kiku-picker-item-name\">Capture all ({discussed.length})</span>\n </button>\n )}\n {discussed.length === 0 && (\n <button\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => { onCapture({ name: 'current page', id: undefined }); onDismiss(); }}\n >\n <span className=\"hsk-kiku-picker-icon\"><BookmarkIcon /></span>\n <span className=\"hsk-kiku-picker-item-name\">Capture current page</span>\n </button>\n )}\n <button\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => { onViewHistory(); onDismiss(); }}\n >\n <span className=\"hsk-kiku-picker-icon\"><HistoryIcon /></span>\n <span className=\"hsk-kiku-picker-item-name\">What have you saved?</span>\n </button>\n <button\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => { onDelete(); onDismiss(); }}\n >\n <span className=\"hsk-kiku-picker-icon\"><TrashIcon /></span>\n <span className=\"hsk-kiku-picker-item-name\">Delete this</span>\n </button>\n </div>\n );\n}\n\n// ─── @ Extension Picker Menu ──────────────────────────────────────────────────\n\ninterface AtPickerMenuProps {\n onSelect: (extension: string) => void;\n onDismiss: () => void;\n}\n\nfunction AtPickerMenu({ onSelect, onDismiss }: AtPickerMenuProps) {\n return (\n <div\n className=\"hsk-kiku-picker\"\n role=\"menu\"\n aria-label=\"Extensions\"\n onMouseDown={e => e.preventDefault()} // keep textarea focused\n >\n <button\n className=\"hsk-kiku-picker-item\"\n role=\"menuitem\"\n onClick={() => onSelect('@kiku')}\n >\n <span className=\"hsk-kiku-picker-icon hsk-kiku-picker-icon--accent\"><SparkleIcon /></span>\n <span className=\"hsk-kiku-picker-item-name\">kiku — capture &amp; remember</span>\n </button>\n </div>\n );\n}\n\n// ─── Sources Carousel ──────────────────────────────────────────────────────────\n\ninterface SourcesCarouselProps {\n sources: ChatSource[];\n defaultCurrency: string;\n onSelectSource?: (src: ChatSource) => void;\n onImageClick?: (src: string) => void;\n referencedIds?: string[];\n compact?: boolean;\n}\n\nfunction SourceImg({ src, alt, onImageClick }: { src: string; alt?: string; onImageClick?: (src: string) => void }) {\n const [failed, setFailed] = useState(false);\n if (failed) {\n return (\n <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--hsk-chat-source-bg, rgba(0,0,0,.04))', color: 'var(--hsk-chat-muted, #888)' }}>\n <SparkleIcon />\n </div>\n );\n }\n return (\n <img\n src={src}\n alt={alt ?? ''}\n onError={() => setFailed(true)}\n onClick={onImageClick ? (e) => { e.stopPropagation(); onImageClick(src); } : undefined}\n />\n );\n}\n\nfunction SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClick, referencedIds = [], compact = false }: SourcesCarouselProps) {\n const client = useAkropolysContext();\n const isProperty = client?.vertical === 'property';\n const railRef = useRef<HTMLDivElement>(null);\n const [showNext, setShowNext] = useState(false);\n\n const measure = useCallback(() => {\n const el = railRef.current;\n if (!el) return;\n const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 8;\n setShowNext(el.scrollWidth > el.clientWidth + 4 && !atEnd);\n }, []);\n\n useEffect(() => {\n measure();\n const el = railRef.current;\n if (!el) return;\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n el.addEventListener('scroll', measure, { passive: true });\n return () => { ro.disconnect(); el.removeEventListener('scroll', measure); };\n }, [measure, sources]);\n\n const scrollNext = () => {\n railRef.current?.scrollBy({ left: 170, behavior: 'smooth' });\n };\n\n // Show only the products the answer referenced via <entity_ref>. If it\n // referenced none, show none — never dump raw retrieval candidates, which is\n // what surfaced product cards for questions nobody asked.\n const display = sources.filter(s => s.id && referencedIds.includes(s.id));\n if (display.length === 0) return null;\n\n return (\n <div className={cn(\"hsk-cb-sources-wrap\", compact && \"hsk-cb-sources-wrap--compact\")}>\n <div className=\"hsk-cb-sources\" ref={railRef}>\n {display.map((src, si) => {\n const isReferenced = !!(src.id && referencedIds.includes(src.id));\n return (\n <div\n key={src.id ?? si}\n className={cn(\"hsk-cb-source\", isReferenced && \"hsk-cb-source--referenced\")}\n style={{ animationDelay: `${si * 50}ms` }}\n onClick={() => onSelectSource?.(src)}\n >\n {src.image ? (\n <div className=\"hsk-cb-src-imgwrap\" style={{ position: 'relative' }}>\n <SourceImg src={src.image} alt={src.name} onImageClick={onImageClick} />\n {isReferenced && (\n <div className=\"hsk-cb-source-ref-badge\" title=\"Featured in response\">\n <SparkleIcon size={10} />\n </div>\n )}\n {isProperty && (\n <div style={{\n position: 'absolute',\n top: '6px',\n right: '6px',\n background: 'rgba(14, 14, 15, 0.75)',\n backdropFilter: 'blur(4px)',\n borderRadius: '50%',\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#fbbf24', // Gold sparkle badge\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)'\n }}>\n <SparkleIcon size={12} />\n </div>\n )}\n </div>\n ) : (\n <div className=\"hsk-cb-src-imgwrap-empty\" style={{ position: 'relative' }}>\n <SparkleIcon />\n {isReferenced && (\n <div className=\"hsk-cb-source-ref-badge\" title=\"Featured in response\">\n <SparkleIcon size={10} />\n </div>\n )}\n </div>\n )}\n <div className=\"hsk-cb-src-info\">\n <div className=\"hsk-cb-src-name\">{src.name}</div>\n {src.price && (\n <div className=\"hsk-cb-src-price\">\n {src.currency ?? defaultCurrency}{' '}\n {parseFloat(String(src.price).replace(/[^0-9.]/g, '') || '0').toLocaleString()}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n {showNext && (\n <>\n <div\n className=\"hsk-cb-sources-fade\"\n style={{ background: 'linear-gradient(to right, transparent, var(--hsk-fade-bg, #0e0e0f))' }}\n />\n <button className=\"hsk-cb-sources-next\" onClick={scrollNext} aria-label=\"See more\">\n <ChevronRightIcon />\n </button>\n </>\n )}\n </div>\n );\n}\n\n// ─── Strip markdown tables (used for compare view to avoid duplicate) ──────────\n\nfunction stripMarkdownTables(content: string): string {\n const lines = content.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (line.trim().startsWith('|')) continue; // table row or separator\n out.push(line);\n }\n // Collapse runs of 3+ blank lines down to 2\n return out.join('\\n').replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\n// ─── Smart context pills ──────────────────────────────────────────────────────\n// Shown after every assistant response (when there's no cart action).\n// Pills are generated from the current intent + sources so they're always relevant.\n\nfunction SmartContextPills({\n intent,\n sources,\n onSend,\n loading,\n}: {\n intent: string | null;\n sources: ChatSource[];\n onSend: (text: string) => void;\n loading: boolean;\n}) {\n const client = useAkropolysContext();\n const isProperty = client?.vertical === 'property';\n if (!intent) return null;\n\n const pills: { label: string; query: string; emoji: string }[] = [];\n\n // Find the cheapest product in the sources list\n const cheapest =\n sources.length > 0\n ? sources.reduce((min, s) => {\n const p = parseFloat(String(s.price ?? '').replace(/[^0-9.]/g, ''));\n const m = parseFloat(String(min.price ?? '').replace(/[^0-9.]/g, ''));\n return !isNaN(p) && (isNaN(m) || p < m) ? s : min;\n }, sources[0])\n : null;\n\n const firstName = sources[0]?.name ?? '';\n const firstTwo = sources.slice(0, 2).map(s => s.name);\n\n if (intent === 'search' && sources.length > 0) {\n if (firstTwo.length >= 2) {\n pills.push({\n emoji: '⚖️',\n label: 'Compare top 2',\n query: `Compare the ${firstTwo[0]} and ${firstTwo[1]}`,\n });\n }\n if (cheapest && !isProperty && cheapest.name) {\n const short = cheapest.name.split(' ').slice(0, 3).join(' ');\n pills.push({\n emoji: '💡',\n label: `More on ${short}`,\n query: `Tell me more about the ${cheapest.name}`,\n });\n }\n if (isProperty) {\n pills.push({ emoji: '💰', label: 'Under KSh 5M', query: 'Show me options under KSh 5,000,000' });\n } else {\n pills.push({ emoji: '💰', label: 'Under KSh 20K', query: 'Show me options under KSh 20,000' });\n }\n } else if (intent === 'compare' && sources.length > 0) {\n if (firstName) {\n pills.push({\n emoji: '🔍',\n label: 'Similar options',\n query: isProperty\n ? `Show me more properties similar to the ${firstName}`\n : `Show me more products similar to the ${firstName}`,\n });\n }\n pills.push({ emoji: '💡', label: 'Which is best?', query: 'Which one would you recommend and why?' });\n } else if (intent === 'specs' && sources.length > 0) {\n if (firstName) {\n pills.push({\n emoji: '🔄',\n label: 'Find alternatives',\n query: `What are good alternatives to the ${firstName}?`,\n });\n }\n } else if (intent === 'general') {\n if (isProperty) {\n pills.push({ emoji: '🔍', label: 'Show popular listings', query: 'What are your most popular properties?' });\n } else {\n pills.push({ emoji: '🔍', label: 'Show popular items', query: 'What are your most popular products?' });\n }\n pills.push({ emoji: '💡', label: 'Recommend something', query: 'What do you recommend for me?' });\n }\n\n if (pills.length === 0) return null;\n\n return (\n <div className=\"hsk-action-pills\">\n {pills.map(pill => (\n <button\n key={pill.query}\n className=\"hsk-action-pill\"\n onClick={() => onSend(pill.query)}\n disabled={loading}\n >\n <span className=\"hsk-pill-emoji\">{pill.emoji}</span>\n {pill.label}\n </button>\n ))}\n </div>\n );\n}\n\n// ─── Error helper ──────────────────────────────────────────────────────────────\n\nconst getFriendlyError = (err: any) => {\n let str = '';\n if (typeof err === 'string') str = err;\n else if (err && typeof err === 'object' && err.message) str = err.message;\n else try { str = JSON.stringify(err); } catch { str = String(err); }\n\n const lower = str.toLowerCase();\n if (\n lower.includes('429') ||\n lower.includes('too many requests') ||\n lower.includes('requests per minute limit exceeded') ||\n lower.includes('too_many_requests_error') ||\n lower.includes('request_quota_exceeded') ||\n lower.includes('quota')\n ) {\n return 'The assistant is currently receiving too many requests. Please try again in a few moments.';\n }\n\n if (lower.includes('token limit')) {\n return \"You've reached your usage limit. Please update your billing limits in your dashboard to continue.\";\n }\n\n // Never let a raw status or network failure reach a shopper.\n if (lower.includes('failed to fetch') || lower.includes('networkerror') || lower.includes('request failed')) {\n return \"The assistant couldn't respond just now — please try again in a moment.\";\n }\n\n try {\n const parsed = JSON.parse(str);\n return parsed.error || parsed.message || str;\n } catch {\n return str;\n }\n};\n\n// The kiku key is the shopper's portable, anonymous identity (kiku_<hex>) —\n// server-minted, shown exactly once. Entering the same key on any site (or\n// giving it to an AI agent) opens the same memory. Lost key = lost memory.\nconst KIKU_KEY_REVEAL_SECONDS = 60;\n\n// ─── ChatModal Props ───────────────────────────────────────────────────────────\n\ninterface ChatModalProps extends Pick<KikuButtonProps, 'title' | 'placeholder' | 'backdropColor' | 'backdropBlur' | 'onSelectSource' | 'defaultCurrency' | 'chips' | 'theme' | 'classNames' | 'enableVoice' | 'voiceLang' | 'enableVision' | 'visionCategoryHint'> {\n theme?: 'light' | 'dark' | AkropolysTheme;\n classNames?: any;\n onClose: () => void;\n}\n\n// ─── ChatModal ─────────────────────────────────────────────────────────────────\n\nfunction parseThinking(text: string): { thinking: string; content: string; isComplete: boolean } {\n const openMatch = text.match(/<\\s*thinking\\s*>/i);\n if (!openMatch) {\n return { thinking: '', content: text, isComplete: true };\n }\n\n const openIdx = openMatch.index ?? 0;\n const openTagLength = openMatch[0].length;\n const start = openIdx + openTagLength;\n \n const contentBefore = text.slice(0, openIdx);\n const textAfterOpen = text.slice(start);\n \n const closeMatch = textAfterOpen.match(/<\\/\\s*thinking\\s*>/i);\n if (!closeMatch) {\n return { \n thinking: textAfterOpen, \n content: contentBefore, \n isComplete: false \n };\n }\n\n const closeIdx = closeMatch.index ?? 0;\n const closeTagLength = closeMatch[0].length;\n \n return {\n thinking: textAfterOpen.slice(0, closeIdx),\n content: contentBefore + textAfterOpen.slice(closeIdx + closeTagLength),\n isComplete: true\n };\n}\n\nfunction ThinkingBlock({ text, isComplete, seconds: fixedSeconds }: { text: string; isComplete: boolean; seconds?: number }) {\n const startRef = useRef(Date.now());\n const [seconds, setSeconds] = useState<number | null>(() => (isComplete ? null : 0));\n const [isOpen, setIsOpen] = useState(!isComplete);\n\n // Live-tick while thinking streams; freeze the duration and fold the block\n // away once the answer takes over — the label becomes \"Thought for Xs\".\n useEffect(() => {\n if (isComplete) {\n if (seconds !== null) {\n setSeconds(Math.max(1, Math.round((Date.now() - startRef.current) / 1000)));\n setIsOpen(false);\n }\n return;\n }\n setIsOpen(true);\n const t = setInterval(() => {\n setSeconds(Math.round((Date.now() - startRef.current) / 1000));\n }, 1000);\n return () => clearInterval(t);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isComplete]);\n\n const finalSeconds = fixedSeconds ?? seconds;\n const label = isComplete\n ? (finalSeconds !== null && finalSeconds !== undefined ? `Thought for ${finalSeconds}s` : 'Thought process')\n : `Thinking${seconds ? ` · ${seconds}s` : '…'}`;\n const expandable = !!text;\n\n return (\n <div className={cn('hsk-cb-think', !isComplete && 'hsk-cb-think--live')}>\n <button\n type=\"button\"\n className={cn('hsk-cb-think-head', !expandable && 'hsk-cb-think-head--static')}\n onClick={expandable ? () => setIsOpen(o => !o) : undefined}\n aria-expanded={expandable ? isOpen : undefined}\n >\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={!isComplete ? 'hsk-cb-think-spin' : undefined}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 6v6l4 2\" />\n </svg>\n <span>{label}</span>\n {expandable && <span className={cn('hsk-cb-think-chevron', isOpen && 'hsk-cb-think-chevron--open')}>▶</span>}\n </button>\n {expandable && isOpen && <div className=\"hsk-cb-think-body\">{text}</div>}\n </div>\n );\n}\n\nfunction ChatModal({\n title = 'kiku',\n placeholder = 'Ask me anything…',\n backdropColor,\n backdropBlur,\n onClose,\n onSelectSource,\n defaultCurrency = 'KES',\n chips = DEFAULT_CHIPS,\n theme,\n classNames = {},\n enableVoice = false,\n voiceLang,\n enableVision = false,\n visionCategoryHint,\n}: ChatModalProps) {\n const client = useAkropolysContext();\n const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, stopped, interrupted, continueGenerating, reset, referencedIds } = useKiku();\n const [input, setInput] = useState('');\n const [shopperName, setShopperNameState] = useState<string>(() => {\n try { return client.getShopperName?.() ?? ''; } catch { return ''; }\n });\n const [nameSkipped, setNameSkipped] = useState(false);\n // First-run onboarding: greet, pitch, and ask the shopper's name before any chat.\n const awaitingName = messages.length === 0 && !shopperName && !nameSkipped;\n\n // ── Image attachments ────────────────────────────────────────────────────────\n const [attachments, setAttachments] = useState<ChatAttachment[]>([]);\n const imageInputRef = useRef<HTMLInputElement>(null);\n\n const handleImageFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return;\n Array.from(files).forEach(file => {\n if (!file.type.startsWith('image/')) return;\n const reader = new FileReader();\n reader.onload = (e) => {\n const dataUrl = e.target?.result as string;\n if (dataUrl) {\n setAttachments(prev => [...prev, { type: 'image', data: dataUrl }]);\n }\n };\n reader.readAsDataURL(file);\n });\n };\n\n const removeAttachment = (idx: number) => {\n setAttachments(prev => prev.filter((_, i) => i !== idx));\n };\n\n // ── Voice mode (Web Speech API) ──────────────────────────────────────────────\n const [voiceState, setVoiceState] = useState<'idle' | 'listening' | 'processing'>('idle');\n const recognitionRef = useRef<any>(null);\n const pendingVoiceRef = useRef<string | null>(null); // transcript queued for auto-send\n const hasSpeechAPI = typeof window !== 'undefined' && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);\n\n const startVoice = useCallback(() => {\n if (!hasSpeechAPI || voiceState !== 'idle') return;\n const SR = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;\n const recognition = new SR();\n // Transcribe in the site's language, not a dictated one: developer override\n // → page <html lang> → browser language → English as last resort.\n recognition.lang = voiceLang || document.documentElement.lang || navigator.language || 'en-US';\n // Stream partial results so the user SEES words appear as they speak —\n // without this there's no feedback that anything was captured until the end.\n recognition.interimResults = true;\n recognition.maxAlternatives = 1;\n recognitionRef.current = recognition;\n\n recognition.onstart = () => setVoiceState('listening');\n recognition.onresult = (event: any) => {\n let finalText = '';\n let interimText = '';\n for (let i = 0; i < event.results.length; i++) {\n const seg = event.results[i][0].transcript;\n if (event.results[i].isFinal) finalText += seg;\n else interimText += seg;\n }\n // Live feedback: show the (final + in-progress) text in the input box.\n const live = (finalText + ' ' + interimText).trim();\n if (live) setInput(live);\n // Only auto-send once we have a finalized transcript.\n if (finalText.trim()) {\n pendingVoiceRef.current = finalText.trim();\n setVoiceState('processing');\n }\n };\n recognition.onerror = (event: any) => {\n // Surface the cause (most often denied mic permission or no speech) so the\n // user isn't left guessing whether it worked.\n const err = event?.error;\n if (err === 'not-allowed' || err === 'service-not-allowed') {\n setInput('Microphone access was blocked — enable it in your browser to use voice.');\n } else if (err === 'no-speech') {\n setInput(\"Didn't catch that — tap the mic and try again.\");\n }\n setVoiceState('idle');\n };\n recognition.onend = () => {\n // Only reset if we didn't already move to processing\n setVoiceState(prev => prev === 'listening' ? 'idle' : prev);\n };\n recognition.start();\n }, [hasSpeechAPI, voiceState, voiceLang]);\n\n const stopVoice = useCallback(() => {\n recognitionRef.current?.stop();\n setVoiceState('idle');\n }, []);\n\n // Clean up recognition on unmount\n useEffect(() => {\n return () => recognitionRef.current?.abort();\n }, []);\n\n // No vertical pre-determination: chips and placeholder are whatever the\n // integrator passed (blank by default). One widget can't guess what a given\n // site sells, so it never assumes.\n const activeChips = chips;\n const activeTitle = title;\n const activePlaceholder = awaitingName ? 'Type your name…' : placeholder;\n\n\n const [selectedProduct, setSelectedProduct] = useState<ChatSource | null>(null);\n const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);\n const [markupSrc, setMarkupSrc] = useState<string | null>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [keyInput, setKeyInput] = useState('');\n const [keyPhase, setKeyPhase] = useState<'idle' | 'prompt_key'>('idle');\n const [mintedKey, setMintedKey] = useState<string | null>(null);\n const [mintedPub, setMintedPub] = useState<string | null>(null);\n const [copied, setCopied] = useState<string | null>(null);\n\n const copyValue = (value: string, which: string) => {\n try { navigator.clipboard?.writeText(value); } catch { /* ignore */ }\n setCopied(which);\n setTimeout(() => setCopied(c => (c === which ? null : c)), 1600);\n };\n const [keyCountdown, setKeyCountdown] = useState(KIKU_KEY_REVEAL_SECONDS);\n const [minting, setMinting] = useState(false);\n const [showKikuPicker, setShowKikuPicker] = useState(false);\n const [showAtPicker, setShowAtPicker] = useState(false);\n\n // React to lastAction from chat\n useEffect(() => {\n if (!lastAction) return;\n if (lastAction.type === 'request_kiku_key') {\n setKeyPhase('prompt_key');\n }\n }, [lastAction]);\n\n // Show-once countdown: the minted key is visible for a fixed window, then\n // gone for good — it stays active on this device, but is never shown again.\n useEffect(() => {\n if (!mintedKey) return;\n setKeyCountdown(KIKU_KEY_REVEAL_SECONDS);\n const t = setInterval(() => {\n setKeyCountdown(s => {\n if (s <= 1) {\n clearInterval(t);\n setMintedKey(null);\n setMintedPub(null);\n return 0;\n }\n return s - 1;\n });\n }, 1000);\n return () => clearInterval(t);\n }, [mintedKey]);\n\n const { themeAttr: hskThemeAttr, vars: customStyles } = resolveTheme(theme);\n\n // Retry the interrupted request (e.g. the capture) under the new identity.\n // Goes through handleSend so an \"@kiku …\" prefix is re-parsed back into a\n // forced intent instead of being sent as literal query text.\n const retryLastMessage = async () => {\n const lastUserMsg = [...messages].reverse().find(m => m.role === 'user');\n if (lastUserMsg) await handleSend(lastUserMsg.content);\n };\n\n // Returning shopper: paste an existing public id.\n const handleUseExistingKey = async () => {\n const pub = keyInput.trim();\n if (!pub) return;\n client.setKikuPub(pub);\n setKeyInput('');\n setKeyPhase('idle');\n await retryLastMessage();\n };\n\n // New shopper: mint server-side. The secret is revealed once; the public id\n // is stored for saving across sites.\n const handleCreateKey = async () => {\n if (minting) return;\n setMinting(true);\n try {\n const { secret, publicId } = await client.mintKikuKey();\n setMintedKey(secret);\n setMintedPub(publicId);\n setKeyPhase('idle');\n await retryLastMessage();\n } catch {\n // mint failed — keep the prompt open so the shopper can try again\n } finally {\n setMinting(false);\n }\n };\n\n // Auto-scroll. A freshly sent user message is pinned to the top of the\n // view (like Claude) so the question and the start of the answer are both\n // visible without scrolling. While a response streams in, we only follow it\n // to the bottom if the user is already pinned there — this lets them freely\n // scroll up to re-read earlier messages.\n const msgsContainerRef = useRef<HTMLDivElement>(null);\n const messageRefs = useRef<(HTMLDivElement | null)[]>([]);\n useEffect(() => {\n const container = msgsContainerRef.current;\n if (!container) return;\n const lastMsg = messages[messages.length - 1];\n if (lastMsg?.role === 'user') {\n messageRefs.current[messages.length - 1]?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n return;\n }\n const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;\n if (distanceFromBottom < 120) {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n }\n }, [messages, loading, selectedProduct]);\n\n // Lock the host page's own scroll while the panel is open, so only the\n // widget's internal message list scrolls — otherwise both scrollbars show.\n useEffect(() => {\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => { document.body.style.overflow = prev; };\n }, []);\n\n useEffect(() => {\n const h = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (lightboxSrc) { setLightboxSrc(null); return; }\n onClose();\n };\n document.addEventListener('keydown', h);\n return () => document.removeEventListener('keydown', h);\n }, [lightboxSrc, onClose]);\n\n const handleReset = useCallback(() => {\n reset();\n setKeyPhase('idle');\n }, [reset]);\n\n const handleSourceClick = (src: ChatSource) => {\n setSelectedProduct(src);\n onSelectSource?.(src);\n // If the assistant just asked a question (\"Which sofa would you like…?\"),\n // clicking a card answers it with that product instead of pivoting to specs.\n const lastAssistant = [...messages].reverse().find(m => m.role === 'assistant');\n if (lastAssistant && lastAssistant.content.trim().endsWith('?')) {\n send(`The ${src.name}`);\n return;\n }\n const q = `Tell me more about the ${src.name}${src.price ? ` (${src.currency ?? defaultCurrency} ${src.price})` : ''} — what are its key specs, who is it best for, and is it worth buying?`;\n send(q);\n };\n\n const handleSend = async (text?: string, extraAttachments?: ChatAttachment[], forcedIntent?: string, captureTargets?: CaptureTarget[]) => {\n const raw = (text ?? input).trim();\n if (!raw || loading) return;\n\n // Onboarding: the first thing typed is treated as the shopper's name when it\n // reads like one; we store it and greet them, with no backend call. If it\n // reads like a query, we skip the name step and search normally.\n if (awaitingName) {\n const name = extractName(raw);\n if (name) {\n try { client.setShopperName?.(name); } catch { /* ignore */ }\n setShopperNameState(name);\n setInput('');\n if (textareaRef.current) textareaRef.current.style.height = 'auto';\n return;\n }\n setNameSkipped(true);\n }\n\n const kiku = parseAtKiku(raw);\n const q = kiku ? kiku.cleanQuery : raw;\n const resolvedForcedIntent = forcedIntent ?? kiku?.intent;\n\n setSelectedProduct(null);\n setShowKikuPicker(false);\n setShowAtPicker(false);\n setInput('');\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n }\n const toSend = extraAttachments ?? attachments;\n setAttachments([]);\n await send(q, raw /* displayQuery */, toSend.length > 0 ? toSend : undefined, resolvedForcedIntent, captureTargets);\n };\n\n const handleSelectExtension = (ext: string) => {\n setInput(ext + ' ');\n setShowAtPicker(false);\n setShowKikuPicker(true);\n if (textareaRef.current) {\n textareaRef.current.focus();\n }\n };\n\n // Convenience wrappers for @kiku picker actions\n const handleKikuCapture = useCallback((product: ChatSource) => {\n const name = product.name || '';\n const display = `@kiku capture${name ? ' ' + name : ''}`;\n const q = name || 'capture current page';\n setInput('');\n setSelectedProduct(null);\n const toSend = attachments;\n setAttachments([]);\n send(q, display, toSend.length > 0 ? toSend : undefined, 'capture');\n }, [attachments, send]);\n\n const handleKikuCaptureAll = useCallback((products: ChatSource[]) => {\n const targets: CaptureTarget[] = products\n .filter(p => p.id)\n .map(p => ({\n name: p.name || '',\n url: (p as any).url || '',\n image: p.image || '',\n price: p.price ? String(p.price) : '',\n currency: p.currency || defaultCurrency,\n }));\n const names = products.map(p => p.name).filter(Boolean).join(', ');\n const display = `@kiku capture all (${products.length} items)`;\n setInput('');\n setSelectedProduct(null);\n setAttachments([]);\n send(names || 'capture all', display, undefined, 'capture_all', targets);\n }, [defaultCurrency, send]);\n\n const handleKikuViewHistory = useCallback(() => {\n const display = '@kiku what have you saved?';\n setInput('');\n setSelectedProduct(null);\n setAttachments([]);\n send('show my saved items', display, undefined, 'view_history');\n }, [send]);\n\n const handleKikuDelete = useCallback(() => {\n const display = '@kiku delete this';\n setInput('');\n setSelectedProduct(null);\n setAttachments([]);\n send('delete this', display, undefined, 'delete');\n }, [send]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Escape' && showKikuPicker) { e.preventDefault(); setShowKikuPicker(false); return; }\n if (e.key === 'Escape' && showAtPicker) { e.preventDefault(); setShowAtPicker(false); return; }\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); }\n };\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const val = e.target.value;\n setInput(val);\n const trimmed = val.trim();\n // Show @ picker when input is exactly '@'\n setShowAtPicker(trimmed === '@');\n // Show the @kiku picker only while the mention is bare — once the shopper\n // types a query past it, they've chosen to write instead of pick, so it hides.\n setShowKikuPicker(/^@kiku\\s*$/i.test(trimmed));\n const t = e.target;\n t.style.height = 'auto';\n t.style.height = `${Math.min(t.scrollHeight, 140)}px`;\n };\n\n // Auto-send voice transcript once processing state is reached\n useEffect(() => {\n if (voiceState !== 'processing') return;\n const transcript = pendingVoiceRef.current;\n if (!transcript) { setVoiceState('idle'); return; }\n pendingVoiceRef.current = null;\n // Brief delay so user sees the transcript fill in before it fires\n const timer = setTimeout(() => {\n setVoiceState('idle');\n handleSend(transcript);\n }, 400);\n return () => clearTimeout(timer);\n }, [voiceState]);\n\n\n const blurVal = typeof backdropBlur === 'number' ? `${backdropBlur}px` : (backdropBlur ?? '20px');\n\n const displayMessages = messages;\n\n return (\n <div\n className={cn(\"hsk-cb-overlay\", classNames.overlay)}\n onClick={onClose}\n data-hsk-theme={hskThemeAttr}\n style={{\n backdropFilter: `blur(${blurVal})`,\n WebkitBackdropFilter: `blur(${blurVal})`,\n ...(backdropColor ? { background: backdropColor } : {}),\n ...customStyles,\n }}\n >\n <div\n className={cn(\"hsk-cb-panel\", classNames.panel)}\n onClick={e => {\n e.stopPropagation();\n const target = e.target as HTMLElement;\n if (target.tagName === 'IMG' && (target.classList.contains('hsk-markdown-img') || target.classList.contains('hsk-cb-user-img-thumb'))) {\n const src = (target as HTMLImageElement).src;\n if (src) setLightboxSrc(src);\n }\n }}\n >\n {lightboxSrc && (\n <div className=\"hsk-lightbox\" onClick={() => setLightboxSrc(null)}>\n <button className=\"hsk-lightbox-close\" onClick={() => setLightboxSrc(null)} aria-label=\"Close image\">\n <CloseIcon />\n </button>\n <img src={lightboxSrc} alt=\"\" className=\"hsk-lightbox-img\" onClick={e => e.stopPropagation()} />\n </div>\n )}\n\n {markupSrc && (\n <div className=\"hsk-markup-overlay\">\n <MarkupEditor\n src={markupSrc}\n onCancel={() => setMarkupSrc(null)}\n onSend={(dataUrl, instruction) => {\n setMarkupSrc(null);\n handleSend(\n instruction || 'Apply the change indicated by the markings on the image.',\n [{ type: 'image', data: dataUrl, annotated: true }],\n );\n }}\n />\n </div>\n )}\n\n {/* ── Main Chat Area ── */}\n <div className=\"hsk-cb-main\">\n\n {/* Top bar */}\n <div className=\"hsk-cb-topbar\">\n <div className=\"hsk-cb-topbar-left\">\n <span className=\"hsk-cb-topbar-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </span>\n <div>\n <div className=\"hsk-cb-topbar-title\">{activeTitle}</div>\n </div>\n </div>\n <div className=\"hsk-cb-topbar-actions\">\n {messages.length > 0 && (\n <button className=\"hsk-cb-topbar-btn\" onClick={handleReset}>Clear chat</button>\n )}\n <button className=\"hsk-cb-close\" onClick={onClose} aria-label=\"Close\">\n <CloseIcon />\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div className=\"hsk-cb-msgs\" ref={msgsContainerRef}>\n {displayMessages.length === 0 ? (\n <div className=\"hsk-cb-empty\">\n {awaitingName ? (\n <>\n <h2 className=\"hsk-cb-hello\">Hi, I'm <b>kiku</b>.</h2>\n <p className=\"hsk-cb-hello-lead\">I can search, visualize, or capture anything for you — on this site or any other.</p>\n <p className=\"hsk-cb-hello-ask\">What should I call you?</p>\n <button className=\"hsk-cb-hello-skip\" onClick={() => setNameSkipped(true)}>Skip for now</button>\n </>\n ) : shopperName ? (\n <>\n <h2 className=\"hsk-cb-hello\">Hi, {shopperName}.</h2>\n <p className=\"hsk-cb-hello-lead\">What can I find for you today?</p>\n </>\n ) : (\n <>\n <h2 className=\"hsk-cb-hello\">Hi, I'm <b>kiku</b>.</h2>\n <p className=\"hsk-cb-hello-lead\">Ask me to search, visualize, or capture anything — I look across the whole site in real time.</p>\n </>\n )}\n {!awaitingName && activeChips.length > 0 && (\n <div className=\"hsk-cb-chips\">\n {activeChips.map(chip => (\n <button\n key={chip}\n className=\"hsk-cb-chip\"\n onClick={() => handleSend(chip)}\n >\n {chip}\n </button>\n ))}\n </div>\n )}\n </div>\n ) : (\n displayMessages.map((msg: ChatMessage, idx: number) => {\n const isLast = idx === displayMessages.length - 1;\n const isLastUser = msg.role === 'user' && !displayMessages.slice(idx + 1).some(m => m.role === 'user');\n const isUser = msg.role === 'user';\n // The matrix can only stand in for the LLM's table when BOTH compared\n // products came from this turn's retrieval; a follow-up compare against\n // an item from memory must keep the markdown table.\n const compareSources = sources.filter(s => s.id && referencedIds.includes(s.id));\n const showMatrix = isLast && lastIntent === 'compare' && compareSources.length >= 2;\n const displayContent =\n !isUser && showMatrix ? stripMarkdownTables(msg.content) : msg.content;\n return (\n <div key={idx} className=\"hsk-cb-msg-group\" ref={(el) => { messageRefs.current[idx] = el; }}>\n {isUser ? (\n <div className={`hsk-cb-user-msg${isLastUser ? ' hsk-sent' : ''}`}>\n {/* Image thumbnails in user bubble */}\n {msg.images && msg.images.length > 0 && (\n <div className=\"hsk-cb-user-imgs\">\n {msg.images.map((img, i) => (\n <img key={i} src={img} alt={`attachment ${i + 1}`} className=\"hsk-cb-user-img-thumb\" />\n ))}\n </div>\n )}\n {msg.content && (\n <div className=\"hsk-cb-user-bubble\">\n {/^@kiku\\b/i.test(msg.content) ? (\n <>\n <span className=\"hsk-kiku-badge\">@kiku</span>\n {msg.content.replace(/^@kiku\\s*/i, '')}\n </>\n ) : msg.content}\n </div>\n )}\n </div>\n ) : (\n <div className=\"hsk-cb-ai-msg\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-ai-body\">\n {(() => {\n // Structured thinking (SSE event) is primary; parseThinking stays as a\n // net for legacy inline tags in restored histories.\n const parsed = parseThinking(displayContent);\n const thinking = msg.thinking || parsed.thinking;\n const content = parsed.content;\n const isComplete = msg.thinking\n ? (content.length > 0 || !(isLast && streaming))\n : parsed.isComplete;\n return (\n <>\n {(thinking || msg.thoughtForSeconds != null) && (\n <ThinkingBlock text={thinking} isComplete={isComplete} seconds={msg.thoughtForSeconds} />\n )}\n {content && (\n <div className=\"hsk-cb-ai-text\">\n {renderMarkdown(content, isLast && streaming)}\n {isLast && streaming && (\n <span style={{ display: 'inline-block', width: '0.5em', height: '1.05em', marginLeft: '2px', verticalAlign: 'text-bottom', background: 'currentColor', opacity: 0.55, borderRadius: '1px' }} />\n )}\n </div>\n )}\n </>\n );\n })()}\n\n {msg.visualizing && (\n <div className=\"hsk-cb-viz hsk-cb-viz--loading\">\n <span className=\"hsk-cb-viz-spinner\" />\n <span>{msg.visualizingText || 'Visualizing…'}</span>\n </div>\n )}\n {msg.visualization && (\n <div className=\"hsk-cb-viz\">\n <div className=\"hsk-cb-viz-imgwrap\">\n {msg.visualizationType === 'video' || msg.visualization.includes('/videos/') ? (\n <video\n src={msg.visualization}\n controls\n autoPlay\n loop\n muted\n playsInline\n className=\"hsk-markdown-video\"\n style={{ display: 'block', maxHeight: '400px', objectFit: 'contain', width: '100%' }}\n />\n ) : (\n <img\n src={msg.visualization}\n alt=\"Product visualized in your photo\"\n className=\"hsk-markdown-img\"\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n )}\n {isLast && !streaming && (msg.visualizationType !== 'video' && !msg.visualization.includes('/videos/')) && (\n <button className=\"hsk-cb-viz-mark\" onClick={() => setMarkupSrc(msg.visualization!)}>\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 20h9\" /><path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z\" />\n </svg>\n Mark &amp; edit\n </button>\n )}\n </div>\n <div className=\"hsk-cb-viz-disclaimer\">\n {msg.visualizationType === 'video' || msg.visualization.includes('/videos/') ?\n \"AI-generated video makeover — colors, size and movement may differ from the real product.\" :\n \"AI-generated preview — colours, size and placement may differ from the real product.\"\n }\n </div>\n </div>\n )}\n\n {/* Owner-authored reference images (directed knowledge) — structured, never model-pasted */}\n {!isUser && (msg.knowledgeImages?.length ?? 0) > 0 && (\n <div className=\"hsk-cb-kimgs\">\n {msg.knowledgeImages!.map((ref) => (\n <div key={ref.entryId} className=\"hsk-cb-kimg-group\">\n <div className=\"hsk-cb-kimg-grid\">\n {ref.images.map((img, i) => (\n <img\n key={i}\n src={img.url}\n alt={img.note || ref.title || 'Reference image'}\n className=\"hsk-cb-kimg\"\n loading=\"lazy\"\n onClick={() => setLightboxSrc(img.url)}\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\n />\n ))}\n </div>\n {(ref.title || ref.images[0]?.note) && (\n <div className=\"hsk-cb-kimg-caption\">{ref.title || ref.images[0]?.note}</div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* Comparison matrix — replaces the markdown table when comparing products */}\n {showMatrix && (\n <ComparisonMatrix sources={compareSources} defaultCurrency={defaultCurrency} />\n )}\n\n {(() => {\n const msgReferencedIds = isLast ? referencedIds : (msg.referencedIds ?? []);\n const msgSources = isLast ? sources : (msg.sources ?? []);\n // Gate on this message's own intent — the live lastAction hid every earlier carousel.\n const msgIntent = isLast ? lastIntent : msg.intent;\n const hiddenIntent = msgIntent === 'compare' || msgIntent === 'capture' ||\n msgIntent === 'capture_all' || msgIntent === 'delete' || msgIntent === 'view_history';\n const showCarousel = msgReferencedIds.length > 0 && !hiddenIntent &&\n (!isLast || lastAction?.type !== 'request_kiku_key');\n return showCarousel && (\n <SourcesCarousel\n sources={msgSources}\n defaultCurrency={defaultCurrency}\n onSelectSource={handleSourceClick}\n onImageClick={setLightboxSrc}\n referencedIds={msgReferencedIds}\n compact={!!msg.visualization}\n />\n );\n })()}\n\n {/* Registered action link — the site executes; we just route */}\n {isLast && !loading && lastAction?.url && (\n <div className=\"hsk-action-pills\">\n <a className=\"hsk-action-pill\" href={lastAction.url}>\n {String(lastAction.type || 'continue').replace(/_/g, ' ')} →\n </a>\n </div>\n )}\n\n {/* Smart context pills — built only from products the answer referenced */}\n {isLast && !loading && (\n <SmartContextPills\n intent={lastIntent}\n sources={sources.filter(s => s.id && referencedIds.includes(s.id))}\n onSend={handleSend}\n loading={loading}\n />\n )}\n </div>\n </div>\n )}\n </div>\n );\n })\n )}\n\n {/* Selected product pinned card — shows while LLM fetches details */}\n {selectedProduct && loading && (\n <div\n className=\"hsk-cb-selected-product\"\n onClick={() => selectedProduct.url && window.open(selectedProduct.url, '_blank')}\n >\n {selectedProduct.image && (\n <img className=\"hsk-cb-selected-img\" src={selectedProduct.image} alt={selectedProduct.name} />\n )}\n <div className=\"hsk-cb-selected-info\">\n <div className=\"hsk-cb-selected-name\">{selectedProduct.name}</div>\n {selectedProduct.price && (\n <div className=\"hsk-cb-selected-price\">\n {selectedProduct.currency ?? defaultCurrency} {parseFloat(String(selectedProduct.price ?? '').replace(/[^0-9.]/g, '') || '0').toLocaleString()}\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Shown only while waiting for the server; stops the moment tokens start streaming in. */}\n {loading && !streaming && (\n <div className=\"hsk-cb-typing-row\" style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div className=\"hsk-cb-thinking-icon\">\n <svg className=\"hsk-brand-mark\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" transform=\"translate(22.7 19) scale(0.62)\" fillRule=\"evenodd\" />\n </svg>\n <svg className=\"hsk-brand-mark hsk-brand-mark--sheen\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" transform=\"translate(22.7 19) scale(0.62)\" fillRule=\"evenodd\" />\n </svg>\n <span className=\"hsk-handle-orbit\">\n <span className=\"hsk-handle-ring\">\n <span className=\"hsk-handle-ball\" />\n <span className=\"hsk-handle-ball\" />\n <span className=\"hsk-handle-ball\" />\n <span className=\"hsk-handle-ball\" />\n <span className=\"hsk-handle-ball\" />\n </span>\n </span>\n <span className=\"hsk-handle-rest\" />\n </div>\n <span className=\"hsk-cb-thinking-text\">Thinking…</span>\n </div>\n )}\n\n {/* Memory lives on mimi (reads need the secret). Surface it as a pill\n so the link can't be lost inside a paragraph. */}\n {lastAction?.type === 'open_memory' && lastAction.url && !loading && !streaming && (\n <a\n className=\"hsk-cb-memory-pill\"\n href={String(lastAction.url)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Open my memory on mimi\n <ExternalIcon />\n </a>\n )}\n\n {/* Resume affordance after a manual stop or a mid-answer interruption.\n A stop before the first token (last message still the user's) resends\n the question; with a partial answer it resumes into the same bubble. */}\n {(stopped || interrupted) && !loading && !streaming && messages.length > 0 && (\n <div className=\"hsk-cb-stopped\">\n <span className=\"hsk-cb-stopped-label\">\n {stopped ? 'You stopped this response.' : 'This response was interrupted.'}\n </span>\n <button className=\"hsk-cb-continue\" onClick={continueGenerating}>\n <ContinueIcon />\n {messages[messages.length - 1]?.role === 'assistant' ? 'Continue generating' : 'Generate response'}\n </button>\n </div>\n )}\n\n {error && <div className=\"hsk-cb-error\">{getFriendlyError(error)}</div>}\n\n {/* Carry-your-items prompt: paste an existing kiku key, or mint a\n new one (shown exactly once). No phone, no account. */}\n {keyPhase === 'prompt_key' && (\n <div className=\"hsk-cb-ai-msg\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-ai-body\">\n <div className=\"hsk-cb-ai-text\">\n <div className=\"hsk-cb-phone-form\">\n <label className=\"hsk-cb-phone-label\">Paste your public id — or create one</label>\n <input\n type=\"text\"\n className=\"hsk-cb-phone-input\"\n placeholder=\"your public id…\"\n value={keyInput}\n onChange={e => setKeyInput(e.target.value)}\n onKeyDown={e => e.key === 'Enter' && handleUseExistingKey()}\n autoFocus\n />\n <div style={{ display: 'flex', gap: 8 }}>\n <button className=\"hsk-cb-phone-submit\" onClick={handleUseExistingKey} disabled={!keyInput.trim()}>\n Use my id\n </button>\n <button className=\"hsk-cb-phone-submit\" onClick={handleCreateKey} disabled={minting}>\n {minting ? 'Creating…' : \"I'm new — create one\"}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {mintedKey && (\n <div className=\"hsk-cb-ai-msg\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-ai-body\">\n <div className=\"hsk-cb-ai-text\">\n <div style={{ padding: '12px 14px', border: '1px solid var(--hsk-border, #e5e5e5)', borderRadius: 'var(--hsk-border-radius, 0px)', display: 'flex', flexDirection: 'column', gap: 12 }}>\n <div>\n <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 4 }}>Your secret — shown only once</div>\n <code style={{ display: 'block', fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: 'break-all' }}>{mintedKey}</code>\n <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>\n <button className=\"hsk-cb-phone-submit\" style={{ padding: '4px 10px' }} onClick={() => copyValue(mintedKey, 'secret')}>\n {copied === 'secret' ? 'Copied' : 'Copy secret'}\n </button>\n <span style={{ fontSize: 11, opacity: 0.7 }}>\n Keep it private — use it to unlock your memory at mimi.akropolys.cloud. If lost, the memory is lost with it.\n </span>\n </div>\n </div>\n {mintedPub && (\n <div>\n <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 4 }}>Your public id</div>\n <code style={{ display: 'block', fontSize: 13, fontWeight: 600, marginBottom: 6, wordBreak: 'break-all', opacity: 0.85 }}>{mintedPub}</code>\n <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>\n <button className=\"hsk-cb-phone-submit\" style={{ padding: '4px 10px' }} onClick={() => copyValue(mintedPub, 'pub')}>\n {copied === 'pub' ? 'Copied' : 'Copy id'}\n </button>\n <span style={{ fontSize: 11, opacity: 0.7 }}>\n Paste this on any site to keep saving to the same memory.\n </span>\n </div>\n </div>\n )}\n <div style={{ fontSize: 11, opacity: 0.6 }}>Hidden in {keyCountdown}s.</div>\n </div>\n </div>\n </div>\n </div>\n )}\n\n <div ref={bottomRef} style={{ height: 1 }} />\n </div>\n\n <div className=\"hsk-cb-input-wrap\">\n {/* @ extension picker — floats above the input area */}\n {showAtPicker && (\n <AtPickerMenu\n onSelect={handleSelectExtension}\n onDismiss={() => setShowAtPicker(false)}\n />\n )}\n {/* @kiku command picker — floats above the input area */}\n {showKikuPicker && (\n <KikuPickerMenu\n sources={sources}\n referencedIds={referencedIds}\n defaultCurrency={defaultCurrency}\n onCapture={handleKikuCapture}\n onCaptureAll={handleKikuCaptureAll}\n onViewHistory={handleKikuViewHistory}\n onDelete={handleKikuDelete}\n onDismiss={() => setShowKikuPicker(false)}\n />\n )}\n {/* Image attachment strip */}\n {attachments.length > 0 && (\n <div className=\"hsk-cb-img-strip\">\n {attachments.map((att, i) => (\n <div key={i} className=\"hsk-cb-img-thumb-wrap\">\n <img src={att.data} alt={`attachment ${i + 1}`} className=\"hsk-cb-img-thumb\" />\n <button\n className=\"hsk-cb-img-thumb-remove\"\n onClick={() => removeAttachment(i)}\n aria-label=\"Remove image\"\n >\n ×\n </button>\n </div>\n ))}\n </div>\n )}\n <div className=\"hsk-cb-input-box\">\n {/* Hidden file input */}\n <input\n ref={imageInputRef}\n type=\"file\"\n accept=\"image/*\"\n multiple\n style={{ display: 'none' }}\n onChange={e => handleImageFiles(e.target.files)}\n />\n {/* Attach button — only shown if vision is enabled */}\n {enableVision && (\n <button\n className=\"hsk-cb-attach-btn\"\n onClick={() => imageInputRef.current?.click()}\n disabled={loading}\n aria-label=\"Attach image\"\n title=\"Attach image\"\n >\n <PaperclipIcon />\n </button>\n )}\n <textarea\n ref={textareaRef}\n className={cn(\"hsk-cb-textarea\", classNames.input)}\n value={input}\n onChange={handleInput}\n onKeyDown={handleKeyDown}\n placeholder={\n voiceState === 'listening' ? '🎙️ Listening… tap the mic to stop'\n : voiceState === 'processing' ? 'Got it — sending…'\n : activePlaceholder\n }\n rows={1}\n disabled={loading}\n autoFocus\n />\n {/* Voice button — only shown if SpeechRecognition is supported and enabled */}\n {hasSpeechAPI && enableVoice && (\n <button\n className={cn(\n \"hsk-cb-mic-btn\",\n voiceState === 'listening' && \"hsk-cb-mic-btn--listening\",\n voiceState === 'processing' && \"hsk-cb-mic-btn--processing\"\n )}\n onClick={voiceState === 'idle' ? startVoice : stopVoice}\n disabled={loading}\n aria-label={voiceState === 'idle' ? 'Start voice input' : 'Stop recording'}\n title={voiceState === 'idle' ? 'Voice input' : 'Stop'}\n >\n {voiceState === 'listening' ? <MicOffIcon /> : <MicIcon />}\n {voiceState === 'listening' && <span className=\"hsk-cb-mic-pulse\" />}\n </button>\n )}\n {(loading || streaming) ? (\n <button\n className={cn(\"hsk-cb-send\", \"hsk-cb-send--stop\", classNames.sendButton)}\n onClick={stop}\n aria-label=\"Stop generating\"\n title=\"Stop generating\"\n >\n <StopIcon />\n </button>\n ) : (\n <button\n className={cn(\"hsk-cb-send\", classNames.sendButton)}\n onClick={() => handleSend()}\n disabled={!input.trim() && attachments.length === 0}\n aria-label=\"Send message\"\n >\n <ArrowUpIcon />\n </button>\n )}\n </div>\n <div className=\"hsk-cb-hint\">kiku · searches the whole catalogue in real time</div>\n </div>\n\n </div>{/* end .hsk-cb-main */}\n\n </div>\n </div>\n );\n}\n\n// ─── KikuButton (public export) ─────────────────────────────────────────────\n\nexport function KikuButton({\n label,\n title,\n placeholder,\n backdropColor,\n backdropBlur,\n className,\n onSelectSource,\n defaultCurrency,\n chips,\n theme,\n classNames = {},\n enableVoice = false,\n voiceLang,\n enableVision = false,\n visionCategoryHint,\n}: KikuButtonProps) {\n const [open, setOpen] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n\n if (typeof window !== 'undefined' && !(window as any).__akropolys_nav_patched) {\n (window as any).__akropolys_nav_patched = true;\n const originalPush = window.history.pushState;\n const originalReplace = window.history.replaceState;\n\n window.history.pushState = function(...args) {\n originalPush.apply(this, args);\n window.dispatchEvent(new CustomEvent('akropolys:navigation'));\n };\n\n window.history.replaceState = function(...args) {\n originalReplace.apply(this, args);\n window.dispatchEvent(new CustomEvent('akropolys:navigation'));\n };\n }\n\n const handleNavigation = () => {\n setOpen(false);\n };\n\n window.addEventListener('popstate', handleNavigation);\n window.addEventListener('akropolys:navigation', handleNavigation);\n\n return () => {\n window.removeEventListener('popstate', handleNavigation);\n window.removeEventListener('akropolys:navigation', handleNavigation);\n };\n }, []);\n\n const { themeAttr: hskThemeAttr, vars: customStyles } = resolveTheme(theme);\n\n return (\n <>\n <button\n className={cn(\"hsk-cb-btn\", classNames.button, className)}\n onClick={() => setOpen(true)}\n style={customStyles}\n data-hsk-theme={hskThemeAttr}\n aria-label=\"Open AI chat\"\n >\n <span className=\"hsk-cb-btn-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </span>\n {label !== undefined ? label : null}\n </button>\n {open && mounted && createPortal(\n <ChatModal\n title={title}\n placeholder={placeholder}\n backdropColor={backdropColor}\n backdropBlur={backdropBlur}\n onClose={() => setOpen(false)}\n onSelectSource={onSelectSource}\n defaultCurrency={defaultCurrency}\n chips={chips}\n theme={theme}\n classNames={classNames}\n enableVoice={enableVoice}\n voiceLang={voiceLang}\n enableVision={enableVision}\n visionCategoryHint={visionCategoryHint}\n />,\n document.body\n )}\n </>\n );\n}\n","import React from 'react';\nimport type { ChatSource } from '@akropolys/sdk';\nimport { resolveDisplayFields } from '@akropolys/sdk';\n\nexport interface ComparisonMatrixProps {\n sources: ChatSource[];\n defaultCurrency?: string;\n displayConfig?: Record<string, string>;\n}\n\ninterface Row {\n label: string;\n values: (string | null)[];\n type?: 'image' | 'price' | 'availability' | 'text';\n bestIdx?: number;\n}\n\nfunction normalizeKey(key: string): string {\n let s = key.replace(/[_-]+/g, ' ');\n s = s.replace(/([a-z])([A-Z])/g, '$1 $2');\n return s.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n}\n\nfunction getBaseGroup(normalized: string): string {\n const norm = normalized.toLowerCase().trim();\n if (norm.startsWith('salary') || norm.startsWith('pay') || norm.startsWith('wage')) {\n return 'Salary';\n }\n if (norm.startsWith('price') || norm.startsWith('cost') || norm.startsWith('rate')) {\n return 'Price';\n }\n if (norm.startsWith('location') || norm.startsWith('address') || norm.startsWith('city')) {\n return 'Location';\n }\n if (norm.startsWith('image') || norm.startsWith('photo') || norm.startsWith('pic') || norm.startsWith('thumb')) {\n return 'Image';\n }\n if (norm.startsWith('title') || norm.startsWith('name') || norm.startsWith('label') || norm.startsWith('heading')) {\n return 'Title';\n }\n return normalized;\n}\n\nfunction buildRows(products: ChatSource[], displayConfig?: Record<string, string>, defaultCurrency = 'KES'): Row[] {\n const rows: Row[] = [];\n const resolved = products.map(p => resolveDisplayFields(p.fields || p, displayConfig));\n\n rows.push({\n label: 'Product Preview',\n values: resolved.map(r => r.image || null),\n type: 'image',\n });\n\n const prices = resolved.map(r => {\n const n = parseFloat(String(r.price ?? '').replace(/[^0-9.]/g, ''));\n return isNaN(n) ? null : n;\n });\n\n const priceLabels = products.map((p, i) => {\n const c = p.fields?.currency || p.currency || defaultCurrency;\n const n = prices[i];\n return n !== null\n ? `${c} ${n.toLocaleString('en-KE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`\n : null;\n });\n\n const validPrices = prices.filter((p): p is number => p !== null);\n const minPrice = validPrices.length ? Math.min(...validPrices) : null;\n rows.push({\n label: 'Price',\n values: priceLabels,\n type: 'price',\n bestIdx: minPrice !== null ? prices.indexOf(minPrice) : undefined,\n });\n\n const keysToExclude = new Set<string>([\n 'url', 'fields', 'id', 'score', 'currency', 'status', 'indexed_at', 'indexedAt'\n ]);\n \n if (displayConfig) {\n Object.values(displayConfig).forEach(v => {\n if (v) keysToExclude.add(v);\n });\n }\n\n const commonKeys = [\n 'title', 'name', 'label', 'headline', 'subject', 'job_title', 'listing_title', 'common_name', 'product_name',\n 'image', 'images', 'thumbnail', 'photo', 'cover', 'featured_image', 'hero_image', 'listing_image', 'logo',\n 'price', 'cost', 'listingPrice', 'rate', 'fee', 'startingFrom',\n 'brand', 'category', 'location', 'type', 'variety', 'make'\n ];\n commonKeys.forEach(k => keysToExclude.add(k));\n\n const allFieldKeys = new Set<string>();\n products.forEach(p => {\n const f = p.fields || p;\n if (f) {\n Object.keys(f).forEach(k => {\n if (!keysToExclude.has(k)) {\n allFieldKeys.add(k);\n }\n });\n }\n });\n\n const groupedKeys = new Map<string, string[]>();\n allFieldKeys.forEach(k => {\n const norm = normalizeKey(k);\n const base = getBaseGroup(norm);\n if (!groupedKeys.has(base)) {\n groupedKeys.set(base, []);\n }\n groupedKeys.get(base)!.push(k);\n });\n\n const sortedGroups = Array.from(groupedKeys.keys()).sort();\n\n sortedGroups.forEach(group => {\n const originalKeys = groupedKeys.get(group)!;\n const values = products.map(p => {\n const f = (p.fields || p) as Record<string, any>;\n if (!f) return null;\n for (const k of originalKeys) {\n if (f[k] !== undefined && f[k] !== null) {\n if (typeof f[k] === 'object') {\n return JSON.stringify(f[k]);\n }\n return String(f[k]);\n }\n }\n return null;\n });\n\n if (values.some(v => v !== null)) {\n rows.push({\n label: group,\n values,\n type: 'text',\n });\n }\n });\n\n const avail = products.map(s => {\n const f = s.fields || s;\n const a = (f.availability as string) || '';\n if (!a) return null;\n if (/in.?stock/i.test(a)) return 'In-Stock';\n if (/out.?of.?stock/i.test(a)) return 'Out of Stock';\n return a;\n });\n if (avail.some(Boolean)) {\n rows.push({ label: 'Availability', values: avail, type: 'availability' });\n }\n\n const cats = products.map(s => {\n const f = s.fields || s;\n return (f.category as string) || null;\n });\n if (cats.some(Boolean)) rows.push({ label: 'Category', values: cats });\n\n return rows;\n}\n\nfunction ImageCell({ value, name }: { value: string | null; name: string }) {\n if (!value) {\n return <div style={{ fontSize: 28, textAlign: 'center' }}>📦</div>;\n }\n return (\n <img\n src={value}\n alt={name}\n style={{\n width: 72,\n height: 72,\n objectFit: 'contain',\n borderRadius: 8,\n background: '#f5f5f5',\n display: 'block',\n }}\n />\n );\n}\n\n// Custom green pulsing ring on availability dot to match design guidelines\nfunction AvailabilityCell({ value }: { value: string | null }) {\n if (!value) return <span style={{ color: '#9ca3af' }}>—</span>;\n const inStock = /in.?stock/i.test(value);\n return (\n <span style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 13, color: 'var(--hsk-text, #111827)' }}>\n <span style={{\n width: 8, height: 8, borderRadius: '50%', flexShrink: 0,\n background: inStock ? '#22c55e' : '#ef4444',\n boxShadow: inStock ? '0 0 0 3px rgba(34,197,94,0.2)' : '0 0 0 3px rgba(239,68,68,0.2)',\n display: 'inline-block',\n }} />\n {value}\n </span>\n );\n}\n\nexport function ComparisonMatrix({ sources, defaultCurrency = 'KES', displayConfig }: ComparisonMatrixProps) {\n if (!sources || sources.length < 2) return null;\n\n const products = sources.slice(0, 3);\n const rows = buildRows(products, displayConfig, defaultCurrency);\n const colTemplate = `140px repeat(${products.length}, 1fr)`;\n\n const labelStyle: React.CSSProperties = {\n padding: '10px 12px',\n fontSize: 11,\n fontWeight: 700,\n color: 'var(--hsk-text-muted, #4b5563)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n borderBottom: '1px solid var(--hsk-border, rgba(0,0,0,0.07))',\n verticalAlign: 'middle',\n whiteSpace: 'nowrap',\n display: 'flex',\n alignItems: 'center',\n };\n\n const cellBase: React.CSSProperties = {\n padding: '10px 14px',\n fontSize: 13,\n color: 'var(--hsk-text, #111827)',\n borderBottom: '1px solid var(--hsk-border, rgba(0,0,0,0.07))',\n verticalAlign: 'middle',\n display: 'flex',\n alignItems: 'center',\n };\n\n return (\n <div\n className=\"hsk-compare-matrix\"\n style={{\n marginTop: 10,\n borderRadius: 12,\n overflow: 'hidden',\n border: '1px solid var(--hsk-border, rgba(0,0,0,0.09))',\n background: 'var(--hsk-surface, #fff)',\n fontSize: 13,\n }}\n >\n <div style={{ display: 'grid', gridTemplateColumns: colTemplate, background: 'var(--hsk-surface2, #f9fafb)', borderBottom: '2px solid var(--hsk-border, rgba(0,0,0,0.09))' }}>\n <div style={{ ...labelStyle, borderBottom: 'none', color: 'var(--hsk-text, #111)', fontSize: 12 }}>Feature</div>\n {products.map((p, i) => {\n const { title } = resolveDisplayFields(p.fields || p, displayConfig);\n return (\n <a\n key={i}\n href={p.url || '#'}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: 'flex',\n alignItems: 'center',\n padding: '10px 14px',\n fontSize: 12,\n fontWeight: 700,\n color: 'var(--hsk-primary, #16a34a)',\n textDecoration: 'none',\n lineHeight: 1.3,\n borderLeft: i > 0 ? '1px solid var(--hsk-border, rgba(0,0,0,0.07))' : 'none',\n }}\n >\n {title}\n </a>\n );\n })}\n </div>\n\n {rows.map((row, rowIdx) => (\n <div\n key={rowIdx}\n style={{\n display: 'grid',\n gridTemplateColumns: colTemplate,\n background: rowIdx % 2 === 1 ? 'var(--hsk-surface2, rgba(0,0,0,0.015))' : 'transparent',\n }}\n >\n <div style={labelStyle}>{row.label}</div>\n\n {products.map((p, i) => {\n const val = row.values[i];\n const isBest = row.bestIdx === i && row.values.filter(Boolean).length > 1;\n const { title } = resolveDisplayFields(p.fields || p, displayConfig);\n\n if (row.type === 'image') {\n return (\n <div key={i} style={{ ...cellBase, justifyContent: 'center', padding: '12px', borderLeft: i > 0 ? '1px solid var(--hsk-border, rgba(0,0,0,0.07))' : 'none' }}>\n <ImageCell value={val} name={title} />\n </div>\n );\n }\n if (row.type === 'availability') {\n return (\n <div key={i} style={{ ...cellBase, borderLeft: i > 0 ? '1px solid var(--hsk-border, rgba(0,0,0,0.07))' : 'none' }}>\n <AvailabilityCell value={val} />\n </div>\n );\n }\n return (\n <div\n key={i}\n style={{\n ...cellBase,\n fontWeight: isBest ? 700 : 400,\n color: isBest\n ? 'var(--hsk-primary, #ea580c)'\n : row.type === 'price'\n ? 'var(--hsk-text, #374151)'\n : 'var(--hsk-text, #111827)',\n borderLeft: i > 0 ? '1px solid var(--hsk-border, rgba(0,0,0,0.07))' : 'none',\n }}\n >\n {val ?? <span style={{ color: '#9ca3af' }}>—</span>}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\n\n// Gemini-style image markup: the shopper sketches, erases, or writes on the\n// current scene to show exactly WHERE an edit should happen. The flattened\n// image is sent as an annotated attachment; the backend tells the model to\n// apply the change at the marks and scrub them from the output.\n\ntype Tool = 'pen' | 'eraser' | 'text';\n\ninterface Point { x: number; y: number }\ninterface StrokeAction { kind: 'stroke'; tool: 'pen' | 'eraser'; color: string; size: number; points: Point[] }\ninterface TextAction { kind: 'text'; x: number; y: number; color: string; value: string; size: number }\ntype Action = StrokeAction | TextAction;\n\nconst COLORS = ['#111111', '#ff5a5a', '#ffb300', '#22c55e', '#06b6d4', '#d946ef', '#9ca3af'];\nconst MAX_EXPORT_DIM = 1280;\n\nexport function MarkupEditor({ src, onCancel, onSend }: {\n src: string;\n onCancel: () => void;\n onSend: (dataUrl: string, instruction: string) => void;\n}) {\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [loadError, setLoadError] = useState(false);\n const [tool, setTool] = useState<Tool>('pen');\n const [color, setColor] = useState(COLORS[1]);\n const [actions, setActions] = useState<Action[]>([]);\n const [pendingText, setPendingText] = useState<{ x: number; y: number } | null>(null);\n const [textValue, setTextValue] = useState('');\n const [instruction, setInstruction] = useState('');\n const [exportError, setExportError] = useState(false);\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const drawingRef = useRef<StrokeAction | null>(null);\n const textInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n const el = new Image();\n el.crossOrigin = 'anonymous';\n el.onload = () => setImg(el);\n el.onerror = () => setLoadError(true);\n el.src = src;\n }, [src]);\n\n // Canvas internal resolution = (capped) natural size so exports stay sharp.\n const dims = (() => {\n if (!img) return { w: 0, h: 0 };\n const scale = Math.min(1, MAX_EXPORT_DIM / Math.max(img.naturalWidth, img.naturalHeight));\n return { w: Math.round(img.naturalWidth * scale), h: Math.round(img.naturalHeight * scale) };\n })();\n\n // Marks live on their own layer so the eraser only removes ink, never photo.\n const markLayer = useRef<HTMLCanvasElement | null>(null);\n const paint = (live?: StrokeAction | null) => {\n const canvas = canvasRef.current;\n if (!canvas || !img) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n if (!markLayer.current) markLayer.current = document.createElement('canvas');\n const layer = markLayer.current;\n layer.width = canvas.width;\n layer.height = canvas.height;\n const lctx = layer.getContext('2d')!;\n const all = live ? [...actions, live] : actions;\n for (const a of all) {\n if (a.kind === 'stroke') {\n lctx.save();\n lctx.globalCompositeOperation = a.tool === 'eraser' ? 'destination-out' : 'source-over';\n lctx.strokeStyle = a.color;\n lctx.lineWidth = a.tool === 'eraser' ? a.size * 3 : a.size;\n lctx.lineCap = 'round';\n lctx.lineJoin = 'round';\n lctx.beginPath();\n a.points.forEach((p, i) => (i === 0 ? lctx.moveTo(p.x, p.y) : lctx.lineTo(p.x, p.y)));\n if (a.points.length === 1) lctx.lineTo(a.points[0].x + 0.01, a.points[0].y);\n lctx.stroke();\n lctx.restore();\n } else {\n lctx.save();\n lctx.fillStyle = a.color;\n lctx.font = `600 ${a.size}px system-ui, sans-serif`;\n lctx.fillText(a.value, a.x, a.y);\n lctx.restore();\n }\n }\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n ctx.drawImage(layer, 0, 0);\n };\n\n useEffect(() => { paint(); /* eslint-disable-line react-hooks/exhaustive-deps */ }, [img, actions, dims.w, dims.h]);\n useEffect(() => { if (pendingText) textInputRef.current?.focus(); }, [pendingText]);\n\n const toCanvasPoint = (e: React.PointerEvent): Point => {\n const canvas = canvasRef.current!;\n const rect = canvas.getBoundingClientRect();\n return {\n x: ((e.clientX - rect.left) / rect.width) * canvas.width,\n y: ((e.clientY - rect.top) / rect.height) * canvas.height,\n };\n };\n\n const strokeSize = () => Math.max(4, Math.round(dims.w / 180));\n const textSize = () => Math.max(18, Math.round(dims.w / 28));\n\n const onPointerDown = (e: React.PointerEvent) => {\n if (!img) return;\n const p = toCanvasPoint(e);\n if (tool === 'text') {\n setPendingText({ x: p.x, y: p.y });\n setTextValue('');\n return;\n }\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n drawingRef.current = { kind: 'stroke', tool, color, size: strokeSize(), points: [p] };\n paint(drawingRef.current);\n };\n const onPointerMove = (e: React.PointerEvent) => {\n if (!drawingRef.current) return;\n drawingRef.current.points.push(toCanvasPoint(e));\n paint(drawingRef.current);\n };\n const onPointerUp = () => {\n if (!drawingRef.current) return;\n const done = drawingRef.current;\n drawingRef.current = null;\n setActions(prev => [...prev, done]);\n };\n\n const commitText = () => {\n if (pendingText && textValue.trim()) {\n setActions(prev => [...prev, { kind: 'text', x: pendingText.x, y: pendingText.y, color, value: textValue.trim(), size: textSize() }]);\n }\n setPendingText(null);\n setTextValue('');\n };\n\n const handleSend = () => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n try {\n paint();\n const dataUrl = canvas.toDataURL('image/jpeg', 0.92);\n onSend(dataUrl, instruction.trim());\n } catch {\n setExportError(true);\n }\n };\n\n const hasMarks = actions.length > 0;\n\n return (\n <div className=\"hsk-markup\" role=\"dialog\" aria-label=\"Mark up image\">\n <div className=\"hsk-markup-head\">\n <span className=\"hsk-markup-title\">Mark where you want the change</span>\n <button className=\"hsk-markup-cancel\" onClick={onCancel}>Cancel</button>\n </div>\n\n <div className=\"hsk-markup-stage\">\n {loadError ? (\n <div className=\"hsk-markup-error\">This image can't be edited here.</div>\n ) : !img ? (\n <div className=\"hsk-markup-loading\">Loading image…</div>\n ) : (\n <div className=\"hsk-markup-canvas-wrap\">\n <canvas\n ref={canvasRef}\n width={dims.w}\n height={dims.h}\n className={`hsk-markup-canvas hsk-markup-canvas--${tool}`}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerLeave={onPointerUp}\n />\n {pendingText && canvasRef.current && (\n <input\n ref={textInputRef}\n className=\"hsk-markup-textinput\"\n style={{\n left: `${(pendingText.x / dims.w) * 100}%`,\n top: `${(pendingText.y / dims.h) * 100}%`,\n color,\n }}\n value={textValue}\n placeholder=\"Type, then Enter\"\n onChange={e => setTextValue(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') commitText(); if (e.key === 'Escape') { setPendingText(null); setTextValue(''); } }}\n onBlur={commitText}\n />\n )}\n </div>\n )}\n </div>\n\n <div className=\"hsk-markup-tools\">\n <div className=\"hsk-markup-colors\">\n {COLORS.map(c => (\n <button\n key={c}\n className={`hsk-markup-color${color === c ? ' hsk-markup-color--on' : ''}`}\n style={{ background: c }}\n onClick={() => { setColor(c); if (tool === 'eraser') setTool('pen'); }}\n aria-label={`Colour ${c}`}\n />\n ))}\n </div>\n <div className=\"hsk-markup-actions\">\n <button className={`hsk-markup-tool${tool === 'pen' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('pen')}>Sketch</button>\n <button className={`hsk-markup-tool${tool === 'text' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('text')}>Text</button>\n <button className={`hsk-markup-tool${tool === 'eraser' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('eraser')}>Eraser</button>\n <button className=\"hsk-markup-tool\" onClick={() => setActions(prev => prev.slice(0, -1))} disabled={!hasMarks}>Undo</button>\n <button className=\"hsk-markup-tool\" onClick={() => setActions([])} disabled={!hasMarks}>Clear</button>\n </div>\n </div>\n\n <div className=\"hsk-markup-send\">\n <input\n className=\"hsk-markup-instruction\"\n value={instruction}\n placeholder=\"Describe the change — e.g. add the sofa here\"\n onChange={e => setInstruction(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter' && (hasMarks || instruction.trim())) handleSend(); }}\n />\n <button\n className=\"hsk-markup-go\"\n onClick={handleSend}\n disabled={!img || (!hasMarks && !instruction.trim())}\n >\n Send\n </button>\n </div>\n {exportError && <div className=\"hsk-markup-error\">Couldn't process this image — try a newer visualization.</div>}\n </div>\n );\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useSearch, useKiku, useAkropolysContext } from '@akropolys/sdk';\nimport { renderMarkdown } from '../utils/markdown';\nimport { SearchResult, Product, AkropolysTheme } from '@akropolys/sdk';\nimport { cn } from '../utils/cn';\nimport { ArrowUpIcon } from '../utils/icons';\n\nexport interface SparkleProps {\n productName: string;\n limit?: number;\n onResult?: (results: SearchResult[]) => void;\n /** Override the backdrop colour (any CSS colour/gradient) */\n backdropColor?: string;\n /** Override backdrop blur — e.g. \"8px\" or 8 */\n backdropBlur?: string | number;\n /** Extra classes on the trigger button */\n className?: string;\n /** Called when user clicks a result — return false to prevent default navigation */\n onNavigate?: (result: SearchResult) => boolean | void;\n theme?: AkropolysTheme;\n classNames?: {\n button?: string;\n backdrop?: string;\n card?: string;\n item?: string;\n };\n product?: Product;\n children?: React.ReactNode;\n}\n\n/* ── Modal ────────────────────────────────────────────────────────────────── */\ninterface ModalProps extends Pick<SparkleProps, 'productName' | 'limit' | 'backdropColor' | 'backdropBlur' | 'onNavigate' | 'onResult' | 'theme' | 'classNames' | 'product'> {\n onClose: () => void;\n}\n\nconst SparkleIcon = ({ className, size = 16 }: { className?: string; size?: number }) => (\n <svg\n className={cn(\"hsk-brand-mark\", className)}\n width={size}\n height={size}\n viewBox=\"0 0 100 100\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-label=\"kiku\"\n >\n <g transform=\"translate(22.7 19) scale(0.62)\" fill=\"currentColor\" fillRule=\"evenodd\">\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" />\n <circle cx=\"55\" cy=\"82\" r=\"3.4\" />\n </g>\n </svg>\n);\n\nconst CloseIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n);\n\n\n/* ── Modal ────────────────────────────────────────────────────────────────── */\ninterface ModalProps extends Pick<SparkleProps, 'productName' | 'limit' | 'backdropColor' | 'backdropBlur' | 'onNavigate' | 'onResult' | 'theme' | 'classNames' | 'product'> {\n onClose: () => void;\n}\n\nconst getFriendlyError = (err: any) => {\n let str = '';\n if (typeof err === 'string') str = err;\n else if (err && typeof err === 'object' && err.message) str = err.message;\n else try { str = JSON.stringify(err); } catch { str = String(err); }\n\n if (str.toLowerCase().includes('token limit')) {\n return \"You've reached your usage limit. Please update your billing limits in your dashboard to continue.\";\n }\n\n try {\n const parsed = JSON.parse(str);\n return parsed.error || parsed.message || str;\n } catch {\n return str;\n }\n};\n\nfunction SparkleModal({ \n productName, \n limit, \n backdropColor, \n backdropBlur, \n onClose, \n onNavigate, \n onResult,\n theme,\n classNames = {},\n product: initialProduct,\n}: ModalProps) {\n const client = useAkropolysContext();\n const [fetchedProduct, setFetchedProduct] = useState<Product | null>(null);\n const displayProduct = initialProduct || fetchedProduct;\n const { results, loading: searchLoading, search } = useSearch({ type: 'vector' });\n const { messages, sources, loading: chatLoading, error: chatError, send } = useKiku();\n const [chatInput, setChatInput] = useState('');\n const [isMobile, setIsMobile] = useState(false);\n const [showSpecs, setShowSpecs] = useState(false);\n const [collapseSimilar, setCollapseSimilar] = useState(false);\n const chatBottomRef = useRef<HTMLDivElement>(null);\n const chatTextareaRef = useRef<HTMLTextAreaElement>(null);\n\n /* auto-search and product fetching on open */\n useEffect(() => {\n if (!initialProduct && !fetchedProduct) {\n client.api.searchVector(productName, 1)\n .then(res => {\n if (res.results && res.results.length > 0) {\n setFetchedProduct(res.results[0].entity);\n }\n })\n .catch(err => console.error('[Akropolys] Failed to fetch product details', err));\n }\n search(productName, limit);\n }, [productName, initialProduct, fetchedProduct, client, limit, search]);\n\n /* handle window resize for mobile check */\n useEffect(() => {\n const handleResize = () => setIsMobile(window.innerWidth <= 768);\n handleResize();\n if (typeof window !== 'undefined') {\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }\n }, []);\n\n /* fire callback */\n useEffect(() => { if (results.length > 0) onResult?.(results); }, [results, onResult]);\n\n /* Escape key */\n useEffect(() => {\n const h = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n document.addEventListener('keydown', h);\n return () => document.removeEventListener('keydown', h);\n }, [onClose]);\n\n /* Scroll chat to bottom */\n useEffect(() => {\n chatBottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, chatLoading]);\n\n const blurVal = typeof backdropBlur === 'number' ? `${backdropBlur}px` : (backdropBlur ?? '16px');\n const bg = backdropColor ?? undefined;\n\n const handleNav = (r: SearchResult) => {\n const prevent = onNavigate?.(r);\n if (prevent !== false) {\n onClose();\n if (r.entity.url) window.location.href = r.entity.url;\n }\n };\n\n const handleSend = async (text?: string) => {\n const q = (text ?? chatInput).trim();\n if (!q || chatLoading) return;\n setChatInput('');\n if (chatTextareaRef.current) {\n chatTextareaRef.current.style.height = 'auto';\n }\n\n if (messages.length === 0 && displayProduct) {\n const contextQuery = `[Context: Shopper is viewing \"${displayProduct.name}\". Price: ${displayProduct.price}. Description: ${displayProduct.description || ''}]\\n\\nQuestion: ${q}`;\n await send(contextQuery, q);\n } else {\n await send(q);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); }\n };\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setChatInput(e.target.value);\n const t = e.target;\n t.style.height = 'auto';\n t.style.height = `${Math.min(t.scrollHeight, 140)}px`;\n };\n\n const customStyles = {\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\n } as React.CSSProperties;\n\n const displayMessages = messages.length === 0 && displayProduct\n ? [\n {\n role: 'assistant' as const,\n content: `Hi! I can help you with **${displayProduct.name}**. Ask me about its specifications, features, compare it with other options, or find alternatives!`,\n },\n ]\n : messages;\n\n if (isMobile) {\n return (\n <div\n className={cn(\"hsk-sp-backdrop hsk-sp-mobile-view\", classNames.backdrop)}\n onClick={onClose}\n style={{\n backdropFilter: `blur(${blurVal})`,\n WebkitBackdropFilter: `blur(${blurVal})`,\n background: bg ?? undefined,\n ...customStyles,\n }}\n >\n <div className={cn(\"hsk-sp-card hsk-sp-fullscreen hsk-sp-mobile-card\", classNames.card)} onClick={e => e.stopPropagation()}>\n {/* Header */}\n <div className=\"hsk-sp-header\">\n <span className=\"hsk-sp-header-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </span>\n <div className=\"hsk-sp-header-body\">\n <div className=\"hsk-sp-header-title-row\">\n <div className=\"hsk-sp-header-title\">{displayProduct?.name || productName}</div>\n {displayProduct && (\n <button \n type=\"button\" \n className=\"hsk-sp-header-specs-btn\"\n onClick={() => setShowSpecs(true)}\n >\n Specs\n </button>\n )}\n </div>\n <div className=\"hsk-sp-header-sub\">kiku</div>\n </div>\n <button className=\"hsk-sp-close\" onClick={onClose} aria-label=\"Close\">\n <CloseIcon />\n </button>\n </div>\n\n {searchLoading && <div className=\"hsk-sp-bar\" />}\n\n {/* Chat Assistant */}\n <div className=\"hsk-sp-mobile-chat-container\">\n <div className=\"hsk-cb-msgs\">\n {displayMessages.map((msg, idx) => {\n const isUser = msg.role === 'user';\n return (\n <div key={idx} className=\"hsk-cb-msg-group\">\n {isUser ? (\n <div className=\"hsk-cb-user-msg\">\n <div className=\"hsk-cb-user-bubble\">{msg.content}</div>\n </div>\n ) : (\n <div className=\"hsk-cb-ai-msg\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-ai-body\">\n <div className=\"hsk-cb-ai-text\">{renderMarkdown(msg.content)}</div>\n \n {/* Inline Claude-like attachments under the first assistant message */}\n {idx === 0 && displayProduct && (\n <div className=\"hsk-sp-mobile-attachment-deck\">\n {/* Main Product Card */}\n <div className=\"hsk-sp-mobile-main-card\">\n <div className=\"hsk-sp-mobile-main-card-img\">\n {displayProduct.images?.[0] ? (\n <img src={displayProduct.images[0]} alt={displayProduct.name} />\n ) : (\n <span>🛍</span>\n )}\n </div>\n <div className=\"hsk-sp-mobile-main-card-info\">\n <div className=\"hsk-sp-mobile-main-card-brand\">\n {displayProduct.brand || displayProduct.category || 'Product'}\n </div>\n <div className=\"hsk-sp-mobile-main-card-name\">{displayProduct.name}</div>\n <div className=\"hsk-sp-mobile-main-card-price\">\n {displayProduct.currency ?? 'KES'} {parseFloat(displayProduct.price?.replace(/[^0-9.]/g, '') || '0').toLocaleString()}\n </div>\n </div>\n {((displayProduct.specs && Object.keys(displayProduct.specs).length > 0) || displayProduct.description) && (\n <button \n type=\"button\"\n className=\"hsk-sp-mobile-main-card-specs-btn\"\n onClick={() => setShowSpecs(true)}\n >\n Specs\n </button>\n )}\n </div>\n\n {/* Similar Products Carousel */}\n {(() => {\n const similarProducts = results.filter(\n r => {\n const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());\n const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();\n return !isSameName && !isSameSlug;\n }\n );\n\n if (similarProducts.length === 0) return null;\n\n return (\n <div className=\"hsk-sp-mobile-similar-carousel-inline\">\n <div className=\"hsk-sp-mobile-similar-carousel-title\">Similar Products</div>\n <div className=\"hsk-sp-mobile-similar-carousel-list\">\n {similarProducts.map((r) => {\n const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, '') || '0');\n const currency = r.entity.currency ?? 'KES';\n return (\n <div\n key={r.id}\n className=\"hsk-sp-mobile-similar-carousel-item\"\n onClick={() => handleNav(r)}\n >\n <div className=\"hsk-sp-mobile-similar-carousel-img\">\n {r.entity.images?.[0] ? (\n <img src={r.entity.images[0]} alt={r.entity.name} />\n ) : (\n <span>🛍</span>\n )}\n </div>\n <div className=\"hsk-sp-mobile-similar-carousel-meta\">\n <div className=\"hsk-sp-mobile-similar-carousel-name\" title={r.entity.name}>\n {r.entity.name}\n </div>\n <div className=\"hsk-sp-mobile-similar-carousel-price\">\n {currency} {price.toLocaleString()}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n })()}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n );\n })}\n\n {chatLoading && (\n <div className=\"hsk-cb-typing-row\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-typing\">\n <div className=\"hsk-cb-dot\" />\n <div className=\"hsk-cb-dot\" />\n <div className=\"hsk-cb-dot\" />\n </div>\n </div>\n )}\n\n {chatError && <div className=\"hsk-cb-error\">{getFriendlyError(chatError)}</div>}\n <div ref={chatBottomRef} style={{ height: 1 }} />\n </div>\n\n <div className=\"hsk-cb-input-wrap\">\n <div className=\"hsk-cb-input-box\">\n <textarea\n ref={chatTextareaRef}\n className=\"hsk-cb-textarea\"\n value={chatInput}\n onChange={handleInput}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask about this product, specs, or comparison...\"\n rows={1}\n disabled={chatLoading}\n />\n <button\n className=\"hsk-cb-send\"\n onClick={() => handleSend()}\n disabled={!chatInput.trim() || chatLoading}\n aria-label=\"Send message\"\n >\n <ArrowUpIcon />\n </button>\n </div>\n </div>\n </div>\n\n {/* Specs Sheet Drawer Overlay */}\n {showSpecs && displayProduct && (\n <div className=\"hsk-sp-mobile-specs-overlay\" onClick={() => setShowSpecs(false)}>\n <div className=\"hsk-sp-mobile-specs-drawer\" onClick={e => e.stopPropagation()}>\n <div className=\"hsk-sp-mobile-specs-header\">\n <h3>Specifications</h3>\n <button type=\"button\" onClick={() => setShowSpecs(false)}>Close</button>\n </div>\n <div className=\"hsk-sp-mobile-specs-body\">\n <h4 className=\"hsk-sp-mobile-specs-title\">{displayProduct.name}</h4>\n {displayProduct.description && (\n <div className=\"hsk-sp-mobile-specs-desc\">\n <h5>Description</h5>\n <p>{displayProduct.description}</p>\n </div>\n )}\n {displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && (\n <div className=\"hsk-sp-mobile-specs-list\">\n <h5>Details</h5>\n {Object.entries(displayProduct.specs).map(([key, val]) => (\n <div key={key} className=\"hsk-sp-mobile-spec-row\">\n <span className=\"hsk-sp-mobile-spec-label\">{key}</span>\n <span className=\"hsk-sp-mobile-spec-value\">{val}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"hsk-sp-backdrop\", classNames.backdrop)}\n onClick={onClose}\n style={{\n backdropFilter: `blur(${blurVal})`,\n WebkitBackdropFilter: `blur(${blurVal})`,\n background: bg ?? undefined,\n ...customStyles,\n }}\n >\n <div className={cn(\"hsk-sp-card hsk-sp-fullscreen\", classNames.card)} onClick={e => e.stopPropagation()}>\n <div className=\"hsk-sp-header\">\n <span className=\"hsk-sp-header-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </span>\n <div className=\"hsk-sp-header-body\">\n <div className=\"hsk-sp-header-title\">{displayProduct?.name || productName}</div>\n <div className=\"hsk-sp-header-sub\">Ask questions, compare specs, or check similar products</div>\n </div>\n <button className=\"hsk-sp-close\" onClick={onClose} aria-label=\"Close\">\n <CloseIcon />\n </button>\n </div>\n\n {searchLoading && <div className=\"hsk-sp-bar\" />}\n\n {/* Split pane body */}\n <div className=\"hsk-sp-body\">\n {/* Left Pane: Product Profile */}\n <div className=\"hsk-sp-details-pane\">\n {displayProduct && (\n <div className=\"hsk-sp-product-profile-container\">\n <div className=\"hsk-sp-product-profile\">\n <div className=\"hsk-sp-details-imgwrap\">\n {displayProduct.images?.[0] ? (\n <img src={displayProduct.images[0]} alt={displayProduct.name} />\n ) : (\n <span className=\"hsk-sp-img-placeholder\">🛍</span>\n )}\n </div>\n <div className=\"hsk-sp-details-meta\">\n {displayProduct.brand && <span className=\"hsk-sp-item-brand\">{displayProduct.brand}</span>}\n {displayProduct.category && <span className=\"hsk-sp-item-cat\">{displayProduct.category}</span>}\n <h2 className=\"hsk-sp-details-name\">{displayProduct.name}</h2>\n <div className=\"hsk-sp-item-price-row\">\n <span className=\"hsk-sp-item-currency\">{displayProduct.currency ?? 'KES'}</span>\n <span className=\"hsk-sp-item-price\">{parseFloat(displayProduct.price?.replace(/[^0-9.]/g, '') || '0').toLocaleString()}</span>\n {displayProduct.originalPrice && (\n <span className=\"hsk-sp-item-original-price\">\n {parseFloat(displayProduct.originalPrice.replace(/[^0-9.]/g, '') || '0').toLocaleString()}\n </span>\n )}\n {displayProduct.discount && (\n <span className=\"hsk-sp-item-discount\">({displayProduct.discount})</span>\n )}\n </div>\n \n <div className=\"hsk-sp-item-meta-badges\">\n {displayProduct.rating && (\n <span className=\"hsk-sp-meta-badge hsk-sp-meta-badge-rating\">\n ★ {parseFloat(displayProduct.rating.toString()).toFixed(1)} {displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ''}\n </span>\n )}\n {displayProduct.availability && (\n <span className={`hsk-sp-meta-badge hsk-sp-meta-badge-avail ${displayProduct.availability.toLowerCase().includes('in') ? 'in-stock' : 'out-stock'}`}>\n {displayProduct.availability}\n </span>\n )}\n {displayProduct.stock && !displayProduct.availability && (\n <span className=\"hsk-sp-meta-badge hsk-sp-meta-badge-stock\">\n Stock: {displayProduct.stock}\n </span>\n )}\n </div>\n </div>\n </div>\n\n {displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && (\n <div className=\"hsk-sp-specs-horizontal\">\n {Object.entries(displayProduct.specs).map(([key, val]) => (\n <div key={key} className=\"hsk-sp-spec-item-horizontal\">\n <span className=\"hsk-sp-spec-label-horizontal\">{key}:</span>\n <span className=\"hsk-sp-spec-value-horizontal\" title={val}>{val}</span>\n </div>\n ))}\n </div>\n )}\n\n {displayProduct.description && (\n <div className=\"hsk-sp-details-desc\">\n <h4>Description</h4>\n <p>{displayProduct.description}</p>\n </div>\n )}\n </div>\n )}\n\n {/* Similar Products */}\n <div className=\"hsk-sp-similar-section\">\n <h3>Similar Products</h3>\n <div className=\"hsk-sp-results\">\n {(() => {\n const similarProducts = results.filter(\n r => {\n const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());\n const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();\n return !isSameName && !isSameSlug;\n }\n );\n\n if (!searchLoading && similarProducts.length === 0) {\n return <div className=\"hsk-sp-empty\">No similar products found.</div>;\n }\n\n return similarProducts.map((r, i) => {\n const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, '') || '0');\n const currency = r.entity.currency ?? 'KES';\n return (\n <div\n key={r.id}\n className={cn(\"hsk-sp-item\", classNames.item)}\n style={{ animationDelay: `${i * 55}ms`, cursor: 'pointer' }}\n onClick={() => handleNav(r)}\n >\n <div className=\"hsk-sp-img-wrap\">\n {r.entity.images?.[0] ? (\n <img src={r.entity.images[0]} alt={r.entity.name} />\n ) : (\n <span className=\"hsk-sp-img-placeholder\">🛍</span>\n )}\n </div>\n <div className=\"hsk-sp-item-body\">\n <div>\n {r.entity.category && (\n <div className=\"hsk-sp-item-cat\">{r.entity.category}</div>\n )}\n <div className=\"hsk-sp-item-name\" title={r.entity.name}>{r.entity.name}</div>\n </div>\n <div className=\"hsk-sp-item-price-row\">\n <span className=\"hsk-sp-item-currency\">{currency}</span>\n <span className=\"hsk-sp-item-price\">{price.toLocaleString()}</span>\n </div>\n <div className=\"hsk-sp-actions\">\n <button\n className=\"hsk-sp-action hsk-sp-action-primary\"\n onClick={(e) => { e.stopPropagation(); handleNav(r); }}\n >\n View\n </button>\n </div>\n </div>\n </div>\n );\n });\n })()}\n </div>\n </div>\n </div>\n\n {/* Right Pane: AI Chat Assistant */}\n <div className=\"hsk-sp-chat-pane\">\n <div className=\"hsk-cb-msgs\">\n {displayMessages.map((msg, idx) => {\n const isUser = msg.role === 'user';\n return (\n <div key={idx} className=\"hsk-cb-msg-group\">\n {isUser ? (\n <div className=\"hsk-cb-user-msg\">\n <div className=\"hsk-cb-user-bubble\">{msg.content}</div>\n </div>\n ) : (\n <div className=\"hsk-cb-ai-msg\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-ai-body\">\n <div className=\"hsk-cb-ai-text\">{renderMarkdown(msg.content)}</div>\n </div>\n </div>\n )}\n </div>\n );\n })}\n\n {chatLoading && (\n <div className=\"hsk-cb-typing-row\">\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\n <SparkleIcon />\n </div>\n <div className=\"hsk-cb-typing\">\n <div className=\"hsk-cb-dot\" />\n <div className=\"hsk-cb-dot\" />\n <div className=\"hsk-cb-dot\" />\n </div>\n </div>\n )}\n\n {chatError && <div className=\"hsk-cb-error\">{getFriendlyError(chatError)}</div>}\n <div ref={chatBottomRef} style={{ height: 1 }} />\n </div>\n\n <div className=\"hsk-cb-input-wrap\">\n <div className=\"hsk-cb-input-box\">\n <textarea\n ref={chatTextareaRef}\n className=\"hsk-cb-textarea\"\n value={chatInput}\n onChange={handleInput}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask about this product, specs, or comparison...\"\n rows={1}\n disabled={chatLoading}\n />\n <button\n className=\"hsk-cb-send\"\n onClick={() => handleSend()}\n disabled={!chatInput.trim() || chatLoading}\n aria-label=\"Send message\"\n >\n <ArrowUpIcon />\n </button>\n </div>\n <div className=\"hsk-cb-hint\">Akropolys &middot; instant product knowledge</div>\n </div>\n </div>\n </div>\n\n <div className=\"hsk-sp-footer\">\n <span className=\"hsk-sp-esc\">Esc to close</span>\n </div>\n </div>\n </div>\n );\n}\n\n/* ── Exported component ───────────────────────────────────────────────────── */\nexport function Sparkle({ \n productName, \n limit = 8, \n onResult, \n backdropColor, \n backdropBlur, \n className, \n onNavigate,\n theme,\n classNames = {},\n product,\n children,\n}: SparkleProps) {\n const [open, setOpen] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => { setMounted(true); }, []);\n\n const customStyles = {\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\n } as React.CSSProperties;\n\n return (\n <>\n <button\n className={cn(\"hsk-sp-btn\", classNames.button, className)}\n onClick={() => setOpen(true)}\n style={customStyles}\n title=\"Find similar products\"\n aria-label=\"Find similar products\"\n >\n {children || <SparkleIcon />}\n </button>\n {open && mounted && createPortal(\n <SparkleModal\n productName={productName}\n limit={limit}\n onResult={onResult}\n backdropColor={backdropColor}\n backdropBlur={backdropBlur}\n onClose={() => setOpen(false)}\n onNavigate={onNavigate}\n theme={theme}\n classNames={classNames}\n product={product}\n />,\n document.body\n )}\n </>\n );\n}\n\n"],"mappings":"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","names":["import_react","import_sdk","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_sdk","import_jsx_runtime","import_jsx_runtime","import_react","import_sdk","import_sdk","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","SparkleIcon","MicIcon","SparkleIcon","import_react","import_react_dom","import_sdk","import_jsx_runtime","SparkleIcon","CloseIcon","getFriendlyError"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/SearchBar.tsx","../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs","../src/utils/cn.ts","../src/components/ChatWidget.tsx","../src/utils/markdown.tsx","../src/utils/icons.tsx","../src/utils/theme.ts","../src/components/VoiceButton.tsx","../src/utils/voiceSession.ts","../src/utils/tts.ts","../src/components/VisualSearch.tsx","../src/utils/downscaleImage.ts","../src/components/KikuButton.tsx","../src/generated/cssText.ts","../src/utils/shadowRoot.ts","../src/utils/chromeWarm.ts","../src/utils/hostFont.ts","../src/components/ChatModal/types.ts","../src/components/ChatModal/ChatModal.tsx","../src/components/ChatModal/icons.tsx","../src/components/ChatModal/themes.ts","../src/utils/sheetGesture.ts","../src/components/MarkupEditor.tsx","../src/utils/markRegions.ts","../src/components/KikuDoodles.tsx","../src/components/ChatModal/hooks/useScriptFont.tsx","../src/components/ChatModal/locales.json","../src/components/ChatModal/hooks/useChatScroll.ts","../src/components/ChatModal/hooks/useKikuKey.ts","../src/components/ChatModal/hooks/useChatCommands.ts","../src/components/ChatModal/hooks/useVoiceController.ts","../src/utils/liveVoice.ts","../src/components/ChatModal/ChatTopbar.tsx","../src/components/KikuAvatar.tsx","../src/components/ChatModal/OnboardingView.tsx","../src/components/ChatModal/components/ListeningWave.tsx","../src/components/ChatModal/components/CascadeText.tsx","../src/components/ChatModal/components/AnimatedPlaceholder.tsx","../src/components/ChatModal/components/MessageItem.tsx","../src/components/LiveTable.tsx","../src/components/ChatModal/components/ThinkingBlock.tsx","../src/components/ChatModal/components/SourcesCarousel.tsx","../src/components/ChatModal/components/SmartContextPills.tsx","../src/components/ChatModal/components/MemoryKeyCards.tsx","../src/components/ChatModal/ChatMessages.tsx","../src/components/ChatModal/ChatComposer.tsx","../src/components/VoiceCanvas.tsx","../src/components/ChatModal/VoiceOverlay.tsx","../src/components/ChatModal/components/LightboxModal.tsx","../src/components/ChatModal/components/ConversationTimeline.tsx","../src/components/Sparkle.tsx","../src/shopify.tsx"],"sourcesContent":["\r\nexport { SearchBar } from './components/SearchBar';\r\nexport type { SearchBarProps } from './components/SearchBar';\r\nexport { ChatWidget, ChatWidget as KikuChat } from './components/ChatWidget';\r\nexport type { ChatWidgetProps, ChatWidgetProps as KikuChatProps } from './components/ChatWidget';\r\nexport { KikuButton } from './components/KikuButton';\r\nexport type { KikuButtonProps } from './components/KikuButton';\r\nexport { Sparkle } from './components/Sparkle';\r\n\r\n\r\nexport { VoiceButton } from './components/VoiceButton';\r\nexport type { VoiceButtonProps } from './components/VoiceButton';\r\nexport { VisualSearch } from './components/VisualSearch';\r\nexport type { VisualSearchProps } from './components/VisualSearch';\r\n\r\nexport {\r\n normalizeShopifyProduct,\r\n shopifyAddToCart,\r\n shopifyGetCart,\r\n initKiku,\r\n} from './shopify';\r\nexport type { ShopifyProduct, StandaloneConfig } from './shopify';\r\n\r\n","import React, { useState, useEffect, useRef } from 'react';\r\nimport { useSearch, SearchResult, AkropolysTheme, useAkropolysContext } from '@akropolys/sdk';\r\nimport { cn } from '../utils/cn';\r\n\r\nexport interface SearchBarProps {\r\n placeholder?: string;\r\n limit?: number;\r\n debounceMs?: number;\r\n onSelect?: (result: SearchResult) => void;\r\n className?: string;\r\n inputClassName?: string;\r\n dropdownClassName?: string;\r\n renderResult?: (result: SearchResult) => React.ReactNode;\r\n theme?: AkropolysTheme;\r\n classNames?: {\r\n root?: string;\r\n input?: string;\r\n dropdown?: string;\r\n row?: string;\r\n };\r\n}\r\n\r\nconst SearchIcon = () => (\r\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\r\n <circle cx=\"8.5\" cy=\"8.5\" r=\"5.5\"/>\r\n <line x1=\"13\" y1=\"13\" x2=\"18\" y2=\"18\"/>\r\n </svg>\r\n);\r\n\r\nexport function SearchBar({\r\n placeholder = 'Search products…',\r\n limit = 10,\r\n debounceMs = 150,\r\n onSelect,\r\n className,\r\n inputClassName,\r\n dropdownClassName,\r\n renderResult,\r\n theme,\r\n classNames = {},\r\n}: SearchBarProps) {\r\n const [query, setQuery] = useState('');\r\n const [open, setOpen] = useState(false);\r\n const { results, loading, search, clear } = useSearch({ debounceMs });\r\n const client = useAkropolysContext();\r\n const wrap = useRef<HTMLDivElement>(null);\r\n const ignoreNextQueryChange = useRef(false);\r\n\r\n useEffect(() => {\r\n if (ignoreNextQueryChange.current) {\r\n ignoreNextQueryChange.current = false;\r\n return;\r\n }\r\n if (!query.trim()) {\r\n clear();\r\n setOpen(false);\r\n return;\r\n }\r\n setOpen(true); // open immediately (stale results show while fetching)\r\n search(query, limit);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [query]);\r\n\r\n useEffect(() => {\r\n const h = (e: MouseEvent) => {\r\n if (wrap.current && !wrap.current.contains(e.target as Node)) setOpen(false);\r\n };\r\n document.addEventListener('mousedown', h);\r\n return () => document.removeEventListener('mousedown', h);\r\n }, []);\r\n\r\n const handleSelect = (r: SearchResult) => {\r\n if (query.trim()) {\r\n client.api.searchVector(query, 1, undefined, true).catch(() => {});\r\n }\r\n ignoreNextQueryChange.current = true;\r\n setOpen(false);\r\n setQuery(r.entity.title ?? r.entity.name ?? '');\r\n onSelect?.(r);\r\n };\r\n\r\n const handleCommitSearch = () => {\r\n if (!query.trim()) return;\r\n client.api.searchVector(query, 1, undefined, true).catch(() => {});\r\n if (results.length > 0) {\r\n handleSelect(results[0]);\r\n }\r\n };\r\n\r\n const showDrop = open && query.trim().length > 0;\r\n\r\n const customStyles = {\r\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\r\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\r\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\r\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\r\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\r\n } as React.CSSProperties;\r\n\r\n return (\r\n <div className={cn(\"hsk-sb-wrap\", classNames.root, className)} ref={wrap} style={customStyles}>\r\n <span className=\"hsk-sb-icon\"><SearchIcon /></span>\r\n <input\r\n className={cn(\"hsk-sb-input\", classNames.input, inputClassName)}\r\n type=\"text\"\r\n value={query}\r\n placeholder={placeholder}\r\n onChange={e => setQuery(e.target.value)}\r\n onFocus={() => results.length > 0 && query.trim() && setOpen(true)}\r\n onKeyDown={e => {\r\n if (e.key === 'Enter') {\r\n handleCommitSearch();\r\n }\r\n }}\r\n autoComplete=\"off\"\r\n spellCheck={false}\r\n />\r\n {showDrop && (\r\n <div className={cn(\"hsk-sb-drop\", classNames.dropdown, dropdownClassName)} style={{ position: 'absolute' }}>\r\n {loading && <div className=\"hsk-sb-loading-bar\" />}\r\n\r\n {loading && results.length === 0 ? (\r\n <>\r\n <div className=\"hsk-sb-skeleton-row\">\r\n <span className=\"hsk-sb-skeleton-icon\" />\r\n <div className=\"hsk-sb-row-body\">\r\n <div className=\"hsk-sb-skeleton-text1\" />\r\n <div className=\"hsk-sb-skeleton-text2\" />\r\n </div>\r\n </div>\r\n <div className=\"hsk-sb-skeleton-row\">\r\n <span className=\"hsk-sb-skeleton-icon\" />\r\n <div className=\"hsk-sb-row-body\">\r\n <div className=\"hsk-sb-skeleton-text1\" style={{ width: '45%' }} />\r\n <div className=\"hsk-sb-skeleton-text2\" style={{ width: '25%' }} />\r\n </div>\r\n </div>\r\n </>\r\n ) : (\r\n <>\r\n {results.length === 0 && !loading && (\r\n <div className=\"hsk-sb-empty\">No results for &ldquo;{query}&rdquo;</div>\r\n )}\r\n\r\n {results.map((r, i) => {\r\n if (renderResult) {\r\n return (\r\n <div\r\n key={r.id}\r\n onClick={() => handleSelect(r)}\r\n className=\"hsk-sb-fade\"\r\n style={{ animationDelay: `${i * 18}ms` }}\r\n >\r\n {renderResult(r)}\r\n </div>\r\n );\r\n }\r\n const thumb = r.entity.image ?? r.entity.thumbnail ?? r.entity.images?.[0];\r\n return (\r\n <div\r\n key={r.id}\r\n className={cn(\"hsk-sb-row hsk-sb-fade\", classNames.row)}\r\n style={{ animationDelay: `${i * 18}ms` }}\r\n onClick={() => handleSelect(r)}\r\n >\r\n <span className=\"hsk-sb-row-thumb\">\r\n {thumb ? (\r\n <img\r\n src={thumb}\r\n alt=\"\"\r\n loading=\"lazy\"\r\n onError={e => { e.currentTarget.style.display = 'none'; }}\r\n />\r\n ) : (\r\n <SearchIcon />\r\n )}\r\n </span>\r\n <div className=\"hsk-sb-row-body\">\r\n <div className=\"hsk-sb-row-title\">{r.entity.title ?? r.entity.name}</div>\r\n {(r.entity.category || r.entity.brand) && (\r\n <div className=\"hsk-sb-row-sub\">\r\n {r.entity.category ?? r.entity.brand}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","import React, { useState, useRef, useEffect } from 'react';\r\nimport { useKiku, useAkropolysContext, resolveDisplayFields, ChatMessage, ChatSource } from '@akropolys/sdk';\r\nimport { renderMarkdown } from '../utils/markdown';\r\nimport { AkropolysTheme } from '@akropolys/sdk';\r\nimport { cn } from '../utils/cn';\r\nimport { ArrowUpIcon } from '../utils/icons';\r\nimport { resolveTheme } from '../utils/theme';\r\nimport { VoiceButton } from './VoiceButton';\r\nimport { VisualSearch } from './VisualSearch';\r\nimport { speak, stopSpeech } from '../utils/tts';\r\n\r\nexport interface ChatWidgetProps {\r\n title?: string;\r\n placeholder?: string;\r\n emptyStateText?: string;\r\n emptyStateSuggestions?: string;\r\n defaultCurrency?: string;\r\n className?: string;\r\n\r\n theme?: AkropolysTheme;\r\n\r\n classNames?: {\r\n root?: string;\r\n header?: string;\r\n messageBubble?: string;\r\n input?: string;\r\n };\r\n\r\n onSelectSource?: (source: ChatSource) => void;\r\n\r\n enableVoice?: boolean;\r\n /** Enable 📷 visual style-match search */\r\n enableVision?: boolean;\r\n\r\n visionCategoryHint?: string;\r\n\r\n /** Enable 🔊 TTS voice audio responses from AI */\r\n enableAudioResponse?: boolean;\r\n /** Optional AI voice preset */\r\n ttsVoice?: string;\r\n\r\n autoSpeakResponses?: boolean;\r\n}\r\n\r\nconst SparkleIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z\"/>\r\n </svg>\r\n);\r\n\r\nconst SpeakerIcon = ({ active }: { active: boolean }) => (\r\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" fill={active ? 'currentColor' : 'none'} />\r\n {active ? (\r\n <>\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\r\n </>\r\n ) : (\r\n <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\" />\r\n )}\r\n </svg>\r\n);\r\n\r\nfunction SourceCard({\r\n source,\r\n defaultCurrency,\r\n onSelect,\r\n isReferenced\r\n}: {\r\n source: ChatSource;\r\n defaultCurrency: string;\r\n onSelect?: (s: ChatSource) => void;\r\n isReferenced?: boolean;\r\n}) {\r\n return (\r\n <div\r\n className={cn(\"hsk-source-card\", isReferenced && \"hsk-source-card--referenced\")}\r\n onClick={() => onSelect?.(source)}\r\n >\r\n {source.image && <img src={source.image} alt={source.name} className=\"hsk-source-img\" />}\r\n <div style={{ flex: 1, minWidth: 0, position: 'relative' }}>\r\n {isReferenced && (\r\n <div className=\"hsk-cb-source-ref-badge\" title=\"Featured in response\" style={{ top: '0', right: '0' }}>\r\n <SparkleIcon />\r\n </div>\r\n )}\r\n <div className=\"hsk-source-name\" style={{ paddingRight: isReferenced ? '20px' : undefined }}>{source.name}</div>\r\n {source.price && (\r\n <div className=\"hsk-source-price\">{source.currency ?? defaultCurrency} {source.price}</div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\ninterface ChatMessageWithVisual extends ChatMessage {\r\n imagePreview?: string;\r\n styleDNA?: any;\r\n visualSources?: ChatSource[];\r\n}\r\n\r\nexport function ChatWidget({\r\n title = 'kiku',\r\n placeholder = 'Ask about anything in our store…',\r\n emptyStateText = 'Ask me anything about our products',\r\n emptyStateSuggestions = '\"Find me headphones under KSh 5,000\" · \"Gift ideas\"',\r\n defaultCurrency = 'KES',\r\n className,\r\n theme,\r\n classNames = {},\r\n onSelectSource,\r\n enableVoice = false,\r\n enableVision = false,\r\n visionCategoryHint,\r\n enableAudioResponse = true,\r\n ttsVoice,\r\n autoSpeakResponses = true\r\n}: ChatWidgetProps) {\r\n const client = useAkropolysContext();\r\n const { messages, sources, referencedIds, loading: chatLoading, streaming, error, send, reset } = useKiku();\r\n const [input, setInput] = useState('');\r\n const [visualLoading, setVisualLoading] = useState(false);\r\n const bottomRef = useRef<HTMLDivElement>(null);\r\n const textareaRef = useRef<HTMLTextAreaElement>(null);\r\n\r\n const [audioEnabled, setAudioEnabled] = useState(enableAudioResponse);\r\n const [speakingMsgIndex, setSpeakingMsgIndex] = useState<number | null>(null);\r\n const prevStreamingRef = useRef(streaming);\r\n const userInitiatedVoiceRef = useRef(false);\r\n\r\n const loading = chatLoading || visualLoading;\r\n\r\n const [chatHistory, setChatHistory] = useState<ChatMessageWithVisual[]>([]);\r\n const lastSyncedCount = useRef(0);\r\n\r\n useEffect(() => {\r\n if (messages.length === 0) {\r\n setChatHistory([]);\r\n lastSyncedCount.current = 0;\r\n return;\r\n }\r\n\r\n if (messages.length > lastSyncedCount.current) {\r\n const newMsgs = messages.slice(lastSyncedCount.current);\r\n setChatHistory(prev => [...prev, ...newMsgs]);\r\n lastSyncedCount.current = messages.length;\r\n } else if (messages.length < lastSyncedCount.current) {\r\n setChatHistory(messages);\r\n lastSyncedCount.current = messages.length;\r\n } else {\r\n setChatHistory(prev => {\r\n const next = [...prev];\r\n let hookIdx = messages.length - 1;\r\n let historyIdx = next.length - 1;\r\n while (hookIdx >= 0 && historyIdx >= 0) {\r\n if (next[historyIdx].role === messages[hookIdx].role) {\r\n next[historyIdx] = {\r\n ...next[historyIdx],\r\n content: messages[hookIdx].content,\r\n actionType: messages[hookIdx].actionType,\r\n thinking: messages[hookIdx].thinking,\r\n thoughtForSeconds: messages[hookIdx].thoughtForSeconds,\r\n statusMessage: messages[hookIdx].statusMessage,\r\n };\r\n break;\r\n }\r\n historyIdx--;\r\n }\r\n return next;\r\n });\r\n }\r\n }, [messages]);\r\n\r\n useEffect(() => {\r\n const wasStreaming = prevStreamingRef.current;\r\n prevStreamingRef.current = streaming;\r\n\r\n const spoken = userInitiatedVoiceRef.current;\r\n userInitiatedVoiceRef.current = false;\r\n if (wasStreaming && !streaming && spoken && audioEnabled && autoSpeakResponses) {\r\n const lastMsgIndex = chatHistory.length - 1;\r\n const lastMsg = chatHistory[lastMsgIndex];\r\n if (lastMsg && lastMsg.role === 'assistant' && lastMsg.content) {\r\n setSpeakingMsgIndex(lastMsgIndex);\r\n void speak({\r\n client: client as any,\r\n text: lastMsg.content,\r\n voice: ttsVoice,\r\n language: client.getShopperLanguage?.(),\r\n onEnd: () => setSpeakingMsgIndex(null),\r\n onError: () => setSpeakingMsgIndex(null),\r\n });\r\n }\r\n }\r\n }, [streaming, audioEnabled, autoSpeakResponses, chatHistory, ttsVoice, client]);\r\n\r\n useEffect(() => {\r\n bottomRef.current?.scrollIntoView({ behavior: loading ? 'auto' : 'smooth' });\r\n }, [chatHistory, loading]);\r\n\r\n const handleSend = async () => {\r\n const q = input.trim();\r\n if (!q || loading) return;\r\n stopSpeech();\r\n setSpeakingMsgIndex(null);\r\n setInput('');\r\n if (textareaRef.current) textareaRef.current.style.height = 'auto';\r\n await send(q);\r\n };\r\n\r\n const handleKey = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n setInput(e.target.value);\r\n const t = e.target;\r\n t.style.height = 'auto';\r\n t.style.height = Math.min(t.scrollHeight, 120) + 'px';\r\n };\r\n\r\n const handleSpeakToggle = (idx: number, text: string) => {\r\n if (speakingMsgIndex === idx) {\r\n stopSpeech();\r\n setSpeakingMsgIndex(null);\r\n } else {\r\n setSpeakingMsgIndex(idx);\r\n void speak({\r\n client: client as any,\r\n text,\r\n voice: ttsVoice,\r\n language: client.getShopperLanguage?.(),\r\n onEnd: () => setSpeakingMsgIndex(null),\r\n onError: () => setSpeakingMsgIndex(null),\r\n });\r\n }\r\n };\r\n\r\n const handleVisualResults = (res: any, preview: string) => {\r\n const userMsg: ChatMessageWithVisual = {\r\n role: 'user',\r\n content: 'Uploaded a photo for visual search',\r\n imagePreview: preview,\r\n };\r\n\r\n const dna = res.style_dna;\r\n let content = `I've analyzed your image! Here is the Style DNA I found:\\n`;\r\n if (dna) {\r\n if (dna.color_palette) content += `* **Palette:** ${dna.color_palette}\\n`;\r\n if (dna.dominant_colors && dna.dominant_colors.length > 0) {\r\n content += `* **Colors:** ${dna.dominant_colors.join(', ')}\\n`;\r\n }\r\n if (dna.aesthetic && dna.aesthetic.length > 0) {\r\n content += `* **Aesthetic:** ${dna.aesthetic.join(', ')}\\n`;\r\n }\r\n if (dna.texture) content += `* **Texture:** ${dna.texture}\\n`;\r\n if (dna.formality) content += `* **Formality:** ${dna.formality}\\n`;\r\n }\r\n\r\n const results = res.results || [];\r\n if (results.length > 0) {\r\n content += `\\nI found ${results.length} matching products in the store for you.`;\r\n } else {\r\n content += `\\nI couldn't find any matching products in the store.`;\r\n }\r\n\r\n const assistantMsg: ChatMessageWithVisual = {\r\n role: 'assistant',\r\n content,\r\n styleDNA: dna,\r\n visualSources: results.map((r: any) => {\r\n const fields = r.entity ?? {};\r\n const d = resolveDisplayFields(fields, undefined);\r\n return {\r\n id: r.id,\r\n url: r.url ?? fields.url,\r\n fields,\r\n name: d.title,\r\n price: d.price,\r\n image: d.image,\r\n brand: d.subtitle,\r\n currency: typeof fields.currency === 'string' ? fields.currency : undefined,\r\n };\r\n }),\r\n };\r\n\r\n setChatHistory(prev => [...prev, userMsg, assistantMsg]);\r\n };\r\n\r\n const { vars: customStyles } = resolveTheme(theme);\r\n\r\n return (\r\n <div\r\n className={cn(\"hsk-chat-widget\", classNames.root, className)}\r\n style={customStyles}\r\n >\r\n <div className={cn(\"hsk-chat-header\", classNames.header)}>\r\n <span className=\"hsk-chat-header-icon\"><SparkleIcon /></span>\r\n <span className=\"hsk-chat-title\">{title}</span>\r\n <span className=\"hsk-chat-badge\">AI</span>\r\n <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: '8px' }}>\r\n {enableAudioResponse && (\r\n <button\r\n type=\"button\"\r\n className={cn(\"hsk-audio-toggle-btn\", audioEnabled && \"hsk-audio-toggle-btn--active\")}\r\n onClick={() => {\r\n const next = !audioEnabled;\r\n setAudioEnabled(next);\r\n if (!next) {\r\n stopSpeech();\r\n setSpeakingMsgIndex(null);\r\n }\r\n }}\r\n title={audioEnabled ? \"Mute AI audio response\" : \"Enable AI audio response\"}\r\n aria-label={audioEnabled ? \"Mute voice\" : \"Enable voice\"}\r\n >\r\n <SpeakerIcon active={audioEnabled} />\r\n </button>\r\n )}\r\n {chatHistory.length > 0 && (\r\n <button className=\"hsk-chat-reset\" onClick={() => { stopSpeech(); reset(); }}>Clear</button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"hsk-chat-messages\">\r\n {chatHistory.length === 0 ? (\r\n <div className=\"hsk-chat-empty\">\r\n <div className=\"hsk-chat-empty-icon\"><SparkleIcon /></div>\r\n <div>{emptyStateText}</div>\r\n <div className=\"hsk-chat-empty-suggestions\">{emptyStateSuggestions}</div>\r\n </div>\r\n ) : (\r\n chatHistory.map((msg, idx) => (\r\n <div key={idx}>\r\n <div className={`hsk-msg-row ${msg.role}`}>\r\n <div className={cn(\"hsk-msg-avatar\", msg.role === 'assistant' ? 'ai' : 'user')}>\r\n {msg.role === 'assistant' ? <SparkleIcon /> : 'U'}\r\n </div>\r\n <div className={cn(\"hsk-msg-bubble\", msg.role, classNames.messageBubble)}>\r\n {msg.imagePreview && (\r\n <div className=\"kiku-vs-preview-bubble\" style={{ marginBottom: '8px' }}>\r\n <img src={msg.imagePreview} alt=\"Uploaded Preview\" className=\"kiku-vs-preview-bubble-img\" style={{ maxWidth: '200px', borderRadius: '8px' }} />\r\n </div>\r\n )}\r\n {msg.thinking && (\r\n <details className=\"hsk-thinking-details\" open={streaming && idx === chatHistory.length - 1 && !msg.content}>\r\n <summary className=\"hsk-thinking-summary\">\r\n Thought for {msg.thoughtForSeconds ?? 1}s\r\n </summary>\r\n <div className=\"hsk-thinking-text\">{msg.thinking}</div>\r\n </details>\r\n )}\r\n {(!msg.content && !msg.thinking && msg.role === 'assistant' && idx === chatHistory.length - 1) && (\r\n <div className=\"hsk-status-live\">\r\n <span className=\"hsk-status-dot\" />\r\n <span>{msg.statusMessage || 'Thinking...'}</span>\r\n </div>\r\n )}\r\n {renderMarkdown(msg.content)}\r\n {msg.role === 'assistant' && msg.content && !streaming && (\r\n <button\r\n type=\"button\"\r\n className={cn(\"hsk-msg-audio-btn\", speakingMsgIndex === idx && \"hsk-msg-audio-btn--active\")}\r\n onClick={() => handleSpeakToggle(idx, msg.content)}\r\n title={speakingMsgIndex === idx ? \"Stop speaking\" : \"Listen to response\"}\r\n aria-label=\"Toggle speech\"\r\n >\r\n <SpeakerIcon active={speakingMsgIndex === idx} />\r\n </button>\r\n )}\r\n {streaming && idx === chatHistory.length - 1 && msg.role === 'assistant' && (\r\n <span className=\"hsk-streaming-cursor\" />\r\n )}\r\n {msg.styleDNA && (\r\n <div className=\"kiku-vs-preview-banner\" style={{ marginTop: '10px' }}>\r\n {chatHistory[idx - 1]?.imagePreview && (\r\n <img src={chatHistory[idx - 1].imagePreview} alt=\"Visual Search Input\" className=\"kiku-vs-preview-img\" />\r\n )}\r\n <div className=\"kiku-vs-preview-info\">\r\n <div className=\"kiku-vs-preview-label\">Visual Match Palette</div>\r\n <div className=\"kiku-vs-preview-palette\">{msg.styleDNA.color_palette || 'Detected Style DNA'}</div>\r\n {msg.styleDNA.style_tags && msg.styleDNA.style_tags.length > 0 && (\r\n <div className=\"kiku-style-tags\">\r\n {msg.styleDNA.style_tags.map((tag: string, ti: number) => (\r\n <span key={ti} className=\"kiku-style-tag\">#{tag}</span>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n {msg.role === 'assistant' && msg.visualSources && msg.visualSources.length > 0 && (\r\n <div className=\"hsk-sources-container\">\r\n <div className=\"hsk-sources\">\r\n {msg.visualSources.map((src, si) => (\r\n <SourceCard key={si} source={src} defaultCurrency={defaultCurrency} onSelect={onSelectSource} />\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n {msg.role === 'assistant' && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && (() => {\r\n const isStreamingActive = chatLoading || streaming;\r\n if (isStreamingActive) {\r\n return (\r\n <div className=\"hsk-sources-container\">\r\n <div className=\"hsk-sources\">\r\n {sources.map((src, si) => {\r\n const isReferenced = !!(src.id && referencedIds.includes(src.id));\r\n return (\r\n <SourceCard\r\n key={si}\r\n source={src}\r\n defaultCurrency={defaultCurrency}\r\n onSelect={onSelectSource}\r\n isReferenced={isReferenced}\r\n />\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n const featured = sources.filter(src => src.id && referencedIds.includes(src.id));\r\n const general = referencedIds.length > 0\r\n ? []\r\n : sources.filter(src => !src.id || !referencedIds.includes(src.id));\r\n\r\n return (\r\n <div className=\"hsk-sources-container\">\r\n {featured.length > 0 && (\r\n <div className=\"hsk-sources-group\" style={{ marginBottom: '10px' }}>\r\n <div className=\"hsk-sources-group-title\">⭐ Featured in response</div>\r\n <div className=\"hsk-sources\">\r\n {featured.map((src, si) => (\r\n <SourceCard\r\n key={`feat-${si}`}\r\n source={src}\r\n defaultCurrency={defaultCurrency}\r\n onSelect={onSelectSource}\r\n isReferenced={true}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n {general.length > 0 && (\r\n <div className=\"hsk-sources-group\">\r\n {featured.length > 0 && <div className=\"hsk-sources-group-title\">All matches</div>}\r\n <div className=\"hsk-sources\">\r\n {general.map((src, si) => (\r\n <SourceCard\r\n key={`gen-${si}`}\r\n source={src}\r\n defaultCurrency={defaultCurrency}\r\n onSelect={onSelectSource}\r\n isReferenced={false}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })()}\r\n </div>\r\n ))\r\n )}\r\n\r\n {loading && (\r\n <div className=\"hsk-msg-row\">\r\n <div className=\"hsk-msg-avatar ai\"><SparkleIcon /></div>\r\n <div className=\"hsk-pending\" role=\"status\" aria-live=\"polite\">\r\n <div className=\"hsk-pending-glyph\">\r\n <span className=\"hsk-pending-ring\" />\r\n <span className=\"hsk-pending-dot\" />\r\n </div>\r\n <div className=\"hsk-pending-text\">\r\n <span className=\"hsk-pending-step step-1\">Searching catalog</span>\r\n <span className=\"hsk-pending-step step-2\">Reasoning</span>\r\n <span className=\"hsk-pending-step step-3\">Composing</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"hsk-chat-error\">\r\n {(() => {\r\n try {\r\n const parsed = JSON.parse(error);\r\n return parsed.error || parsed.message || error;\r\n } catch {\r\n return error;\r\n }\r\n })()}\r\n </div>\r\n )}\r\n <div ref={bottomRef} />\r\n </div>\r\n\r\n <div className=\"hsk-chat-input-area\" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\r\n {enableVision && (\r\n <VisualSearch\r\n onResults={handleVisualResults}\r\n onError={(err) => console.error('[VisualSearch] error:', err)}\r\n categoryHint={visionCategoryHint}\r\n disabled={loading}\r\n />\r\n )}\r\n <textarea\r\n ref={textareaRef}\r\n className={cn(\"hsk-chat-input\", classNames.input)}\r\n value={input}\r\n onChange={handleInput}\r\n onKeyDown={handleKey}\r\n placeholder={placeholder}\r\n rows={1}\r\n disabled={loading}\r\n style={{ flex: 1 }}\r\n />\r\n {enableVoice && (\r\n <VoiceButton\r\n onTranscript={(text) => {\r\n userInitiatedVoiceRef.current = true;\r\n stopSpeech();\r\n setSpeakingMsgIndex(null);\r\n setInput(text);\r\n send(text);\r\n setInput('');\r\n }}\r\n onInterim={(text) => setInput(text)}\r\n disabled={loading}\r\n />\r\n )}\r\n <button\r\n className=\"hsk-chat-send\"\r\n onClick={handleSend}\r\n disabled={!input.trim() || loading}\r\n aria-label=\"Send message\"\r\n >\r\n <ArrowUpIcon />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n","import React from 'react';\r\n\r\nconst SPACING_DOUBLE_REGEX = /[ \\t]{2,}/g;\r\nconst SPACING_PUNCT_REGEX = / ([.,!?:;])/g;\r\nconst SPACING_OPEN_PAREN_REGEX = /\\(([ \\t]+)/g;\r\nconst SPACING_CLOSE_PAREN_REGEX = /([ \\t]+)\\)/g;\r\nconst SPACING_UNIT_REGEX = /(\\d+)\\s+(MP|mAh|W|GB|MB|KHz|Hz|KSh|KES|USD|EUR)\\b/gi;\r\n\r\nconst TOKEN_SPLIT_REGEX = /(!\\[[^\\]]*\\]\\([^)]+\\)|\\[[^\\]]+\\]\\([^)]+\\)|\\*\\*[^*]+\\*\\*|`[^`]+`)/g;\r\nconst IMAGE_PARSE_REGEX = /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\r\nconst LINK_PARSE_REGEX = /^\\[([^\\]]+)\\]\\(([^)]+)\\)$/;\r\nconst SAFE_IMG_REGEX = /^(https?|data:image|blob):/i;\r\nconst SAFE_LINK_REGEX = /^(https?|mailto|tel):/i;\r\nconst MEMORY_LINK_FILTER_REGEX = /memory|mimi/i;\r\nconst MEMORY_URL_FILTER_REGEX = /mimi\\.akropolys/i;\r\n\r\nconst normalizeSpacing = (text: string): string => {\r\n if (!text) return text;\r\n return text\r\n .replace(SPACING_DOUBLE_REGEX, ' ')\r\n .replace(SPACING_PUNCT_REGEX, '$1')\r\n .replace(SPACING_OPEN_PAREN_REGEX, '(')\r\n .replace(SPACING_CLOSE_PAREN_REGEX, ')')\r\n .replace(SPACING_UNIT_REGEX, '$1 $2');\r\n};\r\n\r\nconst parseInline = (text: string, keyPrefix: string): React.ReactNode => {\r\n const normalizedText = normalizeSpacing(text);\r\n const parts = normalizedText.split(TOKEN_SPLIT_REGEX);\r\n\r\n return parts.map((part, index) => {\r\n if (!part) return null;\r\n const key = `${keyPrefix}-inline-${index}`;\r\n\r\n if (part.startsWith('`') && part.endsWith('`')) {\r\n return (\r\n <code key={key} className=\"hsk-markdown-code\">\r\n {part.slice(1, -1)}\r\n </code>\r\n );\r\n }\r\n\r\n if (part.startsWith('**') && part.endsWith('**')) {\r\n return <strong key={key}>{parseInline(part.slice(2, -2), key)}</strong>;\r\n }\r\n\r\n const imageMatch = part.match(IMAGE_PARSE_REGEX);\r\n if (imageMatch) {\r\n const alt = imageMatch[1];\r\n const url = imageMatch[2];\r\n const isSafeUrl = SAFE_IMG_REGEX.test(url) || url.startsWith('/');\r\n if (isSafeUrl) {\r\n return (\r\n <img\r\n key={key}\r\n src={url}\r\n alt={alt || 'Product image'}\r\n className=\"hsk-markdown-img\"\r\n loading=\"lazy\"\r\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\r\n />\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n const linkMatch = part.match(LINK_PARSE_REGEX);\r\n if (linkMatch) {\r\n const linkText = linkMatch[1];\r\n const url = linkMatch[2];\r\n if (MEMORY_LINK_FILTER_REGEX.test(linkText) || MEMORY_URL_FILTER_REGEX.test(url)) {\r\n return null;\r\n }\r\n const isSafeUrl = SAFE_LINK_REGEX.test(url) || url.startsWith('/');\r\n if (isSafeUrl) {\r\n return (\r\n <a key={key} href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"hsk-markdown-link\">\r\n {parseInline(linkText, key)}\r\n </a>\r\n );\r\n }\r\n return <span key={key}>{parseInline(linkText, key)}</span>;\r\n }\r\n\r\n return part;\r\n });\r\n};\r\n\r\nfunction isTableLine(line: string, inTable: boolean): boolean {\r\n const t = line.trim();\r\n if (inTable) return t.includes('|');\r\n return t.startsWith('|');\r\n}\r\n\r\nfunction splitTableCells(rowLine: string): string[] {\r\n let t = rowLine.trim();\r\n if (t.startsWith('|')) t = t.slice(1);\r\n if (t.endsWith('|')) t = t.slice(0, -1);\r\n return t.split('|').map(c => c.trim());\r\n}\r\n\r\nexport function TableWrapper({ children }: { children: React.ReactNode }) {\r\n const ref = React.useRef<HTMLDivElement>(null);\r\n const [scrollState, setScrollState] = React.useState<'left' | 'middle' | 'right' | 'none'>('none');\r\n const [isDragging, setIsDragging] = React.useState(false);\r\n const dragRef = React.useRef({ startX: 0, scrollLeft: 0, isDown: false, hasMoved: false });\r\n\r\n const checkScroll = React.useCallback(() => {\r\n const el = ref.current;\r\n if (!el) return;\r\n const canScroll = el.scrollWidth > el.clientWidth + 2;\r\n if (!canScroll) {\r\n setScrollState('none');\r\n return;\r\n }\r\n const rtl = getComputedStyle(el).direction === 'rtl';\r\n const travelled = Math.abs(el.scrollLeft);\r\n const atStart = travelled <= 4;\r\n const atEnd = travelled + el.clientWidth >= el.scrollWidth - 4;\r\n if (atStart) setScrollState(rtl ? 'right' : 'left');\r\n else if (atEnd) setScrollState(rtl ? 'left' : 'right');\r\n else setScrollState('middle');\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n checkScroll();\r\n const el = ref.current;\r\n if (!el) return;\r\n const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(checkScroll) : null;\r\n ro?.observe(el);\r\n return () => ro?.disconnect();\r\n }, [checkScroll]);\r\n\r\n const onMouseDown = (e: React.MouseEvent) => {\r\n const el = ref.current;\r\n if (!el || el.scrollWidth <= el.clientWidth) return;\r\n if ((e.target as HTMLElement).closest('a, button, input')) return;\r\n dragRef.current = { startX: e.pageX - el.offsetLeft, scrollLeft: el.scrollLeft, isDown: true, hasMoved: false };\r\n setIsDragging(true);\r\n };\r\n\r\n const onMouseMove = (e: React.MouseEvent) => {\r\n if (!dragRef.current.isDown) return;\r\n const el = ref.current;\r\n if (!el) return;\r\n const x = e.pageX - el.offsetLeft;\r\n const walk = (x - dragRef.current.startX) * 1.5;\r\n if (Math.abs(walk) > 3) {\r\n dragRef.current.hasMoved = true;\r\n e.preventDefault();\r\n el.scrollLeft = dragRef.current.scrollLeft - walk;\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n dragRef.current.isDown = false;\r\n setIsDragging(false);\r\n };\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={`hsk-table-wrapper hsk-table-wrapper--${scrollState}${isDragging ? ' is-dragging' : ''}`}\r\n onScroll={checkScroll}\r\n onMouseDown={onMouseDown}\r\n onMouseMove={onMouseMove}\r\n onMouseUp={onMouseUp}\r\n onMouseLeave={onMouseUp}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function renderMarkdown(content: string, streaming = false): React.ReactNode {\r\n return buildMarkdown(content, streaming);\r\n}\r\n\r\nfunction buildMarkdown(content: string, streaming: boolean): React.ReactNode {\r\n const lines = content.split('\\n');\r\n if (streaming && lines.length > 0) {\r\n const last = lines[lines.length - 1];\r\n if (last.trim().startsWith('|') && !last.trim().endsWith('|')) {\r\n lines.pop();\r\n }\r\n }\r\n\r\n const blocks: React.ReactNode[] = [];\r\n let currentTextNodes: React.ReactNode[] = [];\r\n let bubbleIndex = 0;\r\n\r\n const flushTextBubble = () => {\r\n if (currentTextNodes.length > 0) {\r\n blocks.push(\r\n <div key={`text-bubble-${bubbleIndex++}`} className=\"hsk-cb-ai-text\">\r\n {currentTextNodes}\r\n </div>\r\n );\r\n currentTextNodes = [];\r\n }\r\n };\r\n\r\n let i = 0;\r\n while (i < lines.length) {\r\n const line = lines[i];\r\n const key = `md-line-${i}`;\r\n\r\n if (!line.trim()) {\r\n i++;\r\n continue;\r\n }\r\n\r\n const standaloneImageMatch = line.trim().match(/^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/);\r\n if (standaloneImageMatch) {\r\n flushTextBubble();\r\n const alt = standaloneImageMatch[1];\r\n const url = standaloneImageMatch[2];\r\n const isSafeUrl = /^(https?|data:image|blob):/i.test(url) || url.startsWith('/');\r\n if (isSafeUrl) {\r\n blocks.push(\r\n <div key={key} className=\"hsk-markdown-img-block\">\r\n <img\r\n src={url}\r\n alt={alt || 'Product image'}\r\n className=\"hsk-markdown-img\"\r\n loading=\"lazy\"\r\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\r\n />\r\n </div>\r\n );\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n const headerMatch = line.match(/^(#{1,3})\\s+(.*)/);\r\n if (headerMatch) {\r\n const level = headerMatch[1].length;\r\n const Tag = `h${level + 3}` as keyof JSX.IntrinsicElements; // Maps # to h4, ## to h5 to avoid messing up host page hierarchy\r\n currentTextNodes.push(<Tag key={key} className={`hsk-markdown-h${level}`}>{parseInline(headerMatch[2], key)}</Tag>);\r\n i++;\r\n continue;\r\n }\r\n\r\n if (line.match(/^[\\s]*[-*+•]\\s+/)) {\r\n const listItems: React.ReactNode[] = [];\r\n while (i < lines.length && lines[i].match(/^[\\s]*[-*+•]\\s+/)) {\r\n const itemText = lines[i].replace(/^[\\s]*[-*+•]\\s+/, '');\r\n listItems.push(<li key={`li-${i}`}>{parseInline(itemText, `li-${i}`)}</li>);\r\n i++;\r\n }\r\n currentTextNodes.push(<ul key={`ul-${key}`} className=\"hsk-markdown-list hsk-markdown-ul\">{listItems}</ul>);\r\n continue;\r\n }\r\n\r\n if (line.match(/^[\\s]*\\d+[\\.\\)]\\s+/)) {\r\n const listItems: React.ReactNode[] = [];\r\n while (i < lines.length && lines[i].match(/^[\\s]*\\d+[\\.\\)]\\s+/)) {\r\n const itemText = lines[i].replace(/^[\\s]*\\d+[\\.\\)]\\s+/, '');\r\n listItems.push(<li key={`li-${i}`}>{parseInline(itemText, `li-${i}`)}</li>);\r\n i++;\r\n }\r\n currentTextNodes.push(<ol key={`ol-${key}`} className=\"hsk-markdown-list hsk-markdown-ol\">{listItems}</ol>);\r\n continue;\r\n }\r\n\r\n if (isTableLine(line, false)) {\r\n flushTextBubble();\r\n\r\n let headerCells: string[] = [];\r\n const rawBodyRows: string[][] = [];\r\n let alignments: ('start' | 'center' | 'end')[] = [];\r\n let isHeader = true;\r\n\r\n while (i < lines.length && isTableLine(lines[i], true)) {\r\n const rowLine = lines[i].trim();\r\n if (rowLine.match(/^\\|?[-:| ]+\\|?$/) && rowLine.includes('-')) {\r\n const sepCells = splitTableCells(rowLine);\r\n alignments = sepCells.map(cell => {\r\n const trimmed = cell.trim();\r\n const startColon = trimmed.startsWith(':');\r\n const endColon = trimmed.endsWith(':');\r\n if (startColon && endColon) return 'center';\r\n if (endColon) return 'end';\r\n return 'start';\r\n });\r\n i++;\r\n isHeader = false;\r\n continue;\r\n }\r\n\r\n const cells = splitTableCells(rowLine);\r\n\r\n if (isHeader && headerCells.length === 0) {\r\n headerCells = cells;\r\n } else {\r\n rawBodyRows.push(cells);\r\n }\r\n i++;\r\n }\r\n\r\n const colCount = Math.max(headerCells.length, ...rawBodyRows.map(r => r.length));\r\n const finalAlignments: ('start' | 'center' | 'end')[] = [];\r\n for (let c = 0; c < colCount; c++) {\r\n if (alignments[c]) {\r\n finalAlignments[c] = alignments[c];\r\n } else if (c === 0) {\r\n finalAlignments[c] = 'start';\r\n } else {\r\n const numericCount = rawBodyRows.filter(r => {\r\n const val = (r[c] || '').trim();\r\n return /^[\\$€£¥+-]?\\d+([.,]\\d+)?%?$/.test(val) || /^[\\$€£¥+-]?\\d+([.,]\\d+)?\\s*(bps|M|K|B)?$/i.test(val);\r\n }).length;\r\n finalAlignments[c] = numericCount >= Math.ceil(rawBodyRows.length / 2) ? 'end' : 'start';\r\n }\r\n }\r\n\r\n const headerRow = headerCells.length > 0 ? (\r\n <tr key={`tr-head-${key}`}>\r\n {headerCells.map((cell, cIdx) => (\r\n <th\r\n key={`th-${key}-${cIdx}`}\r\n style={{ textAlign: finalAlignments[cIdx] || 'start' }}\r\n >\r\n {}\r\n <bdi>{parseInline(cell, `th-${key}-${cIdx}`)}</bdi>\r\n </th>\r\n ))}\r\n </tr>\r\n ) : null;\r\n\r\n const bodyRows = rawBodyRows.map((cells, rIdx) => (\r\n <tr key={`tr-body-${key}-${rIdx}`}>\r\n {cells.map((cell, cIdx) => (\r\n <td\r\n key={`td-${key}-${rIdx}-${cIdx}`}\r\n style={{ textAlign: finalAlignments[cIdx] || 'start' }}\r\n >\r\n <bdi>{parseInline(cell, `td-${key}-${rIdx}-${cIdx}`)}</bdi>\r\n </td>\r\n ))}\r\n </tr>\r\n ));\r\n\r\n blocks.push(\r\n <TableWrapper key={`table-wrapper-${key}`}>\r\n <table className=\"hsk-markdown-table\">\r\n {headerRow && <thead>{headerRow}</thead>}\r\n <tbody>{bodyRows}</tbody>\r\n </table>\r\n </TableWrapper>\r\n );\r\n continue;\r\n }\r\n\r\n currentTextNodes.push(\r\n <p key={key} className=\"hsk-markdown-p\">\r\n {parseInline(line, key)}\r\n </p>\r\n );\r\n i++;\r\n }\r\n\r\n flushTextBubble();\r\n\r\n return <>{blocks}</>;\r\n}\r\n","import React from 'react';\r\n\r\nexport const ArrowUpIcon = () => (\r\n <svg\r\n className=\"hsk-telegram-icon\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n >\r\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\r\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\r\n </svg>\r\n);\r\n\r\nexport const TelegramSendIcon = ArrowUpIcon;\r\n\r\n","import type { CSSProperties } from 'react';\r\nimport type { AkropolysTheme } from '@akropolys/sdk';\r\n\r\nexport type ThemeProp = string | AkropolysTheme | undefined;\r\n\r\nexport function resolveTheme(theme: ThemeProp): {\r\n themeAttr: string | undefined;\r\n vars: CSSProperties | undefined;\r\n} {\r\n if (typeof theme === 'string') {\r\n return { themeAttr: theme as any, vars: undefined };\r\n }\r\n if (!theme) {\r\n return { themeAttr: undefined, vars: undefined };\r\n }\r\n const vars: Record<string, string> = {};\r\n if (theme.primaryColor) vars['--hsk-primary'] = theme.primaryColor;\r\n if (theme.backgroundColor) {\r\n vars['--hsk-bg'] = theme.backgroundColor;\r\n vars['--hsk-chat-bg'] = theme.backgroundColor;\r\n }\r\n if (theme.textColor) {\r\n vars['--hsk-text'] = theme.textColor;\r\n vars['--hsk-chat-text'] = theme.textColor;\r\n }\r\n if (theme.fontFamily) vars['--hsk-font'] = theme.fontFamily;\r\n if (theme.fontSize) vars['--hsk-font-size'] = theme.fontSize;\r\n if (theme.mobileFontSize) vars['--hsk-mobile-font-size'] = theme.mobileFontSize;\r\n if (theme.borderRadius) vars['--hsk-border-radius'] = theme.borderRadius;\r\n return { themeAttr: undefined, vars: vars as CSSProperties };\r\n}\r\n","import React, { useCallback, useEffect, useRef } from 'react';\r\nimport { useVoiceSession } from '../utils/voiceSession';\r\n\r\nexport interface VoiceButtonProps {\r\n onTranscript: (text: string) => void;\r\n onInterim?: (text: string) => void;\r\n /** BCP-47 tag. Defaults to the page's <html lang>, then the browser language. */\r\n lang?: string;\r\n className?: string;\r\n disabled?: boolean;\r\n /** Raw SpeechRecognition error code — 'not-allowed', 'audio-capture', etc. */\r\n onError?: (code: string) => void;\r\n}\r\n\r\nconst MicIcon = ({ active }: { active: boolean }) => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"11\" rx=\"3\" fill={active ? 'currentColor' : 'none'} />\r\n <path d=\"M5 10a7 7 0 0 0 14 0\" />\r\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" />\r\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\" />\r\n </svg>\r\n);\r\n\r\n/**\r\n * VoiceButton — speech to text input with pause-based utterance detection.\r\n */\r\nexport function VoiceButton({\r\n onTranscript,\r\n onInterim,\r\n lang,\r\n className = '',\r\n disabled = false,\r\n onError,\r\n}: VoiceButtonProps) {\r\n const onTranscriptRef = useRef(onTranscript);\r\n useEffect(() => { onTranscriptRef.current = onTranscript; }, [onTranscript]);\r\n\r\n const stopRef = useRef<() => void>(() => {});\r\n const handleUtterance = useCallback((text: string) => {\r\n stopRef.current();\r\n onTranscriptRef.current(text);\r\n }, []);\r\n\r\n const voice = useVoiceSession({ lang, onUtterance: handleUtterance, onError });\r\n useEffect(() => { stopRef.current = voice.stop; }, [voice.stop]);\r\n\r\n useEffect(() => {\r\n if (voice.interim) onInterim?.(voice.interim);\r\n }, [voice.interim, onInterim]);\r\n\r\n if (!voice.supported) return null;\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={`kiku-voice-btn${voice.active ? ' kiku-voice-btn--active' : ''} ${className}`}\r\n onClick={() => (voice.active ? voice.stop() : void voice.start())}\r\n disabled={disabled}\r\n title={voice.active ? 'Stop listening' : 'Speak your search'}\r\n aria-label={voice.active ? 'Stop voice input' : 'Start voice input'}\r\n >\r\n <MicIcon active={voice.active} />\r\n {voice.active && <span className=\"kiku-voice-ripple\" aria-hidden=\"true\" />}\r\n </button>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { speechLevel, duckSpeech } from './tts';\r\n\r\nexport type VoicePhase = 'idle' | 'listening' | 'thinking' | 'speaking';\r\n\r\nexport interface VoiceSessionOptions {\r\n /** BCP-47 tag for recognition. */\r\n lang?: string;\r\n\r\n onUtterance: (text: string) => void;\r\n /** Raw SpeechRecognition error code. */\r\n onError?: (code: string) => void;\r\n\r\n onBargeIn?: () => void;\r\n /** Silence, in ms, that ends an utterance. */\r\n silenceMs?: number;\r\n\r\n paused?: boolean;\r\n}\r\n\r\nconst DEFAULT_SILENCE_MS = 1100;\r\nconst SPEECH_MARGIN = 0.012;\r\nconst BARGE_IN_MS = 320;\r\nconst ECHO_REJECT = 0.09;\r\n\r\nconst DUCK_LEVEL = 0.25;\r\nconst DUCK_FADE_MS = 130;\r\nconst CONFIRM_MS = 700;\r\nconst CONFIRM_FRAMES = 12;\r\n\r\nconst MOD_WINDOW = 48; // ~0.8s of envelope history at 60fps\r\n\r\nconst W_ENERGY = 0.45;\r\nconst W_MODULATION = 0.35;\r\nconst W_BAND = 0.20;\r\nconst DUCK_SCORE = 0.55;\r\n\r\nexport function useVoiceSession({\r\n lang,\r\n onUtterance,\r\n onError,\r\n onBargeIn,\r\n silenceMs = DEFAULT_SILENCE_MS,\r\n paused = false,\r\n}: VoiceSessionOptions) {\r\n const [active, setActive] = useState(false);\r\n const [hearing, setHearing] = useState(false);\r\n const [interim, setInterim] = useState('');\r\n const [supported, setSupported] = useState(false);\r\n\r\n const recognitionRef = useRef<any>(null);\r\n const streamRef = useRef<MediaStream | null>(null);\r\n const audioCtxRef = useRef<AudioContext | null>(null);\r\n const analyserRef = useRef<AnalyserNode | null>(null);\r\n const rafRef = useRef<number | null>(null);\r\n const dataRef = useRef<Uint8Array | null>(null);\r\n\r\n const levelRef = useRef(0);\r\n const floorRef = useRef(0.008);\r\n const lastLoudRef = useRef(0);\r\n const loudSinceRef = useRef(0);\r\n const transcriptRef = useRef('');\r\n const consumedRef = useRef(0);\r\n const resultLenRef = useRef(0);\r\n const activeRef = useRef(false);\r\n const pausedRef = useRef(paused);\r\n const wantRestartRef = useRef(false);\r\n const stoppingRef = useRef(false);\r\n\r\n const onUtteranceRef = useRef(onUtterance);\r\n const onErrorRef = useRef(onError);\r\n const onBargeInRef = useRef(onBargeIn);\r\n useEffect(() => { onUtteranceRef.current = onUtterance; }, [onUtterance]);\r\n useEffect(() => { onErrorRef.current = onError; }, [onError]);\r\n useEffect(() => { onBargeInRef.current = onBargeIn; }, [onBargeIn]);\r\n useEffect(() => { pausedRef.current = paused; }, [paused]);\r\n\r\n useEffect(() => {\r\n setSupported(\r\n typeof window !== 'undefined' &&\r\n ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) &&\r\n !!navigator.mediaDevices?.getUserMedia\r\n );\r\n }, []);\r\n\r\n const micLevel = useCallback(() => levelRef.current, []);\r\n\r\n const micSpectrum = useCallback((out: Uint8Array) => {\r\n const a = analyserRef.current;\r\n if (!a || out.length !== a.frequencyBinCount) return false;\r\n a.getByteFrequencyData(out as any);\r\n return true;\r\n }, []);\r\n\r\n const spectrumBins = useCallback(() => analyserRef.current?.frequencyBinCount ?? 0, []);\r\n\r\n const envRef = useRef<number[]>([]);\r\n const freqRef = useRef<Uint8Array | null>(null);\r\n const duckedRef = useRef(false);\r\n const duckAtRef = useRef(0);\r\n const bargeEvidenceRef = useRef(0);\r\n\r\n const voiceLikeness = useCallback((rms: number): number => {\r\n const analyser = analyserRef.current;\r\n if (!analyser) return 0;\r\n\r\n const env = envRef.current;\r\n env.push(rms);\r\n if (env.length > MOD_WINDOW) env.shift();\r\n\r\n let modulation = 0;\r\n if (env.length >= 12) {\r\n let mean = 0;\r\n for (const v of env) mean += v;\r\n mean /= env.length;\r\n if (mean > 0.0001) {\r\n let variance = 0;\r\n for (const v of env) variance += (v - mean) * (v - mean);\r\n modulation = Math.min(1, Math.sqrt(variance / env.length) / mean / 0.6);\r\n }\r\n }\r\n\r\n let band = 0;\r\n if (!freqRef.current || freqRef.current.length !== analyser.frequencyBinCount) {\r\n freqRef.current = new Uint8Array(analyser.frequencyBinCount);\r\n }\r\n const freq = freqRef.current;\r\n analyser.getByteFrequencyData(freq as any);\r\n const nyquist = (audioCtxRef.current?.sampleRate ?? 48000) / 2;\r\n const per = nyquist / freq.length;\r\n const lo = Math.floor(300 / per);\r\n const hi = Math.min(freq.length - 1, Math.ceil(3400 / per));\r\n let inBand = 0, total = 0;\r\n for (let i = 0; i < freq.length; i++) {\r\n total += freq[i];\r\n if (i >= lo && i <= hi) inBand += freq[i];\r\n }\r\n if (total > 0) band = inBand / total;\r\n\r\n const energy = Math.min(1, rms / (floorRef.current + SPEECH_MARGIN * 3));\r\n return W_ENERGY * energy + W_MODULATION * modulation + W_BAND * band;\r\n }, []);\r\n\r\n const commit = useCallback(() => {\r\n const text = transcriptRef.current.trim();\r\n transcriptRef.current = '';\r\n consumedRef.current = resultLenRef.current;\r\n setInterim('');\r\n setHearing(false);\r\n if (text) onUtteranceRef.current(text);\r\n }, []);\r\n\r\n const monitor = useCallback(() => {\r\n const analyser = analyserRef.current;\r\n const data = dataRef.current;\r\n if (!analyser || !data) return;\r\n\r\n analyser.getByteTimeDomainData(data as any);\r\n let sum = 0;\r\n for (let i = 0; i < data.length; i++) {\r\n const v = (data[i] - 128) / 128;\r\n sum += v * v;\r\n }\r\n const rms = Math.sqrt(sum / data.length);\r\n const lvl = Math.min(1, rms * 4);\r\n levelRef.current += (lvl - levelRef.current) * (lvl > levelRef.current ? 0.6 : 0.12);\r\n\r\n const now = Date.now();\r\n const echo = pausedRef.current ? speechLevel() * ECHO_REJECT : 0;\r\n const speech = rms > floorRef.current + SPEECH_MARGIN + echo;\r\n if (speech) {\r\n lastLoudRef.current = now;\r\n if (!loudSinceRef.current) loudSinceRef.current = now;\r\n } else {\r\n loudSinceRef.current = 0;\r\n floorRef.current = Math.min(floorRef.current * 1.02 + 0.00002, Math.max(0.004, rms));\r\n }\r\n\r\n if (pausedRef.current) {\r\n if (!duckedRef.current) {\r\n if (loudSinceRef.current && now - loudSinceRef.current > BARGE_IN_MS &&\r\n voiceLikeness(rms) > DUCK_SCORE) {\r\n loudSinceRef.current = 0;\r\n duckedRef.current = true;\r\n duckAtRef.current = now;\r\n bargeEvidenceRef.current = 0;\r\n duckSpeech(DUCK_LEVEL, DUCK_FADE_MS);\r\n }\r\n } else {\r\n if (voiceLikeness(rms) > DUCK_SCORE) bargeEvidenceRef.current += 1;\r\n else bargeEvidenceRef.current = Math.max(0, bargeEvidenceRef.current - 2);\r\n\r\n if (bargeEvidenceRef.current >= CONFIRM_FRAMES) {\r\n duckedRef.current = false;\r\n bargeEvidenceRef.current = 0;\r\n duckSpeech(1, 0);\r\n onBargeInRef.current?.();\r\n } else if (now - duckAtRef.current > CONFIRM_MS) {\r\n duckedRef.current = false;\r\n bargeEvidenceRef.current = 0;\r\n duckSpeech(1, DUCK_FADE_MS * 2);\r\n }\r\n }\r\n } else if (transcriptRef.current.trim() && now - lastLoudRef.current > silenceMs) {\r\n commit();\r\n }\r\n\r\n rafRef.current = requestAnimationFrame(monitor);\r\n }, [commit, silenceMs, voiceLikeness]);\r\n\r\n const startRecognition = useCallback(() => {\r\n if (recognitionRef.current || !activeRef.current) return;\r\n const SR: any = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;\r\n const recognition = new SR();\r\n consumedRef.current = 0;\r\n resultLenRef.current = 0;\r\n recognition.lang = lang || document.documentElement.lang || navigator.language || 'en-US';\r\n recognition.interimResults = true;\r\n recognition.maxAlternatives = 1;\r\n recognition.continuous = true;\r\n\r\n recognition.onresult = (event: any) => {\r\n let text = '';\r\n for (let i = consumedRef.current; i < event.results.length; i++) {\r\n text += event.results[i][0].transcript;\r\n }\r\n resultLenRef.current = event.results.length;\r\n text = text.trim();\r\n if (!text) return;\r\n transcriptRef.current = text;\r\n setInterim(text);\r\n setHearing(true);\r\n };\r\n\r\n recognition.onerror = (event: any) => {\r\n const code = event?.error || '';\r\n if (code === 'no-speech' || code === 'aborted') return;\r\n onErrorRef.current?.(code);\r\n };\r\n\r\n recognition.onend = () => {\r\n recognitionRef.current = null;\r\n if (activeRef.current && wantRestartRef.current) {\r\n setTimeout(() => {\r\n startRecognition();\r\n }, 120);\r\n }\r\n };\r\n\r\n recognitionRef.current = recognition;\r\n try {\r\n recognition.start();\r\n } catch (e: any) {\r\n recognitionRef.current = null;\r\n onErrorRef.current?.('failed-to-start');\r\n }\r\n }, [lang]);\r\n\r\n const stopRecognition = useCallback(() => {\r\n wantRestartRef.current = false;\r\n const r = recognitionRef.current;\r\n recognitionRef.current = null;\r\n try { r?.stop(); } catch { }\r\n }, []);\r\n\r\n const stop = useCallback(() => {\r\n activeRef.current = false;\r\n duckedRef.current = false;\r\n bargeEvidenceRef.current = 0;\r\n envRef.current = [];\r\n duckSpeech(1, 0);\r\n wantRestartRef.current = false;\r\n setActive(false);\r\n setHearing(false);\r\n setInterim('');\r\n transcriptRef.current = '';\r\n levelRef.current = 0;\r\n const r = recognitionRef.current;\r\n recognitionRef.current = null;\r\n try { r?.abort(); } catch { }\r\n if (rafRef.current !== null) { cancelAnimationFrame(rafRef.current); rafRef.current = null; }\r\n streamRef.current?.getTracks().forEach(t => t.stop());\r\n streamRef.current = null;\r\n analyserRef.current = null;\r\n audioCtxRef.current?.close().catch(() => { });\r\n audioCtxRef.current = null;\r\n }, []);\r\n\r\n const start = useCallback(async () => {\r\n if (activeRef.current || !supported) return;\r\n activeRef.current = true;\r\n setActive(true);\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({\r\n audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true },\r\n });\r\n streamRef.current = stream;\r\n const AC = (window as any).AudioContext || (window as any).webkitAudioContext;\r\n const ctx: AudioContext = new AC();\r\n audioCtxRef.current = ctx;\r\n const analyser = ctx.createAnalyser();\r\n analyser.fftSize = 1024;\r\n analyser.smoothingTimeConstant = 0.25;\r\n ctx.createMediaStreamSource(stream).connect(analyser);\r\n analyserRef.current = analyser;\r\n dataRef.current = new Uint8Array(analyser.fftSize);\r\n floorRef.current = 0.008;\r\n lastLoudRef.current = Date.now();\r\n rafRef.current = requestAnimationFrame(monitor);\r\n } catch (e: any) {\r\n activeRef.current = false;\r\n setActive(false);\r\n onErrorRef.current?.(e?.name === 'NotAllowedError' ? 'not-allowed' : 'audio-capture');\r\n return;\r\n }\r\n wantRestartRef.current = true;\r\n startRecognition();\r\n }, [supported, monitor, startRecognition]);\r\n\r\n useEffect(() => {\r\n if (!active) return;\r\n if (paused) {\r\n transcriptRef.current = '';\r\n setInterim('');\r\n duckedRef.current = false;\r\n bargeEvidenceRef.current = 0;\r\n envRef.current = [];\r\n stopRecognition();\r\n } else {\r\n duckedRef.current = false;\r\n lastLoudRef.current = Date.now();\r\n wantRestartRef.current = true;\r\n startRecognition();\r\n }\r\n }, [paused, active, startRecognition, stopRecognition]);\r\n\r\n useEffect(() => {\r\n if (!active || paused) return;\r\n const id = setInterval(() => {\r\n const alive = !!recognitionRef.current;\r\n const hearingSomething = levelRef.current > floorRef.current + SPEECH_MARGIN;\r\n if (!alive) {\r\n } else if (hearingSomething && !transcriptRef.current) {\r\n }\r\n }, 2000);\r\n return () => clearInterval(id);\r\n }, [active, paused]);\r\n\r\n useEffect(() => () => { stop(); }, [stop]);\r\n\r\n return { supported, active, hearing, interim, micLevel, micSpectrum, spectrumBins, start, stop };\r\n}\r\n","import type { SpeechResult, VoiceRefusal } from '@akropolys/sdk';\r\n\r\nexport interface SpeakOptions {\r\n\r\n client: { synthesizeSpeech: (text: string, voice?: string, language?: string, signal?: AbortSignal) => Promise<SpeechResult | null> };\r\n text: string;\r\n voice?: string;\r\n\r\n language?: string;\r\n\r\n bcp47?: string;\r\n onStart?: () => void;\r\n onEnd?: () => void;\r\n onError?: (err: any) => void;\r\n\r\n onRefused?: (reason: VoiceRefusal) => void;\r\n\r\n onSecondsLeft?: (seconds: number) => void;\r\n}\r\n\r\nlet ctx: AudioContext | null = null;\r\nlet analyser: AnalyserNode | null = null;\r\nlet duckGain: GainNode | null = null;\r\nlet timeData: Uint8Array | null = null;\r\nlet generation = 0;\r\nlet speaking = false;\r\nlet smoothed = 0;\r\nlet usingFallback = false;\r\n\r\nfunction audio(): { ctx: AudioContext; analyser: AnalyserNode } | null {\r\n if (typeof window === 'undefined') return null;\r\n const AC = (window as any).AudioContext || (window as any).webkitAudioContext;\r\n if (!AC) return null;\r\n if (!ctx) {\r\n ctx = new AC();\r\n analyser = ctx!.createAnalyser();\r\n analyser.fftSize = 1024;\r\n analyser.smoothingTimeConstant = 0.25;\r\n duckGain = ctx!.createGain();\r\n duckGain.gain.value = 1;\r\n analyser.connect(duckGain);\r\n duckGain.connect(ctx!.destination);\r\n timeData = new Uint8Array(analyser.fftSize);\r\n }\r\n return { ctx: ctx!, analyser: analyser! };\r\n}\r\n\r\nexport function duckSpeech(level: number, fadeMs = 130): void {\r\n const g = duckGain;\r\n if (!g || !ctx) return;\r\n const now = ctx.currentTime;\r\n g.gain.cancelScheduledValues(now);\r\n g.gain.setValueAtTime(g.gain.value, now);\r\n g.gain.linearRampToValueAtTime(Math.max(0, Math.min(1, level)), now + fadeMs / 1000);\r\n}\r\n\r\nexport function speechLevel(): number {\r\n if (!speaking) {\r\n smoothed *= 0.85;\r\n return smoothed;\r\n }\r\n if (usingFallback || !analyser || !timeData) {\r\n const t = Date.now() / 1000;\r\n return 0.35 + 0.18 * Math.sin(t * 7.1) + 0.1 * Math.sin(t * 3.3);\r\n }\r\n analyser.getByteTimeDomainData(timeData as any);\r\n let sum = 0;\r\n for (let i = 0; i < timeData.length; i++) {\r\n const v = (timeData[i] - 128) / 128;\r\n sum += v * v;\r\n }\r\n const rms = Math.sqrt(sum / timeData.length);\r\n const level = Math.min(1, rms * 3.2);\r\n smoothed += (level - smoothed) * (level > smoothed ? 0.6 : 0.12);\r\n return smoothed;\r\n}\r\n\r\nexport function speechSpectrum(out: Uint8Array): boolean {\r\n if (!speaking || usingFallback || !analyser) return false;\r\n if (out.length !== analyser.frequencyBinCount) return false;\r\n analyser.getByteFrequencyData(out as any);\r\n return true;\r\n}\r\n\r\nexport function spectrumBins(): number {\r\n return analyser ? analyser.frequencyBinCount : 0;\r\n}\r\n\r\nexport function isSpeaking(): boolean {\r\n return speaking;\r\n}\r\n\r\nexport function stopSpeech() {\r\n generation++;\r\n speaking = false;\r\n if (duckGain && ctx) {\r\n duckGain.gain.cancelScheduledValues(ctx.currentTime);\r\n duckGain.gain.value = 1;\r\n }\r\n if (typeof window !== 'undefined' && 'speechSynthesis' in window) {\r\n try { window.speechSynthesis.cancel(); } catch { }\r\n }\r\n}\r\n\r\nexport function cleanTextForSpeech(text: string): string {\r\n return text\r\n .replace(/```[\\s\\S]*?```/g, ' ')\r\n .replace(/`([^`]+)`/g, '$1')\r\n .replace(/!\\[[^\\]]*\\]\\([^)]*\\)/g, ' ')\r\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\r\n .replace(/https?:\\/\\/\\S+/g, ' ')\r\n .replace(/^\\s{0,3}#{1,6}\\s+/gm, '')\r\n .replace(/^\\s*[-*+]\\s+/gm, '')\r\n .replace(/[*_~>|]/g, '')\r\n .replace(/\\s*\\n\\s*\\n\\s*/g, '. ')\r\n .replace(/\\s*\\n\\s*/g, ' ')\r\n .replace(/\\s+/g, ' ')\r\n .replace(/\\s+([.,!?;:])/g, '$1')\r\n .trim();\r\n}\r\n\r\nconst SENTENCE_END = /([.!?…。!?؟۔।]+[\"'”’)\\]]*\\s+)/;\r\nconst CHUNK_TARGET = 240;\r\n\r\nexport function chunkForSpeech(text: string, target = CHUNK_TARGET): string[] {\r\n const pieces = text.split(SENTENCE_END).filter(Boolean);\r\n const chunks: string[] = [];\r\n let buf = '';\r\n for (const piece of pieces) {\r\n if (buf && (buf + piece).length > target) {\r\n chunks.push(buf.trim());\r\n buf = '';\r\n }\r\n buf += piece;\r\n while (buf.length > target * 2) {\r\n const cut = buf.lastIndexOf(' ', target * 2);\r\n chunks.push(buf.slice(0, cut > target ? cut : target * 2).trim());\r\n buf = buf.slice(cut > target ? cut : target * 2);\r\n }\r\n }\r\n if (buf.trim()) chunks.push(buf.trim());\r\n return chunks.filter(c => /\\S/.test(c));\r\n}\r\n\r\nfunction playBuffer(a: { ctx: AudioContext; analyser: AnalyserNode }, buf: AudioBuffer, gen: number): Promise<void> {\r\n return new Promise(resolve => {\r\n if (gen !== generation) return resolve();\r\n const src = a.ctx.createBufferSource();\r\n src.buffer = buf;\r\n src.connect(a.analyser);\r\n src.onended = () => resolve();\r\n src.start();\r\n const watchdog = setInterval(() => {\r\n if (gen !== generation) {\r\n clearInterval(watchdog);\r\n try { src.stop(); } catch { }\r\n resolve();\r\n }\r\n }, 100);\r\n src.onended = () => { clearInterval(watchdog); resolve(); };\r\n });\r\n}\r\n\r\nexport async function speak({\r\n client,\r\n text,\r\n voice,\r\n language,\r\n bcp47,\r\n onStart,\r\n onEnd,\r\n onError,\r\n onRefused,\r\n onSecondsLeft,\r\n}: SpeakOptions): Promise<void> {\r\n stopSpeech();\r\n const gen = ++generation;\r\n usingFallback = false;\r\n\r\n const clean = cleanTextForSpeech(text);\r\n if (!clean) { onEnd?.(); return; }\r\n\r\n const a = audio();\r\n if (!a) { fallbackWebSpeech(clean, bcp47, onStart, onEnd, onError); return; }\r\n if (a.ctx.state === 'suspended') { try { await a.ctx.resume(); } catch { } }\r\n\r\n const chunks = chunkForSpeech(clean);\r\n const synth = (t: string) => client.synthesizeSpeech(t, voice, language).catch(() => null);\r\n\r\n let started = false;\r\n let pending = synth(chunks[0]);\r\n\r\n for (let i = 0; i < chunks.length; i++) {\r\n if (gen !== generation) break;\r\n const result = await pending;\r\n pending = i + 1 < chunks.length ? synth(chunks[i + 1]) : Promise.resolve(null);\r\n\r\n if (result && 'refused' in result && result.refused) {\r\n onRefused?.(result.refused);\r\n onEnd?.();\r\n return;\r\n }\r\n if (!result) {\r\n if (!started) {\r\n fallbackWebSpeech(chunks.slice(i).join(' '), bcp47, onStart, onEnd, onError);\r\n return;\r\n }\r\n continue;\r\n }\r\n if (result.secondsLeft !== undefined) onSecondsLeft?.(result.secondsLeft);\r\n if (gen !== generation) break;\r\n\r\n let decoded: AudioBuffer;\r\n try {\r\n decoded = await a.ctx.decodeAudioData(result.audio.slice(0));\r\n } catch (e) {\r\n onError?.(e);\r\n continue;\r\n }\r\n if (gen !== generation) break;\r\n\r\n if (!started) { started = true; speaking = true; onStart?.(); }\r\n await playBuffer(a, decoded, gen);\r\n }\r\n\r\n if (gen === generation) {\r\n speaking = false;\r\n onEnd?.();\r\n }\r\n}\r\n\r\nfunction pickVoice(tag: string): SpeechSynthesisVoice | undefined {\r\n const voices = window.speechSynthesis.getVoices?.() ?? [];\r\n if (!voices.length || !tag) return undefined;\r\n const want = tag.toLowerCase();\r\n const base = want.split('-')[0];\r\n const candidates = voices.filter(v => v.lang?.toLowerCase().replace('_', '-') === want);\r\n const loose = candidates.length\r\n ? candidates\r\n : voices.filter(v => v.lang?.toLowerCase().split(/[-_]/)[0] === base);\r\n if (!loose.length) return undefined;\r\n return loose.find(v => v.localService === false) ?? loose[0];\r\n}\r\n\r\nfunction fallbackWebSpeech(\r\n text: string,\r\n bcp47?: string,\r\n onStart?: () => void,\r\n onEnd?: () => void,\r\n onError?: (err: any) => void\r\n) {\r\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) {\r\n onError?.('speech-unavailable');\r\n onEnd?.();\r\n return;\r\n }\r\n const gen = generation;\r\n usingFallback = true;\r\n try {\r\n window.speechSynthesis.cancel();\r\n const utterance = new SpeechSynthesisUtterance(text);\r\n const tag = bcp47 || document.documentElement.lang || navigator.language || '';\r\n if (tag) utterance.lang = tag;\r\n const v = pickVoice(tag);\r\n if (v) utterance.voice = v;\r\n utterance.rate = 1.0;\r\n utterance.pitch = 1.0;\r\n\r\n utterance.onstart = () => { speaking = true; onStart?.(); };\r\n utterance.onend = () => {\r\n if (gen !== generation) return;\r\n speaking = false;\r\n onEnd?.();\r\n };\r\n utterance.onerror = (e) => {\r\n speaking = false;\r\n onError?.(e);\r\n onEnd?.();\r\n };\r\n window.speechSynthesis.speak(utterance);\r\n } catch (e) {\r\n speaking = false;\r\n onError?.(e);\r\n onEnd?.();\r\n }\r\n}\r\n","import React, { useRef, useState } from 'react';\r\nimport { downscaleImage } from '../utils/downscaleImage';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport type { VisualSearchResponse } from '@akropolys/sdk';\r\n\r\nexport interface VisualSearchProps {\r\n /** Called with search results + the base64 preview when Gemini responds. */\r\n onResults: (res: VisualSearchResponse, previewBase64: string) => void;\r\n onError?: (err: Error) => void;\r\n /**\r\n * Category hint sent to Gemini to sharpen the match_query.\r\n * e.g. \"dress\", \"curtains\", \"sofa\", \"shoes\"\r\n */\r\n categoryHint?: string;\r\n className?: string;\r\n disabled?: boolean;\r\n}\r\n\r\nconst CameraIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\" />\r\n <circle cx=\"12\" cy=\"13\" r=\"4\" />\r\n </svg>\r\n);\r\n\r\nconst SpinnerIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" className=\"kiku-vs-spin\">\r\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\r\n </svg>\r\n);\r\n\r\nfunction fileToBase64(file: File): Promise<string> {\r\n return downscaleImage(file);\r\n}\r\n\r\n/**\r\n * VisualSearch — camera/image-upload button for style-match search.\r\n */\r\nexport function VisualSearch({\r\n onResults,\r\n onError,\r\n categoryHint,\r\n className = '',\r\n disabled = false,\r\n}: VisualSearchProps) {\r\n const client = useAkropolysContext();\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleFile = async (file: File) => {\r\n if (!file.type.startsWith('image/')) return;\r\n setLoading(true);\r\n try {\r\n const base64 = await fileToBase64(file);\r\n const res = await (client.api as any).searchByImage(base64, categoryHint);\r\n onResults(res as VisualSearchResponse, base64);\r\n } catch (e: any) {\r\n onError?.(e instanceof Error ? e : new Error(String(e)));\r\n } finally {\r\n setLoading(false);\r\n if (inputRef.current) inputRef.current.value = '';\r\n }\r\n };\r\n\r\n return (\r\n <label\r\n className={`kiku-vs-btn${loading ? ' kiku-vs-btn--loading' : ''} ${className}`}\r\n title=\"Search by photo\"\r\n aria-label=\"Search by uploading a photo\"\r\n style={{ cursor: disabled || loading ? 'not-allowed' : 'pointer' }}\r\n >\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n capture=\"environment\"\r\n onChange={e => e.target.files?.[0] && handleFile(e.target.files[0])}\r\n disabled={disabled || loading}\r\n hidden\r\n />\r\n {loading ? <SpinnerIcon /> : <CameraIcon />}\r\n </label>\r\n );\r\n}\r\n","const MAX_EDGE = 1536;\r\nconst QUALITY = 0.85;\r\n\r\nconst SKIP_UNDER_BYTES = 300 * 1024;\r\n\r\nfunction approxBytesOfDataURL(dataURL: string): number {\r\n const i = dataURL.indexOf(',');\r\n const b64 = i === -1 ? dataURL : dataURL.slice(i + 1);\r\n return Math.floor(b64.length * 0.75);\r\n}\r\n\r\nexport async function downscaleImage(file: File): Promise<string> {\r\n const original = await new Promise<string>((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = () => resolve(reader.result as string);\r\n reader.onerror = () => reject(reader.error ?? new Error('read failed'));\r\n reader.readAsDataURL(file);\r\n });\r\n\r\n if (file.type === 'image/gif' || file.type === 'image/svg+xml') return original;\r\n if (approxBytesOfDataURL(original) <= SKIP_UNDER_BYTES) return original;\r\n\r\n try {\r\n const bitmap = await createImageBitmap(file);\r\n try {\r\n const scale = Math.min(1, MAX_EDGE / Math.max(bitmap.width, bitmap.height));\r\n const w = Math.max(1, Math.round(bitmap.width * scale));\r\n const h = Math.max(1, Math.round(bitmap.height * scale));\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = w;\r\n canvas.height = h;\r\n const cx = canvas.getContext('2d');\r\n if (!cx) return original;\r\n cx.drawImage(bitmap, 0, 0, w, h);\r\n\r\n const keepPNG = file.type === 'image/png';\r\n const out = canvas.toDataURL(keepPNG ? 'image/png' : 'image/jpeg', QUALITY);\r\n\r\n return approxBytesOfDataURL(out) < approxBytesOfDataURL(original) ? out : original;\r\n } finally {\r\n bitmap.close?.();\r\n }\r\n } catch {\r\n return original;\r\n }\r\n}\r\n","'use client';\r\n\r\nimport React, { useState, useEffect, useCallback } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { getShadowContainer } from '../utils/shadowRoot';\r\nimport type { AkropolysTheme, ChatSource } from '@akropolys/sdk';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { cn } from '../utils/cn';\r\nimport { resolveTheme } from '../utils/theme';\r\nimport { warmChrome } from '../utils/chromeWarm';\r\nimport { useHostFontFace } from '../utils/hostFont';\r\nimport { DEFAULT_CHIPS, DEFAULT_UI_STRINGS } from './ChatModal/types';\r\nimport { ChatModal } from './ChatModal';\r\n\r\nexport interface KikuButtonProps {\r\n label?: React.ReactNode;\r\n children?: React.ReactNode;\r\n icon?: React.ReactNode;\r\n title?: string;\r\n placeholder?: string;\r\n backdropColor?: string;\r\n backdropBlur?: string | number;\r\n className?: string;\r\n onSelectSource?: (source: ChatSource) => void;\r\n defaultCurrency?: string;\r\n chips?: string[];\r\n theme?: 'light' | 'dark' | AkropolysTheme;\r\n classNames?: {\r\n button?: string;\r\n overlay?: string;\r\n panel?: string;\r\n input?: string;\r\n sendButton?: string;\r\n };\r\n\r\n enableVoice?: boolean;\r\n\r\n voiceLang?: string;\r\n\r\n enableVision?: boolean;\r\n\r\n visionCategoryHint?: string;\r\n\r\n /** Enable 🔊 TTS voice audio responses from AI */\r\n enableAudioResponse?: boolean;\r\n\r\n ttsVoice?: string;\r\n\r\n autoSpeakResponses?: boolean;\r\n}\r\n\r\nexport function KikuButton({\r\n label = 'Ask AI',\r\n children,\r\n icon,\r\n title,\r\n placeholder,\r\n backdropColor,\r\n backdropBlur,\r\n className,\r\n onSelectSource,\r\n defaultCurrency = '$',\r\n chips = DEFAULT_CHIPS,\r\n theme,\r\n classNames = {},\r\n enableVoice = false,\r\n voiceLang,\r\n enableVision = false,\r\n visionCategoryHint,\r\n enableAudioResponse,\r\n ttsVoice,\r\n autoSpeakResponses,\r\n}: KikuButtonProps) {\r\n const client = useAkropolysContext();\r\n const [open, setOpen] = useState(false);\r\n const [mounted, setMounted] = useState(false);\r\n const [origin, setOrigin] = useState<import('./ChatModal/types').ModalOrigin | null>(null);\r\n\r\n // The open path otherwise pays for ~190KB of CSS parsing plus the ui-strings and\r\n // base-font round trips. Pulling both forward means the click only mounts React.\r\n const warmShadow = useCallback(() => {\r\n getShadowContainer();\r\n try {\r\n warmChrome(client, client?.getShopperLanguage?.() ?? '', DEFAULT_UI_STRINGS);\r\n } catch { }\r\n }, [client]);\r\n\r\n const openFrom = useCallback((el: HTMLElement) => {\r\n const b = el.getBoundingClientRect();\r\n const style = window.getComputedStyle(el);\r\n const br = parseFloat(style.borderRadius) || 12;\r\n const x = b.left + b.width / 2;\r\n const y = b.top + b.height / 2;\r\n const w = window.innerWidth, h = window.innerHeight;\r\n const r = Math.max(\r\n Math.hypot(x, y), Math.hypot(w - x, y),\r\n Math.hypot(x, h - y), Math.hypot(w - x, h - y),\r\n );\r\n setOrigin({\r\n x,\r\n y,\r\n r,\r\n top: b.top,\r\n left: b.left,\r\n width: b.width,\r\n height: b.height,\r\n borderRadius: br,\r\n });\r\n setOpen(true);\r\n }, []);\r\n\r\n useEffect(() => {\r\n setMounted(true);\r\n\r\n // backstop for the first click when it arrives without a prior hover (touch, programmatic)\r\n const ric = (window as any).requestIdleCallback;\r\n const warmId = ric ? ric(warmShadow, { timeout: 2000 }) : setTimeout(warmShadow, 600);\r\n\r\n if (typeof window !== 'undefined' && !(window as any).__akropolys_nav_patched) {\r\n (window as any).__akropolys_nav_patched = true;\r\n let lastPath = window.location.pathname;\r\n const originalPush = window.history.pushState;\r\n const originalReplace = window.history.replaceState;\r\n\r\n window.history.pushState = function(...args) {\r\n originalPush.apply(this, args);\r\n if (window.location.pathname !== lastPath) {\r\n lastPath = window.location.pathname;\r\n window.dispatchEvent(new CustomEvent('akropolys:navigation'));\r\n }\r\n };\r\n\r\n window.history.replaceState = function(...args) {\r\n originalReplace.apply(this, args);\r\n if (window.location.pathname !== lastPath) {\r\n lastPath = window.location.pathname;\r\n window.dispatchEvent(new CustomEvent('akropolys:navigation'));\r\n }\r\n };\r\n }\r\n\r\n const handleNavigation = () => {\r\n setOpen(false);\r\n };\r\n\r\n window.addEventListener('popstate', handleNavigation);\r\n window.addEventListener('akropolys:navigation', handleNavigation);\r\n\r\n return () => {\r\n const cic = (window as any).cancelIdleCallback;\r\n if (ric && cic) cic(warmId); else clearTimeout(warmId as any);\r\n window.removeEventListener('popstate', handleNavigation);\r\n window.removeEventListener('akropolys:navigation', handleNavigation);\r\n };\r\n }, [warmShadow]);\r\n\r\n const { themeAttr: hskThemeAttr, vars: customStyles } = resolveTheme(theme);\r\n useHostFontFace(theme);\r\n\r\n return (\r\n <>\r\n <button\r\n className={cn(\"hsk-cb-btn\", classNames.button, className)}\r\n onClick={e => openFrom(e.currentTarget)}\r\n onPointerEnter={warmShadow}\r\n onPointerDown={warmShadow}\r\n style={customStyles}\r\n data-hsk-theme={hskThemeAttr}\r\n aria-label=\"Open AI chat\"\r\n >\r\n {children !== undefined ? (\r\n children\r\n ) : (\r\n <>\r\n {icon ? (\r\n <span className=\"hsk-cb-btn-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n {icon}\r\n </span>\r\n ) : null}\r\n {label}\r\n </>\r\n )}\r\n </button>\r\n {open && mounted && createPortal(\r\n <ChatModal\r\n title={title}\r\n placeholder={placeholder}\r\n backdropColor={backdropColor}\r\n backdropBlur={backdropBlur}\r\n origin={origin}\r\n onClose={() => setOpen(false)}\r\n onSelectSource={onSelectSource}\r\n defaultCurrency={defaultCurrency}\r\n chips={chips}\r\n theme={theme}\r\n classNames={classNames}\r\n enableVoice={enableVoice}\r\n voiceLang={voiceLang}\r\n enableVision={enableVision}\r\n visionCategoryHint={visionCategoryHint}\r\n enableAudioResponse={enableAudioResponse}\r\n ttsVoice={ttsVoice}\r\n autoSpeakResponses={autoSpeakResponses}\r\n />,\r\n getShadowContainer() ?? document.body\r\n )}\r\n </>\r\n );\r\n}\r\n","// AUTO-GENERATED by scripts/gen-css.mjs — do not edit.\nexport default \"@property --hsk-chat-bg{syntax:'<color>';inherits:true;initial-value:#0a0a0a}@property --hsk-chat-text{syntax:'<color>';inherits:true;initial-value:#f0efed}@property --hsk-chat-muted{syntax:'<color>';inherits:true;initial-value:#888888}@property --hsk-chat-divide{syntax:'<color>';inherits:true;initial-value:rgba(255,255,255,.08)}@property --hsk-chat-input-bg{syntax:'<color>';inherits:true;initial-value:#191919}@property --hsk-chat-source-bg{syntax:'<color>';inherits:true;initial-value:rgba(255,255,255,.04)}@property --hsk-fade-bg{syntax:'<color>';inherits:true;initial-value:#0a0a0a}@property --hsk-surface-1{syntax:'<color>';inherits:true;initial-value:rgba(255,255,255,.06)}@property --hsk-surface-2{syntax:'<color>';inherits:true;initial-value:#1f1f22}@property --hsk-bubble-bg{syntax:'<color>';inherits:true;initial-value:#1f1f22}@property --hsk-think-text{syntax:'<color>';inherits:true;initial-value:#a6a6a6}@property --hsk-placeholder{syntax:'<color>';inherits:true;initial-value:#555555}@property --hsk-grid-bg{syntax:'<color>';inherits:true;initial-value:#1a1a1c}@property --hsk-active-bg{syntax:'<color>';inherits:true;initial-value:#f0efed}@property --hsk-on-active{syntax:'<color>';inherits:true;initial-value:#0a0a0a}@property --hsk-src-title{syntax:'<color>';inherits:true;initial-value:#f9fafb}@property --hsk-src-desc{syntax:'<color>';inherits:true;initial-value:#9ca3af}@property --hsk-price-bg{syntax:'<color>';inherits:true;initial-value:rgba(255,255,255,.08)}@property --hsk-price-text{syntax:'<color>';inherits:true;initial-value:#ff7a45}@property --hsk-sheet-bg{syntax:'<color>';inherits:true;initial-value:#1f1f22}@property --hsk-primary{syntax:'<color>';inherits:true;initial-value:#ff6a33}:host,:root{--hsk-border-radius:0;--hsk-brand-green:#2D7A4B;--hsk-font:\\\"Geist\\\",\\\"Inter\\\",-apple-system,BlinkMacSystemFont,\\\"SF Pro Text\\\",\\\"SF Pro Display\\\",\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif;--hsk-default-font-size:15px}.hsk-cb-btn,.hsk-cb-close,.hsk-cb-topbar-btn,.hsk-cb-chip,.hsk-cb-source,.hsk-cb-sources-next,.hsk-action-pill,.hsk-chat-send,.hsk-chat-reset,.hsk-close-btn,.hsk-cb-overlay{--hsk-font-size:16px;touch-action:manipulation;-webkit-tap-highlight-color:transparent;font-family:var(--hsk-font)}.hsk-cb-overlay{transition:--hsk-chat-bg .45s cubic-bezier(.16,1,.3,1),--hsk-chat-text .45s cubic-bezier(.16,1,.3,1),--hsk-chat-muted .45s cubic-bezier(.16,1,.3,1),--hsk-chat-divide .45s cubic-bezier(.16,1,.3,1),--hsk-chat-input-bg .45s cubic-bezier(.16,1,.3,1),--hsk-surface-1 .45s cubic-bezier(.16,1,.3,1),--hsk-surface-2 .45s cubic-bezier(.16,1,.3,1),--hsk-bubble-bg .45s cubic-bezier(.16,1,.3,1),--hsk-primary .45s cubic-bezier(.16,1,.3,1),--hsk-grid-bg .45s cubic-bezier(.16,1,.3,1),--hsk-active-bg .45s cubic-bezier(.16,1,.3,1),--hsk-on-active .45s cubic-bezier(.16,1,.3,1),--hsk-src-title .45s cubic-bezier(.16,1,.3,1),--hsk-src-desc .45s cubic-bezier(.16,1,.3,1),--hsk-price-bg .45s cubic-bezier(.16,1,.3,1),--hsk-price-text .45s cubic-bezier(.16,1,.3,1),--hsk-sheet-bg .45s cubic-bezier(.16,1,.3,1),background-color .45s cubic-bezier(.16,1,.3,1),border-color .45s cubic-bezier(.16,1,.3,1),color .45s cubic-bezier(.16,1,.3,1),fill .45s cubic-bezier(.16,1,.3,1),stroke .45s cubic-bezier(.16,1,.3,1),box-shadow .45s cubic-bezier(.16,1,.3,1)}.hsk-kiku-avatar,.hsk-kiku-avatar *{transition:none}@media (prefers-reduced-motion:reduce){.hsk-cb-overlay,.hsk-cb-overlay *,.hsk-cb-overlay *::before,.hsk-cb-overlay *::after{transition:none}}.hsk-cb-overlay button,.hsk-cb-overlay [role=\\\"button\\\"],.hsk-cb-overlay input,.hsk-cb-overlay textarea,.hsk-cb-overlay select,.hsk-chat button,.hsk-chat [role=\\\"button\\\"],.hsk-chat input,.hsk-chat textarea,.hsk-chat select,.hsk-cb-btn,.hsk-search button,.hsk-search [role=\\\"button\\\"],.hsk-search input,.hsk-search textarea,.hsk-search select{touch-action:manipulation;-webkit-tap-highlight-color:transparent;font-family:var(--hsk-font)}:host,:root,.hsk-cb-btn,.hsk-cb-overlay,.hsk-chat-widget{--hsk-marble-1:color-mix(in srgb,var(--hsk-primary,#ff6a33) 12%,#fffaf4);--hsk-marble-2:color-mix(in srgb,var(--hsk-primary,#ff6a33) 30%,#fdf0e4);--hsk-marble-3:color-mix(in srgb,var(--hsk-primary,#ff6a33) 62%,#e8cbb0);--hsk-marble-4:color-mix(in srgb,var(--hsk-primary,#ff6a33) 85%,#6d3a1c);--hsk-marble-sheen:.5}@media (prefers-color-scheme:dark){:host,:root,.hsk-cb-btn,.hsk-cb-overlay,.hsk-chat-widget{--hsk-marble-1:#FFFDF6;--hsk-marble-2:#FBF3E2;--hsk-marble-3:color-mix(in srgb,var(--hsk-primary,#ff6a33) 20%,#EDDFC4);--hsk-marble-4:color-mix(in srgb,var(--hsk-primary,#ff6a33) 42%,#D8C39C);--hsk-marble-sheen:.9}}.hsk-chat-widget{--hsk-bg:var(--chat-bg-color,#ffffff);--hsk-text:var(--chat-text-color,#1f1f1f);--hsk-primary:var(--chat-primary-color,#ff6a33);--hsk-font:var(--chat-font-family,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif);--hsk-font-size:var(--chat-font-size,16px);display:flex;flex-direction:column;height:100%;min-height:320px;font-family:var(--hsk-font);letter-spacing:normal;word-spacing:normal;text-transform:none;background:var(--hsk-bg);border:1px solid #f1f3f4;border-radius:var(--hsk-border-radius,0);overflow:hidden}@media (prefers-color-scheme:dark){.hsk-chat-widget{--hsk-bg:var(--chat-bg-color,#0a0a0a);--hsk-text:var(--chat-text-color,#e8eaed);border-color:#202124}}.hsk-chat-header{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid #f1f3f4;background:var(--hsk-bg);flex-shrink:0}@media (prefers-color-scheme:dark){.hsk-chat-header{border-bottom-color:#202124}}.hsk-chat-header-icon{color:var(--hsk-primary);display:flex;align-items:center}.hsk-chat-title{font-size:14px;font-weight:600;color:var(--hsk-text)}.hsk-chat-badge{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--hsk-primary);background:rgba(255,106,51,.09);border:1px solid rgba(255,106,51,.18);padding:2px 8px;border-radius:var(--hsk-border-radius,0)}.hsk-chat-messages{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;overscroll-behavior:contain}.hsk-chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:8px;color:#555;font-size:13px;text-align:center;padding:24px}.hsk-chat-empty-icon{font-size:28px;margin-bottom:4px;color:var(--hsk-primary);display:flex;align-items:center;justify-content:center}.hsk-chat-empty-suggestions{font-size:12px;color:#666;margin-top:4px}.hsk-msg-row{display:flex;gap:8px;align-items:flex-start}.hsk-msg-row.user{flex-direction:row-reverse}.hsk-msg-avatar{width:28px;height:28px;border-radius:var(--hsk-border-radius,0);flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700}.hsk-msg-avatar.ai{background:rgba(255,106,51,.12);border:1px solid rgba(255,106,51,.25);color:var(--hsk-primary);display:flex;align-items:center;justify-content:center}.hsk-msg-avatar.user{background:#f1f3f4;color:#5f6368}@media (prefers-color-scheme:dark){.hsk-msg-avatar.user{background:#202124;color:#888}}.hsk-msg-bubble{max-width:78%;padding:10px 14px;border-radius:var(--hsk-border-radius,0);font-size:var(--hsk-font-size,13px);line-height:1.6}.hsk-msg-bubble.ai{background:var(--hsk-bg);border:1px solid #f1f3f4;color:var(--hsk-text)}@media (prefers-color-scheme:dark){.hsk-msg-bubble.ai{border-color:#202124}}.hsk-msg-bubble.user{background:var(--hsk-primary);color:#fff}.hsk-streaming-cursor{display:inline-block;width:6px;height:1.1em;margin-inline-start:3px;vertical-align:-2px;background-color:var(--hsk-primary);animation:hsk-cursor-blink .9s infinite}@keyframes hsk-cursor-blink{0%,100%{opacity:1}50%{opacity:0}}.hsk-status-live{display:flex;align-items:center;gap:8px;font-size:12px;color:#666;padding:4px 0 8px 0;font-weight:500}.hsk-status-dot{width:8px;height:8px;border-radius:50%;background-color:var(--hsk-primary);animation:hsk-pulse 1.4s infinite ease-in-out}@keyframes hsk-pulse{0%,100%{transform:scale(.8);opacity:.5}50%{transform:scale(1.2);opacity:1}}.hsk-thinking-details{margin-bottom:10px;padding:8px 12px;background:rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.06);border-radius:8px;font-size:12px}.hsk-thinking-summary{cursor:pointer;font-weight:600;color:#666;user-select:none}.hsk-thinking-text{margin-top:8px;white-space:pre-wrap;color:#555;font-family:monospace;font-size:11px;line-height:1.4;max-height:200px;overflow-y:auto}.hsk-sources-container{margin-inline-start:36px}.hsk-sources{margin-top:10px;display:flex;flex-direction:column;gap:6px}.hsk-source-card{display:flex;align-items:center;gap:10px;padding:8px 10px;background:#f8f9fa;border:1px solid #f1f3f4;border-radius:var(--hsk-border-radius,0);cursor:pointer;transition:border-color .15s}@media (prefers-color-scheme:dark){.hsk-source-card{background:#1a1a1b;border-color:#202124}}.hsk-source-card:hover{border-color:rgba(255,106,51,.37)}.hsk-source-img{width:36px;height:36px;object-fit:cover;border-radius:var(--hsk-border-radius,0);background:#fff}.hsk-source-name{font-size:12px;font-weight:500;color:var(--hsk-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-source-price{font-size:11px;color:var(--hsk-primary);font-weight:700;margin-top:2px}.hsk-typing{display:flex;gap:4px;align-items:center;padding:10px 14px;background:var(--hsk-bg);border:1px solid #f1f3f4;border-radius:var(--hsk-border-radius,0);width:fit-content}@media (prefers-color-scheme:dark){.hsk-typing{border-color:#202124}}.hsk-typing-dot{width:6px;height:6px;background:var(--hsk-primary);border-radius:50%;animation:hsk-chat-bounce 1.2s infinite}.hsk-typing-dot:nth-child(2){animation-delay:.2s}.hsk-typing-dot:nth-child(3){animation-delay:.4s}@keyframes hsk-chat-bounce{0%,100%{opacity:.3;transform:translateY(0)}50%{opacity:1;transform:translateY(-4px)}}.hsk-pending{display:inline-flex;align-items:center;gap:10px;padding:10px 14px;background:var(--hsk-bg);border:1px solid #f1f3f4;border-radius:var(--hsk-border-radius,0);position:relative}@media (prefers-color-scheme:dark){.hsk-pending{border-color:#202124}}.hsk-pending-glyph{width:18px;height:18px;position:relative;display:inline-flex;align-items:center;justify-content:center}.hsk-pending-ring{width:18px;height:18px;border-radius:50%;border:2px solid rgba(255,106,51,.25);border-top-color:var(--hsk-primary);animation:hsk-pending-spin 1.1s linear infinite}.hsk-pending-dot{position:absolute;width:6px;height:6px;border-radius:50%;background:var(--hsk-primary);box-shadow:0 0 8px rgba(255,106,51,.45);animation:hsk-pending-pulse 1.4s ease-in-out infinite}.hsk-pending-text{position:relative;min-width:140px;height:16px;font-size:12px;color:var(--hsk-text);letter-spacing:.01em}.hsk-pending-step{position:absolute;left:0;top:0;opacity:0;animation:hsk-pending-cycle 6s infinite}.hsk-pending-step.step-1{animation-delay:0s}.hsk-pending-step.step-2{animation-delay:2s}.hsk-pending-step.step-3{animation-delay:4s}@keyframes hsk-pending-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes hsk-pending-pulse{0%,100%{transform:scale(.75);opacity:.6}50%{transform:scale(1);opacity:1}}@keyframes hsk-pending-cycle{0%,10%{opacity:0;transform:translateY(2px)}20%,45%{opacity:1;transform:translateY(0)}55%,100%{opacity:0;transform:translateY(-2px)}}.hsk-chat-input-area{display:flex;align-items:center;gap:8px;padding:12px 14px;border-top:1px solid #f1f3f4;background:var(--hsk-bg);flex-shrink:0}@media (prefers-color-scheme:dark){.hsk-chat-input-area{border-top-color:#202124}}.hsk-chat-input{flex:1;background:#f1f3f4;border:1px solid #f1f3f4;border-radius:var(--hsk-border-radius,0);padding:9px 14px;font-size:13px;color:var(--hsk-text);outline:none;font-family:inherit;transition:border-color .2s;resize:none;min-height:38px;max-height:120px;line-height:1.5}@media (prefers-color-scheme:dark){.hsk-chat-input{background:#1a1a1b;border-color:#202124}}.hsk-chat-input::placeholder{color:#888}.hsk-chat-input:focus{border-color:var(--hsk-primary)}.hsk-chat-send{width:34px;height:34px;border-radius:var(--hsk-border-radius,0);background:var(--hsk-primary);border:none;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;transition:opacity .15s,transform .1s}.hsk-chat-send:hover{opacity:.88}.hsk-chat-send:active{transform:scale(.93)}.hsk-chat-send:disabled{opacity:.4;cursor:not-allowed}.hsk-chat-reset{font-size:11px;color:#555;cursor:pointer;padding:0 4px;transition:color .15s;background:none;border:none;font-family:inherit}.hsk-chat-reset:hover{color:var(--hsk-primary)}.hsk-chat-error{font-size:12px;color:#ef4444;text-align:center;padding:8px}.hsk-cb-btn{--hsk-primary:var(--chat-primary-color,#ff6a33);display:inline-flex;align-items:center;gap:7px;padding:8px 16px;border-radius:var(--hsk-border-radius,0);border:1px solid rgba(255,106,51,.4);background:rgba(255,106,51,.1);color:var(--hsk-primary);font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,transform .12s,box-shadow .15s;font-family:inherit;white-space:nowrap}.hsk-cb-btn:hover{background:rgba(255,106,51,.18);border-color:rgba(255,106,51,.7);box-shadow:0 4px 16px rgba(255,106,51,.2)}.hsk-cb-btn:active{transform:scale(.95)}.hsk-cb-btn-icon{font-size:15px;line-height:1;display:flex;align-items:center}.hsk-cb-overlay{--hsk-primary:var(--chat-primary-color,#ff6a33);--hsk-font:var(--chat-font-family,\\\"Geist\\\",ui-sans-serif,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif);letter-spacing:normal;word-spacing:normal;font-kerning:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--hsk-font-size:var(--hsk-desktop-font-size,15px);--hsk-mobile-font-size:14px;position:fixed !important;inset:0 !important;width:100vw !important;height:100vh !important;height:100dvh !important;z-index:2147483647 !important;display:flex !important;flex-direction:column !important;overflow:hidden !important;animation:hsk-overlay-in .2s ease-out;background:var(--hsk-chat-bg,#ffffff) !important;box-sizing:border-box !important;margin:0 !important;padding:0 !important}@keyframes hsk-overlay-in{from{opacity:0}to{opacity:1}}.hsk-cb-overlay.hsk-cb-overlay--grows{animation:hsk-overlay-in .18s cubic-bezier(.16,1,.3,1) both !important}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-panel{transform-origin:var(--hsk-ox,50%) var(--hsk-oy,50%);animation:hsk-panel-float-in .22s cubic-bezier(.16,1,.3,1) both !important}@keyframes hsk-panel-float-in{0%{opacity:0;transform:translateY(8px) scale(.985)}100%{opacity:1;transform:translateY(0) scale(1)}}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-msgs{animation:hsk-content-fade .2s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-content-fade{0%{opacity:0;transform:translateY(4px)}100%{opacity:1;transform:translateY(0)}}.hsk-cb-lang-chip,.hsk-cb-chip{animation:hsk-pill-wave .22s cubic-bezier(.16,1,.3,1) both;animation-delay:calc(.04s+var(--hsk-pill-idx,0) * .012s)}.hsk-cb-lang-chips-hint{animation:hsk-content-fade .22s cubic-bezier(.16,1,.3,1) both;animation-delay:calc(.04s+var(--hsk-pill-idx,0) * .012s)}@keyframes hsk-pill-wave{0%{opacity:0;transform:translateY(6px) scale(.96)}100%{opacity:1;transform:translateY(0) scale(1)}}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-input-wrap{animation:hsk-input-dock .22s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-input-dock{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-hello-avatar{animation:hsk-avatar-spring .22s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-avatar-spring{0%{opacity:0;transform:scale(.92)}100%{opacity:1;transform:scale(1)}}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-hello-wrap{animation:hsk-hello-spring .2s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-hello-spring{0%{opacity:0;transform:translateY(6px)}100%{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion:reduce){.hsk-cb-overlay.hsk-cb-overlay--grows{animation:none !important;-webkit-clip-path:none !important;clip-path:none !important}.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-panel,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-msgs,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-lang-chip,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-chip,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-input-wrap,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-hello-avatar,.hsk-cb-overlay.hsk-cb-overlay--grows .hsk-cb-hello-wrap{animation:none !important}}.hsk-cb-panel{position:relative;display:flex;flex-direction:column;height:100%;max-width:720px;width:100%;margin:0 auto;animation:hsk-panel-in .28s cubic-bezier(.34,1.2,.64,1)}.hsk-cb-main{flex:1;min-width:0;display:flex;flex-direction:column;height:100%;overflow:hidden}@keyframes hsk-panel-in{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}.hsk-cb-topbar{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;padding:14px var(--hsk-gutter,24px) 10px;flex-shrink:0;position:relative;z-index:10;background:transparent !important;backdrop-filter:none !important;-webkit-backdrop-filter:none !important}.hsk-cb-topbar::after{display:none !important}.hsk-cb-topbar-left{display:flex;align-items:center;gap:10px;justify-self:start;min-width:0}.hsk-cb-topbar-mark{justify-self:center;display:flex;flex-direction:column;align-items:center;line-height:0;cursor:pointer;user-select:none;touch-action:manipulation;transition:transform .22s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-topbar-mark:hover{transform:translateY(-1px)}.hsk-cb-topbar-mark[data-unread=\\\"true\\\"] .hsk-cb-topbar-name{background:var(--hsk-primary,#ff6a33);color:#fff;box-shadow:0 0 0 3px var(--hsk-chat-bg,#ffffff);animation:hsk-unread-pill .9s cubic-bezier(.34,1.56,.64,1) infinite}@keyframes hsk-unread-pill{0%,100%{transform:scale(1,1)}38%{transform:scale(1.08,.92)}62%{transform:scale(.97,1.03)}}@media (prefers-reduced-motion:reduce){.hsk-cb-topbar-mark[data-unread=\\\"true\\\"] .hsk-cb-topbar-name{animation:none}}.hsk-cb-topbar-name{margin-top:-5px;padding:3px 13px;white-space:nowrap;border-radius:999px;background:var(--hsk-surface-2);box-shadow:0 0 0 3px var(--hsk-chat-bg),0 1px 3px rgba(0,0,0,.12);font-size:12px;font-weight:700;line-height:18px;letter-spacing:-.01em;color:var(--hsk-name-text,var(--hsk-chat-text));transform-origin:50% 0;transition:transform .18s cubic-bezier(.34,1.8,.64,1)}.hsk-cb-topbar-mark{position:relative;z-index:100}.hsk-cb-topbar-ooze-menu{position:absolute;top:calc(100%+12px) !important;left:50%;transform:translateX(-50%);width:216px;padding:6px;border-radius:20px;background:var(--hsk-chat-source-bg,rgba(255,255,255,.08));border:none !important;box-shadow:none !important;z-index:1000;animation:hsk-topbar-ooze .25s cubic-bezier(.16,1,.3,1) both}.hsk-cb-topbar-ooze-menu .hsk-cb-theme-2x2-grid{display:grid !important;grid-template-columns:repeat(2,1fr) !important;gap:6px !important;width:100% !important;box-shadow:none !important}.hsk-cb-topbar-ooze-menu .hsk-cb-theme-grid-item{width:100%;display:inline-flex;align-items:center;justify-content:flex-start;gap:6px;padding:8px 11px;border-radius:14px;border:none !important;box-shadow:none !important;font-size:11.5px;font-weight:550;box-sizing:border-box;white-space:nowrap}@keyframes hsk-topbar-ooze{0%{opacity:0;transform:translateX(-50%) translateY(-6px) scale(.94)}100%{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}}.hsk-cb-topbar-mark[data-impacting=\\\"true\\\"] .hsk-cb-topbar-name{transform:translateY(1.5px) scale(1.09,.91);box-shadow:0 0 0 3px var(--hsk-chat-bg,#ffffff),0 2px 10px var(--hsk-contact-glow,rgba(19,78,61,.45))}.hsk-cb-back{width:34px;height:34px;border-radius:999px;border:none;padding:0;display:flex;align-items:center;justify-content:center;background:var(--hsk-surface-1);color:var(--hsk-chat-muted);cursor:pointer;transition:transform .18s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-back:hover{background:var(--hsk-chat-divide,rgba(0,0,0,.09))}.hsk-cb-back:active{transform:scale(.94)}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-back-icon{display:inline-flex;transform:scaleX(-1)}.hsk-cb-topbar-actions{justify-self:end}.hsk-cb-topbar-title{font-size:16px;font-weight:500;color:var(--hsk-chat-text,#1f1f1f);letter-spacing:-.01em}.hsk-cb-topbar-sub{font-size:12px;color:var(--hsk-chat-muted,#5f6368);margin-top:2px}.hsk-cb-kiku-id-rail{display:none}@media (min-width:900px){.hsk-cb-kiku-id-rail.hsk-cb-kiku-id-rail--left{display:flex;position:absolute;left:auto !important;right:100% !important;margin-right:28px !important;transform:none !important;top:auto !important;bottom:48px !important;flex-direction:column;justify-content:flex-end;align-items:flex-start;gap:8px;max-width:240px;min-width:0;padding:0;border:0;background:none;font-family:inherit;z-index:10}.hsk-cb-kiku-id-rail.hsk-cb-kiku-id-rail--right{display:flex;position:absolute;left:100% !important;right:auto !important;margin-left:28px !important;transform:none !important;top:auto !important;bottom:48px !important;flex-direction:column;justify-content:flex-end;align-items:flex-start;gap:8px;max-width:240px;min-width:0;padding:0;border:0;background:none;font-family:inherit;z-index:10}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-kiku-id-rail{bottom:50px !important}.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-kiku-id-rail{bottom:58px !important}.hsk-cb-kiku-id-pill{display:inline-flex;align-items:center;gap:6px;max-width:100%;padding:5px 12px;border-radius:999px;border:none !important;background:var(--hsk-chat-source-bg,rgba(255,255,255,.05));color:var(--hsk-chat-muted,#71717a);cursor:pointer;font-family:inherit;transition:all .22s cubic-bezier(.16,1,.3,1)}.hsk-cb-kiku-id-pill:hover{color:var(--hsk-primary,#ff6a33)}.hsk-cb-kiku-id-rail-val{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;letter-spacing:-.01em;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hsk-cb-kiku-id-pill svg{flex:none;opacity:.8}.hsk-cb-theme-squircle-wrap{position:relative;display:flex;flex-direction:column;align-items:flex-start;padding:0;margin:0;border:none !important;box-shadow:none !important;background:transparent;transition:all .28s cubic-bezier(.16,1,.3,1)}.hsk-cb-theme-squircle-wrap.is-open{padding:6px;border-radius:18px;background:var(--hsk-chat-source-bg,rgba(255,255,255,.06));box-shadow:none !important}.hsk-cb-theme-squircle-trigger{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 12px;border-radius:16px;border:none !important;outline:none !important;background:var(--hsk-surface-1) !important;color:var(--hsk-chat-text) !important;font-size:11.5px;font-weight:600;cursor:pointer;font-family:inherit;transition:transform .2s cubic-bezier(.16,1,.3,1);box-shadow:none !important}.hsk-cb-theme-squircle-trigger:hover{background:var(--hsk-primary,#ff6a33);color:#ffffff;box-shadow:none !important}.hsk-cb-theme-trigger-icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.hsk-cb-theme-trigger-icon svg{width:13px;height:13px}.hsk-cb-theme-trigger-label{letter-spacing:-0.01em}.hsk-cb-theme-2x2-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:5px;box-shadow:none !important;transform-origin:bottom center;animation:hsk-theme-morph-in .26s cubic-bezier(.16,1,.3,1) both}.hsk-cb-theme-squircle-wrap.is-closing .hsk-cb-theme-2x2-grid{animation:hsk-theme-morph-out .2s cubic-bezier(.4,0,.9,.4) both}.hsk-cb-theme-grid-item{display:inline-flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:6px;padding:7px 11px;border-radius:13px;border:none !important;outline:none !important;background:var(--hsk-chat-bg,#1a1a1c);color:var(--hsk-chat-muted,#a1a1aa);font-size:11px;font-weight:550;cursor:pointer;font-family:inherit;transition:all .18s cubic-bezier(.16,1,.3,1);box-shadow:none !important}.hsk-cb-theme-grid-item svg{flex-shrink:0;width:12px;height:12px}.hsk-cb-theme-grid-item:hover{background:rgba(255,255,255,.1);color:var(--hsk-chat-text,#f0efed);box-shadow:none !important}.hsk-cb-theme-grid-item.is-active{background:var(--hsk-primary,#ff6a33) !important;color:#ffffff !important;box-shadow:none !important}}@keyframes hsk-ooze-in{0%{opacity:0;transform:translateX(-50%) translateY(-16px) scale(.88);filter:blur(6px)}65%{transform:translateX(-50%) translateY(3px) scale(1.02);filter:blur(0)}100%{opacity:1;transform:translateX(-50%) translateY(0) scale(1);filter:blur(0)}}.hsk-cb-topbar-actions{display:flex;align-items:center;gap:8px}.hsk-cb-topbar-btn{height:34px;padding:0 14px;border-radius:var(--hsk-control-radius,999px);border:1px solid transparent;background:var(--hsk-chat-subtle,rgba(0,0,0,.045));color:var(--hsk-chat-muted,#5f6368);font-size:12px;font-weight:500;cursor:pointer;transition:all .15s;font-family:inherit}.hsk-cb-topbar-btn:hover{background:color-mix(in srgb,var(--hsk-primary) 12%,transparent);color:var(--hsk-primary)}.hsk-cb-close{width:34px;height:34px;border-radius:var(--hsk-control-radius,999px);border:1px solid transparent;background:var(--hsk-chat-subtle,rgba(0,0,0,.045));color:var(--hsk-chat-muted,#5f6368);cursor:pointer;font-size:20px;display:flex;align-items:center;justify-content:center;transition:all .15s;flex-shrink:0;font-family:inherit;line-height:1}.hsk-cb-close:hover{background:color-mix(in srgb,var(--hsk-primary) 12%,transparent);color:var(--hsk-primary)}.hsk-cb-msgs{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;touch-action:pan-y;overscroll-behavior-y:none;overflow-anchor:none;padding:16px var(--hsk-gutter,24px) 16px;display:flex;flex-direction:column;gap:0;scrollbar-width:none;-ms-overflow-style:none;mask-image:linear-gradient(to bottom,transparent 0,#000000 8px,#000000 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0,#000000 8px,#000000 100%)}.hsk-cb-msgs>:first-child{margin-top:auto}.hsk-cb-msgs.hsk-scrolling>*{pointer-events:none}.hsk-cb-msgs::-webkit-scrollbar{display:none !important;width:0 !important;height:0 !important}.hsk-cb-empty{flex:1;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:14px;padding:24px 0 32px;width:100%;text-align:start}.hsk-cb-onboarding-card{display:flex;flex-direction:column;align-items:flex-start;width:100%;gap:10px}.hsk-cb-onboarding-head{display:flex;align-items:center;justify-content:flex-end;width:100%;margin-bottom:8px}.hsk-cb-step-badge{font-size:11px;font-weight:600;letter-spacing:.05em;color:var(--hsk-chat-muted,#71717a);background:var(--hsk-chat-source-bg,rgba(255,255,255,.06));border:1px solid var(--hsk-chat-border,rgba(255,255,255,.08));padding:4px 10px;border-radius:999px;line-height:1}.hsk-cb-hello-wrap{display:flex;flex-direction:column;align-items:flex-start;text-align:start;gap:6px;padding:0;width:100%}.hsk-cb-hello-avatar{--hsk-avatar-size:80px;display:flex;align-items:center;justify-content:flex-start;width:auto;margin-inline-start:calc(var(--hsk-avatar-size,80px) * -0.25);margin-inline-end:0;margin-top:0;margin-bottom:0;animation:hsk-avatar-spring .42s cubic-bezier(.16,1,.3,1) both}.hsk-cb-hello{margin:0;font-size:clamp(24px,4.5vw,34px);font-weight:500;line-height:1.2;letter-spacing:-0.02em;color:color-mix(in srgb,var(--hsk-chat-text,#111) 55%,var(--hsk-chat-muted,#8b8b8f));text-align:start}.hsk-cb-hello b{font-weight:700;color:var(--hsk-primary,#ff6a33)}.hsk-cb-hello-lead{margin:0;font-size:15px;line-height:22px;color:var(--hsk-chat-muted,#5f6368);max-width:42ch;text-align:start}.hsk-cb-hello-ask{margin:2px 0 2px;font-size:16px;font-weight:500;color:var(--hsk-chat-text,#111);text-align:start}.hsk-cb-step{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--hsk-chat-muted,#9aa0a6)}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-msgs{direction:ltr}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-msgs>*{direction:rtl}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-user-imgs{margin-left:0;margin-right:auto}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-user-bubble,.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-ai-text{word-break:normal;overflow-wrap:break-word;letter-spacing:normal}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-hello{line-height:1.6;letter-spacing:normal}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-entlang-cards{justify-content:end}.hsk-cb-lang-chips{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 4px}.hsk-cb-lang-chip{display:inline-flex;align-items:center;justify-content:center;min-height:36px;padding:6px 16px;font-size:14px;font-weight:500;line-height:1;color:var(--hsk-chat-text,#111);background:var(--hsk-chat-source-bg,rgba(0,0,0,.04));border:1px solid var(--hsk-chat-border,rgba(0,0,0,.09));border-radius:999px;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.03);transition:all .18s cubic-bezier(.16,1,.3,1);user-select:none;-webkit-font-smoothing:antialiased}.hsk-cb-lang-chip:hover{background:var(--hsk-primary,#ff6a33);color:#ffffff;border-color:var(--hsk-primary,#ff6a33);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--hsk-primary,#ff6a33) 25%,transparent)}.hsk-cb-lang-chip:active{transform:scale(.96)}@media (prefers-color-scheme:dark){.hsk-cb-lang-chip{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.1);color:#f4f4f5}}[data-hsk-theme=\\\"dark\\\"] .hsk-cb-lang-chip{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.1);color:#f4f4f5}.hsk-cb-lang-chips-hint{display:inline-flex;align-items:center;font-size:13px;color:var(--hsk-chat-muted,#71717a);padding:0 6px;margin-inline-start:4px;user-select:none;align-self:center}.hsk-cb-chrome-loading{display:flex;flex-direction:column;align-items:flex-start;text-align:start;gap:12px;width:100%;max-width:480px;margin:4px 0 2px;animation:hsk-content-fade .3s ease-out both}.hsk-cb-chrome-loading-header{display:flex;flex-direction:column;align-items:flex-start;text-align:start;gap:6px;width:100%}.hsk-cb-chrome-loading-sub{margin:0;font-size:15px;color:var(--hsk-chat-muted,#71717a);line-height:1.45;text-align:start}.hsk-cb-chrome-loading-sub b{color:var(--hsk-chat-text,#f4f4f5);font-weight:600}.hsk-cb-chrome-progress{height:3px;width:100%;border-radius:3px;background:var(--hsk-chat-source-bg,rgba(255,255,255,.08));overflow:hidden;margin-top:4px}.hsk-cb-chrome-progress-track{height:100%;width:100%;border-radius:3px;background:linear-gradient( 90deg,#ff6a33,#f7b733,#43c59e,#3d8bfd,#9b5de5,#ff5d8f,#ff6a33 );background-size:300% 100%;animation:hsk-chrome-rainbow 2.6s linear infinite}.hsk-cb-chrome-progress{position:relative;overflow:hidden}.hsk-cb-chrome-progress::after{content:'';position:absolute;inset:0;background:linear-gradient( 100deg,transparent 20%,rgba(255,255,255,.55) 50%,transparent 80% );transform:translateX(-100%);animation:hsk-chrome-sheen 1.9s cubic-bezier(.55,0,.45,1) infinite;pointer-events:none}@keyframes hsk-chrome-rainbow{0%{background-position:0 0}100%{background-position:-300% 0}}@keyframes hsk-chrome-sheen{0%{transform:translateX(-100%)}100%{transform:translateX(200%)}}@media (prefers-reduced-motion:reduce){.hsk-cb-chrome-progress-track{animation:none;opacity:.5}.hsk-cb-chrome-progress::after{animation:none;opacity:0}}.hsk-cb-chrome-back-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;margin-top:6px;font-size:13px;font-weight:500;color:var(--hsk-chat-muted,#a1a1aa);background:var(--hsk-chat-source-bg,rgba(255,255,255,.05));border:1px solid var(--hsk-chat-border,rgba(255,255,255,.09));border-radius:999px;cursor:pointer;transition:all .15s ease;user-select:none}.hsk-cb-chrome-back-btn:hover{background:var(--hsk-chat-source-bg,rgba(255,255,255,.12));color:var(--hsk-chat-text,#ffffff);border-color:var(--hsk-chat-border,rgba(255,255,255,.18))}.hsk-cb-chrome-notice{display:flex;flex-direction:column;gap:6px;max-width:48ch;margin:24px 0 0;padding:14px 16px;border-radius:14px;background:var(--hsk-chat-source-bg,rgba(255,255,255,.04));border:1px solid var(--hsk-chat-border,rgba(255,255,255,.09));text-align:start;font-family:var(--hsk-font,system-ui,sans-serif);animation:hsk-content-fade .4s ease-out both}.hsk-cb-chrome-notice-header{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.hsk-cb-chrome-notice-pill{display:inline-flex;align-items:center;padding:2px 7px;border-radius:6px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;background:rgba(255,106,51,.15);color:var(--hsk-primary,#ff6a33);border:1px solid rgba(255,106,51,.28)}.hsk-cb-chrome-notice-title{font-size:12px;font-weight:600;letter-spacing:.01em;color:var(--hsk-chat-text,#ffffff)}.hsk-cb-chrome-notice-body{font-size:12px;line-height:1.55;color:var(--hsk-chat-muted,#a1a1aa)}.hsk-cb-chrome-notice-body b{color:var(--hsk-chat-text,#ffffff)}@media (prefers-color-scheme:light){.hsk-cb-chrome-loading-sub b{color:var(--hsk-chat-text,#18181b)}.hsk-cb-chrome-progress{background:var(--hsk-chat-source-bg,rgba(0,0,0,.06))}.hsk-cb-chrome-back-btn{color:#52525b;background:rgba(0,0,0,.04);border-color:rgba(0,0,0,.08)}.hsk-cb-chrome-back-btn:hover{background:rgba(0,0,0,.08);color:#09090b;border-color:rgba(0,0,0,.14)}}.hsk-cb-input-box--waiting{opacity:.45;pointer-events:none}.hsk-cb-entlang-opts{display:flex;flex-direction:column;gap:10px;width:100%;max-width:440px;margin-top:6px}.hsk-cb-entlang-opt{position:relative;display:flex;flex-direction:row;align-items:center;width:100%;padding:16px 20px;text-align:start;background:transparent !important;border:none !important;outline:none !important;border-radius:16px;cursor:pointer;user-select:none;overflow:hidden;box-shadow:none !important;animation:hsk-entlang-opt-in .22s cubic-bezier(.16,1,.3,1) both;animation-delay:calc(.04s+var(--hsk-opt-idx,0) * .02s)}@media (prefers-color-scheme:light){.hsk-cb-entlang-opt{background:transparent !important}}[data-hsk-theme=\\\"light\\\"] .hsk-cb-entlang-opt{background:transparent !important}@keyframes hsk-entlang-opt-in{0%{opacity:0;transform:translateY(6px)}100%{opacity:1;transform:translateY(0)}}.hsk-cb-entlang-opt:hover{background:transparent !important;border:none !important;box-shadow:none !important}.hsk-cb-entlang-opt:active{opacity:.8}.hsk-cb-entlang-radio{position:relative;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;min-height:18px;border-radius:999px;border:1.5px solid var(--hsk-chat-divide,rgba(255,255,255,.22));flex-shrink:0;margin-inline-end:14px;box-sizing:border-box;transform:none !important;transition:border-color .2s cubic-bezier(.16,1,.3,1),background-color .2s ease}.hsk-cb-entlang-radio-dot{width:9px;height:9px;border-radius:999px;background:var(--hsk-primary,#ff6a33);opacity:0;transition:opacity .15s ease;pointer-events:none}.hsk-cb-entlang-opt:hover .hsk-cb-entlang-radio,.hsk-cb-entlang-opt.is-selected .hsk-cb-entlang-radio{border-color:var(--hsk-primary,#ff6a33)}.hsk-cb-entlang-opt.is-selected .hsk-cb-entlang-radio-dot{opacity:1}.hsk-cb-entlang-opt-text{display:flex;flex-direction:column;gap:3px;width:100%}.hsk-cb-entlang-opt-title{font-size:15px;font-weight:600;color:var(--hsk-chat-text,#1f1f1f);letter-spacing:-0.01em}.hsk-cb-entlang-opt-note{font-size:12.5px;color:var(--hsk-chat-muted,#71717a);line-height:1.45}.hsk-cb-shimmer-char{display:inline;color:inherit;font-family:inherit}.hsk-cb-entlang-opt:hover .hsk-cb-entlang-opt-title .hsk-cb-shimmer-char{animation:hsk-entlang-char-shimmer-title .5s cubic-bezier(.16,1,.3,1) both;animation-delay:calc(var(--hsk-char-idx,0) * 16ms)}.hsk-cb-entlang-opt:hover .hsk-cb-entlang-opt-note .hsk-cb-shimmer-char{animation:hsk-entlang-char-shimmer-note .5s cubic-bezier(.16,1,.3,1) both;animation-delay:calc(var(--hsk-char-idx,0) * 16ms)}@keyframes hsk-entlang-char-shimmer-title{0%{color:var(--hsk-chat-text,#1f1f1f)}45%{color:hsl(var(--hsk-ph-hue,0) 80% 60%)}100%{color:var(--hsk-primary,#ff6a33)}}@keyframes hsk-entlang-char-shimmer-note{0%{color:var(--hsk-chat-muted,#71717a)}45%{color:hsl(var(--hsk-ph-hue,0) 75% 55%)}100%{color:var(--hsk-chat-muted,#71717a)}}.hsk-cb-entlang-opt-note{font-size:12.5px;color:var(--hsk-chat-muted,#71717a);line-height:1.45}@keyframes hsk-hello-rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}.hsk-cb-hello,.hsk-cb-hello-lead,.hsk-cb-hello-ask,.hsk-cb-hello-skip{opacity:0;animation:hsk-hello-rise .9s cubic-bezier(.22,1,.36,1) both}.hsk-cb-hello{animation-delay:.06s}.hsk-cb-hello-lead{animation-delay:.26s}.hsk-cb-hello-ask{animation-delay:.44s}.hsk-cb-hello-skip{animation-delay:.60s}.hsk-cb-hello.hsk-cascade,.hsk-cb-hello-lead.hsk-cascade,.hsk-cb-hello-ask.hsk-cascade{opacity:1;animation:none;filter:none}.hsk-cascade__w{display:inline-block;white-space:nowrap;opacity:0;animation:hsk-cascade-rise .44s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-cascade-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion:reduce){.hsk-cb-hello,.hsk-cb-hello-lead,.hsk-cb-hello-ask,.hsk-cb-hello-skip,.hsk-cascade__w{animation:none;opacity:1;transform:none;filter:none}}.hsk-cb-chips{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-start;margin-top:4px}.hsk-cb-chip{padding:8px 16px;border-radius:var(--hsk-border-radius,0);border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.1));background:var(--hsk-chat-source-bg,rgba(0,0,0,.03));color:var(--hsk-chat-text,#333);font-size:13px;cursor:pointer;transition:all .15s;font-family:inherit}.hsk-cb-chip:hover{border-color:var(--hsk-primary);color:var(--hsk-primary);background:rgba(255,106,51,.06)}.hsk-cb-msg-group{padding:16px 0;border-bottom:none;animation:hsk-msg-in .22s ease-out both}.hsk-cb-spoken-mark{position:absolute;top:50%;margin-top:-5px;inset-inline-start:-17px;opacity:.4;pointer-events:none}.hsk-cb-msg-group--run-mid{padding-bottom:0}.hsk-cb-msg-group--run-mid .hsk-cb-user-msg{margin-bottom:0}.hsk-cb-msg-group--run-cont{padding-top:2px}.hsk-cb-msg-group:last-child{border-bottom:none}@keyframes hsk-msg-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.hsk-cb-user-msg{display:flex;flex-direction:column;align-items:flex-end;align-self:flex-end;max-width:min(75%,420px);margin-inline-start:auto;margin-inline-end:0;gap:6px;margin-bottom:20px}@media (max-width:640px){.hsk-cb-user-msg{max-width:84%}}.hsk-cb-user-msg.hsk-sent{transform-origin:bottom right;animation:hsk-send-in .42s cubic-bezier(.2,.9,.3,1.2) both}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-user-msg.hsk-sent{transform-origin:bottom left}@keyframes hsk-send-in{0%{opacity:0;transform:translateY(28px) scale(.55)}55%{opacity:1}75%{transform:translateY(-2px) scale(1.02)}100%{opacity:1;transform:translateY(0) scale(1)}}@media (prefers-reduced-motion:reduce){.hsk-cb-user-msg.hsk-sent{animation:none}}.hsk-cb-user-bubble{background:var(--hsk-user-bubble-bg,#007aff);color:#ffffff;padding:10px 18px;border-radius:20px;position:relative;font-size:var(--hsk-font-size,15.5px);font-family:var(--hsk-font);line-height:1.45;max-width:100%;font-weight:500;word-break:break-word;overflow-wrap:anywhere;letter-spacing:-0.01em}.hsk-cb-user-bubble--tail::before,.hsk-cb-user-bubble--tail::after{content:'';position:absolute;bottom:0;height:25px;pointer-events:none}.hsk-cb-user-bubble--tail::before{right:-7px;width:20px;background:var(--hsk-user-bubble-bg,#007aff);border-bottom-left-radius:16px 14px}.hsk-cb-user-bubble--tail::after{right:-26px;width:26px;background:var(--hsk-chat-bg,#ffffff);border-bottom-left-radius:10px}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-user-bubble--tail::before{right:auto;left:-7px;border-bottom-left-radius:0;border-bottom-right-radius:16px 14px}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-user-bubble--tail::after{right:auto;left:-26px;border-bottom-left-radius:0;border-bottom-right-radius:10px}.hsk-cb-ai-msg{display:block}.hsk-cb-ai-icon{width:32px;height:32px;border-radius:0;background:transparent !important;border:none !important;color:var(--hsk-primary,#ff6a33);display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:-2px}.hsk-cb-ai-icon>svg{width:30px !important;height:30px !important}.hsk-cb-ai-icon>.hsk-cb-ai-mark{width:40px !important;height:40px !important}.hsk-cb-ai-body{flex:1;min-width:0}.hsk-cb-ai-content{display:flex;flex-direction:column;gap:10px;align-items:flex-start;width:100%}.hsk-cb-think+.hsk-cb-ai-content>.hsk-cb-ai-text:first-child{padding-top:20px}.hsk-cb-ai-text{font-size:var(--hsk-font-size,14.5px);font-family:var(--hsk-font);line-height:1.48;color:var(--hsk-chat-text,#111827);background:var(--hsk-chat-ai-bg,#eeeef0);padding:11px 15px;border-radius:18px;position:relative;display:inline-block;width:fit-content;box-sizing:border-box;max-width:min(88%,560px);word-break:break-word;overflow-wrap:anywhere;margin-top:4px}.hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::before,.hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::after{content:'';position:absolute;bottom:0;height:25px;pointer-events:none}.hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::before{left:-7px;width:20px;background:var(--hsk-chat-ai-bg,#eeeef0);border-bottom-right-radius:16px 14px}.hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::after{left:-26px;width:26px;background:var(--hsk-chat-bg,#ffffff);border-bottom-right-radius:10px}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::before{left:auto;right:-7px;border-bottom-right-radius:0;border-bottom-left-radius:16px 14px}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::after{left:auto;right:-26px;border-bottom-right-radius:0;border-bottom-left-radius:10px}.hsk-cb-sent-status{font-size:11px;line-height:1;color:var(--hsk-chat-muted,#8a8f98);padding:4px 6px 0 0;animation:hsk-sent-in .2s ease-out both}@keyframes hsk-sent-in{from{opacity:0}to{opacity:1}}.hsk-cb-user-bubble--queued{opacity:.55}.hsk-cb-queued-status{display:inline-flex;align-items:center;gap:5px;font-size:11px;line-height:1;color:var(--hsk-chat-muted,#8a8f98);padding:4px 0 0;background:none;border:none;cursor:pointer;font-family:var(--hsk-font);animation:hsk-sent-in .2s ease-out both}.hsk-cb-queued-dot{width:5px;height:5px;border-radius:999px;background:currentColor;animation:hsk-queued-pulse 1.1s ease-in-out infinite}@keyframes hsk-queued-pulse{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}.hsk-cb-queued-now{color:var(--hsk-primary,#ff6a33);font-weight:600;transition:opacity .15s ease}.hsk-cb-queued-status:hover .hsk-cb-queued-now{opacity:.7}@media (prefers-reduced-motion:reduce){.hsk-cb-queued-dot{animation:none;opacity:.8}}.hsk-cb-timeline{display:none}@media (min-width:900px){.hsk-cb-timeline.hsk-cb-timeline--left{display:block;position:absolute;left:auto !important;right:100% !important;margin-right:28px !important;top:50%;transform:translateY(-50%) !important;width:180px;max-height:60%;overflow:hidden;z-index:10;pointer-events:auto;direction:ltr !important;-webkit-mask-image:linear-gradient(to bottom,transparent,#000 14%,#000 86%,transparent);mask-image:linear-gradient(to bottom,transparent,#000 14%,#000 86%,transparent)}.hsk-cb-timeline.hsk-cb-timeline--right{display:block;position:absolute;left:100% !important;right:auto !important;margin-left:28px !important;top:50%;transform:translateY(-50%) !important;width:180px;max-height:60%;overflow:hidden;z-index:10;pointer-events:auto;direction:ltr !important;-webkit-mask-image:linear-gradient(to bottom,transparent,#000 14%,#000 86%,transparent);mask-image:linear-gradient(to bottom,transparent,#000 14%,#000 86%,transparent)}.hsk-cb-timeline-track{animation:hsk-tl-in .32s cubic-bezier(.22,1,.36,1) both}}@keyframes hsk-tl-in{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}.hsk-cb-timeline-track{--hsk-tl-x:9px;position:relative;padding-left:26px !important;padding-right:6px !important}.hsk-cb-timeline-track::before,.hsk-cb-timeline-track::after{content:'';position:absolute;left:calc(var(--hsk-tl-x) - 1px) !important;right:auto !important;top:8px;bottom:8px;width:2px;border-radius:2px}.hsk-cb-timeline-track::before{background:var(--hsk-chat-divide,rgba(0,0,0,.09))}.hsk-cb-timeline-track::after{background:var(--hsk-primary,#ff6a33);opacity:.5;transform-origin:top;transform:scaleY(var(--hsk-tl-progress,0));transition:transform .18s linear}.hsk-cb-tl-item{--hsk-tl-d:0;position:relative;display:block;width:100%;padding:7px 6px 7px 0 !important;border:none;background:none;text-align:left !important;cursor:pointer;font-family:var(--hsk-font)}.hsk-cb-tl-dot{position:absolute;left:calc(var(--hsk-tl-x,9px) - 3.5px) !important;right:auto !important;top:50%;width:7px;height:7px;margin-top:-3.5px;border-radius:999px;background:var(--hsk-chat-divide,rgba(0,0,0,.18));opacity:max(.25,calc(1 - var(--hsk-tl-d) * .22));transition:transform .28s cubic-bezier(.34,1.4,.64,1),opacity .46s cubic-bezier(.22,1,.36,1),background .2s ease}.hsk-cb-tl-label{display:block;font-size:12px;line-height:1.4;color:var(--hsk-chat-muted,#8a8f98);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transform:translateX(calc(var(--hsk-tl-d) * 7px));opacity:max(.32,calc(.9 - var(--hsk-tl-d) * .15));transition:transform .46s cubic-bezier(.22,1,.36,1),opacity .46s cubic-bezier(.22,1,.36,1),color .2s ease}.hsk-cb-tl-item:hover .hsk-cb-tl-label{opacity:1;transform:translateX(calc(var(--hsk-tl-d) * 7px - 2px))}.hsk-cb-tl-item:hover .hsk-cb-tl-dot{transform:scale(1.25)}.hsk-cb-tl-cursor{position:absolute;left:calc(var(--hsk-tl-x,9px) - 4.5px) !important;right:auto !important;top:0;width:9px;height:9px;margin-top:-4.5px;border-radius:999px;background:var(--hsk-primary,#ff6a33);transform:translateY(0);transition:transform .44s cubic-bezier(.22,1,.36,1);will-change:transform;pointer-events:none}.hsk-cb-tl-item--on .hsk-cb-tl-dot{opacity:.35}.hsk-cb-tl-item--on .hsk-cb-tl-label{color:var(--hsk-chat-text,#1f1f1f);opacity:1;font-weight:500}@media (prefers-reduced-motion:reduce){.hsk-cb-timeline-track{animation:none}.hsk-cb-timeline-track::after,.hsk-cb-tl-label,.hsk-cb-tl-cursor,.hsk-cb-tl-dot{transition:none}}@media (prefers-color-scheme:dark){.hsk-cb-ai-text{--hsk-chat-ai-bg:#26262a;background:var(--hsk-chat-ai-bg);color:#f9fafb}}.hsk-cb-sources-wrap{position:relative;margin-top:20px}.hsk-cb-sources{display:flex;flex-direction:row;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none;padding-bottom:4px}.hsk-cb-sources::-webkit-scrollbar{display:none}.hsk-cb-sources-fade-left,.hsk-cb-sources-fade-right{position:absolute;top:0;bottom:4px;width:30px;pointer-events:none;z-index:2}.hsk-cb-sources-fade-left,.hsk-cb-sources-fade-right{background-color:var(--hsk-fade-bg,var(--hsk-chat-bg,#0e0e0f))}.hsk-cb-sources-fade-left,[dir=\\\"rtl\\\"] .hsk-cb-sources-fade-right{-webkit-mask-image:linear-gradient(to right,#000 0,rgba(0,0,0,.55) 45%,transparent 100%);mask-image:linear-gradient(to right,#000 0,rgba(0,0,0,.55) 45%,transparent 100%)}.hsk-cb-sources-fade-right,[dir=\\\"rtl\\\"] .hsk-cb-sources-fade-left{-webkit-mask-image:linear-gradient(to left,#000 0,rgba(0,0,0,.55) 45%,transparent 100%);mask-image:linear-gradient(to left,#000 0,rgba(0,0,0,.55) 45%,transparent 100%)}.hsk-cb-sources-fade-left{inset-inline-start:0}.hsk-cb-sources-fade-right{inset-inline-end:0}.hsk-cb-sources-next,.hsk-cb-sources-prev{position:absolute;top:42%;transform:translateY(-50%);width:34px;height:34px;border-radius:50% !important;background:var(--hsk-chat-bg,#ffffff) !important;border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.12)) !important;color:var(--hsk-primary,#ff6a33) !important;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(0,0,0,.14);z-index:10;cursor:pointer;transition:transform .2s cubic-bezier(.34,1.56,.64,1),background .18s ease,color .18s ease,box-shadow .18s ease}.hsk-cb-sources-next:hover,.hsk-cb-sources-prev:hover{background:var(--hsk-primary,#ff6a33) !important;color:#ffffff !important;border-color:var(--hsk-primary,#ff6a33) !important;transform:translateY(-50%) scale(1.1);box-shadow:0 6px 18px rgba(255,106,51,.35)}.hsk-cb-sources-next{inset-inline-end:2px}.hsk-cb-sources-prev{inset-inline-start:2px}[dir=\\\"rtl\\\"] .hsk-cb-sources-next svg,[dir=\\\"rtl\\\"] .hsk-cb-sources-prev svg{transform:scaleX(-1)}.hsk-cb-carousel-dots{display:flex;align-items:center;justify-content:center;gap:5px;margin-top:10px}.hsk-cb-dot-item{width:6px;height:6px;border-radius:50%;background:rgba(150,150,150,.35);transition:all .25s cubic-bezier(.34,1.56,.64,1);cursor:pointer}.hsk-cb-dot-item--active{width:18px;border-radius:999px;background:var(--hsk-primary,#ff6a33)}.hsk-cb-source{flex:0 0 188px;scroll-snap-align:start;border-radius:var(--hsk-border-radius,0);border:none;background:transparent;cursor:pointer;transition:transform .14s,opacity .14s;animation:hsk-card-in .26s ease-out both;overflow:visible}@keyframes hsk-card-in{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}}.hsk-cb-source:hover{transform:translateY(-3px);opacity:.92}.hsk-cb-src-imgwrap{width:188px;height:188px;overflow:hidden;border-radius:var(--hsk-border-radius,0);display:block;background:var(--hsk-chat-source-bg,#f8f9fa)}.hsk-cb-src-imgwrap img{width:100%;height:100%;object-fit:cover;transition:transform .22s;display:block}.hsk-cb-source:hover .hsk-cb-src-imgwrap img{transform:scale(1.05)}.hsk-cb-src-imgwrap-empty{width:188px;height:188px;background:var(--hsk-chat-divide,rgba(0,0,0,.06));display:flex;align-items:center;justify-content:center;color:var(--hsk-chat-muted,#555);font-size:32px}.hsk-cb-src-info{padding:8px 2px 0}.hsk-cb-sources-wrap--compact{margin-top:10px}.hsk-cb-sources-wrap--compact .hsk-cb-sources{gap:10px}.hsk-cb-sources-wrap--compact .hsk-cb-source{flex:0 0 96px}.hsk-cb-sources-wrap--compact .hsk-cb-src-imgwrap,.hsk-cb-sources-wrap--compact .hsk-cb-src-imgwrap-empty{width:96px;height:96px}.hsk-cb-sources-wrap--compact .hsk-cb-src-imgwrap-empty{font-size:20px}.hsk-cb-sources-wrap--compact .hsk-cb-src-name{font-size:12px;-webkit-line-clamp:1}.hsk-cb-sources-wrap--compact .hsk-cb-src-price{font-size:11px;padding:1px 6px}.hsk-cb-sources-wrap--compact .hsk-cb-source-ref-badge{display:none}.hsk-cb-src-name{font-size:13px;font-weight:600;color:var(--hsk-chat-text,#333);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.hsk-cb-src-price{display:inline-flex;align-items:center;width:fit-content;max-width:100%;padding:2px 9px;border-radius:9999px;background:var(--hsk-chat-source-bg,rgba(0,0,0,.05));border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.08));font-size:12px;font-weight:600;color:var(--hsk-primary,#ff6a33);margin-top:5px;line-height:1.2}.hsk-cb-typing-row{display:flex;align-items:flex-start;gap:14px;padding:20px 0}@keyframes hsk-shimmer{0%{background-position:130% 0}100%{background-position:-110% 0}}.hsk-cb-input-wrap{position:relative;--hsk-composer-pad-top:16px;--hsk-composer-pad-x:var(--hsk-gutter,24px);padding:var(--hsk-composer-pad-top) var(--hsk-composer-pad-x) 24px;flex-shrink:0;background:transparent !important;z-index:10}.hsk-cb-input-wrap::after{display:none !important}.hsk-cb-input-card{border-radius:20px;background:var(--hsk-chat-input-bg,#ffffff);border:none !important;outline:none !important;box-shadow:0 3px 14px -1px rgba(0,0,0,.05),0 1px 4px rgba(0,0,0,.03) !important;overflow:hidden;position:relative;z-index:1;transition:height .22s cubic-bezier(.32,.72,0,1)}.hsk-cb-input-card:focus-within{border:none !important;outline:none !important;box-shadow:0 4px 18px -1px rgba(0,0,0,.07),0 2px 6px rgba(0,0,0,.04) !important}.hsk-cb-docked-header{display:flex;align-items:center;gap:8px;padding:10px 16px 6px;background:transparent;border-bottom:none !important;user-select:none}.hsk-cb-docked-icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--hsk-primary,#ff6a33)}.hsk-cb-docked-title{font-size:13px;font-weight:700;color:var(--hsk-primary,#ff6a33);letter-spacing:-0.01em}.hsk-cb-docked-sub{font-size:12px;font-weight:500;letter-spacing:-0.01em;color:var(--hsk-chat-text,#1f1f1f);flex:1}.hsk-cb-docked-close{background:none;border:none;color:var(--hsk-chat-muted,rgba(0,0,0,.4));font-size:16px;line-height:1;cursor:pointer;padding:2px 6px;border-radius:50%;transition:background .12s,color .12s}.hsk-cb-docked-close:hover{background:rgba(0,0,0,.08);color:var(--hsk-chat-text,#111111)}.hsk-cb-field{margin-inline:5px}.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-field{margin-inline:0}.hsk-cb-docked-options{display:flex;flex-direction:column;padding:4px 6px;background:transparent;border-bottom:none !important;max-height:220px;overflow-y:auto;scrollbar-width:thin}.hsk-cb-docked-option{display:flex;align-items:center;gap:10px;width:100%;padding:8px 12px;border:none;background:transparent !important;border-radius:10px;color:var(--hsk-chat-text,#1f1f1f);font-family:inherit;font-size:14px;text-align:start;cursor:pointer;transition:color .15s ease}.hsk-cb-docked-option:hover,.hsk-cb-docked-option:focus{background:transparent !important;color:var(--hsk-primary,#ff6a33)}.hsk-cb-docked-option-icon{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:8px;background:color-mix(in srgb,var(--hsk-primary,#ff6a33) 12%,transparent);color:var(--hsk-primary,#ff6a33);flex-shrink:0;overflow:hidden;transition:transform .2s cubic-bezier(.34,1.56,.64,1),background .18s ease}.hsk-cb-docked-option:hover .hsk-cb-docked-option-icon,.hsk-cb-docked-option:focus .hsk-cb-docked-option-icon{background:color-mix(in srgb,var(--hsk-primary,#ff6a33) 22%,transparent);transform:scale(1.15) rotate(4deg)}.hsk-cb-docked-option-icon img{width:100%;height:100%;object-fit:cover}.hsk-cb-docked-option-title{font-weight:500;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .15s ease}.hsk-cb-docked-option-desc{font-size:12px;color:var(--hsk-chat-muted,#6b7280);font-weight:400}.hsk-cb-docked-option-price{font-size:12px;font-weight:600;color:var(--hsk-chat-muted,#6b7280)}.hsk-cb-input-box{position:relative;display:grid;grid-template-columns:auto auto 1fr auto auto;grid-template-rows:auto 0;align-items:center;justify-items:start;column-gap:10px;row-gap:0;transition:grid-template-rows .2s cubic-bezier(.32,.72,0,1),row-gap .2s cubic-bezier(.32,.72,0,1);background:transparent !important;border:none !important;outline:none !important;border-radius:0 !important;padding-block:12px;padding-inline:18px 14px;box-shadow:none !important}.hsk-cb-tools-toggle{display:none}.hsk-cb-toolsheet-wrap{position:absolute;bottom:calc(100% - 6px);inset-inline-start:var(--hsk-composer-pad-x,14px);inset-inline-end:auto;z-index:100;transform-origin:bottom left;animation:hsk-toolsheet-in .22s cubic-bezier(.16,1,.3,1) both;pointer-events:auto}[dir=\\\"rtl\\\"] .hsk-cb-toolsheet-wrap,.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-toolsheet-wrap{transform-origin:bottom right}.hsk-cb-toolsheet{position:relative;z-index:1;min-width:200px;padding:6px;border-radius:16px;background:var(--hsk-chat-source-bg,rgba(255,255,255,.08));border:none !important;box-shadow:none !important}@keyframes hsk-toolsheet-in{0%{opacity:0;transform:translateY(8px) scale(.92)}100%{opacity:1;transform:translateY(0) scale(1)}}.hsk-cb-toolsheet-scrim{position:fixed;inset:0;z-index:90;background:transparent;cursor:default}.hsk-cb-toolsheet-item{display:flex;align-items:center;gap:11px;width:100%;padding:10px 12px;border:none;border-radius:11px;background:transparent;color:var(--hsk-chat-text,#111827);font-family:var(--hsk-font);font-size:15px;text-align:start;cursor:pointer;transition:background-color .15s ease}.hsk-cb-toolsheet-item:hover:not(:disabled){background:var(--hsk-chat-subtle,rgba(0,0,0,.05))}.hsk-cb-toolsheet-item:disabled{opacity:.45;cursor:default}.hsk-cb-toolsheet-item>svg{flex-shrink:0;color:var(--hsk-chat-muted,#6b7280)}[data-hsk-theme] .hsk-cb-toolsheet{background:var(--hsk-sheet-bg,var(--hsk-chat-input-bg,#f3f4f6)) !important;border:none !important}[data-hsk-theme] .hsk-cb-toolsheet-item{color:var(--hsk-chat-text,#111827) !important}[data-hsk-theme] .hsk-cb-toolsheet-item:hover:not(:disabled){background:var(--hsk-sheet-hover,var(--hsk-surface-2,rgba(0,0,0,.05))) !important}[data-hsk-theme] .hsk-cb-toolsheet-item>svg{color:var(--hsk-chat-muted,#6b7280) !important}@media (prefers-reduced-motion:reduce){.hsk-cb-toolsheet-wrap,.hsk-cb-toolsheet-stem{animation:none}.hsk-cb-toolsheet-stem{transform:scale(.62)}}.hsk-cb-input-box>.hsk-cb-attach-btn{grid-column:1;grid-row:1}.hsk-cb-input-box>.hsk-cb-voice-mode-btn{grid-column:2;grid-row:1}.hsk-cb-input-box>.hsk-cb-field{grid-column:3;grid-row:1}.hsk-cb-input-box>.hsk-cb-mic-btn{grid-column:4;grid-row:1}.hsk-cb-input-box>.hsk-cb-send,.hsk-cb-input-box>.hsk-chat-send{grid-column:5;grid-row:1}.hsk-cb-input-box[data-expanded=\\\"true\\\"]{grid-template-rows:auto 36px;row-gap:6px}.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-field{grid-column:1 / -1;grid-row:1}.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-attach-btn,.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-voice-mode-btn,.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-mic-btn,.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-send,.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-chat-send{grid-row:2}.hsk-cb-textarea{width:100%;background:transparent;border:none;outline:none;resize:none;font-size:var(--hsk-input-font-size,16px);font-family:var(--hsk-font);color:var(--hsk-chat-text,#111);min-height:28px;max-height:140px;field-sizing:content;line-height:var(--hsk-input-line-height,1.55);word-break:break-word;overflow-wrap:break-word;padding:0;transition:height .18s cubic-bezier(.32,.72,0,1),color .42s cubic-bezier(.16,1,.3,1);scrollbar-width:none}.hsk-cb-textarea::-webkit-scrollbar{width:0;height:0}.hsk-cb-textarea::placeholder{color:var(--hsk-chat-muted,#9ca3af);font-family:var(--hsk-font);font-size:16px}.hsk-cb-attach-btn,.hsk-cb-mic-btn,.hsk-cb-send,.hsk-chat-send{width:36px;height:36px;border-radius:12px;display:flex;align-items:center;justify-content:center;flex-shrink:0;border:none;cursor:pointer;transition:transform .2s cubic-bezier(.34,1.56,.64,1),box-shadow .2s cubic-bezier(.34,1.56,.64,1),background-color .42s cubic-bezier(.16,1,.3,1),opacity .2s ease;font-family:inherit;margin:0;padding:0}.hsk-cb-send,.hsk-chat-send{background:linear-gradient(135deg,#007aff 0,#0056b3 100%);color:#ffffff;border-radius:12px !important;box-shadow:0 4px 14px rgba(0,122,255,.38),inset 0 1px 0 rgba(255,255,255,.35);position:relative;overflow:hidden}.hsk-cb-send .hsk-telegram-icon,.hsk-chat-send .hsk-telegram-icon{transition:transform .25s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-send:hover:not(:disabled),.hsk-chat-send:hover:not(:disabled){opacity:1;transform:translateY(-1px) scale(1.05);box-shadow:0 6px 18px rgba(0,122,255,.48),inset 0 1px 0 rgba(255,255,255,.45)}.hsk-cb-send:hover:not(:disabled) .hsk-telegram-icon,.hsk-chat-send:hover:not(:disabled) .hsk-telegram-icon{transform:translate(2px,-2px) rotate(-10deg) scale(1.1)}.hsk-cb-send:active:not(:disabled),.hsk-chat-send:active:not(:disabled){transform:translateY(0) scale(.94);box-shadow:0 1px 4px rgba(0,122,255,.3)}.hsk-cb-send:disabled,.hsk-chat-send:disabled{opacity:.4;cursor:not-allowed;background:var(--hsk-chat-muted,#ccc);box-shadow:none}.hsk-cb-send--stop{background:#e5342a !important}.hsk-cb-send--stop:hover{background:#c92a21 !important;opacity:1}.hsk-cb-hint{text-align:center;font-size:9px;line-height:14px;color:var(--hsk-chat-muted,#bbb);margin-top:10px}.hsk-cb-field{position:relative;grid-area:field;display:flex;align-items:center;width:100%;min-width:0;--hsk-input-font-size:16px;--hsk-input-line-height:1.55;--hsk-input-control:36px;--hsk-input-line-box:calc(var(--hsk-input-font-size) * var(--hsk-input-line-height))}.hsk-cb-listening{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between;pointer-events:none}.hsk-cb-listening span{width:2px;height:2px;border-radius:999px;background:var(--hsk-primary,#ff6a33);opacity:.3;transform-origin:center;will-change:transform,opacity;transition:transform 90ms linear,opacity 90ms linear}.hsk-animated-placeholder{position:absolute;inset:0;display:flex;align-items:center;height:100%;pointer-events:none;overflow:hidden;user-select:none;padding:0;z-index:1}.hsk-cb-input-box>*{--hsk-cascade-ease:cubic-bezier(.45,0,.55,1);--hsk-cascade-dur:.44s;--hsk-cascade-step:55ms}.hsk-cb-input-box[data-cascade]>*:not([type=\\\"file\\\"]):not(.hsk-cb-field){animation-duration:var(--hsk-cascade-dur);animation-timing-function:var(--hsk-cascade-ease);animation-fill-mode:none}.hsk-cb-input-box[data-cascade=\\\"a\\\"]>*:not([type=\\\"file\\\"]):not(.hsk-cb-field){animation-name:hsk-leaf-settle-a}.hsk-cb-input-box[data-cascade=\\\"b\\\"]>*:not([type=\\\"file\\\"]):not(.hsk-cb-field){animation-name:hsk-leaf-settle-b}.hsk-cb-input-box[data-cascade]>*:not([type=\\\"file\\\"]):not(.hsk-cb-field),.hsk-animated-placeholder__char{will-change:transform}.hsk-cb-input-box:hover>*,.hsk-cb-input-box:focus-within>*{will-change:auto}.hsk-cb-input-box>*{--hsk-cascade-field:110ms}.hsk-cb-input-box[data-cascade]>.hsk-cb-attach-btn{animation-delay:0ms}.hsk-cb-input-box[data-cascade]>.hsk-cb-voice-mode-btn{animation-delay:var(--hsk-cascade-step)}.hsk-cb-input-box[data-cascade]>.hsk-cb-mic-btn{animation-delay:calc(var(--hsk-cascade-field)+var(--hsk-text-sweep,0ms))}.hsk-cb-input-box[data-cascade]>.hsk-cb-send,.hsk-cb-input-box[data-cascade]>.hsk-chat-send{animation-delay:calc(var(--hsk-cascade-field)+var(--hsk-text-sweep,0ms)+var(--hsk-cascade-step))}@keyframes hsk-leaf-settle-a{0%{transform:translateY(0) scale(1)}42%{transform:translateY(-3px) scale(1.05)}100%{transform:translateY(0) scale(1)}}@keyframes hsk-leaf-settle-b{0%{transform:translateY(0) scale(1)}42%{transform:translateY(-3px) scale(1.05)}100%{transform:translateY(0) scale(1)}}.hsk-cb-input-box>.hsk-cb-field .hsk-animated-placeholder__char{animation-name:hsk-placeholder-animate-up}@media (prefers-reduced-motion:reduce){.hsk-cb-input-box[data-cascade=\\\"a\\\"]>*,.hsk-cb-input-box[data-cascade=\\\"b\\\"]>*{animation:none;transform:none;opacity:1}.hsk-cb-textarea,.hsk-cb-input-card{transition-property:background-color,box-shadow}}.hsk-animated-placeholder__char{display:inline-block;font-size:var(--hsk-input-font-size,16px);line-height:var(--hsk-input-line-height,1.55);color:var(--hsk-chat-muted,#9ca3af);font-family:var(--hsk-font);white-space:pre;animation:hsk-placeholder-animate-up .46s cubic-bezier(.16,1,.3,1) both}@keyframes hsk-placeholder-animate-up{0%{opacity:0;transform:translateY(9px);color:hsl(var(--hsk-ph-hue,0) var(--hsk-ph-sat,68%) var(--hsk-ph-light,55%))}55%{opacity:1;color:hsl(var(--hsk-ph-hue,0) var(--hsk-ph-sat,68%) var(--hsk-ph-light,55%))}100%{opacity:1;transform:translateY(0);color:var(--hsk-chat-muted,#9ca3af)}}@media (prefers-reduced-motion:reduce){.hsk-animated-placeholder__char{animation:none;transform:none;opacity:1;color:var(--hsk-chat-muted,#9ca3af);animation-delay:0ms !important}}.hsk-cb-voice-error{display:flex;align-items:center;justify-content:center;gap:8px;font-size:12px;line-height:1.4;max-width:90%;margin-inline:auto;text-wrap:balance;color:#ff6b6b;margin-top:8px;padding:4px 12px;border-radius:12px;background:rgba(229,72,77,.12);border:none;cursor:pointer;animation:hsk-msg-in .2s ease-out both}.hsk-cb-voice-error-dismiss{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;border:none;background:rgba(255,255,255,.12);color:inherit;font-size:14px;line-height:1;cursor:pointer;padding:0;flex-shrink:0;transition:background .15s ease,transform .15s ease}.hsk-cb-voice-error-dismiss:hover{background:rgba(255,255,255,.25);transform:scale(1.1)}.hsk-cb-img-strip{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:10px 18px 2px 18px;background:transparent;border:none;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;animation:hsk-msg-in .2s ease-out both}.hsk-cb-img-thumb-wrap{position:relative;width:60px;height:60px;flex-shrink:0;border-radius:12px;box-shadow:0 2px 8px rgba(0,0,0,.08),0 0 0 1px rgba(255,255,255,.12);transition:transform .2s cubic-bezier(.16,1,.3,1),box-shadow .2s cubic-bezier(.16,1,.3,1);overflow:visible}.hsk-cb-img-thumb-wrap:hover{transform:translateY(-2px);box-shadow:0 6px 14px rgba(0,0,0,.12),0 0 0 1px rgba(255,255,255,.2)}.hsk-cb-img-thumb{width:100%;height:100%;object-fit:cover;border-radius:12px;border:none;display:block}.hsk-cb-img-thumb-remove{position:absolute;top:-5px;inset-inline-end:-5px;width:18px;height:18px;border-radius:50%;background:rgba(20,20,24,.75);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);color:#ffffff;border:1px solid rgba(255,255,255,.25);box-shadow:0 2px 6px rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;transition:transform .15s cubic-bezier(.16,1,.3,1),background-color .15s ease;z-index:2}.hsk-cb-img-thumb-remove:hover{background:rgba(239,68,68,.92);border-color:rgba(255,255,255,.4);transform:scale(1.15)}.hsk-cb-attach-btn,.hsk-cb-mic-btn,.hsk-cb-voice-mode-btn{position:relative;width:36px;height:36px;border-radius:12px;border:none !important;outline:none !important;background:transparent;color:var(--hsk-chat-muted,#71717a);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:none !important;opacity:.75;transition:transform .35s cubic-bezier(.34,1.8,.64,1),background-color .2s ease,color .2s ease,opacity .2s ease;font-family:inherit;overflow:visible}.hsk-cb-attach-btn:hover:not(:disabled),.hsk-cb-mic-btn:hover:not(:disabled),.hsk-cb-voice-mode-btn:hover:not(:disabled){opacity:1;color:var(--hsk-chat-text,#1f1f1f);background:transparent;transform:translateY(-1px)}.hsk-cb-attach-btn:active:not(:disabled),.hsk-cb-mic-btn:active:not(:disabled),.hsk-cb-voice-mode-btn:active:not(:disabled){transform:translateY(0) scale(.94);transition-duration:.1s}.hsk-cb-attach-btn svg,.hsk-cb-mic-btn svg,.hsk-cb-voice-mode-btn svg{overflow:visible}.hsk-cb-attach-btn svg{transition:transform .34s cubic-bezier(.22,1,.36,1)}.hsk-cb-attach-btn:hover:not(:disabled) svg{transform:rotate(-14deg) translateY(-1px)}.hsk-mic-cap{transform-box:fill-box;transform-origin:center;transition:transform .32s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-mic-btn:hover:not(:disabled) .hsk-mic-cap{transform:translateY(-1.5px)}.hsk-wave-bar{transform-box:fill-box;transform-origin:center;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-voice-mode-btn:hover:not(:disabled) .hsk-wave-bar{animation:hsk-wave-wake .52s cubic-bezier(.34,1.8,.64,1) both,hsk-wave-live var(--hsk-period,1.1s) ease-in-out .52s infinite;animation-delay:calc(var(--hsk-bar,0) * 55ms),calc(.52s+var(--hsk-bar,0) * 55ms)}.hsk-cb-voice-mode-btn:hover:not(:disabled) .hsk-wave-bar--tip{animation-name:hsk-wave-wake-tip,hsk-wave-live-tip}@keyframes hsk-wave-wake{0%{transform:scaleY(.12)}55%{transform:scaleY(calc(var(--hsk-amp,1.6) * 1.12))}100%{transform:scaleY(1)}}@keyframes hsk-wave-live{0%,100%{transform:scaleY(1)}30%{transform:scaleY(var(--hsk-amp,1.6))}55%{transform:scaleY(calc(1+(var(--hsk-amp,1.6) - 1) * .22))}78%{transform:scaleY(calc(1+(var(--hsk-amp,1.6) - 1) * .62))}}@keyframes hsk-wave-wake-tip{0%{transform:scaleX(.2);opacity:.4}55%{transform:scaleX(calc(var(--hsk-amp,1.9) * 1.1));opacity:1}100%{transform:scaleX(1);opacity:.8}}@keyframes hsk-wave-live-tip{0%,100%{transform:scaleX(1);opacity:.7}30%{transform:scaleX(var(--hsk-amp,1.9));opacity:1}70%{transform:scaleX(1.15);opacity:.8}}.hsk-copy-sheet,.hsk-copy-back{transform-box:fill-box;transform-origin:center;transition:transform .3s cubic-bezier(.22,1,.36,1)}.hsk-cb-kiku-id-pill:hover .hsk-copy-sheet{transform:translate(.9px,.9px)}.hsk-cb-kiku-id-pill:hover .hsk-copy-back{transform:translate(-0.9px,-0.9px)}@media (prefers-reduced-motion:reduce){.hsk-cb-attach-btn:hover:not(:disabled) svg,.hsk-cb-mic-btn:hover:not(:disabled) .hsk-mic-cap,.hsk-cb-kiku-id-pill:hover .hsk-copy-sheet,.hsk-cb-kiku-id-pill:hover .hsk-copy-back{transform:none}.hsk-cb-voice-mode-btn:hover:not(:disabled) .hsk-wave-bar{animation:none}}.hsk-cb-attach-btn:disabled,.hsk-cb-mic-btn:disabled,.hsk-cb-voice-mode-btn:disabled{opacity:.3;cursor:not-allowed;transform:none}.hsk-cb-mic-btn--listening{color:#ef4444 !important;background:rgba(239,68,68,.16) !important;transform:scale(1.1) !important}.hsk-cb-mic-btn--processing{color:var(--hsk-primary,#ff6a33) !important;opacity:.85}.hsk-cb-user-imgs{display:grid;gap:2px;width:fit-content;max-width:min(78%,320px);margin-bottom:4px;margin-left:auto;border-radius:18px 18px 4px 18px;overflow:hidden;box-shadow:0 4px 16px rgba(0,0,0,.16)}.hsk-cb-user-imgs[data-count=\\\"1\\\"]{grid-template-columns:1fr}.hsk-cb-user-imgs[data-count=\\\"2\\\"]{grid-template-columns:1fr 1fr}.hsk-cb-user-imgs[data-count=\\\"3\\\"]{grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr}.hsk-cb-user-imgs[data-count=\\\"3\\\"]>:first-child{grid-row:span 2}.hsk-cb-user-imgs[data-count=\\\"4\\\"]{grid-template-columns:1fr 1fr}.hsk-cb-user-img-cell{position:relative;display:block;padding:0;border:none;background:none;cursor:pointer;overflow:hidden;min-width:0;line-height:0}.hsk-cb-user-imgs[data-count=\\\"1\\\"] .hsk-cb-user-img-cell{aspect-ratio:auto}.hsk-cb-user-imgs:not([data-count=\\\"1\\\"]) .hsk-cb-user-img-cell{aspect-ratio:1}.hsk-cb-user-img-more{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.45);color:#fff;font-size:20px;font-weight:600;line-height:1}.hsk-cb-user-img-thumb{width:100%;height:100%;object-fit:cover;display:block;cursor:pointer}.hsk-cb-user-imgs[data-count=\\\"1\\\"] .hsk-cb-user-img-thumb{height:auto;max-height:300px;object-fit:contain}.hsk-cb-user-img-cell:hover .hsk-cb-user-img-thumb{filter:brightness(.93)}.hsk-cb-error{display:block;width:fit-content;max-width:min(560px,100%);margin:10px auto 8px;padding:10px 14px;border-radius:10px;background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.2);color:#ef4444;font-size:13px;line-height:1.5;font-family:var(--hsk-font);text-align:center}.hsk-kiku-badge{display:inline-block;font-size:var(--hsk-font-size,16px);font-family:var(--hsk-font);font-weight:600;background:rgba(255,255,255,.22);border:1px solid rgba(255,255,255,.35);color:#ffffff;padding:1px 7px;border-radius:6px;margin-inline-end:6px}.hsk-cb-memory-pill{display:inline-flex;align-items:center;gap:10px;align-self:flex-start;margin:12px 0 6px 0;padding:12px 22px;font-size:15px;font-weight:600;text-decoration:none;color:#ffffff;background:linear-gradient(135deg,#007aff 0,#0056b3 100%);border:none;border-radius:18px 18px 18px 4px !important;box-shadow:0 4px 16px -2px rgba(0,122,255,.38),inset 0 1px 0 rgba(255,255,255,.28);transition:transform .18s cubic-bezier(.34,1.56,.64,1),opacity .15s,box-shadow .18s ease;cursor:pointer}.hsk-cb-memory-pill:hover{opacity:.96;transform:translateY(-1px) scale(1.02);box-shadow:0 6px 20px rgba(0,122,255,.48)}.hsk-cb-think{position:relative;z-index:2;margin-bottom:-11px;margin-inline-start:12px;font-size:14px;font-family:var(--hsk-font)}.hsk-cb-think-head{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 11px;border:none;border-radius:999px;background:var(--hsk-chat-ai-bg,#eeeef0);box-shadow:0 0 0 3px var(--hsk-chat-bg,#ffffff),0 1px 3px rgba(0,0,0,.13);font-family:var(--hsk-font);font-size:12px;font-weight:600;color:var(--hsk-chat-muted,#6b7280);cursor:pointer;user-select:none;line-height:28px}.hsk-cb-think-head:hover{color:var(--hsk-chat-text,#111827)}.hsk-cb-think-head--static{cursor:default}.hsk-cb-think-head--static:hover{color:var(--hsk-chat-muted,#6b7280)}.hsk-cb-think-spin{animation:hsk-think-spin 3s linear infinite}@keyframes hsk-think-spin{to{transform:rotate(360deg)}}.hsk-cb-think-chevron{font-size:9px;transition:transform .12s}.hsk-cb-think-chevron--open{transform:rotate(90deg)}.hsk-cb-think-body{margin-top:6px;padding:8px 12px;border-left:2px solid var(--hsk-chat-border,rgba(128,128,128,.25));color:var(--hsk-chat-muted,#4b5563);white-space:pre-wrap;line-height:1.5;font-family:var(--hsk-font);font-size:14px}.hsk-cb-stopped{display:flex;flex-direction:column;align-items:start;gap:8px;margin:10px 0 14px}.hsk-cb-stopped--empty{align-items:center;text-align:center;margin:22px auto 18px}.hsk-cb-stopped--empty .hsk-cb-stopped-label{text-align:center}.hsk-cb-stopped-dots{display:flex;gap:5px;margin-bottom:2px}.hsk-cb-stopped-dots i{width:5px;height:5px;border-radius:50%;background:var(--hsk-chat-muted,#888);opacity:.4}.hsk-cb-stopped-label{font-size:13px;line-height:1.5;color:var(--hsk-chat-muted,#888);font-family:var(--hsk-font);text-align:start}.hsk-cb-continue{display:inline-flex;align-items:center;gap:7px;padding:7px 14px;font-size:13px;font-weight:500;font-family:var(--hsk-font);color:var(--hsk-chat-text,#111);background:var(--hsk-chat-source-bg,rgba(0,0,0,.04));border:1px solid transparent;border-radius:999px;cursor:pointer;transition:border-color .15s,color .15s,background .15s}.hsk-cb-continue:hover{border-color:var(--hsk-primary);color:var(--hsk-primary);background:transparent}.hsk-cb-continue svg{flex:none}[dir=\\\"rtl\\\"] .hsk-cb-continue svg{transform:scaleX(-1)}@media (prefers-color-scheme:dark){.hsk-cb-continue{background:rgba(255,255,255,.06);color:#f0efed}.hsk-cb-continue:hover{background:transparent}}.hsk-sb-wrap{--hsk-bg:#ffffff;--hsk-border:#f1f3f4;--hsk-text:#1f1f1f;--hsk-muted:#5f6368;--hsk-hover:#f8f9fa;--hsk-drop-shadow:0 8px 30px rgba(0,0,0,.06);--hsk-primary:var(--chat-primary-color,#ff6a33);position:relative;width:100%;font-family:inherit}@media (prefers-color-scheme:dark){.hsk-sb-wrap{--hsk-bg:#0a0a0a;--hsk-border:#202124;--hsk-text:#e8eaed;--hsk-muted:#888;--hsk-hover:#1a1a1b;--hsk-drop-shadow:0 12px 40px rgba(0,0,0,.4)}}.hsk-sb-input{width:100%;padding:10px 16px 10px 40px;font-size:14px;border-radius:var(--hsk-border-radius,0);border:1.5px solid var(--hsk-border);outline:none;box-sizing:border-box;background:var(--hsk-bg);color:var(--hsk-text);transition:border-color .15s,box-shadow .15s;font-family:inherit}.hsk-sb-input::placeholder{color:var(--hsk-muted)}.hsk-sb-input:focus{border-color:var(--hsk-primary);box-shadow:0 0 0 3px rgba(255,106,51,.12)}.hsk-sb-icon{position:absolute;inset-inline-start:14px;top:50%;transform:translateY(-50%);color:var(--hsk-muted);pointer-events:none;display:flex;align-items:center}.hsk-sb-drop{position:absolute;top:calc(100%+6px);left:0;right:0;background:var(--hsk-bg);border:1px solid var(--hsk-border);border-radius:var(--hsk-border-radius,0);box-shadow:var(--hsk-drop-shadow);z-index:9999;overflow:hidden;padding:6px 0}.hsk-sb-row{display:flex;align-items:center;gap:12px;padding:9px 16px;cursor:pointer;transition:background .1s}.hsk-sb-row:hover{background:var(--hsk-hover)}.hsk-sb-row-icon{color:var(--hsk-muted);flex-shrink:0;display:flex;align-items:center}.hsk-sb-row-thumb{width:38px;height:38px;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:var(--hsk-muted);background:var(--hsk-hover);border-radius:var(--hsk-border-radius,0);overflow:hidden}.hsk-sb-row-thumb img{width:100%;height:100%;object-fit:cover;display:block}.hsk-sb-row-body{flex:1;min-width:0}.hsk-sb-row-title{font-size:13px;font-weight:500;color:var(--hsk-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}.hsk-sb-row-sub{font-size:11px;color:var(--hsk-muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-sb-empty{padding:14px 16px;font-size:13px;color:var(--hsk-muted)}.hsk-sb-loading-bar{height:2px;background:linear-gradient(90deg,transparent,var(--hsk-primary),transparent);background-size:200% 100%;animation:hsk-sweep .9s linear infinite;position:absolute;top:0;left:0;right:0}@keyframes hsk-sweep{0%{background-position:200% 0}100%{background-position:-200% 0}}.hsk-sb-fade{animation:hsk-fin .1s ease-out both}@keyframes hsk-fin{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}.hsk-sb-skeleton-row{display:flex;align-items:center;gap:12px;padding:9px 16px}.hsk-sb-skeleton-icon{width:38px;height:38px;background:var(--hsk-hover,rgba(0,0,0,.05));border-radius:var(--hsk-border-radius,0);flex-shrink:0;animation:hsk-pulse 1.5s ease-in-out infinite}.hsk-sb-skeleton-text1{height:12px;background:var(--hsk-hover,rgba(0,0,0,.05));border-radius:3px;width:60%;animation:hsk-pulse 1.5s ease-in-out infinite}.hsk-sb-skeleton-text2{height:8px;background:var(--hsk-hover,rgba(0,0,0,.05));border-radius:2px;width:35%;margin-top:5px;animation:hsk-pulse 1.5s ease-in-out infinite}@keyframes hsk-pulse{0%,100%{opacity:.6}50%{opacity:1}}.hsk-sp-btn{--hsk-primary:var(--chat-primary-color,#ff6a33);display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--hsk-border-radius,0);border:1px solid var(--hsk-sp-border,rgba(255,106,51,.35));background:var(--hsk-sp-bg,rgba(255,106,51,.08));color:var(--hsk-primary);cursor:pointer;font-size:15px;line-height:1;transition:background .15s,border-color .15s,transform .12s;flex-shrink:0;padding:0}.hsk-sp-btn:hover{background:rgba(255,106,51,.18);border-color:rgba(255,106,51,.7);transform:scale(1.1)}.hsk-sp-btn:active{transform:scale(.92)}.hsk-sp-backdrop{position:fixed;inset:0;width:100vw;height:100vh;min-height:100dvh;z-index:2147483647 !important;display:flex;align-items:center;justify-content:center;padding:24px;animation:hsk-bd-in .2s ease-out both;background:var(--hsk-chat-bg,#ffffff) !important;box-sizing:border-box}@keyframes hsk-bd-in{from{opacity:0}to{opacity:1}}.hsk-sp-card{--hsk-primary:var(--chat-primary-color,#ff6a33);width:100%;max-width:600px;border-radius:var(--hsk-border-radius,0);overflow:hidden;animation:hsk-card-in .24s cubic-bezier(.34,1.36,.64,1) both;flex-shrink:0;background:var(--hsk-modal-card-bg,#ffffff);border:1px solid var(--hsk-modal-card-border,#f1f3f4);box-shadow:0 32px 80px rgba(0,0,0,.08),0 2px 8px rgba(0,0,0,.04);display:flex;flex-direction:column}.hsk-sp-card.hsk-sp-fullscreen{max-width:1000px;width:90vw;height:85vh;max-height:800px}@media (max-width:768px){.hsk-sp-backdrop{padding:0}.hsk-sp-card.hsk-sp-fullscreen{width:100vw;height:100vh;height:100dvh;max-height:100vh;max-height:100dvh;border:none;border-radius:0}}@keyframes hsk-card-in{from{opacity:0;transform:scale(.96) translateY(-12px)}to{opacity:1;transform:scale(1) translateY(0)}}.hsk-sp-header{display:flex;align-items:center;gap:10px;padding:18px 20px 14px;border-bottom:1px solid var(--hsk-modal-divide,#f1f3f4);flex-shrink:0}.hsk-sp-header-icon{font-size:18px;color:var(--hsk-primary);flex-shrink:0;display:flex;align-items:center}.hsk-sp-header-body{flex:1;min-width:0}.hsk-sp-header-title{font-size:14px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-sp-header-sub{font-size:11px;color:var(--hsk-modal-muted,#5f6368);margin-top:2px}.hsk-sp-close{width:30px;height:30px;border-radius:var(--hsk-border-radius,0);border:1px solid var(--hsk-modal-divide,#f1f3f4);background:none;color:var(--hsk-modal-muted,#5f6368);cursor:pointer;font-size:18px;display:flex;align-items:center;justify-content:center;transition:all .15s;flex-shrink:0}.hsk-sp-close:hover{border-color:var(--hsk-primary);color:var(--hsk-primary)}.hsk-sp-bar{height:2px;background:linear-gradient(90deg,transparent 0,var(--hsk-primary) 40%,#ffaa80 60%,transparent 100%);background-size:200% 100%;animation:hsk-bar .9s linear infinite;flex-shrink:0}@keyframes hsk-bar{0%{background-position:200% 0}100%{background-position:-200% 0}}.hsk-sp-body{display:flex;flex:1;overflow:hidden}.hsk-sp-details-pane{flex:1;overflow-y:auto;padding:24px;border-right:1px solid var(--hsk-modal-divide,#f1f3f4);display:flex;flex-direction:column;gap:20px}.hsk-sp-chat-pane{flex:1.2;display:flex;flex-direction:column;background:var(--hsk-chat-bg,#ffffff)}.hsk-sp-product-profile{display:flex;gap:20px}@media (max-width:480px){.hsk-sp-product-profile{flex-direction:column}}.hsk-sp-details-imgwrap{width:140px;height:140px;flex-shrink:0;border:1px solid var(--hsk-modal-divide,#f1f3f4);background:#ffffff;display:flex;align-items:center;justify-content:center;padding:8px;border-radius:var(--hsk-border-radius,0)}.hsk-sp-details-imgwrap img{max-width:100%;max-height:100%;object-fit:contain}.hsk-sp-details-meta{flex:1;display:flex;flex-direction:column;gap:6px}.hsk-sp-details-name{font-size:20px;font-weight:700;color:var(--hsk-modal-text,#1f1f1f);margin:0;line-height:1.3}.hsk-sp-details-desc{margin-top:12px}.hsk-sp-details-desc h4{font-size:13px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);margin:0 0 4px 0}.hsk-sp-details-desc p{font-size:13px;line-height:1.5;color:var(--hsk-modal-muted,#5f6368);margin:0}.hsk-sp-similar-section{border-top:1px solid var(--hsk-modal-divide,#f1f3f4);padding-top:20px}.hsk-sp-similar-section h3{font-size:14px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);margin:0 0 12px 0}.hsk-sp-results{padding:10px 0;display:flex;flex-direction:row;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:8px}.hsk-sp-empty{padding:40px;text-align:center;font-size:13px;color:var(--hsk-modal-muted,#999)}.hsk-sp-item{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:var(--hsk-border-radius,0);border:1px solid var(--hsk-modal-item-border,#f1f3f4);background:var(--hsk-modal-item-bg,#f8f9fa);animation:hsk-toast-up .28s cubic-bezier(.22,.68,0,1.2) both;overflow:hidden;flex:0 0 170px;scroll-snap-align:start}@keyframes hsk-toast-up{from{opacity:0;transform:translateY(18px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}.hsk-sp-img-wrap{width:100%;height:120px;border-radius:var(--hsk-border-radius,0);background:#fff;border:1px solid var(--hsk-modal-divide,#f1f3f4);flex-shrink:0;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:6px}.hsk-sp-img-wrap img{max-width:100%;max-height:100%;object-fit:contain}.hsk-sp-img-placeholder{font-size:26px}.hsk-sp-item-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between;gap:6px}.hsk-sp-item-name{font-size:13px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.hsk-sp-item-cat{font-size:11px;font-weight:600;color:var(--hsk-primary);text-transform:uppercase;letter-spacing:.05em}.hsk-sp-item-price-row{display:flex;align-items:baseline;gap:4px;margin-top:2px;flex-wrap:wrap}.hsk-sp-item-price{font-size:15px;font-weight:700;color:var(--hsk-modal-text,#1f1f1f)}.hsk-sp-item-currency{font-size:11px;color:var(--hsk-modal-muted,#5f6368)}.hsk-sp-actions{display:flex;gap:6px;margin-top:auto}.hsk-sp-action{flex:1;padding:6px 8px;border-radius:var(--hsk-border-radius,0);font-size:11px;font-weight:600;cursor:pointer;border:1px solid transparent;transition:all .15s;text-align:center;font-family:inherit}.hsk-sp-action-primary{background:var(--hsk-primary);color:#fff;border-color:var(--hsk-primary)}.hsk-sp-action-primary:hover{opacity:.88}.hsk-sp-action-secondary{background:var(--hsk-action-sec-bg,#f1f3f4);color:var(--hsk-modal-muted,#5f6368);border-color:var(--hsk-modal-divide,#f1f3f4)}.hsk-sp-action-secondary:hover{background:var(--hsk-action-sec-bg-hover,#e8eaed);color:var(--hsk-modal-text,#1f1f1f)}.hsk-sp-footer{padding:12px 20px;border-top:1px solid var(--hsk-modal-divide,#f1f3f4);display:flex;align-items:center;gap:8px;flex-shrink:0}.hsk-sp-badge{font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--hsk-primary);background:rgba(255,106,51,.1);border:1px solid rgba(255,106,51,.25);padding:2px 8px;border-radius:var(--hsk-border-radius,0)}.hsk-sp-esc{font-size:11px;color:var(--hsk-modal-muted,#5f6368);margin-inline-start:auto}@media (max-width:768px){.hsk-cb-overlay{--hsk-font-size:var(--hsk-mobile-font-size,14px) !important;position:fixed !important;inset:0 !important;top:0 !important;left:0 !important;right:0 !important;width:100vw !important;height:100% !important;height:var(--hsk-vvh,100dvh) !important;min-height:0 !important;z-index:2147483647 !important;display:flex !important;flex-direction:column !important;overflow:hidden !important;overscroll-behavior:contain !important;background:var(--hsk-chat-bg,#0a0a0a) !important;box-sizing:border-box !important}.hsk-cb-panel{position:relative !important;height:100% !important;width:100% !important;max-width:100% !important;margin:0 !important;display:flex !important;flex-direction:column !important;overflow:hidden !important;border-radius:0 !important;background:var(--hsk-chat-bg,#0a0a0a) !important;box-sizing:border-box !important}.hsk-cb-main{flex:1 1 auto !important;height:100% !important;min-height:0 !important;display:flex !important;flex-direction:column !important;justify-content:space-between !important;overflow:hidden !important;background:var(--hsk-chat-bg,#0a0a0a) !important;box-sizing:border-box !important}.hsk-cb-topbar{padding:14px 14px 8px !important}.hsk-cb-msgs{flex:1 1 auto !important;min-height:0 !important;overflow-y:auto !important;-webkit-overflow-scrolling:touch !important;padding:10px 14px 0 !important}.hsk-cb-empty{flex:1 1 auto !important;min-height:0 !important;justify-content:center !important;padding:16px 4px !important}.hsk-cb-input-box{grid-template-columns:auto 1fr auto auto}.hsk-cb-input-box>.hsk-cb-attach-btn,.hsk-cb-input-box>.hsk-cb-voice-mode-btn{display:none}.hsk-cb-input-box>.hsk-cb-field{grid-column:2}.hsk-cb-input-box>.hsk-cb-mic-btn{grid-column:3}.hsk-cb-input-box>.hsk-cb-send,.hsk-cb-input-box>.hsk-chat-send{grid-column:4}.hsk-cb-tools-toggle{display:flex;grid-column:1;grid-row:1;width:36px;height:36px;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;border-radius:12px;background:var(--hsk-chat-subtle,rgba(0,0,0,.045));color:var(--hsk-chat-muted,#6b7280);cursor:pointer;transition:transform .26s cubic-bezier(.34,1.56,.64,1),background-color .2s ease}.hsk-cb-tools-toggle--open{transform:rotate(45deg);background:var(--hsk-chat-divide,rgba(0,0,0,.09))}.hsk-cb-toolsheet-wrap,.hsk-cb-toolsheet-scrim{display:block}.hsk-cb-toolsheet-item{display:flex}.hsk-cb-input-box[data-expanded=\\\"true\\\"]>.hsk-cb-tools-toggle{grid-row:2}.hsk-cb-ai-msg--inline{display:block !important;padding-inline-end:34px}.hsk-cb-hello-avatar{display:none !important}.hsk-cb-hello-wrap{align-items:center !important;text-align:center !important;gap:3px !important;max-width:30ch;margin-inline:auto}.hsk-cb-hello{font-size:21px !important;font-weight:600 !important;letter-spacing:-.015em;color:var(--hsk-chat-muted,#8b8b8f) !important;text-align:center !important}.hsk-cb-hello-lead,.hsk-cb-hello-ask{font-size:14px !important;font-weight:400 !important;text-align:center !important;color:color-mix(in srgb,var(--hsk-chat-muted,#8b8b8f) 78%,transparent) !important}.hsk-cb-onboarding-head{justify-content:flex-end !important;margin-bottom:12px !important}.hsk-cb-hello{font-size:clamp(26px,6.8vw,36px) !important;font-weight:600 !important;line-height:1.22 !important;letter-spacing:-0.025em !important}.hsk-cb-hello-lead{font-size:15px !important;line-height:1.45 !important;color:var(--hsk-chat-muted,#71717a) !important;margin-top:4px !important}.hsk-cb-doodles{opacity:.92 !important}.hsk-cb-input-wrap{margin-top:auto !important;flex-shrink:0 !important;--hsk-composer-pad-top:8px;--hsk-composer-pad-x:14px;padding:8px 14px !important;padding-bottom:max(12px,env(safe-area-inset-bottom)) !important;background:var(--hsk-chat-bg,#0a0a0a) !important;position:relative !important;z-index:10 !important}.hsk-cb-attach-btn,.hsk-cb-mic-btn,.hsk-cb-send,.hsk-chat-send{width:32px !important;height:32px !important;border-radius:8px !important}.hsk-cb-attach-btn svg,.hsk-cb-mic-btn svg,.hsk-cb-send svg,.hsk-chat-send svg{width:15px !important;height:15px !important}.hsk-sp-backdrop.hsk-sp-mobile-view{position:fixed !important;top:0 !important;left:0 !important;right:0 !important;bottom:auto !important;width:100vw !important;height:var(--hsk-vvh,100dvh) !important;min-height:0 !important;z-index:2147483647 !important;display:flex !important;flex-direction:column !important;overflow:hidden !important;overscroll-behavior:contain !important;background:var(--hsk-chat-bg,#0a0a0a) !important;padding:0 !important;box-sizing:border-box !important}.hsk-sp-card.hsk-sp-mobile-card{position:relative !important;width:100% !important;height:100% !important;max-width:100% !important;margin:0 !important;display:flex !important;flex-direction:column !important;justify-content:space-between !important;overflow:hidden !important;border-radius:0 !important;background:var(--hsk-chat-bg,#0a0a0a) !important;box-sizing:border-box !important}.hsk-sp-body{flex:1 1 auto !important;min-height:0 !important;display:flex !important;flex-direction:column !important;overflow-y:auto !important;-webkit-overflow-scrolling:touch !important;background:var(--hsk-chat-bg,#0a0a0a) !important}.hsk-cb-input-box{padding:10px 10px 10px 14px}.hsk-cb-user-bubble{max-width:85%}.hsk-sp-footer{padding:8px 12px}}@media (prefers-color-scheme:dark){.hsk-sp-backdrop{background:#000000 !important}.hsk-sp-card{--hsk-modal-card-bg:#0a0a0a;--hsk-modal-card-border:#202124;--hsk-modal-text:#e8eaed;--hsk-modal-muted:#888;--hsk-action-sec-bg:#202124;--hsk-action-sec-bg-hover:#2d2f34}.hsk-sp-details-imgwrap{background:#202124;border-color:#202124}.hsk-sp-img-wrap{background:#202124;border-color:#202124}.hsk-sp-chat-pane{background:var(--hsk-chat-bg,#0a0a0a)}}@media (prefers-color-scheme:light){.hsk-sp-backdrop{background:#ffffff !important}}.hsk-table-wrapper{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:12px 0 8px;width:100%;max-width:100%;min-width:0;border-radius:0;padding:0 0 6px;background:transparent;box-shadow:none;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:var(--hsk-chat-divide,rgba(0,0,0,.2)) transparent;cursor:grab;user-select:auto;transition:mask-image .15s ease,-webkit-mask-image .15s ease}.hsk-table-wrapper.is-dragging{cursor:grabbing;user-select:none}.hsk-table-wrapper::-webkit-scrollbar{height:5px}.hsk-table-wrapper::-webkit-scrollbar-track{background:transparent}.hsk-table-wrapper::-webkit-scrollbar-thumb{background:var(--hsk-chat-divide,rgba(0,0,0,.25));border-radius:4px}.hsk-table-wrapper::-webkit-scrollbar-thumb:hover{background:var(--hsk-chat-muted,rgba(0,0,0,.5))}.hsk-cb-ai-text .hsk-markdown-p{margin:0 0 10px}.hsk-cb-ai-text .hsk-markdown-p:last-child{margin-bottom:0}.hsk-cb-ai-text .hsk-markdown-list{margin:0 0 10px;padding-inline-start:1.2em}.hsk-cb-ai-text .hsk-markdown-list:last-child{margin-bottom:0}.hsk-cb-ai-text .hsk-markdown-ul{list-style:disc outside}.hsk-cb-ai-text .hsk-markdown-ol{list-style:decimal outside}.hsk-cb-ai-text .hsk-markdown-list li{margin:0 0 7px;padding-left:3px;line-height:1.5}.hsk-cb-ai-text .hsk-markdown-list li:last-child{margin-bottom:0}.hsk-cb-ai-text .hsk-markdown-list li::marker{color:var(--hsk-primary,#ff6a33)}.hsk-cb-ai-text .hsk-markdown-h1,.hsk-cb-ai-text .hsk-markdown-h2,.hsk-cb-ai-text .hsk-markdown-h3{margin:14px 0 7px;font-weight:650;line-height:1.3;letter-spacing:-0.01em}.hsk-cb-ai-text .hsk-markdown-h1{font-size:1.09em}.hsk-cb-ai-text .hsk-markdown-h2{font-size:1.03em}.hsk-cb-ai-text .hsk-markdown-h3{font-size:1em}.hsk-cb-ai-text>:first-child{margin-top:0}.hsk-markdown-table{width:max-content;min-width:100%;border-collapse:collapse;border-spacing:0;text-align:start;font-size:13px;background:transparent;margin:0;border:none;font-variant-numeric:tabular-nums}.hsk-markdown-table th{padding:8px 16px 6px 16px;vertical-align:bottom;line-height:1.35;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;white-space:nowrap;color:var(--hsk-chat-muted,rgba(0,0,0,.55));border-bottom:1px solid var(--hsk-chat-divide,rgba(0,0,0,.1));background:transparent !important}.hsk-markdown-table td{padding:8px 16px 8px 16px;vertical-align:middle;line-height:1.45;font-size:13px;white-space:nowrap;color:var(--hsk-chat-text,inherit);border-bottom:.5px solid var(--hsk-chat-divide,rgba(0,0,0,.06));background:transparent !important}.hsk-markdown-table th:first-child,.hsk-markdown-table td:first-child{padding-inline-start:0;font-weight:590;white-space:normal;max-width:280px;min-width:150px;line-height:1.35}.hsk-markdown-table th:last-child,.hsk-markdown-table td:last-child{padding-inline-end:0}.hsk-markdown-table tbody tr:last-child td{border-bottom:none}.hsk-markdown-table td *{color:inherit}.hsk-markdown-table .hsk-markdown-link{display:inline-flex;align-items:center;padding:2px 8px;background-color:var(--hsk-chat-source-bg,rgba(0,0,0,.04));border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.08));color:var(--hsk-primary,#ff6a33);font-size:12px;font-weight:500;border-radius:6px;text-decoration:none !important;margin:2px 0;transition:opacity .15s ease}.hsk-markdown-table .hsk-markdown-link:hover{opacity:.8}@media (prefers-color-scheme:dark){.hsk-markdown-table th{color:var(--hsk-chat-muted,rgba(255,255,255,.5));border-bottom-color:var(--hsk-chat-divide,rgba(255,255,255,.1))}.hsk-markdown-table td{color:var(--hsk-chat-text,#f0efed);border-bottom-color:var(--hsk-chat-divide,rgba(255,255,255,.06))}}.hsk-markdown-link{color:var(--hsk-primary,#ff6a33);text-decoration:underline;text-underline-offset:2px}.hsk-markdown-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace,var(--hsk-font);font-size:.85em;background-color:rgba(128,128,128,.15);padding:.2em .4em;border-radius:var(--hsk-border-radius,0);color:inherit;word-break:break-word}.hsk-markdown-img-block{margin:8px 0;line-height:0}.hsk-markdown-img{display:block;max-width:100%;width:auto;max-height:220px;border-radius:10px;box-shadow:0 2px 12px rgba(0,0,0,.18);object-fit:cover;background:rgba(128,128,128,.08)}.hsk-sp-item-original-price{font-size:12px;text-decoration:line-through;color:var(--hsk-modal-muted,#888);margin-left:6px}.hsk-sp-item-discount{font-size:11px;font-weight:600;color:#10b981;margin-left:6px}.hsk-sp-item-meta-badges{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}.hsk-sp-meta-badge{font-size:11px;font-weight:500;padding:3px 8px;border-radius:var(--hsk-border-radius,0);background:var(--hsk-modal-item-bg,#f8f9fa);border:1px solid var(--hsk-modal-divide,#f1f3f4);color:var(--hsk-modal-muted,#5f6368)}.hsk-sp-meta-badge-rating{color:#f59e0b;background:rgba(245,158,11,.08);border-color:rgba(245,158,11,.2)}.hsk-sp-meta-badge-avail.in-stock{color:#10b981;background:rgba(16,185,129,.08);border-color:rgba(16,185,129,.2)}.hsk-sp-meta-badge-avail.out-stock{color:#ef4444;background:rgba(239,68,68,.08);border-color:rgba(239,68,68,.2)}.hsk-sp-item-brand{font-size:11px;font-weight:700;color:var(--hsk-modal-muted,#888);text-transform:uppercase;letter-spacing:.05em;margin-bottom:-2px}.hsk-chat-widget::-webkit-scrollbar,.hsk-sp-card::-webkit-scrollbar,.hsk-cb-msgs::-webkit-scrollbar,.hsk-sp-details-pane::-webkit-scrollbar,.hsk-sp-results::-webkit-scrollbar,.hsk-chat-messages::-webkit-scrollbar{width:3px;height:3px}.hsk-chat-widget::-webkit-scrollbar-track,.hsk-sp-card::-webkit-scrollbar-track,.hsk-cb-msgs::-webkit-scrollbar-track,.hsk-sp-details-pane::-webkit-scrollbar-track,.hsk-sp-results::-webkit-scrollbar-track,.hsk-chat-messages::-webkit-scrollbar-track{background:transparent}.hsk-chat-widget::-webkit-scrollbar-thumb,.hsk-sp-card::-webkit-scrollbar-thumb,.hsk-cb-msgs::-webkit-scrollbar-thumb,.hsk-sp-details-pane::-webkit-scrollbar-thumb,.hsk-sp-results::-webkit-scrollbar-thumb,.hsk-chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.06);border-radius:99px;transition:background .2s ease}.hsk-chat-widget::-webkit-scrollbar-thumb:hover,.hsk-cb-msgs::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.15)}@media (prefers-color-scheme:dark){.hsk-chat-widget::-webkit-scrollbar-thumb,.hsk-sp-card::-webkit-scrollbar-thumb,.hsk-cb-msgs::-webkit-scrollbar-thumb,.hsk-sp-details-pane::-webkit-scrollbar-thumb,.hsk-sp-results::-webkit-scrollbar-thumb,.hsk-chat-messages::-webkit-scrollbar-thumb{background:rgba(255,255,255,.08)}.hsk-chat-widget::-webkit-scrollbar-thumb:hover,.hsk-cb-msgs::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.2)}}.hsk-sp-details-pane,.hsk-sp-results,.hsk-chat-messages{scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.06) transparent}@media (prefers-color-scheme:dark){.hsk-sp-details-pane,.hsk-sp-results,.hsk-chat-messages{scrollbar-color:rgba(255,255,255,.08) transparent}}.hsk-sp-specs-horizontal{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.hsk-sp-spec-item-horizontal{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--hsk-modal-item-bg,#f8f9fa);border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:var(--hsk-border-radius,0);font-size:11px}.hsk-sp-spec-label-horizontal{font-weight:500;color:var(--hsk-modal-muted,#888)}.hsk-sp-spec-value-horizontal{font-weight:600;color:var(--hsk-modal-text,#1f1f1f)}@media (prefers-color-scheme:dark){.hsk-sp-spec-item-horizontal{background:#1a1a1b;border-color:#202124}}.hsk-cb-phone-form{display:flex;flex-direction:column;gap:8px;margin-top:8px}.hsk-cb-phone-label{font-size:.875rem;color:var(--hsk-chat-text,#111);margin:0}.hsk-cb-phone-input{width:100%;box-sizing:border-box;padding:8px 12px;border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.12));border-radius:var(--hsk-border-radius,0);background:var(--hsk-chat-input-bg,rgba(0,0,0,.04));color:var(--hsk-chat-text,#111);font-size:.9rem;outline:none;transition:border-color .15s}.hsk-cb-phone-input::placeholder{color:var(--hsk-chat-muted,#888)}.hsk-cb-phone-input:focus{border-color:var(--hsk-primary,#ff6a33)}.hsk-cb-phone-submit{align-self:flex-start;padding:8px 16px;border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.12));border-radius:var(--hsk-border-radius,0);background:transparent;color:var(--hsk-chat-text,#111);font-size:.875rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.hsk-cb-phone-submit:hover{border-color:var(--hsk-primary,#ff6a33);color:var(--hsk-primary,#ff6a33)}.hsk-cb-main{flex:1;min-width:0;display:flex;flex-direction:column;height:100%;overflow:hidden}@keyframes hsk-fade-in-up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.hsk-action-pills{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;animation:hsk-fade-in-up .35s ease .1s both}.hsk-action-pill{display:inline-flex;align-items:center;gap:5px;padding:6px 12px;border-radius:20px;border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.12));background:var(--hsk-pill-bg,rgba(255,255,255,.8));color:var(--hsk-chat-text,#1f1f1f);font-size:12px;font-weight:500;cursor:pointer;font-family:inherit;transition:all .15s;white-space:nowrap;backdrop-filter:blur(4px)}.hsk-action-pill:hover:not(:disabled){border-color:var(--hsk-primary,#ff6a33);background:color-mix(in srgb,var(--hsk-primary,#ff6a33) 8%,transparent);color:var(--hsk-primary,#ff6a33);transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.08)}.hsk-action-pill:disabled{opacity:.4;cursor:not-allowed}.hsk-pill-emoji{font-size:13px;line-height:1}@media (prefers-color-scheme:dark){.hsk-action-pill{--hsk-pill-bg:rgba(40,40,42,.85);border-color:rgba(255,255,255,.1);color:var(--hsk-chat-text,#e8eaed)}}[data-hsk-theme=\\\"dark\\\"] .hsk-action-pill{--hsk-pill-bg:rgba(40,40,42,.85);border-color:rgba(255,255,255,.1);color:var(--hsk-chat-text,#e8eaed)}.hsk-sp-tabs-mobile{display:none}@media (max-width:768px){.hsk-sp-tabs-mobile{display:flex;border-bottom:1px solid var(--hsk-modal-divide,#f1f3f4);background:var(--hsk-modal-card-bg,#ffffff);flex-shrink:0}.hsk-sp-tab-btn{flex:1;padding:12px 8px;background:none;border:none;border-bottom:2px solid transparent;font-size:13px;font-weight:600;color:var(--hsk-modal-muted,#5f6368);cursor:pointer;text-align:center;transition:all .15s;font-family:inherit}.hsk-sp-tab-btn.active{color:var(--hsk-primary);border-bottom-color:var(--hsk-primary)}.hsk-sp-pane-hidden-mobile{display:none !important}.hsk-sp-details-pane,.hsk-sp-chat-pane{flex:1 !important;height:100% !important;max-height:none !important}}@media (max-width:768px){.hsk-sp-header-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.hsk-sp-header-specs-btn{flex-shrink:0;padding:4px 10px;font-size:11px;font-weight:600;color:var(--hsk-modal-muted,#5f6368);background:var(--hsk-action-sec-bg,#f1f3f4);border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:20px;cursor:pointer;font-family:inherit;transition:all .2s ease}.hsk-sp-header-specs-btn:hover{background:var(--hsk-action-sec-bg-hover,#e8eaed);color:var(--hsk-primary)}.hsk-sp-mobile-attachment-deck{margin-top:10px;display:flex;flex-direction:column;gap:10px;width:100%}.hsk-sp-mobile-main-card{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--hsk-modal-item-bg,#f8f9fa);border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:8px;width:100%;box-sizing:border-box}.hsk-sp-mobile-main-card-img{width:44px;height:44px;flex-shrink:0;border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:6px;background:#ffffff;display:flex;align-items:center;justify-content:center;padding:3px;overflow:hidden}.hsk-sp-mobile-main-card-img img{max-width:100%;max-height:100%;object-fit:contain}.hsk-sp-mobile-main-card-info{flex:1;min-width:0}.hsk-sp-mobile-main-card-brand{font-size:9px;font-weight:700;color:var(--hsk-modal-muted,#888);text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-sp-mobile-main-card-name{font-size:13px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}.hsk-sp-mobile-main-card-price{font-size:12px;font-weight:700;color:var(--hsk-primary);margin-top:1px}.hsk-sp-mobile-main-card-specs-btn{padding:5px 10px;font-size:11px;font-weight:600;color:var(--hsk-primary);background:transparent;border:1px solid var(--hsk-primary);border-radius:4px;cursor:pointer;font-family:inherit;transition:all .2s ease}.hsk-sp-mobile-main-card-specs-btn:hover{background:var(--hsk-primary);color:#ffffff}.hsk-sp-mobile-similar-carousel-inline{display:flex;flex-direction:column;gap:6px;width:100%}.hsk-sp-mobile-similar-carousel-title{font-size:10px;font-weight:700;color:var(--hsk-modal-muted,#888);text-transform:uppercase;letter-spacing:.05em;padding-left:2px}.hsk-sp-mobile-similar-carousel-list{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:2px}.hsk-sp-mobile-similar-carousel-list::-webkit-scrollbar{display:none}.hsk-sp-mobile-similar-carousel-item{flex:0 0 160px;display:flex;align-items:center;gap:8px;padding:6px 8px;background:var(--hsk-modal-item-bg,#f8f9fa);border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:6px;cursor:pointer;box-sizing:border-box;transition:transform .15s ease,border-color .15s ease}.hsk-sp-mobile-similar-carousel-item:hover{border-color:var(--hsk-primary)}.hsk-sp-mobile-similar-carousel-img{width:32px;height:32px;flex-shrink:0;border-radius:4px;background:#ffffff;border:1px solid var(--hsk-modal-divide,#f1f3f4);display:flex;align-items:center;justify-content:center;padding:2px;overflow:hidden}.hsk-sp-mobile-similar-carousel-img img{max-width:100%;max-height:100%;object-fit:contain}.hsk-sp-mobile-similar-carousel-meta{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center}.hsk-sp-mobile-similar-carousel-name{font-size:11px;font-weight:600;color:var(--hsk-modal-text,#1f1f1f);line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-sp-mobile-similar-carousel-price{font-size:10px;font-weight:700;color:var(--hsk-primary);margin-top:1px}.hsk-sp-mobile-chat-container{flex:1;display:flex;flex-direction:column;overflow:hidden;background:var(--hsk-chat-bg,#ffffff)}.hsk-sp-mobile-specs-overlay{position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,.4);display:flex;align-items:flex-end;animation:hsk-bd-in .2s ease-out}.hsk-sp-mobile-specs-drawer{width:100%;background:var(--hsk-modal-card-bg,#ffffff);border-top-left-radius:12px;border-top-right-radius:12px;max-height:70vh;display:flex;flex-direction:column;animation:hsk-drawer-in .25s cubic-bezier(0,0,.2,1);box-shadow:0 -8px 24px rgba(0,0,0,.15)}@keyframes hsk-drawer-in{from{transform:translateY(100%)}to{transform:translateY(0)}}.hsk-sp-mobile-specs-header{display:flex;justify-content:space-between;align-items:center;padding:14px 16px;border-bottom:1px solid var(--hsk-modal-divide,#f1f3f4)}.hsk-sp-mobile-specs-header h3{margin:0;font-size:14px;font-weight:700;color:var(--hsk-modal-text,#1f1f1f)}.hsk-sp-mobile-specs-header button{background:none;border:none;font-size:12px;font-weight:600;color:var(--hsk-primary);cursor:pointer;font-family:inherit}.hsk-sp-mobile-specs-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:16px}.hsk-sp-mobile-specs-title{font-size:15px;font-weight:700;color:var(--hsk-modal-text,#1f1f1f);margin:0}.hsk-sp-mobile-specs-desc h5,.hsk-sp-mobile-specs-list h5{margin:0 0 6px 0;font-size:11px;font-weight:700;color:var(--hsk-modal-muted,#888);text-transform:uppercase;letter-spacing:.05em}.hsk-sp-mobile-specs-desc p{margin:0;font-size:13px;line-height:1.5;color:var(--hsk-modal-text,#333)}.hsk-sp-mobile-specs-list{display:flex;flex-direction:column;gap:8px}.hsk-sp-mobile-spec-row{display:flex;justify-content:space-between;padding:8px 10px;background:var(--hsk-modal-item-bg,#f8f9fa);border:1px solid var(--hsk-modal-divide,#f1f3f4);border-radius:var(--hsk-border-radius,4px);font-size:12px;gap:12px}.hsk-sp-mobile-spec-label{color:var(--hsk-modal-muted,#5f6368);font-weight:500}.hsk-sp-mobile-spec-value{color:var(--hsk-modal-text,#1f1f1f);font-weight:600;text-align:right}}@media (prefers-color-scheme:dark){.hsk-sp-mobile-main-card{background:#0a0a0a !important}.hsk-sp-mobile-main-card-img{background:#1a1a1b !important}.hsk-sp-mobile-similar-carousel-item{background:#0a0a0a !important}.hsk-sp-mobile-similar-carousel-img{background:#1a1a1b !important}.hsk-sp-mobile-specs-drawer{background:#0a0a0a !important}.hsk-sp-mobile-spec-row{background:#1a1a1b !important}}.kiku-voice-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;border:none;background:transparent;color:var(--hsk-text-muted,#888);cursor:pointer;transition:color .2s,background .2s;flex-shrink:0}.kiku-voice-btn:hover{background:var(--hsk-hover-bg,rgba(0,0,0,.06));color:var(--hsk-primary,#6c47ff)}.kiku-voice-btn--active{color:#ef4444;background:rgba(239,68,68,.1)}.kiku-voice-btn:disabled{opacity:.4;cursor:not-allowed}.kiku-voice-ripple{position:absolute;inset:-4px;border-radius:50%;border:2px solid #ef4444;animation:kiku-voice-pulse 1.2s ease-out infinite;pointer-events:none}@keyframes kiku-voice-pulse{0%{transform:scale(1);opacity:1}100%{transform:scale(1.6);opacity:0}}.kiku-vs-btn{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;border:none;background:transparent;color:var(--hsk-text-muted,#888);cursor:pointer;transition:color .2s,background .2s;flex-shrink:0}.kiku-vs-btn:hover{background:var(--hsk-hover-bg,rgba(0,0,0,.06));color:var(--hsk-primary,#6c47ff)}.kiku-vs-btn--loading{opacity:.6;pointer-events:none}@keyframes kiku-vs-rotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.kiku-vs-spin{animation:kiku-vs-rotate .8s linear infinite}.kiku-style-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.kiku-style-tag{display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:99px;background:var(--hsk-primary-alpha,rgba(108,71,255,.1));color:var(--hsk-primary,#6c47ff);font-size:11px;font-weight:500;white-space:nowrap}.kiku-vs-preview-banner{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--hsk-surface,#f9f9f9);border-radius:10px;margin-bottom:12px;border:1px solid var(--hsk-border,#e5e5e5)}.kiku-vs-preview-img{width:44px;height:44px;object-fit:cover;border-radius:8px;flex-shrink:0}.kiku-vs-preview-info{flex:1;min-width:0}.kiku-vs-preview-label{font-size:11px;color:var(--hsk-text-muted,#888);margin-bottom:2px}.kiku-vs-preview-palette{font-size:13px;font-weight:600;color:var(--hsk-text,#1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kiku-voice-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;border:none;background:transparent;color:var(--hsk-text-muted,#888);cursor:pointer;transition:color .2s,background .2s;flex-shrink:0}.kiku-voice-btn:hover{background:var(--hsk-hover-bg,rgba(0,0,0,.06));color:var(--hsk-primary,#ff6a33)}.kiku-voice-btn--active{color:#ef4444;background:rgba(239,68,68,.1)}.kiku-voice-btn:disabled{opacity:.4;cursor:not-allowed}.kiku-voice-ripple{position:absolute;inset:-4px;border-radius:50%;border:2px solid #ef4444;animation:kiku-voice-pulse 1.2s ease-out infinite;pointer-events:none}@keyframes kiku-voice-pulse{0%{transform:scale(1);opacity:1}100%{transform:scale(1.7);opacity:0}}.kiku-vs-btn{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;border:none;background:transparent;color:var(--hsk-text-muted,#888);cursor:pointer;transition:color .2s,background .2s;flex-shrink:0}.kiku-vs-btn:hover{background:var(--hsk-hover-bg,rgba(0,0,0,.06));color:var(--hsk-primary,#ff6a33)}.kiku-vs-btn--loading{opacity:.6;pointer-events:none}@keyframes kiku-vs-rotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}.kiku-vs-spin{animation:kiku-vs-rotate .8s linear infinite}.kiku-style-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.kiku-style-tag{display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:99px;background:rgba(255,106,51,.1);color:var(--hsk-primary,#ff6a33);font-size:11px;font-weight:500;white-space:nowrap}.kiku-vs-preview-banner{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--hsk-surface,#f9f9f9);border-radius:10px;margin-bottom:12px;border:1px solid var(--hsk-border,#e5e5e5);animation:hsk-msg-in .22s ease-out both}.kiku-vs-preview-img{width:44px;height:44px;object-fit:cover;border-radius:8px;flex-shrink:0}.kiku-vs-preview-info{flex:1;min-width:0}.kiku-vs-preview-label{font-size:11px;color:var(--hsk-text-muted,#888);margin-bottom:2px}.kiku-vs-preview-palette{font-size:13px;font-weight:600;color:var(--hsk-text,#1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hsk-cb-source--referenced{}.hsk-source-card--referenced{}.hsk-cb-source-ref-badge{position:absolute;top:6px;right:6px;background:#fbbf24;color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 4px rgba(0,0,0,.15);z-index:10;animation:hsk-badge-pop .3s cubic-bezier(.34,1.56,.64,1) both}@keyframes hsk-badge-pop{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}.hsk-sources-group-title{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:#888;margin:14px 0 8px 0;display:flex;align-items:center;gap:4px}.hsk-kiku-badge{display:inline-flex;align-items:center;gap:3px;font-size:13px;font-weight:700;letter-spacing:-0.01em;color:#ffffff;background:rgba(255,255,255,.28);border:1px solid rgba(255,255,255,.45);padding:2px 8px;border-radius:8px;margin-inline-end:8px;vertical-align:middle;position:relative;top:-1px;box-shadow:0 1px 3px rgba(0,0,0,.12)}.hsk-markdown-img,.hsk-cb-user-img-thumb,.hsk-cb-source .hsk-cb-src-imgwrap img{cursor:zoom-in}.hsk-lightbox{position:fixed;inset:0;z-index:999999;background:rgba(0,0,0,.85);display:flex;align-items:center;justify-content:center;padding:24px;animation:hsk-lightbox-in .15s ease-out both;cursor:zoom-out}@keyframes hsk-lightbox-in{from{opacity:0}to{opacity:1}}.hsk-lightbox-img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;border-radius:4px;cursor:default}.hsk-lightbox-close{position:absolute;top:16px;right:16px;width:36px;height:36px;border-radius:50%;border:none;background:rgba(255,255,255,.15);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s}.hsk-lightbox-close:hover{background:rgba(255,255,255,.28)}.hsk-cb-viz{margin-top:10px;animation:hsk-msg-in .2s ease-out both}.hsk-cb-viz img,.hsk-cb-viz video{width:100%;max-width:420px;border-radius:8px;display:block}.hsk-cb-viz-disclaimer{max-width:420px;margin-top:4px;font-size:11px;line-height:1.4;color:var(--hsk-chat-muted,#9aa0a6)}.hsk-cb-calc-disclaimer{max-width:440px;margin-top:8px;padding:8px 12px;font-size:11.5px;line-height:1.45;color:var(--hsk-chat-muted,rgba(255,255,255,.65));background:var(--hsk-chat-callout-bg,rgba(255,255,255,.04));border:1px solid var(--hsk-border-subtle,rgba(255,255,255,.08));border-radius:8px}[data-hsk-theme=\\\"light\\\"] .hsk-cb-calc-disclaimer{color:rgba(0,0,0,.6);background:rgba(0,0,0,.03);border-color:rgba(0,0,0,.08)}.hsk-cb-stale{max-width:420px;margin-top:8px;padding:8px 10px;border:1px solid rgba(220,38,38,.35);border-left-width:3px;border-radius:6px;background:rgba(220,38,38,.06)}.hsk-cb-stale-title{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#dc2626}.hsk-cb-stale-item{margin-top:3px;font-size:12px;line-height:1.45;color:var(--hsk-chat-text,#202124)}.hsk-cb-stale-reason{color:var(--hsk-chat-muted,#9aa0a6)}.hsk-cb-viz-imgwrap{position:relative;display:inline-block;max-width:100%}.hsk-cb-viz-mark{position:absolute;right:10px;bottom:10px;display:inline-flex;align-items:center;gap:6px;padding:8px 14px;font-size:13px;font-weight:600;color:#fff;background:rgba(0,0,0,.62);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.35);border-radius:999px;cursor:pointer;transition:background .15s}.hsk-cb-viz-mark:hover{background:var(--hsk-primary,#ff6a33);border-color:transparent}.hsk-markup-overlay{position:fixed;inset:0;z-index:999999;background:rgba(0,0,0,.88);display:flex;align-items:center;justify-content:center;padding:16px;animation:hsk-lightbox-in .15s ease-out both}.hsk-markup{display:flex;flex-direction:column;gap:12px;width:min(720px,100%);max-height:100%;overflow-y:auto}.hsk-markup-head{display:flex;align-items:center;justify-content:space-between}.hsk-markup-title{font-size:14px;font-weight:600;color:#fff}.hsk-markup-cancel{padding:6px 12px;font-size:12px;font-weight:600;color:#fff;background:rgba(255,255,255,.12);border:none;border-radius:var(--hsk-border-radius,0);cursor:pointer}.hsk-markup-cancel:hover{background:rgba(255,255,255,.22)}.hsk-markup-stage{display:flex;justify-content:center}.hsk-markup-canvas-wrap{position:relative;max-width:100%}.hsk-markup-canvas{display:block;max-width:100%;max-height:60vh;border-radius:var(--hsk-border-radius,0);touch-action:none}.hsk-markup-canvas--pen,.hsk-markup-canvas--eraser{cursor:crosshair}.hsk-markup-canvas--text{cursor:text}.hsk-markup-textinput{position:absolute;transform:translateY(-100%);min-width:140px;padding:4px 6px;font-size:14px;font-weight:600;background:rgba(0,0,0,.55);border:1px dashed rgba(255,255,255,.6);border-radius:4px;outline:none}.hsk-markup-loading,.hsk-markup-error{padding:40px 16px;font-size:13px;color:rgba(255,255,255,.75);text-align:center}.hsk-markup-tools{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.hsk-markup-colors{display:flex;gap:8px}.hsk-markup-color{width:22px;height:22px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0}.hsk-markup-color--on{border-color:#fff;transform:scale(1.15)}.hsk-markup-actions{display:flex;gap:6px}.hsk-markup-tool{padding:6px 11px;font-size:12px;font-weight:600;color:#fff;background:rgba(255,255,255,.12);border:none;border-radius:var(--hsk-border-radius,0);cursor:pointer}.hsk-markup-tool:hover:not(:disabled){background:rgba(255,255,255,.22)}.hsk-markup-tool--on{background:var(--hsk-primary,#ff6a33)}.hsk-markup-tool--on:hover:not(:disabled){background:var(--hsk-primary,#ff6a33)}.hsk-markup-tool:disabled{opacity:.4;cursor:default}.hsk-markup-send{display:flex;gap:8px}.hsk-markup-instruction{flex:1;min-width:0;padding:10px 12px;font-size:14px;color:#fff;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.25);border-radius:var(--hsk-border-radius,0);outline:none}.hsk-markup-instruction::placeholder{color:rgba(255,255,255,.5)}.hsk-markup-instruction:focus{border-color:var(--hsk-primary,#ff6a33)}.hsk-markup-go{padding:10px 20px;font-size:13px;font-weight:600;color:#fff;background:var(--hsk-primary,#ff6a33);border:none;border-radius:var(--hsk-border-radius,0);cursor:pointer}.hsk-markup-go:hover:not(:disabled){opacity:.9}.hsk-markup-go:disabled{opacity:.45;cursor:default}.hsk-cb-kimgs{margin-top:10px;display:flex;flex-direction:column;gap:10px;animation:hsk-msg-in .2s ease-out both}.hsk-cb-kimg-grid{display:flex;flex-wrap:wrap;gap:6px}.hsk-cb-kimg{width:132px;height:132px;object-fit:cover;border-radius:8px;cursor:zoom-in;border:1px solid var(--hsk-chat-border,rgba(0,0,0,.08))}.hsk-cb-kimg:only-child{width:100%;max-width:320px;height:auto}.hsk-cb-kimg-caption{margin-top:4px;font-size:11px;line-height:1.4;color:var(--hsk-chat-muted,#9aa0a6)}.hsk-cb-viz--loading{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--hsk-chat-muted,#888);padding:10px 0}.hsk-cb-viz-spinner{width:14px;height:14px;border-radius:50%;border:2px solid var(--hsk-chat-divide,rgba(0,0,0,.15));border-top-color:var(--hsk-primary,#ff6a33);animation:hsk-viz-spin .7s linear infinite}@keyframes hsk-viz-spin{to{transform:rotate(360deg)}}.hsk-cb-panel[data-script=\\\"nonlatin\\\"][data-host-font=\\\"gap\\\"]{--hsk-font:\\\"Geist\\\",system-ui,-apple-system,'Segoe UI',Roboto,'Noto Sans',sans-serif}.hsk-cb-panel[data-script=\\\"nonlatin\\\"],.hsk-cb-panel[data-script=\\\"nonlatin\\\"] *{letter-spacing:normal;font-family:var(--hsk-font)}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello-lead,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello-ask,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-user-bubble,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hint,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-chip,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-topbar-btn,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-textarea,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-entlang-opt-title,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-entlang-opt-note,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text .hsk-markdown-list li,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text .hsk-markdown-h1,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text .hsk-markdown-h2,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text .hsk-markdown-h3,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-markdown-table th,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-markdown-table td{line-height:1.9}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hint{font-size:11px;line-height:16px;bottom:4px}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-voice-error{font-size:12px;line-height:22px;max-width:30ch}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello{font-size:clamp(20px,3.4vw,26px);line-height:1.5;text-wrap:balance;overflow-wrap:break-word}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello-ask{font-size:15px;line-height:1.75}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-hello-wrap{max-width:100%;min-width:0}.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-hello,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-hello-lead,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-hello-ask,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-ai-text,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-user-bubble,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-hint,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-chip,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-topbar-btn,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-textarea,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-entlang-opt-title,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-entlang-opt-note,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-ai-text .hsk-markdown-list li,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-ai-text .hsk-markdown-h1,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-ai-text .hsk-markdown-h2,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-ai-text .hsk-markdown-h3,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-markdown-table th,.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-markdown-table td{line-height:2.2}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-chip{font-size:14px}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-topbar-btn{height:auto;min-height:34px;padding:5px 14px}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-field{--hsk-input-line-height:1.9}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-textarea{min-height:34px}.hsk-cb-panel[data-nastaliq=\\\"true\\\"] .hsk-cb-field{--hsk-input-line-height:2.2}.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-user-bubble,.hsk-cb-panel[data-script=\\\"nonlatin\\\"] .hsk-cb-ai-text{overflow-wrap:break-word;word-break:normal}.hsk-cb-viz-broken{font-size:13px;color:var(--hsk-chat-muted,#71717a);padding:14px 16px;border:1px dashed var(--hsk-chat-divide,rgba(0,0,0,.12));border-radius:12px}.hsk-msg-audio-btn{background:transparent;border:none;color:#888;cursor:pointer;padding:4px;border-radius:4px;display:inline-flex;align-items:center}.hsk-cb-voice-mode-btn{width:36px;height:36px;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;background:transparent;border:1px solid transparent;border-radius:12px;color:var(--hsk-chat-muted,#71717a);cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);font-family:inherit}.hsk-cb-voice-mode-btn:hover:not(:disabled),.hsk-cb-mic-btn:hover:not(:disabled){border-color:color-mix(in srgb,var(--hsk-primary,#ff6a33) 25%,transparent);color:var(--hsk-primary,#ff6a33);background:color-mix(in srgb,var(--hsk-primary,#ff6a33) 8%,transparent);transform:translateY(-1px)}.hsk-cb-voice-mode-btn:disabled{opacity:.35;cursor:not-allowed}.hsk-cb-voice-mode-btn--active,.hsk-cb-mic-btn--listening{color:var(--hsk-primary,#ff6a33);background:color-mix(in srgb,var(--hsk-primary,#ff6a33) 12%,transparent)}.hsk-cb-mic-btn--processing{color:var(--hsk-primary,#ff6a33);opacity:.7}.hsk-voice-overlay{position:absolute;inset:0;z-index:30;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(12px,2.2vh,26px);padding:clamp(14px,2.5vh,24px);overflow-y:auto;overscroll-behavior:contain;background:var(--hsk-chat-bg,#ffffff);animation:hsk-voice-in .32s cubic-bezier(.2,.8,.2,1);will-change:opacity;contain:paint}.hsk-voice-overlay::before{content:'';position:absolute;inset:0;background:radial-gradient(42% 26% at 50% 40%,color-mix(in srgb,var(--hsk-primary,#ff6a33) 8%,transparent) 0,transparent 68%);pointer-events:none}.hsk-voice-overlay>*{position:relative}@keyframes hsk-voice-in{from{opacity:0}to{opacity:1}}.hsk-voice-allowance{position:absolute;top:14px;left:14px;display:flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:0 10px;font-size:12px;font-variant-numeric:tabular-nums;font-weight:600;border:1px solid color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 14%,transparent);border-radius:999px;color:var(--hsk-chat-muted,#71717a);transition:color .18s ease,border-color .18s ease}.hsk-voice-allowance--low{color:#dc2626;border-color:color-mix(in srgb,#dc2626 40%,transparent)}.hsk-voice-exit{position:absolute;top:14px;right:14px;display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;background:transparent;border:1px solid color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 14%,transparent);border-radius:999px;color:var(--hsk-chat-muted,#71717a);cursor:pointer;transition:color .18s ease,border-color .18s ease}.hsk-voice-exit:hover{color:var(--hsk-chat-text,#1f1f1f);border-color:color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 32%,transparent)}.hsk-voice-stage{width:min(560px,100%);height:clamp(110px,24vh,240px);flex:none}.hsk-voice-canvas{display:block;width:100%;height:100%}.hsk-voice-controls{display:flex;align-items:center;gap:12px}.hsk-voice-control{display:flex;align-items:center;justify-content:center;width:52px;height:52px;padding:0;background:var(--hsk-surface-2,rgba(255,255,255,.95));border:1px solid color-mix(in srgb,var(--hsk-chat-text,#000000) 10%,transparent);border-radius:999px;color:var(--hsk-chat-text,#1f1f1f);cursor:pointer;box-shadow:0 2px 12px rgba(0,0,0,.08),0 1px 3px rgba(0,0,0,.04);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);transition:color .2s ease,border-color .2s ease,background .2s ease,transform .2s cubic-bezier(.16,1,.3,1),box-shadow .2s ease}.hsk-voice-control:hover{transform:scale(1.06);box-shadow:0 4px 18px rgba(0,0,0,.12)}.hsk-voice-control:active{transform:scale(.92);transition-duration:.08s}.hsk-voice-control--muted{color:var(--hsk-chat-muted,#888888);border-color:color-mix(in srgb,var(--hsk-chat-text,#000000) 12%,transparent);background:color-mix(in srgb,var(--hsk-chat-bg,#ffffff) 85%,transparent);box-shadow:0 1px 4px rgba(0,0,0,.04)}.hsk-voice-control-icon{display:inline-flex;align-items:center;justify-content:center;z-index:2;transition:transform .2s ease}@keyframes hsk-voice-icon-in{from{opacity:0;transform:scale(.6) rotate(-12deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes hsk-voice-control-pulse{0%{transform:scale(1);box-shadow:0 0 0 0 color-mix(in srgb,var(--hsk-primary,#ff6a33) 45%,transparent)}40%{transform:scale(1.08);box-shadow:0 0 0 8px color-mix(in srgb,var(--hsk-primary,#ff6a33) 0,transparent)}100%{transform:scale(1);box-shadow:0 0 0 0 transparent}}@media (prefers-reduced-motion:reduce){.hsk-voice-control-icon,.hsk-voice-control--muted{animation:none}}.hsk-voice-caption{display:flex;flex-direction:column;align-items:center;gap:10px;max-width:min(520px,100%);text-align:center}.hsk-voice-phase{font-family:var(--hsk-font);font-size:.72rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--hsk-chat-muted,#71717a);transition:color .25s ease}.hsk-voice-phase--listening,.hsk-voice-phase--speaking{color:var(--hsk-primary,#ff6a33)}.hsk-voice-phase--thinking{animation:hsk-voice-breathe 1.6s ease-in-out infinite}@keyframes hsk-voice-breathe{0%,100%{opacity:.45}50%{opacity:1}}.hsk-voice-stage--connecting{opacity:.4;transition:opacity .25s ease}.hsk-voice-connecting{display:flex;align-items:center;gap:7px;font-family:var(--hsk-font);font-size:13px;color:var(--hsk-chat-muted,#8a8f98);animation:hsk-sent-in .2s ease-out both}.hsk-voice-connecting-dot{width:6px;height:6px;border-radius:999px;background:currentColor;animation:hsk-queued-pulse 1s ease-in-out infinite}@media (prefers-reduced-motion:reduce){.hsk-voice-connecting-dot{animation:none;opacity:.7}}.hsk-voice-heard{font-family:var(--hsk-font);font-size:1.05rem;line-height:1.5;color:var(--hsk-chat-text,#1f1f1f)}.hsk-voice-hint-sub{font-family:var(--hsk-font);font-size:14px;color:var(--hsk-chat-muted,#a1a1aa);line-height:1.4;opacity:.85}.hsk-voice-items{display:flex;flex-wrap:wrap;align-items:stretch;justify-content:center;gap:10px;width:min(620px,100%)}.hsk-voice-item{display:flex;flex-direction:column;align-items:flex-start;gap:6px;width:clamp(108px,30vw,132px);padding:8px;text-align:start;background:transparent;border:1px solid color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 10%,transparent);border-radius:12px;cursor:pointer;font-family:var(--hsk-font);animation:hsk-voice-item-in .34s cubic-bezier(.2,.8,.2,1) both;transition:border-color .18s ease,transform .18s ease}.hsk-voice-item:hover{border-color:color-mix(in srgb,var(--hsk-primary,#ff6a33) 45%,transparent);transform:translateY(-2px)}@keyframes hsk-voice-item-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}.hsk-voice-item-img{width:100%;height:clamp(52px,8.5vh,78px);object-fit:cover;border-radius:8px;background:color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 5%,transparent)}.hsk-voice-item-img--empty{display:flex;align-items:center;justify-content:center;color:color-mix(in srgb,var(--hsk-chat-text,#1f1f1f) 30%,transparent)}.hsk-voice-item-name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:.78rem;line-height:1.35;color:var(--hsk-chat-text,#1f1f1f)}.hsk-voice-item-price{font-size:.78rem;font-weight:600;color:var(--hsk-primary,#ff6a33)}@media (prefers-reduced-motion:reduce){.hsk-voice-item{animation:none}}.hsk-voice-error{font-family:var(--hsk-font);font-size:.85rem;color:#e5484d;text-align:center}@media (prefers-reduced-motion:reduce){.hsk-voice-overlay,.hsk-voice-phase--thinking{animation:none}}.hsk-cb-listen{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;margin-top:6px;padding:0;background:transparent;border:none;border-radius:999px;color:var(--hsk-chat-muted,#71717a);cursor:pointer;opacity:0;transition:opacity .18s ease,color .18s ease}.hsk-cb-msg-group:hover .hsk-cb-listen,.hsk-cb-listen:focus-visible,.hsk-cb-listen--active{opacity:1}.hsk-cb-listen:hover,.hsk-cb-listen--active{color:var(--hsk-primary,#ff6a33)}.hsk-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.hsk-voice-picker{position:absolute;top:clamp(14px,3vh,28px);left:50%;transform:translateX(-50%);display:flex;gap:8px;flex-wrap:nowrap;justify-content:center;max-width:min(100%,420px);padding:0 56px;z-index:2}.hsk-voice-pill{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;border:1px solid rgba(0,0,0,.09);background:rgba(255,255,255,.72);backdrop-filter:blur(8px);font:inherit;font-size:11px;letter-spacing:.01em;color:#5b5b5b;cursor:pointer;transition:background 160ms ease,border-color 160ms ease,color 160ms ease,transform 160ms ease;opacity:0;animation:hsk-voice-pill-in 420ms cubic-bezier(.16,1,.3,1) forwards}.hsk-voice-pill--on{animation:hsk-voice-pill-in 420ms cubic-bezier(.16,1,.3,1) forwards,hsk-voice-pill-pop 260ms ease}@keyframes hsk-voice-pill-in{from{opacity:0;transform:translateY(-6px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes hsk-voice-pill-pop{0%{transform:scale(1)}40%{transform:scale(1.06)}100%{transform:scale(1)}}@media (prefers-reduced-motion:reduce){.hsk-voice-pill{opacity:1;animation:none}}@media (max-width:520px){.hsk-voice-picker{gap:5px;padding:0 44px}.hsk-voice-pill{padding:5px 8px;gap:4px}}.hsk-voice-pill:hover{background:rgba(255,255,255,.95);border-color:rgba(0,0,0,.16)}.hsk-voice-pill--on:hover{background:#1c1c1c;border-color:#1c1c1c;color:#fff}.hsk-voice-pill--on{background:#1a1a1a;border-color:#1a1a1a;color:#fff}@media (prefers-color-scheme:dark){.hsk-voice-pill{border-color:rgba(255,255,255,.14);background:rgba(30,30,30,.7);color:#cfcfcf}.hsk-voice-pill:hover{background:rgba(45,45,45,.9)}.hsk-voice-pill--on:hover{background:#f2f2f2;border-color:#f2f2f2;color:#141414}.hsk-voice-pill--on{background:#f2f2f2;border-color:#f2f2f2;color:#141414}}@media (max-width:520px){.hsk-cb-input-box{gap:6px;padding:10px 10px 10px 12px}.hsk-cb-attach-btn,.hsk-cb-mic-btn,.hsk-cb-send,.hsk-cb-voice-mode-btn,.hsk-chat-send{width:32px;height:32px;border-radius:10px}.hsk-cb-textarea{flex:1 1 auto;min-width:0;font-size:16px}.hsk-cb-input-box .hsk-cb-listening{display:none}}.hsk-cb-main{position:relative}.hsk-cb-main,.hsk-voice-overlay{--hsk-doodle-ink:31,31,31;--hsk-doodle-tint:255,106,51}@keyframes hsk-doodles-shimmer-in{0%{opacity:0}100%{opacity:.9}}.hsk-cb-doodles{position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:.9;animation:hsk-doodles-shimmer-in .28s cubic-bezier(.16,1,.3,1) both}.hsk-cb-main>*:not(.hsk-cb-doodles){position:relative}@media (prefers-color-scheme:dark){.hsk-cb-main,.hsk-voice-overlay{--hsk-doodle-ink:240,239,237;--hsk-doodle-tint:255,150,110}}[data-hsk-theme=\\\"light\\\"] .hsk-cb-main,[data-hsk-theme=\\\"light\\\"] .hsk-voice-overlay{--hsk-doodle-ink:31,31,31;--hsk-doodle-tint:255,106,51}[data-hsk-theme=\\\"dark\\\"] .hsk-cb-main,[data-hsk-theme=\\\"dark\\\"] .hsk-voice-overlay{--hsk-doodle-ink:240,239,237;--hsk-doodle-tint:255,150,110}.hsk-cb-docked-option-price,.hsk-cb-entlang-price,.hsk-cb-src-price,.hsk-kiku-picker-item-price,.hsk-source-price,.hsk-sp-item-discount,.hsk-sp-item-original-price,.hsk-sp-item-price,.hsk-sp-mobile-main-card-price,.hsk-sp-mobile-similar-carousel-price,.hsk-voice-item-price,.hsk-live-cell{font-variant-numeric:tabular-nums}.hsk-live-wrap{margin:8px 0 2px;max-width:min(88%,560px);box-sizing:border-box}.hsk-live-carousel{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-start}.hsk-live-card{flex:0 1 auto;min-width:0;max-width:100%;background:var(--hsk-chat-source-bg,rgba(0,0,0,.035));border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.08));border-radius:14px;padding:10px 12px;box-sizing:border-box;display:flex;flex-direction:column;gap:8px;transition:opacity .2s ease}.hsk-live-card.is-stale{opacity:.75}.hsk-live-card__header{display:flex;align-items:center;justify-content:space-between;gap:8px}.hsk-live-card__status{display:flex;align-items:center;gap:6px;min-width:0}.hsk-live-dot{width:7px;height:7px;border-radius:50%;background:#10b981;flex-shrink:0}@media (prefers-reduced-motion:no-preference){.hsk-live-dot:not(.is-stale){animation:hsk-live-pulse 2s ease-in-out infinite}}.hsk-live-dot.is-stale{background:var(--hsk-chat-muted,#9ca3af)}.hsk-live-card__title{font-size:12px;font-weight:600;color:var(--hsk-chat-text,#111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-0.01em}.hsk-live-card__meta{display:flex;align-items:center;gap:8px;flex-shrink:0}.hsk-live-card__close{font-size:11px;font-weight:500;color:var(--hsk-chat-muted,#6b7280);opacity:.85;white-space:nowrap}.hsk-live-card__age{font-size:11px;font-weight:400;color:var(--hsk-chat-muted,#6b7280);white-space:nowrap;flex-shrink:0}.hsk-live-card__pills{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.hsk-live-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;background:var(--hsk-chat-bg,#ffffff);border:1px solid var(--hsk-chat-divide,rgba(0,0,0,.08));border-radius:8px;font-size:12px;font-variant-numeric:tabular-nums;line-height:1.3;color:var(--hsk-chat-text,#111827);box-shadow:0 1px 2px rgba(0,0,0,.03)}.hsk-live-pill__label{font-weight:500;color:var(--hsk-chat-muted,#6b7280);font-size:11px;text-transform:capitalize}.hsk-live-pill__value{font-weight:650;color:var(--hsk-chat-text,#111827)}@media (prefers-reduced-motion:no-preference){.hsk-live-pill.is-changed{animation:hsk-live-pill-flash 1.2s ease-out}@keyframes hsk-live-pill-flash{0%{background:rgba(16,185,129,.25);border-color:#10b981}100%{background:var(--hsk-chat-bg,#ffffff);border-color:var(--hsk-chat-divide,rgba(0,0,0,.08))}}}@media (max-width:640px){.hsk-cb-source{flex:0 0 128px}.hsk-cb-src-imgwrap,.hsk-cb-src-imgwrap-empty{width:128px;height:128px;font-size:24px}.hsk-cb-sources{gap:10px}.hsk-cb-src-name{font-size:12px;line-height:1.35}.hsk-cb-src-price{font-size:11px;padding:1px 7px;margin-top:4px}.hsk-cb-ai-text,.hsk-live{max-width:100%;width:100%}}@media (max-width:480px){.hsk-cb-source{flex:0 0 114px}.hsk-cb-src-imgwrap,.hsk-cb-src-imgwrap-empty{width:114px;height:114px;font-size:20px}.hsk-cb-sources{gap:8px}.hsk-live{border-radius:12px;padding:2px 0 8px;margin:8px 0 2px}.hsk-live-card{flex:1 1 100%}}.hsk-cb-overlay[data-hsk-theme],[data-hsk-theme] .hsk-cb-overlay{background:var(--hsk-chat-bg) !important;color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-panel{background:transparent !important;color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-topbar-name{background:var(--hsk-surface-2) !important;color:var(--hsk-name-text,var(--hsk-chat-text)) !important;box-shadow:0 0 0 3px var(--hsk-chat-bg),0 1px 3px rgba(var(--hsk-primary-rgb),.2) !important}[data-hsk-theme] .hsk-cb-think-head{background:var(--hsk-surface-2) !important;color:var(--hsk-think-text) !important;box-shadow:0 0 0 3px var(--hsk-chat-bg),0 1px 3px rgba(var(--hsk-primary-rgb),.2) !important}[data-hsk-theme] .hsk-cb-chip,[data-hsk-theme] .hsk-cb-lang-chip,[data-hsk-theme] .hsk-action-pill{border:var(--hsk-chip-border,none) !important;background:var(--hsk-surface-1) !important;color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-chip:hover,[data-hsk-theme] .hsk-cb-lang-chip:hover,[data-hsk-theme] .hsk-action-pill:hover{background:rgba(var(--hsk-primary-rgb),.12) !important;color:var(--hsk-primary) !important}[data-hsk-theme] .hsk-cb-ai-text{background:var(--hsk-bubble-bg) !important;color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::before{background:var(--hsk-bubble-bg) !important}[data-hsk-theme] .hsk-cb-ai-text:not(:has(~.hsk-cb-ai-text))::after{background:var(--hsk-chat-bg) !important}[data-hsk-theme] .hsk-cb-user-bubble--tail::before{background:#007aff !important}[data-hsk-theme] .hsk-cb-user-bubble--tail::after{background:var(--hsk-chat-bg) !important}[data-hsk-theme] .hsk-cb-topbar-title{color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-topbar-btn,[data-hsk-theme] .hsk-cb-back{background:var(--hsk-surface-1) !important;color:var(--hsk-chat-muted) !important}[data-hsk-theme] .hsk-cb-input-box{background:transparent !important;border:none !important;border-radius:inherit !important}[data-hsk-theme] .hsk-cb-textarea{color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-cb-textarea::placeholder{color:var(--hsk-placeholder) !important}[data-hsk-theme] .hsk-markdown-table th{color:var(--hsk-chat-muted) !important;border-bottom:1px solid var(--hsk-chat-divide) !important}[data-hsk-theme] .hsk-markdown-table td{color:var(--hsk-chat-text) !important;border-bottom:1px solid var(--hsk-chat-divide) !important}[data-hsk-theme] .hsk-cb-kiku-id-pill{background:var(--hsk-surface-1) !important;border:none !important;box-shadow:none !important;color:var(--hsk-chat-muted) !important}[data-hsk-theme] .hsk-cb-kiku-id-pill:hover{color:var(--hsk-primary) !important}[data-hsk-theme] .hsk-cb-theme-squircle-wrap.is-open,[data-hsk-theme] .hsk-cb-topbar-ooze-menu{background:var(--hsk-surface-2) !important;box-shadow:none !important}[data-hsk-theme] .hsk-cb-theme-squircle-trigger{background:var(--hsk-surface-1) !important;color:var(--hsk-chat-text) !important;border:none !important;box-shadow:none !important}[data-hsk-theme] .hsk-cb-theme-grid-item{background:var(--hsk-grid-bg) !important;color:var(--hsk-chat-muted) !important;border:none !important;box-shadow:none !important}[data-hsk-theme] .hsk-cb-theme-grid-item.is-active{background:var(--hsk-active-bg) !important;color:var(--hsk-on-active) !important;box-shadow:none !important}[data-hsk-theme] .hsk-cb-src-name,[data-hsk-theme] .hsk-source-card__title{color:var(--hsk-src-title) !important;font-weight:650 !important}[data-hsk-theme] .hsk-cb-src-desc,[data-hsk-theme] .hsk-cb-src-detail,[data-hsk-theme] .hsk-source-card__desc{color:var(--hsk-src-desc) !important}[data-hsk-theme] .hsk-cb-src-price{background:var(--hsk-price-bg) !important;color:var(--hsk-price-text) !important;font-weight:700 !important}[data-hsk-theme] .hsk-cb-main,[data-hsk-theme] .hsk-voice-overlay{--hsk-doodle-ink:var(--hsk-ink) !important;--hsk-doodle-tint:var(--hsk-tint) !important}[data-hsk-theme] .hsk-voice-pill{background:var(--hsk-chat-input-bg) !important;border-color:var(--hsk-chat-divide) !important;color:var(--hsk-chat-muted) !important}[data-hsk-theme] .hsk-voice-pill:hover{background:var(--hsk-surface-2) !important;color:var(--hsk-chat-text) !important}[data-hsk-theme] .hsk-voice-pill--on,[data-hsk-theme] .hsk-voice-pill--on:hover{background:var(--hsk-active-bg) !important;border-color:var(--hsk-active-bg) !important;color:var(--hsk-on-active) !important}.hsk-cb-overlay[data-hsk-theme=\\\"light\\\"],[data-hsk-theme=\\\"light\\\"] .hsk-cb-overlay{--hsk-primary:#ff6a33 !important;--hsk-primary-rgb:255,106,51 !important;--hsk-chat-bg:#ffffff !important;--hsk-chat-text:#1f1f1f !important;--hsk-chat-muted:#5f6368 !important;--hsk-chat-divide:#e5e7eb !important;--hsk-chat-input-bg:#f3f4f6 !important;--hsk-chat-source-bg:#f9fafb !important;--hsk-fade-bg:#ffffff !important;--hsk-goo-fill:#ffffff !important;--hsk-surface-1:rgba(0,0,0,.05) !important;--hsk-surface-2:#f1f3f4 !important;--hsk-bubble-bg:#f3f4f6 !important;--hsk-think-text:#4b5563 !important;--hsk-placeholder:#757575 !important;--hsk-grid-bg:#ffffff !important;--hsk-active-bg:#1f1f1f !important;--hsk-on-active:#ffffff !important;--hsk-src-title:#111827 !important;--hsk-src-desc:#4b5563 !important;--hsk-price-bg:#f3f4f6 !important;--hsk-price-text:#ea580c !important;--hsk-sheet-bg:#f3f4f6 !important;--hsk-chip-border:1px solid rgba(0,0,0,.08) !important;--hsk-ink:55,65,81 !important;--hsk-tint:145,77,47 !important}.hsk-cb-overlay[data-hsk-theme=\\\"dark\\\"],[data-hsk-theme=\\\"dark\\\"] .hsk-cb-overlay{--hsk-primary:#ff6a33 !important;--hsk-primary-rgb:255,106,51 !important;--hsk-chat-bg:#0a0a0a !important;--hsk-chat-text:#f0efed !important;--hsk-chat-muted:#888888 !important;--hsk-chat-divide:rgba(255,255,255,.08) !important;--hsk-chat-input-bg:#191919 !important;--hsk-chat-source-bg:rgba(255,255,255,.04) !important;--hsk-fade-bg:#0a0a0a !important;--hsk-goo-fill:#1a1a1c !important;--hsk-surface-1:rgba(255,255,255,.06) !important;--hsk-surface-2:#1f1f22 !important;--hsk-bubble-bg:#1f1f22 !important;--hsk-think-text:#a6a6a6 !important;--hsk-placeholder:#555555 !important;--hsk-grid-bg:#1a1a1c !important;--hsk-active-bg:#f0efed !important;--hsk-on-active:#0a0a0a !important;--hsk-src-title:#f9fafb !important;--hsk-src-desc:#9ca3af !important;--hsk-price-bg:rgba(255,255,255,.08) !important;--hsk-price-text:#ff7a45 !important;--hsk-sheet-bg:#1f1f22 !important;--hsk-ink:240,239,237 !important;--hsk-tint:248,195,174 !important}.hsk-cb-overlay[data-hsk-theme=\\\"mahogany\\\"],[data-hsk-theme=\\\"mahogany\\\"] .hsk-cb-overlay{--hsk-primary:#e07a38 !important;--hsk-primary-rgb:224,122,56 !important;--hsk-chat-bg:#140d09 !important;--hsk-chat-text:#f6eee3 !important;--hsk-chat-muted:#a89485 !important;--hsk-chat-divide:rgba(217,140,85,.18) !important;--hsk-chat-input-bg:#211610 !important;--hsk-chat-source-bg:#1c130d !important;--hsk-fade-bg:#140d09 !important;--hsk-goo-fill:#211610 !important;--hsk-surface-1:#211610 !important;--hsk-surface-2:#2b1c14 !important;--hsk-bubble-bg:#261912 !important;--hsk-think-text:#c4b1a1 !important;--hsk-placeholder:#7a6557 !important;--hsk-grid-bg:#2b1c14 !important;--hsk-active-bg:#e07a38 !important;--hsk-on-active:#ffffff !important;--hsk-src-title:#fdf8f4 !important;--hsk-src-desc:#c4b1a1 !important;--hsk-price-bg:#2b1c14 !important;--hsk-price-text:#f59e0b !important;--hsk-sheet-bg:#211610 !important;--hsk-ink:246,238,227 !important;--hsk-tint:235,180,142 !important}.hsk-cb-overlay[data-hsk-theme=\\\"blush\\\"],[data-hsk-theme=\\\"blush\\\"] .hsk-cb-overlay{--hsk-primary:#ec4899 !important;--hsk-primary-rgb:236,72,153 !important;--hsk-chat-bg:#fff5f7 !important;--hsk-chat-text:#3d1424 !important;--hsk-chat-muted:#94536d !important;--hsk-chat-divide:rgba(236,72,153,.18) !important;--hsk-chat-input-bg:#ffe4ec !important;--hsk-chat-source-bg:#fff0f4 !important;--hsk-fade-bg:#fff5f7 !important;--hsk-goo-fill:#ffe4ec !important;--hsk-surface-1:#ffe4ec !important;--hsk-surface-2:#fbcfe8 !important;--hsk-bubble-bg:#ffebf1 !important;--hsk-think-text:#831843 !important;--hsk-name-text:#831843 !important;--hsk-placeholder:#b57a91 !important;--hsk-grid-bg:#fff0f4 !important;--hsk-active-bg:#ec4899 !important;--hsk-on-active:#ffffff !important;--hsk-src-title:#2b0c19 !important;--hsk-src-desc:#702648 !important;--hsk-price-bg:#fce7f3 !important;--hsk-price-text:#db2777 !important;--hsk-sheet-bg:#ffe4ec !important;--hsk-sheet-hover:#ffd2e0 !important;--hsk-ink:130,36,75 !important;--hsk-tint:175,38,97 !important}.hsk-cb-overlay[data-hsk-theme=\\\"coffee\\\"],[data-hsk-theme=\\\"coffee\\\"] .hsk-cb-overlay{--hsk-primary:#a9714b !important;--hsk-primary-rgb:169,113,75 !important;--hsk-chat-bg:#f7f1e8 !important;--hsk-chat-text:#3b2a1d !important;--hsk-chat-muted:#8a7561 !important;--hsk-chat-divide:rgba(169,113,75,.18) !important;--hsk-chat-input-bg:#efe4d6 !important;--hsk-chat-source-bg:#f2eade !important;--hsk-fade-bg:#f7f1e8 !important;--hsk-goo-fill:#efe4d6 !important;--hsk-surface-1:#efe4d6 !important;--hsk-surface-2:#e6d7c4 !important;--hsk-bubble-bg:#f0e7da !important;--hsk-think-text:#6b543f !important;--hsk-placeholder:#a89680 !important;--hsk-grid-bg:#f2eade !important;--hsk-active-bg:#a9714b !important;--hsk-on-active:#ffffff !important;--hsk-src-title:#2a1c11 !important;--hsk-src-desc:#6b543f !important;--hsk-price-bg:#ece0cf !important;--hsk-price-text:#9a5f32 !important;--hsk-sheet-bg:#efe4d6 !important;--hsk-sheet-hover:#e6d7c4 !important;--hsk-ink:59,42,29 !important;--hsk-tint:120,88,62 !important}.hsk-cb-overlay[data-hsk-theme=\\\"midnight\\\"],[data-hsk-theme=\\\"midnight\\\"] .hsk-cb-overlay{--hsk-primary:#6366f1 !important;--hsk-primary-rgb:99,102,241 !important;--hsk-chat-bg:#0f1420 !important;--hsk-chat-text:#dfe6f5 !important;--hsk-chat-muted:#8792ad !important;--hsk-chat-divide:rgba(99,102,241,.18) !important;--hsk-chat-input-bg:#1a2133 !important;--hsk-chat-source-bg:#161d2c !important;--hsk-fade-bg:#0f1420 !important;--hsk-goo-fill:#1a2133 !important;--hsk-surface-1:#1a2133 !important;--hsk-surface-2:#222b40 !important;--hsk-bubble-bg:#1e2637 !important;--hsk-think-text:#a8b3cc !important;--hsk-placeholder:#5c6780 !important;--hsk-grid-bg:#222b40 !important;--hsk-active-bg:#6366f1 !important;--hsk-on-active:#ffffff !important;--hsk-src-title:#f2f5fc !important;--hsk-src-desc:#a8b3cc !important;--hsk-price-bg:#222b40 !important;--hsk-price-text:#818cf8 !important;--hsk-sheet-bg:#1a2133 !important;--hsk-sheet-hover:#222b40 !important;--hsk-ink:223,230,245 !important;--hsk-tint:150,160,200 !important}.hsk-cb-back-icon{display:inline-flex;transition:transform .22s cubic-bezier(.22,1,.36,1)}.hsk-cb-back:hover:not(:disabled) .hsk-cb-back-icon{transform:translateX(-2px)}.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-back:hover:not(:disabled) .hsk-cb-back-icon{transform:scaleX(-1) translateX(-2px)}.hsk-cb-tools-toggle{transition:transform .26s cubic-bezier(.34,1.56,.64,1),background-color .42s cubic-bezier(.16,1,.3,1),color .42s cubic-bezier(.16,1,.3,1)}.hsk-cb-tools-toggle:hover:not(:disabled){color:var(--hsk-primary,#ff6a33);transform:rotate(90deg)}.hsk-cb-tools-toggle--open:hover:not(:disabled){transform:rotate(135deg)}.hsk-cb-tools-toggle:active:not(:disabled){transform:scale(.9);transition-duration:.1s}.hsk-cb-theme-trigger-icon{display:inline-flex;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-theme-squircle-trigger:hover .hsk-cb-theme-trigger-icon{transform:translateY(-1.5px) rotate(-8deg)}.hsk-cb-dot-item:hover:not(.hsk-cb-dot-item--active){background:var(--hsk-chat-muted,rgba(120,120,120,.6));transform:scale(1.35)}.hsk-msg-audio-btn{transition:color .18s ease,transform .22s cubic-bezier(.34,1.56,.64,1)}.hsk-msg-audio-btn:hover:not(:disabled){color:var(--hsk-primary,#ff6a33);transform:scale(1.12)}.hsk-msg-audio-btn:active:not(:disabled){transform:scale(.94);transition-duration:.1s}.hsk-markup-color{transition:transform .22s cubic-bezier(.34,1.56,.64,1),border-color .18s ease}.hsk-markup-color:hover:not(.hsk-markup-color--on){transform:scale(1.22)}.hsk-markup-color--on:hover{transform:scale(1.15)}@media (prefers-reduced-motion:reduce){.hsk-cb-back:hover:not(:disabled) .hsk-cb-back-icon,.hsk-cb-panel[dir=\\\"rtl\\\"] .hsk-cb-back:hover:not(:disabled) .hsk-cb-back-icon,.hsk-cb-theme-squircle-trigger:hover .hsk-cb-theme-trigger-icon,.hsk-cb-dot-item:hover:not(.hsk-cb-dot-item--active),.hsk-msg-audio-btn:hover:not(:disabled),.hsk-markup-color:hover:not(.hsk-markup-color--on){transform:none}.hsk-cb-tools-toggle:hover:not(:disabled),.hsk-cb-tools-toggle--open:hover:not(:disabled){transform:none}}.hsk-voice-control{position:relative;isolation:isolate;border-radius:999px}.hsk-voice-control:not(.hsk-voice-control--muted)::before{content:'';position:absolute;inset:-1.5px;border-radius:inherit;background:conic-gradient( from 0deg,#ff3b30,#ff9500,#ffd60a,#34c759,#00c7be,#30b0c7,#007aff,#5856d6,#af52de,#ff2d55,#ff3b30 );-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2.5px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,transparent calc(100% - 2.5px),#000 calc(100% - 2px));animation:hsk-apple-siri-spin 3s linear infinite;pointer-events:none;z-index:1}.hsk-voice-control::after{display:none !important}.hsk-voice-control-icon{will-change:transform}.hsk-voice-control:not(.hsk-voice-control--muted) .hsk-voice-control-icon{animation:hsk-apple-siri-mic-pulse 2.2s ease-in-out infinite}@keyframes hsk-apple-siri-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes hsk-apple-siri-breathe{0%,100%{transform:scale(.95);opacity:.55}50%{transform:scale(1.15);opacity:.95}}@keyframes hsk-apple-siri-mic-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}.hsk-voice-control--muted::before,.hsk-voice-control--muted::after{display:none}@media (prefers-reduced-motion:reduce){.hsk-voice-control:not(:hover):not(.hsk-voice-control--muted) .hsk-voice-control-icon,.hsk-voice-control:hover::before,.hsk-voice-control--muted::before,.hsk-voice-control--muted::after{animation:none}.hsk-voice-control:hover,.hsk-voice-control:hover .hsk-mic-cap{transform:none}}.hsk-cb-voice-error{animation:hsk-error-shake .26s cubic-bezier(.36,.07,.19,.97) both}@keyframes hsk-error-shake{0%,100%{transform:translateX(0)}22%{transform:translateX(-3px)}55%{transform:translateX(2px)}80%{transform:translateX(-1px)}}@media (prefers-reduced-motion:reduce){.hsk-cb-voice-error{animation:none}}.hsk-sun-rays,.hsk-sun-core,.hsk-moon-body,.hsk-wood-layer,.hsk-heart-body,.hsk-steam,.hsk-star-spark,.hsk-check-mark,.hsk-send-tail,.hsk-send-body{transform-box:fill-box;transform-origin:center}.hsk-sun-rays{transform-origin:12px 12px;transition:transform .5s cubic-bezier(.22,1,.36,1)}.hsk-cb-theme-grid-item:hover .hsk-sun-rays,.hsk-cb-theme-squircle-trigger:hover .hsk-sun-rays{transform:rotate(45deg)}.hsk-sun-core{transition:transform .32s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-theme-grid-item:hover .hsk-sun-core,.hsk-cb-theme-squircle-trigger:hover .hsk-sun-core{transform:scale(1.14)}.hsk-moon-body{transition:transform .34s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-theme-grid-item:hover .hsk-moon-body,.hsk-cb-theme-squircle-trigger:hover .hsk-moon-body{transform:rotate(-16deg)}.hsk-wood-layer{transition:transform .34s cubic-bezier(.34,1.56,.64,1)}.hsk-wood-layer{transition-delay:calc(var(--hsk-layer,0) * 45ms)}.hsk-cb-theme-grid-item:hover .hsk-wood-layer,.hsk-cb-theme-squircle-trigger:hover .hsk-wood-layer{transform:translateY(-1.2px)}.hsk-cb-theme-grid-item:hover .hsk-heart-body,.hsk-cb-theme-squircle-trigger:hover .hsk-heart-body{animation:hsk-heartbeat 1.1s ease-in-out infinite}@keyframes hsk-heartbeat{0%,100%{transform:scale(1)}14%{transform:scale(1.18)}28%{transform:scale(1)}42%{transform:scale(1.12)}56%{transform:scale(1)}}.hsk-steam{opacity:.9}.hsk-cb-theme-grid-item:hover .hsk-steam,.hsk-cb-theme-squircle-trigger:hover .hsk-steam{animation:hsk-steam-rise 1.6s ease-out infinite;animation-delay:calc(var(--hsk-steam,0) * 220ms)}@keyframes hsk-steam-rise{0%{transform:translateY(2px) scaleY(.5);opacity:0}35%{opacity:.95}100%{transform:translateY(-3px) scaleY(1.15);opacity:0}}.hsk-cb-theme-grid-item:hover .hsk-star-spark,.hsk-cb-theme-squircle-trigger:hover .hsk-star-spark{animation:hsk-twinkle 1.4s ease-in-out infinite}@keyframes hsk-twinkle{0%,100%{transform:scale(1) rotate(0deg);opacity:.85}50%{transform:scale(1.45) rotate(20deg);opacity:1}}.hsk-check-mark{stroke-dasharray:30;stroke-dashoffset:30;animation:hsk-check-draw .42s cubic-bezier(.65,0,.35,1) forwards}@keyframes hsk-check-draw{to{stroke-dashoffset:0}}.hsk-send-body,.hsk-send-tail{transition:transform .28s cubic-bezier(.22,1,.36,1)}.hsk-send-tail{transition-delay:40ms}.hsk-chat-send:hover:not(:disabled) .hsk-send-body,.hsk-cb-send:hover:not(:disabled) .hsk-send-body{transform:translate(1.5px,-1.5px)}.hsk-chat-send:hover:not(:disabled) .hsk-send-tail,.hsk-cb-send:hover:not(:disabled) .hsk-send-tail{transform:translate(2.5px,-2.5px)}@media (prefers-reduced-motion:reduce){.hsk-sun-rays,.hsk-sun-core,.hsk-moon-body,.hsk-wood-layer,.hsk-send-body,.hsk-send-tail{transition:none;transform:none !important}.hsk-cb-theme-grid-item:hover .hsk-heart-body,.hsk-cb-theme-squircle-trigger:hover .hsk-heart-body,.hsk-cb-theme-grid-item:hover .hsk-steam,.hsk-cb-theme-squircle-trigger:hover .hsk-steam,.hsk-cb-theme-grid-item:hover .hsk-star-spark,.hsk-cb-theme-squircle-trigger:hover .hsk-star-spark{animation:none}.hsk-check-mark{animation:none;stroke-dashoffset:0}}.hsk-cb-send-stage{position:relative;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:visible}.hsk-cb-send-seam{position:absolute;top:50%;left:50%;width:2px;height:15px;border-radius:2px;background:currentColor;transform:translate(-50%,-50%) rotate(38deg) scaleY(0);transform-origin:center;opacity:0;pointer-events:none}.hsk-cb-send-kite{display:inline-flex;transform-origin:center;will-change:transform}.hsk-cb-send:hover:not(:disabled) .hsk-cb-send-kite{transform:translate(1.5px,-1.5px);transition:transform .26s cubic-bezier(.22,1,.36,1)}.hsk-cb-send.is-launching .hsk-cb-send-kite{animation:hsk-kite-tear .55s cubic-bezier(.22,1,.36,1) both}.hsk-cb-send.is-launching .hsk-cb-send-seam{animation:hsk-seam-heal .55s cubic-bezier(.4,0,.3,1) both}@keyframes hsk-kite-tear{0%{transform:translate(0,0) scale(1) rotate(0deg);opacity:1}18%{transform:translate(-1px,2.5px) scale(.92,1.08) rotate(-4deg);opacity:1}45%{transform:translate(3px,-16px) scale(1.2,.8) rotate(6deg);opacity:.95}75%{transform:translate(6px,-38px) scale(1.05,.7) rotate(10deg);opacity:.6}100%{transform:translate(8px,-56px) scale(.6,.4) rotate(12deg);opacity:0}}@keyframes hsk-seam-heal{0%{transform:translate(-50%,-50%) rotate(38deg) scaleY(0);opacity:0}22%{transform:translate(-50%,-50%) rotate(38deg) scaleY(1);opacity:.9}45%{transform:translate(-50%,-50%) rotate(38deg) scaleY(1.3);opacity:.8}72%{transform:translate(-50%,-50%) rotate(38deg) scaleY(.3);opacity:.35}100%{transform:translate(-50%,-50%) rotate(38deg) scaleY(0);opacity:0}}.hsk-kite-wing{transform-box:fill-box;transform-origin:100% 0}.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-kite-wing--far{animation:hsk-wing-beat-far .62s ease-in-out infinite}.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-kite-wing--near{animation:hsk-wing-beat-near .62s ease-in-out .07s infinite}.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-cb-send-kite{animation:hsk-kite-strain 2.4s cubic-bezier(.45,0,.35,1) infinite}.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-cb-send-seam{animation:hsk-seam-strain 2.4s cubic-bezier(.45,0,.35,1) infinite}@keyframes hsk-kite-strain{0%,10%{transform:translate(0,0) scale(1) rotate(0deg)}20%{transform:translate(-1.2px,2px) scale(.94,1.05) rotate(-4deg)}34%{transform:translate(3.5px,-5px) scale(1.16,.86) rotate(8deg)}42%{transform:translate(4.2px,-6px) scale(1.2,.82) rotate(9deg)}50%{transform:translate(2.4px,-3.4px) scale(1.06,.94) rotate(5deg)}64%{transform:translate(-.6px,1.2px) scale(.97,1.03) rotate(-2deg)}78%,100%{transform:translate(0,0) scale(1) rotate(0deg)}}@keyframes hsk-seam-strain{0%,22%{transform:translate(-50%,-50%) rotate(38deg) scaleY(0);opacity:0}34%{transform:translate(-50%,-50%) rotate(38deg) scaleY(.6);opacity:.34}42%{transform:translate(-50%,-50%) rotate(38deg) scaleY(.95);opacity:.5}52%{transform:translate(-50%,-50%) rotate(38deg) scaleY(.55);opacity:.3}66%,100%{transform:translate(-50%,-50%) rotate(38deg) scaleY(0);opacity:0}}@keyframes hsk-wing-beat-far{0%,100%{transform:scaleX(1) skewY(0deg)}50%{transform:scaleX(.86) skewY(-4deg)}}@keyframes hsk-wing-beat-near{0%,100%{transform:scaleX(1) skewY(0deg)}50%{transform:scaleX(1.1) skewY(3deg)}}.hsk-stop-ring{transform-box:fill-box;transform-origin:center;stroke-dasharray:22 38;opacity:.85;animation:hsk-stop-orbit 1.4s linear infinite}.hsk-stop-core{transform-box:fill-box;transform-origin:center;animation:hsk-stop-pulse 1.4s ease-in-out infinite;transition:rx .2s ease,transform .2s cubic-bezier(.34,1.56,.64,1)}.hsk-cb-send--stop:hover .hsk-stop-core{transform:scale(1.16);animation-play-state:paused}.hsk-cb-send--stop:hover .hsk-stop-ring{animation-duration:.7s}@keyframes hsk-stop-orbit{to{transform:rotate(1turn)}}@keyframes hsk-stop-pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.86);opacity:.75}}@media (prefers-reduced-motion:reduce){.hsk-cb-send.is-launching .hsk-cb-send-kite,.hsk-cb-send.is-launching .hsk-cb-send-seam,.hsk-cb-send:hover:not(:disabled) .hsk-cb-send-kite{animation:none;transform:none}}.hsk-cb-send.is-launching{overflow:visible !important}.hsk-cb-send-sheath{position:absolute;inset:-1px;background:radial-gradient(120% 90% at 32% 22%,rgba(255,255,255,.44) 0,rgba(255,255,255,0) 58%),linear-gradient(150deg,color-mix(in srgb,var(--hsk-primary,#1273e6) 72%,#ffffff) 0,var(--hsk-primary,#1273e6) 46%,color-mix(in srgb,var(--hsk-primary,#1273e6) 74%,#000000) 100%);border-radius:46% 54% 52% 48% / 50% 47% 53% 50%;box-shadow:inset 0 2px 3px rgba(255,255,255,.5),inset 0 -3px 5px color-mix(in srgb,var(--hsk-primary,#1273e6) 30%,rgba(0,0,0,.55)),0 2px 5px rgba(0,0,0,.20),0 7px 16px color-mix(in srgb,var(--hsk-primary,#1273e6) 16%,transparent);transform-origin:58% 62%;pointer-events:none;z-index:1;will-change:transform,border-radius;transition:border-radius .5s cubic-bezier(.34,1.6,.5,1),box-shadow .3s ease}.hsk-cb-send-stage{z-index:2;position:relative}.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-cb-send-sheath{animation:hsk-sheath-press 2.4s cubic-bezier(.35,.8,.3,1) infinite}@keyframes hsk-sheath-press{0%,12%{transform:scale(1);border-radius:46% 54% 52% 48% / 50% 47% 53% 50%}22%{transform:scale(.94,1.08) translate(-1.4px,2.2px);border-radius:52% 48% 44% 56% / 58% 40% 60% 42%}36%{transform:scale(1.14,.87) translate(2.6px,-3.4px) rotate(2deg);border-radius:38% 66% 54% 46% / 40% 62% 38% 60%}46%{transform:scale(1.19,.83) translate(3.6px,-4.6px) rotate(2.8deg);border-radius:34% 72% 56% 44% / 36% 68% 32% 64%}58%{transform:scale(.93,1.09) translate(-1.2px,1.8px) rotate(-1.4deg);border-radius:56% 44% 42% 58% / 60% 38% 62% 40%}70%{transform:scale(1.05,.96) translate(.8px,-1px) rotate(.6deg);border-radius:44% 56% 50% 50% / 46% 54% 46% 54%}80%{transform:scale(.98,1.03);border-radius:50% 50% 48% 52% / 52% 48% 52% 48%}88%,100%{transform:scale(1);border-radius:46% 54% 52% 48% / 50% 47% 53% 50%}}.hsk-cb-send.is-launching .hsk-cb-send-sheath{animation:hsk-sheath-yield .55s cubic-bezier(.3,.7,.25,1) both}@keyframes hsk-sheath-yield{0%{transform:scale(1);border-radius:46% 54% 52% 48% / 50% 47% 53% 50%}20%{transform:scale(.88,1.14) translate(-2px,3.4px);border-radius:56% 44% 40% 60% / 64% 34% 66% 36%}45%{transform:scale(1.34,.68) translate(6px,-10px) rotate(4.6deg);border-radius:24% 86% 62% 38% / 26% 80% 20% 74%}65%{transform:scale(.86,1.16) translate(-2.2px,3.6px) rotate(-2.2deg);border-radius:60% 40% 38% 62% / 68% 30% 70% 32%}82%{transform:scale(1.06,.95) translate(1px,-1px) rotate(.8deg);border-radius:44% 56% 52% 48% / 46% 54% 46% 54%}100%{transform:scale(1);border-radius:46% 54% 52% 48% / 50% 47% 53% 50%}}.hsk-cb-send:disabled .hsk-cb-send-sheath{opacity:0}.hsk-cb-send--stop .hsk-cb-send-sheath{display:none}.hsk-cb-send:active:not(:disabled) .hsk-cb-send-sheath{box-shadow:inset 0 1px 2px rgba(255,255,255,.3),inset 0 -1px 3px color-mix(in srgb,var(--hsk-primary,#1273e6) 24%,rgba(0,0,0,.6)),0 1px 3px rgba(0,0,0,.24)}@media (prefers-reduced-motion:reduce){.hsk-cb-send:not(:disabled):not(.is-launching) .hsk-cb-send-sheath,.hsk-cb-send.is-launching .hsk-cb-send-sheath{animation:none}}.hsk-cb-send:not(.hsk-cb-send--stop):not(:disabled){background:transparent !important;box-shadow:none !important;overflow:visible !important}.hsk-cb-send:not(.hsk-cb-send--stop):not(:disabled):hover{box-shadow:none !important}.hsk-cb-send:not(:disabled):hover .hsk-cb-send-sheath{box-shadow:inset 0 2px 4px rgba(255,255,255,.58),inset 0 -3px 6px color-mix(in srgb,var(--hsk-primary,#1273e6) 28%,rgba(0,0,0,.5)),0 3px 7px rgba(0,0,0,.22),0 10px 22px color-mix(in srgb,var(--hsk-primary,#1273e6) 20%,transparent)}.hsk-cb-terms-sanctuary{display:flex;flex-direction:column;margin:18px 0 22px;width:100%;max-width:520px;text-align:start;background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;border:none;border-radius:0;padding:0;box-shadow:none;opacity:0;animation:hsk-terms-delicate-in .5s cubic-bezier(.16,1,.3,1) .05s forwards}@keyframes hsk-terms-delicate-in{0%{opacity:0;transform:translateY(8px)}100%{opacity:1;transform:translateY(0)}}.hsk-cb-terms-item{display:flex;flex-direction:column;gap:4px;opacity:0;animation:hsk-terms-item-in .45s cubic-bezier(.16,1,.3,1) forwards;animation-delay:calc(var(--hsk-row-idx,0) * 60ms+80ms)}@keyframes hsk-terms-item-in{0%{opacity:0;transform:translateY(6px)}100%{opacity:1;transform:translateY(0)}}.hsk-cb-terms-head{display:flex;align-items:baseline;gap:10px}.hsk-cb-terms-numeral{font-family:ui-serif,Georgia,Cambria,\\\"Times New Roman\\\",Times,serif;font-style:italic;font-size:11px;font-weight:600;letter-spacing:.12em;color:var(--hsk-primary,#ff6a33);opacity:.85;flex-shrink:0;user-select:none}.hsk-cb-terms-title{margin:0;font-size:14.5px;font-weight:700;letter-spacing:-0.015em;color:var(--hsk-chat-text,#ffffff)}.hsk-cb-terms-desc{margin:0;padding-inline-start:22px;font-size:13px;line-height:1.55;color:var(--hsk-chat-muted,#9ca3af);font-weight:400}.hsk-cb-terms-divider{height:1px;margin:14px 0;background:linear-gradient( 90deg,transparent 0,color-mix(in srgb,var(--hsk-chat-text,#000000) 8%,transparent) 20%,color-mix(in srgb,var(--hsk-chat-text,#000000) 8%,transparent) 80%,transparent 100% )}.hsk-cb-terms-action-wrap{display:flex;justify-content:center;width:100%;margin-top:14px}.hsk-cb-terms-agree-btn{display:inline-flex;align-items:center;justify-content:center;padding:12px 34px;font-size:14px;font-weight:600;border-radius:9999px;border:1px solid var(--hsk-chat-divide,rgba(255,255,255,.08));background:var(--hsk-chat-divide,rgba(255,255,255,.06));color:var(--hsk-chat-muted,rgba(255,255,255,.4));cursor:not-allowed;transition:all .3s cubic-bezier(.16,1,.3,1);letter-spacing:-0.01em}.hsk-cb-terms-agree-btn.is-active{background:#ff6a33;color:#ffffff;border-color:#ff6a33;cursor:pointer;box-shadow:0 4px 14px rgba(255,106,51,.3)}.hsk-cb-terms-agree-btn.is-active:hover{background:#e55620;border-color:#e55620;transform:translateY(-1px);box-shadow:0 6px 18px rgba(255,106,51,.38)}.hsk-cb-terms-agree-btn.is-active:active{transform:translateY(0);box-shadow:0 2px 6px rgba(255,106,51,.2)}\";\n","import cssText from '../generated/cssText';\r\n\r\nconst CONTAINER_ID = 'akropolys-kiku-root';\r\nlet container: HTMLElement | null = null;\r\nlet shadow: ShadowRoot | null = null;\r\n\r\nfunction applyStyles(root: ShadowRoot): void {\r\n if (typeof CSSStyleSheet !== 'undefined' && 'replaceSync' in CSSStyleSheet.prototype) {\r\n try {\r\n const sheet = new CSSStyleSheet();\r\n sheet.replaceSync(cssText);\r\n root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];\r\n return;\r\n } catch {\r\n }\r\n }\r\n const style = document.createElement('style');\r\n style.textContent = cssText;\r\n root.appendChild(style);\r\n}\r\n\r\nexport function getShadowContainer(): HTMLElement | null {\r\n if (typeof document === 'undefined') return null; // SSR\r\n if (shadow) return shadow as unknown as HTMLElement;\r\n\r\n container = document.getElementById(CONTAINER_ID);\r\n if (!container) {\r\n container = document.createElement('div');\r\n container.id = CONTAINER_ID;\r\n container.style.cssText = 'all: initial;';\r\n document.body.appendChild(container);\r\n }\r\n\r\n shadow = container.shadowRoot ?? container.attachShadow({ mode: 'open' });\r\n applyStyles(shadow);\r\n\r\n return shadow as unknown as HTMLElement;\r\n}\r\n\r\nexport function destroyShadowContainer(): void {\r\n container?.remove();\r\n container = null;\r\n shadow = null;\r\n}\r\n","import type { ScriptFont } from '@akropolys/sdk';\r\n\r\n// baseFont() is a bare fetch with no client-side cache, and every component running\r\n// useScriptFont calls it — six round trips per open. One promise per client instead.\r\nconst BASE_FONT = new WeakMap<object, Promise<ScriptFont | null>>();\r\n\r\nexport function cachedBaseFont(client: any): Promise<ScriptFont | null> {\r\n if (!client) return Promise.resolve(null);\r\n const hit = BASE_FONT.get(client);\r\n if (hit) return hit;\r\n const p = Promise.resolve()\r\n .then(() => client.baseFont?.() ?? null)\r\n .catch(() => null);\r\n BASE_FONT.set(client, p);\r\n return p;\r\n}\r\n\r\n// Pulled forward on hover/idle so the click doesn't pay for the round trips.\r\nexport function warmChrome(client: any, shopperLanguage: string, defaults: Record<string, string>): void {\r\n if (!client) return;\r\n cachedBaseFont(client);\r\n if (shopperLanguage) {\r\n try { client.getUIStrings?.(shopperLanguage, defaults)?.catch?.(() => {}); } catch { }\r\n }\r\n}\r\n","import { useEffect } from 'react';\r\nimport type { AkropolysTheme, ScriptFont } from '@akropolys/sdk';\r\n\r\nconst MOUNTED = new Map<string, number>();\r\n\r\nfunction formatFor(url: string): string {\r\n const ext = url.split('?')[0].split('#')[0].split('.').pop()?.toLowerCase();\r\n if (ext === 'woff2') return 'woff2';\r\n if (ext === 'woff') return 'woff';\r\n if (ext === 'otf') return 'opentype';\r\n if (ext === 'ttf') return 'truetype';\r\n return '';\r\n}\r\n\r\nfunction safeUrl(url: string): string | null {\r\n const u = url.trim();\r\n if (!u) return null;\r\n if (/[\"'()\\\\\\s]/.test(u)) return null;\r\n if (/^(javascript|vbscript):/i.test(u)) return null;\r\n return u;\r\n}\r\n\r\nconst RANGE_SEGMENT = /^[Uu]\\+[0-9A-Fa-f?]{1,6}(-[0-9A-Fa-f]{1,6})?$/;\r\n\r\nconst safeRange = (r: string): string => {\r\n const parts = r.split(',').map(s => s.trim()).filter(Boolean);\r\n if (parts.length === 0 || !parts.every(p => RANGE_SEGMENT.test(p))) return '';\r\n return parts.join(', ');\r\n};\r\n\r\nconst safeWeight = (w: string): string => (/^\\d{3}( \\d{3})?$/.test(w) ? w : '400');\r\n\r\nfunction useMountedFaces(key: string, css: string): void {\r\n useEffect(() => {\r\n if (!key || !css || typeof document === 'undefined') return;\r\n let h = 5381;\r\n for (let i = 0; i < key.length; i++) h = ((h << 5) + h + key.charCodeAt(i)) >>> 0;\r\n const id = `hsk-font-${h.toString(36)}`;\r\n\r\n MOUNTED.set(key, (MOUNTED.get(key) ?? 0) + 1);\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n return () => {\r\n const left = (MOUNTED.get(key) ?? 1) - 1;\r\n if (left > 0) { MOUNTED.set(key, left); return; }\r\n MOUNTED.delete(key);\r\n document.getElementById(id)?.remove();\r\n };\r\n }, [key, css]);\r\n}\r\n\r\nfunction scriptFontCSS(font: ScriptFont): string {\r\n return font.faces\r\n .map(f => {\r\n const url = safeUrl(f.url);\r\n if (!url) return '';\r\n return `@font-face{font-family:\"${font.family}\";font-style:normal;` +\r\n `font-weight:${safeWeight(f.weight)};font-display:swap;src:url(${url}) format(\"woff2\");` +\r\n (safeRange(f.unicodeRange) ? `unicode-range:${safeRange(f.unicodeRange)};` : '') + '}';\r\n })\r\n .join('');\r\n}\r\n\r\nexport function useScriptFontFace(font: ScriptFont | null | undefined): void {\r\n const faces = font?.faces ?? [];\r\n const css = font && faces.length ? scriptFontCSS(font) : '';\r\n useMountedFaces(css ? `script|${font!.family}|${faces.map(f => f.url).join('|')}` : '', css);\r\n}\r\n\r\nexport async function preloadScriptFont(font: ScriptFont, timeoutMs = 1200): Promise<void> {\r\n if (typeof document === 'undefined' || !('fonts' in document)) return;\r\n const css = scriptFontCSS(font);\r\n if (!css) return;\r\n\r\n const key = `script|${font.family}|${font.faces.map(f => f.url).join('|')}`;\r\n let h = 5381;\r\n for (let i = 0; i < key.length; i++) h = ((h << 5) + h + key.charCodeAt(i)) >>> 0;\r\n const id = `hsk-font-${h.toString(36)}`;\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n const fonts = (document as any).fonts;\r\n const loads = font.faces.map(() =>\r\n fonts.load(`16px \"${font.family}\"`).catch(() => {})\r\n );\r\n await Promise.race([\r\n Promise.all(loads),\r\n new Promise(resolve => setTimeout(resolve, timeoutMs)),\r\n ]);\r\n}\r\n\r\nexport function useHostFontFace(theme: 'light' | 'dark' | AkropolysTheme | undefined): void {\r\n const t = typeof theme === 'object' && theme ? theme : undefined;\r\n const family = t?.fontFamily?.split(',')[0].trim().replace(/^['\"]|['\"]$/g, '') ?? '';\r\n const urls = typeof t?.fontUrl === 'string' ? { normal: t.fontUrl } : (t?.fontUrl ?? {});\r\n const normal = urls.normal ?? '';\r\n const bold = urls.bold ?? '';\r\n const variable = urls.variable ?? '';\r\n\r\n useEffect(() => {\r\n if (!family || (!normal && !bold && !variable)) return;\r\n\r\n const weights: ReadonlyArray<readonly [string, string]> = variable\r\n ? [['100 900', variable]]\r\n : [['400', normal], ['700', bold]];\r\n\r\n const faces: string[] = [];\r\n for (const [weight, raw] of weights) {\r\n if (!raw) continue;\r\n const url = safeUrl(raw);\r\n if (!url) continue;\r\n const fmt = formatFor(url);\r\n faces.push(\r\n `@font-face{font-family:\"${family}\";font-style:normal;font-weight:${weight};` +\r\n `font-display:swap;src:url(${url})${fmt ? ` format(\"${fmt}\")` : ''};}`\r\n );\r\n }\r\n if (faces.length === 0) return;\r\n\r\n const css = faces.join('');\r\n const key = `${family}|${normal}|${bold}|${variable}`;\r\n let h = 5381;\r\n for (let i = 0; i < key.length; i++) h = ((h << 5) + h + key.charCodeAt(i)) >>> 0;\r\n const id = `hsk-host-font-${h.toString(36)}`;\r\n\r\n MOUNTED.set(key, (MOUNTED.get(key) ?? 0) + 1);\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n return () => {\r\n const left = (MOUNTED.get(key) ?? 1) - 1;\r\n if (left > 0) { MOUNTED.set(key, left); return; }\r\n MOUNTED.delete(key);\r\n document.getElementById(id)?.remove();\r\n };\r\n }, [family, normal, bold, variable]);\r\n}\r\n","import React from 'react';\r\nimport type { AkropolysTheme, ChatSource } from '@akropolys/sdk';\r\nimport type { KikuButtonProps } from '../KikuButton';\r\n\r\nexport const DEFAULT_CHIPS: string[] = [];\r\n\r\nexport const LANGUAGE_CHOICES = [\r\n { value: 'English', native: 'English', tag: 'en', rtl: false },\r\n { value: 'Chinese', native: '中文', tag: 'zh', rtl: false },\r\n { value: 'Spanish', native: 'Español', tag: 'es', rtl: false },\r\n { value: 'Arabic', native: 'العربية', tag: 'ar', rtl: true },\r\n { value: 'Hindi', native: 'हिन्दी', tag: 'hi', rtl: false },\r\n { value: 'French', native: 'Français', tag: 'fr', rtl: false },\r\n { value: 'Swahili', native: 'Kiswahili', tag: 'sw', rtl: false },\r\n { value: 'Portuguese', native: 'Português', tag: 'pt', rtl: false },\r\n { value: 'Japanese', native: '日本語', tag: 'ja', rtl: false },\r\n { value: 'Urdu', native: 'اردو', tag: 'ur', rtl: true },\r\n];\r\n\r\nexport function endonymFor(lang: string | null | undefined): string | undefined {\r\n if (!lang) return undefined;\r\n const typed = lang.trim();\r\n if (!typed) return undefined;\r\n const l = typed.toLowerCase();\r\n const hit = LANGUAGE_CHOICES.find(\r\n x => x.value.toLowerCase() === l || x.native.toLowerCase() === l || x.tag === l\r\n );\r\n return hit ? hit.native : typed;\r\n}\r\n\r\nexport function isRTLText(s: string): boolean {\r\n for (const ch of s) {\r\n const code = ch.codePointAt(0) ?? 0;\r\n if (\r\n (code >= 0x0590 && code <= 0x08ff) || // Hebrew, Arabic, Syriac, Arabic Supplement, Thaana, NKo, Samaritan, Mandaic, Arabic Extended-A\r\n (code >= 0xfb1d && code <= 0xfdff) || // Hebrew/Arabic presentation forms A\r\n (code >= 0xfe70 && code <= 0xfeff) // Arabic presentation forms B\r\n ) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport const LANGUAGE_METAS: Record<string, { preparing: string; changeLang: string; rtl?: boolean; endonym?: string }> = {\r\n english: { preparing: 'Preparing in English…', changeLang: 'Change language', endonym: 'English' },\r\n swahili: { preparing: 'Inatayarisha kwa Kiswahili…', changeLang: 'Badilisha lugha', endonym: 'Kiswahili' },\r\n french: { preparing: 'Configuration en français…', changeLang: 'Changer de langue', endonym: 'Français' },\r\n spanish: { preparing: 'Configurando en español…', changeLang: 'Cambiar idioma', endonym: 'Español' },\r\n arabic: { preparing: 'جارٍ الإعداد باللغة العربية…', changeLang: 'تغيير اللغة', rtl: true, endonym: 'العربية' },\r\n portuguese: { preparing: 'Configurando em português…', changeLang: 'Alterar idioma', endonym: 'Português' },\r\n hindi: { preparing: 'हिन्दी में तैयार किया जा रहा है…', changeLang: 'भाषा बदलें', endonym: 'हिन्दी' },\r\n chinese: { preparing: '正在准备中文环境…', changeLang: '更改语言', endonym: '中文' },\r\n urdu: { preparing: 'اردو میں تیاری جاری ہے…', changeLang: 'زبان تبدیل کریں', rtl: true, endonym: 'اردو' },\r\n japanese: { preparing: '日本語を設定中…', changeLang: '言語を変更', endonym: '日本語' },\r\n german: { preparing: 'Wird auf Deutsch eingerichtet…', changeLang: 'Sprache ändern', endonym: 'Deutsch' },\r\n italian: { preparing: 'Configurazione in italiano…', changeLang: 'Cambia lingua', endonym: 'Italiano' },\r\n russian: { preparing: 'Настройка на русском…', changeLang: 'Изменить язык', endonym: 'Русский' },\r\n korean: { preparing: '한국어로 설정 중…', changeLang: '언어 변경', endonym: '한국어' },\r\n turkish: { preparing: 'Türkçe olarak hazırlanıyor…', changeLang: 'Dili değiştir', endonym: 'Türkçe' },\r\n vietnamese: { preparing: 'Đang thiết lập bằng Tiếng Việt…', changeLang: 'Đổi ngôn ngữ', endonym: 'Tiếng Việt' },\r\n indonesian: { preparing: 'Menyiapkan dalam Bahasa Indonesia…', changeLang: 'Ubah bahasa', endonym: 'Bahasa Indonesia' },\r\n polish: { preparing: 'Przygotowywanie w języku polskim…', changeLang: 'Zmień język', endonym: 'Polski' },\r\n dutch: { preparing: 'Instellen in het Nederlands…', changeLang: 'Taal wijzigen', endonym: 'Nederlands' },\r\n thai: { preparing: 'กำลังตั้งค่าเป็นภาษาไทย…', changeLang: 'เปลี่ยนภาษา', endonym: 'ไทย' },\r\n bengali: { preparing: 'বাংলায় প্রস্তুত করা হচ্ছে…', changeLang: 'ভাষা পরিবর্তন করুন', endonym: 'বাংলা' },\r\n tamil: { preparing: 'தமிழில் தயார் செய்யப்படுகிறது…', changeLang: 'மொழியை மாற்றவும்', endonym: 'தமிழ்' },\r\n telugu: { preparing: 'తెలుగులో సిద్ధం చేస్తోంది…', changeLang: 'భాషను మార్చండి', endonym: 'తెలుగు' },\r\n persian: { preparing: 'در حال آماده‌سازی به زبان فارسی…', changeLang: 'تغییر زبان', rtl: true, endonym: 'فارسی' },\r\n farsi: { preparing: 'در حال آماده‌سازی به زبان فارسی…', changeLang: 'تغییر زبان', rtl: true, endonym: 'فارسی' },\r\n greek: { preparing: 'Ρύθμιση στα ελληνικά…', changeLang: 'Αλλαγή γλώσσας', endonym: 'Ελληνικά' },\r\n hebrew: { preparing: 'מגדיר בעברית…', changeLang: 'שנה שפה', rtl: true, endonym: 'עברית' },\r\n swedish: { preparing: 'Ställer in på svenska…', changeLang: 'Byt språk', endonym: 'Svenska' },\r\n kikuyu: { preparing: 'Gĩkũyũ gĩgĩthondekwo…', changeLang: 'Cenjia rũthiomi', endonym: 'Gĩkũyũ' },\r\n gikuyu: { preparing: 'Gĩkũyũ gĩgĩthondekwo…', changeLang: 'Cenjia rũthiomi', endonym: 'Gĩkũyũ' },\r\n akan: { preparing: 'Yɛresiesie wɔ Akan mu…', changeLang: 'Sesa kasa', endonym: 'Akan' },\r\n twi: { preparing: 'Yɛresiesie wɔ Twi mu…', changeLang: 'Sesa kasa', endonym: 'Twi' },\r\n yoruba: { preparing: 'Ngbaradi ni Èdè Yorùbá…', changeLang: 'Yi ede pada', endonym: 'Èdè Yorùbá' },\r\n amharic: { preparing: 'በአማርኛ በመዘጋጀት ላይ…', changeLang: 'ቋንቋ ቀይር', endonym: 'አማርኛ' },\r\n somali: { preparing: 'Diyaarinta af Soomaali…', changeLang: 'Beddel luqadda', endonym: 'Af-Soomaali' },\r\n hausa: { preparing: 'Shirya cikin Hausa…', changeLang: 'Canja harshe', endonym: 'Hausa' },\r\n zulu: { preparing: 'Ilungiselela ngesiZulu…', changeLang: 'Shintsha ulimi', endonym: 'isiZulu' },\r\n oromo: { preparing: 'Afaan Oromootiin qophaa\\'aa jira…', changeLang: 'Afaan jijjiiri', endonym: 'Afaan Oromoo' },\r\n luganda: { preparing: 'Tuteekateeka mu Oluganda…', changeLang: 'Kyusa olulimi', endonym: 'Oluganda' },\r\n};\r\n\r\nfunction formatLangName(str: string): string {\r\n const trimmed = str.trim();\r\n if (!trimmed) return '…';\r\n return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);\r\n}\r\n\r\nexport function getLoadingMeta(lang: string | null | undefined) {\r\n if (!lang) {\r\n return {\r\n nativeName: '…',\r\n preparing: 'Preparing…',\r\n changeLang: '←',\r\n rtl: false,\r\n known: true,\r\n };\r\n }\r\n const l = lang.trim().toLowerCase();\r\n const hit = Object.entries(LANGUAGE_METAS).find(\r\n ([k, v]) => k === l || v.endonym?.toLowerCase() === l || endonymFor(k)?.toLowerCase() === l\r\n );\r\n if (hit) {\r\n return {\r\n nativeName: hit[1].endonym || endonymFor(lang) || formatLangName(lang),\r\n preparing: hit[1].preparing,\r\n changeLang: hit[1].changeLang,\r\n rtl: !!hit[1].rtl || isRTLText(hit[1].preparing),\r\n known: true,\r\n };\r\n }\r\n const rawName = endonymFor(lang) || lang;\r\n const nativeName = formatLangName(rawName);\r\n const rtl = isRTLText(nativeName);\r\n return {\r\n nativeName,\r\n preparing: `Preparing in ${nativeName}…`,\r\n changeLang: rtl ? 'تغيير' : 'Change',\r\n rtl,\r\n known: false,\r\n };\r\n}\r\n\r\nexport const LIVE_VOICES = [\r\n { name: 'Puck', label: 'Puck', gender: 'male' },\r\n { name: 'Charon', label: 'Charon', gender: 'male' },\r\n { name: 'Kore', label: 'Kore', gender: 'female' },\r\n { name: 'Aoede', label: 'Aoede', gender: 'female' },\r\n] as const;\r\n\r\nexport type { VoicePhase } from '../../utils/voiceSession';\r\n\r\nexport const VOICE_STORAGE_KEY = 'hsk-live-voice';\r\n\r\nexport const DEFAULT_UI_STRINGS = {\r\n langPlaceholder: 'Type your preferred language…',\r\n nameStepTitle: 'Nice to meet you.',\r\n nameStepLead: 'I can search, visualize, or capture anything for you — on this site or any other.',\r\n nameStepAsk: 'What should I call you?',\r\n namePlaceholder: 'Type your name…',\r\n attachImage: 'Attach a photo',\r\n vizUnavailable: 'The preview could not be loaded.',\r\n vizDisclaimerImage: 'Generated using Artificial Intelligence — colours, size and placement may differ from the real product.',\r\n vizDisclaimerVideo: 'Generated using Artificial Intelligence — colours, size and movement may differ from the real product.',\r\n calcDisclaimer: 'This is a calculation from live figures, not a guarantee — the market can move against it.',\r\n staleTitle: 'No longer available',\r\n staleRemoved: '{title} has been removed and is no longer on offer.',\r\n staleUnavailable: '{title} is currently unavailable.',\r\n keyPastePrompt: 'Paste your public id — or create one',\r\n keyPastePlaceholder: 'your public id…',\r\n keyUseMine: 'Use my id',\r\n keyCreating: 'Creating…',\r\n keyCreateNew: \"I'm new — create one\",\r\n keySecretTitle: 'Your secret — shown only once',\r\n keyDismiss: 'Dismiss',\r\n keyCopySecret: 'Copy secret',\r\n keyCopied: 'Copied',\r\n keySecretHint: 'Keep it private — use it to unlock your memory.',\r\n keyPublicTitle: 'Your public id',\r\n keyCopyId: 'Copy id',\r\n keyPublicHint: 'Paste this on any site to save to the same memory.',\r\n keyAutoHide: 'Hides automatically in {seconds}s.',\r\n greetReturning: 'Hi, {name}.',\r\n greetReturningLead: 'What can I find for you today?',\r\n howShouldResultsLook: 'How should results look?',\r\n entityLangIntro: 'I reply in {lang}. Product names stay as this site lists them — the details can too, or be translated.',\r\n asWritten: 'As written',\r\n inLanguage: 'In {lang}',\r\n namesAsWritten: 'Details exactly as the site lists them.',\r\n detailsTranslated: 'Details translated. Numbers and links stay exactly as listed.',\r\n entityLangPlaceholder: 'Pick one of the two cards above…',\r\n termsStepTitle: 'Privacy & Terms of Use',\r\n termsStepSubtitle: 'Transparent, anonymous, and zero-PII by design.',\r\n termsPiiTitle: 'Zero PII Collection',\r\n termsPiiDesc: 'We never collect or store personal identifying information (no emails, phone numbers, or real-world identities) from your chats or voice sessions.',\r\n termsSessionTitle: 'Anonymous Session Tokens',\r\n termsSessionDesc: 'Your session uses an anonymous client-side token solely to maintain context. It is never linked to your real identity.',\r\n termsMemoryTitle: 'Ephemeral Chats vs. Mimi Vault',\r\n termsMemoryDesc: 'Regular chats are ephemeral — closing the tab or clicking \"Clear Chat\" terminates them forever. Items you save with \"@kiku\" are encrypted and can be unlocked at mimi.akropolys.cloud with your Secret Access Key.',\r\n termsCookieTitle: 'Host Website Telemetry',\r\n termsCookieDesc: 'The host website where Kiku is embedded may collect cookies and analytics per their own cookie policy, outside Kiku\\'s control.',\r\n termsAgreeButton: 'Agree & Continue',\r\n termsAgreeCounting: 'Agree & Continue ({seconds}s)',\r\n termsPlaceholder: 'Please review and accept our Privacy & Terms above…',\r\n allSet: \"You're all set, {name}.\",\r\n replyingTranslated: 'Replying in {lang}, results translated too. Ask me anything.',\r\n replyingOriginal: 'Replying in {lang}, results as this site wrote them. Ask me anything.',\r\n defaultPlaceholder: 'Ask me anything…',\r\n footerHint: 'kiku · searches the whole catalogue in real time',\r\n voiceListening: 'Listening… tap the mic to stop',\r\n voiceSending: 'Got it — sending…',\r\n voiceModeStart: 'Hands-free conversation',\r\n voiceModeExit: 'Leave hands-free',\r\n voicePhaseListening: 'Listening',\r\n voicePhaseThinking: 'Thinking',\r\n voicePhaseSpeaking: 'Speaking',\r\n voiceHint: \"Just talk — I'll answer when you pause.\",\r\n voiceMuted: 'Muted',\r\n voiceMutedHint: 'Tap the microphone to speak again.',\r\n micDenied: 'Microphone blocked. Allow mic access for this site, then try again.',\r\n micInsecure: 'Voice needs a secure (https) connection.',\r\n micMissing: 'No microphone found.',\r\n micLangUnsupported: 'This browser cannot transcribe that language yet. Type instead.',\r\n micNetwork: \"Couldn't reach voice. Try again in a moment.\",\r\n voiceUnavailable: 'Voice is unavailable right now. Try again in a moment.',\r\n voiceLimitReached: \"You've used up today's voice time. It resets in a day — chat still works.\",\r\n voiceSiteLimit: 'Voice is out of allowance on this site for now. Chat still works.',\r\n voicePickerLabel: 'Choose a voice',\r\n micNoSpeech: \"Didn't catch anything. Try again, a little closer to the mic.\",\r\n micFailed: \"Couldn't hear that. Try again.\",\r\n clearChat: 'Clear chat',\r\n thinking: 'Thinking',\r\n thoughtForSeconds: 'Thought for {duration}',\r\n thoughtProcess: 'Thought process',\r\n captureAndRemember: 'kiku — capture & remember',\r\n captureCurrentPage: 'Capture current page',\r\n captureAll: 'Capture all ({count})',\r\n whatHaveYouSaved: 'What have you saved?',\r\n deleteThis: 'Delete this',\r\n errShopperReplyLimit: \"You've reached this site's reply limit for your account.\",\r\n errAccessRevoked: 'Your access to the assistant has been revoked by the store.',\r\n errAccountRequired: 'Please create an account to continue using the chat assistant.',\r\n errStreamInterrupted: 'The reply was interrupted. Please try again.',\r\n errNetwork: \"The assistant couldn't respond just now — please try again in a moment.\",\r\n errGeneric: 'Something went wrong. Please try again.',\r\n vizWorking: 'Visualizing…',\r\n vizMarkEdit: 'Mark & edit',\r\n markupTitle: 'Mark where you want the change',\r\n markupCancel: 'Cancel',\r\n markupSketch: 'Sketch',\r\n markupText: 'Text',\r\n markupEraser: 'Eraser',\r\n markupUndo: 'Undo',\r\n markupClear: 'Clear',\r\n markupSend: 'Send',\r\n markupTextHint: 'Type, then Enter',\r\n markupInstruction: 'Describe the change — e.g. add the sofa here',\r\n markupDialogLabel: 'Mark up image',\r\n markupColorLabel: 'Colour {colour}',\r\n markupError: \"Couldn't process this image — try a newer visualization.\",\r\n markupLoadError: \"This image can't be edited here.\",\r\n markupLoading: 'Loading image…',\r\n markupApplyMarks: 'Apply the change I marked on the image.',\r\n openMemory: 'Open my memory on mimi',\r\n errTooManyRequests: 'The assistant is currently receiving too many requests. Please try again in a few moments.',\r\n errTokenLimit: \"You've reached your usage limit. Please update your billing limits in your dashboard to continue.\",\r\n statusSent: 'Sent',\r\n statusStopped: 'Sent · reply stopped',\r\n queuedWaiting: 'Queued',\r\n queuedSendNow: 'Send now',\r\n jumpToLatest: 'Scroll to latest',\r\n timelineLabel: 'Questions in this conversation',\r\n voiceConnecting: 'Connecting — wait for the tone before speaking',\r\n stoppedByYou: 'You stopped this response.',\r\n stoppedInterrupted: 'This response was interrupted.',\r\n continueGenerating: 'Continue generating',\r\n generateResponse: 'Generate response',\r\n pillCompareTop2: 'Compare top 2',\r\n pillCompareTop2Query: 'Compare the {a} and {b}',\r\n pillMoreOn: 'More on {name}',\r\n pillMoreOnQuery: 'Tell me more about the {name}',\r\n pillUnder: 'Under {amount}',\r\n pillUnderQuery: 'Show me options under {amount}',\r\n pillSimilarOptions: 'Similar options',\r\n pillSimilarOptionsQuery: 'Show me more like the {name}',\r\n pillWhichBest: 'Which is best?',\r\n pillWhichBestQuery: 'Which one would you recommend and why?',\r\n pillFindAlternatives: 'Find alternatives',\r\n pillFindAlternativesQuery: 'What are good alternatives to the {name}?',\r\n pillShowPopular: 'Show popular items',\r\n pillShowPopularQuery: 'What are your most popular items?',\r\n pillRecommend: 'Recommend something',\r\n pillRecommendQuery: 'What do you recommend for me?',\r\n cardClickAnswer: 'The {name}',\r\n cardClickQuery: 'Tell me more about the {name}{price} — what are its key details, who is it best suited for, and what should I know?',\r\n displayCapture: 'capture {name}',\r\n displayCaptureAll: 'capture all ({count} items)',\r\n displayViewHistory: 'what have you saved?',\r\n displayDelete: 'delete this',\r\n} as const;\r\n\r\nexport type UIStringKey = keyof typeof DEFAULT_UI_STRINGS;\r\nexport type Translate = (key: UIStringKey, vars?: Record<string, string>) => string;\r\n\r\nexport const UIStringsContext = React.createContext<Translate>(\r\n (key, vars) => {\r\n let s: string = DEFAULT_UI_STRINGS[key];\r\n if (vars) for (const [k, v] of Object.entries(vars)) s = s.split(`{${k}}`).join(v);\r\n return s;\r\n }\r\n);\r\nexport const useT = () => React.useContext(UIStringsContext);\r\n\r\nexport function extractName(raw: string): string | null {\r\n let s = raw.trim();\r\n if (!s || s.length > 40 || s.includes('?')) return null;\r\n s = s.replace(/^(hi|hey|hello|yo)[,!.\\s]+/i, '');\r\n s = s.replace(/^(i['’]?m|im|my name is|call me|it['’]?s|this is|name['’]?s)\\s+/i, '');\r\n s = s.trim().replace(/[.!,]+$/, '');\r\n const words = s.split(/\\s+/);\r\n if (words.length === 0 || words.length > 3) return null;\r\n if (!/^[\\p{L}][\\p{L}\\-'’ ]{0,30}$/u.test(s)) return null;\r\n const q = s.toLowerCase();\r\n const queryish = ['phone', 'laptop', 'tv', 'cheap', 'best', 'under', 'buy', 'search', 'find', 'show', 'need', 'want', 'price', 'sofa', 'shoe', 'headphone', 'camera', 'gift', 'help'];\r\n if (queryish.some(w => q.includes(w))) return null;\r\n const name = words[0];\r\n return name.charAt(0).toUpperCase() + name.slice(1);\r\n}\r\n\r\nexport const SERVER_ERROR_STRINGS: Record<string, UIStringKey> = {\r\n shopper_reply_limit: 'errShopperReplyLimit',\r\n RATE_LIMIT_EXCEEDED: 'errShopperReplyLimit',\r\n access_revoked: 'errAccessRevoked',\r\n account_required: 'errAccountRequired',\r\n stream_interrupted: 'errStreamInterrupted',\r\n};\r\n\r\nexport const TERMINAL_ERROR_CODES = new Set(['account_required', 'access_revoked', 'shopper_reply_limit', 'RATE_LIMIT_EXCEEDED']);\r\n\r\nexport const isTerminalError = (code: string | null | undefined): boolean =>\r\n Boolean(code && TERMINAL_ERROR_CODES.has(code));\r\n\r\nexport const getFriendlyError = (err: any, tr: Translate) => {\r\n const code = err && typeof err === 'object' ? (err as { code?: string }).code : undefined;\r\n if (code && SERVER_ERROR_STRINGS[code]) return tr(SERVER_ERROR_STRINGS[code]);\r\n\r\n let str = '';\r\n if (typeof err === 'string') str = err;\r\n else if (err && typeof err === 'object' && err.message) str = err.message;\r\n else try { str = JSON.stringify(err); } catch { str = String(err); }\r\n\r\n const lower = str.toLowerCase();\r\n if (\r\n lower.includes('429') ||\r\n lower.includes('too many requests') ||\r\n lower.includes('requests per minute limit exceeded') ||\r\n lower.includes('too_many_requests_error') ||\r\n lower.includes('request_quota_exceeded') ||\r\n lower.includes('quota')\r\n ) {\r\n return tr('errTooManyRequests');\r\n }\r\n\r\n if (lower.includes('token limit')) {\r\n return tr('errTokenLimit');\r\n }\r\n\r\n if (lower.includes('failed to fetch') || lower.includes('networkerror') || lower.includes('request failed')) {\r\n return tr('errNetwork');\r\n }\r\n\r\n if (str) {\r\n try { console.warn('[kiku] untranslated error:', str); } catch { /* no console */ }\r\n }\r\n return tr('errGeneric');\r\n};\r\n\r\nexport const isSecureOrigin = () =>\r\n typeof window === 'undefined' || window.isSecureContext !== false;\r\n\r\nexport const KIKU_KEY_REVEAL_SECONDS = 15;\r\n\r\nexport interface ModalOrigin {\r\n x: number;\r\n y: number;\r\n r: number;\r\n top?: number;\r\n left?: number;\r\n width?: number;\r\n height?: number;\r\n borderRadius?: number;\r\n}\r\n\r\nexport interface ChatModalProps extends Pick<KikuButtonProps, 'title' | 'placeholder' | 'backdropColor' | 'backdropBlur' | 'onSelectSource' | 'defaultCurrency' | 'chips' | 'theme' | 'classNames' | 'enableVoice' | 'voiceLang' | 'enableVision' | 'visionCategoryHint' | 'enableAudioResponse' | 'ttsVoice' | 'autoSpeakResponses'> {\r\n theme?: 'light' | 'dark' | AkropolysTheme;\r\n classNames?: any;\r\n origin?: ModalOrigin | null;\r\n onClose: () => void;\r\n}\r\n","import React, { useState, useEffect, useLayoutEffect, useRef, useCallback, useId } from 'react';\r\nimport { flushSync } from 'react-dom';\r\nimport { THEMES, isThemeId, themeDef, DEFAULT_DARK, DEFAULT_LIGHT, type ThemeId } from './themes';\r\nimport { useKiku, ChatSource, ChatAttachment, CaptureTarget, subscribeLiveStream } from '@akropolys/sdk';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { cn } from '../../utils/cn';\r\nimport { resolveTheme } from '../../utils/theme';\r\nimport { useHostFontFace } from '../../utils/hostFont';\r\nimport { useDragToDismiss } from '../../utils/sheetGesture';\r\nimport { downscaleImage } from '../../utils/downscaleImage';\r\nimport { MarkupEditor } from '../MarkupEditor';\r\nimport type { KikuState } from '../KikuAvatar';\r\nimport KikuDoodles from '../KikuDoodles';\r\n\r\nimport {\r\n DEFAULT_CHIPS,\r\n UIStringsContext,\r\n extractName,\r\n ChatModalProps,\r\n} from './types';\r\nimport { useScriptFont } from './hooks/useScriptFont';\r\nimport { useChatScroll } from './hooks/useChatScroll';\r\nimport { useKikuKey } from './hooks/useKikuKey';\r\nimport { useChatCommands } from './hooks/useChatCommands';\r\nimport { useVoiceController } from './hooks/useVoiceController';\r\nimport { ChatTopbar } from './ChatTopbar';\r\nimport { CopyIcon, CheckIcon } from './icons';\r\nimport { OnboardingView } from './OnboardingView';\r\nimport { ChatMessages } from './ChatMessages';\r\nimport { ChatComposer } from './ChatComposer';\r\nimport { VoiceOverlay } from './VoiceOverlay';\r\nimport { LightboxModal } from './components/LightboxModal';\r\nimport { ConversationTimeline } from './components/ConversationTimeline';\r\n\r\nexport function ChatModal({\r\n title = 'kiku',\r\n placeholder = 'Ask me anything…',\r\n backdropColor,\r\n backdropBlur,\r\n onClose,\r\n onSelectSource,\r\n defaultCurrency = '',\r\n chips = DEFAULT_CHIPS,\r\n theme,\r\n classNames = {},\r\n enableVoice = false,\r\n voiceLang,\r\n enableVision = false,\r\n visionCategoryHint,\r\n enableAudioResponse = true,\r\n ttsVoice = 'Puck',\r\n autoSpeakResponses = true,\r\n origin,\r\n}: ChatModalProps) {\r\n const client = useAkropolysContext();\r\n const { messages, sources, loading, streaming, error, errorCode, lastAction, lastIntent, allowedActions, send, queuedMessage, sendQueuedNow, appendSpokenExchange, stop, stopped, interrupted, continueGenerating, reset, referencedIds } = useKiku();\r\n\r\n const [shopperName, setShopperNameState] = useState<string>(() => {\r\n try { return client.getShopperName?.() ?? ''; } catch { return ''; }\r\n });\r\n const [shopperLanguage, setShopperLanguageState] = useState<string>(() => {\r\n try { return client.getShopperLanguage?.() ?? ''; } catch { return ''; }\r\n });\r\n const [entityLangPref, setEntityLangPrefState] = useState<string>(() => {\r\n try { return client.getEntityLanguageMode?.() ?? ''; } catch { return ''; }\r\n });\r\n const [justCompleted, setJustCompleted] = useState(false);\r\n\r\n const {\r\n chromeReady,\r\n isRTL,\r\n speechLang,\r\n scriptFont,\r\n fontStack,\r\n isNonLatin,\r\n hostFontCovers,\r\n t,\r\n tNode,\r\n } = useScriptFont({ shopperLanguage, theme });\r\n\r\n const discussedSources = React.useMemo(() => {\r\n const byRef = sources.filter(s => s.id && referencedIds.includes(s.id));\r\n const answer = [...messages].reverse().find(m => m.role === 'assistant')?.content ?? '';\r\n if (!answer) return byRef;\r\n const seen = new Set(byRef.map(s => s.id));\r\n const hay = answer.toLowerCase().replace(/\\s+/g, ' ');\r\n const aliases = (name: string) => {\r\n const n = String(name ?? '').toLowerCase().replace(/\\s+/g, ' ').trim();\r\n const w = n.split(' ');\r\n const out = [n];\r\n if (w.length > 3) out.push(w.slice(0, 3).join(' '));\r\n if (w.length > 4) out.push(w.slice(0, 4).join(' '));\r\n return out.filter(a => a.length >= 5);\r\n };\r\n const named = sources.filter(s =>\r\n s.id && !seen.has(s.id) && aliases(s.name).some(a => hay.includes(a))\r\n );\r\n return [...byRef, ...named];\r\n }, [sources, referencedIds, messages]);\r\n\r\n const captureAllowed = allowedActions === null || allowedActions.includes('capture');\r\n const [input, setInput] = useState('');\r\n const [showKikuPicker, setShowKikuPicker] = useState(false);\r\n const [showAtPicker, setShowAtPicker] = useState(false);\r\n const [attachments, setAttachments] = useState<ChatAttachment[]>([]);\r\n const imageInputRef = useRef<HTMLInputElement>(null);\r\n const [vizState, setVizState] = useState<Record<string, 'ok' | 'err'>>({});\r\n const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);\r\n const [markupSrc, setMarkupSrc] = useState<string | null>(null);\r\n\r\n const [termsAgreed, setTermsAgreed] = useState<boolean>(() => {\r\n if (typeof window === 'undefined') return false;\r\n try {\r\n return localStorage.getItem('akropolys_terms_agreed') === 'true';\r\n } catch {\r\n return false;\r\n }\r\n });\r\n\r\n const onboarding = messages.length === 0;\r\n const awaitingLang = onboarding && !shopperLanguage;\r\n const awaitingName = onboarding && !!shopperLanguage && !shopperName;\r\n const awaitingEntityLang = onboarding && !!shopperLanguage && !!shopperName && !entityLangPref;\r\n const awaitingConsent = onboarding && !!shopperLanguage && !!shopperName && !!entityLangPref && !termsAgreed;\r\n const inOnboarding = awaitingLang || awaitingName || awaitingEntityLang || awaitingConsent;\r\n\r\n const hasLiveData = React.useMemo(\r\n () => messages.some(m => (m as any).liveKeys?.length > 0),\r\n [messages]\r\n );\r\n useEffect(() => {\r\n if (!hasLiveData) return;\r\n return subscribeLiveStream({ client });\r\n }, [hasLiveData, client]);\r\n\r\n const [isNarrow, setIsNarrow] = useState(false);\r\n useEffect(() => {\r\n const mq = window.matchMedia?.('(max-width: 768px)');\r\n if (!mq) return;\r\n const apply = () => setIsNarrow(mq.matches);\r\n apply();\r\n mq.addEventListener?.('change', apply);\r\n return () => mq.removeEventListener?.('change', apply);\r\n }, []);\r\n\r\n const chooseLanguage = (lang: string) => {\r\n const v = lang.trim();\r\n if (!v) {\r\n try { client.setShopperLanguage?.(''); } catch { }\r\n setShopperLanguageState('');\r\n return;\r\n }\r\n try { client.setShopperLanguage?.(v); } catch { }\r\n setShopperLanguageState(v);\r\n setJustCompleted(false);\r\n };\r\n\r\n const chooseEntityLang = (mode: 'translated' | 'original') => {\r\n try { client.setEntityLanguageMode?.(mode); } catch { }\r\n setEntityLangPrefState(mode);\r\n if (termsAgreed) {\r\n setJustCompleted(true);\r\n }\r\n };\r\n\r\n const agreeTerms = () => {\r\n try {\r\n localStorage.setItem('akropolys_terms_agreed', 'true');\r\n } catch { /* noop */ }\r\n setTermsAgreed(true);\r\n setJustCompleted(true);\r\n };\r\n\r\n const activeTitle = title === 'kiku' ? (t('nameStepTitle') ? 'kiku' : title) : title;\r\n const activePlaceholder =\r\n awaitingLang ? t('langPlaceholder')\r\n : awaitingName ? t('namePlaceholder')\r\n : awaitingEntityLang ? t('entityLangPlaceholder')\r\n : awaitingConsent ? t('termsPlaceholder')\r\n : (placeholder === 'Ask me anything…' ? t('defaultPlaceholder') : placeholder);\r\n\r\n const activeChips = !chips || chips === DEFAULT_CHIPS ? [] : (Array.isArray(chips) ? chips : []);\r\n const onboardingMood: KikuState =\r\n awaitingLang ? 'curious'\r\n : awaitingName ? 'welcoming'\r\n : awaitingEntityLang ? 'guiding'\r\n : awaitingConsent ? 'focused'\r\n : 'happy';\r\n\r\n const [currentTheme, setCurrentTheme] = useState<ThemeId>(() => {\r\n if (isThemeId(theme)) return theme;\r\n if (typeof window !== 'undefined') {\r\n const saved = localStorage.getItem('akropolys_theme');\r\n if (isThemeId(saved)) return saved;\r\n return window.matchMedia?.('(prefers-color-scheme: light)').matches ? DEFAULT_LIGHT : DEFAULT_DARK;\r\n }\r\n return DEFAULT_DARK;\r\n });\r\n\r\n // Fluid theme switch: updates active theme and lets CSS & canvas glyphs animate live\r\n const handleToggleTheme = (next: ThemeId, alsoCloseMenu = false) => {\r\n setCurrentTheme(next);\r\n if (alsoCloseMenu) {\r\n setThemeMenuOpen(false);\r\n setThemeMenuClosing(false);\r\n }\r\n try { localStorage.setItem('akropolys_theme', next); } catch { /* noop */ }\r\n };\r\n\r\n const { vars: customStyles } = resolveTheme(theme);\r\n const hskThemeAttr = currentTheme;\r\n useHostFontFace(theme);\r\n\r\n const handleSendRef = useRef<(text: string) => void>(() => {});\r\n\r\n const handleSend = async (text?: string, extraAttachments?: ChatAttachment[], forcedIntent?: string, captureTargets?: CaptureTarget[]) => {\r\n const raw = (text ?? input).trim();\r\n if (!raw || !chromeReady || queuedMessage) return;\r\n\r\n if (awaitingName) {\r\n const name = extractName(raw) || raw.slice(0, 40);\r\n try { client.setShopperName?.(name); } catch { }\r\n setShopperNameState(name);\r\n setInput('');\r\n return;\r\n }\r\n if (awaitingLang) {\r\n chooseLanguage(raw);\r\n setInput('');\r\n return;\r\n }\r\n if (awaitingEntityLang) {\r\n setInput('');\r\n return;\r\n }\r\n\r\n setShowKikuPicker(false);\r\n setShowAtPicker(false);\r\n setInput('');\r\n const toSend = extraAttachments ?? attachments;\r\n setAttachments([]);\r\n await send(raw, raw, toSend.length > 0 ? toSend : undefined, forcedIntent, captureTargets);\r\n };\r\n\r\n const retryLastMessage = useCallback(async () => {\r\n const lastUserMsg = [...messages].reverse().find(m => m.role === 'user');\r\n if (lastUserMsg) await handleSend(lastUserMsg.content);\r\n }, [messages]);\r\n\r\n const {\r\n keyInput,\r\n setKeyInput,\r\n keyPhase,\r\n setKeyPhase,\r\n mintedKey,\r\n setMintedKey,\r\n mintedPub,\r\n setMintedPub,\r\n copied,\r\n keyCountdown,\r\n minting,\r\n copyValue,\r\n handleUseExistingKey,\r\n handleCreateKey,\r\n } = useKikuKey(lastAction, retryLastMessage);\r\n\r\n const getStoredKikuId = useCallback((): string => {\r\n if (typeof window === 'undefined') return 'N/A';\r\n try {\r\n const fromSession = sessionStorage.getItem('akropolys_kiku_pub') || sessionStorage.getItem('kiku_pub');\r\n if (fromSession) return fromSession;\r\n const fromLocal = localStorage.getItem('akropolys_kiku_pub') || localStorage.getItem('kiku_pub') || localStorage.getItem('kiku_id');\r\n if (fromLocal) return fromLocal;\r\n const match = document.cookie.match(/(?:^|;\\s*)(?:akropolys_kiku_pub|kiku_pub|kiku_id)=([^;]+)/);\r\n if (match) return decodeURIComponent(match[1]);\r\n } catch {}\r\n return 'N/A';\r\n }, []);\r\n\r\n const displayKikuPub = mintedPub ?? client?.getKikuPub?.() ?? getStoredKikuId();\r\n\r\n const {\r\n handleKikuCapture,\r\n handleKikuCaptureAll,\r\n handleKikuViewHistory,\r\n handleKikuDelete,\r\n } = useChatCommands({\r\n attachments,\r\n setAttachments,\r\n setInput,\r\n send,\r\n defaultCurrency,\r\n t,\r\n });\r\n\r\n const {\r\n voiceMode,\r\n voicePhase,\r\n voiceConnecting,\r\n voiceError,\r\n setVoiceError,\r\n voiceMuted,\r\n setVoiceMuted,\r\n voiceSecondsLeft,\r\n voiceBlocked,\r\n liveVoiceName,\r\n chooseVoice,\r\n canConverse,\r\n startVoice,\r\n stopVoice,\r\n voice,\r\n live,\r\n } = useVoiceController({\r\n voiceLang,\r\n speechLang,\r\n shopperLanguage,\r\n ttsVoice,\r\n handleSendUtterance: (text) => handleSendRef.current(text),\r\n appendSpokenExchange,\r\n });\r\n\r\n const panelRef = useRef<HTMLDivElement>(null);\r\n const [themeMenuOpen, setThemeMenuOpen] = useState(false);\r\n const [themeMenuClosing, setThemeMenuClosing] = useState(false);\r\n const themeMenuCloseTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const themeMenuRef = useRef<HTMLDivElement>(null);\r\n const mobileThemeRef = useRef<HTMLDivElement>(null);\r\n const messageRefs = useRef<(HTMLDivElement | null)[]>([]);\r\n const textareaRef = useRef<HTMLTextAreaElement>(null);\r\n const bottomRef = useRef<HTMLDivElement>(null);\r\n const overlayRef = useRef<HTMLDivElement>(null);\r\n const gooId = `hsk-goo-${useId()}`;\r\n\r\n // keeps the panel mounted long enough to morph back into the pill\r\n const closeThemeMenu = useCallback(() => {\r\n if (themeMenuCloseTimer.current) return;\r\n setThemeMenuClosing(true);\r\n themeMenuCloseTimer.current = setTimeout(() => {\r\n setThemeMenuOpen(false);\r\n setThemeMenuClosing(false);\r\n themeMenuCloseTimer.current = null;\r\n }, 200);\r\n }, []);\r\n\r\n useEffect(() => () => {\r\n if (themeMenuCloseTimer.current) clearTimeout(themeMenuCloseTimer.current);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!themeMenuOpen) return;\r\n const handleOutside = (e: MouseEvent | TouchEvent) => {\r\n const path = (e.composedPath ? e.composedPath() : []) as EventTarget[];\r\n const isInsideRail = themeMenuRef.current && (path.includes(themeMenuRef.current) || themeMenuRef.current.contains(e.target as Node));\r\n const isInsideMobile = mobileThemeRef.current && (path.includes(mobileThemeRef.current) || mobileThemeRef.current.contains(e.target as Node));\r\n const targetEl = e.target as HTMLElement | null;\r\n const isInsideTopbarMark = targetEl?.closest?.('.hsk-cb-topbar-mark');\r\n const isInsideOoze = targetEl?.closest?.('.hsk-cb-topbar-ooze-menu') || path.some((el: any) => el?.classList?.contains?.('hsk-cb-topbar-ooze-menu'));\r\n\r\n if (isInsideRail || isInsideMobile || isInsideTopbarMark || isInsideOoze) {\r\n return;\r\n }\r\n closeThemeMenu();\r\n };\r\n document.addEventListener('mousedown', handleOutside);\r\n document.addEventListener('touchstart', handleOutside, { passive: true });\r\n return () => {\r\n document.removeEventListener('mousedown', handleOutside);\r\n document.removeEventListener('touchstart', handleOutside);\r\n };\r\n }, [themeMenuOpen]);\r\n\r\n const {\r\n msgsContainerRef,\r\n lastExternalScrollRef,\r\n showJumpToBottom,\r\n scrollProgress,\r\n activeMsgIdx,\r\n unreadBelow,\r\n jumpToMessage,\r\n jumpToBottom,\r\n } = useChatScroll({ messages, loading, messageRefs });\r\n\r\n useDragToDismiss({\r\n panel: useCallback(() => panelRef.current, []),\r\n scroller: useCallback(() => msgsContainerRef.current, []),\r\n onDismiss: onClose,\r\n quiescent: useCallback(() => performance.now() - lastExternalScrollRef.current > 90, []),\r\n });\r\n\r\n useEffect(() => {\r\n const prev = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n return () => { document.body.style.overflow = prev; };\r\n }, []);\r\n\r\n useEffect(() => {\r\n const vv = window.visualViewport;\r\n if (!vv) return;\r\n const root = document.documentElement;\r\n const apply = () => { root.style.setProperty('--hsk-vvh', `${vv.height}px`); };\r\n apply();\r\n vv.addEventListener('resize', apply);\r\n vv.addEventListener('scroll', apply);\r\n return () => {\r\n vv.removeEventListener('resize', apply);\r\n vv.removeEventListener('scroll', apply);\r\n root.style.removeProperty('--hsk-vvh');\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n const h = (e: KeyboardEvent) => {\r\n if (e.key !== 'Escape') return;\r\n if (lightboxSrc) { setLightboxSrc(null); return; }\r\n onClose();\r\n };\r\n document.addEventListener('keydown', h);\r\n return () => document.removeEventListener('keydown', h);\r\n }, [lightboxSrc, onClose]);\r\n\r\n const handleReset = useCallback(() => {\r\n reset();\r\n setKeyPhase('idle');\r\n }, [reset, setKeyPhase]);\r\n\r\n const handleSourceClick = (src: ChatSource) => {\r\n onSelectSource?.(src);\r\n const lastAssistant = [...messages].reverse().find(m => m.role === 'assistant');\r\n if (lastAssistant && lastAssistant.content.trim().endsWith('?')) {\r\n send(t('cardClickAnswer', { name: src.name }));\r\n return;\r\n }\r\n const price = src.price ? ` (${src.currency ?? defaultCurrency} ${src.price})` : '';\r\n send(t('cardClickQuery', { name: src.name, price }));\r\n };\r\n\r\n const handleSelectExtension = (ext: string) => {\r\n setInput(ext + ' ');\r\n setShowAtPicker(false);\r\n setShowKikuPicker(true);\r\n if (textareaRef.current) textareaRef.current.focus();\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n if (e.key === 'Escape' && showKikuPicker) { e.preventDefault(); setShowKikuPicker(false); return; }\r\n if (e.key === 'Escape' && showAtPicker) { e.preventDefault(); setShowAtPicker(false); return; }\r\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) { e.preventDefault(); handleSend(); }\r\n };\r\n\r\n const composerHeight = useRef(28);\r\n const singleRowFieldWidth = useRef(280);\r\n const measureCanvasRef = useRef<HTMLCanvasElement | null>(null);\r\n\r\n const getTextWidth = (text: string, font: string): number => {\r\n try {\r\n if (!measureCanvasRef.current && typeof document !== 'undefined') {\r\n measureCanvasRef.current = document.createElement('canvas');\r\n }\r\n const ctx = measureCanvasRef.current?.getContext('2d');\r\n if (!ctx) return text.length * 8.5;\r\n ctx.font = font;\r\n return ctx.measureText(text).width;\r\n } catch {\r\n return text.length * 8.5;\r\n }\r\n };\r\n\r\n const autoGrow = (el: HTMLTextAreaElement) => {\r\n const box = el.closest('.hsk-cb-input-box') as HTMLElement | null;\r\n if (!box) return;\r\n\r\n const val = el.value;\r\n const isCurrentlyExpanded = box.dataset.expanded === 'true';\r\n\r\n if (!isCurrentlyExpanded && el.clientWidth > 50) {\r\n singleRowFieldWidth.current = el.clientWidth;\r\n }\r\n\r\n const cs = window.getComputedStyle(el);\r\n const font = cs.font || `${cs.fontSize || '16px'} ${cs.fontFamily || 'Geist, sans-serif'}`;\r\n const textWidth = getTextWidth(val, font);\r\n\r\n const threshold = Math.max(120, singleRowFieldWidth.current - 14);\r\n const hasNewline = val.includes('\\n');\r\n const shouldExpand = Boolean(val && (hasNewline || textWidth > threshold));\r\n\r\n if (box.dataset.expanded !== (shouldExpand ? 'true' : 'false')) {\r\n box.dataset.expanded = shouldExpand ? 'true' : 'false';\r\n }\r\n\r\n if (!val) {\r\n composerHeight.current = 28;\r\n el.style.height = '';\r\n return;\r\n }\r\n\r\n if (!shouldExpand) {\r\n composerHeight.current = 28;\r\n el.style.height = '';\r\n return;\r\n }\r\n\r\n el.style.height = 'auto';\r\n const targetHeight = Math.max(28, Math.min(el.scrollHeight, 140));\r\n composerHeight.current = targetHeight;\r\n el.style.height = `${targetHeight}px`;\r\n };\r\n\r\n useEffect(() => {\r\n if (textareaRef.current) autoGrow(textareaRef.current);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [input]);\r\n\r\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const val = e.target.value;\r\n setInput(val);\r\n if (voiceError) setVoiceError('');\r\n const trimmed = val.trim();\r\n setShowAtPicker(trimmed === '@');\r\n setShowKikuPicker(/^@kiku\\s*$/i.test(trimmed));\r\n };\r\n\r\n useEffect(() => {\r\n handleSendRef.current = (text: string) => { void handleSend(text); };\r\n });\r\n\r\n const handleImageFiles = async (files: FileList | null) => {\r\n if (!files || files.length === 0) return;\r\n const list = Array.from(files);\r\n for (const file of list) {\r\n if (!file.type.startsWith('image/')) continue;\r\n try {\r\n const dataUrl = await downscaleImage(file);\r\n setAttachments(prev => [...prev, { type: 'image', data: dataUrl }]);\r\n } catch { }\r\n }\r\n };\r\n\r\n const removeAttachment = (idx: number) => {\r\n setAttachments(prev => prev.filter((_, i) => i !== idx));\r\n };\r\n\r\n const shownSources = (live.sources?.length ?? 0) > 0 ? live.sources : discussedSources;\r\n const hasTranslucentBackdrop = backdropColor && (backdropColor.includes('rgba') || backdropColor.includes('hsla') || backdropColor === 'transparent');\r\n const backdropFilterStyle = (backdropBlur || hasTranslucentBackdrop) ? {\r\n backdropFilter: `blur(${typeof backdropBlur === 'number' ? `${backdropBlur}px` : (backdropBlur || '20px')})`,\r\n WebkitBackdropFilter: `blur(${typeof backdropBlur === 'number' ? `${backdropBlur}px` : (backdropBlur || '20px')})`,\r\n } : {};\r\n const halted = (stopped || interrupted) && !loading && !streaming;\r\n\r\n const displayMessages = React.useMemo(() => {\r\n const inFlight = loading || streaming;\r\n return messages.filter((m, i) => {\r\n if (m.role !== 'assistant') return true;\r\n const isLastMsg = i === messages.length - 1;\r\n if (isLastMsg && inFlight) return true;\r\n const hasBody = !!m.content || !!m.visualization || m.visualizing ||\r\n (m.knowledgeImages?.length ?? 0) > 0 || (m.referencedIds?.length ?? 0) > 0;\r\n return hasBody;\r\n });\r\n }, [messages, loading, streaming]);\r\n\r\n const timelineItems = React.useMemo(\r\n () => displayMessages\r\n .map((m, idx) => ({ m, idx }))\r\n .filter(({ m }) => m.role === 'user' && !!m.content.trim())\r\n .map(({ m, idx }) => {\r\n const clean = m.content.replace(/^@kiku\\s*/i, '').replace(/\\s+/g, ' ').trim();\r\n return { idx, text: clean.length > 30 ? clean.slice(0, 29).trimEnd() + '…' : clean };\r\n }),\r\n [displayMessages]\r\n );\r\n\r\n const haltedEmpty =\r\n halted && displayMessages[displayMessages.length - 1]?.role !== 'assistant';\r\n\r\n const mountTimeRef = useRef(Date.now());\r\n useEffect(() => {\r\n mountTimeRef.current = Date.now();\r\n }, []);\r\n\r\n return (\r\n <UIStringsContext.Provider value={t}>\r\n <div\r\n ref={overlayRef}\r\n className={cn(\"hsk-cb-overlay\", origin && \"hsk-cb-overlay--grows\", classNames.overlay)}\r\n onPointerDown={e => {\r\n if (e.target === e.currentTarget) {\r\n (overlayRef.current as any)._ptrDown = true;\r\n }\r\n }}\r\n onClick={e => {\r\n if (e.target === e.currentTarget && (overlayRef.current as any)?._ptrDown && Date.now() - mountTimeRef.current > 200) {\r\n onClose();\r\n }\r\n if (overlayRef.current) (overlayRef.current as any)._ptrDown = false;\r\n }}\r\n data-hsk-theme={hskThemeAttr}\r\n style={{\r\n ...(backdropFilterStyle),\r\n ...(backdropColor ? { background: backdropColor } : {}),\r\n ...(origin ? {\r\n '--hsk-ox': `${origin.x}px`,\r\n '--hsk-oy': `${origin.y}px`,\r\n '--hsk-or': `${Math.ceil(origin.r)}px`,\r\n '--hsk-bt': `${Math.round(origin.top ?? origin.y)}px`,\r\n '--hsk-bl': `${Math.round(origin.left ?? origin.x)}px`,\r\n '--hsk-bw': `${Math.round(origin.width ?? 0)}px`,\r\n '--hsk-bh': `${Math.round(origin.height ?? 0)}px`,\r\n '--hsk-bbr': `${Math.round(origin.borderRadius ?? 12)}px`,\r\n } as React.CSSProperties : {}),\r\n ...customStyles,\r\n }}\r\n >\r\n <div\r\n ref={panelRef}\r\n className={cn(\"hsk-cb-panel\", classNames.panel)}\r\n dir={isRTL ? 'rtl' : 'ltr'}\r\n data-script={isNonLatin ? 'nonlatin' : 'latin'}\r\n data-host-font={hostFontCovers ? 'covers' : 'gap'}\r\n data-nastaliq={(scriptFont?.family === 'Noto Nastaliq Urdu' || shopperLanguage?.toLowerCase() === 'urdu' || shopperLanguage?.toLowerCase() === 'ur' || shopperLanguage === 'اردو') ? 'true' : undefined}\r\n style={fontStack ? ({ '--hsk-font': fontStack } as React.CSSProperties) : undefined}\r\n onClick={e => {\r\n e.stopPropagation();\r\n const target = e.target as HTMLElement;\r\n if (target.tagName === 'IMG' && (target.classList.contains('hsk-markdown-img') || target.classList.contains('hsk-cb-user-img-thumb'))) {\r\n const src = (target as HTMLImageElement).src;\r\n if (src) setLightboxSrc(src);\r\n }\r\n }}\r\n >\r\n <LightboxModal src={lightboxSrc} onClose={() => setLightboxSrc(null)} />\r\n\r\n {markupSrc && (\r\n <div className=\"hsk-markup-overlay\">\r\n <MarkupEditor\r\n src={markupSrc}\r\n t={t as (key: string, vars?: Record<string, string>) => string}\r\n onCancel={() => setMarkupSrc(null)}\r\n onSend={(dataUrl, instruction, marks, preview) => {\r\n setMarkupSrc(null);\r\n handleSend(\r\n instruction || t('markupApplyMarks'),\r\n [{ type: 'image', data: dataUrl, annotated: true, marks, instructed: !!instruction, preview }],\r\n );\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"hsk-cb-main\">\r\n <KikuDoodles seed={(client as any)?.api?.siteId ?? ''} theme={hskThemeAttr} dir={isRTL ? 'rtl' : 'ltr'} />\r\n\r\n <ChatTopbar\r\n title={activeTitle}\r\n hasMessages={messages.length > 0}\r\n avatarState={streaming ? 'speaking' : loading ? 'thinking' : 'idle'}\r\n unread={unreadBelow}\r\n awayFromBottom={showJumpToBottom}\r\n themeMenuOpen={themeMenuOpen}\r\n themeMenuClosing={themeMenuClosing}\r\n isNarrow={isNarrow}\r\n currentTheme={currentTheme}\r\n onJumpToLatest={jumpToBottom}\r\n onReset={handleReset}\r\n onClose={onClose}\r\n onToggleThemeMenu={() => (themeMenuOpen ? closeThemeMenu() : setThemeMenuOpen(true))}\r\n onSelectTheme={(t) => { handleToggleTheme(t, true); }}\r\n />\r\n\r\n <div className=\"hsk-cb-msgs\" ref={msgsContainerRef as any}>\r\n {displayMessages.length === 0 ? (\r\n <OnboardingView\r\n inOnboarding={inOnboarding}\r\n justCompleted={justCompleted}\r\n onboardingMood={onboardingMood}\r\n awaitingLang={awaitingLang}\r\n awaitingName={awaitingName}\r\n awaitingEntityLang={awaitingEntityLang}\r\n awaitingConsent={awaitingConsent}\r\n termsAgreed={termsAgreed}\r\n shopperLanguage={shopperLanguage}\r\n shopperName={shopperName}\r\n entityLangPref={entityLangPref}\r\n chromeReady={chromeReady}\r\n activeChips={activeChips}\r\n t={t}\r\n tNode={tNode}\r\n chooseLanguage={chooseLanguage}\r\n chooseEntityLang={chooseEntityLang}\r\n agreeTerms={agreeTerms}\r\n handleSend={handleSend}\r\n />\r\n ) : (\r\n <ChatMessages\r\n displayMessages={displayMessages}\r\n messageRefs={messageRefs}\r\n isNarrow={isNarrow}\r\n loading={loading}\r\n streaming={streaming}\r\n sources={sources}\r\n referencedIds={referencedIds}\r\n discussedSources={discussedSources}\r\n lastIntent={lastIntent}\r\n lastAction={lastAction}\r\n defaultCurrency={defaultCurrency}\r\n stopped={stopped}\r\n interrupted={interrupted}\r\n halted={halted}\r\n haltedEmpty={haltedEmpty}\r\n error={error}\r\n errorCode={errorCode}\r\n keyPhase={keyPhase}\r\n keyInput={keyInput}\r\n setKeyInput={setKeyInput}\r\n mintedKey={mintedKey}\r\n setMintedKey={setMintedKey}\r\n mintedPub={mintedPub}\r\n setMintedPub={setMintedPub}\r\n minting={minting}\r\n copied={copied}\r\n keyCountdown={keyCountdown}\r\n handleUseExistingKey={handleUseExistingKey}\r\n handleCreateKey={handleCreateKey}\r\n copyValue={copyValue}\r\n queuedMessage={queuedMessage}\r\n sendQueuedNow={sendQueuedNow}\r\n setLightboxSrc={setLightboxSrc}\r\n setMarkupSrc={setMarkupSrc}\r\n handleSend={handleSend}\r\n handleSourceClick={handleSourceClick}\r\n continueGenerating={continueGenerating}\r\n t={t}\r\n bottomRef={bottomRef}\r\n vizState={vizState}\r\n setVizState={setVizState}\r\n messages={messages}\r\n />\r\n )}\r\n </div>\r\n\r\n <ChatComposer\r\n gooId={gooId}\r\n input={input}\r\n setInput={setInput}\r\n showKikuPicker={showKikuPicker}\r\n setShowKikuPicker={setShowKikuPicker}\r\n showAtPicker={showAtPicker}\r\n setShowAtPicker={setShowAtPicker}\r\n captureAllowed={captureAllowed}\r\n discussedSources={discussedSources}\r\n defaultCurrency={defaultCurrency}\r\n handleSelectExtension={handleSelectExtension}\r\n handleKikuCapture={handleKikuCapture}\r\n handleKikuCaptureAll={handleKikuCaptureAll}\r\n handleKikuViewHistory={handleKikuViewHistory}\r\n handleKikuDelete={handleKikuDelete}\r\n attachments={attachments}\r\n removeAttachment={removeAttachment}\r\n chromeLoading={!chromeReady}\r\n imageInputRef={imageInputRef}\r\n handleImageFiles={handleImageFiles}\r\n enableVision={enableVision}\r\n enableVoice={enableVoice}\r\n canConverse={canConverse}\r\n voiceMode={voiceMode}\r\n startVoice={startVoice}\r\n stopVoice={stopVoice}\r\n voiceBlocked={voiceBlocked}\r\n textareaRef={textareaRef}\r\n classNames={classNames}\r\n handleInput={handleInput}\r\n handleKeyDown={handleKeyDown}\r\n voice={voice}\r\n voicePhase={voicePhase}\r\n activePlaceholder={activePlaceholder}\r\n loading={loading}\r\n streaming={streaming}\r\n stop={stop}\r\n handleSend={handleSend}\r\n voiceError={voiceError}\r\n setVoiceError={setVoiceError}\r\n shopperLanguage={shopperLanguage}\r\n t={t}\r\n />\r\n </div>\r\n\r\n <ConversationTimeline\r\n items={timelineItems}\r\n activeIdx={activeMsgIdx}\r\n progress={scrollProgress}\r\n onJump={jumpToMessage}\r\n side={isRTL ? 'left' : 'right'}\r\n />\r\n\r\n <div className={cn(\"hsk-cb-kiku-id-rail\", isRTL ? \"hsk-cb-kiku-id-rail--right\" : \"hsk-cb-kiku-id-rail--left\")}>\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-kiku-id-pill\"\r\n onClick={() => displayKikuPub !== 'N/A' && copyValue(displayKikuPub, 'pub')}\r\n title={t('keyCopyId')}\r\n >\r\n <span className=\"hsk-cb-kiku-id-rail-val\">{displayKikuPub}</span>\r\n {copied === 'pub' ? <CheckIcon /> : <CopyIcon />}\r\n </button>\r\n\r\n <div className={cn(\"hsk-cb-theme-squircle-wrap\", themeMenuOpen && \"is-open\", themeMenuClosing && \"is-closing\")} ref={themeMenuRef}>\r\n {!themeMenuOpen ? (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-theme-squircle-trigger\"\r\n onClick={() => setThemeMenuOpen(true)}\r\n aria-label=\"Themes\"\r\n aria-expanded=\"false\"\r\n >\r\n <span className=\"hsk-cb-theme-trigger-icon\">\r\n {React.createElement(themeDef(currentTheme).Icon)}\r\n </span>\r\n <span className=\"hsk-cb-theme-trigger-label\">\r\n {themeDef(currentTheme).label}\r\n </span>\r\n </button>\r\n ) : (\r\n <div className=\"hsk-cb-theme-2x2-grid\" role=\"dialog\" aria-label=\"Theme selector\">\r\n {THEMES.map(({ id, label, Icon }) => (\r\n <button\r\n key={id}\r\n type=\"button\"\r\n className={cn(\"hsk-cb-theme-grid-item\", currentTheme === id && \"is-active\")}\r\n onClick={(e) => { e.stopPropagation(); handleToggleTheme(id, true); }}\r\n >\r\n <Icon />\r\n <span>{label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {voiceMode === 'converse' && (\r\n <VoiceOverlay\r\n siteId={(client as any)?.api?.siteId ?? ''}\r\n themeAttr={hskThemeAttr}\r\n stopVoice={stopVoice}\r\n chooseVoice={chooseVoice}\r\n liveVoiceName={liveVoiceName}\r\n voiceSecondsLeft={voiceSecondsLeft}\r\n voiceConnecting={voiceConnecting}\r\n voicePhase={voicePhase}\r\n live={live}\r\n voiceMuted={voiceMuted}\r\n setVoiceMuted={setVoiceMuted}\r\n shownSources={shownSources}\r\n onSelectSource={onSelectSource}\r\n defaultCurrency={defaultCurrency}\r\n voiceError={voiceError}\r\n t={t}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n </UIStringsContext.Provider>\r\n );\r\n}\r\n","import React from 'react';\r\nimport { cn } from '../../utils/cn';\r\n\r\nexport const KikuIcon = ({ className, size = 18, tight = false }: { className?: string; size?: number; tight?: boolean }) => (\r\n <svg\r\n className={cn(\"hsk-brand-mark\", className)}\r\n width={size}\r\n height={size}\r\n viewBox={tight ? \"10.2 17.4 79.5 79.5\" : \"0 0 100 100\"}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-label=\"kiku\"\r\n >\r\n <g transform=\"translate(22.7 19) scale(0.62)\" fill=\"currentColor\" fillRule=\"evenodd\">\r\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" />\r\n <circle cx=\"55\" cy=\"82\" r=\"3.4\" />\r\n </g>\r\n </svg>\r\n);\r\n\r\nexport const SparkleIcon = KikuIcon;\r\n\r\nexport const StopIcon = () => (\r\n <svg className=\"hsk-stop-icon\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <circle\r\n className=\"hsk-stop-ring\"\r\n cx=\"12\" cy=\"12\" r=\"9.5\"\r\n stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\"\r\n />\r\n <rect className=\"hsk-stop-core\" x=\"8.5\" y=\"8.5\" width=\"7\" height=\"7\" rx=\"1.8\" fill=\"currentColor\" />\r\n </svg>\r\n);\r\n\r\nexport const SpeakerIcon = ({ active }: { active?: boolean }) => (\r\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" fill={active ? 'currentColor' : 'none'} />\r\n {active ? (\r\n <>\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\r\n </>\r\n ) : (\r\n <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\" />\r\n )}\r\n </svg>\r\n);\r\n\r\nexport const ExternalIcon = () => (\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\r\n <polyline points=\"15 3 21 3 21 9\" />\r\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\r\n </svg>\r\n);\r\n\r\nexport const ContinueIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M8 5v14l11-7z\" />\r\n </svg>\r\n);\r\n\r\nexport const CloseIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n);\r\n\r\nexport const ChevronLeftIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m15 18-6-6 6-6\"/>\r\n </svg>\r\n);\r\n\r\nexport const ChevronRightIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m9 18 6-6-6-6\"/>\r\n </svg>\r\n);\r\n\r\nexport const HistoryIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/>\r\n <path d=\"M3 3v5h5\"/>\r\n <path d=\"M12 7v5l4 2\"/>\r\n </svg>\r\n);\r\n\r\nexport const BookmarkIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M19 21 12 16l-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z\"/>\r\n </svg>\r\n);\r\n\r\nexport const TrashIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M3 6h18\"/>\r\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>\r\n </svg>\r\n);\r\n\r\nexport const SecureShieldIcon = ({ className, size = 18 }: { className?: string; size?: number }) => (\r\n <svg\r\n className={className}\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2.5\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n >\r\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\r\n <path d=\"M12 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z\" />\r\n <path d=\"M12 11v4\" />\r\n </svg>\r\n);\r\n\r\nexport const PlusIcon = () => (\r\n <svg width=\"19\" height=\"19\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\r\n <path d=\"M12 5v14M5 12h14\"/>\r\n </svg>\r\n);\r\n\r\nexport const PaperclipIcon = () => (\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/>\r\n </svg>\r\n);\r\n\r\nexport const CopyIcon = ({ size = 13 }: { size?: number } = {}) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <rect className=\"hsk-copy-sheet\" x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/>\r\n <path className=\"hsk-copy-back\" d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/>\r\n </svg>\r\n);\r\n\r\nexport const CheckIcon = ({ size = 13 }: { size?: number } = {}) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <polyline className=\"hsk-check-mark\" points=\"20 6 9 17 4 12\"/>\r\n </svg>\r\n);\r\n\r\nexport const MicIcon = ({ className, size = 18 }: { className?: string; size?: number } = {}) => (\r\n <svg className={className} width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path className=\"hsk-mic-cap\" d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z\"/>\r\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\r\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/>\r\n </svg>\r\n);\r\n\r\nexport const MicOffIcon = () => (\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"2\" y1=\"2\" x2=\"22\" y2=\"22\"/>\r\n <path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\"/>\r\n <path d=\"M5 10v2a7 7 0 0 0 12 5\"/>\r\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\"/>\r\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\"/>\r\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/>\r\n </svg>\r\n);\r\n\r\nexport const WaveformIcon = ({ active }: { active?: boolean }) => (\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path className=\"hsk-wave-bar hsk-wave-bar--tip\" style={{ '--hsk-bar': 0, '--hsk-amp': 1.9, '--hsk-period': '1.24s' } as React.CSSProperties} d=\"M2 12h2\" />\r\n <path className=\"hsk-wave-bar\" style={{ '--hsk-bar': 1, '--hsk-amp': 1.78, '--hsk-period': '0.94s' } as React.CSSProperties} d=\"M6 8v8\" />\r\n <path className=\"hsk-wave-bar\" style={{ '--hsk-bar': 2, '--hsk-amp': 1.26, '--hsk-period': '1.42s' } as React.CSSProperties} d=\"M10 4v16\" />\r\n <path className=\"hsk-wave-bar\" style={{ '--hsk-bar': 3, '--hsk-amp': 1.62, '--hsk-period': '1.08s' } as React.CSSProperties} d=\"M14 7v10\" />\r\n <path className=\"hsk-wave-bar\" style={{ '--hsk-bar': 4, '--hsk-amp': 2.05, '--hsk-period': '0.86s' } as React.CSSProperties} d=\"M18 9v6\" />\r\n <path className=\"hsk-wave-bar hsk-wave-bar--tip\" style={{ '--hsk-bar': 5, '--hsk-amp': 1.9, '--hsk-period': '1.32s' } as React.CSSProperties} d=\"M22 12h-2\" />\r\n </svg>\r\n);\r\n\r\nexport const ArrowUpIcon = () => (\r\n <svg\r\n className=\"hsk-telegram-icon\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n >\r\n {/* the silhouette is unchanged at rest; splitting it at the fold gives two\r\n wings that can beat independently */}\r\n <polygon className=\"hsk-kite-wing hsk-kite-wing--far\" points=\"22 2 11 13 2 9\" />\r\n <polygon className=\"hsk-kite-wing hsk-kite-wing--near\" points=\"22 2 15 22 11 13\" />\r\n <line className=\"hsk-kite-spine\" x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\r\n </svg>\r\n);\r\n\r\nexport const SunIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <circle className=\"hsk-sun-core\" cx=\"12\" cy=\"12\" r=\"5\"/>\r\n <g className=\"hsk-sun-rays\">\r\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\"/>\r\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\"/>\r\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\"/>\r\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\"/>\r\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\"/>\r\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\"/>\r\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\"/>\r\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\"/>\r\n </g>\r\n </svg>\r\n);\r\n\r\nexport const MoonIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path className=\"hsk-moon-body\" d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/>\r\n </svg>\r\n);\r\n\r\nexport const WoodIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path className=\"hsk-wood-layer\" style={{ '--hsk-layer': 0 } as React.CSSProperties} d=\"M12 2L2 7l10 5 10-5-10-5z\"/>\r\n <path className=\"hsk-wood-layer\" style={{ '--hsk-layer': 2 } as React.CSSProperties} d=\"M2 17l10 5 10-5\"/>\r\n <path className=\"hsk-wood-layer\" style={{ '--hsk-layer': 1 } as React.CSSProperties} d=\"M2 12l10 5 10-5\"/>\r\n </svg>\r\n);\r\n\r\nexport const HeartIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path className=\"hsk-heart-body\" d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\"/>\r\n </svg>\r\n);\r\n\r\nexport const CoffeeIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M17 8h1a4 4 0 1 1 0 8h-1\"/>\r\n <path d=\"M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4z\"/>\r\n <line className=\"hsk-steam\" style={{ '--hsk-steam': 0 } as React.CSSProperties} x1=\"6\" y1=\"1\" x2=\"6\" y2=\"4\"/>\r\n <line className=\"hsk-steam\" style={{ '--hsk-steam': 1 } as React.CSSProperties} x1=\"10\" y1=\"1\" x2=\"10\" y2=\"4\"/>\r\n <line className=\"hsk-steam\" style={{ '--hsk-steam': 2 } as React.CSSProperties} x1=\"14\" y1=\"1\" x2=\"14\" y2=\"4\"/>\r\n </svg>\r\n);\r\n\r\nexport const StarIcon = () => (\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M12 3a6.5 6.5 0 0 0 9 9 9 9 0 1 1-9-9z\"/>\r\n <path className=\"hsk-star-spark\" d=\"M18.5 2.5l.6 1.6 1.6.6-1.6.6-.6 1.6-.6-1.6-1.6-.6 1.6-.6z\"/>\r\n </svg>\r\n);\r\n\r\nexport const ShieldIcon = ({ size = 18 }: { size?: number }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/>\r\n <path d=\"m9 12 2 2 4-4\"/>\r\n </svg>\r\n);\r\n\r\nexport const KeyOutlineIcon = ({ size = 18 }: { size?: number }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"m21 2-2 2m-1.5 1.5L14 9a5.5 5.5 0 1 0 2 2l3.5-3.5\"/>\r\n <circle cx=\"7.5\" cy=\"15.5\" r=\"2.5\"/>\r\n </svg>\r\n);\r\n\r\nexport const VaultIcon = ({ size = 18 }: { size?: number }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"3\"/>\r\n <circle cx=\"12\" cy=\"12\" r=\"3\"/>\r\n <path d=\"m14.5 9.5-5 5\"/>\r\n </svg>\r\n);\r\n\r\nexport const GlobeIcon = ({ size = 18 }: { size?: number }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\r\n <line x1=\"2\" x2=\"22\" y1=\"12\" y2=\"12\"/>\r\n <path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"/>\r\n </svg>\r\n);\r\n\r\nexport const XIcon = ({ size = 11 }: { size?: number }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n);\r\n\r\n\r\n","import type { ComponentType } from 'react';\r\nimport { SunIcon, MoonIcon, WoodIcon, HeartIcon, CoffeeIcon, StarIcon } from './icons';\r\n\r\nexport interface ThemeDef {\r\n id: string;\r\n label: string;\r\n Icon: ComponentType;\r\n dark: boolean;\r\n}\r\n\r\n// Single source of truth. Add a theme here plus a token block in styles.css.\r\nexport const THEMES: ThemeDef[] = [\r\n { id: 'light', label: 'Silver', Icon: SunIcon, dark: false },\r\n { id: 'dark', label: 'Onyx', Icon: MoonIcon, dark: true },\r\n { id: 'mahogany', label: 'Mahogany', Icon: WoodIcon, dark: true },\r\n { id: 'blush', label: 'Blush', Icon: HeartIcon, dark: false },\r\n { id: 'coffee', label: 'Coffee', Icon: CoffeeIcon, dark: false },\r\n { id: 'midnight', label: 'Midnight', Icon: StarIcon, dark: true },\r\n];\r\n\r\nexport type ThemeId = string;\r\n\r\nexport const DEFAULT_DARK: ThemeId = 'dark';\r\nexport const DEFAULT_LIGHT: ThemeId = 'light';\r\n\r\nexport function isThemeId(value: unknown): value is ThemeId {\r\n return typeof value === 'string' && THEMES.some(t => t.id === value);\r\n}\r\n\r\nexport function themeDef(id: ThemeId): ThemeDef {\r\n return THEMES.find(t => t.id === id) ?? THEMES[0];\r\n}\r\n","import { useEffect, useRef } from 'react';\r\n\r\nexport function rubberBand(offset: number, dimension: number, coeff = 0.55): number {\r\n if (dimension <= 0) return 0;\r\n return (offset * dimension * coeff) / (dimension + coeff * Math.abs(offset));\r\n}\r\n\r\ntype SpringOpts = { stiffness?: number; damping?: number; onFrame: (v: number) => void; onRest?: () => void };\r\n\r\nexport function createSpring({ stiffness = 500, damping = 45, onFrame, onRest }: SpringOpts) {\r\n let value = 0, velocity = 0, target = 0;\r\n let raf: number | null = null;\r\n let last = 0;\r\n\r\n const tick = (now: number) => {\r\n const dt = Math.min(0.032, (now - last) / 1000) || 1 / 60;\r\n last = now;\r\n const steps = Math.max(1, Math.ceil(dt / 0.008));\r\n const h = dt / steps;\r\n for (let i = 0; i < steps; i++) {\r\n const a = -stiffness * (value - target) - damping * velocity;\r\n velocity += a * h;\r\n value += velocity * h;\r\n }\r\n if (Math.abs(value - target) < 0.5 && Math.abs(velocity) < 0.5) {\r\n value = target; velocity = 0; raf = null;\r\n onFrame(value); onRest?.();\r\n return;\r\n }\r\n onFrame(value);\r\n raf = requestAnimationFrame(tick);\r\n };\r\n\r\n const start = () => { if (raf === null) { last = performance.now(); raf = requestAnimationFrame(tick); } };\r\n\r\n return {\r\n\r\n track(v: number) {\r\n if (raf !== null) { cancelAnimationFrame(raf); raf = null; }\r\n value = v; velocity = 0; onFrame(value);\r\n },\r\n\r\n to(t: number, v0 = 0) { target = t; velocity = v0; start(); },\r\n get value() { return value; },\r\n stop() { if (raf !== null) { cancelAnimationFrame(raf); raf = null; } },\r\n };\r\n}\r\n\r\ntype Opts = {\r\n panel: () => HTMLElement | null;\r\n scroller: () => HTMLElement | null;\r\n onDismiss: () => void;\r\n\r\n quiescent?: () => boolean;\r\n enabled?: boolean;\r\n};\r\n\r\nexport function useDragToDismiss({ panel, scroller, onDismiss, quiescent, enabled = true }: Opts): void {\r\n const dismissRef = useRef(onDismiss);\r\n dismissRef.current = onDismiss;\r\n\r\n useEffect(() => {\r\n if (!enabled) return;\r\n const el = panel();\r\n if (!el) return;\r\n if (typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches) return;\r\n\r\n let dragging = false, startY = 0, startX = 0, offset = 0, pointerId = -1;\r\n let lastY = 0, lastT = 0, velocity = 0, decided = false, exiting = false;\r\n\r\n const apply = (v: number) => {\r\n el.style.transform = v === 0 ? '' : `translate3d(0, ${v}px, 0)`;\r\n const host = el.parentElement;\r\n if (host) host.style.opacity = v === 0 ? '' : String(Math.max(0.35, 1 - v / (el.offsetHeight || 1) * 1.1));\r\n };\r\n const spring = createSpring({\r\n onFrame: apply,\r\n onRest: () => {\r\n el.style.willChange = '';\r\n if (exiting) { exiting = false; dismissRef.current(); }\r\n },\r\n });\r\n\r\n const atTop = () => {\r\n const s = scroller();\r\n if (s && s.scrollTop > 0) return false;\r\n return quiescent ? quiescent() : true;\r\n };\r\n\r\n const onDown = (e: PointerEvent) => {\r\n if (e.pointerType === 'mouse' || !e.isPrimary) return;\r\n dragging = false; decided = false;\r\n pointerId = e.pointerId;\r\n startY = lastY = e.clientY; startX = e.clientX;\r\n lastT = e.timeStamp; velocity = 0;\r\n offset = spring.value;\r\n };\r\n\r\n const onMove = (e: PointerEvent) => {\r\n if (e.pointerId !== pointerId) return;\r\n const dy = e.clientY - startY;\r\n const dx = e.clientX - startX;\r\n\r\n if (!decided) {\r\n if (Math.abs(dy) < 6 && Math.abs(dx) < 6) return;\r\n decided = true;\r\n dragging = dy > 0 && Math.abs(dy) > Math.abs(dx) && atTop();\r\n if (dragging) {\r\n try { el.setPointerCapture(e.pointerId); } catch { }\r\n spring.stop();\r\n el.style.animation = 'none';\r\n el.style.willChange = 'transform';\r\n }\r\n }\r\n if (!dragging) return;\r\n\r\n const dt = e.timeStamp - lastT;\r\n if (dt > 0) velocity = ((e.clientY - lastY) / dt) * 1000;\r\n lastY = e.clientY; lastT = e.timeStamp;\r\n\r\n const raw = offset + dy;\r\n spring.track(raw < 0 ? -rubberBand(-raw, el.offsetHeight || 1) : raw);\r\n if (e.cancelable) e.preventDefault();\r\n };\r\n\r\n const onUp = (e: PointerEvent) => {\r\n if (e.pointerId !== pointerId) return;\r\n try { if (el.hasPointerCapture(e.pointerId)) el.releasePointerCapture(e.pointerId); } catch { }\r\n pointerId = -1;\r\n if (!dragging) return;\r\n dragging = false;\r\n const h = el.offsetHeight || 1;\r\n const projected = spring.value + velocity * 0.12;\r\n if (projected > h * 0.3 || velocity > 900) {\r\n exiting = true;\r\n el.style.pointerEvents = 'none';\r\n spring.to(h, velocity);\r\n } else {\r\n spring.to(0, velocity);\r\n }\r\n };\r\n\r\n el.addEventListener('pointerdown', onDown, { passive: true });\r\n el.addEventListener('pointermove', onMove, { passive: false });\r\n el.addEventListener('pointerup', onUp, { passive: true });\r\n el.addEventListener('pointercancel', onUp, { passive: true });\r\n return () => {\r\n spring.stop();\r\n el.removeEventListener('pointerdown', onDown);\r\n el.removeEventListener('pointermove', onMove);\r\n el.removeEventListener('pointerup', onUp);\r\n el.removeEventListener('pointercancel', onUp);\r\n el.style.transform = ''; el.style.willChange = ''; el.style.animation = ''; el.style.pointerEvents = '';\r\n const host = el.parentElement;\r\n if (host) host.style.opacity = '';\r\n };\r\n }, [enabled, panel, scroller, quiescent]);\r\n}\r\n","import React, { useEffect, useRef, useState } from 'react';\r\nimport { buildMarkRegions, type MarkRegion } from '../utils/markRegions';\r\n\r\ntype Tool = 'pen' | 'eraser' | 'text';\r\n\r\ninterface Point { x: number; y: number }\r\ninterface StrokeAction { kind: 'stroke'; tool: 'pen' | 'eraser'; color: string; size: number; points: Point[] }\r\ninterface TextAction { kind: 'text'; x: number; y: number; color: string; value: string; size: number }\r\ntype Action = StrokeAction | TextAction;\r\n\r\nconst COLORS = ['#111111', '#ff5a5a', '#ffb300', '#22c55e', '#06b6d4', '#d946ef', '#9ca3af'];\r\nconst MAX_EXPORT_DIM = 1280;\r\n\r\nexport function MarkupEditor({ src, onCancel, onSend, t }: {\r\n src: string;\r\n onCancel: () => void;\r\n onSend: (dataUrl: string, instruction: string, marks: MarkRegion[], preview: string) => void;\r\n t: (key: string, vars?: Record<string, string>) => string;\r\n}) {\r\n const [img, setImg] = useState<HTMLImageElement | null>(null);\r\n const [loadError, setLoadError] = useState(false);\r\n const [tool, setTool] = useState<Tool>('pen');\r\n const [color, setColor] = useState(COLORS[1]);\r\n const [actions, setActions] = useState<Action[]>([]);\r\n const [pendingText, setPendingText] = useState<{ x: number; y: number } | null>(null);\r\n const [textValue, setTextValue] = useState('');\r\n const [instruction, setInstruction] = useState('');\r\n const [exportError, setExportError] = useState(false);\r\n\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const drawingRef = useRef<StrokeAction | null>(null);\r\n const textInputRef = useRef<HTMLInputElement>(null);\r\n\r\n useEffect(() => {\r\n const el = new Image();\r\n el.crossOrigin = 'anonymous';\r\n el.onload = () => setImg(el);\r\n el.onerror = () => setLoadError(true);\r\n el.src = src;\r\n }, [src]);\r\n\r\n const dims = (() => {\r\n if (!img) return { w: 0, h: 0 };\r\n const scale = Math.min(1, MAX_EXPORT_DIM / Math.max(img.naturalWidth, img.naturalHeight));\r\n return { w: Math.round(img.naturalWidth * scale), h: Math.round(img.naturalHeight * scale) };\r\n })();\r\n\r\n const markLayer = useRef<HTMLCanvasElement | null>(null);\r\n const paint = (live?: StrokeAction | null) => {\r\n const canvas = canvasRef.current;\r\n if (!canvas || !img) return;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n if (!markLayer.current) markLayer.current = document.createElement('canvas');\r\n const layer = markLayer.current;\r\n layer.width = canvas.width;\r\n layer.height = canvas.height;\r\n const lctx = layer.getContext('2d')!;\r\n const all = live ? [...actions, live] : actions;\r\n for (const a of all) {\r\n if (a.kind === 'stroke') {\r\n lctx.save();\r\n lctx.globalCompositeOperation = a.tool === 'eraser' ? 'destination-out' : 'source-over';\r\n lctx.strokeStyle = a.color;\r\n lctx.lineWidth = a.tool === 'eraser' ? a.size * 3 : a.size;\r\n lctx.lineCap = 'round';\r\n lctx.lineJoin = 'round';\r\n lctx.beginPath();\r\n a.points.forEach((p, i) => (i === 0 ? lctx.moveTo(p.x, p.y) : lctx.lineTo(p.x, p.y)));\r\n if (a.points.length === 1) lctx.lineTo(a.points[0].x + 0.01, a.points[0].y);\r\n lctx.stroke();\r\n lctx.restore();\r\n } else {\r\n lctx.save();\r\n lctx.fillStyle = a.color;\r\n lctx.font = `600 ${a.size}px system-ui, sans-serif`;\r\n lctx.fillText(a.value, a.x, a.y);\r\n lctx.restore();\r\n }\r\n }\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\r\n ctx.drawImage(layer, 0, 0);\r\n };\r\n\r\n useEffect(() => { paint(); }, [img, actions, dims.w, dims.h]);\r\n useEffect(() => { if (pendingText) textInputRef.current?.focus(); }, [pendingText]);\r\n\r\n const toCanvasPoint = (e: React.PointerEvent): Point => {\r\n const canvas = canvasRef.current!;\r\n const rect = canvas.getBoundingClientRect();\r\n return {\r\n x: ((e.clientX - rect.left) / rect.width) * canvas.width,\r\n y: ((e.clientY - rect.top) / rect.height) * canvas.height,\r\n };\r\n };\r\n\r\n const strokeSize = () => Math.max(4, Math.round(dims.w / 180));\r\n const textSize = () => Math.max(18, Math.round(dims.w / 28));\r\n\r\n const onPointerDown = (e: React.PointerEvent) => {\r\n if (!img) return;\r\n const p = toCanvasPoint(e);\r\n if (tool === 'text') {\r\n setPendingText({ x: p.x, y: p.y });\r\n setTextValue('');\r\n return;\r\n }\r\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\r\n drawingRef.current = { kind: 'stroke', tool, color, size: strokeSize(), points: [p] };\r\n paint(drawingRef.current);\r\n };\r\n const onPointerMove = (e: React.PointerEvent) => {\r\n if (!drawingRef.current) return;\r\n drawingRef.current.points.push(toCanvasPoint(e));\r\n paint(drawingRef.current);\r\n };\r\n const onPointerUp = () => {\r\n if (!drawingRef.current) return;\r\n const done = drawingRef.current;\r\n drawingRef.current = null;\r\n setActions(prev => [...prev, done]);\r\n };\r\n\r\n const commitText = () => {\r\n if (pendingText && textValue.trim()) {\r\n setActions(prev => [...prev, { kind: 'text', x: pendingText.x, y: pendingText.y, color, value: textValue.trim(), size: textSize() }]);\r\n }\r\n setPendingText(null);\r\n setTextValue('');\r\n };\r\n\r\n const handleSend = () => {\r\n if (!img) return;\r\n try {\r\n const clean = document.createElement('canvas');\r\n clean.width = dims.w;\r\n clean.height = dims.h;\r\n const cctx = clean.getContext('2d');\r\n if (!cctx) { setExportError(true); return; }\r\n cctx.drawImage(img, 0, 0, dims.w, dims.h);\r\n const dataUrl = clean.toDataURL('image/jpeg', 0.92);\r\n const drawn = canvasRef.current?.toDataURL('image/jpeg', 0.85) || dataUrl;\r\n onSend(dataUrl, instruction.trim(), buildMarkRegions(actions, dims.w, dims.h), drawn);\r\n } catch {\r\n setExportError(true);\r\n }\r\n };\r\n\r\n const hasMarks = actions.length > 0;\r\n\r\n return (\r\n <div className=\"hsk-markup\" role=\"dialog\" aria-label={t('markupDialogLabel')}>\r\n <div className=\"hsk-markup-head\">\r\n <span className=\"hsk-markup-title\">{t('markupTitle')}</span>\r\n <button className=\"hsk-markup-cancel\" onClick={onCancel}>{t('markupCancel')}</button>\r\n </div>\r\n\r\n <div className=\"hsk-markup-stage\">\r\n {loadError ? (\r\n <div className=\"hsk-markup-error\">{t('markupLoadError')}</div>\r\n ) : !img ? (\r\n <div className=\"hsk-markup-loading\">{t('markupLoading')}</div>\r\n ) : (\r\n <div className=\"hsk-markup-canvas-wrap\">\r\n <canvas\r\n ref={canvasRef}\r\n width={dims.w}\r\n height={dims.h}\r\n className={`hsk-markup-canvas hsk-markup-canvas--${tool}`}\r\n onPointerDown={onPointerDown}\r\n onPointerMove={onPointerMove}\r\n onPointerUp={onPointerUp}\r\n onPointerLeave={onPointerUp}\r\n />\r\n {pendingText && canvasRef.current && (\r\n <input\r\n ref={textInputRef}\r\n className=\"hsk-markup-textinput\"\r\n style={{\r\n left: `${(pendingText.x / dims.w) * 100}%`,\r\n top: `${(pendingText.y / dims.h) * 100}%`,\r\n color,\r\n }}\r\n value={textValue}\r\n placeholder={t('markupTextHint')}\r\n onChange={e => setTextValue(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') commitText(); if (e.key === 'Escape') { setPendingText(null); setTextValue(''); } }}\r\n onBlur={commitText}\r\n />\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"hsk-markup-tools\">\r\n <div className=\"hsk-markup-colors\">\r\n {COLORS.map(c => (\r\n <button\r\n key={c}\r\n className={`hsk-markup-color${color === c ? ' hsk-markup-color--on' : ''}`}\r\n style={{ background: c }}\r\n onClick={() => { setColor(c); if (tool === 'eraser') setTool('pen'); }}\r\n aria-label={t('markupColorLabel', { colour: c })}\r\n />\r\n ))}\r\n </div>\r\n <div className=\"hsk-markup-actions\">\r\n <button className={`hsk-markup-tool${tool === 'pen' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('pen')}>{t('markupSketch')}</button>\r\n <button className={`hsk-markup-tool${tool === 'text' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('text')}>{t('markupText')}</button>\r\n <button className={`hsk-markup-tool${tool === 'eraser' ? ' hsk-markup-tool--on' : ''}`} onClick={() => setTool('eraser')}>{t('markupEraser')}</button>\r\n <button className=\"hsk-markup-tool\" onClick={() => setActions(prev => prev.slice(0, -1))} disabled={!hasMarks}>{t('markupUndo')}</button>\r\n <button className=\"hsk-markup-tool\" onClick={() => setActions([])} disabled={!hasMarks}>{t('markupClear')}</button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"hsk-markup-send\">\r\n <input\r\n className=\"hsk-markup-instruction\"\r\n value={instruction}\r\n placeholder={t('markupInstruction')}\r\n onChange={e => setInstruction(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter' && (hasMarks || instruction.trim())) handleSend(); }}\r\n />\r\n <button\r\n className=\"hsk-markup-go\"\r\n onClick={handleSend}\r\n disabled={!img || (!hasMarks && !instruction.trim())}\r\n >\r\n {t('markupSend')}\r\n </button>\r\n </div>\r\n {exportError && <div className=\"hsk-markup-error\">{t('markupError')}</div>}\r\n </div>\r\n );\r\n}\r\n","\r\nexport interface Point { x: number; y: number }\r\n\r\nexport type MarkGesture = 'ring' | 'cross' | 'scribble' | 'arrow' | 'text';\r\n\r\nexport interface MarkRegion {\r\n gesture: MarkGesture;\r\n box: [number, number, number, number];\r\n to?: [number, number];\r\n text?: string;\r\n}\r\n\r\nconst dist = (a: Point, b: Point) => Math.hypot(a.x - b.x, a.y - b.y);\r\n\r\nfunction pathLength(pts: Point[]): number {\r\n let n = 0;\r\n for (let i = 1; i < pts.length; i++) n += dist(pts[i - 1], pts[i]);\r\n return n;\r\n}\r\n\r\nfunction bbox(pts: Point[]) {\r\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\r\n for (const p of pts) {\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n return { minX, minY, maxX, maxY };\r\n}\r\n\r\nconst clamp1000 = (v: number) => Math.max(0, Math.min(1000, Math.round(v)));\r\n\r\nfunction norm(b: ReturnType<typeof bbox>, w: number, h: number): [number, number, number, number] {\r\n return [\r\n clamp1000((b.minY / h) * 1000),\r\n clamp1000((b.minX / w) * 1000),\r\n clamp1000((b.maxY / h) * 1000),\r\n clamp1000((b.maxX / w) * 1000),\r\n ];\r\n}\r\n\r\nfunction overlaps(a: [number, number, number, number], b: [number, number, number, number]): boolean {\r\n const [ay0, ax0, ay1, ax1] = a;\r\n const [by0, bx0, by1, bx1] = b;\r\n const iw = Math.min(ax1, bx1) - Math.max(ax0, bx0);\r\n const ih = Math.min(ay1, by1) - Math.max(ay0, by0);\r\n if (iw <= 0 || ih <= 0) return false;\r\n const smaller = Math.min((ax1 - ax0) * (ay1 - ay0), (bx1 - bx0) * (by1 - by0));\r\n return smaller > 0 && (iw * ih) / smaller > 0.35;\r\n}\r\n\r\nconst union = (\r\n a: [number, number, number, number],\r\n b: [number, number, number, number],\r\n): [number, number, number, number] =>\r\n [Math.min(a[0], b[0]), Math.min(a[1], b[1]), Math.max(a[2], b[2]), Math.max(a[3], b[3])];\r\n\r\ninterface Classified { gesture: MarkGesture; box: [number, number, number, number]; to?: [number, number]; straight: boolean }\r\n\r\nfunction classifyStroke(pts: Point[], w: number, h: number): Classified | null {\r\n if (pts.length < 2) return null;\r\n const b = bbox(pts);\r\n const box = norm(b, w, h);\r\n const diag = Math.hypot(b.maxX - b.minX, b.maxY - b.minY);\r\n if (diag < 4) return null; // a tap, not a gesture\r\n\r\n const len = pathLength(pts);\r\n const endGap = dist(pts[0], pts[pts.length - 1]);\r\n const straightness = len / Math.max(endGap, 1e-6);\r\n\r\n if (endGap / diag < 0.3 && len > diag * 1.8) return { gesture: 'ring', box, straight: false };\r\n\r\n if (straightness < 1.25) {\r\n return {\r\n gesture: 'arrow',\r\n box,\r\n to: [clamp1000((pts[pts.length - 1].y / h) * 1000), clamp1000((pts[pts.length - 1].x / w) * 1000)],\r\n straight: true,\r\n };\r\n }\r\n\r\n return { gesture: 'scribble', box, straight: false };\r\n}\r\n\r\nexport function buildMarkRegions(\r\n actions: ReadonlyArray<{ kind: string; points?: Point[]; x?: number; y?: number; value?: string; tool?: string }>,\r\n width: number,\r\n height: number,\r\n): MarkRegion[] {\r\n if (!width || !height) return [];\r\n\r\n const strokes: Classified[] = [];\r\n const texts: MarkRegion[] = [];\r\n\r\n for (const a of actions) {\r\n if (a.kind === 'text' && a.value && typeof a.x === 'number' && typeof a.y === 'number') {\r\n const p = { x: a.x, y: a.y };\r\n texts.push({ gesture: 'text', box: norm(bbox([p, p]), width, height), text: a.value });\r\n continue;\r\n }\r\n if (a.kind === 'stroke' && a.tool !== 'eraser' && a.points) {\r\n const c = classifyStroke(a.points, width, height);\r\n if (c) strokes.push(c);\r\n }\r\n }\r\n\r\n const used = new Set<number>();\r\n const out: MarkRegion[] = [];\r\n for (let i = 0; i < strokes.length; i++) {\r\n if (used.has(i)) continue;\r\n let cur = strokes[i];\r\n for (let j = i + 1; j < strokes.length; j++) {\r\n if (used.has(j) || !cur.straight || !strokes[j].straight) continue;\r\n if (!overlaps(cur.box, strokes[j].box)) continue;\r\n used.add(j);\r\n cur = { gesture: 'cross', box: union(cur.box, strokes[j].box), straight: false };\r\n }\r\n used.add(i);\r\n out.push(cur.gesture === 'arrow'\r\n ? { gesture: 'arrow', box: cur.box, to: cur.to }\r\n : { gesture: cur.gesture, box: cur.box });\r\n }\r\n\r\n return [...out, ...texts];\r\n}\r\n","import React, { useEffect, useRef } from 'react';\r\n\r\ntype Rng = () => number;\r\n\r\nfunction hashSeed(s: string): number {\r\n let h = 2166136261 >>> 0;\r\n for (let i = 0; i < s.length; i++) {\r\n h ^= s.charCodeAt(i);\r\n h = Math.imul(h, 16777619);\r\n }\r\n return h >>> 0;\r\n}\r\n\r\nfunction mulberry32(seed: number): Rng {\r\n let a = seed >>> 0;\r\n return () => {\r\n a = (a + 0x6d2b79f5) >>> 0;\r\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\r\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\r\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\r\n };\r\n}\r\n\r\nconst smooth = (t: number) => t * t * (3 - 2 * t);\r\n\r\nfunction makeNoise(rng: Rng) {\r\n const size = 256;\r\n const lat = new Float32Array(size * size);\r\n for (let i = 0; i < lat.length; i++) lat[i] = rng();\r\n const at = (x: number, y: number) => lat[(y & 255) * size + (x & 255)];\r\n\r\n return (x: number, y: number) => {\r\n const xi = Math.floor(x);\r\n const yi = Math.floor(y);\r\n const xf = smooth(x - xi);\r\n const yf = smooth(y - yi);\r\n const a = at(xi, yi);\r\n const b = at(xi + 1, yi);\r\n const c = at(xi, yi + 1);\r\n const d = at(xi + 1, yi + 1);\r\n return (a + (b - a) * xf) * (1 - yf) + (c + (d - c) * xf) * yf;\r\n };\r\n}\r\n\r\nfunction poisson(w: number, h: number, r: number, rng: Rng): Array<[number, number]> {\r\n const cell = r / Math.SQRT2;\r\n const gw = Math.ceil(w / cell);\r\n const gh = Math.ceil(h / cell);\r\n const grid = new Int32Array(gw * gh).fill(-1);\r\n const pts: Array<[number, number]> = [];\r\n const active: number[] = [];\r\n\r\n const place = (x: number, y: number) => {\r\n const i = pts.length;\r\n pts.push([x, y]);\r\n grid[Math.floor(y / cell) * gw + Math.floor(x / cell)] = i;\r\n active.push(i);\r\n };\r\n\r\n const fits = (x: number, y: number) => {\r\n if (x < 0 || y < 0 || x >= w || y >= h) return false;\r\n const cx = Math.floor(x / cell);\r\n const cy = Math.floor(y / cell);\r\n for (let gy = Math.max(cy - 2, 0); gy <= Math.min(cy + 2, gh - 1); gy++) {\r\n for (let gx = Math.max(cx - 2, 0); gx <= Math.min(cx + 2, gw - 1); gx++) {\r\n const j = grid[gy * gw + gx];\r\n if (j < 0) continue;\r\n const dx = pts[j][0] - x;\r\n const dy = pts[j][1] - y;\r\n if (dx * dx + dy * dy < r * r) return false;\r\n }\r\n }\r\n return true;\r\n };\r\n\r\n place(rng() * w, rng() * h);\r\n while (active.length) {\r\n const ai = (rng() * active.length) | 0;\r\n const [px, py] = pts[active[ai]];\r\n let placed = false;\r\n for (let k = 0; k < 24; k++) {\r\n const ang = rng() * Math.PI * 2;\r\n const rad = r * (1 + rng());\r\n const x = px + Math.cos(ang) * rad;\r\n const y = py + Math.sin(ang) * rad;\r\n if (fits(x, y)) {\r\n place(x, y);\r\n placed = true;\r\n break;\r\n }\r\n }\r\n if (!placed) active.splice(ai, 1);\r\n }\r\n return pts;\r\n}\r\n\r\ntype Glyph = (ctx: CanvasRenderingContext2D, s: number, rng: Rng) => void;\r\n\r\nconst wob = (rng: Rng, k: number) => (rng() - 0.5) * k;\r\n\r\nconst motifs: Glyph[] = [\r\n (ctx, s, rng) => {\r\n const h = s * 0.5;\r\n const w = s * (0.14 + rng() * 0.04);\r\n const cap = s * 0.07;\r\n ctx.beginPath();\r\n ctx.moveTo(-w - cap * 0.6, -h);\r\n ctx.lineTo(w + cap * 0.6, -h);\r\n ctx.moveTo(-w, -h + cap);\r\n ctx.lineTo(w, -h + cap);\r\n ctx.moveTo(-w, -h + cap);\r\n ctx.lineTo(-w * 0.85, h - cap);\r\n ctx.moveTo(w, -h + cap);\r\n ctx.lineTo(w * 0.85, h - cap);\r\n ctx.moveTo(0, -h + cap * 1.7);\r\n ctx.lineTo(0, h - cap * 1.7);\r\n ctx.moveTo(-w, h - cap);\r\n ctx.lineTo(w, h - cap);\r\n ctx.moveTo(-w - cap * 0.6, h);\r\n ctx.lineTo(w + cap * 0.6, h);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const eave = -q * (0.18 + rng() * 0.1);\r\n ctx.beginPath();\r\n ctx.moveTo(-q, eave);\r\n ctx.lineTo(0, -q);\r\n ctx.lineTo(q, eave);\r\n ctx.closePath();\r\n ctx.moveTo(-q * 0.92, eave + q * 0.16);\r\n ctx.lineTo(q * 0.92, eave + q * 0.16);\r\n for (const x of [-0.62, -0.21, 0.21, 0.62]) {\r\n ctx.moveTo(q * x, eave + q * 0.16);\r\n ctx.lineTo(q * x, q * 0.8);\r\n }\r\n ctx.moveTo(-q, q * 0.8);\r\n ctx.lineTo(q, q * 0.8);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const belly = q * (0.48 + rng() * 0.12);\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.2, -q * 0.86);\r\n ctx.lineTo(q * 0.2, -q * 0.86);\r\n ctx.moveTo(-q * 0.15, -q * 0.78);\r\n ctx.bezierCurveTo(-belly, -q * 0.3, -belly * 0.85, q * 0.6, 0, q * 0.86);\r\n ctx.bezierCurveTo(belly * 0.85, q * 0.6, belly, -q * 0.3, q * 0.15, -q * 0.78);\r\n ctx.moveTo(-q * 0.17, -q * 0.64);\r\n ctx.quadraticCurveTo(-belly * 1.16, -q * 0.48, -belly * 0.7, -q * 0.04);\r\n ctx.moveTo(q * 0.17, -q * 0.64);\r\n ctx.quadraticCurveTo(belly * 1.16, -q * 0.48, belly * 0.7, -q * 0.04);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.9, q * 0.52);\r\n ctx.quadraticCurveTo(0, -q * 0.18, q * 0.9, -q * 0.58);\r\n ctx.stroke();\r\n const n = 4 + ((rng() * 3) | 0);\r\n for (let i = 0; i < n; i++) {\r\n const t = 0.16 + (i / n) * 0.8;\r\n const px = -q * 0.9 + t * q * 1.8;\r\n const py = q * 0.52 - t * q * 1.16 + (1 - t) * t * q * 0.3;\r\n const dir = i % 2 ? 1 : -1;\r\n const l = q * (0.26 + rng() * 0.1);\r\n ctx.beginPath();\r\n ctx.moveTo(px, py);\r\n ctx.quadraticCurveTo(px + l * 0.5, py + dir * l * 0.66, px + l * 0.9, py + dir * l * 0.08);\r\n ctx.quadraticCurveTo(px + l * 0.42, py + dir * l * 0.04, px, py);\r\n ctx.stroke();\r\n }\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.85, -q * 0.7);\r\n ctx.quadraticCurveTo(-q * 0.1, -q * 0.35, q * 0.2, q * 0.1);\r\n ctx.stroke();\r\n const drupes: Array<[number, number]> = [\r\n [-q * 0.45, -q * 0.12],\r\n [q * 0.05, q * 0.3],\r\n [q * 0.42, -q * 0.4],\r\n ];\r\n for (const [ox, oy] of drupes) {\r\n ctx.beginPath();\r\n ctx.moveTo(ox, oy - q * 0.28);\r\n ctx.lineTo(ox - q * 0.02, oy - q * 0.16);\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.ellipse(ox, oy, q * (0.15 + rng() * 0.04), q * 0.19, wob(rng, 0.5), 0, Math.PI * 2);\r\n ctx.stroke();\r\n }\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n for (const side of [-1, 1]) {\r\n ctx.beginPath();\r\n ctx.arc(0, 0, q * 0.72, side > 0 ? -1.25 : 1.25, side > 0 ? 1.25 : Math.PI * 2 - 1.25, side < 0);\r\n ctx.stroke();\r\n for (let i = 0; i < 5; i++) {\r\n const a = -1.05 + (i / 4) * 2.1;\r\n const ax = Math.sin(a) * side * q * 0.72;\r\n const ay = Math.cos(a) * q * 0.72;\r\n const l = q * (0.2 + rng() * 0.08);\r\n ctx.beginPath();\r\n ctx.moveTo(ax, ay);\r\n ctx.quadraticCurveTo(ax + side * l * 0.9, ay - l * 0.5, ax + side * l * 0.6, ay - l * 1.05);\r\n ctx.stroke();\r\n }\r\n }\r\n },\r\n (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(-q, q * 0.6);\r\n ctx.lineTo(q * 0.55, q * 0.6);\r\n ctx.lineTo(q * 0.55, -q * 0.6);\r\n ctx.lineTo(-q * 0.45, -q * 0.6);\r\n ctx.lineTo(-q * 0.45, q * 0.15);\r\n ctx.lineTo(q * 0.1, q * 0.15);\r\n ctx.lineTo(q * 0.1, -q * 0.18);\r\n ctx.stroke();\r\n },\r\n (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.62, q * 0.8);\r\n ctx.lineTo(-q * 0.62, -q * 0.05);\r\n ctx.arc(0, -q * 0.05, q * 0.62, Math.PI, 0);\r\n ctx.lineTo(q * 0.62, q * 0.8);\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.86, q * 0.8);\r\n ctx.lineTo(q * 0.86, q * 0.8);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.arc(0, 0, q * 0.4, 0, Math.PI * 2);\r\n ctx.stroke();\r\n const off = rng() * 0.5;\r\n for (let i = 0; i < 8; i++) {\r\n const a = off + (i / 8) * Math.PI * 2;\r\n ctx.beginPath();\r\n ctx.moveTo(Math.cos(a) * q * 0.6, Math.sin(a) * q * 0.6);\r\n ctx.lineTo(Math.cos(a) * q * 0.94, Math.sin(a) * q * 0.94);\r\n ctx.stroke();\r\n }\r\n },\r\n (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.44, q * 0.7);\r\n ctx.bezierCurveTo(-q, q * 0.2, -q * 0.8, -q * 0.7, -q * 0.3, -q * 0.6);\r\n ctx.moveTo(q * 0.44, q * 0.7);\r\n ctx.bezierCurveTo(q, q * 0.2, q * 0.8, -q * 0.7, q * 0.3, -q * 0.6);\r\n ctx.moveTo(-q * 0.32, -q * 0.64);\r\n ctx.lineTo(q * 0.32, -q * 0.64);\r\n ctx.moveTo(-q * 0.44, q * 0.7);\r\n ctx.lineTo(q * 0.44, q * 0.7);\r\n for (const x of [-0.16, 0.02, 0.2]) {\r\n ctx.moveTo(q * x, -q * 0.56);\r\n ctx.lineTo(q * x, q * 0.62);\r\n }\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const lift = q * (0.4 + rng() * 0.18);\r\n ctx.beginPath();\r\n ctx.moveTo(-q, q * 0.16);\r\n ctx.quadraticCurveTo(-q * 0.5, -lift, 0, -q * 0.02);\r\n ctx.quadraticCurveTo(q * 0.5, -lift, q, q * 0.16);\r\n ctx.stroke();\r\n },\r\n];\r\n\r\nconst scribbles: Glyph[] = [\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n let px = -q + wob(rng, q * 0.3);\r\n let py = wob(rng, q);\r\n ctx.beginPath();\r\n ctx.moveTo(px, py);\r\n const n = 4 + ((rng() * 4) | 0);\r\n for (let i = 0; i < n; i++) {\r\n const nx = px + (q * 2) / n + wob(rng, q * 0.5);\r\n const ny = wob(rng, q * 1.5);\r\n ctx.quadraticCurveTo(px + wob(rng, q * 0.9), py + wob(rng, q * 1.6), nx, ny);\r\n px = nx;\r\n py = ny;\r\n }\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const turns = 2.2 + rng() * 1.6;\r\n const dir = rng() < 0.5 ? -1 : 1;\r\n ctx.beginPath();\r\n for (let i = 0; i <= 60; i++) {\r\n const t = i / 60;\r\n const a = dir * t * turns * Math.PI * 2;\r\n const rr = q * t * (0.9 + wob(rng, 0.06));\r\n const x = Math.cos(a) * rr;\r\n const y = Math.sin(a) * rr;\r\n if (i === 0) ctx.moveTo(x, y);\r\n else ctx.lineTo(x, y);\r\n }\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const n = 4 + ((rng() * 4) | 0);\r\n const lean = wob(rng, 0.7);\r\n for (let i = 0; i < n; i++) {\r\n const x = -q + (i / (n - 1)) * q * 2 + wob(rng, q * 0.16);\r\n const len = q * (0.7 + rng() * 0.6);\r\n ctx.beginPath();\r\n ctx.moveTo(x - lean * len * 0.5, -len * 0.5);\r\n ctx.quadraticCurveTo(x + wob(rng, q * 0.2), 0, x + lean * len * 0.5, len * 0.5);\r\n ctx.stroke();\r\n }\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.5;\r\n const n = 2 + ((rng() * 3) | 0);\r\n const step = (q * 2) / n;\r\n ctx.beginPath();\r\n ctx.moveTo(-q, q * 0.4);\r\n for (let i = 0; i < n; i++) {\r\n const x = -q + i * step;\r\n const r = step * (0.42 + rng() * 0.18);\r\n ctx.bezierCurveTo(x + r * 0.2, q * 0.4 - r * 2.1, x + step - r * 0.2, q * 0.4 - r * 2.1, x + step, q * 0.4 + wob(rng, q * 0.14));\r\n }\r\n ctx.stroke();\r\n },\r\n];\r\n\r\nconst specks: Glyph[] = [\r\n (ctx, s, rng) => {\r\n ctx.beginPath();\r\n ctx.arc(0, 0, s * 0.1 + rng() * s * 0.04, 0, Math.PI * 2);\r\n ctx.fill();\r\n },\r\n (ctx, s, rng) => {\r\n ctx.beginPath();\r\n ctx.arc(wob(rng, s * 0.04), wob(rng, s * 0.04), s * 0.32, 0, Math.PI * 2);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const o = s * 0.4;\r\n const i = o * (0.2 + rng() * 0.12);\r\n ctx.beginPath();\r\n ctx.moveTo(0, -o);\r\n ctx.quadraticCurveTo(i, -i, o, 0);\r\n ctx.quadraticCurveTo(i, i, 0, o);\r\n ctx.quadraticCurveTo(-i, i, -o, 0);\r\n ctx.quadraticCurveTo(-i, -i, 0, -o);\r\n ctx.stroke();\r\n },\r\n (ctx, s, rng) => {\r\n const q = s * 0.4;\r\n ctx.beginPath();\r\n ctx.moveTo(-q, wob(rng, s * 0.08));\r\n ctx.quadraticCurveTo(0, wob(rng, s * 0.16), q, wob(rng, s * 0.08));\r\n ctx.stroke();\r\n },\r\n];\r\n\r\n// One per theme, drawn rarely and a touch brighter than the field around it.\r\nconst accents: Record<string, Glyph> = {\r\n light: (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(0, -q);\r\n ctx.quadraticCurveTo(q * 0.16, -q * 0.16, q, 0);\r\n ctx.quadraticCurveTo(q * 0.16, q * 0.16, 0, q);\r\n ctx.quadraticCurveTo(-q * 0.16, q * 0.16, -q, 0);\r\n ctx.quadraticCurveTo(-q * 0.16, -q * 0.16, 0, -q);\r\n ctx.stroke();\r\n },\r\n dark: (ctx, s) => {\r\n const q = s * 0.44;\r\n ctx.beginPath();\r\n ctx.moveTo(-q * 0.6, -q * 0.5);\r\n ctx.lineTo(q * 0.6, -q * 0.5);\r\n ctx.lineTo(q, q * 0.05);\r\n ctx.lineTo(0, q);\r\n ctx.lineTo(-q, q * 0.05);\r\n ctx.closePath();\r\n ctx.moveTo(-q, q * 0.05);\r\n ctx.lineTo(q, q * 0.05);\r\n ctx.moveTo(-q * 0.6, -q * 0.5);\r\n ctx.lineTo(-q * 0.3, q * 0.05);\r\n ctx.lineTo(0, q);\r\n ctx.moveTo(q * 0.6, -q * 0.5);\r\n ctx.lineTo(q * 0.3, q * 0.05);\r\n ctx.lineTo(0, q);\r\n ctx.stroke();\r\n },\r\n mahogany: (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.moveTo(0, q);\r\n ctx.bezierCurveTo(-q * 0.9, q * 0.2, -q * 0.7, -q * 0.7, 0, -q);\r\n ctx.bezierCurveTo(q * 0.7, -q * 0.7, q * 0.9, q * 0.2, 0, q);\r\n ctx.moveTo(0, q * 0.86);\r\n ctx.lineTo(0, -q * 0.86);\r\n for (let i = 0; i < 3; i++) {\r\n const t = -0.34 + i * 0.36;\r\n ctx.moveTo(0, q * t);\r\n ctx.lineTo(q * 0.44, q * (t - 0.26));\r\n ctx.moveTo(0, q * t);\r\n ctx.lineTo(-q * 0.44, q * (t - 0.26));\r\n }\r\n ctx.stroke();\r\n },\r\n blush: (ctx, s) => {\r\n const q = s * 0.5;\r\n for (let i = 0; i < 5; i++) {\r\n const a = (i / 5) * Math.PI * 2 - Math.PI / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(Math.cos(a) * q * 0.52, Math.sin(a) * q * 0.52, q * 0.42, q * 0.26, a, 0, Math.PI * 2);\r\n ctx.stroke();\r\n }\r\n ctx.beginPath();\r\n ctx.arc(0, 0, q * 0.19, 0, Math.PI * 2);\r\n ctx.stroke();\r\n },\r\n coffee: (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n ctx.ellipse(0, 0, q * 0.6, q * 0.9, 0, 0, Math.PI * 2);\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.moveTo(0, -q * 0.84);\r\n ctx.bezierCurveTo(q * 0.34, -q * 0.3, -q * 0.34, q * 0.3, 0, q * 0.84);\r\n ctx.stroke();\r\n },\r\n midnight: (ctx, s) => {\r\n const q = s * 0.5;\r\n ctx.beginPath();\r\n for (let i = 0; i < 10; i++) {\r\n const r = i % 2 === 0 ? q : q * 0.4;\r\n const a = (i / 10) * Math.PI * 2 - Math.PI / 2;\r\n const x = Math.cos(a) * r;\r\n const y = Math.sin(a) * r;\r\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\r\n }\r\n ctx.closePath();\r\n ctx.stroke();\r\n },\r\n};\r\n\r\nconst rgb = (s: string): [number, number, number] => {\r\n const p = s.split(',').map(n => parseFloat(n.trim()));\r\n return [p[0] || 0, p[1] || 0, p[2] || 0];\r\n};\r\n\r\nfunction mix(a: string, b: string, k: number): string {\r\n const A = rgb(a);\r\n const B = rgb(b);\r\n return `rgb(${Math.round(A[0] + (B[0] - A[0]) * k)},${Math.round(A[1] + (B[1] - A[1]) * k)},${Math.round(A[2] + (B[2] - A[2]) * k)})`;\r\n}\r\n\r\ninterface DoodleGlyph {\r\n x: number;\r\n y: number;\r\n roll: number;\r\n rotation: number;\r\n lineWidth: number;\r\n alpha: number;\r\n baseColor: string;\r\n shimmerColor: string;\r\n drawFn: (ctx: CanvasRenderingContext2D, size: number, rng: Rng) => void;\r\n size: number;\r\n seed: number;\r\n normDist: number;\r\n}\r\n\r\nfunction getShimmerColor(seed: number, normDist: number, isDarkMode: boolean): string {\r\n // Exact rainbow spectrum as the animated placeholder text (0 -> 300 hue)\r\n const hue = Math.round((normDist * 300) % 360);\r\n const sat = isDarkMode ? 72 : 68;\r\n const light = isDarkMode ? 58 : 46;\r\n return `hsl(${hue}, ${sat}%, ${light}%)`;\r\n}\r\n\r\nfunction generateGlyphs(\r\n w: number,\r\n h: number,\r\n ink: string,\r\n tint: string,\r\n seed: number,\r\n isRTL: boolean,\r\n themeId?: string,\r\n): DoodleGlyph[] {\r\n const accent = themeId ? accents[themeId] : undefined;\r\n const rng = mulberry32(seed);\r\n const noise = makeNoise(mulberry32(seed ^ 0x9e3779b9));\r\n\r\n const area = w * h;\r\n const target = Math.max(40, Math.min(520, Math.round(area / 3100)));\r\n const raw = target / 0.48;\r\n const r = Math.max(26, Math.sqrt((0.7 * area) / raw));\r\n const pts = poisson(w, h, r, rng);\r\n\r\n const fa = 4.4 / Math.max(w, h);\r\n const fb = fa * 2.6;\r\n const reach = Math.hypot(w, h);\r\n const angle = rng() * Math.PI * 2;\r\n const ca = Math.cos(angle);\r\n const sa = Math.sin(angle);\r\n const poleX = w * (0.18 + rng() * 0.64);\r\n const poleY = h * (0.12 + rng() * 0.5);\r\n\r\n const glyphs: DoodleGlyph[] = [];\r\n const maxDist = Math.hypot(w, h) || 1;\r\n // light ink means it is being drawn onto a dark surface\r\n const [ir, ig, ib] = ink.split(',').map(n => parseFloat(n) || 0);\r\n const isDarkMode = 0.2126 * ir + 0.7152 * ig + 0.0722 * ib > 128;\r\n\r\n for (const [x, y] of pts) {\r\n const d = noise(x * fa, y * fa) * 0.72 + noise(x * fb, y * fb) * 0.28;\r\n const t = Math.min(1, Math.max(0, (d - 0.26) / 0.44));\r\n if (rng() > t * t * (3 - 2 * t)) continue;\r\n const roll = rng();\r\n const bloom = Math.max(0, 1 - Math.hypot(x - poleX, y - poleY) / (reach * 0.72)) ** 1.6;\r\n const axis = ((x - w / 2) * ca + (y - h / 2) * sa) / reach + 0.5;\r\n const isLightMode = !isDarkMode;\r\n const alphaBase = isLightMode ? 0.055 : 0.028;\r\n const alpha = (alphaBase + rng() * (isLightMode ? 0.04 : 0.025)) * (0.75 + axis * 0.55) * (1 + bloom * 0.4);\r\n\r\n const baseColor = mix(ink, tint, bloom * 0.85);\r\n // RTL: from Bottom-Right (w, h) to Top-Left (0, 0)\r\n // LTR: from Top-Left (0, 0) to Bottom-Right (w, h)\r\n const normDist = isRTL\r\n ? (w - x + h - y) / (w + h || 1)\r\n : (x + y) / (w + h || 1);\r\n\r\n const glyphSeed = (rng() * 0xffffff) | 0;\r\n const shimmerColor = getShimmerColor(glyphSeed, normDist, isDarkMode);\r\n\r\n let rotation = 0;\r\n let lineWidth = isLightMode ? 1.05 + rng() * 0.35 : 0.65 + rng() * 0.35;\r\n let size = 20;\r\n let drawFn = motifs[0];\r\n let alphaMul = 1;\r\n\r\n if (roll < 0.5) {\r\n rotation = wob(rng, 0.16);\r\n lineWidth = isLightMode ? 1.15 + rng() * 0.45 : 0.7 + rng() * 0.35;\r\n size = 20 + rng() * 16;\r\n drawFn = motifs[(rng() * motifs.length) | 0];\r\n } else if (roll < 0.82) {\r\n rotation = rng() * Math.PI * 2;\r\n lineWidth = isLightMode ? 0.95 + rng() * 0.4 : 0.6 + rng() * 0.4;\r\n size = 16 + rng() * 20;\r\n drawFn = scribbles[(rng() * scribbles.length) | 0];\r\n } else if (roll < 0.95 || !accent) {\r\n rotation = rng() * Math.PI * 2;\r\n lineWidth = isLightMode ? 0.85 + rng() * 0.35 : 0.55 + rng() * 0.35;\r\n size = 7 + rng() * 7;\r\n drawFn = specks[(rng() * specks.length) | 0];\r\n } else {\r\n rotation = wob(rng, 0.3);\r\n lineWidth = isLightMode ? 1.1 + rng() * 0.3 : 0.75 + rng() * 0.3;\r\n size = 15 + rng() * 9;\r\n drawFn = accent;\r\n alphaMul = 2.6;\r\n }\r\n\r\n glyphs.push({\r\n x,\r\n y,\r\n roll,\r\n rotation,\r\n lineWidth,\r\n alpha: alpha * alphaMul,\r\n baseColor,\r\n shimmerColor,\r\n drawFn,\r\n size,\r\n seed: glyphSeed,\r\n normDist,\r\n });\r\n }\r\n\r\n return glyphs;\r\n}\r\n\r\nfunction renderDoodles(\r\n ctx: CanvasRenderingContext2D,\r\n glyphs: DoodleGlyph[],\r\n w: number,\r\n h: number,\r\n shimmerProgress: number,\r\n) {\r\n ctx.clearRect(0, 0, w, h);\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n\r\n // Active smooth fluid shimmer wave (-0.2 to 1.4)\r\n const isShimmering = shimmerProgress >= 0 && shimmerProgress <= 1.4;\r\n const wavePos = isShimmering ? shimmerProgress * 1.4 - 0.2 : -999;\r\n const waveWidth = 0.30;\r\n\r\n for (const g of glyphs) {\r\n let alpha = g.alpha;\r\n let stroke = g.baseColor;\r\n let lw = g.lineWidth;\r\n\r\n if (isShimmering) {\r\n const diff = g.normDist - wavePos;\r\n\r\n // Ahead of wave: subtle dormant state\r\n if (diff > waveWidth) {\r\n alpha = g.alpha * 0.45;\r\n stroke = g.baseColor;\r\n lw = g.lineWidth;\r\n }\r\n // Behind wave (wake): permanently awake resting state\r\n else if (diff < -waveWidth) {\r\n alpha = g.alpha;\r\n stroke = g.baseColor;\r\n lw = g.lineWidth;\r\n }\r\n // In wavefront beam: soft, delicate rainbow/silver glint\r\n else {\r\n const surge = Math.cos((diff / waveWidth) * (Math.PI / 2)) ** 2;\r\n alpha = g.alpha + surge * 0.08;\r\n stroke = surge > 0.08 ? mix(g.baseColor, g.shimmerColor, surge * 0.65) : g.baseColor;\r\n lw = g.lineWidth * (1 + surge * 0.2);\r\n }\r\n }\r\n\r\n ctx.save();\r\n ctx.translate(g.x, g.y);\r\n ctx.rotate(g.rotation);\r\n ctx.globalAlpha = Math.min(alpha, 1.0);\r\n ctx.strokeStyle = stroke;\r\n ctx.fillStyle = stroke;\r\n ctx.lineWidth = lw;\r\n\r\n const glyphRng = mulberry32(g.seed);\r\n g.drawFn(ctx, g.size, glyphRng);\r\n ctx.restore();\r\n }\r\n}\r\n\r\nconst KikuDoodles = React.memo(function KikuDoodles({\r\n seed = '',\r\n theme,\r\n dir,\r\n}: {\r\n seed?: string;\r\n theme?: string;\r\n dir?: string;\r\n}) {\r\n const ref = useRef<HTMLCanvasElement>(null);\r\n const isAnimatingRef = useRef(false);\r\n const animFrameRef = useRef(0);\r\n const cachedGlyphsRef = useRef<DoodleGlyph[] | null>(null);\r\n const lastWidthRef = useRef<number>(0);\r\n\r\n useEffect(() => {\r\n const cv = ref.current;\r\n if (!cv) return;\r\n\r\n const numeric = hashSeed(seed || 'kiku');\r\n let timer = 0;\r\n\r\n const tick = (startTime: number, duration: number, glyphs: DoodleGlyph[], isRTL: boolean) => (now: number) => {\r\n const elapsed = now - startTime;\r\n const rawProgress = Math.min(1, elapsed / duration);\r\n const eased = (1 - Math.cos(rawProgress * Math.PI)) / 2;\r\n const progress = eased * 1.4;\r\n\r\n const w = cv.clientWidth;\r\n const h = cv.clientHeight;\r\n if (w && h) {\r\n const dpr = Math.min(window.devicePixelRatio || 1, 3);\r\n const targetW = Math.round(w * dpr);\r\n const targetH = Math.round(h * dpr);\r\n if (cv.width !== targetW || cv.height !== targetH) {\r\n cv.width = targetW;\r\n cv.height = targetH;\r\n }\r\n const ctx = cv.getContext('2d');\r\n if (ctx) {\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n renderDoodles(ctx, glyphs, w, h, progress);\r\n }\r\n }\r\n\r\n if (rawProgress < 1) {\r\n animFrameRef.current = requestAnimationFrame(tick(startTime, duration, glyphs, isRTL));\r\n } else {\r\n isAnimatingRef.current = false;\r\n const w = cv.clientWidth;\r\n const h = cv.clientHeight;\r\n const ctx = cv.getContext('2d');\r\n if (ctx && w && h) {\r\n const dpr = Math.min(window.devicePixelRatio || 1, 3);\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n renderDoodles(ctx, glyphs, w, h, -1);\r\n }\r\n }\r\n };\r\n\r\n const updateCanvas = () => {\r\n const w = cv.clientWidth;\r\n const h = cv.clientHeight;\r\n if (!w || !h) return;\r\n\r\n const dpr = Math.min(window.devicePixelRatio || 1, 3);\r\n const ctx = cv.getContext('2d');\r\n if (!ctx) return;\r\n\r\n const cs = getComputedStyle(cv);\r\n const ink = cs.getPropertyValue('--hsk-doodle-ink').trim() || '31,31,31';\r\n const tint = cs.getPropertyValue('--hsk-doodle-tint').trim() || ink;\r\n const isRTL = dir === 'rtl' || cs.direction === 'rtl' || cv.closest('[dir=\"rtl\"]') !== null;\r\n\r\n const fullScreenH = typeof window !== 'undefined' ? Math.max(h, window.innerHeight || 0) : h;\r\n\r\n const glyphs = generateGlyphs(w, fullScreenH, ink, tint, numeric, isRTL, theme);\r\n cachedGlyphsRef.current = glyphs;\r\n lastWidthRef.current = w;\r\n\r\n const targetW = Math.round(w * dpr);\r\n const targetH = Math.round(h * dpr);\r\n if (cv.width !== targetW || cv.height !== targetH) {\r\n cv.width = targetW;\r\n cv.height = targetH;\r\n }\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n\r\n const reducedMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches;\r\n\r\n if (reducedMotion) {\r\n renderDoodles(ctx, glyphs, w, h, -1);\r\n return;\r\n }\r\n\r\n cancelAnimationFrame(animFrameRef.current);\r\n isAnimatingRef.current = true;\r\n const duration = 1200;\r\n const startTime = performance.now();\r\n animFrameRef.current = requestAnimationFrame(tick(startTime, duration, glyphs, isRTL));\r\n };\r\n\r\n const handleResize = () => {\r\n clearTimeout(timer);\r\n timer = window.setTimeout(updateCanvas, 20);\r\n };\r\n\r\n updateCanvas();\r\n\r\n const ro = new ResizeObserver(handleResize);\r\n ro.observe(cv);\r\n const scheme = window.matchMedia?.('(prefers-color-scheme: dark)');\r\n const handleSchemeChange = () => {\r\n updateCanvas();\r\n };\r\n scheme?.addEventListener?.('change', handleSchemeChange);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n cancelAnimationFrame(animFrameRef.current);\r\n isAnimatingRef.current = false;\r\n ro.disconnect();\r\n scheme?.removeEventListener?.('change', handleSchemeChange);\r\n };\r\n }, [seed, theme, dir]);\r\n\r\n return <canvas className=\"hsk-cb-doodles\" ref={ref} aria-hidden=\"true\" />;\r\n});\r\n\r\nexport default KikuDoodles;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport type { ScriptFont, AkropolysTheme } from '@akropolys/sdk';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { useScriptFontFace, preloadScriptFont } from '../../../utils/hostFont';\r\nimport { cachedBaseFont } from '../../../utils/chromeWarm';\r\nimport { DEFAULT_UI_STRINGS, getLoadingMeta, type UIStringKey } from '../types';\r\nimport BUILTIN_LOCALES from '../locales.json';\r\n\r\nexport interface UseScriptFontOptions {\r\n shopperLanguage: string;\r\n theme?: 'light' | 'dark' | AkropolysTheme;\r\n}\r\n\r\nfunction getBuiltinLocale(lang: string): { strings: Record<string, string>; dir: string; bcp47: string } | null {\r\n if (!lang) return null;\r\n const l = lang.trim().toLowerCase();\r\n const map: Record<string, string> = {\r\n english: 'english',\r\n en: 'english',\r\n swahili: 'swahili',\r\n kiswahili: 'swahili',\r\n sw: 'swahili',\r\n french: 'french',\r\n français: 'french',\r\n francais: 'french',\r\n fr: 'french',\r\n spanish: 'spanish',\r\n español: 'spanish',\r\n espanol: 'spanish',\r\n es: 'spanish',\r\n arabic: 'arabic',\r\n 'العربية': 'arabic',\r\n ar: 'arabic',\r\n portuguese: 'portuguese',\r\n português: 'portuguese',\r\n pt: 'portuguese',\r\n hindi: 'hindi',\r\n 'हिन्दी': 'hindi',\r\n hi: 'hindi',\r\n chinese: 'chinese',\r\n '中文': 'chinese',\r\n zh: 'chinese',\r\n japanese: 'japanese',\r\n '日本語': 'japanese',\r\n ja: 'japanese',\r\n urdu: 'urdu',\r\n 'اردو': 'urdu',\r\n ur: 'urdu',\r\n };\r\n const key = map[l];\r\n if (!key || !(key in BUILTIN_LOCALES)) return null;\r\n const raw = (BUILTIN_LOCALES as Record<string, Record<string, string>>)[key];\r\n const isRtl = key === 'arabic' || key === 'urdu';\r\n const bcp = key === 'arabic' ? 'ar' :\r\n key === 'hindi' ? 'hi' :\r\n key === 'chinese' ? 'zh' :\r\n key === 'japanese' ? 'ja' :\r\n key === 'urdu' ? 'ur' :\r\n key === 'swahili' ? 'sw' :\r\n key === 'french' ? 'fr' :\r\n key === 'spanish' ? 'es' :\r\n key === 'portuguese' ? 'pt' : 'en';\r\n return {\r\n strings: raw,\r\n dir: isRtl ? 'rtl' : 'ltr',\r\n bcp47: bcp,\r\n };\r\n}\r\n\r\nfunction resolveFirstFamily(varRef: string): string {\r\n const name = /var\\(\\s*(--[\\w-]+)/.exec(varRef)?.[1];\r\n if (!name || typeof document === 'undefined') return '';\r\n for (const el of [document.documentElement, document.body]) {\r\n const value = el ? getComputedStyle(el).getPropertyValue(name).trim() : '';\r\n if (value) return value.split(',')[0].trim();\r\n }\r\n return '';\r\n}\r\n\r\nexport function useScriptFont({ shopperLanguage, theme }: UseScriptFontOptions) {\r\n const client = useAkropolysContext();\r\n const [chromeStrings, setChromeStrings] = useState<Record<string, string>>(() => {\r\n const builtin = getBuiltinLocale(shopperLanguage);\r\n return builtin?.strings || {};\r\n });\r\n const [chromeCurated, setChromeCurated] = useState<boolean>(true);\r\n const [chromeReady, setChromeReady] = useState<boolean>(() => {\r\n return !shopperLanguage || !!getBuiltinLocale(shopperLanguage);\r\n });\r\n\r\n const dirKey = shopperLanguage ? `akropolys_ui_dir_${shopperLanguage.toLowerCase()}` : '';\r\n const [isRTL, setIsRTL] = useState<boolean>(() => {\r\n const builtin = getBuiltinLocale(shopperLanguage);\r\n if (builtin) return builtin.dir === 'rtl';\r\n const meta = getLoadingMeta(shopperLanguage);\r\n if (meta?.rtl) return true;\r\n if (typeof window === 'undefined' || !dirKey) return false;\r\n try { return localStorage.getItem(dirKey) === 'rtl'; } catch { return false; }\r\n });\r\n const [speechLang, setSpeechLang] = useState(() => {\r\n return getBuiltinLocale(shopperLanguage)?.bcp47 || '';\r\n });\r\n const [scriptFont, setScriptFont] = useState<ScriptFont | null>(null);\r\n const [baseFont, setBaseFont] = useState<ScriptFont | null>(null);\r\n\r\n useEffect(() => {\r\n if (!shopperLanguage) {\r\n setSpeechLang('');\r\n setScriptFont(null);\r\n setChromeStrings({});\r\n setChromeReady(true);\r\n setIsRTL(false);\r\n return;\r\n }\r\n const builtin = getBuiltinLocale(shopperLanguage);\r\n const meta = getLoadingMeta(shopperLanguage);\r\n if (builtin) {\r\n setChromeStrings(builtin.strings);\r\n setIsRTL(builtin.dir === 'rtl');\r\n setSpeechLang(builtin.bcp47);\r\n setChromeReady(true);\r\n } else {\r\n if (meta?.rtl) setIsRTL(true);\r\n setChromeReady(false);\r\n }\r\n\r\n let cancelled = false;\r\n (async () => {\r\n try {\r\n const res = await client.getUIStrings?.(shopperLanguage, DEFAULT_UI_STRINGS);\r\n if (!cancelled && res?.complete) {\r\n setChromeCurated(res.curated !== false);\r\n setChromeStrings(prev => ({ ...(builtin?.strings || {}), ...res.strings }));\r\n setIsRTL(res.dir === 'rtl');\r\n setSpeechLang(res.bcp47 || builtin?.bcp47 || '');\r\n try { localStorage.setItem(dirKey, res.dir); } catch { }\r\n // fire-and-forget: the face declares font-display:swap, so blocking the\r\n // chrome on a ~160KB woff2 only delays text that would render anyway\r\n if (res.font) void preloadScriptFont(res.font, 250);\r\n setScriptFont(res.font ?? null);\r\n }\r\n } catch {\r\n /* Builtin or defaults */\r\n }\r\n if (!cancelled) setChromeReady(true);\r\n })();\r\n return () => { cancelled = true; };\r\n }, [shopperLanguage, dirKey, client]);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n (async () => {\r\n try {\r\n const f = await cachedBaseFont(client);\r\n if (!cancelled && f) setBaseFont(f);\r\n } catch {\r\n\r\n }\r\n })();\r\n return () => { cancelled = true; };\r\n }, [client]);\r\n\r\n useScriptFontFace(scriptFont);\r\n useScriptFontFace(baseFont);\r\n\r\n const fontStack = React.useMemo(() => {\r\n const declared = typeof theme === 'object' && theme?.fontFamily ? theme.fontFamily : '';\r\n const first = declared.split(',')[0].trim();\r\n const isVarRef = /^var\\(/i.test(first);\r\n const hostName = first.replace(/^['\"]|['\"]$/g, '');\r\n const resolved = isVarRef ? resolveFirstFamily(first) : '';\r\n const host = isVarRef\r\n ? (resolved ? `${resolved}, ` : '')\r\n : (hostName ? `\"${hostName}\", ` : '');\r\n\r\n if (scriptFont) {\r\n return `${host}\"Geist\", \"${scriptFont.family}\", system-ui, sans-serif`;\r\n }\r\n\r\n const l = shopperLanguage ? shopperLanguage.trim().toLowerCase() : '';\r\n if (l === 'japanese' || l === 'ja' || l === '日本語') {\r\n return `${host}\"Geist\", \"Hiragino Sans\", \"Hiragino Kaku Gothic ProN\", \"Yu Gothic\", \"Meiryo\", system-ui, sans-serif`;\r\n }\r\n if (l === 'chinese' || l === 'zh' || l === '中文') {\r\n return `${host}\"Geist\", \"PingFang SC\", \"Microsoft YaHei\", \"Hiragino Sans GB\", system-ui, sans-serif`;\r\n }\r\n if (l === 'urdu' || l === 'ur' || l === 'اردو') {\r\n return `${host}\"Noto Nastaliq Urdu\", \"IBM Plex Sans Arabic\", \"Geist\", system-ui, sans-serif`;\r\n }\r\n if (l === 'arabic' || l === 'ar' || l === 'العربية') {\r\n return `${host}\"IBM Plex Sans Arabic\", \"Geist\", system-ui, sans-serif`;\r\n }\r\n if (l === 'hindi' || l === 'hi' || l === 'हिन्दी') {\r\n return `${host}\"Hind\", \"Geist\", system-ui, sans-serif`;\r\n }\r\n\r\n return undefined;\r\n }, [scriptFont, shopperLanguage, typeof theme === 'object' && theme ? theme.fontFamily : undefined]);\r\n\r\n const isNonLatin = React.useMemo(() => {\r\n let latin = 0;\r\n let other = 0;\r\n for (const v of Object.values(chromeStrings)) {\r\n for (const ch of v) {\r\n const c = ch.codePointAt(0) ?? 0;\r\n if (c < 0x00c0) continue;\r\n if (!/\\p{L}/u.test(ch)) continue;\r\n if (c <= 0x024f) latin++;\r\n else other++;\r\n }\r\n }\r\n return other > latin;\r\n }, [chromeStrings]);\r\n\r\n const [fontEpoch, setFontEpoch] = useState(0);\r\n useEffect(() => {\r\n if (typeof document === 'undefined' || !(document as any).fonts?.ready) return;\r\n let live = true;\r\n (document as any).fonts.ready.then(() => {\r\n if (live) setFontEpoch(e => e + 1);\r\n });\r\n return () => { live = false; };\r\n }, [scriptFont]);\r\n\r\n const hostFontCovers = React.useMemo(() => {\r\n if (!isNonLatin || typeof document === 'undefined') return true;\r\n const declared = typeof theme === 'object' && theme?.fontFamily ? theme.fontFamily : '';\r\n const first = declared.split(',')[0].trim();\r\n if (!first) return false;\r\n let sample = '';\r\n for (const v of Object.values(chromeStrings)) {\r\n if (v) { sample = v; break; }\r\n }\r\n if (!sample) return true;\r\n const text = sample.replace(/\\s+/g, '');\r\n if (!text) return true;\r\n try {\r\n const canvas = document.createElement('canvas');\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return true;\r\n const hostFamily = first.startsWith('var(')\r\n ? getComputedStyle(document.documentElement).getPropertyValue(first.slice(4, -1).trim()).trim() || first\r\n : first;\r\n ctx.font = `16px ${hostFamily}, __akropolys_nonexistent_font__`;\r\n const withHost = ctx.measureText(text).width;\r\n ctx.font = '16px __akropolys_nonexistent_font__';\r\n const withoutHost = ctx.measureText(text).width;\r\n return Math.abs(withHost - withoutHost) > 1;\r\n } catch {\r\n return true;\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [isNonLatin, chromeStrings, typeof theme === 'object' && theme ? theme.fontFamily : undefined, fontEpoch]);\r\n\r\n const t = useCallback((key: UIStringKey, vars?: Record<string, string>): string => {\r\n let s: string = chromeStrings[key] || DEFAULT_UI_STRINGS[key] || key;\r\n if (vars) {\r\n for (const [k, v] of Object.entries(vars)) s = s.split(`{${k}}`).join(v);\r\n }\r\n return s;\r\n }, [chromeStrings]);\r\n\r\n const tNode = useCallback((key: UIStringKey, vars: Record<string, string>) => {\r\n const s = chromeStrings[key] || DEFAULT_UI_STRINGS[key] || key;\r\n return s.split(/(\\{[a-zA-Z]+\\})/g).map((part, i) => {\r\n const m = part.match(/^\\{([a-zA-Z]+)\\}$/);\r\n if (m && vars[m[1]] !== undefined) return <bdi key={i}>{vars[m[1]]}</bdi>;\r\n return <React.Fragment key={i}>{part}</React.Fragment>;\r\n });\r\n }, [chromeStrings]);\r\n\r\n return {\r\n chromeStrings,\r\n chromeReady,\r\n chromeCurated,\r\n isRTL,\r\n speechLang,\r\n scriptFont,\r\n fontStack,\r\n isNonLatin,\r\n hostFontCovers,\r\n t,\r\n tNode,\r\n };\r\n}\r\n","{\n \"arabic\": {\n \"allSet\": \"أنت جاهز، {name}.\",\n \"asWritten\": \"كما هي مكتوبة\",\n \"captureAll\": \"التقاط الكل ({count})\",\n \"captureAndRemember\": \"kiku — التقاط وتذكر\",\n \"captureCurrentPage\": \"التقاط الصفحة الحالية\",\n \"cardClickAnswer\": \"الـ {name}\",\n \"cardClickQuery\": \"أخبرني المزيد عن {name}{price} — ما هي تفاصيله الرئيسية، ولمن هو الأنسب، وماذا يجب أن أعرف؟\",\n \"clearChat\": \"مسح الدردشة\",\n \"defaultPlaceholder\": \"اسألني أي شيء...\",\n \"deleteThis\": \"حذف هذا\",\n \"detailsTranslated\": \"تمت ترجمة التفاصيل. تبقى الأرقام والروابط كما هي تمامًا.\",\n \"displayCapture\": \"التقاط {name}\",\n \"displayCaptureAll\": \"التقاط الكل ({count} عناصر)\",\n \"displayDelete\": \"حذف هذا\",\n \"displayViewHistory\": \"ماذا حفظت؟\",\n \"entityLangIntro\": \"أنا أرد بـ {lang}. يمكن أن تبقى بطاقات النتائج كما كتبها هذا الموقع تمامًا، أو يمكن ترجمتها أيضًا.\",\n \"entityLangPlaceholder\": \"اختر إحدى البطاقتين أعلاه...\",\n \"errAccessRevoked\": \"تم إلغاء وصولك إلى المساعد من قبل المتجر.\",\n \"errAccountRequired\": \"الرجاء إنشاء حساب لمتابعة استخدام مساعد الدردشة.\",\n \"errShopperReplyLimit\": \"لقد وصلت إلى حد الردود المسموح به لحسابك في هذا الموقع.\",\n \"errStreamInterrupted\": \"تمت مقاطعة الرد. الرجاء المحاولة مرة أخرى.\",\n \"errTokenLimit\": \"لقد وصلت إلى حد الاستخدام الخاص بك. الرجاء تحديث حدود الفواتير في لوحة التحكم الخاصة بك للمتابعة.\",\n \"errTooManyRequests\": \"يتلقى المساعد حاليًا عددًا كبيرًا جدًا من الطلبات. الرجاء المحاولة مرة أخرى بعد لحظات قليلة.\",\n \"footerHint\": \"kiku · يبحث في الكتالوج بأكمله في الوقت الفعلي\",\n \"greetReturning\": \"أهلاً، {name}.\",\n \"greetReturningLead\": \"ماذا يمكنني أن أجد لك اليوم؟\",\n \"howShouldResultsLook\": \"كيف يجب أن تبدو النتائج؟\",\n \"inLanguage\": \"بـ {lang}\",\n \"keyAutoHide\": \"يختفي تلقائيًا في {seconds} ثوانٍ.\",\n \"keyCopied\": \"تم النسخ\",\n \"keyCopyId\": \"نسخ المعرّف\",\n \"keyCopySecret\": \"نسخ السر\",\n \"keyCreateNew\": \"أنا جديد — أنشئ واحدًا\",\n \"keyCreating\": \"جارٍ الإنشاء…\",\n \"keyDismiss\": \"تجاهل\",\n \"keyPastePlaceholder\": \"معرّفك العام…\",\n \"keyPastePrompt\": \"الصق معرّفك العام — أو أنشئ واحدًا\",\n \"keyPublicHint\": \"الصقه في أي موقع للحفظ في نفس الذاكرة.\",\n \"keyPublicTitle\": \"معرّفك العام\",\n \"keySecretHint\": \"احتفظ به خاصًا — استخدمه لفتح ذاكرتك.\",\n \"keySecretTitle\": \"سرك — يُعرض مرة واحدة فقط\",\n \"keyUseMine\": \"استخدم معرّفي\",\n \"kikuActionUnavailable\": \"عذرًا — هذا الإجراء غير متاح على هذا الموقع.\",\n \"kikuCaptureDbError\": \"فشل الالتقاط بسبب خطأ في قاعدة البيانات.\",\n \"kikuCaptureNoContext\": \"فشل الالتقاط لأنه لم يتم توفير سياق الصفحة أو المنتج بواسطة SDK.\",\n \"kikuCaptureNoUrl\": \"تعذر حفظ أي عناصر — لم يكن لأي منها عنوان URL صالح.\",\n \"kikuCaptureNoneSelected\": \"لم يتم تحديد أي عناصر لالتقاطها.\",\n \"kikuDeleteDbError\": \"فشل الحذف بسبب خطأ في قاعدة البيانات.\",\n \"kikuDeleteDone\": \"تمت إزالته من العناصر المحفوظة لديك.\",\n \"kikuDeleteNoContext\": \"فشل الحذف لأنه لم يتم توفير سياق الصفحة لتحديد ما يجب حذفه.\",\n \"kikuMemoryIntro\": \"كل ما التقطته عبر المواقع موجود في ذاكرتك الخاصة. افتحها باستخدام سرك:\",\n \"kikuMintNeeded\": \"لحفظ العناصر عبر المواقع، تحتاج إلى مفتاح kiku — سأقوم بإنشاء واحد لك. يُعرض مرة واحدة فقط، لذا احفظه في مكان آمن.\",\n \"kikuMintOffer\": \"يمكنني الاحتفاظ بهذا لك ومتابعته معك عبر المواقع — سأقوم بإنشاء مفتاح kiku لك. يُعرض مرة واحدة فقط، لذا احفظه في مكان آمن.\",\n \"kikuNeedKeyToUpdate\": \"أدخل مفتاح kiku الخاص بك حتى أتمكن من العثور على العناصر المحفوظة لديك وتحديثها.\",\n \"micDenied\": \"تم حظر الميكروفون. اسمح بالوصول إلى الميكروفون لهذا الموقع، ثم حاول مرة أخرى.\",\n \"micFailed\": \"لم أتمكن من سماع ذلك. حاول مرة أخرى.\",\n \"micInsecure\": \"يتطلب الصوت اتصالاً آمنًا (https).\",\n \"micLangUnsupported\": \"لا يمكن لهذا المتصفح نسخ هذه اللغة بعد. يرجى الكتابة بدلاً من ذلك.\",\n \"micMissing\": \"لم يتم العثور على ميكروفون.\",\n \"micNetwork\": \"تتطلب ميزة الصوت اتصالاً الآن. يرجى التحقق من اتصالك والمحاولة مرة أخرى.\",\n \"micNoSpeech\": \"لم أسمع شيئًا. يرجى المحاولة مرة أخرى، واقترب قليلاً من الميكروفون.\",\n \"namePlaceholder\": \"اكتب اسمك...\",\n \"nameStepAsk\": \"ماذا يجب أن أناديك؟\",\n \"nameStepLead\": \"يمكنني البحث عن أي شيء أو تصوره أو التقاطه لك — في هذا الموقع أو أي موقع آخر.\",\n \"nameStepTitle\": \"سررت بلقائك.\",\n \"namesAsWritten\": \"الأسماء والتفاصيل تمامًا كما هي مدرجة في الموقع.\",\n \"pillCompareTop2\": \"قارن أفضل 2\",\n \"pillCompareTop2Query\": \"قارن بين {a} و {b}\",\n \"pillFindAlternatives\": \"ابحث عن بدائل\",\n \"pillFindAlternativesQuery\": \"ما هي البدائل الجيدة لـ {name}؟\",\n \"pillMoreOn\": \"المزيد عن {name}\",\n \"pillMoreOnQuery\": \"أخبرني المزيد عن {name}\",\n \"pillRecommend\": \"أوصِ بشيء\",\n \"pillRecommendQuery\": \"ماذا توصي لي؟\",\n \"pillShowPopular\": \"عرض العناصر الشائعة\",\n \"pillShowPopularQuery\": \"ما هي منتجاتك الأكثر شعبية؟\",\n \"pillSimilarOptions\": \"خيارات مشابهة\",\n \"pillSimilarOptionsQuery\": \"أرني المزيد المشابه لـ {name}\",\n \"pillUnder\": \"أقل من {amount}\",\n \"pillUnderQuery\": \"أظهر لي خيارات بسعر أقل من {amount}\",\n \"pillWhichBest\": \"أيهما الأفضل؟\",\n \"pillWhichBestQuery\": \"أيهما توصي ولماذا؟\",\n \"replyingOriginal\": \"أردّ باللغة {lang}، والنتائج كما كتبها هذا الموقع. اسألني أي شيء.\",\n \"replyingTranslated\": \"أردّ باللغة {lang}، والنتائج مترجمة أيضًا. اسألني أي شيء.\",\n \"statusSent\": \"تم الإرسال\",\n \"statusStopped\": \"تم الإرسال · تم إيقاف الرد\",\n \"thinking\": \"جاري التفكير\",\n \"thoughtForSeconds\": \"فكرت لمدة {duration}\",\n \"thoughtProcess\": \"عملية التفكير\",\n \"vizDisclaimerImage\": \"تم الإنشاء باستخدام الذكاء الاصطناعي — قد تختلف الألوان والحجم والموضع عن المنتج الحقيقي.\",\n \"vizDisclaimerVideo\": \"تم الإنشاء باستخدام الذكاء الاصطناعي — قد تختلف الألوان والحجم والحركة عن المنتج الحقيقي.\",\n \"vizUnavailable\": \"تعذر تحميل المعاينة.\",\n \"voiceListening\": \"جاري الاستماع... اضغط على الميكروفون للإيقاف\",\n \"voiceSending\": \"تمام — جاري الإرسال...\",\n \"termsStepTitle\": \"الخصوصية وشروط الاستخدام\",\n \"termsStepSubtitle\": \"شفافية كاملة، وهوية مجهولة، وبدون جمع أي بيانات شخصية.\",\n \"termsPiiTitle\": \"عدم جمع البيانات الشخصية\",\n \"termsPiiDesc\": \"نحن لا نجمع أو نطلب أو نخزن أي معلومات تعريف شخصية (لا بريد إلكتروني، لا أرقام هواتف، ولا هويات حقيقية) من محادثاتك أو جلساتك الصوتية.\",\n \"termsSessionTitle\": \"معرّفات جلسة مجهولة\",\n \"termsSessionDesc\": \"تستخدم جلستك معرّفًا مجهولاً من جانب العميل فقط للحفاظ على السياق، ولا يتم ربطه بهويتك الحقيقية أبداً.\",\n \"termsMemoryTitle\": \"محادثات مؤقتة مقابل خزينة ميمي\",\n \"termsMemoryDesc\": \"المحادثات العادية مؤقتة — إغلاق النافذة أو مسح الدردشة ينهيها نهائيًا. العناصر التي تحفظها عبر \\\"@kiku\\\" مشفرة ويمكن فتحها في mimi.akropolys.cloud باستخدام مفتاحك السري.\",\n \"termsCookieTitle\": \"بيانات تتبع الموقع المضيف\",\n \"termsCookieDesc\": \"قد يقوم الموقع المضيف بجمع ملفات تعريف الارتباط والتحليلات وفقًا لسياسة ملفات تعريف الارتباط الخاصة به، وهي خارجة عن سيطرة kiku.\",\n \"termsAgreeButton\": \"الموافقة والمتابعة\",\n \"termsAgreeCounting\": \"الموافقة والمتابعة ({seconds} ث)\",\n \"termsPlaceholder\": \"يرجى مراجعة وقبول الخصوصية والشروط أعلاه...\",\n \"whatHaveYouSaved\": \"ماذا حفظت؟\",\n \"voiceHint\": \"تحدث فقط — سأجيب عندما تتوقف.\",\n \"voiceModeExit\": \"الخروج من الوضع بدون استخدام اليدين\",\n \"voiceModeStart\": \"محادثة بدون استخدام اليدين\",\n \"voiceMuted\": \"مكتوم\",\n \"voiceMutedHint\": \"اضغط على الميكروفون للتحدث مرة أخرى.\",\n \"voicePhaseListening\": \"استماع\",\n \"voicePhaseSpeaking\": \"تحدث\",\n \"voicePhaseThinking\": \"تفكير\"\n },\n \"chinese\": {\n \"allSet\": \"您已准备好,{name}。\",\n \"asWritten\": \"如原文所示\",\n \"captureAll\": \"捕获全部({count})\",\n \"captureAndRemember\": \"kiku — 捕获并记住\",\n \"captureCurrentPage\": \"捕获当前页面\",\n \"cardClickAnswer\": \"{name}\",\n \"cardClickQuery\": \"告诉我更多关于 {name}{price} — 关键细节是什么,最适合谁,我需要了解什么?\",\n \"clearChat\": \"清除聊天\",\n \"defaultPlaceholder\": \"随便问我任何事…\",\n \"deleteThis\": \"删除此项\",\n \"detailsTranslated\": \"详情已翻译。数字和链接保持原样。\",\n \"displayCapture\": \"捕获 {name}\",\n \"displayCaptureAll\": \"捕获全部({count} 项)\",\n \"displayDelete\": \"删除此项\",\n \"displayViewHistory\": \"我保存了什么?\",\n \"entityLangIntro\": \"我会用 {lang} 回复。结果卡片可以保持网站原文,也可以翻译。\",\n \"entityLangPlaceholder\": \"从上面的两张卡片中选择一个…\",\n \"errAccessRevoked\": \"您的访问权限已被商店撤销。\",\n \"errAccountRequired\": \"请创建账户以继续使用聊天助手。\",\n \"errShopperReplyLimit\": \"您已达到此站点对您账户的回复上限。\",\n \"errStreamInterrupted\": \"回复被中断。请再试一次。\",\n \"errTokenLimit\": \"您已达到使用上限。请在仪表板中更新计费上限以继续。\",\n \"errTooManyRequests\": \"助手当前请求过多。请稍后再试。\",\n \"footerHint\": \"kiku · 实时搜索整个目录\",\n \"greetReturning\": \"您好,{name}。\",\n \"greetReturningLead\": \"今天我能为您找到什么?\",\n \"howShouldResultsLook\": \"结果应该是什么样子?\",\n \"inLanguage\": \"使用 {lang}\",\n \"namePlaceholder\": \"输入您的名字…\",\n \"nameStepAsk\": \"我该怎么称呼您?\",\n \"nameStepLead\": \"我可以为您搜索、可视化或捕获任何内容——在此站点或其他任何站点。\",\n \"nameStepTitle\": \"很高兴见到您。\",\n \"namesAsWritten\": \"名称和详情完全按站点列出。\",\n \"pillCompareTop2\": \"比较前两项\",\n \"pillCompareTop2Query\": \"比较 {a} 和 {b}\",\n \"pillFindAlternatives\": \"寻找替代品\",\n \"pillFindAlternativesQuery\": \"有什么好的替代品可以替代 {name}?\",\n \"pillMoreOn\": \"更多关于 {name}\",\n \"pillMoreOnQuery\": \"告诉我更多关于 {name}\",\n \"pillRecommend\": \"推荐一些东西\",\n \"pillRecommendQuery\": \"您会推荐什么给我?\",\n \"pillShowPopular\": \"显示热门项目\",\n \"pillShowPopularQuery\": \"您最受欢迎的项目是什么?\",\n \"pillSimilarOptions\": \"相似选项\",\n \"pillSimilarOptionsQuery\": \"展示更多类似 {name} 的内容\",\n \"pillUnder\": \"低于 {amount}\",\n \"pillUnderQuery\": \"展示低于 {amount} 的选项\",\n \"pillWhichBest\": \"哪一个最好?\",\n \"pillWhichBestQuery\": \"您会推荐哪一个,为什么?\",\n \"replyingOriginal\": \"用 {lang} 回复,结果保持网站原文。随便问我任何事。\",\n \"replyingTranslated\": \"用 {lang} 回复,结果也已翻译。随便问我任何事。\",\n \"statusSent\": \"已发送\",\n \"statusStopped\": \"已发送 · 回复已停止\",\n \"thinking\": \"思考中\",\n \"thoughtForSeconds\": \"思考了 {duration}\",\n \"thoughtProcess\": \"思考过程\",\n \"termsStepTitle\": \"隐私与使用条款\",\n \"termsStepSubtitle\": \"透明、匿名,从设计之初即零个人身份信息。\",\n \"termsPiiTitle\": \"零个人身份信息收集\",\n \"termsPiiDesc\": \"我们绝不会从您的对话或语音中收集或存储任何个人身份信息(无邮箱、电话号码或真实姓名)。\",\n \"termsSessionTitle\": \"匿名会话凭证\",\n \"termsSessionDesc\": \"您的会话仅使用客户端生成的匿名标识符来维持上下文,绝不与您的真实身份关联。\",\n \"termsMemoryTitle\": \"即时会话 vs. Mimi 记忆库\",\n \"termsMemoryDesc\": \"普通对话完全即时处理——关闭或清除聊天即可彻底销毁。使用 \\\"@kiku\\\" 保存的内容经过加密,可在 mimi.akropolys.cloud 使用您的私钥随时解锁。\",\n \"termsCookieTitle\": \"宿主网站遥测\",\n \"termsCookieDesc\": \"嵌入 kiku 的宿主网站可能会根据其自身的 Cookie 政策收集浏览数据,不受 kiku 控制。\",\n \"termsAgreeButton\": \"同意并继续\",\n \"termsAgreeCounting\": \"同意并继续 ({seconds}秒)\",\n \"termsPlaceholder\": \"请查阅并同意上方的隐私与条款…\",\n \"whatHaveYouSaved\": \"我保存了什么?\",\n \"keyAutoHide\": \"将在 {seconds} 秒后自动隐藏。\",\n \"keyCopied\": \"已复制\",\n \"keyCopyId\": \"复制 ID\",\n \"keyCopySecret\": \"复制密钥\",\n \"keyCreateNew\": \"我是新用户 — 创建一个\",\n \"keyCreating\": \"正在创建…\",\n \"keyDismiss\": \"关闭\",\n \"keyPastePlaceholder\": \"您的公开 ID…\",\n \"keyPastePrompt\": \"粘贴您的公开 ID — 或创建一个\",\n \"keyPublicHint\": \"在任何网站上粘贴此 ID 即可保存到相同的记忆库中。\",\n \"keyPublicTitle\": \"您的公开 ID\",\n \"keySecretHint\": \"请妥善保管 — 用于解锁您的记忆库。\",\n \"keySecretTitle\": \"您的密钥 — 仅显示一次\",\n \"keyUseMine\": \"使用我的 ID\",\n \"kikuActionUnavailable\": \"抱歉 — 此站点暂不支持该操作。\",\n \"kikuCaptureDbError\": \"由于数据库错误,保存失败。\",\n \"kikuCaptureNoContext\": \"由于未提供页面或产品上下文,保存失败。\",\n \"kikuCaptureNoUrl\": \"无法保存任何项目 — 均无有效网址。\",\n \"kikuCaptureNoneSelected\": \"未选择要保存的项目。\",\n \"kikuDeleteDbError\": \"由于数据库错误,删除失败。\",\n \"kikuDeleteDone\": \"已从保存的项目中移除。\",\n \"kikuDeleteNoContext\": \"未提供页面上下文以确定要删除的内容。\",\n \"kikuMemoryIntro\": \"您在各站点保存的所有内容均存储在您的私有记忆库中。使用您的密钥解锁:\",\n \"kikuMintNeeded\": \"要在跨站点保存项目,您需要一个 kiku 密钥 — 我将为您生成一个。该密钥仅显示一次,请妥善保存。\",\n \"kikuMintOffer\": \"我可以为您保存并跟随您跨站点同步 — 我将为您生成一个 kiku 密钥。仅显示一次,请妥善保存。\",\n \"kikuNeedKeyToUpdate\": \"输入您的 kiku 密钥以便我查找并更新您保存的项目。\",\n \"micDenied\": \"麦克风已被阻止。请允许此站点访问麦克风,然后重试。\",\n \"micFailed\": \"未能听清。请重试。\",\n \"micInsecure\": \"语音功能需要安全连接 (HTTPS)。\",\n \"micLangUnsupported\": \"此浏览器暂不支持该语言的语音转录。请使用文字输入。\",\n \"micMissing\": \"未找到麦克风。\",\n \"micNetwork\": \"语音功能需要网络连接。请检查网络后重试。\",\n \"micNoSpeech\": \"未检测到声音。请靠近麦克风后重试。\",\n \"vizDisclaimerImage\": \"由人工智能生成 — 颜色、尺寸和位置可能与实物略有不同。\",\n \"vizDisclaimerVideo\": \"由人工智能生成 — 颜色、尺寸和动作可能与实物略有不同。\",\n \"vizUnavailable\": \"无法加载预览。\",\n \"voiceHint\": \"直接说话即可 — 您停顿后我会回答。\",\n \"voiceListening\": \"正在聆听… 点击麦克风停止\",\n \"voiceModeExit\": \"退出免提模式\",\n \"voiceModeStart\": \"免提对话\",\n \"voiceMuted\": \"静音\",\n \"voiceMutedHint\": \"点击麦克风重新开始说话。\",\n \"voicePhaseListening\": \"正在聆听\",\n \"voicePhaseSpeaking\": \"正在回答\",\n \"voicePhaseThinking\": \"正在思考\",\n \"voiceSending\": \"已收到 — 正在发送…\"\n },\n \"english\": {\n \"allSet\": \"You're all set, {name}.\",\n \"asWritten\": \"As written\",\n \"captureAll\": \"Capture all ({count})\",\n \"captureAndRemember\": \"kiku — capture & remember\",\n \"captureCurrentPage\": \"Capture current page\",\n \"cardClickAnswer\": \"The {name}\",\n \"cardClickQuery\": \"Tell me more about the {name}{price} — what are its key details, who is it best suited for, and what should I know?\",\n \"clearChat\": \"Clear chat\",\n \"defaultPlaceholder\": \"Ask me anything…\",\n \"deleteThis\": \"Delete this\",\n \"detailsTranslated\": \"Details translated. Numbers and links stay exactly as listed.\",\n \"displayCapture\": \"capture {name}\",\n \"displayCaptureAll\": \"capture all ({count} items)\",\n \"displayDelete\": \"delete this\",\n \"displayViewHistory\": \"what have you saved?\",\n \"entityLangIntro\": \"I reply in {lang}. Result cards can stay exactly as this site wrote them, or be translated too.\",\n \"entityLangPlaceholder\": \"Pick one of the two cards above…\",\n \"errAccessRevoked\": \"Your access to the assistant has been revoked by the store.\",\n \"errAccountRequired\": \"Please create an account to continue using the chat assistant.\",\n \"errShopperReplyLimit\": \"You've reached this site's reply limit for your account.\",\n \"errStreamInterrupted\": \"The reply was interrupted. Please try again.\",\n \"errTokenLimit\": \"You've reached your usage limit. Please update your billing limits in your dashboard to continue.\",\n \"errTooManyRequests\": \"The assistant is currently receiving too many requests. Please try again in a few moments.\",\n \"footerHint\": \"kiku · searches the whole catalogue in real time\",\n \"greetReturning\": \"Hi, {name}.\",\n \"greetReturningLead\": \"What can I find for you today?\",\n \"howShouldResultsLook\": \"How should results look?\",\n \"inLanguage\": \"In {lang}\",\n \"keyAutoHide\": \"Hides automatically in {seconds}s.\",\n \"keyCopied\": \"Copied\",\n \"keyCopyId\": \"Copy id\",\n \"keyCopySecret\": \"Copy secret\",\n \"keyCreateNew\": \"I'm new — create one\",\n \"keyCreating\": \"Creating…\",\n \"keyDismiss\": \"Dismiss\",\n \"keyPastePlaceholder\": \"your public id…\",\n \"keyPastePrompt\": \"Paste your public id — or create one\",\n \"keyPublicHint\": \"Paste this on any site to save to the same memory.\",\n \"keyPublicTitle\": \"Your public id\",\n \"keySecretHint\": \"Keep it private — use it to unlock your memory.\",\n \"keySecretTitle\": \"Your secret — shown only once\",\n \"keyUseMine\": \"Use my id\",\n \"kikuActionUnavailable\": \"Sorry — that action isn't available on this site.\",\n \"kikuCaptureDbError\": \"Capture failed due to a database error.\",\n \"kikuCaptureNoContext\": \"Capture failed because no page or product context was provided by the SDK.\",\n \"kikuCaptureNoUrl\": \"Couldn’t save any items — none had a valid URL.\",\n \"kikuCaptureNoneSelected\": \"No items were selected to capture.\",\n \"kikuDeleteDbError\": \"Delete failed due to a database error.\",\n \"kikuDeleteDone\": \"Removed it from your saved items.\",\n \"kikuDeleteNoContext\": \"Delete failed because no page context was provided to identify what to delete.\",\n \"kikuMemoryIntro\": \"Everything you've captured across sites lives in your private memory. Unlock it with your secret:\",\n \"kikuMintNeeded\": \"To save items across sites you need a kiku key — I'll mint one for you. It's shown only once, so save it somewhere safe.\",\n \"kikuMintOffer\": \"I can keep this for you and have it follow you across sites — I'll mint you a kiku key. It's shown only once, so save it somewhere safe.\",\n \"kikuNeedKeyToUpdate\": \"Enter your kiku key so I can find and update your saved items.\",\n \"micDenied\": \"Microphone blocked. Allow mic access for this site, then try again.\",\n \"micFailed\": \"Couldn't hear that. Try again.\",\n \"micInsecure\": \"Voice needs a secure (https) connection.\",\n \"micLangUnsupported\": \"This browser cannot transcribe that language yet. Type instead.\",\n \"micMissing\": \"No microphone found.\",\n \"micNetwork\": \"Voice needs a connection right now. Check yours and try again.\",\n \"micNoSpeech\": \"Didn't catch anything. Try again, a little closer to the mic.\",\n \"namePlaceholder\": \"Type your name…\",\n \"nameStepAsk\": \"What should I call you?\",\n \"nameStepLead\": \"I can search, visualize, or capture anything for you — on this site or any other.\",\n \"nameStepTitle\": \"Nice to meet you.\",\n \"namesAsWritten\": \"Names and details exactly as the site lists them.\",\n \"pillCompareTop2\": \"Compare top 2\",\n \"pillCompareTop2Query\": \"Compare the {a} and {b}\",\n \"pillFindAlternatives\": \"Find alternatives\",\n \"pillFindAlternativesQuery\": \"What are good alternatives to the {name}?\",\n \"pillMoreOn\": \"More on {name}\",\n \"pillMoreOnQuery\": \"Tell me more about the {name}\",\n \"pillRecommend\": \"Recommend something\",\n \"pillRecommendQuery\": \"What do you recommend for me?\",\n \"pillShowPopular\": \"Show popular items\",\n \"pillShowPopularQuery\": \"What are your most popular items?\",\n \"pillSimilarOptions\": \"Similar options\",\n \"pillSimilarOptionsQuery\": \"Show me more like the {name}\",\n \"pillUnder\": \"Under {amount}\",\n \"pillUnderQuery\": \"Show me options under {amount}\",\n \"pillWhichBest\": \"Which is best?\",\n \"pillWhichBestQuery\": \"Which one would you recommend and why?\",\n \"replyingOriginal\": \"Replying in {lang}, results as this site wrote them. Ask me anything.\",\n \"replyingTranslated\": \"Replying in {lang}, results translated too. Ask me anything.\",\n \"statusSent\": \"Sent\",\n \"statusStopped\": \"Sent · reply stopped\",\n \"thinking\": \"Thinking\",\n \"thoughtForSeconds\": \"Thought for {duration}\",\n \"thoughtProcess\": \"Thought process\",\n \"vizDisclaimerImage\": \"Generated using Artificial Intelligence — colours, size and placement may differ from the real product.\",\n \"vizDisclaimerVideo\": \"Generated using Artificial Intelligence — colours, size and movement may differ from the real product.\",\n \"vizUnavailable\": \"The preview could not be loaded.\",\n \"voiceHint\": \"Just talk — I'll answer when you pause.\",\n \"voiceListening\": \"Listening… tap the mic to stop\",\n \"voiceModeExit\": \"Leave hands-free\",\n \"voiceModeStart\": \"Hands-free conversation\",\n \"voiceMuted\": \"Muted\",\n \"voiceMutedHint\": \"Tap the microphone to speak again.\",\n \"voicePhaseListening\": \"Listening\",\n \"voicePhaseSpeaking\": \"Speaking\",\n \"voicePhaseThinking\": \"Thinking\",\n \"voiceSending\": \"Got it — sending…\",\n \"termsStepTitle\": \"Privacy & Terms of Use\",\n \"termsStepSubtitle\": \"Transparent, anonymous, and zero-PII by design.\",\n \"termsPiiTitle\": \"Zero PII Collection\",\n \"termsPiiDesc\": \"We never collect or store personal identifying information (no emails, phone numbers, or real-world identities) from your chats or voice sessions.\",\n \"termsSessionTitle\": \"Anonymous Session Tokens\",\n \"termsSessionDesc\": \"Your session uses an anonymous client-side token solely to maintain context. It is never linked to your real identity.\",\n \"termsMemoryTitle\": \"Ephemeral Chats vs. Mimi Vault\",\n \"termsMemoryDesc\": \"Regular chats are ephemeral — closing the tab or clicking \\\"Clear Chat\\\" terminates them forever. Items you save with \\\"@kiku\\\" are encrypted and can be unlocked at mimi.akropolys.cloud with your Secret Access Key.\",\n \"termsCookieTitle\": \"Host Website Telemetry\",\n \"termsCookieDesc\": \"The host website where Kiku is embedded may collect cookies and analytics per their own cookie policy, outside Kiku's control.\",\n \"termsAgreeButton\": \"Agree & Continue\",\n \"termsAgreeCounting\": \"Agree & Continue ({seconds}s)\",\n \"termsPlaceholder\": \"Please review and accept our Privacy & Terms above…\",\n \"whatHaveYouSaved\": \"What have you saved?\"\n },\n \"french\": {\n \"allSet\": \"C'est tout bon, {name}.\",\n \"asWritten\": \"Tel quel\",\n \"captureAll\": \"Tout capturer ({count})\",\n \"captureAndRemember\": \"kiku — capturer et mémoriser\",\n \"captureCurrentPage\": \"Capturer la page actuelle\",\n \"cardClickAnswer\": \"Le {name}\",\n \"cardClickQuery\": \"Dites-m'en plus sur le {name}{price} : ses caractéristiques principales, à qui il convient le mieux et ce que je devrais savoir.\",\n \"clearChat\": \"Effacer le chat\",\n \"defaultPlaceholder\": \"Posez-moi n'importe quelle question…\",\n \"deleteThis\": \"Supprimer ceci\",\n \"detailsTranslated\": \"Détails traduits. Les chiffres et les liens restent exactement tels qu'ils sont.\",\n \"displayCapture\": \"capturer {name}\",\n \"displayCaptureAll\": \"tout capturer ({count} articles)\",\n \"displayDelete\": \"supprimer ceci\",\n \"displayViewHistory\": \"qu'avez-vous enregistré ?\",\n \"entityLangIntro\": \"Je réponds en {lang}. Les fiches de résultats peuvent rester exactement telles que ce site les a écrites, ou être également traduites.\",\n \"entityLangPlaceholder\": \"Choisissez l'une des deux fiches ci-dessus…\",\n \"errAccessRevoked\": \"Votre accès à l'assistant a été révoqué par le magasin.\",\n \"errAccountRequired\": \"Veuillez créer un compte pour continuer à utiliser l'assistant de chat.\",\n \"errShopperReplyLimit\": \"Vous avez atteint la limite de réponses de ce site pour votre compte.\",\n \"errStreamInterrupted\": \"La réponse a été interrompue. Veuillez réessayer.\",\n \"errTokenLimit\": \"Vous avez atteint votre limite d'utilisation. Veuillez mettre à jour vos limites de facturation dans votre tableau de bord pour continuer.\",\n \"errTooManyRequests\": \"L'assistant reçoit actuellement trop de requêtes. Veuillez réessayer dans quelques instants.\",\n \"footerHint\": \"kiku · recherche dans tout le catalogue en temps réel\",\n \"greetReturning\": \"Bonjour, {name}.\",\n \"greetReturningLead\": \"Que puis-je trouver pour vous aujourd'hui ?\",\n \"howShouldResultsLook\": \"Comment les résultats doivent-ils s'afficher ?\",\n \"inLanguage\": \"En {lang}\",\n \"keyAutoHide\": \"Se masque automatiquement dans {seconds}s.\",\n \"keyCopied\": \"Copié\",\n \"keyCopyId\": \"Copier l'identifiant\",\n \"keyCopySecret\": \"Copier le secret\",\n \"keyCreateNew\": \"Je suis nouveau — créez-en un\",\n \"keyCreating\": \"Création en cours…\",\n \"keyDismiss\": \"Ignorer\",\n \"keyPastePlaceholder\": \"votre identifiant public…\",\n \"keyPastePrompt\": \"Collez votre identifiant public — ou créez-en un\",\n \"keyPublicHint\": \"Collez ceci sur n'importe quel site pour enregistrer dans la même mémoire.\",\n \"keyPublicTitle\": \"Votre identifiant public\",\n \"keySecretHint\": \"Gardez-le privé — utilisez-le pour déverrouiller votre mémoire.\",\n \"keySecretTitle\": \"Votre secret — affiché une seule fois\",\n \"keyUseMine\": \"Utiliser mon identifiant\",\n \"kikuActionUnavailable\": \"Désolé — cette action n'est pas disponible sur ce site.\",\n \"kikuCaptureDbError\": \"La capture a échoué en raison d'une erreur de base de données.\",\n \"kikuCaptureNoContext\": \"La capture a échoué car aucun contexte de page ou de produit n'a été fourni par le SDK.\",\n \"kikuCaptureNoUrl\": \"Impossible d'enregistrer des articles — aucun n'avait d'URL valide.\",\n \"kikuCaptureNoneSelected\": \"Aucun article n'a été sélectionné pour la capture.\",\n \"kikuDeleteDbError\": \"La suppression a échoué en raison d'une erreur de base de données.\",\n \"kikuDeleteDone\": \"Je l'ai retiré de vos articles enregistrés.\",\n \"kikuDeleteNoContext\": \"La suppression a échoué car aucun contexte de page n'a été fourni pour identifier ce qu'il fallait supprimer.\",\n \"kikuMemoryIntro\": \"Tout ce que vous avez capturé sur les sites se trouve dans votre mémoire privée. Déverrouillez-la avec votre secret :\",\n \"kikuMintNeeded\": \"Pour enregistrer des articles sur différents sites, vous avez besoin d'une clé kiku — je vais en créer une pour vous. Elle n'est affichée qu'une seule fois, alors enregistrez-la en lieu sûr.\",\n \"kikuMintOffer\": \"Je peux garder ceci pour vous et le faire vous suivre sur les sites — je vais vous créer une clé kiku. Elle n'est affichée qu'une seule fois, alors enregistrez-la en lieu sûr.\",\n \"kikuNeedKeyToUpdate\": \"Entrez votre clé kiku afin que je puisse trouver et mettre à jour vos articles enregistrés.\",\n \"micDenied\": \"Microphone bloqué. Autorisez l'accès au micro pour ce site, puis réessayez.\",\n \"micFailed\": \"Je n'ai pas entendu. Réessayez.\",\n \"micInsecure\": \"La voix nécessite une connexion sécurisée (https).\",\n \"micLangUnsupported\": \"Ce navigateur ne peut pas encore transcrire cette langue. Veuillez taper à la place.\",\n \"micMissing\": \"Aucun microphone détecté.\",\n \"micNetwork\": \"La voix nécessite une connexion en ce moment. Vérifiez la vôtre et réessayez.\",\n \"micNoSpeech\": \"Je n'ai rien entendu. Réessayez, un peu plus près du micro.\",\n \"namePlaceholder\": \"Tapez votre nom…\",\n \"nameStepAsk\": \"Comment dois-je vous appeler ?\",\n \"nameStepLead\": \"Je peux chercher, visualiser ou capturer n'importe quoi pour vous — sur ce site ou n'importe quel autre.\",\n \"nameStepTitle\": \"Enchanté de vous rencontrer.\",\n \"namesAsWritten\": \"Noms et détails exactement tels qu'ils sont listés sur le site.\",\n \"pillCompareTop2\": \"Comparer les 2 meilleurs\",\n \"pillCompareTop2Query\": \"Comparez le {a} et le {b}\",\n \"pillFindAlternatives\": \"Trouver des alternatives\",\n \"pillFindAlternativesQuery\": \"Quelles sont de bonnes alternatives au {name} ?\",\n \"pillMoreOn\": \"Plus sur {name}\",\n \"pillMoreOnQuery\": \"Dites-m'en plus sur le {name}\",\n \"pillRecommend\": \"Recommander quelque chose\",\n \"pillRecommendQuery\": \"Que me recommandez-vous ?\",\n \"pillShowPopular\": \"Afficher les articles populaires\",\n \"pillShowPopularQuery\": \"Quels sont vos articles les plus populaires ?\",\n \"pillSimilarOptions\": \"Options similaires\",\n \"pillSimilarOptionsQuery\": \"Montrez-m'en plus comme le {name}\",\n \"pillUnder\": \"Moins de {amount}\",\n \"pillUnderQuery\": \"Montrez-moi des options à moins de {amount}\",\n \"pillWhichBest\": \"Lequel est le meilleur ?\",\n \"pillWhichBestQuery\": \"Lequel recommanderiez-vous et pourquoi ?\",\n \"replyingOriginal\": \"Je réponds en {lang}, les résultats sont tels que le site les a écrits. Posez-moi n'importe quelle question.\",\n \"replyingTranslated\": \"Je réponds en {lang}, les résultats sont également traduits. Posez-moi n'importe quelle question.\",\n \"statusSent\": \"Envoyé\",\n \"statusStopped\": \"Envoyé · réponse arrêtée\",\n \"thinking\": \"Réflexion en cours\",\n \"thoughtForSeconds\": \"Réflexion pendant {duration}\",\n \"thoughtProcess\": \"Processus de réflexion\",\n \"vizDisclaimerImage\": \"Généré par Intelligence Artificielle — les couleurs, la taille et le placement peuvent différer du produit réel.\",\n \"vizDisclaimerVideo\": \"Généré par Intelligence Artificielle — les couleurs, la taille et le mouvement peuvent différer du produit réel.\",\n \"vizUnavailable\": \"L'aperçu n'a pas pu être chargé.\",\n \"voiceListening\": \"Écoute… touchez le micro pour arrêter\",\n \"voiceSending\": \"Bien reçu — envoi en cours…\",\n \"termsStepTitle\": \"Confidentialité et conditions d'utilisation\",\n \"termsStepSubtitle\": \"Transparent, anonyme et sans collecte de données personnelles.\",\n \"termsPiiTitle\": \"Zéro collecte de données personnelles\",\n \"termsPiiDesc\": \"Nous ne collectons ni ne stockons aucune information d'identification personnelle (ni e-mail, ni numéro de téléphone, ni identité réelle) depuis vos discussions ou sessions vocales.\",\n \"termsSessionTitle\": \"Jetons de session anonymes\",\n \"termsSessionDesc\": \"Votre session utilise un identifiant anonyme côté client uniquement pour maintenir le contexte, jamais lié à votre identité réelle.\",\n \"termsMemoryTitle\": \"Discussions éphémères vs Coffre Mimi\",\n \"termsMemoryDesc\": \"Les discussions normales sont éphémères — fermer ou effacer le chat les détruit pour toujours. Les éléments enregistrés avec « @kiku » sont chiffrés et accessibles sur mimi.akropolys.cloud avec votre clé secrète.\",\n \"termsCookieTitle\": \"Télémétrie du site hôte\",\n \"termsCookieDesc\": \"Le site hôte sur lequel kiku est intégré peut collecter des cookies et des données d'analyse selon sa propre politique de cookies, hors du contrôle de kiku.\",\n \"termsAgreeButton\": \"Accepter et continuer\",\n \"termsAgreeCounting\": \"Accepter et continuer ({seconds}s)\",\n \"termsPlaceholder\": \"Veuillez examiner et accepter la politique de confidentialité et les conditions ci-dessus…\",\n \"whatHaveYouSaved\": \"Qu'avez-vous enregistré ?\",\n \"voiceHint\": \"Parlez simplement — je répondrai dès que vous ferez une pause.\",\n \"voiceModeExit\": \"Quitter le mode mains libres\",\n \"voiceModeStart\": \"Conversation mains libres\",\n \"voiceMuted\": \"En sourdine\",\n \"voiceMutedHint\": \"Appuyez sur le micro pour parler à nouveau.\",\n \"voicePhaseListening\": \"Écoute\",\n \"voicePhaseSpeaking\": \"Parle\",\n \"voicePhaseThinking\": \"Réflexion\"\n },\n \"hindi\": {\n \"allSet\": \"आप तैयार हैं, {name}.\",\n \"asWritten\": \"जैसा लिखा है\",\n \"captureAll\": \"सभी को कैप्चर करें ({count})\",\n \"captureAndRemember\": \"kiku — कैप्चर & याद रखें\",\n \"captureCurrentPage\": \"वर्तमान पृष्ठ को कैप्चर करें\",\n \"cardClickAnswer\": \"{name}\",\n \"cardClickQuery\": \"कृपया {name}{price} के बारे में अधिक बताइए — इसके मुख्य विवरण क्या हैं, यह किसके लिए सबसे उपयुक्त है, और मुझे क्या जानना चाहिए?\",\n \"clearChat\": \"चैट साफ़ करें\",\n \"defaultPlaceholder\": \"मुझसे कुछ भी पूछें…\",\n \"deleteThis\": \"इसे हटाएँ\",\n \"detailsTranslated\": \"विवरण अनुवादित। संख्याएँ और लिंक ठीक वैसे ही रहें।\",\n \"displayCapture\": \"कैप्चर {name}\",\n \"displayCaptureAll\": \"सभी को कैप्चर करें ({count} आइटम)\",\n \"displayDelete\": \"इसे हटाएँ\",\n \"displayViewHistory\": \"आपने क्या सहेजा है?\",\n \"entityLangIntro\": \"मैं {lang} में उत्तर दूँगा। परिणाम कार्ड इस साइट ने जैसा लिखा है वैसा ही रह सकते हैं, या अनूदित भी हो सकते हैं।\",\n \"entityLangPlaceholder\": \"ऊपर दो कार्डों में से एक चुनें…\",\n \"errAccessRevoked\": \"स्टोर द्वारा आपके सहायक तक पहुँच रद्द कर दी गई है।\",\n \"errAccountRequired\": \"चैट सहायक का उपयोग जारी रखने के लिए कृपया एक खाता बनाएँ।\",\n \"errShopperReplyLimit\": \"आपने इस साइट के लिए अपने खाते की उत्तर सीमा तक पहुँच बना ली है।\",\n \"errStreamInterrupted\": \"उत्तर बाधित हो गया। कृपया पुनः प्रयास करें।\",\n \"errTokenLimit\": \"आपने अपनी उपयोग सीमा तक पहुँच बना ली है। जारी रखने के लिए अपने डैशबोर्ड में बिलिंग सीमा अपडेट करें।\",\n \"errTooManyRequests\": \"सहायक वर्तमान में बहुत अधिक अनुरोध प्राप्त कर रहा है। कुछ क्षण बाद पुनः प्रयास करें।\",\n \"footerHint\": \"kiku · वास्तविक समय में पूरे कैटलॉग को खोजता है\",\n \"greetReturning\": \"नमस्ते, {name}.\",\n \"greetReturningLead\": \"आज मैं आपके लिए क्या खोजूँ?\",\n \"howShouldResultsLook\": \"परिणाम कैसे दिखें?\",\n \"inLanguage\": \"{lang} में\",\n \"keyAutoHide\": \"स्वतः {seconds}s में छिप जाएगा.\",\n \"keyCopied\": \"कॉपी किया गया\",\n \"keyCopyId\": \"आईडी कॉपी करें\",\n \"keyCopySecret\": \"सीक्रेट कॉपी करें\",\n \"keyCreateNew\": \"मैं नया हूँ — एक बनाएं\",\n \"keyCreating\": \"बना रहा हूँ…\",\n \"keyDismiss\": \"बंद करें\",\n \"keyPastePlaceholder\": \"आपका सार्वजनिक आईडी…\",\n \"keyPastePrompt\": \"अपना सार्वजनिक आईडी पेस्ट करें — या एक बनाएं\",\n \"keyPublicHint\": \"इसे किसी भी साइट पर पेस्ट करें ताकि वही मेमोरी में सहेजा जा सके।\",\n \"keyPublicTitle\": \"आपका सार्वजनिक आईडी\",\n \"keySecretHint\": \"इसे निजी रखें — अपने मेमोरी को अनलॉक करने के लिए उपयोग करें।\",\n \"keySecretTitle\": \"आपका सीक्रेट — केवल एक बार दिखाया गया\",\n \"keyUseMine\": \"मेरी आईडी उपयोग करें\",\n \"kikuActionUnavailable\": \"क्षमा करें — यह कार्रवाई इस साइट पर उपलब्ध नहीं है।\",\n \"kikuCaptureDbError\": \"डेटाबेस त्रुटि के कारण कैप्चर विफल रहा।\",\n \"kikuCaptureNoContext\": \"SDK द्वारा कोई पेज या प्रोडक्ट कॉन्टेक्स्ट प्रदान नहीं किया गया, इसलिए कैप्चर विफल रहा।\",\n \"kikuCaptureNoUrl\": \"कोई आइटम सहेजा नहीं जा सका — कोई भी वैध URL नहीं था।\",\n \"kikuCaptureNoneSelected\": \"कैप्चर करने के लिए कोई आइटम चयनित नहीं किया गया।\",\n \"kikuDeleteDbError\": \"डेटाबेस त्रुटि के कारण हटाना विफल रहा।\",\n \"kikuDeleteDone\": \"इसे आपके सहेजे गए आइटम्स से हटा दिया गया।\",\n \"kikuDeleteNoContext\": \"हटाने के लिए कोई पेज कॉन्टेक्स्ट प्रदान नहीं किया गया, इसलिए हटाना विफल रहा।\",\n \"kikuMemoryIntro\": \"आपने विभिन्न साइटों पर जो भी कैप्चर किया है, वह आपके निजी मेमोरी में रहता है। इसे अपने सीक्रेट से अनलॉक करें:\",\n \"kikuMintNeeded\": \"साइटों के बीच आइटम्स सहेजने के लिए आपको एक किकु कुंजी चाहिए — मैं आपके लिए एक बनाऊँगा। यह केवल एक बार दिखाया जाता है, इसलिए इसे सुरक्षित जगह पर रखें।\",\n \"kikuMintOffer\": \"मैं इसे आपके लिए रख सकता हूँ और साइटों के बीच आपके साथ ले जा सकता हूँ — मैं आपके लिए एक किकु कुंजी बनाऊँगा। यह केवल एक बार दिखाया जाता है, इसलिए इसे सुरक्षित जगह पर रखें।\",\n \"kikuNeedKeyToUpdate\": \"अपनी किकु कुंजी दर्ज करें ताकि मैं आपके सहेजे गए आइटम्स को खोज और अपडेट कर सकूँ।\",\n \"namePlaceholder\": \"अपना नाम टाइप करें…\",\n \"nameStepAsk\": \"मैं आपको क्या कहूँ?\",\n \"nameStepLead\": \"मैं आपके लिए कुछ भी खोज, विज़ुअलाइज़ या कैप्चर कर सकता हूँ — इस साइट पर या किसी अन्य पर।\",\n \"nameStepTitle\": \"आपसे मिलकर खुशी हुई।\",\n \"namesAsWritten\": \"नाम और विवरण ठीक उसी तरह जैसे साइट पर सूचीबद्ध हैं।\",\n \"pillCompareTop2\": \"शीर्ष 2 की तुलना करें\",\n \"pillCompareTop2Query\": \"{a} और {b} की तुलना करें\",\n \"pillFindAlternatives\": \"विकल्प खोजें\",\n \"pillFindAlternativesQuery\": \"{name} के अच्छे विकल्प क्या हैं?\",\n \"pillMoreOn\": \"{name} के बारे में अधिक\",\n \"pillMoreOnQuery\": \"कृपया {name} के बारे में अधिक बताइए\",\n \"pillRecommend\": \"कुछ सुझाएँ\",\n \"pillRecommendQuery\": \"मेरे लिए आप क्या सुझाएंगे?\",\n \"pillShowPopular\": \"लोकप्रिय आइटम दिखाएँ\",\n \"pillShowPopularQuery\": \"आपके सबसे लोकप्रिय आइटम कौन से हैं?\",\n \"pillSimilarOptions\": \"समान विकल्प\",\n \"pillSimilarOptionsQuery\": \"{name} जैसा और दिखाइए\",\n \"pillUnder\": \"{amount} से कम\",\n \"pillUnderQuery\": \"{amount} से कम विकल्प दिखाइए\",\n \"pillWhichBest\": \"कौन सबसे अच्छा है?\",\n \"pillWhichBestQuery\": \"आप कौन सा सुझाएंगे और क्यों?\",\n \"replyingOriginal\": \"{lang} में उत्तर दे रहा हूँ, परिणाम साइट के लिखे अनुसार। मुझसे कुछ भी पूछें।\",\n \"replyingTranslated\": \"{lang} में उत्तर दे रहा हूँ, परिणाम भी अनूदित हैं। मुझसे कुछ भी पूछें।\",\n \"statusSent\": \"भेजा गया\",\n \"statusStopped\": \"भेजा गया · उत्तर रोक दिया गया\",\n \"thinking\": \"सोच रहा हूँ\",\n \"thoughtForSeconds\": \"{duration} तक सोचा\",\n \"thoughtProcess\": \"विचार प्रक्रिया\",\n \"vizUnavailable\": \"पूर्वावलोकन लोड नहीं हो सका।\",\n \"termsStepTitle\": \"गोपनीयता और उपयोग की शर्तें\",\n \"termsStepSubtitle\": \"पारदर्शी, अज्ञात और शून्य व्यक्तिगत पहचान डेटा।\",\n \"termsPiiTitle\": \"शून्य व्यक्तिगत डेटा संग्रह\",\n \"termsPiiDesc\": \"हम आपकी बातचीत या वॉयस सत्रों से व्यक्तिगत पहचान योग्य जानकारी (कोई ईमेल, फ़ोन नंबर या वास्तविक पहचान नहीं) एकत्र या संग्रहीत नहीं करते हैं।\",\n \"termsSessionTitle\": \"अज्ञात सत्र टोकन\",\n \"termsSessionDesc\": \"आपका सत्र केवल संदर्भ बनाए रखने के लिए एक अनाम क्लाइंट टोकन का उपयोग करता है। यह आपकी वास्तविक पहचान से कभी नहीं जुड़ता।\",\n \"termsMemoryTitle\": \"अस्थायी चैट बनाम मिमी वॉल्ट\",\n \"termsMemoryDesc\": \"नियमित चैट अस्थायी हैं — चैट बंद करने या साफ़ करने पर वे हमेशा के लिए समाप्त हो जाती हैं। \\\"@kiku\\\" से सहेजे गए आइटम एन्क्रिप्टेड हैं और mimi.akropolys.cloud पर आपकी गुप्त कुंजी से खोले जा सकते हैं।\",\n \"termsCookieTitle\": \"होस्ट वेबसाइट टेलीमेट्री\",\n \"termsCookieDesc\": \"जिस वेबसाइट पर kiku एम्बेडेड है, वह अपनी स्वयं की कुकी नीति के अनुसार कुकीज़ और एनालिटिक्स एकत्र कर सकती है।\",\n \"termsAgreeButton\": \"सहमत हों और आगे बढ़ें\",\n \"termsAgreeCounting\": \"सहमत हों और आगे बढ़ें ({seconds}s)\",\n \"termsPlaceholder\": \"कृपया ऊपर दी गई गोपनीयता और शर्तों की समीक्षा करें और स्वीकार करें…\",\n \"whatHaveYouSaved\": \"आपने क्या सहेजा है?\",\n \"micDenied\": \"माइक्रोफ़ोन ब्लॉक है। इस साइट के लिए माइक एक्सेस की अनुमति दें, फिर पुनः प्रयास करें।\",\n \"micFailed\": \"सुनाई नहीं दिया। पुनः प्रयास करें।\",\n \"micInsecure\": \"वॉयस के लिए सुरक्षित (https) कनेक्शन आवश्यक है।\",\n \"micLangUnsupported\": \"यह ब्राउज़र अभी इस भाषा को ट्रांसक्राइब नहीं कर सकता। इसके बजाय टाइप करें।\",\n \"micMissing\": \"कोई माइक्रोफ़ोन नहीं मिला।\",\n \"micNetwork\": \"वॉयस के लिए इंटरनेट कनेक्शन आवश्यक है। अपना कनेक्शन जांचें और पुनः प्रयास करें।\",\n \"micNoSpeech\": \"कुछ सुनाई नहीं दिया। कृपया माइक के पास आकर दोबारा बोलें।\",\n \"vizDisclaimerImage\": \"कृत्रिम बुद्धिमत्ता (AI) द्वारा निर्मित — रंग, आकार और स्थिति वास्तविक उत्पाद से भिन्न हो सकते हैं।\",\n \"vizDisclaimerVideo\": \"कृत्रिम बुद्धिमत्ता (AI) द्वारा निर्मित — रंग, आकार और गति वास्तविक उत्पाद से भिन्न हो सकते हैं।\",\n \"voiceHint\": \"बस बोलें — जब आप रुकेंगे तो मैं उत्तर दूंगा।\",\n \"voiceListening\": \"सुन रहा है… रोकने के लिए माइक पर टैप करें\",\n \"voiceModeExit\": \"हैंड्स-फ्री से बाहर निकलें\",\n \"voiceModeStart\": \"हैंड्स-फ्री बातचीत\",\n \"voiceMuted\": \"म्यूट किया गया\",\n \"voiceMutedHint\": \"दोबारा बोलने के लिए माइक्रोफ़ोन पर टैप करें।\",\n \"voicePhaseListening\": \"सुन रहा है\",\n \"voicePhaseSpeaking\": \"बोल रहा है\",\n \"voicePhaseThinking\": \"सोच रहा है\",\n \"voiceSending\": \"समझ गया — भेजा जा रहा है…\"\n },\n \"japanese\": {\n \"allSet\": \"準備が完了しました、{name}さん。\",\n \"asWritten\": \"サイトの原文通り\",\n \"captureAll\": \"すべて保存 ({count})\",\n \"captureAndRemember\": \"kiku — 保存と記憶\",\n \"captureCurrentPage\": \"現在のページを保存\",\n \"cardClickAnswer\": \"{name}\",\n \"cardClickQuery\": \"{name}{price} について詳しく教えてください — 主な特徴、どんな人に向いているか、知っておくべきことは何ですか?\",\n \"clearChat\": \"チャットを消去\",\n \"defaultPlaceholder\": \"何でもお聞きください…\",\n \"deleteThis\": \"これを削除\",\n \"detailsTranslated\": \"詳細を翻訳しました。価格やリンクはサイトの表記そのままです。\",\n \"displayCapture\": \"{name} を保存\",\n \"displayCaptureAll\": \"すべて保存({count}件)\",\n \"displayDelete\": \"これを削除\",\n \"displayViewHistory\": \"何を保存しましたか?\",\n \"entityLangIntro\": \"{lang}で返答します。検索結果のカードはサイトの原文のまま表示することも、翻訳して表示することもできます。\",\n \"entityLangPlaceholder\": \"上の2つのカードから1つ選んでください…\",\n \"errAccessRevoked\": \"ストアによってアシスタントへのアクセス権が取り消されました。\",\n \"errAccountRequired\": \"チャットアシスタントを引き続きご利用いただくには、アカウントを作成してください。\",\n \"errShopperReplyLimit\": \"このサイトでのあなたのアカウントの返答上限に達しました。\",\n \"errStreamInterrupted\": \"返答が中断されました。もう一度お試しください。\",\n \"errTokenLimit\": \"利用上限に達しました。ダッシュボードで利用上限を更新して続行してください。\",\n \"errTooManyRequests\": \"現在リクエストが集中しています。しばらくしてからもう一度お試しください。\",\n \"footerHint\": \"kiku · カタログ全体をリアルタイムで検索\",\n \"greetReturning\": \"こんにちは、{name}さん。\",\n \"greetReturningLead\": \"今日は何をお探しですか?\",\n \"howShouldResultsLook\": \"検索結果はどのように表示しますか?\",\n \"inLanguage\": \"{lang}で\",\n \"keyAutoHide\": \"{seconds}秒後に自動で閉じます。\",\n \"keyCopied\": \"コピーしました\",\n \"keyCopyId\": \"IDをコピー\",\n \"keyCopySecret\": \"シークレットをコピー\",\n \"keyCreateNew\": \"初めて利用 — 新規作成\",\n \"keyCreating\": \"作成中…\",\n \"keyDismiss\": \"閉じる\",\n \"keyPastePlaceholder\": \"公開IDを入力…\",\n \"keyPastePrompt\": \"公開IDを貼り付けるか、新規作成してください\",\n \"keyPublicHint\": \"どのサイトでもこれを貼り付けると、同じメモリーに保存できます。\",\n \"keyPublicTitle\": \"あなたの公開ID\",\n \"keySecretHint\": \"大切に保管してください — メモリーのロック解除に使用します。\",\n \"keySecretTitle\": \"あなたのシークレット — 1度だけ表示されます\",\n \"keyUseMine\": \"自分のIDを使用\",\n \"kikuActionUnavailable\": \"申し訳ありません。このサイトではその操作は利用できません。\",\n \"kikuCaptureDbError\": \"データベースエラーのため保存に失敗しました。\",\n \"kikuCaptureNoContext\": \"ページ情報が提供されなかったため保存に失敗しました。\",\n \"kikuCaptureNoUrl\": \"有効なURLがないため、アイテムを保存できませんでした。\",\n \"kikuCaptureNoneSelected\": \"保存するアイテムが選択されていません。\",\n \"kikuDeleteDbError\": \"データベースエラーのため削除に失敗しました。\",\n \"kikuDeleteDone\": \"保存したアイテムから削除しました。\",\n \"kikuDeleteNoContext\": \"削除対象を特定するためのページ情報がありませんでした。\",\n \"kikuMemoryIntro\": \"複数サイトで保存したすべてのアイテムはプライベートメモリーに保持されます。シークレットでロック解除:\",\n \"kikuMintNeeded\": \"サイトをまたいでアイテムを保存するにはkikuキーが必要です。新しく発行します。1度しか表示されないため、安全な場所に保存してください。\",\n \"kikuMintOffer\": \"アイテムを保持して他のサイトでも引き継ぐことができます — kikuキーを発行します。1度しか表示されないため安全に保存してください。\",\n \"kikuNeedKeyToUpdate\": \"保存したアイテムを更新・検索するにはkikuキーを入力してください。\",\n \"micDenied\": \"マイクがブロックされています。このサイトでのマイクアクセスを許可してから、もう一度お試しください。\",\n \"micFailed\": \"聞き取れませんでした。もう一度お話しください。\",\n \"micInsecure\": \"音声入力には保護された接続 (HTTPS) が必要です。\",\n \"micLangUnsupported\": \"お使いのブラウザはこの言語の音声認識にまだ対応していません。文字で入力してください。\",\n \"micMissing\": \"マイクが見つかりませんでした。\",\n \"micNetwork\": \"音声入力にはネットワーク接続が必要です。接続を確認してもう一度お試しください。\",\n \"micNoSpeech\": \"音声が検出されませんでした。マイクに近づいてもう一度お話しください。\",\n \"namePlaceholder\": \"お名前を入力…\",\n \"nameStepAsk\": \"何とお呼びすればよろしいですか?\",\n \"nameStepLead\": \"このサイトや他のサイトの情報を検索・視覚化・保存できます。\",\n \"nameStepTitle\": \"はじめまして。\",\n \"namesAsWritten\": \"商品名や詳細はサイトの掲載通り。\",\n \"pillCompareTop2\": \"トップ2を比較\",\n \"pillCompareTop2Query\": \"{a} と {b} を比較して\",\n \"pillFindAlternatives\": \"代替品を探す\",\n \"pillFindAlternativesQuery\": \"{name} の良い代替品はありますか?\",\n \"pillMoreOn\": \"{name} についてもっと知る\",\n \"pillMoreOnQuery\": \"{name} についてもっと詳しく教えて\",\n \"pillRecommend\": \"おすすめを教えて\",\n \"pillRecommendQuery\": \"私に何をおすすめしますか?\",\n \"pillShowPopular\": \"人気商品を見る\",\n \"pillShowPopularQuery\": \"一番人気の商品はどれですか?\",\n \"pillSimilarOptions\": \"似ているオプション\",\n \"pillSimilarOptionsQuery\": \"{name} に似た商品をもっと見せて\",\n \"pillUnder\": \"{amount} 以下\",\n \"pillUnderQuery\": \"{amount} 以下の選択肢を見せて\",\n \"pillWhichBest\": \"どれが一番おすすめ?\",\n \"pillWhichBestQuery\": \"どれが一番おすすめですか?その理由も教えてください。\",\n \"replyingOriginal\": \"{lang}で返答します(結果はサイト原文のまま)。何でもお聞きください。\",\n \"replyingTranslated\": \"{lang}で返答します(結果も翻訳)。何でもお聞きください。\",\n \"statusSent\": \"送信済み\",\n \"statusStopped\": \"送信済み · 返答を停止しました\",\n \"thinking\": \"思考中\",\n \"thoughtForSeconds\": \"{duration} 考えました\",\n \"thoughtProcess\": \"思考プロセス\",\n \"vizDisclaimerImage\": \"人工知能によって生成されました — 色、サイズ、配置は実際の商品と異なる場合があります。\",\n \"vizDisclaimerVideo\": \"人工知能によって生成されました — 色、サイズ、動きは実際の商品と異なる場合があります。\",\n \"vizUnavailable\": \"プレビューを読み込めませんでした。\",\n \"voiceHint\": \"お話しください — 話し終えたらお答えします。\",\n \"voiceListening\": \"聞き取り中… タップして停止\",\n \"voiceModeExit\": \"ハンズフリーを終了\",\n \"voiceModeStart\": \"ハンズフリー会話\",\n \"voiceMuted\": \"ミュート中\",\n \"voiceMutedHint\": \"マイクをタップしてもう一度お話しください。\",\n \"voicePhaseListening\": \"聞き取り中\",\n \"voicePhaseSpeaking\": \"発答中\",\n \"voicePhaseThinking\": \"考え中\",\n \"voiceSending\": \"受け取りました — 送信中…\",\n \"termsStepTitle\": \"プライバシーと利用規約\",\n \"termsStepSubtitle\": \"透明性、匿名性、そして個人を特定しない設計。\",\n \"termsPiiTitle\": \"個人を特定する情報の不収集\",\n \"termsPiiDesc\": \"チャットや音声セッションから個人を特定できる情報(メールアドレス、電話番号、実名など)を収集・保存することは一切ありません。\",\n \"termsSessionTitle\": \"匿名のセッション識別子\",\n \"termsSessionDesc\": \"コンテキストを維持するためにクライアント側で生成された匿名トークンのみを使用し、実際の身元と紐付けることはありません。\",\n \"termsMemoryTitle\": \"一時的なチャット vs Mimi Vault\",\n \"termsMemoryDesc\": \"通常のチャットは一時的なものです。タブを閉じるかチャットを消去すると完全に破棄されます。「@kiku」で保存したアイテムは暗号化され、mimi.akropolys.cloud でシークレットキーを使ってロック解除できます。\",\n \"termsCookieTitle\": \"ホストサイトのテレメトリ\",\n \"termsCookieDesc\": \"kikuが埋め込まれているホストサイトは、独自のクッキーポリシーに基づいてクッキーやアクセス解析を収集する場合があります(kikuの管理外)。\",\n \"termsAgreeButton\": \"同意して続行\",\n \"termsAgreeCounting\": \"同意して続行 ({seconds}秒)\",\n \"termsPlaceholder\": \"上記のプライバシーと規約をご確認いただき、同意してください…\",\n \"whatHaveYouSaved\": \"何を保存しましたか?\"\n },\n \"portuguese\": {\n \"allSet\": \"Tudo pronto, {name}.\",\n \"asWritten\": \"Como escrito\",\n \"captureAll\": \"Capturar tudo ({count})\",\n \"captureAndRemember\": \"kiku — capturar & lembrar\",\n \"captureCurrentPage\": \"Capturar página atual\",\n \"cardClickAnswer\": \"O {name}\",\n \"cardClickQuery\": \"Fale mais sobre o {name}{price} — quais são seus detalhes principais, para quem é mais indicado e o que devo saber?\",\n \"clearChat\": \"Limpar chat\",\n \"defaultPlaceholder\": \"Pergunte-me qualquer coisa…\",\n \"deleteThis\": \"Excluir isso\",\n \"detailsTranslated\": \"Detalhes traduzidos. Números e links permanecem exatamente como listados.\",\n \"displayCapture\": \"capturar {name}\",\n \"displayCaptureAll\": \"capturar tudo ({count} itens)\",\n \"displayDelete\": \"excluir isso\",\n \"displayViewHistory\": \"o que você salvou?\",\n \"entityLangIntro\": \"Eu respondo em {lang}. Os cartões de resultado podem permanecer exatamente como o site os escreveu ou ser traduzidos também.\",\n \"entityLangPlaceholder\": \"Escolha um dos dois cartões acima…\",\n \"errAccessRevoked\": \"Seu acesso ao assistente foi revogado pela loja.\",\n \"errAccountRequired\": \"Por favor, crie uma conta para continuar usando o assistente de chat.\",\n \"errShopperReplyLimit\": \"Você atingiu o limite de respostas deste site para sua conta.\",\n \"errStreamInterrupted\": \"A resposta foi interrompida. Por favor, tente novamente.\",\n \"errTokenLimit\": \"Você atingiu seu limite de uso. Atualize seus limites de cobrança no painel para continuar.\",\n \"errTooManyRequests\": \"O assistente está recebendo muitas solicitações no momento. Por favor, tente novamente em alguns instantes.\",\n \"footerHint\": \"kiku · pesquisa todo o catálogo em tempo real\",\n \"greetReturning\": \"Oi, {name}.\",\n \"greetReturningLead\": \"O que posso encontrar para você hoje?\",\n \"howShouldResultsLook\": \"Como os resultados devem aparecer?\",\n \"inLanguage\": \"Em {lang}\",\n \"keyAutoHide\": \"Esconde automaticamente em {seconds}s.\",\n \"keyCopied\": \"Copiado\",\n \"keyCopyId\": \"Copiar id\",\n \"keyCopySecret\": \"Copiar segredo\",\n \"keyCreateNew\": \"Sou novo — criar um\",\n \"keyCreating\": \"Criando…\",\n \"keyDismiss\": \"Fechar\",\n \"keyPastePlaceholder\": \"seu id público…\",\n \"keyPastePrompt\": \"Cole seu id público — ou crie um\",\n \"keyPublicHint\": \"Cole isso em qualquer site para salvar na mesma memória.\",\n \"keyPublicTitle\": \"Seu id público\",\n \"keySecretHint\": \"Mantenha privado — use para desbloquear sua memória.\",\n \"keySecretTitle\": \"Seu segredo — mostrado apenas uma vez\",\n \"keyUseMine\": \"Usar meu id\",\n \"kikuActionUnavailable\": \"Desculpe — essa ação não está disponível neste site.\",\n \"kikuCaptureDbError\": \"Falha ao capturar devido a um erro de banco de dados.\",\n \"kikuCaptureNoContext\": \"Falha ao capturar porque nenhum contexto de página ou produto foi fornecido pelo SDK.\",\n \"kikuCaptureNoUrl\": \"Não foi possível salvar nenhum item — nenhum tinha URL válido.\",\n \"kikuCaptureNoneSelected\": \"Nenhum item foi selecionado para captura.\",\n \"kikuDeleteDbError\": \"Falha ao excluir devido a um erro de banco de dados.\",\n \"kikuDeleteDone\": \"Removido dos seus itens salvos.\",\n \"kikuDeleteNoContext\": \"Falha ao excluir porque nenhum contexto de página foi fornecido para identificar o que excluir.\",\n \"kikuMemoryIntro\": \"Tudo que você capturou em sites está na sua memória privada. Desbloqueie-a com seu segredo:\",\n \"kikuMintNeeded\": \"Para salvar itens entre sites você precisa de uma chave kiku — vou gerar uma para você. Ela será mostrada apenas uma vez, então guarde-a em um local seguro.\",\n \"kikuMintOffer\": \"Posso guardar isso para você e fazer com que siga você entre sites — vou gerar uma chave kiku. Ela será mostrada apenas uma vez, então guarde-a em um local seguro.\",\n \"kikuNeedKeyToUpdate\": \"Insira sua chave kiku para que eu possa encontrar e atualizar seus itens salvos.\",\n \"namePlaceholder\": \"Digite seu nome…\",\n \"nameStepAsk\": \"Como devo chamar você?\",\n \"nameStepLead\": \"Posso pesquisar, visualizar ou capturar qualquer coisa para você — neste site ou em qualquer outro.\",\n \"nameStepTitle\": \"Prazer em conhecê-lo.\",\n \"namesAsWritten\": \"Nomes e detalhes exatamente como o site os lista.\",\n \"pillCompareTop2\": \"Comparar os 2 melhores\",\n \"pillCompareTop2Query\": \"Compare o {a} e o {b}\",\n \"pillFindAlternatives\": \"Encontrar alternativas\",\n \"pillFindAlternativesQuery\": \"Quais são boas alternativas ao {name}?\",\n \"pillMoreOn\": \"Mais sobre {name}\",\n \"pillMoreOnQuery\": \"Fale mais sobre o {name}\",\n \"pillRecommend\": \"Recomendar algo\",\n \"pillRecommendQuery\": \"O que você recomenda para mim?\",\n \"pillShowPopular\": \"Mostrar itens populares\",\n \"pillShowPopularQuery\": \"Quais são os seus itens mais populares?\",\n \"pillSimilarOptions\": \"Opções semelhantes\",\n \"pillSimilarOptionsQuery\": \"Mostre-me mais opções semelhantes ao {name}\",\n \"pillUnder\": \"Abaixo de {amount}\",\n \"pillUnderQuery\": \"Mostre-me opções abaixo de {amount}\",\n \"pillWhichBest\": \"Qual é o melhor?\",\n \"pillWhichBestQuery\": \"Qual você recomendaria e por quê?\",\n \"replyingOriginal\": \"Respondendo em {lang}, resultados como o site escreveu. Pergunte-me qualquer coisa.\",\n \"replyingTranslated\": \"Respondendo em {lang}, resultados também traduzidos. Pergunte-me qualquer coisa.\",\n \"statusSent\": \"Enviado\",\n \"statusStopped\": \"Enviado · resposta interrompida\",\n \"thinking\": \"Pensando\",\n \"thoughtForSeconds\": \"Pensou por {duration}\",\n \"thoughtProcess\": \"Processo de pensamento\",\n \"vizUnavailable\": \"A visualização não pôde ser carregada.\",\n \"termsStepTitle\": \"Privacidade e Termos de Uso\",\n \"termsStepSubtitle\": \"Transparente, anônimo e sem coleta de dados pessoais.\",\n \"termsPiiTitle\": \"Zero Coleta de Dados Pessoais\",\n \"termsPiiDesc\": \"Nunca coletamos nem armazenamos informações de identificação pessoal (sem e-mails, telefones ou identidades reais) das suas conversas ou sessões de voz.\",\n \"termsSessionTitle\": \"Tokens de Sessão Anônimos\",\n \"termsSessionDesc\": \"Sua sessão usa um token anônimo no cliente apenas para manter o contexto. Nunca é vinculado à sua identidade real.\",\n \"termsMemoryTitle\": \"Conversas Efêmeras vs. Cofre Mimi\",\n \"termsMemoryDesc\": \"Conversas normais são efêmeras — fechar ou limpar o chat as apaga para sempre. Itens salvos com \\\"@kiku\\\" são criptografados e podem ser desbloqueados em mimi.akropolys.cloud com sua chave secreta.\",\n \"termsCookieTitle\": \"Telemetria do Site Hospedeiro\",\n \"termsCookieDesc\": \"O site onde o kiku está incorporado pode coletar cookies e análises de acordo com sua própria política de cookies, fora do controle do kiku.\",\n \"termsAgreeButton\": \"Concordar e Continuar\",\n \"termsAgreeCounting\": \"Concordar e Continuar ({seconds}s)\",\n \"termsPlaceholder\": \"Por favor, revise e aceite a privacidade e os termos acima…\",\n \"whatHaveYouSaved\": \"O que você salvou?\",\n \"micDenied\": \"Microfone bloqueado. Permita o acesso ao microfone neste site e tente novamente.\",\n \"micFailed\": \"Não foi possível ouvir. Tente novamente.\",\n \"micInsecure\": \"A voz precisa de uma conexão segura (https).\",\n \"micLangUnsupported\": \"Este navegador ainda não transcreve este idioma. Digite em vez disso.\",\n \"micMissing\": \"Nenhum microfone encontrado.\",\n \"micNetwork\": \"A voz precisa de uma conexão no momento. Verifique a sua e tente novamente.\",\n \"micNoSpeech\": \"Não ouvimos nada. Tente novamente, um pouco mais perto do microfone.\",\n \"vizDisclaimerImage\": \"Gerado com Inteligência Artificial — cores, tamanho e posição podem diferir do produto real.\",\n \"vizDisclaimerVideo\": \"Gerado com Inteligência Artificial — cores, tamanho e movimento podem diferir do produto real.\",\n \"voiceHint\": \"Basta falar — responderei quando você fizer uma pausa.\",\n \"voiceListening\": \"Ouvindo… toque no microfone para parar\",\n \"voiceModeExit\": \"Sair do modo mãos-livres\",\n \"voiceModeStart\": \"Conversa em mãos-livres\",\n \"voiceMuted\": \"Silenciado\",\n \"voiceMutedHint\": \"Toque no microfone para falar novamente.\",\n \"voicePhaseListening\": \"Ouvindo\",\n \"voicePhaseSpeaking\": \"Falando\",\n \"voicePhaseThinking\": \"Pensando\",\n \"voiceSending\": \"Entendido — enviando…\"\n },\n \"spanish\": {\n \"allSet\": \"Todo listo, {name}.\",\n \"asWritten\": \"Tal como está escrito\",\n \"captureAll\": \"Capturar todo ({count})\",\n \"captureAndRemember\": \"kiku — capturar y recordar\",\n \"captureCurrentPage\": \"Capturar página actual\",\n \"cardClickAnswer\": \"El {name}\",\n \"cardClickQuery\": \"Cuéntame más sobre {name}{price} — ¿cuáles son sus detalles clave, para quién es más adecuado y qué debería saber?\",\n \"clearChat\": \"Borrar chat\",\n \"defaultPlaceholder\": \"Pregúntame lo que quieras…\",\n \"deleteThis\": \"Eliminar esto\",\n \"detailsTranslated\": \"Detalles traducidos. Los números y enlaces se mantienen exactamente como se muestran.\",\n \"displayCapture\": \"capturar {name}\",\n \"displayCaptureAll\": \"capturar todo ({count} elementos)\",\n \"displayDelete\": \"eliminar esto\",\n \"displayViewHistory\": \"¿qué has guardado?\",\n \"entityLangIntro\": \"Respondo en {lang}. Las tarjetas de resultados pueden mantenerse exactamente como las escribió este sitio, o también pueden traducirse.\",\n \"entityLangPlaceholder\": \"Elige una de las dos tarjetas de arriba…\",\n \"errAccessRevoked\": \"La tienda ha revocado su acceso al asistente.\",\n \"errAccountRequired\": \"Por favor, cree una cuenta para seguir usando el asistente de chat.\",\n \"errShopperReplyLimit\": \"Ha alcanzado el límite de respuestas de este sitio para su cuenta.\",\n \"errStreamInterrupted\": \"La respuesta fue interrumpida. Por favor, inténtelo de nuevo.\",\n \"errTokenLimit\": \"Ha alcanzado su límite de uso. Por favor, actualice sus límites de facturación en su panel de control para continuar.\",\n \"errTooManyRequests\": \"El asistente está recibiendo demasiadas solicitudes en este momento. Por favor, inténtelo de nuevo en unos instantes.\",\n \"footerHint\": \"kiku · busca en todo el catálogo en tiempo real\",\n \"greetReturning\": \"Hola, {name}.\",\n \"greetReturningLead\": \"¿Qué puedo encontrar para usted hoy?\",\n \"howShouldResultsLook\": \"¿Cómo deberían verse los resultados?\",\n \"inLanguage\": \"En {lang}\",\n \"keyAutoHide\": \"Se oculta automáticamente en {seconds}s.\",\n \"keyCopied\": \"Copiado\",\n \"keyCopyId\": \"Copiar ID\",\n \"keyCopySecret\": \"Copiar secreto\",\n \"keyCreateNew\": \"Soy nuevo/a, crear uno\",\n \"keyCreating\": \"Creando…\",\n \"keyDismiss\": \"Descartar\",\n \"keyPastePlaceholder\": \"tu ID público…\",\n \"keyPastePrompt\": \"Pega tu ID público — o crea uno\",\n \"keyPublicHint\": \"Pégalo en cualquier sitio para guardar en la misma memoria.\",\n \"keyPublicTitle\": \"Tu ID público\",\n \"keySecretHint\": \"Mantenlo privado — úsalo para desbloquear tu memoria.\",\n \"keySecretTitle\": \"Tu secreto — mostrado solo una vez\",\n \"keyUseMine\": \"Usar mi ID\",\n \"kikuActionUnavailable\": \"Lo siento, esa acción no está disponible en este sitio.\",\n \"kikuCaptureDbError\": \"La captura falló debido a un error de base de datos.\",\n \"kikuCaptureNoContext\": \"La captura falló porque el SDK no proporcionó contexto de página o producto.\",\n \"kikuCaptureNoUrl\": \"No se pudieron guardar elementos — ninguno tenía una URL válida.\",\n \"kikuCaptureNoneSelected\": \"No se seleccionaron elementos para capturar.\",\n \"kikuDeleteDbError\": \"La eliminación falló debido a un error de base de datos.\",\n \"kikuDeleteDone\": \"Lo he eliminado de tus elementos guardados.\",\n \"kikuDeleteNoContext\": \"La eliminación falló porque no se proporcionó contexto de página para identificar qué eliminar.\",\n \"kikuMemoryIntro\": \"Todo lo que has capturado en diferentes sitios vive en tu memoria privada. Desbloquéala con tu secreto:\",\n \"kikuMintNeeded\": \"Para guardar elementos en diferentes sitios necesitas una clave kiku — te crearé una. Se muestra solo una vez, así que guárdala en un lugar seguro.\",\n \"kikuMintOffer\": \"Puedo guardar esto por ti y hacer que te siga en diferentes sitios — te crearé una clave kiku. Se muestra solo una vez, así que guárdala en un lugar seguro.\",\n \"kikuNeedKeyToUpdate\": \"Introduce tu clave kiku para que pueda encontrar y actualizar tus elementos guardados.\",\n \"micDenied\": \"Micrófono bloqueado. Permite el acceso al micrófono para este sitio e inténtalo de nuevo.\",\n \"micFailed\": \"No pude oír eso. Inténtalo de nuevo.\",\n \"micInsecure\": \"La voz requiere una conexión segura (https).\",\n \"micLangUnsupported\": \"Este navegador aún no puede transcribir ese idioma. Escriba en su lugar.\",\n \"micMissing\": \"No se encontró ningún micrófono.\",\n \"micNetwork\": \"La voz necesita una conexión en este momento. Revise la suya e inténtelo de nuevo.\",\n \"micNoSpeech\": \"No he captado nada. Inténtelo de nuevo, un poco más cerca del micrófono.\",\n \"namePlaceholder\": \"Escriba su nombre…\",\n \"nameStepAsk\": \"¿Cómo debo llamarle?\",\n \"nameStepLead\": \"Puedo buscar, visualizar o capturar cualquier cosa por usted, en este sitio o en cualquier otro.\",\n \"nameStepTitle\": \"Encantado de conocerle.\",\n \"namesAsWritten\": \"Nombres y detalles exactamente como los enumera el sitio.\",\n \"pillCompareTop2\": \"Comparar los 2 mejores\",\n \"pillCompareTop2Query\": \"Compara {a} y {b}\",\n \"pillFindAlternatives\": \"Buscar alternativas\",\n \"pillFindAlternativesQuery\": \"¿Qué alternativas hay a {name}?\",\n \"pillMoreOn\": \"Más sobre {name}\",\n \"pillMoreOnQuery\": \"Cuéntame más sobre {name}\",\n \"pillRecommend\": \"Recomendar algo\",\n \"pillRecommendQuery\": \"¿Qué me recomiendas?\",\n \"pillShowPopular\": \"Mostrar artículos populares\",\n \"pillShowPopularQuery\": \"¿Cuáles son tus artículos más populares?\",\n \"pillSimilarOptions\": \"Opciones similares\",\n \"pillSimilarOptionsQuery\": \"Muéstrame más opciones como {name}\",\n \"pillUnder\": \"Menos de {amount}\",\n \"pillUnderQuery\": \"Muéstrame opciones por menos de {amount}\",\n \"pillWhichBest\": \"¿Cuál es el mejor?\",\n \"pillWhichBestQuery\": \"¿Cuál me recomendarías y por qué?\",\n \"replyingOriginal\": \"Respondiendo en {lang}, resultados tal como los escribió este sitio. Pregúnteme lo que quiera.\",\n \"replyingTranslated\": \"Respondiendo en {lang}, resultados también traducidos. Pregúnteme lo que quiera.\",\n \"statusSent\": \"Enviado\",\n \"statusStopped\": \"Enviado · respuesta detenida\",\n \"thinking\": \"Pensando\",\n \"thoughtForSeconds\": \"Pensado durante {duration}\",\n \"thoughtProcess\": \"Proceso de pensamiento\",\n \"vizDisclaimerImage\": \"Generado con Inteligencia Artificial: los colores, el tamaño y la ubicación pueden diferir del producto real.\",\n \"vizDisclaimerVideo\": \"Generado con Inteligencia Artificial: los colores, el tamaño y el movimiento pueden diferir del producto real.\",\n \"vizUnavailable\": \"No se pudo cargar la vista previa.\",\n \"voiceListening\": \"Escuchando… toque el micrófono para detener.\",\n \"voiceSending\": \"Entendido, enviando…\",\n \"termsStepTitle\": \"Privacidad y términos de uso\",\n \"termsStepSubtitle\": \"Transparente, anónimo y sin recolección de datos personales.\",\n \"termsPiiTitle\": \"Cero recolección de datos personales\",\n \"termsPiiDesc\": \"Nunca recopilamos ni almacenamos información de identificación personal (sin correos, números de teléfono ni identidades reales) de tus conversaciones o sesiones de voz.\",\n \"termsSessionTitle\": \"Tokens de sesión anónimos\",\n \"termsSessionDesc\": \"Tu sesión utiliza un token anónimo generado en el cliente únicamente para mantener el contexto. Nunca se vincula a tu identidad real.\",\n \"termsMemoryTitle\": \"Chats efímeros vs. Bóveda Mimi\",\n \"termsMemoryDesc\": \"Las conversaciones regulares son efímeras: cerrar o borrar el chat las elimina para siempre. Lo que guardas con «@kiku» está cifrado y se puede desbloquear en mimi.akropolys.cloud con tu clave secreta.\",\n \"termsCookieTitle\": \"Telemetría del sitio web anfitrión\",\n \"termsCookieDesc\": \"El sitio web donde está integrado kiku puede recopilar cookies y analíticas según su propia política de cookies, fuera del control de kiku.\",\n \"termsAgreeButton\": \"Aceptar y continuar\",\n \"termsAgreeCounting\": \"Aceptar y continuar ({seconds}s)\",\n \"termsPlaceholder\": \"Por favor, revisa y acepta nuestra privacidad y términos arriba…\",\n \"whatHaveYouSaved\": \"¿Qué ha guardado?\",\n \"voiceHint\": \"Solo habla — responderé cuando hagas una pausa.\",\n \"voiceModeExit\": \"Salir de manos libres\",\n \"voiceModeStart\": \"Conversación manos libres\",\n \"voiceMuted\": \"Silenciado\",\n \"voiceMutedHint\": \"Toca el micrófono para hablar de nuevo.\",\n \"voicePhaseListening\": \"Escuchando\",\n \"voicePhaseSpeaking\": \"Hablando\",\n \"voicePhaseThinking\": \"Pensando\"\n },\n \"swahili\": {\n \"allSet\": \"Uko tayari, {name}.\",\n \"asWritten\": \"Kama ilivyoandikwa\",\n \"captureAll\": \"Chukua zote ({count})\",\n \"captureAndRemember\": \"kiku — chukua & kumbuka\",\n \"captureCurrentPage\": \"Chukua ukurasa wa sasa\",\n \"cardClickAnswer\": \"{name}\",\n \"cardClickQuery\": \"Nisaidie kujua zaidi kuhusu {name}{price} — ni maelezo yake muhimu, ni kwa nani inafaa zaidi, na ninapaswa kujua nini?\",\n \"clearChat\": \"Futa mazungumzo\",\n \"defaultPlaceholder\": \"Uliza chochote…\",\n \"deleteThis\": \"Futa hii\",\n \"detailsTranslated\": \"Maelezo yame tafsiriwa. Nambari na viungo vinabaki kama ilivyo.\",\n \"displayCapture\": \"chukua {name}\",\n \"displayCaptureAll\": \"chukua zote ({count} items)\",\n \"displayDelete\": \"futa hii\",\n \"displayViewHistory\": \"ulivyohifadhi?\",\n \"entityLangIntro\": \"Nitajibu kwa {lang}. Kadi za matokeo zinaweza kubaki kama ilivyoandikwa kwenye tovuti hii, au kutafsiriwa pia.\",\n \"entityLangPlaceholder\": \"Chagua moja ya kadi mbili zilizo juu…\",\n \"errAccessRevoked\": \"Ufikiaji wako kwa msaidizi umeondolewa na duka.\",\n \"errAccountRequired\": \"Tafadhali unda akaunti ili kuendelea kutumia msaidizi wa mazungumzo.\",\n \"errShopperReplyLimit\": \"Umefikia kikomo cha majibu cha tovuti hii kwa akaunti yako.\",\n \"errStreamInterrupted\": \"Jibu lilikatizwa. Tafadhali jaribu tena.\",\n \"errTokenLimit\": \"Umefikia kikomo cha matumizi yako. Tafadhali sasisha mipaka ya malipo kwenye dashbodi yako ili kuendelea.\",\n \"errTooManyRequests\": \"Msaidizi anapokea maombi mengi sana kwa sasa. Tafadhali jaribu tena baada ya muda mfupi.\",\n \"footerHint\": \"kiku · hutafuta katika katalogi nzima kwa wakati halisi\",\n \"greetReturning\": \"Habari, {name}.\",\n \"greetReturningLead\": \"Nini naweza kukutafuta leo?\",\n \"howShouldResultsLook\": \"Matokeo yanapaswa kuonekana vipi?\",\n \"inLanguage\": \"Kwa {lang}\",\n \"keyAutoHide\": \"Inaficha kiotomatiki baada ya {seconds}s.\",\n \"keyCopied\": \"Imekopiwa\",\n \"keyCopyId\": \"Nakili kitambulisho\",\n \"keyCopySecret\": \"Nakili siri\",\n \"keyCreateNew\": \"Mimi mpya — unda moja\",\n \"keyCreating\": \"Inaunda…\",\n \"keyDismiss\": \"Ondoa\",\n \"keyPastePlaceholder\": \"kitambulisho chako cha umma…\",\n \"keyPastePrompt\": \"Bandika kitambulisho chako cha umma — au unda moja\",\n \"keyPublicHint\": \"Bandika hii kwenye tovuti yoyote ili kuihifadhi katika kumbukumbu sawa.\",\n \"keyPublicTitle\": \"Kitambulisho chako cha umma\",\n \"keySecretHint\": \"Ikeepye kibinafsi — tumia kufungua kumbukumbu yako.\",\n \"keySecretTitle\": \"Siri yako — inaonyeshwa mara moja tu\",\n \"keyUseMine\": \"Tumia kitambulisho changu\",\n \"kikuActionUnavailable\": \"Samahani — kitendo hicho hakipatikani kwenye tovuti hii.\",\n \"kikuCaptureDbError\": \"Uchukuaji umeshindwa kutokana na hitilafu ya hifadhidata.\",\n \"kikuCaptureNoContext\": \"Uchukuaji umeshindwa kwa sababu hakuna muktadha wa ukurasa au bidhaa uliotolewa na SDK.\",\n \"kikuCaptureNoUrl\": \"Haikuweza kuhifadhi vitu vyovyote — hakuna kilichokuwa na URL halali.\",\n \"kikuCaptureNoneSelected\": \"Hakuna vitu vilivyochaguliwa kwa uchukuaji.\",\n \"kikuDeleteDbError\": \"Ufutaji umeshindwa kutokana na hitilafu ya hifadhidata.\",\n \"kikuDeleteDone\": \"Imeondolewa kutoka vitu vyako vilivyohifadhiwa.\",\n \"kikuDeleteNoContext\": \"Ufutaji umeshindwa kwa sababu hakuna muktadha wa ukurasa uliotolewa kutambua kinachofutwa.\",\n \"kikuMemoryIntro\": \"Kila kitu ulichukua kwenye tovuti mbalimbali kiko katika kumbukumbu yako ya kibinafsi. Kifungue kwa siri yako:\",\n \"kikuMintNeeded\": \"Ili kuhifadhi vitu kwenye tovuti mbalimbali unahitaji ufunguo wa kiku — nitaunda moja kwa ajili yako. Inaonyeshwa mara moja tu, hivyo uiweke mahali salama.\",\n \"kikuMintOffer\": \"Ninaweza kuhifadhi hii kwa ajili yako na iende nawe kwenye tovuti mbalimbali — nitaunda ufunguo wa kiku. Inaonyeshwa mara moja tu, hivyo uiweke mahali salama.\",\n \"kikuNeedKeyToUpdate\": \"Weka ufunguo wako wa kiku ili niweze kupata na kusasisha vitu vyako vilivyohifadhiwa.\",\n \"micDenied\": \"Kinanda cha sauti kimezuiwa. Ruhusu ufikiaji wa kinanda kwa tovuti hii, kisha jaribu tena.\",\n \"micFailed\": \"Sikuweza kusikia hilo. Jaribu tena.\",\n \"micInsecure\": \"Sauti inahitaji muunganisho salama (https).\",\n \"micLangUnsupported\": \"Kivinjari hiki hakiwezi kuandika lugha hiyo bado. Andika badala yake.\",\n \"micMissing\": \"Hakuna kipaza sauti kilichopatikana.\",\n \"micNetwork\": \"Sauti inahitaji muunganisho kwa sasa. Angalia yako na ujaribu tena.\",\n \"micNoSpeech\": \"Sijapata chochote. Jaribu tena, karibu zaidi na kipaza sauti.\",\n \"namePlaceholder\": \"Andika jina lako…\",\n \"nameStepAsk\": \"Ninapaswa kukuita nani?\",\n \"nameStepLead\": \"Ninaweza kutafuta, kuonyesha, au kunasa chochote kwa ajili yako — kwenye tovuti hii au nyingine yoyote.\",\n \"nameStepTitle\": \"Nafurahi kukutana nawe.\",\n \"namesAsWritten\": \"Majina na maelezo kama ilivyo kwenye tovuti.\",\n \"pillCompareTop2\": \"Linganisha bora 2\",\n \"pillCompareTop2Query\": \"Linganisha {a} na {b}\",\n \"pillFindAlternatives\": \"Tafuta mbadala\",\n \"pillFindAlternativesQuery\": \"Ni mbadala gani mazuri kwa {name}?\",\n \"pillMoreOn\": \"Zaidi kuhusu {name}\",\n \"pillMoreOnQuery\": \"Nisaidie kujua zaidi kuhusu {name}\",\n \"pillRecommend\": \"Pendekeza kitu\",\n \"pillRecommendQuery\": \"Unaweza kunipendekeza nini?\",\n \"pillShowPopular\": \"Onyesha vitu maarufu\",\n \"pillShowPopularQuery\": \"Ni bidhaa gani zimekuwa maarufu zaidi?\",\n \"pillSimilarOptions\": \"Chaguzi zinazofanana\",\n \"pillSimilarOptionsQuery\": \"Nionyeshe zaidi kama {name}\",\n \"pillUnder\": \"Chini ya {amount}\",\n \"pillUnderQuery\": \"Nionyeshe chaguo chini ya {amount}\",\n \"pillWhichBest\": \"Ni ipi bora?\",\n \"pillWhichBestQuery\": \"Ni ipi unayopendekeza na kwa nini?\",\n \"replyingOriginal\": \"Ninajibu kwa {lang}, matokeo kama ilivyoandikwa kwenye tovuti hii. Uliza chochote.\",\n \"replyingTranslated\": \"Ninajibu kwa {lang}, matokeo yamefasiriwa pia. Uliza chochote.\",\n \"statusSent\": \"Imetumwa\",\n \"statusStopped\": \"Imetumwa · majibu yametolewa\",\n \"thinking\": \"Inafikiri\",\n \"thoughtForSeconds\": \"Imefikiri kwa {duration}\",\n \"thoughtProcess\": \"Mchakato wa mawazo\",\n \"vizDisclaimerImage\": \"Imetengenezwa kwa kutumia Akili Bandia — rangi, ukubwa na upangaji huenda yakatofautiana na bidhaa halisi.\",\n \"vizDisclaimerVideo\": \"Imetengenezwa kwa kutumia Akili Bandia — rangi, ukubwa na mwendo huenda yakatofautiana na bidhaa halisi.\",\n \"vizUnavailable\": \"Hakuna uwezo wa kupakia onyesho la awali.\",\n \"voiceListening\": \"Inasikiliza… gonga kipaza sauti ili kusimama\",\n \"voiceSending\": \"Nimepokea — ninatuma…\",\n \"termsStepTitle\": \"Faragha na Masharti ya Matumizi\",\n \"termsStepSubtitle\": \"Wazi, bila utambulisho, na bila kukusanya taarifa binafsi.\",\n \"termsPiiTitle\": \"Hakuna Ukusanyaji wa Taarifa Binafsi\",\n \"termsPiiDesc\": \"Hatukusanyi wala kuhifadhi taarifa za utambulisho binafsi (hakuna barua pepe, nambari za simu, wala majina halisi) kutoka kwa mazungumzo yako au sauti.\",\n \"termsSessionTitle\": \"Vitambulisho Visivyojulikana vya Kipindi\",\n \"termsSessionDesc\": \"Kipindi chako kinatumia kitambulisho kisichojulikana upande wa mteja ili kuendeleza muktadha tu. Hakihusishwi na utambulisho wako halisi.\",\n \"termsMemoryTitle\": \"Mazungumzo ya Muda dhidi ya Hazina ya Mimi\",\n \"termsMemoryDesc\": \"Mazungumzo ya kawaida ni ya muda — kufunga au kufuta mazungumzo kunayaondoa kabisa. Vitu unavyohifadhi kwa \\\"@kiku\\\" vimelindwa na vinaweza kufunguliwa kwenye mimi.akropolys.cloud kwa ufunguo wako wa siri.\",\n \"termsCookieTitle\": \"Takwimu za Tovuti Mwenyeji\",\n \"termsCookieDesc\": \"Tovuti inayotumia kiku inaweza kukusanya vidakuzi na takwimu kulingana na sera yake ya vidakuzi, nje ya udhibiti wa kiku.\",\n \"termsAgreeButton\": \"Kubali na Uendelee\",\n \"termsAgreeCounting\": \"Kubali na Uendelee ({seconds}s)\",\n \"termsPlaceholder\": \"Tafadhali kagua na ukubali sera ya faragha na masharti hapo juu…\",\n \"whatHaveYouSaved\": \"Umehifadhi nini?\",\n \"voiceHint\": \"Ongea tu — nitajibu ukipumzika.\",\n \"voiceModeExit\": \"Ondoka kwenye hali ya bila mikono\",\n \"voiceModeStart\": \"Mazungumzo ya bila mikono\",\n \"voiceMuted\": \"Imezimwa sauti\",\n \"voiceMutedHint\": \"Gonga kipaza sauti ili kuongea tena.\",\n \"voicePhaseListening\": \"Inasikiliza\",\n \"voicePhaseSpeaking\": \"Inazungumza\",\n \"voicePhaseThinking\": \"Inafikiri\"\n },\n \"urdu\": {\n \"allSet\": \"آپ بالکل تیار ہیں، {name}۔\",\n \"asWritten\": \"جیسا لکھا ہے\",\n \"captureAll\": \"سب محفوظ کریں ({count})\",\n \"captureAndRemember\": \"kiku — محفوظ کریں اور یاد رکھیں\",\n \"captureCurrentPage\": \"موجودہ صفحہ محفوظ کریں\",\n \"cardClickAnswer\": \"{name}\",\n \"cardClickQuery\": \"مجھے {name}{price} کے بارے میں مزید بتائیں — اس کی اہم خصوصیات کیا ہیں، یہ کس کے لیے بہترین ہے، اور مجھے کیا جاننا چاہیے؟\",\n \"clearChat\": \"چیٹ صاف کریں\",\n \"defaultPlaceholder\": \"مجھ سے کچھ بھی پوچھیں…\",\n \"deleteThis\": \"اسے حذف کریں\",\n \"detailsTranslated\": \"تفصیلات کا ترجمہ کر دیا گیا۔ قیمتیں اور لنکس ویسے ہی رہیں گے۔\",\n \"displayCapture\": \"{name} کو محفوظ کریں\",\n \"displayCaptureAll\": \"سب محفوظ کریں ({count} اشیاء)\",\n \"displayDelete\": \"اسے حذف کریں\",\n \"displayViewHistory\": \"آپ نے کیا محفوظ کیا ہے؟\",\n \"entityLangIntro\": \"میں {lang} میں جواب دیتا ہوں۔ نتائج کے کارڈز ویسے ہی رہ سکتے ہیں جیسے سائٹ پر لکھے ہیں، یا ان کا ترجمہ بھی کیا جا سکتا ہے۔\",\n \"entityLangPlaceholder\": \"اوپر دیے گئے دو کارڈز میں سے ایک منتخب کریں…\",\n \"errAccessRevoked\": \"اسٹور کی طرف سے اسسٹنٹ تک آپ کی رسائی منسوخ کر دی گئی ہے۔\",\n \"errAccountRequired\": \"چیٹ اسسٹنٹ کا استعمال جاری رکھنے کے لیے برائے مہربانی اکاؤنٹ بنائیں۔\",\n \"errShopperReplyLimit\": \"آپ اس سائٹ پر اپنے اکاؤنٹ کی جوابات کی حد تک پہنچ چکے ہیں۔\",\n \"errStreamInterrupted\": \"جواب میں خلل پڑ گیا۔ برائے مہربانی دوبارہ کوشش کریں۔\",\n \"errTokenLimit\": \"آپ کے استعمال کی حد ختم ہو چکی ہے۔ جاری رکھنے کے لیے اپنے ڈیش بورڈ میں بلنگ کی حد اپ ڈیٹ کریں۔\",\n \"errTooManyRequests\": \"اسسٹنٹ پر اس وقت بہت زیادہ درخواستیں آرہی ہیں۔ برائے مہربانی تھوڑی دیر بعد کوشش کریں۔\",\n \"footerHint\": \"kiku · حقیقی وقت میں مکمل کیٹلاگ تلاش کرتا ہے\",\n \"greetReturning\": \"خوش آمدید، {name}۔\",\n \"greetReturningLead\": \"آج میں آپ کے لیے کیا تلاش کر سکتا ہوں؟\",\n \"howShouldResultsLook\": \"نتائج کیسی دکھنی چاہئیں؟\",\n \"inLanguage\": \"{lang} میں\",\n \"keyAutoHide\": \"{seconds} سیکنڈ میں خود بخود چھپ جائے گا۔\",\n \"keyCopied\": \"کاپی ہو گیا\",\n \"keyCopyId\": \"آئی ڈی کاپی کریں\",\n \"keyCopySecret\": \"خفیہ کلید کاپی کریں\",\n \"keyCreateNew\": \"میں نیا ہوں — نئی بنائیں\",\n \"keyCreating\": \"بنایا جا رہا ہے…\",\n \"keyDismiss\": \"رد کریں\",\n \"keyPastePlaceholder\": \"آپ کی پبلک آئی ڈی…\",\n \"keyPastePrompt\": \"اپنی پبلک آئی ڈی چسپاں کریں — یا نئی بنائیں\",\n \"keyPublicHint\": \"اسی یادداشت میں محفوظ کرنے کے لیے اسے کسی بھی سائٹ پر چسپاں کریں۔\",\n \"keyPublicTitle\": \"آپ کی پبلک آئی ڈی\",\n \"keySecretHint\": \"اسے خفیہ رکھیں — اپنی یادداشت کو کھولنے کے لیے استعمال کریں۔\",\n \"keySecretTitle\": \"آپ کی خفیہ کلید — صرف ایک بار دکھائی جائے گی\",\n \"keyUseMine\": \"میری آئی ڈی استعمال کریں\",\n \"kikuActionUnavailable\": \"معذرت — یہ عمل اس سائٹ پر دستیاب نہیں ہے۔\",\n \"kikuCaptureDbError\": \"ڈیٹا بیس کی خرابی کی وجہ سے محفوظ کرنے میں ناکامی۔\",\n \"kikuCaptureNoContext\": \"صفحے کا سیاق و سباق نہ ملنے کی وجہ سے محفوظ کرنے میں ناکامی۔\",\n \"kikuCaptureNoUrl\": \"کوئی آئٹم محفوظ نہیں ہو سکا کیونکہ کسی کے پاس درست URL نہیں تھا۔\",\n \"kikuCaptureNoneSelected\": \"محفوظ کرنے کے لیے کوئی آئٹم منتخب نہیں کیا گیا۔\",\n \"kikuDeleteDbError\": \"ڈیٹا بیس کی خرابی کی وجہ سے حذف کرنے میں ناکامی۔\",\n \"kikuDeleteDone\": \"آپ کی محفوظ کردہ اشیاء سے ہٹا دیا گیا۔\",\n \"kikuDeleteNoContext\": \"حذف کرنے کے لیے صفحے کا سیاق و سباق فراہم نہیں کیا گیا۔\",\n \"kikuMemoryIntro\": \"سائٹس بھر میں محفوظ کردہ تمام چیزیں آپ کی نجی یادداشت میں ہیں۔ اپنی خفیہ کلید سے کھولیں:\",\n \"kikuMintNeeded\": \"سائٹس پر چیزیں محفوظ کرنے کے لیے آپ کو kiku کی ضرورت ہے — میں آپ کے لیے ایک کلید بناؤں گا۔ یہ صرف ایک بار دکھائی جاتی ہے، اسے محفوظ رکھیں۔\",\n \"kikuMintOffer\": \"میں اسے آپ کے لیے محفوظ رکھ سکتا ہوں — میں آپ کے لیے ایک kiku کلید بناؤں گا۔ یہ صرف ایک بار دکھائی جاتی ہے۔\",\n \"kikuNeedKeyToUpdate\": \"اپنی kiku کلید درج کریں تاکہ میں آپ کی محفوظ کردہ اشیاء تلاش اور اپ ڈیٹ کر سکوں۔\",\n \"micDenied\": \"مائیکروفون بلاک ہے۔ اس سائٹ کے لیے مائیک کی اجازت دیں اور دوبارہ کوشش کریں۔\",\n \"micFailed\": \"آواز سنائی نہیں دی۔ دوبارہ کوشش کریں۔\",\n \"micInsecure\": \"آواز کے لیے محفوظ (https) کنکشن درکار ہے۔\",\n \"micLangUnsupported\": \"یہ براؤزر ابھی اس زبان کو نہیں سمجھ سکتا۔ براہ کرم ٹائپ کریں۔\",\n \"micMissing\": \"کوئی مائیکروفون نہیں ملا۔\",\n \"micNetwork\": \"آواز کے لیے انٹرنیٹ کنکشن درکار ہے۔ اپنا کنکشن چیک کریں اور دوبارہ کوشش کریں۔\",\n \"micNoSpeech\": \"کچھ سنائی نہیں دیا۔ مائیک کے قریب آ کر دوبارہ بولیں۔\",\n \"namePlaceholder\": \"اپنا نام لکھیں…\",\n \"nameStepAsk\": \"میں آپ کو کس نام سے پکاروں؟\",\n \"nameStepLead\": \"میں آپ کے لیے اس سائٹ یا کسی دوسری سائٹ پر کچھ بھی تلاش، تصور یا محفوظ کر سکتا ہوں۔\",\n \"nameStepTitle\": \"آپ سے مل کر خوشی ہوئی۔\",\n \"namesAsWritten\": \"نام اور تفصیلات بالکل ویسے جیسے سائٹ پر درج ہیں۔\",\n \"pillCompareTop2\": \"بہترین 2 کا موازنہ کریں\",\n \"pillCompareTop2Query\": \"{a} اور {b} کا موازنہ کریں\",\n \"pillFindAlternatives\": \"متبادل تلاش کریں\",\n \"pillFindAlternativesQuery\": \"{name} کے اچھے متبادل کیا ہیں؟\",\n \"pillMoreOn\": \"{name} کے بارے میں مزید\",\n \"pillMoreOnQuery\": \"مجھے {name} کے بارے میں مزید بتائیں\",\n \"pillRecommend\": \"کچھ تجویز کریں\",\n \"pillRecommendQuery\": \"آپ میرے لیے کیا تجویز کرتے ہیں؟\",\n \"pillShowPopular\": \"مقبول اشیاء دکھائیں\",\n \"pillShowPopularQuery\": \"آپ کی سب سے مقبول اشیاء کون سی ہیں؟\",\n \"pillSimilarOptions\": \"ملتے جلتے اختیارات\",\n \"pillSimilarOptionsQuery\": \"مجھے {name} جیسی مزید چیزیں دکھائیں\",\n \"pillUnder\": \"{amount} سے کم\",\n \"pillUnderQuery\": \"{amount} سے کم قیمت والے اختیارات دکھائیں\",\n \"pillWhichBest\": \"کون سا بہترین ہے؟\",\n \"pillWhichBestQuery\": \"آپ کون سا تجویز کریں گے اور کیوں؟\",\n \"replyingOriginal\": \"میں {lang} میں جواب دے رہا ہوں، نتائج سائٹ کے مطابق ہیں۔ مجھ سے کچھ بھی پوچھیں۔\",\n \"replyingTranslated\": \"میں {lang} میں جواب دے رہا ہوں، نتائج کا ترجمہ بھی کیا گیا ہے۔ مجھ سے کچھ بھی پوچھیں۔\",\n \"statusSent\": \"بھیج دیا گیا\",\n \"statusStopped\": \"بھیج دیا گیا · جواب روک دیا گیا\",\n \"thinking\": \"سوچ رہا ہے\",\n \"thoughtForSeconds\": \"{duration} تک سوچا\",\n \"thoughtProcess\": \"سوچنے کا عمل\",\n \"vizDisclaimerImage\": \"مصنوعی ذہانت سے تیار کردہ — اصل پروڈکٹ سے رنگ، سائز اور جگہ مختلف ہو سکتی ہے۔\",\n \"vizDisclaimerVideo\": \"مصنوعی ذہانت سے تیار کردہ — اصل پروڈکٹ سے رنگ، سائز اور حرکت مختلف ہو سکتی ہے۔\",\n \"vizUnavailable\": \"پیش نظارہ لوڈ نہیں ہو سکا۔\",\n \"voiceHint\": \"بس بات کریں — جب آپ رکیں گے تو میں جواب دوں گا۔\",\n \"voiceListening\": \"سن رہا ہے… روکنے کے لیے مائیک پر ٹیپ کریں\",\n \"voiceModeExit\": \"ہینڈز فری سے نکلیں\",\n \"voiceModeStart\": \"ہینڈز فری گفتگو\",\n \"voiceMuted\": \"خاموش (میوٹ)\",\n \"voiceMutedHint\": \"دوبارہ بولنے کے لیے مائیکروفون پر ٹیپ کریں۔\",\n \"voicePhaseListening\": \"سن رہا ہے\",\n \"voicePhaseSpeaking\": \"بول رہا ہے\",\n \"voicePhaseThinking\": \"سوچ رہا ہے\",\n \"voiceSending\": \"سمجھ گیا — بھیج رہا ہے…\",\n \"termsStepTitle\": \"رازداری اور استعمال کی شرائط\",\n \"termsStepSubtitle\": \"شفاف، گمنام، اور بغیر کسی ذاتی شناختی ڈیٹا کے۔\",\n \"termsPiiTitle\": \"کوئی ذاتی شناختی ڈیٹا اکٹھا نہیں کیا جاتا\",\n \"termsPiiDesc\": \"ہم آپ کی چیٹس یا صوتی گفتگو سے کبھی بھی کوئی ذاتی شناختی معلومات (کوئی ای میل، فون نمبر، یا حقیقی نام) اکٹھا یا محفوظ نہیں کرتے۔\",\n \"termsSessionTitle\": \"گمنام سیشن ٹوکنز\",\n \"termsSessionDesc\": \"آپ کا سیشن صرف سیاق و سباق برقرار رکھنے کے لیے ایک گمنام ٹوکن استعمال کرتا ہے۔ یہ کبھی بھی آپ کی حقیقی شناخت سے نہیں جڑتا۔\",\n \"termsMemoryTitle\": \"عارضی چیٹس بمقابلہ میمی والٹ\",\n \"termsMemoryDesc\": \"عام چیٹس عارضی ہیں — ٹیب بند کرنے یا چیٹ صاف کرنے سے وہ ہمیشہ کے لیے ختم ہو جاتی ہیں۔ وہ چیزیں جو آپ \\\"@kiku\\\" سے محفوظ کرتے ہیں انکرپٹڈ ہوتی ہیں اور انہیں اپنی خفیہ کلید کے ذریعے mimi.akropolys.cloud پر کھولا جا سکتا ہے۔\",\n \"termsCookieTitle\": \"میزبان ویب سائٹ ٹیلی میٹری\",\n \"termsCookieDesc\": \"جس ویب سائٹ پر kiku شامل ہے وہ اپنی کوکی پالیسی کے تحت کوکیز اور اینالیٹکس جمع کر سکتی ہے، جو kiku کے کنٹرول سے باہر ہے۔\",\n \"termsAgreeButton\": \"متفق ہوں اور جاری رکھیں\",\n \"termsAgreeCounting\": \"متفق ہوں اور جاری رکھیں ({seconds}s)\",\n \"termsPlaceholder\": \"برائے مہربانی اوپر دی گئی رازداری اور شرائط کا جائزہ لیں اور قبول کریں…\",\n \"whatHaveYouSaved\": \"آپ نے کیا محفوظ کیا ہے؟\"\n }\n}\n","import { useState, useRef, useEffect, useCallback } from 'react';\r\nimport type { ChatMessage } from '@akropolys/sdk';\r\n\r\ninterface UseChatScrollOptions {\r\n messages: ChatMessage[];\r\n loading: boolean;\r\n messageRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;\r\n}\r\n\r\nexport function useChatScroll({ messages, loading, messageRefs }: UseChatScrollOptions) {\r\n const msgsContainerRef = useRef<HTMLDivElement>(null);\r\n const lastExternalScrollRef = useRef(0);\r\n const [showJumpToBottom, setShowJumpToBottom] = useState(false);\r\n const [scrollProgress, setScrollProgress] = useState(1);\r\n const [activeMsgIdx, setActiveMsgIdx] = useState(0);\r\n const resyncScrollRef = useRef<() => void>(() => {});\r\n const glideScrollRef = useRef<((to: number) => void) | null>(null);\r\n const touchScrollingRef = useRef(false);\r\n const stickToBottomRef = useRef(true);\r\n const [alertTick, setAlertTick] = useState(0);\r\n const awayEpochRef = useRef(0);\r\n const lastAlertKeyRef = useRef('');\r\n const dismissJumpAlertRef = useRef<() => void>(() => {});\r\n const resetAlertArmingRef = useRef<() => void>(() => {});\r\n\r\n useEffect(() => {\r\n const el = msgsContainerRef.current;\r\n if (!el) return;\r\n let idle: ReturnType<typeof setTimeout>;\r\n const settle = () => {\r\n clearTimeout(idle);\r\n idle = setTimeout(() => { touchScrollingRef.current = false; }, 150);\r\n };\r\n const onTouchStart = () => {\r\n clearTimeout(idle);\r\n touchScrollingRef.current = true;\r\n dismissJumpAlertRef.current();\r\n };\r\n const onScroll = () => { if (touchScrollingRef.current) settle(); };\r\n el.addEventListener('touchstart', onTouchStart, { passive: true });\r\n el.addEventListener('touchend', settle, { passive: true });\r\n el.addEventListener('touchcancel', settle, { passive: true });\r\n el.addEventListener('scroll', onScroll, { passive: true });\r\n return () => {\r\n clearTimeout(idle);\r\n el.removeEventListener('touchstart', onTouchStart);\r\n el.removeEventListener('touchend', settle);\r\n el.removeEventListener('touchcancel', settle);\r\n el.removeEventListener('scroll', onScroll);\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n const el = msgsContainerRef.current;\r\n if (!el) return;\r\n const JUMP_THRESHOLD = 160;\r\n const STICK_ON = 8;\r\n let queued = 0;\r\n\r\n const measure = () => {\r\n queued = 0;\r\n const distance = el.scrollHeight - el.scrollTop - el.clientHeight;\r\n if (distance <= STICK_ON) {\r\n if (!stickToBottomRef.current) resetAlertArmingRef.current();\r\n stickToBottomRef.current = true;\r\n clearUnreadRef.current();\r\n }\r\n\r\n setShowJumpToBottom(distance > JUMP_THRESHOLD && !stickToBottomRef.current);\r\n\r\n const max = el.scrollHeight - el.clientHeight;\r\n setScrollProgress(max > 8 ? Math.min(1, Math.max(0, el.scrollTop / max)) : 1);\r\n\r\n const line = el.scrollTop + el.clientHeight * 0.33;\r\n let active = 0;\r\n for (let i = 0; i < messageRefs.current.length; i++) {\r\n const node = messageRefs.current[i];\r\n if (node && node.offsetTop - el.offsetTop <= line) active = i;\r\n }\r\n setActiveMsgIdx(active);\r\n };\r\n\r\n const onScroll = () => {\r\n if (queued) return;\r\n queued = requestAnimationFrame(measure);\r\n };\r\n\r\n measure();\r\n el.addEventListener('scroll', onScroll, { passive: true });\r\n const ro = new ResizeObserver(onScroll);\r\n ro.observe(el);\r\n return () => {\r\n if (queued) cancelAnimationFrame(queued);\r\n el.removeEventListener('scroll', onScroll);\r\n ro.disconnect();\r\n };\r\n }, [messages.length, messageRefs]);\r\n\r\n const notifyNewBelow = useCallback((turn: number) => {\r\n const key = `${turn}:${awayEpochRef.current}`;\r\n if (lastAlertKeyRef.current === key) return;\r\n lastAlertKeyRef.current = key;\r\n setAlertTick(t => t + 1);\r\n }, []);\r\n\r\n const [unreadBelow, setUnreadBelow] = useState(false);\r\n const unreadBelowRef = useRef(false);\r\n const markUnread = useCallback(() => {\r\n if (unreadBelowRef.current) return;\r\n unreadBelowRef.current = true;\r\n setUnreadBelow(true);\r\n }, []);\r\n const clearUnread = useCallback(() => {\r\n if (!unreadBelowRef.current) return;\r\n unreadBelowRef.current = false;\r\n setUnreadBelow(false);\r\n }, []);\r\n const clearUnreadRef = useRef<() => void>(() => {});\r\n clearUnreadRef.current = clearUnread;\r\n\r\n const [jumpAlert, setJumpAlert] = useState(false);\r\n const jumpAlertRef = useRef(false);\r\n const alertShownAtRef = useRef(0);\r\n const clearAlert = useCallback(() => {\r\n jumpAlertRef.current = false;\r\n setJumpAlert(false);\r\n }, []);\r\n const resetAlertArming = useCallback(() => {\r\n lastAlertKeyRef.current = '';\r\n clearAlert();\r\n clearUnread();\r\n }, [clearAlert, clearUnread]);\r\n const dismissJumpAlert = useCallback(() => {\r\n if (!jumpAlertRef.current) return;\r\n if (performance.now() - alertShownAtRef.current < 700) return;\r\n clearAlert();\r\n }, [clearAlert]);\r\n dismissJumpAlertRef.current = dismissJumpAlert;\r\n resetAlertArmingRef.current = resetAlertArming;\r\n\r\n useEffect(() => {\r\n if (alertTick === 0) return;\r\n jumpAlertRef.current = true;\r\n alertShownAtRef.current = performance.now();\r\n setJumpAlert(true);\r\n const t = setTimeout(clearAlert, 4200);\r\n return () => clearTimeout(t);\r\n }, [alertTick, clearAlert]);\r\n\r\n const jumpToMessage = useCallback((idx: number) => {\r\n const el = msgsContainerRef.current;\r\n const node = messageRefs.current[idx];\r\n if (!el || !node) return;\r\n const to = node.offsetTop - el.offsetTop - 12;\r\n if (glideScrollRef.current) glideScrollRef.current(to);\r\n else el.scrollTo({ top: to, behavior: 'smooth' });\r\n }, [messageRefs]);\r\n\r\n const jumpToBottom = useCallback(() => {\r\n const el = msgsContainerRef.current;\r\n if (!el) return;\r\n stickToBottomRef.current = true;\r\n resetAlertArmingRef.current();\r\n const bottom = el.scrollHeight - el.clientHeight;\r\n if (glideScrollRef.current) glideScrollRef.current(bottom);\r\n else el.scrollTo({ top: bottom, behavior: 'smooth' });\r\n }, []);\r\n\r\n useEffect(() => {\r\n const container = msgsContainerRef.current;\r\n if (!container) return;\r\n const raf = requestAnimationFrame(() => {\r\n const before = container.scrollTop;\r\n if (!stickToBottomRef.current) {\r\n markUnread();\r\n notifyNewBelow(messages.length);\r\n } else {\r\n if (!touchScrollingRef.current) {\r\n const bottom = container.scrollHeight - container.clientHeight;\r\n if (glideScrollRef.current) { glideScrollRef.current(bottom); return; }\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n if (container.scrollTop !== before) resyncScrollRef.current();\r\n });\r\n return () => cancelAnimationFrame(raf);\r\n }, [messages, loading, messageRefs, notifyNewBelow, markUnread]);\r\n\r\n useEffect(() => {\r\n const el = msgsContainerRef.current;\r\n if (!el) return;\r\n\r\n if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) return;\r\n\r\n const LAMBDA = 7;\r\n const LINE_PX = 16;\r\n const step = 1 / (window.devicePixelRatio || 1);\r\n const snap = (v: number) => Math.round(v / step) * step;\r\n\r\n let target = el.scrollTop;\r\n let current = el.scrollTop;\r\n let written = el.scrollTop;\r\n let lastTime = 0;\r\n let rafId: number | null = null;\r\n\r\n const write = (v: number) => {\r\n if (v === written) return;\r\n el.scrollTop = v;\r\n written = el.scrollTop;\r\n };\r\n\r\n const resync = () => {\r\n if (rafId !== null) { cancelAnimationFrame(rafId); rafId = null; }\r\n el.classList.remove('hsk-scrolling');\r\n target = current = written = el.scrollTop;\r\n };\r\n resyncScrollRef.current = resync;\r\n\r\n glideScrollRef.current = (to: number) => {\r\n if (Math.abs(el.scrollTop - written) > 1) { target = current = written = el.scrollTop; }\r\n const next = Math.round(Math.max(0, Math.min(el.scrollHeight - el.clientHeight, to)));\r\n if (next === target) return;\r\n target = next;\r\n if (rafId === null) {\r\n lastTime = performance.now();\r\n rafId = requestAnimationFrame(update);\r\n }\r\n };\r\n\r\n const update = (now: number) => {\r\n const dt = Math.min((now - lastTime) / 1000, 0.05);\r\n lastTime = now;\r\n current += (target - current) * (1 - Math.exp(-LAMBDA * dt));\r\n if (Math.abs(target - current) < step) {\r\n current = target;\r\n write(Math.round(target));\r\n el.classList.remove('hsk-scrolling');\r\n rafId = null;\r\n return;\r\n }\r\n write(snap(current));\r\n rafId = requestAnimationFrame(update);\r\n };\r\n\r\n const handleWheel = (e: WheelEvent) => {\r\n if (e.ctrlKey) return;\r\n if (Math.abs(el.scrollTop - written) > 1) target = current = written = el.scrollTop;\r\n\r\n if (e.deltaY < 0) {\r\n if (stickToBottomRef.current) awayEpochRef.current += 1;\r\n stickToBottomRef.current = false;\r\n }\r\n\r\n dismissJumpAlertRef.current();\r\n\r\n const scale = e.deltaMode === 1 ? LINE_PX : e.deltaMode === 2 ? el.clientHeight : 1;\r\n const maxScroll = Math.max(0, el.scrollHeight - el.clientHeight);\r\n const next = Math.round(Math.max(0, Math.min(maxScroll, target + e.deltaY * scale)));\r\n\r\n if (next === target) { if (maxScroll > 0) e.preventDefault(); return; }\r\n e.preventDefault();\r\n target = next;\r\n\r\n if (rafId === null) {\r\n lastTime = performance.now();\r\n el.classList.add('hsk-scrolling');\r\n rafId = requestAnimationFrame(update);\r\n }\r\n };\r\n\r\n let lastTop = el.scrollTop;\r\n const handleScroll = () => {\r\n const external = Math.abs(el.scrollTop - written) > 1;\r\n if (external) {\r\n lastExternalScrollRef.current = performance.now();\r\n if (el.scrollTop < lastTop - 1 && stickToBottomRef.current) {\r\n awayEpochRef.current += 1;\r\n stickToBottomRef.current = false;\r\n }\r\n }\r\n lastTop = el.scrollTop;\r\n if (rafId !== null && external) {\r\n cancelAnimationFrame(rafId);\r\n rafId = null;\r\n el.classList.remove('hsk-scrolling');\r\n target = current = written = el.scrollTop;\r\n }\r\n };\r\n\r\n el.addEventListener('wheel', handleWheel, { passive: false });\r\n el.addEventListener('scroll', handleScroll, { passive: true });\r\n return () => {\r\n el.removeEventListener('scroll', handleScroll);\r\n el.removeEventListener('wheel', handleWheel);\r\n if (rafId !== null) cancelAnimationFrame(rafId);\r\n el.classList.remove('hsk-scrolling');\r\n resyncScrollRef.current = () => {};\r\n glideScrollRef.current = null;\r\n };\r\n }, []);\r\n\r\n return {\r\n msgsContainerRef,\r\n lastExternalScrollRef,\r\n showJumpToBottom,\r\n scrollProgress,\r\n activeMsgIdx,\r\n jumpAlert,\r\n unreadBelow,\r\n jumpToMessage,\r\n jumpToBottom,\r\n resetAlertArming,\r\n };\r\n}\r\n","import { useState, useEffect, useCallback } from 'react';\r\nimport type { ChatAction } from '@akropolys/sdk';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { KIKU_KEY_REVEAL_SECONDS } from '../types';\r\n\r\nexport function useKikuKey(lastAction: ChatAction | null, retryLastMessage: () => Promise<void>) {\r\n const client = useAkropolysContext();\r\n const [keyInput, setKeyInput] = useState('');\r\n const [keyPhase, setKeyPhase] = useState<'idle' | 'prompt_key'>('idle');\r\n const [mintedKey, setMintedKey] = useState<string | null>(null);\r\n const [mintedPub, setMintedPub] = useState<string | null>(null);\r\n const [copied, setCopied] = useState<'secret' | 'pub' | null>(null);\r\n const [keyCountdown, setKeyCountdown] = useState(KIKU_KEY_REVEAL_SECONDS);\r\n const [minting, setMinting] = useState(false);\r\n\r\n const copyValue = useCallback(async (val: string, type: 'secret' | 'pub') => {\r\n try {\r\n await navigator.clipboard.writeText(val);\r\n setCopied(type);\r\n setTimeout(() => setCopied(null), 2000);\r\n } catch { }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!lastAction) return;\r\n if (lastAction.type === 'request_kiku_key') {\r\n setKeyPhase('prompt_key');\r\n setKeyInput('');\r\n }\r\n }, [lastAction]);\r\n\r\n useEffect(() => {\r\n if (!mintedKey) return;\r\n setKeyCountdown(KIKU_KEY_REVEAL_SECONDS);\r\n const t = setInterval(() => {\r\n setKeyCountdown(s => {\r\n if (s <= 1) {\r\n clearInterval(t);\r\n setMintedKey(null);\r\n setMintedPub(null);\r\n return 0;\r\n }\r\n return s - 1;\r\n });\r\n }, 1000);\r\n return () => clearInterval(t);\r\n }, [mintedKey]);\r\n\r\n const handleUseExistingKey = useCallback(async () => {\r\n const pub = keyInput.trim();\r\n if (!pub) return;\r\n client.setKikuPub(pub);\r\n setKeyInput('');\r\n setKeyPhase('idle');\r\n await retryLastMessage();\r\n }, [client, keyInput, retryLastMessage]);\r\n\r\n const handleCreateKey = useCallback(async () => {\r\n if (minting) return;\r\n setMinting(true);\r\n try {\r\n const { secret, publicId } = await client.mintKikuKey();\r\n setMintedKey(secret);\r\n setMintedPub(publicId);\r\n setKeyPhase('idle');\r\n await retryLastMessage();\r\n } catch { } finally {\r\n setMinting(false);\r\n }\r\n }, [client, minting, retryLastMessage]);\r\n\r\n return {\r\n keyInput,\r\n setKeyInput,\r\n keyPhase,\r\n setKeyPhase,\r\n mintedKey,\r\n setMintedKey,\r\n mintedPub,\r\n setMintedPub,\r\n copied,\r\n keyCountdown,\r\n minting,\r\n copyValue,\r\n handleUseExistingKey,\r\n handleCreateKey,\r\n };\r\n}\r\n","import { useCallback } from 'react';\r\nimport type { ChatSource, ChatAttachment, CaptureTarget } from '@akropolys/sdk';\r\nimport type { UIStringKey } from '../types';\r\n\r\nexport interface UseChatCommandsOptions {\r\n attachments: ChatAttachment[];\r\n setAttachments: React.Dispatch<React.SetStateAction<ChatAttachment[]>>;\r\n setInput: React.Dispatch<React.SetStateAction<string>>;\r\n send: (\r\n prompt: string,\r\n displayContent?: string,\r\n attachments?: ChatAttachment[],\r\n forcedIntent?: string,\r\n captureTargets?: CaptureTarget[]\r\n ) => Promise<any>;\r\n defaultCurrency: string;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n}\r\n\r\nexport function useChatCommands({\r\n attachments,\r\n setAttachments,\r\n setInput,\r\n send,\r\n defaultCurrency,\r\n t,\r\n}: UseChatCommandsOptions) {\r\n const handleKikuCapture = useCallback((product: ChatSource) => {\r\n const name = product.name || '';\r\n const display = `@kiku ${t('displayCapture', { name }).trim()}`;\r\n const q = name || 'capture current page';\r\n setInput('');\r\n const toSend = attachments;\r\n setAttachments([]);\r\n send(q, display, toSend.length > 0 ? toSend : undefined, 'capture');\r\n }, [attachments, send, setAttachments, setInput, t]);\r\n\r\n const handleKikuCaptureAll = useCallback((products: ChatSource[]) => {\r\n const targets: CaptureTarget[] = products\r\n .filter(p => p.id)\r\n .map(p => ({\r\n name: p.name || '',\r\n url: (p as any).url || '',\r\n image: p.image || '',\r\n price: p.price ? String(p.price) : '',\r\n currency: p.currency || defaultCurrency,\r\n }));\r\n const names = products.map(p => p.name).filter(Boolean).join(', ');\r\n const display = `@kiku ${t('displayCaptureAll', { count: String(products.length) })}`;\r\n setInput('');\r\n setAttachments([]);\r\n send(names || 'capture all', display, undefined, 'capture_all', targets);\r\n }, [defaultCurrency, send, setAttachments, setInput, t]);\r\n\r\n const handleKikuViewHistory = useCallback(() => {\r\n const display = `@kiku ${t('displayViewHistory')}`;\r\n setInput('');\r\n setAttachments([]);\r\n send('show my saved items', display, undefined, 'view_history');\r\n }, [send, setAttachments, setInput, t]);\r\n\r\n const handleKikuDelete = useCallback(() => {\r\n const display = `@kiku ${t('displayDelete')}`;\r\n setInput('');\r\n setAttachments([]);\r\n send('delete this', display, undefined, 'delete');\r\n }, [send, setAttachments, setInput, t]);\r\n\r\n return {\r\n handleKikuCapture,\r\n handleKikuCaptureAll,\r\n handleKikuViewHistory,\r\n handleKikuDelete,\r\n };\r\n}\r\n","import { useState, useCallback } from 'react';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { stopSpeech } from '../../../utils/tts';\r\nimport { useVoiceSession } from '../../../utils/voiceSession';\r\nimport { useLiveVoice, type LiveState } from '../../../utils/liveVoice';\r\nimport { LIVE_VOICES, VOICE_STORAGE_KEY, isSecureOrigin, type VoicePhase } from '../types';\r\n\r\nconst toVoicePhase = (s: LiveState): VoicePhase =>\r\n s === 'connecting' || s === 'ended' ? 'idle' : s;\r\n\r\nexport interface UseVoiceControllerOptions {\r\n voiceLang?: string;\r\n speechLang: string;\r\n shopperLanguage: string;\r\n ttsVoice?: string;\r\n handleSendUtterance: (text: string) => void;\r\n appendSpokenExchange: (heard: string, said: string) => void;\r\n}\r\n\r\nexport function useVoiceController({\r\n voiceLang,\r\n speechLang,\r\n shopperLanguage,\r\n ttsVoice = 'Puck',\r\n handleSendUtterance,\r\n appendSpokenExchange,\r\n}: UseVoiceControllerOptions) {\r\n const client = useAkropolysContext();\r\n const [voiceMode, setVoiceMode] = useState<'off' | 'dictate' | 'converse'>('off');\r\n const [dictateState, setDictateState] = useState<'idle' | 'listening' | 'thinking'>('idle');\r\n const [voiceError, setVoiceError] = useState<string>('');\r\n const [voiceMuted, setVoiceMuted] = useState(false);\r\n const [voiceSecondsLeft, setVoiceSecondsLeft] = useState<number | null>(null);\r\n const [voiceBlocked, setVoiceBlocked] = useState(false);\r\n\r\n const [liveVoiceName, setLiveVoiceName] = useState<string>(() => {\r\n try {\r\n const stored = localStorage.getItem(VOICE_STORAGE_KEY);\r\n if (stored && LIVE_VOICES.some(v => v.name === stored)) return stored;\r\n } catch { }\r\n return ttsVoice || 'Puck';\r\n });\r\n\r\n const chooseVoice = useCallback((name: string) => {\r\n setLiveVoiceName(name);\r\n try { localStorage.setItem(VOICE_STORAGE_KEY, name); } catch { }\r\n }, []);\r\n\r\n const voice = useVoiceSession({\r\n lang: voiceLang || speechLang,\r\n onUtterance: (text) => {\r\n setDictateState('thinking');\r\n handleSendUtterance(text);\r\n },\r\n onError: (code) => {\r\n setVoiceMode('off');\r\n setDictateState('idle');\r\n if (code === 'not-allowed') setVoiceError('micDenied');\r\n else if (code === 'language-not-supported') setVoiceError('micLangUnsupported');\r\n else if (code === 'audio-capture') setVoiceError('micMissing');\r\n else if (code === 'network') setVoiceError('micNetwork');\r\n else setVoiceError('micFailed');\r\n },\r\n onBargeIn: () => { stopSpeech(); },\r\n });\r\n\r\n const apiUrl = (client as any)?.api?.apiUrl || (client as any)?.apiUrl || '';\r\n const siteId = (client as any)?.api?.siteId || (client as any)?.siteId || '';\r\n const token = (client as any)?.api?.apiToken || (client as any)?.apiToken || '';\r\n const kikuId = client?.getShopperId?.() || client?.getKikuPub?.() || undefined;\r\n\r\n const live = useLiveVoice({\r\n apiUrl,\r\n siteId,\r\n token,\r\n kikuId,\r\n language: shopperLanguage,\r\n voice: liveVoiceName,\r\n muted: voiceMuted,\r\n onExchange: (exchange) => {\r\n appendSpokenExchange(exchange.heard, exchange.said);\r\n },\r\n onError: (err) => {\r\n if (err === 'shopper_reply_limit' || err === 'access_revoked' || err === 'account_required') {\r\n setVoiceBlocked(true);\r\n live.stop();\r\n setVoiceMode('off');\r\n return;\r\n }\r\n setVoiceMode('off');\r\n if (err === 'not-allowed') setVoiceError('micDenied');\r\n else if (err === 'audio-capture') setVoiceError('micMissing');\r\n else if (err === 'limit') setVoiceError('voiceLimitReached');\r\n else if (err === 'siteLimit') setVoiceError('voiceSiteLimit');\r\n else if (err === 'connection' || err === 'network') setVoiceError('micNetwork');\r\n else setVoiceError('voiceUnavailable');\r\n },\r\n onRefused: (code) => {\r\n if (code === 'shopper_reply_limit' || code === 'access_revoked' || code === 'account_required') {\r\n setVoiceBlocked(true);\r\n }\r\n setVoiceMode('off');\r\n setVoiceError('voiceUnavailable');\r\n },\r\n });\r\n\r\n const canConverse = typeof window !== 'undefined' && !!(window as any).WebSocket;\r\n\r\n const startVoice = useCallback(async (mode: 'dictate' | 'converse') => {\r\n if (!isSecureOrigin()) { setVoiceError('micInsecure'); return; }\r\n setVoiceError('');\r\n setVoiceMode(mode);\r\n if (mode === 'dictate') {\r\n setDictateState('listening');\r\n await voice.start();\r\n } else {\r\n live.start();\r\n }\r\n }, [live, voice]);\r\n\r\n const stopVoice = useCallback(() => {\r\n setVoiceMode('off');\r\n setDictateState('idle');\r\n voice.stop();\r\n live.stop();\r\n }, [live, voice]);\r\n\r\n const voicePhase: VoicePhase =\r\n voiceMode === 'converse' ? toVoicePhase(live.state)\r\n : voiceMode === 'dictate' ? (dictateState === 'listening' ? (voice.hearing ? 'speaking' : 'listening') : dictateState)\r\n : 'idle';\r\n\r\n const voiceConnecting = voiceMode === 'converse' && (live.phase === 'connecting' || live.state === 'connecting');\r\n\r\n return {\r\n voiceMode,\r\n voicePhase,\r\n voiceConnecting,\r\n voiceError,\r\n setVoiceError,\r\n voiceMuted,\r\n setVoiceMuted,\r\n voiceSecondsLeft,\r\n voiceBlocked,\r\n liveVoiceName,\r\n chooseVoice,\r\n canConverse,\r\n startVoice,\r\n stopVoice,\r\n voice,\r\n live,\r\n };\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nexport type LiveState = 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'ended';\r\n\r\nexport interface LiveSource {\r\n id?: string;\r\n url?: string;\r\n name: string;\r\n price?: string;\r\n currency?: string;\r\n image?: string;\r\n brand?: string;\r\n availability?: string;\r\n}\r\n\r\nexport interface LiveVoiceOptions {\r\n apiUrl: string;\r\n siteId: string;\r\n\r\n token: string;\r\n kikuId?: string;\r\n\r\n language?: string;\r\n voice?: string;\r\n\r\n onExchange?: (exchange: { heard: string; said: string }) => void;\r\n onRefused?: (code: string) => void;\r\n onError?: (code: string) => void;\r\n\r\n muted?: boolean;\r\n}\r\n\r\nconst INPUT_RATE = 16000;\r\n\r\nconst WORKLET_SRC = `\r\nclass KikuCapture extends AudioWorkletProcessor {\r\n constructor() {\r\n super();\r\n this._ratio = sampleRate / ${INPUT_RATE};\r\n this._chunk = ${Math.round(INPUT_RATE * 0.04)};\r\n this._acc = new Int16Array(this._chunk);\r\n this._n = 0;\r\n this._pos = 0;\r\n }\r\n process(inputs) {\r\n const ch = inputs[0] && inputs[0][0];\r\n if (!ch) return true;\r\n while (this._pos < ch.length) {\r\n const i = this._pos | 0;\r\n const frac = this._pos - i;\r\n const a = ch[i];\r\n const b = i + 1 < ch.length ? ch[i + 1] : a;\r\n const s = a + (b - a) * frac;\r\n const c = s < -1 ? -1 : s > 1 ? 1 : s;\r\n this._acc[this._n++] = c < 0 ? c * 0x8000 : c * 0x7fff;\r\n if (this._n === this._chunk) {\r\n this.port.postMessage(this._acc.buffer, [this._acc.buffer]);\r\n this._acc = new Int16Array(this._chunk);\r\n this._n = 0;\r\n }\r\n this._pos += this._ratio;\r\n }\r\n this._pos -= ch.length;\r\n return true;\r\n }\r\n}\r\nregisterProcessor('kiku-capture', KikuCapture);\r\n`;\r\n\r\nfunction toBase64(buf: ArrayBuffer): string {\r\n const bytes = new Uint8Array(buf);\r\n let s = '';\r\n for (let i = 0; i < bytes.length; i += 0x8000) {\r\n s += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + 0x8000)));\r\n }\r\n return btoa(s);\r\n}\r\n\r\nfunction fromBase64(b64: string): Int16Array {\r\n const bin = atob(b64);\r\n const bytes = new Uint8Array(bin.length);\r\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\r\n return new Int16Array(bytes.buffer, 0, bytes.length >> 1);\r\n}\r\n\r\nexport function useLiveVoice(opts: LiveVoiceOptions) {\r\n const [state, setState] = useState<LiveState>('idle');\r\n const [hearing, setHearing] = useState(false);\r\n const [sources, setSources] = useState<LiveSource[]>([]);\r\n const [secondsLeft, setSecondsLeft] = useState<number | null>(null);\r\n\r\n const wsRef = useRef<WebSocket | null>(null);\r\n const ctxRef = useRef<AudioContext | null>(null);\r\n const streamRef = useRef<MediaStream | null>(null);\r\n const nodeRef = useRef<AudioWorkletNode | null>(null);\r\n const analyserRef = useRef<AnalyserNode | null>(null);\r\n\r\n const playAtRef = useRef(0);\r\n const sourcesRef = useRef<Set<AudioBufferSourceNode>>(new Set());\r\n const outAnalyserRef = useRef<AnalyserNode | null>(null);\r\n const outRateRef = useRef(24000);\r\n\r\n const optsRef = useRef(opts);\r\n useEffect(() => { optsRef.current = opts; }, [opts]);\r\n\r\n const readyRef = useRef(false);\r\n const armCaptureRef = useRef<(() => void) | null>(null);\r\n\r\n const turnHeardRef = useRef('');\r\n const turnSaidRef = useRef('');\r\n\r\n const flushExchange = useCallback(() => {\r\n const heard = turnHeardRef.current.trim();\r\n const said = turnSaidRef.current.trim();\r\n turnHeardRef.current = '';\r\n turnSaidRef.current = '';\r\n if (!heard && !said) return;\r\n optsRef.current.onExchange?.({ heard, said });\r\n }, []);\r\n\r\n const chirp = useCallback(() => {\r\n // Silent - no synthetic beeps during live voice\r\n }, []);\r\n\r\n const beginCapture = useCallback(() => {\r\n if (!readyRef.current) return;\r\n const arm = armCaptureRef.current;\r\n if (!arm) return;\r\n armCaptureRef.current = null;\r\n arm();\r\n }, []);\r\n\r\n const micLevel = useCallback(() => {\r\n const a = analyserRef.current;\r\n if (!a) return 0;\r\n const d = new Uint8Array(a.fftSize);\r\n a.getByteTimeDomainData(d);\r\n let sum = 0;\r\n for (let i = 0; i < d.length; i++) { const v = (d[i] - 128) / 128; sum += v * v; }\r\n return Math.min(1, Math.sqrt(sum / d.length) * 4);\r\n }, []);\r\n\r\n const outbound = state === 'speaking' || state === 'thinking';\r\n\r\n const micSpectrum = useCallback((out: Uint8Array) => {\r\n const a = outbound ? outAnalyserRef.current : analyserRef.current;\r\n if (!a || out.length !== a.frequencyBinCount) return false;\r\n a.getByteFrequencyData(out as Uint8Array<ArrayBuffer>);\r\n return true;\r\n }, [outbound]);\r\n\r\n const spectrumBins = useCallback(\r\n () => (outbound ? outAnalyserRef.current : analyserRef.current)?.frequencyBinCount ?? 0,\r\n [outbound]\r\n );\r\n\r\n \r\n const flushPlayback = useCallback(() => {\r\n for (const src of sourcesRef.current) {\r\n try { src.onended = null; src.stop(); } catch { }\r\n }\r\n sourcesRef.current.clear();\r\n playAtRef.current = 0;\r\n }, []);\r\n\r\n const enqueue = useCallback((pcm: Int16Array) => {\r\n const ctx = ctxRef.current;\r\n const out = outAnalyserRef.current;\r\n if (!ctx || !out || pcm.length === 0) return;\r\n\r\n const rate = outRateRef.current;\r\n const buf = ctx.createBuffer(1, pcm.length, rate);\r\n const ch = buf.getChannelData(0);\r\n const len = pcm.length;\r\n const fade = Math.min(32, Math.floor(len / 4));\r\n for (let i = 0; i < len; i++) {\r\n let sample = pcm[i] / 0x8000;\r\n // Smooth micro-fade at buffer edges to prevent PCM boundary scratches/clicks\r\n if (i < fade) {\r\n sample *= (i / fade);\r\n } else if (i >= len - fade) {\r\n sample *= ((len - 1 - i) / fade);\r\n }\r\n ch[i] = sample;\r\n }\r\n\r\n const src = ctx.createBufferSource();\r\n src.buffer = buf;\r\n src.connect(out);\r\n\r\n const now = ctx.currentTime;\r\n const at = Math.max(now + 0.02, playAtRef.current || now + 0.02);\r\n src.start(at);\r\n playAtRef.current = at + buf.duration;\r\n\r\n sourcesRef.current.add(src);\r\n src.onended = () => {\r\n sourcesRef.current.delete(src);\r\n if (sourcesRef.current.size === 0) setState(s => (s === 'speaking' ? 'listening' : s));\r\n };\r\n setState(s => (s === 'speaking' || s === 'idle' || s === 'ended' ? s : 'speaking'));\r\n }, []);\r\n\r\n const stopHold = useCallback(() => {\r\n // Silent - no drone\r\n }, []);\r\n\r\n const startHold = useCallback(() => {\r\n // Silent - clean natural voice only\r\n }, []);\r\n\r\n const teardown = useCallback((finalState: LiveState) => {\r\n flushExchange();\r\n wsRef.current = null;\r\n readyRef.current = false;\r\n armCaptureRef.current = null;\r\n stopHold();\r\n flushPlayback();\r\n nodeRef.current?.disconnect();\r\n nodeRef.current = null;\r\n streamRef.current?.getTracks().forEach(t => t.stop());\r\n streamRef.current = null;\r\n analyserRef.current = null;\r\n outAnalyserRef.current = null;\r\n ctxRef.current?.close().catch(() => { });\r\n ctxRef.current = null;\r\n setState(finalState);\r\n setHearing(false);\r\n setSources([]);\r\n }, [flushExchange, flushPlayback, stopHold]);\r\n\r\n const stop = useCallback(() => {\r\n try { wsRef.current?.send(JSON.stringify({ type: 'close' })); } catch { }\r\n try { wsRef.current?.close(); } catch { }\r\n teardown('idle');\r\n }, [teardown]);\r\n\r\n const start = useCallback(async () => {\r\n if (wsRef.current) return;\r\n setState('connecting');\r\n const o = optsRef.current;\r\n\r\n const base = o.apiUrl.replace(/\\/+$/, '');\r\n const url = new URL(base + '/voice/live', window.location.href);\r\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\r\n url.searchParams.set('siteId', o.siteId);\r\n if (o.kikuId) url.searchParams.set('kikuId', o.kikuId);\r\n if (o.language) url.searchParams.set('language', o.language);\r\n if (o.voice) url.searchParams.set('voice', o.voice);\r\n\r\n const ws = new WebSocket(url.toString(), ['akropolys.token.' + o.token]);\r\n wsRef.current = ws;\r\n\r\n ws.onmessage = ev => {\r\n let f: any;\r\n try { f = JSON.parse(ev.data); } catch { return; }\r\n switch (f.type) {\r\n case 'ready':\r\n if (f.sampleRate) outRateRef.current = f.sampleRate;\r\n if (typeof f.secondsLeft === 'number') setSecondsLeft(f.secondsLeft);\r\n readyRef.current = true;\r\n setState('listening');\r\n beginCapture();\r\n break;\r\n case 'audio':\r\n stopHold();\r\n if (f.audio) enqueue(fromBase64(f.audio));\r\n break;\r\n case 'hearing':\r\n setHearing(true);\r\n break;\r\n case 'thinking':\r\n setHearing(false);\r\n setState('thinking');\r\n startHold();\r\n break;\r\n case 'heard':\r\n turnHeardRef.current += f.text;\r\n break;\r\n case 'said':\r\n turnSaidRef.current += f.text;\r\n break;\r\n case 'interrupted':\r\n stopHold();\r\n flushPlayback();\r\n setHearing(false);\r\n setState('listening');\r\n break;\r\n case 'turn_complete':\r\n stopHold();\r\n setHearing(false);\r\n flushExchange();\r\n break;\r\n case 'sources':\r\n if (Array.isArray(f.sources) && f.sources.length) setSources(f.sources);\r\n break;\r\n case 'seconds':\r\n if (typeof f.secondsLeft === 'number') setSecondsLeft(f.secondsLeft);\r\n break;\r\n case 'refused':\r\n optsRef.current.onRefused?.(f.code || 'guest');\r\n stop();\r\n break;\r\n case 'error':\r\n optsRef.current.onError?.(f.code || 'unavailable');\r\n stop();\r\n break;\r\n }\r\n };\r\n\r\n ws.onclose = ev => {\r\n if (wsRef.current !== ws) return;\r\n if (ev.code === 4402) {\r\n abandoned = true;\r\n optsRef.current.onError?.(ev.reason === 'site' ? 'siteLimit' : 'limit');\r\n }\r\n teardown('ended');\r\n };\r\n let abandoned = false;\r\n ws.onerror = () => { if (!abandoned) optsRef.current.onError?.('connection'); };\r\n\r\n let stream: MediaStream;\r\n try {\r\n if (!navigator.mediaDevices?.getUserMedia) throw { name: 'NotAllowedError' };\r\n stream = await navigator.mediaDevices.getUserMedia({\r\n audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true },\r\n });\r\n } catch (e: any) {\r\n abandoned = true;\r\n try { ws.close(); } catch { }\r\n wsRef.current = null;\r\n setState('idle');\r\n o.onError?.(e?.name === 'NotAllowedError' ? 'not-allowed' : 'audio-capture');\r\n return;\r\n }\r\n if (wsRef.current !== ws) {\r\n stream.getTracks().forEach(t => t.stop());\r\n return;\r\n }\r\n streamRef.current = stream;\r\n\r\n const AC: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\r\n const ctx = new AC();\r\n ctxRef.current = ctx;\r\n\r\n const inAnalyser = ctx.createAnalyser();\r\n inAnalyser.fftSize = 1024;\r\n inAnalyser.smoothingTimeConstant = 0.25;\r\n analyserRef.current = inAnalyser;\r\n\r\n const outAnalyser = ctx.createAnalyser();\r\n outAnalyser.fftSize = 1024;\r\n outAnalyser.smoothingTimeConstant = 0.25;\r\n outAnalyser.connect(ctx.destination);\r\n outAnalyserRef.current = outAnalyser;\r\n\r\n try {\r\n const blobUrl = URL.createObjectURL(new Blob([WORKLET_SRC], { type: 'application/javascript' }));\r\n await ctx.audioWorklet.addModule(blobUrl);\r\n URL.revokeObjectURL(blobUrl);\r\n if (wsRef.current !== ws) {\r\n stream.getTracks().forEach(t => t.stop());\r\n ctx.close().catch(() => {});\r\n return;\r\n }\r\n\r\n const node = new AudioWorkletNode(ctx, 'kiku-capture');\r\n nodeRef.current = node;\r\n node.port.onmessage = e => {\r\n if (ws.readyState !== WebSocket.OPEN) return;\r\n ws.send(JSON.stringify({ type: 'audio', audio: toBase64(e.data) }));\r\n };\r\n const srcNode = ctx.createMediaStreamSource(stream);\r\n armCaptureRef.current = () => {\r\n srcNode.connect(inAnalyser);\r\n srcNode.connect(node);\r\n };\r\n beginCapture();\r\n } catch {\r\n optsRef.current.onError?.('audio-worklet');\r\n stop();\r\n }\r\n }, [beginCapture, enqueue, flushExchange, flushPlayback, startHold, stopHold, stop, teardown]);\r\n\r\n useEffect(() => () => { stop(); }, [stop]);\r\n\r\n useEffect(() => {\r\n const stream = streamRef.current;\r\n if (!stream) return;\r\n for (const track of stream.getAudioTracks()) track.enabled = !opts.muted;\r\n }, [opts.muted, state]);\r\n\r\n return { state, phase: state, hearing, sources, secondsLeft, micLevel, micSpectrum, spectrumBins, start, stop };\r\n}\r\n","import React from 'react';\r\nimport { useT } from './types';\r\nimport { ChevronLeftIcon } from './icons';\r\nimport { THEMES, type ThemeId } from './themes';\r\nimport { KikuAvatar, type KikuState } from '../KikuAvatar';\r\nimport { cn } from '../../utils/cn';\r\n\r\nexport interface ChatTopbarProps {\r\n title: string;\r\n hasMessages: boolean;\r\n avatarState?: KikuState;\r\n unread?: boolean;\r\n awayFromBottom?: boolean;\r\n themeMenuOpen?: boolean;\r\n themeMenuClosing?: boolean;\r\n isNarrow?: boolean;\r\n currentTheme?: ThemeId;\r\n onJumpToLatest?: () => void;\r\n onReset: () => void;\r\n onClose: () => void;\r\n onToggleThemeMenu?: () => void;\r\n onSelectTheme?: (theme: ThemeId) => void;\r\n}\r\n\r\nexport function ChatTopbar({\r\n title,\r\n hasMessages,\r\n avatarState = 'idle',\r\n unread = false,\r\n awayFromBottom = false,\r\n themeMenuOpen = false,\r\n themeMenuClosing = false,\r\n isNarrow = false,\r\n currentTheme = 'dark',\r\n onJumpToLatest,\r\n onReset,\r\n onClose,\r\n onToggleThemeMenu,\r\n onSelectTheme,\r\n}: ChatTopbarProps) {\r\n const tr = useT();\r\n const [isImpacting, setIsImpacting] = React.useState(false);\r\n const [impactColor, setImpactColor] = React.useState<string>('#134e3d');\r\n const [impactGlow, setImpactGlow] = React.useState<string>('rgba(19, 78, 61, 0.45)');\r\n const triggerRef = React.useRef<(() => void) | undefined>(undefined);\r\n const longPressTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isLongPressRef = React.useRef(false);\r\n const touchStartTimeRef = React.useRef(0);\r\n\r\n const startPress = React.useCallback(() => {\r\n isLongPressRef.current = false;\r\n touchStartTimeRef.current = Date.now();\r\n longPressTimerRef.current = setTimeout(() => {\r\n isLongPressRef.current = true;\r\n if (typeof navigator !== 'undefined' && navigator.vibrate) {\r\n try { navigator.vibrate(25); } catch {}\r\n }\r\n onToggleThemeMenu?.();\r\n }, 350);\r\n }, [onToggleThemeMenu]);\r\n\r\n const endPress = React.useCallback(() => {\r\n if (longPressTimerRef.current) {\r\n clearTimeout(longPressTimerRef.current);\r\n longPressTimerRef.current = null;\r\n }\r\n }, []);\r\n\r\n const cancelPress = React.useCallback(() => {\r\n if (longPressTimerRef.current) {\r\n clearTimeout(longPressTimerRef.current);\r\n longPressTimerRef.current = null;\r\n }\r\n }, []);\r\n\r\n const handleClick = React.useCallback((e: React.MouseEvent) => {\r\n if (isLongPressRef.current) {\r\n isLongPressRef.current = false;\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (awayFromBottom) {\r\n onJumpToLatest?.();\r\n } else {\r\n triggerRef.current?.();\r\n }\r\n }, [awayFromBottom, onJumpToLatest]);\r\n\r\n const handleImpact = React.useCallback((splat: number, color: string, glow: string) => {\r\n if (splat > 0.04) {\r\n setIsImpacting(true);\r\n setImpactColor(color);\r\n setImpactGlow(glow);\r\n } else {\r\n setIsImpacting(false);\r\n }\r\n }, []);\r\n\r\n return (\r\n <div className=\"hsk-cb-topbar\">\r\n <div className=\"hsk-cb-topbar-left\">\r\n <button className=\"hsk-cb-back\" onClick={onClose} aria-label=\"Close\">\r\n <span className=\"hsk-cb-back-icon\"><ChevronLeftIcon /></span>\r\n </button>\r\n </div>\r\n <div\r\n className={cn(\"hsk-cb-topbar-mark\", isNarrow && themeMenuOpen && \"is-oozing\")}\r\n data-impacting={isImpacting ? 'true' : 'false'}\r\n style={{\r\n '--hsk-contact-color': impactColor,\r\n '--hsk-contact-glow': impactGlow,\r\n } as React.CSSProperties}\r\n data-unread={unread ? 'true' : 'false'}\r\n onTouchStart={startPress}\r\n onTouchEnd={endPress}\r\n onTouchMove={cancelPress}\r\n onTouchCancel={cancelPress}\r\n onClick={handleClick}\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-label={awayFromBottom ? tr('jumpToLatest') : 'kiku (long press for themes)'}\r\n >\r\n <KikuAvatar\r\n state={avatarState}\r\n size={34}\r\n theme={currentTheme}\r\n alert={unread}\r\n onImpact={handleImpact}\r\n triggerRef={triggerRef}\r\n />\r\n <span className=\"hsk-cb-topbar-name\">{title}</span>\r\n </div>\r\n\r\n <div className=\"hsk-cb-topbar-actions\">\r\n {hasMessages && (\r\n <button className=\"hsk-cb-topbar-btn\" onClick={onReset}>\r\n {tr('clearChat')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {isNarrow && themeMenuOpen && (\r\n <div\r\n className={cn(\"hsk-cb-topbar-ooze-menu\", themeMenuClosing && \"is-closing\")}\r\n role=\"dialog\"\r\n aria-label=\"Theme selector\"\r\n style={{\r\n position: 'absolute',\r\n top: '100%',\r\n marginTop: '8px',\r\n left: '50%',\r\n transform: 'translateX(-50%)',\r\n zIndex: 1000,\r\n }}\r\n onPointerDown={(e) => e.stopPropagation()}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n >\r\n <div className=\"hsk-cb-theme-2x2-grid\" style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 6 }}>\r\n {THEMES.map(({ id, label, Icon }) => (\r\n <button\r\n key={id}\r\n type=\"button\"\r\n className={cn(\"hsk-cb-theme-grid-item\", currentTheme === id && \"is-active\")}\r\n onClick={(e) => { e.stopPropagation(); onSelectTheme?.(id); }}\r\n >\r\n <Icon />\r\n <span>{label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import React, { useEffect, useRef } from 'react';\r\n\r\nexport type KikuState = 'idle' | 'thinking' | 'visualizing' | 'speaking' | 'failed' | 'curious' | 'welcoming' | 'guiding' | 'happy' | 'focused';\r\n\r\ntype Shape = { bw: number; bh: number; tr: number; br: number; bow: number };\r\ntype Mood = { lid: number; warm: number; breath: number; wob: number };\r\n\r\nconst BODY: Record<string, Shape> = {\r\n idle: { bw: 50, bh: 60, tr: 1, br: 0.42, bow: 3 },\r\n thinking: { bw: 46, bh: 46, tr: 1, br: 1, bow: 2 },\r\n visualizing: { bw: 64, bh: 42, tr: 0.42,br: 0.42, bow: 2 },\r\n speaking: { bw: 44, bh: 54, tr: 0.9, br: 0.9, bow: 3 },\r\n failed: { bw: 53, bh: 45, tr: 0.95,br: 0.55, bow: 4 },\r\n curious: { bw: 48, bh: 52, tr: 0.9, br: 0.7, bow: 3 },\r\n welcoming: { bw: 50, bh: 58, tr: 1, br: 0.5, bow: 2 },\r\n guiding: { bw: 46, bh: 50, tr: 0.8, br: 0.8, bow: 2 },\r\n happy: { bw: 52, bh: 56, tr: 1, br: 0.4, bow: 4 },\r\n focused: { bw: 48, bh: 52, tr: 0.9, br: 0.7, bow: 2 },\r\n};\r\n\r\nconst MOOD: Record<string, Mood> = {\r\n idle: { lid: 1, warm: 0, breath: 2100, wob: 1 },\r\n thinking: { lid: 1, warm: 0.2, breath: 1700, wob: 1.6 },\r\n visualizing: { lid: 1, warm: 0.9, breath: 1200, wob: 2.2 },\r\n speaking: { lid: 1, warm: 0.35, breath: 900, wob: 1.8 },\r\n failed: { lid: 0.28, warm: 0, breath: 3000, wob: 0.6 },\r\n curious: { lid: 1, warm: 0.15, breath: 1800, wob: 1.4 },\r\n welcoming: { lid: 1, warm: 0.25, breath: 1600, wob: 1.2 },\r\n guiding: { lid: 1, warm: 0.2, breath: 1500, wob: 1.3 },\r\n happy: { lid: 1, warm: 0.4, breath: 1200, wob: 1.5 },\r\n focused: { lid: 1, warm: 0.2, breath: 1500, wob: 1.2 },\r\n};\r\n\r\nconst HOP: [number, number, number][] = [\r\n [0, 0, 0],\r\n [0.09, 0.54, 0], // crouch — the wind-up sells the height that follows\r\n [0.19, -0.36, 32], // launch, stretched thin\r\n [0.31, -0.22, 58],\r\n [0.42, -0.12, 68], // apex, and a beat of hang time\r\n [0.54, 0.04, 28],\r\n [0.63, 0.96, 0], // impact: flat as it gets\r\n [0.71, 0.18, 0],\r\n [0.79, -0.16, 20], // rebound — smaller, faster, the Duolingo tell\r\n [0.88, 0.34, 0],\r\n [0.95, -0.05, 4],\r\n [1, 0, 0],\r\n];\r\n\r\nfunction hopAt(f: number): [number, number] {\r\n let i = 1;\r\n while (i < HOP.length - 1 && HOP[i][0] < f) i++;\r\n const [t0, s0, l0] = HOP[i - 1];\r\n const [t1, s1, l1] = HOP[i];\r\n const u = t1 === t0 ? 0 : (f - t0) / (t1 - t0);\r\n const e = u * u * (3 - 2 * u);\r\n return [s0 + (s1 - s0) * e, l0 + (l1 - l0) * e];\r\n}\r\n\r\nconst SLOTS = 6;\r\nconst KEYS = ['bw', 'bh', 'tr', 'br', 'bow', 'lid', 'warm', 'wob', 'gx', 'gy'] as const;\r\ntype Key = typeof KEYS[number];\r\n\r\nconst clamp = (v: number, a: number, b: number) => Math.max(a, Math.min(b, v));\r\n\r\nfunction side(x: number, y0: number, y1: number, bow: number) {\r\n const f = (n: number) => n.toFixed(2);\r\n const ym = (y0 + y1) / 2;\r\n const xb = x + bow;\r\n const a = (ym - y0) * 0.55;\r\n const b = (y1 - ym) * 0.55;\r\n return (\r\n `C${f(x)} ${f(y0 + a)} ${f(xb)} ${f(ym - a)} ${f(xb)} ${f(ym)}` +\r\n `C${f(xb)} ${f(ym + b)} ${f(x)} ${f(y1 - b)} ${f(x)} ${f(y1)}`\r\n );\r\n}\r\n\r\nfunction bodyPath(bw: number, bh: number, tr: number, br: number, bow: number) {\r\n const rt = clamp(bw * tr, 8, bh * 0.96);\r\n const rb = clamp(bw * br, 8, bh * 0.96);\r\n const p = (x: number, y: number) => `${x.toFixed(2)} ${y.toFixed(2)}`;\r\n const k = 0.46; // continuous corners, never a quarter circle\r\n const ft = clamp((bw - rt) / bw, 0, 1);\r\n const fb = clamp((bw - rb) / bw, 0, 1);\r\n return (\r\n `M${p(-bw, -bh + rt)}` +\r\n `C${p(-bw, -bh + rt * k)} ${p(-bw + rt * k, -bh)} ${p(-bw + rt, -bh)}` +\r\n `C${p(-bw * 0.3 * ft, -bh - 2 * ft)} ${p(bw * 0.3 * ft, -bh - 2 * ft)} ${p(bw - rt, -bh)}` +\r\n `C${p(bw - rt * k, -bh)} ${p(bw, -bh + rt * k)} ${p(bw, -bh + rt)}` +\r\n side(bw, -bh + rt, bh - rb, bow) +\r\n `C${p(bw, bh - rb * k)} ${p(bw - rb * k, bh)} ${p(bw - rb, bh)}` +\r\n `C${p(bw * 0.3 * fb, bh + 2 * fb)} ${p(-bw * 0.3 * fb, bh + 2 * fb)} ${p(-bw + rb, bh)}` +\r\n `C${p(-bw + rb * k, bh)} ${p(-bw, bh - rb * k)} ${p(-bw, bh - rb)}` +\r\n side(-bw, bh - rb, -bh + rt, -bow) +\r\n 'Z'\r\n );\r\n}\r\n\r\nconst NEUTRALS = [\r\n { name: 'Graphite', color: '#4B5058', light: '#A8AEB6', glow: 'rgba(75, 80, 88, 0.26)' },\r\n { name: 'Mist', color: '#78868F', light: '#BFC9CF', glow: 'rgba(120, 134, 143, 0.26)' },\r\n { name: 'Sandstone', color: '#8A7E71', light: '#CBC1B5', glow: 'rgba(138, 126, 113, 0.26)' },\r\n { name: 'Pewter', color: '#5F6670', light: '#B3BAC3', glow: 'rgba(95, 102, 112, 0.26)' },\r\n];\r\n\r\nconst POPS = [\r\n { name: 'Aegean', color: '#2E6FB7', light: '#9CC1E6', glow: 'rgba(46, 111, 183, 0.30)' },\r\n { name: 'Fern', color: '#3C8C60', light: '#A2CFB4', glow: 'rgba(60, 140, 96, 0.30)' },\r\n { name: 'Marigold', color: '#C48A22', light: '#EBD095', glow: 'rgba(196, 138, 34, 0.30)' },\r\n { name: 'Coral', color: '#C15A4E', light: '#E9AEA3', glow: 'rgba(193, 90, 78, 0.30)' },\r\n { name: 'Iris', color: '#5F5CC4', light: '#B6B4E8', glow: 'rgba(95, 92, 196, 0.30)' },\r\n];\r\n\r\nexport const RARE_SHADES = [...NEUTRALS, ...POPS];\r\n\r\nfunction pickShade(current: typeof RARE_SHADES[number]) {\r\n const wasPop = POPS.includes(current as any);\r\n const pool = !wasPop && Math.random() < 0.26 ? POPS : NEUTRALS;\r\n const options = pool.filter(s => s !== current);\r\n return options[Math.floor(Math.random() * options.length)];\r\n}\r\n\r\ntype RGB = [number, number, number];\r\n\r\nfunction toRGB(hex: string): RGB {\r\n const n = parseInt(hex.slice(1), 16);\r\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\r\n}\r\n\r\nfunction rgbCSS(c: RGB) {\r\n return `rgb(${Math.round(c[0])}, ${Math.round(c[1])}, ${Math.round(c[2])})`;\r\n}\r\n\r\nfunction mix(base: RGB, tint: RGB, amount: number): RGB {\r\n return [\r\n base[0] + (tint[0] - base[0]) * amount,\r\n base[1] + (tint[1] - base[1]) * amount,\r\n base[2] + (tint[2] - base[2]) * amount,\r\n ];\r\n}\r\n\r\nconst MARBLE_PAPER: RGB[] = [\r\n [255, 253, 248],\r\n [247, 240, 231],\r\n [231, 218, 202],\r\n [198, 178, 156],\r\n];\r\nconst MARBLE_TINT = [0.05, 0.15, 0.42, 0.74];\r\nconst MARBLE_FLOOD = [0.52, 0.72, 0.9, 1];\r\n\r\nconst ALERT_SHADE = { color: '#E2581D', light: '#FFBE96', glow: 'rgba(226, 88, 29, 0.34)' };\r\n\r\nexport interface KikuAvatarProps {\r\n state?: KikuState;\r\n size?: number;\r\n alert?: boolean;\r\n theme?: string;\r\n feminine?: boolean;\r\n accessories?: {\r\n flower?: boolean;\r\n eyelashes?: boolean;\r\n blush?: boolean;\r\n };\r\n onImpact?: (splat: number, color: string, glow: string) => void;\r\n triggerRef?: React.MutableRefObject<(() => void) | undefined>;\r\n}\r\n\r\nexport function KikuAvatar({\r\n state = 'idle',\r\n size = 40,\r\n alert = false,\r\n theme,\r\n feminine,\r\n accessories,\r\n onImpact,\r\n triggerRef,\r\n}: KikuAvatarProps) {\r\n const stateRef = useRef<KikuState>(state);\r\n stateRef.current = state;\r\n const alertRef = useRef(alert);\r\n alertRef.current = alert;\r\n\r\n const isFeminine = theme === 'blush' || feminine === true || Boolean(accessories?.flower || accessories?.eyelashes || accessories?.blush);\r\n const showFlower = accessories?.flower ?? isFeminine;\r\n const showLashes = accessories?.eyelashes ?? isFeminine;\r\n const showBlush = accessories?.blush ?? isFeminine;\r\n\r\n const bodyRef = useRef<SVGPathElement>(null);\r\n const maskRef = useRef<SVGPathElement>(null);\r\n const figRef = useRef<SVGGElement>(null);\r\n const decorRef = useRef<SVGGElement>(null);\r\n const flowerGRef = useRef<SVGGElement>(null);\r\n const cheeksGRef = useRef<SVGGElement>(null);\r\n const lashesGRef = useRef<SVGGElement>(null);\r\n const lashLRef = useRef<SVGPathElement>(null);\r\n const lashRRef = useRef<SVGPathElement>(null);\r\n const warmRef = useRef<SVGRectElement>(null);\r\n const contactRef = useRef<SVGRectElement>(null);\r\n const stop1Ref = useRef<SVGStopElement>(null);\r\n const stop2Ref = useRef<SVGStopElement>(null);\r\n const stop3Ref = useRef<SVGStopElement>(null);\r\n const marbleRefs = useRef<(SVGStopElement | null)[]>([]);\r\n const slotRefs = useRef<(SVGRectElement | null)[]>([]);\r\n const slotGRef = useRef<SVGGElement>(null);\r\n const uid = useRef(`kiku-${Math.random().toString(36).slice(2, 8)}`).current;\r\n const onImpactRef = useRef(onImpact);\r\n onImpactRef.current = onImpact;\r\n\r\n useEffect(() => {\r\n const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n const at: Record<string, number> = {};\r\n const vel: Record<string, number> = {};\r\n KEYS.forEach(k => {\r\n at[k] = (BODY.idle as any)[k] ?? (MOOD.idle as any)[k] ?? 0;\r\n vel[k] = 0;\r\n });\r\n const slotAt = Array.from({ length: SLOTS }, () => ({ x: 0, y: 0, w: 0, h: 0, rx: 0, a: 0 }));\r\n const slotVel = Array.from({ length: SLOTS }, () => ({ x: 0, y: 0, w: 0, h: 0, rx: 0, a: 0 }));\r\n\r\n let blinkAt = 1800, blinkPhase = -1, wander = 0, wanderAt = 2600, raf = 0, gooOn = false;\r\n let hopDue = 9000 + Math.random() * 8000, hopPhase = -1;\r\n\r\n let lean = 0, leanVel = 0, leanWant = 0, leanAt = 4200;\r\n let peek = 0, peekVel = 0, peekWant = 0, peekAt = 12000;\r\n\r\n let shade = NEUTRALS[0];\r\n let deep: RGB = toRGB(shade.color);\r\n let pale: RGB = toRGB(shade.light);\r\n let deepWant: RGB = [...deep] as RGB;\r\n let paleWant: RGB = [...pale] as RGB;\r\n\r\n const DOUBLE_MS = 2600;\r\n let lastHopAt = -Infinity;\r\n let pendingEncore = false;\r\n let singlesSince = 0;\r\n let queuedHop = false;\r\n let now = 0;\r\n let puff = 0, puffVel = 0, wasAlert = false, nagDue = 0;\r\n\r\n const startHop = (t: number) => {\r\n if (t - lastHopAt < DOUBLE_MS) {\r\n shade = pickShade(shade);\r\n deepWant = toRGB(shade.color);\r\n paleWant = toRGB(shade.light);\r\n lastHopAt = -Infinity; // a third hop starts a fresh pair\r\n } else {\r\n lastHopAt = t;\r\n }\r\n };\r\n\r\n const layout = (t: number, lid: number, gx: number, gy: number) => {\r\n const phase = stateRef.current;\r\n const out = Array.from({ length: SLOTS }, () => ({ x: 0, y: 0, w: 0, h: 0, rx: 0, a: 0 }));\r\n const eye = (i: number, cx: number, dy = 0) => {\r\n const h = Math.max(4, 54 * Math.max(0.06, lid));\r\n out[i] = { x: cx + gx, y: -4 + gy + dy, w: 21, h, rx: 10.5, a: 1 };\r\n };\r\n if (phase === 'thinking') {\r\n const n = 4;\r\n const cycle = (t % 2800) / 2800;\r\n const fuse = Math.pow(Math.sin(cycle * Math.PI * 2) * 0.5 + 0.5, 3); // 1 = gathered\r\n for (let i = 0; i < n; i++) {\r\n const a = t / 700 + (i / n) * Math.PI * 2;\r\n const R = (26 - (i % 2) * 5) * (1 - 0.94 * fuse); // uneven orbits, so it never reads as a spinner\r\n const s = 16 + fuse * 6 + Math.sin(t / 420 + i) * 1.4; // stay above the goo threshold when apart\r\n out[i] = { x: Math.cos(a) * R, y: Math.sin(a) * R * 0.86 + 2, w: s, h: s, rx: s / 2, a: 1 };\r\n }\r\n } else if (phase === 'visualizing') {\r\n out[0] = { x: 0, y: -2, w: 78, h: 26, rx: 13, a: 1 };\r\n } else if (phase === 'speaking') {\r\n const n = 5;\r\n for (let i = 0; i < n; i++) {\r\n const h = 12 + Math.abs(Math.sin(t / 150 + i * 0.9)) * 26;\r\n out[i] = { x: (i - (n - 1) / 2) * 15, y: -2, w: 9, h, rx: 4.5, a: 1 };\r\n }\r\n } else if (phase === 'failed') {\r\n eye(0, -22, 8); eye(1, 22, 8);\r\n } else {\r\n eye(0, -22); eye(1, 22);\r\n }\r\n return out;\r\n };\r\n\r\n if (triggerRef) {\r\n triggerRef.current = () => {\r\n if (hopPhase >= 0) {\r\n queuedHop = true;\r\n shade = pickShade(shade);\r\n deepWant = toRGB(shade.color);\r\n paleWant = toRGB(shade.light);\r\n lastHopAt = -Infinity;\r\n return;\r\n }\r\n hopPhase = 0;\r\n startHop(now);\r\n hopDue = now + 4000;\r\n };\r\n }\r\n\r\n const frame = (t: number) => {\r\n now = t;\r\n const phase = stateRef.current;\r\n const shape = BODY[phase] ?? BODY.idle, mood = MOOD[phase] ?? MOOD.idle;\r\n const facing = phase === 'idle' || phase === 'failed';\r\n\r\n if (facing && !reduced) {\r\n if (t > wanderAt) { wander = (Math.random() - 0.5) * 2; wanderAt = t + 1800 + Math.random() * 3600; }\r\n (at as any).wantGx = wander * 5;\r\n }\r\n const puffWant = alertRef.current ? 1 : 0;\r\n puffVel = (puffVel + (puffWant - puff) * 0.1) * 0.88;\r\n puff += puffVel;\r\n const breath = alertRef.current && !reduced ? Math.sin(t / 480) * 0.055 * puff : 0;\r\n\r\n const want: Record<string, number> = {\r\n bw: shape.bw * (1 + puff * 0.34 + breath), bh: shape.bh * (1 + puff * 0.2 + breath),\r\n tr: shape.tr, br: shape.br, bow: shape.bow,\r\n warm: mood.warm, wob: mood.wob, lid: mood.lid,\r\n gx: facing && !reduced ? wander * 5 : 0,\r\n gy: facing && !reduced ? Math.sin(t / 2600) * 2 : 0,\r\n };\r\n\r\n if (!reduced && facing) {\r\n if (blinkPhase < 0 && t > blinkAt) blinkPhase = 0;\r\n if (blinkPhase >= 0) {\r\n blinkPhase += 1 / 7;\r\n want.lid = mood.lid * Math.abs(blinkPhase - 0.5) * 2;\r\n if (blinkPhase >= 1) {\r\n blinkPhase = -1;\r\n want.lid = mood.lid;\r\n blinkAt = t + (Math.random() < 0.22 ? 340 : 2600 + Math.random() * 4200);\r\n }\r\n }\r\n }\r\n\r\n KEYS.forEach(k => {\r\n const key = k as Key;\r\n if (reduced) { at[key] = want[key]; return; }\r\n const stiff = key === 'lid' ? 0.42 : 0.11;\r\n const damp = key === 'lid' ? 0.55 : 0.78;\r\n vel[key] = (vel[key] + (want[key] - at[key]) * stiff) * damp;\r\n at[key] += vel[key];\r\n });\r\n\r\n let squash = 0, lift = 0;\r\n if (!reduced && alertRef.current && hopPhase < 0 && t > nagDue) {\r\n hopPhase = 0;\r\n nagDue = t + 2100;\r\n hopDue = t + 4000;\r\n }\r\n if (!reduced && phase === 'idle') {\r\n if (hopPhase < 0 && t > hopDue) {\r\n hopPhase = 0;\r\n if (pendingEncore) {\r\n pendingEncore = false;\r\n singlesSince = 0;\r\n shade = pickShade(shade);\r\n deepWant = toRGB(shade.color);\r\n paleWant = toRGB(shade.light);\r\n lastHopAt = -Infinity;\r\n } else {\r\n singlesSince++;\r\n startHop(t);\r\n }\r\n }\r\n } else if (hopPhase < 0) {\r\n hopDue = t + 3000 + Math.random() * 3000;\r\n }\r\n\r\n if (hopPhase >= 0) {\r\n hopPhase += 1 / 96;\r\n [squash, lift] = hopAt(hopPhase);\r\n if (hopPhase >= 1) {\r\n hopPhase = -1; squash = 0; lift = 0;\r\n if (queuedHop) {\r\n queuedHop = false;\r\n singlesSince = 0;\r\n hopDue = t + 150;\r\n } else if (!pendingEncore && singlesSince >= 2) {\r\n pendingEncore = true;\r\n hopDue = t + 240;\r\n } else {\r\n hopDue = t + 5000 + Math.random() * 5000;\r\n }\r\n }\r\n }\r\n const splat = Math.max(0, squash);\r\n\r\n if (alertRef.current !== wasAlert) {\r\n wasAlert = alertRef.current;\r\n const to = alertRef.current ? ALERT_SHADE : shade;\r\n deepWant = toRGB(to.color);\r\n paleWant = toRGB(to.light);\r\n if (alertRef.current && !reduced) {\r\n if (hopPhase < 0) hopPhase = 0;\r\n nagDue = t + 2600;\r\n }\r\n }\r\n\r\n const currentShade = alertRef.current ? ALERT_SHADE : shade;\r\n\r\n if (!reduced) {\r\n for (let i = 0; i < 3; i++) {\r\n deep[i] += (deepWant[i] - deep[i]) * 0.055;\r\n pale[i] += (paleWant[i] - pale[i]) * 0.055;\r\n }\r\n } else {\r\n deep = [...deepWant] as RGB;\r\n pale = [...paleWant] as RGB;\r\n }\r\n const deepCSS = rgbCSS(deep), paleCSS = rgbCSS(pale);\r\n stop1Ref.current?.setAttribute('stop-color', deepCSS);\r\n stop2Ref.current?.setAttribute('stop-color', paleCSS);\r\n stop3Ref.current?.setAttribute('stop-color', paleCSS);\r\n\r\n for (let i = 0; i < 4; i++) {\r\n const amount = MARBLE_TINT[i] + (MARBLE_FLOOD[i] - MARBLE_TINT[i]) * puff;\r\n marbleRefs.current[i]?.style.setProperty(\r\n 'stop-color',\r\n rgbCSS(mix(MARBLE_PAPER[i], deep, amount)),\r\n );\r\n }\r\n\r\n const baseWash = 0.34 + Math.sin(t / 1200) * 0.06;\r\n const contactOpacity = splat > 0.02 ? Math.min(0.72, baseWash + splat * 0.34) : baseWash;\r\n contactRef.current?.setAttribute('opacity', contactOpacity.toFixed(3));\r\n\r\n if (splat > 0.04) {\r\n onImpactRef.current?.(splat, currentShade.color, currentShade.glow);\r\n } else if (lastSplat > 0.04) {\r\n onImpactRef.current?.(0, currentShade.color, currentShade.glow);\r\n }\r\n lastSplat = splat;\r\n\r\n const wobble = reduced ? 0 : Math.sin(t / 1900) * 0.9 * at.wob;\r\n const bwF = at.bw * (1 + squash * 0.55) + wobble * 0.4;\r\n const bhF = at.bh * (1 - squash * 0.62);\r\n const d = bodyPath(\r\n bwF, bhF,\r\n clamp(at.tr + splat * 0.5, 0, 1.2),\r\n clamp(at.br + splat * 0.9, 0, 1),\r\n at.bow + wobble + splat * 5,\r\n );\r\n bodyRef.current?.setAttribute('d', d);\r\n maskRef.current?.setAttribute('d', d);\r\n\r\n const wantGoo = phase === 'thinking';\r\n if (wantGoo !== gooOn) {\r\n gooOn = wantGoo;\r\n slotGRef.current?.setAttribute('filter', wantGoo ? `url(#${uid}-goo)` : 'none');\r\n }\r\n\r\n const targets = layout(t, at.lid * (1 - splat * 0.85), at.gx, at.gy);\r\n for (let i = 0; i < SLOTS; i++) {\r\n const T = targets[i] as any, A = slotAt[i] as any, V = slotVel[i] as any;\r\n for (const k of ['x', 'y', 'w', 'h', 'rx', 'a']) {\r\n if (reduced) { A[k] = T[k]; continue; }\r\n V[k] = (V[k] + (T[k] - A[k]) * 0.16) * 0.74;\r\n A[k] += V[k];\r\n }\r\n const e = slotRefs.current[i];\r\n if (!e) continue;\r\n e.setAttribute('x', (A.x - A.w / 2).toFixed(2));\r\n e.setAttribute('y', (A.y - A.h / 2).toFixed(2));\r\n e.setAttribute('width', Math.max(0, A.w).toFixed(2));\r\n e.setAttribute('height', Math.max(0, A.h).toFixed(2));\r\n e.setAttribute('rx', Math.max(0, Math.min(A.rx, A.w / 2, A.h / 2)).toFixed(2));\r\n e.setAttribute('opacity', clamp(A.a, 0, 1).toFixed(2));\r\n }\r\n\r\n const breathe = reduced ? 0 : Math.sin(t / mood.breath) * 1.5;\r\n\r\n if (!reduced && facing && hopPhase < 0) {\r\n if (t > leanAt) {\r\n leanWant = (Math.random() < 0.5 ? -1 : 1) * (0.35 + Math.random() * 0.65);\r\n leanAt = t + 2600 + Math.random() * 4200;\r\n }\r\n if (t > peekAt) {\r\n peekWant = peekWant > 0.1 ? 0 : 1;\r\n peekAt = t + (peekWant > 0.1 ? 900 : 9000 + Math.random() * 11000);\r\n }\r\n } else {\r\n leanWant = 0;\r\n peekWant = 0;\r\n }\r\n leanVel = (leanVel + (leanWant - lean) * 0.028) * 0.9;\r\n lean += leanVel;\r\n peekVel = (peekVel + (peekWant - peek) * 0.06) * 0.82;\r\n peek += peekVel;\r\n\r\n const planted = at.bh - bhF;\r\n const tilt = lean * 3.4 + peek * 4.5;\r\n const shift = lean * 2.2 + peek * 3;\r\n const dip = peek * 2.4;\r\n figRef.current?.setAttribute(\r\n 'transform',\r\n `translate(${shift.toFixed(2)} ${(breathe + planted - lift + dip).toFixed(2)}) rotate(${tilt.toFixed(2)} 0 60)`,\r\n );\r\n\r\n if (decorRef.current) {\r\n decorRef.current.setAttribute(\r\n 'transform',\r\n `translate(${shift.toFixed(2)} ${(breathe + planted - lift + dip).toFixed(2)}) rotate(${tilt.toFixed(2)} 0 60)`,\r\n );\r\n }\r\n\r\n if (showFlower && flowerGRef.current) {\r\n const flowerX = -bwF * 0.62;\r\n const flowerY = -bhF * 0.70;\r\n const flowerTilt = -16 + (reduced ? 0 : Math.sin(t / 1400) * 3) + tilt * 0.4;\r\n flowerGRef.current.setAttribute(\r\n 'transform',\r\n `translate(${flowerX.toFixed(2)}, ${flowerY.toFixed(2)}) rotate(${flowerTilt.toFixed(2)})`\r\n );\r\n }\r\n\r\n if (showBlush && cheeksGRef.current) {\r\n const cheekY = 12 + at.gy * 0.5;\r\n cheeksGRef.current.setAttribute('transform', `translate(0, ${cheekY.toFixed(2)})`);\r\n }\r\n\r\n if (showLashes && lashesGRef.current) {\r\n const isEyeFacing = phase !== 'thinking' && phase !== 'visualizing' && phase !== 'speaking';\r\n lashesGRef.current.setAttribute('opacity', isEyeFacing ? clamp(at.lid * 1.3, 0, 1).toFixed(2) : '0');\r\n\r\n // rooted on each eye's own top-outer curve, so they track blinks and gaze\r\n // instead of floating at fixed coordinates\r\n const lashes = (A: { x: number; y: number; w: number; h: number }, side: number) => {\r\n const R = Math.max(1, Math.min(A.w, A.h) / 2);\r\n const cy = A.y - A.h / 2 + R;\r\n let d = '';\r\n for (const [deg, len] of [[20, 7], [48, 8], [76, 6.5]]) {\r\n const th = (deg * Math.PI) / 180;\r\n const sx = A.x + side * Math.sin(th) * R;\r\n const sy = cy - Math.cos(th) * R;\r\n const ex = A.x + side * Math.sin(th) * (R + len);\r\n const ey = cy - Math.cos(th) * (R + len) - 1.5;\r\n const cxp = A.x + side * Math.sin(th - 0.22) * (R + len * 0.65);\r\n const cyp = cy - Math.cos(th - 0.22) * (R + len * 0.65);\r\n d += ` M ${sx.toFixed(2)} ${sy.toFixed(2)} Q ${cxp.toFixed(2)} ${cyp.toFixed(2)} ${ex.toFixed(2)} ${ey.toFixed(2)}`;\r\n }\r\n return d.trim();\r\n };\r\n lashLRef.current?.setAttribute('d', lashes(slotAt[0] as any, -1));\r\n lashRRef.current?.setAttribute('d', lashes(slotAt[1] as any, 1));\r\n }\r\n\r\n raf = requestAnimationFrame(frame);\r\n };\r\n\r\n let lastSplat = 0;\r\n\r\n raf = requestAnimationFrame(frame);\r\n return () => cancelAnimationFrame(raf);\r\n }, [showFlower, showLashes, showBlush, isFeminine]);\r\n\r\n return (\r\n <svg className=\"hsk-kiku-avatar\" width={size} height={size} viewBox=\"-100 -100 200 200\" aria-hidden=\"true\" style={{ display: 'block', overflow: 'visible' }}>\r\n <defs>\r\n <linearGradient id={`${uid}-marble`} x1=\".2\" y1=\"0\" x2=\".42\" y2=\"1\">\r\n {[0, 40, 82, 100].map((offset, i) => (\r\n <stop\r\n key={offset}\r\n ref={el => { marbleRefs.current[i] = el; }}\r\n offset={`${offset}%`}\r\n style={{ stopColor: `var(--hsk-marble-${i + 1}, #FAF7F2)` }}\r\n />\r\n ))}\r\n </linearGradient>\r\n <linearGradient id={`${uid}-contact`} x1=\"0\" y1=\"1\" x2=\"0\" y2=\"0\">\r\n {}\r\n <stop ref={stop1Ref} offset=\"0%\" stopColor={NEUTRALS[0].color} stopOpacity=\"0.9\" />\r\n <stop ref={stop2Ref} offset=\"45%\" stopColor={NEUTRALS[0].light} stopOpacity=\"0.5\" />\r\n <stop ref={stop3Ref} offset=\"100%\" stopColor={NEUTRALS[0].light} stopOpacity=\"0\" />\r\n </linearGradient>\r\n <radialGradient id={`${uid}-sheen`} cx=\".34\" cy=\".2\" r=\".55\">\r\n <stop offset=\"0%\" stopColor=\"#FFFFFF\" style={{ stopOpacity: 'var(--hsk-marble-sheen, .9)' }} />\r\n <stop offset=\"100%\" stopColor=\"#FFFFFF\" stopOpacity=\"0\" />\r\n </radialGradient>\r\n <linearGradient id={`${uid}-hibiscus-petal`} x1=\"0\" y1=\"1\" x2=\"0\" y2=\"0\">\r\n <stop offset=\"0%\" stopColor=\"#FF3366\" />\r\n <stop offset=\"65%\" stopColor=\"#FF758F\" />\r\n <stop offset=\"100%\" stopColor=\"#FFAAA6\" />\r\n </linearGradient>\r\n <radialGradient id={`${uid}-blush-cheek`} cx=\"50%\" cy=\"50%\" r=\"50%\">\r\n <stop offset=\"0%\" stopColor=\"#FB7185\" stopOpacity=\"0.48\" />\r\n <stop offset=\"100%\" stopColor=\"#FB7185\" stopOpacity=\"0\" />\r\n </radialGradient>\r\n <clipPath id={`${uid}-skin`}><use href={`#${uid}-body`} /></clipPath>\r\n <filter id={`${uid}-goo`} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\r\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"4\" result=\"b\" />\r\n <feColorMatrix in=\"b\" values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7\" />\r\n </filter>\r\n <mask id={`${uid}-cut`}>\r\n <path ref={maskRef} d=\"\" fill=\"#FFFFFF\" />\r\n <g ref={slotGRef}>\r\n {Array.from({ length: SLOTS }, (_, i) => (\r\n <rect key={i} ref={el => { slotRefs.current[i] = el; }} fill=\"#000000\" />\r\n ))}\r\n </g>\r\n </mask>\r\n </defs>\r\n \r\n {/* Base Body & Cutouts */}\r\n <g ref={figRef} mask={`url(#${uid}-cut)`}>\r\n <path id={`${uid}-body`} ref={bodyRef} d=\"\" fill={`url(#${uid}-marble)`} />\r\n <g clipPath={`url(#${uid}-skin)`}>\r\n <ellipse cx=\"-14\" cy=\"-40\" rx=\"46\" ry=\"34\" fill={`url(#${uid}-sheen)`} />\r\n <rect ref={contactRef} x=\"-100\" y=\"-20\" width=\"200\" height=\"100\" fill={`url(#${uid}-contact)`} opacity=\"0.45\" />\r\n </g>\r\n </g>\r\n\r\n {/* Feminine Blush Decor Overlay (syncs with figure transform) */}\r\n <g ref={decorRef} style={{ pointerEvents: 'none' }}>\r\n {/* Cheek Blush */}\r\n {showBlush && (\r\n <g ref={cheeksGRef}>\r\n <ellipse cx=\"-28\" cy=\"0\" rx=\"10\" ry=\"5.5\" fill={`url(#${uid}-blush-cheek)`} />\r\n <ellipse cx=\"28\" cy=\"0\" rx=\"10\" ry=\"5.5\" fill={`url(#${uid}-blush-cheek)`} />\r\n </g>\r\n )}\r\n\r\n {/* Fluttery Eyelashes */}\r\n {showLashes && (\r\n <g ref={lashesGRef}>\r\n <path ref={lashLRef} stroke=\"#3D1424\" strokeWidth=\"1.7\" strokeLinecap=\"round\" fill=\"none\" />\r\n <path ref={lashRRef} stroke=\"#3D1424\" strokeWidth=\"1.7\" strokeLinecap=\"round\" fill=\"none\" />\r\n </g>\r\n )}\r\n\r\n {/* Tropical Hawaiian Hibiscus Flower */}\r\n {showFlower && (\r\n <g ref={flowerGRef} className=\"hsk-avatar-flower\">\r\n {/* Mint Green Leaf */}\r\n <path d=\"M 0 0 C -12 -7 -15 5 0 0 Z\" fill=\"#10B981\" transform=\"translate(6, 4) rotate(-35)\" />\r\n {/* 5 Petals */}\r\n {[0, 72, 144, 216, 288].map(deg => (\r\n <path\r\n key={deg}\r\n d=\"M 0 0 C -6 -13 6 -13 0 0 Z\"\r\n fill={`url(#${uid}-hibiscus-petal)`}\r\n stroke=\"#FF2A5F\"\r\n strokeWidth=\"0.6\"\r\n transform={`rotate(${deg - 18})`}\r\n />\r\n ))}\r\n {/* Curved Pistil / Stamen */}\r\n <path d=\"M 0 0 Q 3 -10 9 -14\" stroke=\"#F59E0B\" strokeWidth=\"1.6\" strokeLinecap=\"round\" fill=\"none\" />\r\n {/* Golden Yellow Pollen Grains */}\r\n <circle cx=\"9\" cy=\"-14\" r=\"1.3\" fill=\"#FDE047\" />\r\n <circle cx=\"7\" cy=\"-12\" r=\"1.1\" fill=\"#FDE047\" />\r\n <circle cx=\"6.5\" cy=\"-15\" r=\"1.1\" fill=\"#FDE047\" />\r\n {/* Crimson Center Hub */}\r\n <circle cx=\"0\" cy=\"0\" r=\"2.2\" fill=\"#881337\" />\r\n </g>\r\n )}\r\n </g>\r\n </svg>\r\n );\r\n}\r\n\r\nexport default KikuAvatar;\r\n","import React from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport type { KikuState } from '../KikuAvatar';\r\nimport { ChromeLoading } from './components/ListeningWave';\r\nimport { LANGUAGE_CHOICES, endonymFor, type UIStringKey } from './types';\r\nimport { CascadeText } from './components/CascadeText';\r\nimport { splitPlaceholder } from './components/AnimatedPlaceholder';\r\nimport { ShieldIcon, KeyOutlineIcon, VaultIcon, GlobeIcon } from './icons';\r\n\r\nfunction countShimmerUnits(node: React.ReactNode): number {\r\n if (typeof node === 'string') return splitPlaceholder(node).length;\r\n if (Array.isArray(node)) return node.reduce<number>((n, c) => n + countShimmerUnits(c), 0);\r\n if (React.isValidElement(node)) return countShimmerUnits((node.props as any)?.children);\r\n return 0;\r\n}\r\n\r\n// walks the whole tree so interpolated nodes (tNode's <bdi>) shimmer like plain text\r\nfunction shimmerTree(\r\n node: React.ReactNode,\r\n cursor: { i: number },\r\n last: number,\r\n baseIdx: number,\r\n): React.ReactNode {\r\n if (typeof node === 'string') {\r\n return splitPlaceholder(node).map(unit => {\r\n const i = cursor.i++;\r\n return (\r\n <span\r\n key={i}\r\n className=\"hsk-cb-shimmer-char\"\r\n style={{\r\n '--hsk-char-idx': baseIdx + i,\r\n '--hsk-ph-hue': `${Math.round((i / last) * 300)}`,\r\n } as React.CSSProperties}\r\n >\r\n {unit}\r\n </span>\r\n );\r\n });\r\n }\r\n if (Array.isArray(node)) {\r\n return node.map((child, k) => (\r\n <React.Fragment key={k}>{shimmerTree(child, cursor, last, baseIdx)}</React.Fragment>\r\n ));\r\n }\r\n if (React.isValidElement(node)) {\r\n return React.cloneElement(node as any, {\r\n children: shimmerTree((node.props as any)?.children, cursor, last, baseIdx),\r\n });\r\n }\r\n return node;\r\n}\r\n\r\nfunction ShimmerText({ text, baseIdx = 0 }: { text: React.ReactNode; baseIdx?: number }) {\r\n const last = Math.max(countShimmerUnits(text) - 1, 1);\r\n return <>{shimmerTree(text, { i: 0 }, last, baseIdx)}</>;\r\n}\r\n\r\nexport interface OnboardingViewProps {\r\n inOnboarding: boolean;\r\n justCompleted: boolean;\r\n onboardingMood?: KikuState;\r\n awaitingLang: boolean;\r\n awaitingName: boolean;\r\n awaitingEntityLang: boolean;\r\n awaitingConsent: boolean;\r\n termsAgreed: boolean;\r\n shopperLanguage: string;\r\n shopperName: string;\r\n entityLangPref: string;\r\n chromeReady: boolean;\r\n activeChips: string[];\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n tNode: (key: UIStringKey, vars: Record<string, string>) => React.ReactNode;\r\n chooseLanguage: (lang: string) => void;\r\n chooseEntityLang: (mode: 'translated' | 'original') => void;\r\n agreeTerms: () => void;\r\n handleSend: (text: string) => void;\r\n}\r\n\r\nexport function OnboardingView({\r\n inOnboarding,\r\n justCompleted,\r\n onboardingMood,\r\n awaitingLang,\r\n awaitingName,\r\n awaitingEntityLang,\r\n awaitingConsent,\r\n termsAgreed,\r\n shopperLanguage,\r\n shopperName,\r\n entityLangPref,\r\n chromeReady,\r\n activeChips,\r\n t,\r\n tNode,\r\n chooseLanguage,\r\n chooseEntityLang,\r\n agreeTerms,\r\n handleSend,\r\n}: OnboardingViewProps) {\r\n const currentStep = awaitingLang ? '1' : awaitingName ? '2' : awaitingEntityLang ? '3' : awaitingConsent ? '4' : null;\r\n const [countdown, setCountdown] = React.useState(30);\r\n\r\n React.useEffect(() => {\r\n if (!awaitingConsent) {\r\n setCountdown(30);\r\n return;\r\n }\r\n const timer = setInterval(() => {\r\n setCountdown(prev => {\r\n if (prev <= 1) {\r\n clearInterval(timer);\r\n return 0;\r\n }\r\n return prev - 1;\r\n });\r\n }, 1000);\r\n return () => clearInterval(timer);\r\n }, [awaitingConsent]);\r\n\r\n return (\r\n <div className=\"hsk-cb-empty\">\r\n <div className=\"hsk-cb-onboarding-card\">\r\n {currentStep && (\r\n <div className=\"hsk-cb-onboarding-head\">\r\n <span className=\"hsk-cb-step-badge\" dir=\"ltr\">\r\n {currentStep} / 4\r\n </span>\r\n </div>\r\n )}\r\n {awaitingLang ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-lang\">\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>What language should we chat in?</CascadeText>\r\n </h2>\r\n <div className=\"hsk-cb-lang-chips\">\r\n {LANGUAGE_CHOICES.map((l, i) => (\r\n <button\r\n key={l.value}\r\n type=\"button\"\r\n className=\"hsk-cb-lang-chip\"\r\n style={{ '--hsk-pill-idx': i } as React.CSSProperties}\r\n lang={l.tag}\r\n dir={l.rtl ? 'rtl' : 'ltr'}\r\n onClick={() => chooseLanguage(l.value)}\r\n >\r\n {l.native}\r\n </button>\r\n ))}\r\n <span\r\n className=\"hsk-cb-lang-chips-hint\"\r\n style={{ '--hsk-pill-idx': LANGUAGE_CHOICES.length } as React.CSSProperties}\r\n >\r\n or type any other\r\n </span>\r\n </div>\r\n </div>\r\n ) : awaitingName ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-name\">\r\n {chromeReady ? (\r\n <>\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>{t('nameStepTitle')}</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>{t('nameStepLead')}</CascadeText>\r\n </p>\r\n <p className=\"hsk-cb-hello-ask hsk-cascade\">\r\n <CascadeText baseMs={60}>{t('nameStepAsk')}</CascadeText>\r\n </p>\r\n </>\r\n ) : (\r\n <ChromeLoading\r\n language={shopperLanguage}\r\n onBack={() => chooseLanguage('')}\r\n />\r\n )}\r\n </div>\r\n ) : awaitingEntityLang ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-entity-lang\">\r\n {chromeReady && (\r\n <>\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>{t('howShouldResultsLook')}</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>{tNode('entityLangIntro', { lang: shopperLanguage })}</CascadeText>\r\n </p>\r\n </>\r\n )}\r\n {chromeReady && (\r\n <div className=\"hsk-cb-entlang-opts\" role=\"radiogroup\" aria-label={t('howShouldResultsLook')}>\r\n {(['translated', 'original'] as const).map((mode, i) => (\r\n <button\r\n key={mode}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={entityLangPref === mode}\r\n className={cn(\"hsk-cb-entlang-opt\", entityLangPref === mode && \"is-selected\")}\r\n style={{ '--hsk-opt-idx': i } as React.CSSProperties}\r\n onClick={() => chooseEntityLang(mode)}\r\n >\r\n <span className=\"hsk-cb-entlang-radio\" aria-hidden=\"true\">\r\n <span className=\"hsk-cb-entlang-radio-dot\" />\r\n </span>\r\n <span className=\"hsk-cb-entlang-opt-text\">\r\n <span className=\"hsk-cb-entlang-opt-title\">\r\n <ShimmerText\r\n text={\r\n mode === 'translated'\r\n ? tNode('inLanguage', { lang: shopperLanguage })\r\n : t('asWritten')\r\n }\r\n baseIdx={0}\r\n />\r\n </span>\r\n <span className=\"hsk-cb-entlang-opt-note\">\r\n <ShimmerText\r\n text={\r\n mode === 'translated'\r\n ? t('detailsTranslated')\r\n : t('namesAsWritten')\r\n }\r\n baseIdx={15}\r\n />\r\n </span>\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n ) : awaitingConsent ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-terms\">\r\n {chromeReady && (\r\n <>\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>{t('termsStepTitle')}</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>{t('termsStepSubtitle')}</CascadeText>\r\n </p>\r\n <div className=\"hsk-cb-terms-sanctuary\">\r\n <div className=\"hsk-cb-terms-item\" style={{ '--hsk-row-idx': 0 } as React.CSSProperties}>\r\n <div className=\"hsk-cb-terms-head\">\r\n <span className=\"hsk-cb-terms-numeral\">I</span>\r\n <h3 className=\"hsk-cb-terms-title\">{t('termsPiiTitle')}</h3>\r\n </div>\r\n <p className=\"hsk-cb-terms-desc\">{t('termsPiiDesc')}</p>\r\n </div>\r\n\r\n <div className=\"hsk-cb-terms-divider\" />\r\n\r\n <div className=\"hsk-cb-terms-item\" style={{ '--hsk-row-idx': 1 } as React.CSSProperties}>\r\n <div className=\"hsk-cb-terms-head\">\r\n <span className=\"hsk-cb-terms-numeral\">II</span>\r\n <h3 className=\"hsk-cb-terms-title\">{t('termsSessionTitle')}</h3>\r\n </div>\r\n <p className=\"hsk-cb-terms-desc\">{t('termsSessionDesc')}</p>\r\n </div>\r\n\r\n <div className=\"hsk-cb-terms-divider\" />\r\n\r\n <div className=\"hsk-cb-terms-item\" style={{ '--hsk-row-idx': 2 } as React.CSSProperties}>\r\n <div className=\"hsk-cb-terms-head\">\r\n <span className=\"hsk-cb-terms-numeral\">III</span>\r\n <h3 className=\"hsk-cb-terms-title\">{t('termsMemoryTitle')}</h3>\r\n </div>\r\n <p className=\"hsk-cb-terms-desc\">{t('termsMemoryDesc')}</p>\r\n </div>\r\n\r\n <div className=\"hsk-cb-terms-divider\" />\r\n\r\n <div className=\"hsk-cb-terms-item\" style={{ '--hsk-row-idx': 3 } as React.CSSProperties}>\r\n <div className=\"hsk-cb-terms-head\">\r\n <span className=\"hsk-cb-terms-numeral\">IV</span>\r\n <h3 className=\"hsk-cb-terms-title\">{t('termsCookieTitle')}</h3>\r\n </div>\r\n <p className=\"hsk-cb-terms-desc\">{t('termsCookieDesc')}</p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"hsk-cb-terms-action-wrap\">\r\n <button\r\n type=\"button\"\r\n className={cn(\r\n \"hsk-cb-terms-agree-btn\",\r\n countdown === 0 && \"is-active\"\r\n )}\r\n disabled={countdown > 0}\r\n onClick={agreeTerms}\r\n >\r\n {countdown > 0\r\n ? t('termsAgreeCounting', { seconds: String(countdown) })\r\n : t('termsAgreeButton')}\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n ) : justCompleted ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-completed\">\r\n {chromeReady && (\r\n <>\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>{tNode('allSet', { name: shopperName })}</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>\r\n {entityLangPref === 'translated'\r\n ? tNode('replyingTranslated', { lang: shopperLanguage })\r\n : tNode('replyingOriginal', { lang: shopperLanguage })}\r\n </CascadeText>\r\n </p>\r\n </>\r\n )}\r\n </div>\r\n ) : shopperName ? (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-returning\">\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>{tNode('greetReturning', { name: shopperName })}</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>{t('greetReturningLead')}</CascadeText>\r\n </p>\r\n </div>\r\n ) : (\r\n <div className=\"hsk-cb-hello-wrap\" key=\"step-initial\">\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={0}>Hi, I'm <b>kiku</b>.</CascadeText>\r\n </h2>\r\n <p className=\"hsk-cb-hello-lead hsk-cascade\">\r\n <CascadeText baseMs={30}>Ask me to search, visualize, or capture anything — I look across the whole site in real time.</CascadeText>\r\n </p>\r\n </div>\r\n )}\r\n {!inOnboarding && (activeChips?.length ?? 0) > 0 && (\r\n <div className=\"hsk-cb-chips\">\r\n {activeChips.map((chip, i) => (\r\n <button\r\n key={chip}\r\n className=\"hsk-cb-chip\"\r\n style={{ '--hsk-pill-idx': i } as React.CSSProperties}\r\n onClick={() => handleSend(chip)}\r\n >\r\n {chip}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React, { useEffect, useRef } from 'react';\r\nimport { getLoadingMeta } from '../types';\r\nimport { CascadeText } from './CascadeText';\r\n\r\nconst WAVE_BARS = 64;\r\n\r\nexport function ChromeLoading({\r\n language,\r\n onBack,\r\n}: {\r\n language?: string;\r\n onBack?: () => void;\r\n}) {\r\n const meta = getLoadingMeta(language);\r\n\r\n return (\r\n <div className=\"hsk-cb-chrome-loading\" dir={meta.rtl ? 'rtl' : 'ltr'} aria-busy=\"true\">\r\n <div className=\"hsk-cb-chrome-loading-header\">\r\n <h2 className=\"hsk-cb-hello hsk-cascade\">\r\n <CascadeText baseMs={60}>{meta.preparing}</CascadeText>\r\n </h2>\r\n </div>\r\n\r\n {/* Indeterminate on purpose: the translation is all-or-nothing, so a\r\n filling bar would be inventing progress it cannot know. */}\r\n <div className=\"hsk-cb-chrome-progress\" role=\"progressbar\" aria-label={meta.preparing}>\r\n <div className=\"hsk-cb-chrome-progress-track\" />\r\n </div>\r\n\r\n {onBack && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-chrome-back-btn\"\r\n onClick={onBack}\r\n >\r\n <span aria-hidden=\"true\">{meta.rtl ? '→' : '←'}</span> {meta.changeLang}\r\n </button>\r\n )}\r\n\r\n {!meta.known && (\r\n <div className=\"hsk-cb-chrome-notice\" dir=\"ltr\" lang=\"en\">\r\n <div className=\"hsk-cb-chrome-notice-header\">\r\n <span className=\"hsk-cb-chrome-notice-pill\">Preview / Low-Resource</span>\r\n <span className=\"hsk-cb-chrome-notice-title\">Live Machine Translation</span>\r\n </div>\r\n <span className=\"hsk-cb-chrome-notice-body\">\r\n <b>{meta.nativeName}</b> is translated in real time as you browse. Some phrasing\r\n may read differently than human-reviewed copy, but names, prices, and figures are\r\n always strictly preserved.\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport function ListeningWave({ spectrumBins, micSpectrum }: {\r\n spectrumBins: () => number;\r\n micSpectrum: (out: Uint8Array) => boolean;\r\n}) {\r\n const rowRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n let raf = 0;\r\n const level = new Array(WAVE_BARS).fill(0);\r\n const mid = (WAVE_BARS - 1) / 2;\r\n let spectrum = new Uint8Array(0);\r\n\r\n const tick = () => {\r\n raf = requestAnimationFrame(tick);\r\n const bins = spectrumBins();\r\n if (bins === 0) return;\r\n if (spectrum.length !== bins) spectrum = new Uint8Array(bins);\r\n if (!micSpectrum(spectrum)) return;\r\n\r\n const row = rowRef.current;\r\n if (!row) return;\r\n for (let i = 0; i < WAVE_BARS; i++) {\r\n const fromMid = Math.abs(i - mid) / mid;\r\n const bin = Math.min(spectrum.length - 1, Math.round(fromMid * spectrum.length * 0.45));\r\n const target = (spectrum[bin] / 255) * (1 - fromMid * 0.45);\r\n level[i] += (target - level[i]) * 0.3;\r\n const dot = row.children[i] as HTMLElement | undefined;\r\n if (dot) {\r\n dot.style.transform = `scaleY(${(1 + level[i] * 13).toFixed(3)})`;\r\n dot.style.opacity = (0.3 + level[i] * 0.7).toFixed(3);\r\n }\r\n }\r\n };\r\n tick();\r\n\r\n return () => cancelAnimationFrame(raf);\r\n }, [spectrumBins, micSpectrum]);\r\n\r\n return (\r\n <div className=\"hsk-cb-listening\" ref={rowRef} aria-hidden=\"true\">\r\n {Array.from({ length: WAVE_BARS }).map((_, i) => <span key={i} />)}\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\nconst HSK_WORD_STAGGER_MS = 12;\r\n\r\nexport interface CascadeTextProps {\r\n children: React.ReactNode;\r\n baseMs?: number;\r\n}\r\n\r\nfunction plainText(node: React.ReactNode): string {\r\n if (node === null || node === undefined || typeof node === 'boolean') return '';\r\n if (typeof node === 'string' || typeof node === 'number') return String(node);\r\n if (Array.isArray(node)) return node.map(plainText).join('');\r\n if (React.isValidElement(node)) return plainText((node.props as { children?: React.ReactNode }).children);\r\n return '';\r\n}\r\n\r\nfunction cascade(node: React.ReactNode, count: { i: number }, baseMs: number, keyPrefix: string): React.ReactNode {\r\n if (node === null || node === undefined || typeof node === 'boolean') return null;\r\n\r\n if (typeof node === 'string' || typeof node === 'number') {\r\n return String(node)\r\n .split(/(\\s+)/)\r\n .filter(Boolean)\r\n .map((chunk, ci) => {\r\n if (/^\\s+$/.test(chunk)) {\r\n return chunk;\r\n }\r\n const delay = baseMs + count.i * HSK_WORD_STAGGER_MS;\r\n count.i += 1;\r\n return (\r\n <span className=\"hsk-cascade__w\" key={`${keyPrefix}-w${ci}`} style={{ animationDelay: `${delay}ms` }}>\r\n {chunk}\r\n </span>\r\n );\r\n });\r\n }\r\n\r\n if (Array.isArray(node)) return node.map((child, i) => cascade(child, count, baseMs, `${keyPrefix}-${i}`));\r\n\r\n if (React.isValidElement(node)) {\r\n const el = node as React.ReactElement<{ children?: React.ReactNode }>;\r\n return React.cloneElement(el, { key: `${keyPrefix}-el` }, cascade(el.props.children, count, baseMs, `${keyPrefix}-c`));\r\n }\r\n\r\n return node;\r\n}\r\n\r\nexport function CascadeText({ children, baseMs = 0 }: CascadeTextProps) {\r\n const text = plainText(children);\r\n let hash = 0;\r\n for (let i = 0; i < text.length; i++) {\r\n hash = ((hash << 5) - hash + text.charCodeAt(i)) | 0;\r\n }\r\n const prefix = `c${Math.abs(hash)}`;\r\n\r\n return (\r\n <>\r\n <span className=\"hsk-sr-only\">{text}</span>\r\n <span aria-hidden=\"true\">{cascade(children, { i: 0 }, baseMs, prefix)}</span>\r\n </>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\nexport interface AnimatedPlaceholderProps {\r\n text?: string;\r\n placeholder?: string;\r\n visible?: boolean;\r\n replay?: number;\r\n replaySeed?: number;\r\n staggerMs?: number;\r\n}\r\n\r\nexport const HSK_STAGGER_MS = 16;\r\n\r\nconst HSK_FIELD_BASE_MS = 110;\r\n\r\nconst JOINING_SCRIPT = /[؀-ۿ܀-ݏ߀-߿ࡠ-ࣿﭐ-﷿ﹰ-]/;\r\n\r\ntype GraphemeSegmenter = {\r\n segment(input: string): Iterable<{ segment: string }>;\r\n};\r\ntype IntlWithSegmenter = typeof Intl & {\r\n Segmenter?: new (locale?: string, options?: { granularity: string }) => GraphemeSegmenter;\r\n};\r\n\r\nexport function splitPlaceholder(text: string): string[] {\r\n if (!text) return [];\r\n\r\n if (JOINING_SCRIPT.test(text)) return text.split(/(\\s+)/).filter(Boolean);\r\n\r\n const I = typeof Intl !== 'undefined' ? (Intl as IntlWithSegmenter) : undefined;\r\n if (I?.Segmenter) {\r\n const seg = new I.Segmenter(undefined, { granularity: 'grapheme' });\r\n return Array.from(seg.segment(text), s => s.segment);\r\n }\r\n\r\n return text.split(/(\\s+)/).filter(Boolean);\r\n}\r\n\r\nexport function AnimatedPlaceholder({\r\n text,\r\n placeholder,\r\n visible = true,\r\n replay = 0,\r\n replaySeed,\r\n staggerMs = HSK_STAGGER_MS,\r\n}: AnimatedPlaceholderProps) {\r\n if (!visible) return null;\r\n const content = text || placeholder || '';\r\n if (!content) return null;\r\n const seed = replaySeed !== undefined ? replaySeed : replay;\r\n\r\n const units = splitPlaceholder(content);\r\n const last = Math.max(units.length - 1, 1);\r\n\r\n return (\r\n <div className=\"hsk-animated-placeholder\" dir=\"auto\" aria-hidden=\"true\">\r\n {units.map((unit, i) => (\r\n <span\r\n key={`${content}|${seed}|${i}`}\r\n className=\"hsk-animated-placeholder__char\"\r\n style={{\r\n animationDelay: `${HSK_FIELD_BASE_MS + i * staggerMs}ms`,\r\n '--hsk-ph-hue': `${Math.round((i / last) * 300)}`,\r\n } as React.CSSProperties}\r\n >\r\n {unit}\r\n </span>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\nimport type { ChatMessage, ChatSource, ChatAction } from '@akropolys/sdk';\r\nimport { cn } from '../../../utils/cn';\r\nimport { renderMarkdown } from '../../../utils/markdown';\r\nimport { LiveTable } from '../../LiveTable';\r\nimport { ThinkingBlock, parseThinking } from './ThinkingBlock';\r\nimport { SourcesCarousel } from './SourcesCarousel';\r\nimport { SmartContextPills } from './SmartContextPills';\r\nimport { MicIcon, ExternalIcon } from '../icons';\r\nimport type { UIStringKey } from '../types';\r\n\r\nconst MarkdownBlock = React.memo(\r\n ({ content, streaming }: { content: string; streaming: boolean }) => <>{renderMarkdown(content, streaming)}</>,\r\n (a, b) => a.content === b.content && a.streaming === b.streaming\r\n);\r\nMarkdownBlock.displayName = 'MarkdownBlock';\r\n\r\nexport interface MessageItemProps {\r\n msg: ChatMessage;\r\n idx: number;\r\n isLast: boolean;\r\n isLastUser: boolean;\r\n isRunEnd: boolean;\r\n runMid: boolean;\r\n runCont: boolean;\r\n isNarrow: boolean;\r\n loading: boolean;\r\n streaming: boolean;\r\n stopped: boolean;\r\n interrupted: boolean;\r\n sources: ChatSource[];\r\n referencedIds: string[];\r\n discussedSources: ChatSource[];\r\n lastIntent: string | null;\r\n lastAction: ChatAction | null;\r\n defaultCurrency: string;\r\n vizState: Record<string, 'ok' | 'err'>;\r\n setVizState: React.Dispatch<React.SetStateAction<Record<string, 'ok' | 'err'>>>;\r\n setLightboxSrc: (src: string | null) => void;\r\n setMarkupSrc: (src: string | null) => void;\r\n handleSend: (text?: string) => Promise<void>;\r\n handleSourceClick: (src: ChatSource) => void;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n messageRef: (el: HTMLDivElement | null) => void;\r\n}\r\n\r\nexport function MessageItem({\r\n msg,\r\n idx,\r\n isLast,\r\n isLastUser,\r\n isRunEnd,\r\n runMid,\r\n runCont,\r\n isNarrow,\r\n loading,\r\n streaming,\r\n stopped,\r\n interrupted,\r\n sources,\r\n referencedIds,\r\n discussedSources,\r\n lastIntent,\r\n lastAction,\r\n defaultCurrency,\r\n vizState,\r\n setVizState,\r\n setLightboxSrc,\r\n setMarkupSrc,\r\n handleSend,\r\n handleSourceClick,\r\n t,\r\n messageRef,\r\n}: MessageItemProps) {\r\n const isUser = msg.role === 'user';\r\n const displayContent = msg.content;\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'hsk-cb-msg-group',\r\n runMid && 'hsk-cb-msg-group--run-mid',\r\n runCont && 'hsk-cb-msg-group--run-cont',\r\n )}\r\n ref={messageRef}\r\n >\r\n {isUser ? (\r\n <div className={`hsk-cb-user-msg${isLastUser ? ' hsk-sent' : ''}`}>\r\n {msg.images && msg.images.length > 0 && (\r\n <div className=\"hsk-cb-user-imgs\" data-count={Math.min(msg.images.length, 4)}>\r\n {msg.images.slice(0, 4).map((img, i) => (\r\n <button\r\n key={i}\r\n type=\"button\"\r\n className=\"hsk-cb-user-img-cell\"\r\n onClick={() => setLightboxSrc(img)}\r\n >\r\n <img src={img} alt={`attachment ${i + 1}`} className=\"hsk-cb-user-img-thumb\" />\r\n {i === 3 && msg.images!.length > 4 && (\r\n <span className=\"hsk-cb-user-img-more\">+{msg.images!.length - 3}</span>\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n {msg.content && (\r\n <div className={cn(\r\n 'hsk-cb-user-bubble',\r\n isRunEnd && 'hsk-cb-user-bubble--tail',\r\n msg.spoken && 'hsk-cb-user-bubble--spoken',\r\n )}>\r\n {msg.spoken && <MicIcon className=\"hsk-cb-spoken-mark\" size={10} />}\r\n {/^@kiku\\b/i.test(msg.content) ? (\r\n <>\r\n <span className=\"hsk-kiku-badge\">@kiku</span>\r\n {msg.content.replace(/^@kiku\\s*/i, '')}\r\n </>\r\n ) : msg.content}\r\n </div>\r\n )}\r\n {isLastUser && (\r\n <span className=\"hsk-cb-sent-status\">\r\n {stopped || interrupted ? t('statusStopped') : t('statusSent')}\r\n </span>\r\n )}\r\n </div>\r\n ) : (\r\n <div className={cn('hsk-cb-ai-msg', isNarrow && 'hsk-cb-ai-msg--inline')}>\r\n <div className=\"hsk-cb-ai-body\">\r\n {(() => {\r\n const parsed = parseThinking(displayContent);\r\n const thinking = msg.thinking || parsed.thinking;\r\n let content = parsed.content;\r\n const CALC_DISCLAIMER_REGEX = /(?:^|\\n+)(?:[>*_~`\\s]*)(?:This is a calculation from live figures,?\\s*not a guarantee\\s*[—–-]\\s*the market can move against it\\.?)(?:[>*_~`\\s]*)/gi;\r\n const hasCalcDisclaimer = CALC_DISCLAIMER_REGEX.test(content);\r\n const cleanContent = hasCalcDisclaimer ? content.replace(CALC_DISCLAIMER_REGEX, '').trimEnd() : content;\r\n const isComplete = msg.thoughtForSeconds != null || content.length > 0 || !(isLast && (streaming || loading));\r\n return (\r\n <>\r\n {!msg.spoken && (thinking || msg.thoughtForSeconds != null || (isLast && (streaming || loading))) && (\r\n <ThinkingBlock text={thinking} isComplete={isComplete} seconds={msg.thoughtForSeconds} />\r\n )}\r\n {cleanContent && (\r\n <div className=\"hsk-cb-ai-content\">\r\n <MarkdownBlock content={cleanContent} streaming={isLast && streaming} />\r\n </div>\r\n )}\r\n {hasCalcDisclaimer && (\r\n <div className=\"hsk-cb-calc-disclaimer\">\r\n {t('calcDisclaimer')}\r\n </div>\r\n )}\r\n </>\r\n );\r\n })()}\r\n\r\n {msg.visualizing && (\r\n <div className=\"hsk-cb-viz hsk-cb-viz--loading\">\r\n <span className=\"hsk-cb-viz-spinner\" />\r\n <span>{msg.visualizingText || t('vizWorking')}</span>\r\n </div>\r\n )}\r\n {msg.visualization && (\r\n <div className=\"hsk-cb-viz\">\r\n <div className=\"hsk-cb-viz-imgwrap\">\r\n {msg.visualizationType === 'video' || msg.visualization.includes('/videos/') ? (\r\n <video\r\n src={msg.visualization}\r\n controls\r\n autoPlay\r\n loop\r\n muted\r\n playsInline\r\n className=\"hsk-markdown-video\"\r\n style={{ display: 'block', maxHeight: '400px', objectFit: 'contain', width: '100%' }}\r\n />\r\n ) : (\r\n <img\r\n src={msg.visualization}\r\n alt=\"Product visualized in your photo\"\r\n className=\"hsk-markdown-img\"\r\n style={vizState[msg.visualization] === 'err' ? { display: 'none' } : undefined}\r\n onLoad={() => setVizState(p => ({ ...p, [msg.visualization!]: 'ok' }))}\r\n onError={() => setVizState(p => ({ ...p, [msg.visualization!]: 'err' }))}\r\n />\r\n )}\r\n {vizState[msg.visualization] === 'err' && (\r\n <div className=\"hsk-cb-viz-broken\">{t('vizUnavailable')}</div>\r\n )}\r\n {isLast && !streaming && vizState[msg.visualization] === 'ok' && (msg.visualizationType !== 'video' && !msg.visualization.includes('/videos/')) && (\r\n <button className=\"hsk-cb-viz-mark\" onClick={() => setMarkupSrc(msg.visualization!)}>\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M12 20h9\" /><path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z\" />\r\n </svg>\r\n {t('vizMarkEdit')}\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"hsk-cb-viz-disclaimer\">\r\n {msg.visualizationType === 'video' || msg.visualization.includes('/videos/')\r\n ? t('vizDisclaimerVideo')\r\n : t('vizDisclaimerImage')}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {!isUser && (msg.knowledgeImages?.length ?? 0) > 0 && (\r\n <div className=\"hsk-cb-kimgs\">\r\n {msg.knowledgeImages!.map((ref) => (\r\n <div key={ref.entryId} className=\"hsk-cb-kimg-group\">\r\n <div className=\"hsk-cb-kimg-grid\">\r\n {ref.images.map((img, i) => (\r\n <img\r\n key={i}\r\n src={img.url}\r\n alt={img.note || ref.title || 'Reference image'}\r\n className=\"hsk-cb-kimg\"\r\n loading=\"lazy\"\r\n onClick={() => setLightboxSrc(img.url)}\r\n onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}\r\n />\r\n ))}\r\n </div>\r\n {(ref.title || ref.images[0]?.note) && (\r\n <div className=\"hsk-cb-kimg-caption\">{ref.title || ref.images[0]?.note}</div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {!isUser && <LiveTable keys={msg.liveKeys} />}\r\n\r\n {!isUser && (msg.staleNotices?.length ?? 0) > 0 && (\r\n <div className=\"hsk-cb-stale\" role=\"status\">\r\n <div className=\"hsk-cb-stale-title\">{t('staleTitle')}</div>\r\n {msg.staleNotices!.map((n, i) => (\r\n <div key={i} className=\"hsk-cb-stale-item\">\r\n {n.state === 'removed'\r\n ? t('staleRemoved', { title: n.title })\r\n : t('staleUnavailable', { title: n.title })}\r\n {n.reason && <span className=\"hsk-cb-stale-reason\"> {n.reason}</span>}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {(() => {\r\n const msgReferencedIds = isLast ? referencedIds : (msg.referencedIds ?? []);\r\n const msgSources = isLast ? sources : (msg.sources ?? []);\r\n const msgIntent = isLast ? lastIntent : msg.intent;\r\n const hiddenIntent = msgIntent === 'compare' || msgIntent === 'capture' ||\r\n msgIntent === 'capture_all' || msgIntent === 'delete' || msgIntent === 'view_history';\r\n const showCarousel = msgReferencedIds.length > 0 && !hiddenIntent &&\r\n (!isLast || lastAction?.type !== 'request_kiku_key');\r\n return showCarousel && (\r\n <SourcesCarousel\r\n sources={msgSources}\r\n defaultCurrency={defaultCurrency}\r\n onSelectSource={handleSourceClick}\r\n onImageClick={setLightboxSrc}\r\n referencedIds={msgReferencedIds}\r\n compact={!!msg.visualization}\r\n />\r\n );\r\n })()}\r\n\r\n {isLast && !loading && !streaming && lastAction?.type === 'open_memory' && lastAction.url && (\r\n <a\r\n className=\"hsk-cb-memory-pill\"\r\n href={String(lastAction.url)}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n {t('openMemory')}\r\n <ExternalIcon />\r\n </a>\r\n )}\r\n\r\n {isLast && !loading && lastAction?.url && lastAction.type !== 'open_memory' && (\r\n <div className=\"hsk-action-pills\">\r\n <a className=\"hsk-action-pill\" href={lastAction.url}>\r\n {String(lastAction.type || 'continue').replace(/_/g, ' ')} →\r\n </a>\r\n </div>\r\n )}\r\n\r\n {isLast && !loading && (\r\n <SmartContextPills\r\n intent={lastIntent}\r\n sources={discussedSources}\r\n onSend={handleSend}\r\n loading={loading}\r\n defaultCurrency={defaultCurrency}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import React, { useEffect, useState } from 'react';\r\nimport {\r\n describeAge,\r\n getLiveValue,\r\n isFresh,\r\n isStale,\r\n labelFor,\r\n formatLiveValue,\r\n subscribeLiveValues,\r\n LIVE_FLASH_MS,\r\n type LiveValue,\r\n} from '@akropolys/sdk';\r\n\r\nfunction useLiveValues(keys: string[]): (LiveValue | undefined)[] {\r\n const [, bump] = useState(0);\r\n const joined = JSON.stringify(keys);\r\n\r\n useEffect(() => subscribeLiveValues(k => {\r\n if (keys.includes(k)) bump(n => n + 1);\r\n }), [joined]);\r\n\r\n useEffect(() => {\r\n const id = setInterval(() => bump(n => n + 1), 1000);\r\n return () => clearInterval(id);\r\n }, []);\r\n\r\n return keys.map(getLiveValue);\r\n}\r\n\r\nfunction LiveQuoteCard({ record, now }: { record: LiveValue; now: number }) {\r\n const stale = isStale(record, now);\r\n\r\n const fields = record.fields;\r\n const rawTitle = fields.event || fields.question || fields.title || record.key;\r\n const shortTitle = rawTitle.length > 38 ? rawTitle.slice(0, 36) + '…' : rawTitle;\r\n\r\n const hasYesPrice = !!fields.yes_price || !!fields.yesPrice;\r\n const hasNoPrice = !!fields.no_price || !!fields.noPrice;\r\n\r\n const quotePills: { label: string; value: string; rawKey: string }[] = [];\r\n\r\n if (hasYesPrice) {\r\n quotePills.push({ label: 'Yes', value: formatLiveValue('yes_price', fields.yes_price || fields.yesPrice), rawKey: 'yes_price' });\r\n } else if (fields.yes_pct || fields.yesPct) {\r\n quotePills.push({ label: 'Yes', value: formatLiveValue('yes_pct', fields.yes_pct || fields.yesPct), rawKey: 'yes_pct' });\r\n }\r\n\r\n if (hasNoPrice) {\r\n quotePills.push({ label: 'No', value: formatLiveValue('no_price', fields.no_price || fields.noPrice), rawKey: 'no_price' });\r\n } else if (fields.no_pct || fields.noPct) {\r\n quotePills.push({ label: 'No', value: formatLiveValue('no_pct', fields.no_pct || fields.noPct), rawKey: 'no_pct' });\r\n }\r\n\r\n if (fields.bid) quotePills.push({ label: 'Bid', value: formatLiveValue('bid', fields.bid), rawKey: 'bid' });\r\n if (fields.ask) quotePills.push({ label: 'Ask', value: formatLiveValue('ask', fields.ask), rawKey: 'ask' });\r\n if (fields.spread) quotePills.push({ label: 'Spread', value: formatLiveValue('spread', fields.spread), rawKey: 'spread' });\r\n if (!hasYesPrice && !hasNoPrice && !fields.bid && fields.price) {\r\n quotePills.push({ label: 'Price', value: formatLiveValue('price', fields.price), rawKey: 'price' });\r\n }\r\n\r\n if (fields.home_spread || fields.spread_line) quotePills.push({ label: 'Spread', value: formatLiveValue('spread', fields.home_spread || fields.spread_line), rawKey: 'spread' });\r\n if (fields.moneyline || fields.ml) quotePills.push({ label: 'ML', value: formatLiveValue('ml', fields.moneyline || fields.ml), rawKey: 'moneyline' });\r\n if (fields.over_under || fields.total) quotePills.push({ label: 'O/U', value: formatLiveValue('total', fields.over_under || fields.total), rawKey: 'over_under' });\r\n\r\n const volVal = fields.volume || fields.vol || fields['24h_volume'] || fields.turnover;\r\n if (volVal) {\r\n quotePills.push({ label: 'Vol', value: formatLiveValue('volume', volVal), rawKey: 'volume' });\r\n }\r\n\r\n const closeDate = fields.close_date || fields.expiry || fields.expires_at || fields.settle_date;\r\n const formattedClose = closeDate ? formatLiveValue('close_date', closeDate) : null;\r\n\r\n return (\r\n <div className={`hsk-live-card${stale ? ' is-stale' : ''}`} role=\"region\" aria-label=\"Live quote\">\r\n <div className=\"hsk-live-card__header\">\r\n <div className=\"hsk-live-card__status\">\r\n <span className={`hsk-live-dot${stale ? ' is-stale' : ''}`} aria-hidden=\"true\" />\r\n <span className=\"hsk-live-card__title\" title={rawTitle}>{shortTitle}</span>\r\n </div>\r\n <div className=\"hsk-live-card__meta\">\r\n {formattedClose && <span className=\"hsk-live-card__close\">Closes {formattedClose}</span>}\r\n <span className=\"hsk-live-card__age\">\r\n {stale ? `Paused · ${describeAge(now - record.at)}` : `Live · ${describeAge(now - record.at)}`}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"hsk-live-card__pills\">\r\n {quotePills.map(p => {\r\n const flash = isFresh(record, p.rawKey, now);\r\n return (\r\n <div\r\n key={p.rawKey}\r\n className={`hsk-live-pill${flash ? ' is-changed' : ''}`}\r\n style={flash ? { animationDuration: `${LIVE_FLASH_MS}ms` } : undefined}\r\n >\r\n <span className=\"hsk-live-pill__label\">{p.label}</span>\r\n <span className=\"hsk-live-pill__value\">{p.value}</span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function LiveTable({ keys }: { keys?: string[] }) {\r\n const seen = new Set<string>();\r\n const ordered = (keys ?? []).filter(k => (seen.has(k) ? false : (seen.add(k), true)));\r\n\r\n const records = useLiveValues(ordered);\r\n const present = ordered.filter((_, i) => records[i]);\r\n if (present.length === 0) return null;\r\n\r\n const shown = records.filter((r): r is LiveValue => !!r);\r\n const now = Date.now();\r\n\r\n return (\r\n <div className=\"hsk-live-wrap\" role=\"group\" aria-label=\"Live market data\">\r\n <div className=\"hsk-live-carousel\">\r\n {shown.map(r => (\r\n <LiveQuoteCard key={r.key} record={r} now={now} />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React, { useState, useEffect, useRef } from 'react';\r\nimport { cn } from '../../../utils/cn';\r\nimport { useT } from '../types';\r\n\r\nexport function parseThinking(text: string): { thinking: string; content: string; isComplete: boolean } {\r\n const openMatch = text.match(/<\\s*thinking\\s*>/i);\r\n if (!openMatch) {\r\n return { thinking: '', content: text, isComplete: true };\r\n }\r\n\r\n const openIdx = openMatch.index ?? 0;\r\n const openTagLength = openMatch[0].length;\r\n const start = openIdx + openTagLength;\r\n\r\n const contentBefore = text.slice(0, openIdx);\r\n const textAfterOpen = text.slice(start);\r\n\r\n const closeMatch = textAfterOpen.match(/<\\/\\s*thinking\\s*>/i);\r\n if (!closeMatch) {\r\n return {\r\n thinking: textAfterOpen,\r\n content: contentBefore,\r\n isComplete: false\r\n };\r\n }\r\n\r\n const closeIdx = closeMatch.index ?? 0;\r\n const closeTagLength = closeMatch[0].length;\r\n\r\n return {\r\n thinking: textAfterOpen.slice(0, closeIdx),\r\n content: contentBefore + textAfterOpen.slice(closeIdx + closeTagLength),\r\n isComplete: true\r\n };\r\n}\r\n\r\nexport function ThinkingBlock({ text, isComplete, seconds: fixedSeconds }: { text: string; isComplete: boolean; seconds?: number }) {\r\n const tr = useT();\r\n const startRef = useRef(Date.now());\r\n const [seconds, setSeconds] = useState<number | null>(() => (isComplete ? null : 0));\r\n const [isOpen, setIsOpen] = useState(!isComplete);\r\n\r\n useEffect(() => {\r\n if (isComplete) {\r\n if (seconds !== null) {\r\n setSeconds(Math.max(1, Math.round((Date.now() - startRef.current) / 1000)));\r\n setIsOpen(false);\r\n }\r\n return;\r\n }\r\n setIsOpen(true);\r\n const t = setInterval(() => {\r\n setSeconds(Math.round((Date.now() - startRef.current) / 1000));\r\n }, 1000);\r\n return () => clearInterval(t);\r\n }, [isComplete]);\r\n\r\n const finalSeconds = fixedSeconds ?? seconds;\r\n const label = isComplete\r\n ? (finalSeconds !== null && finalSeconds !== undefined\r\n ? tr('thoughtForSeconds', { duration: `${finalSeconds}s` })\r\n : tr('thoughtProcess'))\r\n : `${tr('thinking')}${seconds ? ` · ${seconds}s` : '…'}`;\r\n const expandable = !!text;\r\n\r\n return (\r\n <div className={cn('hsk-cb-think', !isComplete && 'hsk-cb-think--live')}>\r\n <button\r\n type=\"button\"\r\n className={cn('hsk-cb-think-head', !expandable && 'hsk-cb-think-head--static')}\r\n onClick={expandable ? () => setIsOpen(o => !o) : undefined}\r\n aria-expanded={expandable ? isOpen : undefined}\r\n >\r\n <span>{label}</span>\r\n {expandable && <span className={cn('hsk-cb-think-chevron', isOpen && 'hsk-cb-think-chevron--open')}>▶</span>}\r\n </button>\r\n {expandable && isOpen && <div className=\"hsk-cb-think-body\">{text}</div>}\r\n </div>\r\n );\r\n}\r\n","import React, { useState, useRef, useEffect, useCallback } from 'react';\r\nimport type { ChatSource } from '@akropolys/sdk';\r\nimport { useAkropolysContext } from '@akropolys/sdk';\r\nimport { cn } from '../../../utils/cn';\r\nimport { SparkleIcon, ChevronLeftIcon, ChevronRightIcon } from '../icons';\r\n\r\nexport interface SourcesCarouselProps {\r\n sources: ChatSource[];\r\n defaultCurrency: string;\r\n onSelectSource?: (src: ChatSource) => void;\r\n onImageClick?: (src: string) => void;\r\n referencedIds?: string[];\r\n compact?: boolean;\r\n}\r\n\r\nexport function SourceImg({ src, alt, onImageClick }: { src: string; alt?: string; onImageClick?: (src: string) => void }) {\r\n const [failed, setFailed] = useState(false);\r\n if (failed) {\r\n return (\r\n <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--hsk-chat-source-bg, rgba(0,0,0,.04))', color: 'var(--hsk-chat-muted, #888)' }}>\r\n <SparkleIcon />\r\n </div>\r\n );\r\n }\r\n return (\r\n <img\r\n src={src}\r\n alt={alt ?? ''}\r\n onError={() => setFailed(true)}\r\n onClick={onImageClick ? (e) => { e.stopPropagation(); onImageClick(src); } : undefined}\r\n />\r\n );\r\n}\r\n\r\nexport function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClick, referencedIds = [], compact = false }: SourcesCarouselProps) {\r\n const client = useAkropolysContext();\r\n const isProperty = client?.vertical === 'property';\r\n const railRef = useRef<HTMLDivElement>(null);\r\n const [showPrev, setShowPrev] = useState(false);\r\n const [showNext, setShowNext] = useState(false);\r\n const [activeIndex, setActiveIndex] = useState(0);\r\n\r\n const display = sources.filter(s => s.id && referencedIds.includes(s.id));\r\n\r\n const measure = useCallback(() => {\r\n const el = railRef.current;\r\n if (!el || display.length === 0) return;\r\n const travelled = Math.abs(el.scrollLeft);\r\n const maxScroll = el.scrollWidth - el.clientWidth;\r\n setShowPrev(travelled > 10);\r\n setShowNext(maxScroll > 4 && travelled < maxScroll - 12);\r\n\r\n const cardWidth = 190;\r\n const idx = Math.round(travelled / cardWidth);\r\n setActiveIndex(Math.min(Math.max(0, idx), display.length - 1));\r\n }, [display.length]);\r\n\r\n useEffect(() => {\r\n measure();\r\n const el = railRef.current;\r\n if (!el) return;\r\n const ro = new ResizeObserver(measure);\r\n ro.observe(el);\r\n el.addEventListener('scroll', measure, { passive: true });\r\n return () => { ro.disconnect(); el.removeEventListener('scroll', measure); };\r\n }, [measure, sources]);\r\n\r\n const railStep = (dir: 1 | -1) => {\r\n const el = railRef.current;\r\n if (!el) return;\r\n const rtl = getComputedStyle(el).direction === 'rtl';\r\n el.scrollBy({ left: 190 * dir * (rtl ? -1 : 1), behavior: 'smooth' });\r\n };\r\n\r\n const scrollNext = () => railStep(1);\r\n const scrollPrev = () => railStep(-1);\r\n\r\n if (display.length === 0) return null;\r\n\r\n return (\r\n <div className={cn(\"hsk-cb-sources-wrap\", compact && \"hsk-cb-sources-wrap--compact\")}>\r\n {showPrev && (\r\n <>\r\n <div className=\"hsk-cb-sources-fade-left\" />\r\n <button className=\"hsk-cb-sources-prev\" onClick={scrollPrev} aria-label=\"Previous\">\r\n <ChevronLeftIcon />\r\n </button>\r\n </>\r\n )}\r\n\r\n <div className=\"hsk-cb-sources\" ref={railRef}>\r\n {display.map((src, si) => {\r\n const isReferenced = !!(src.id && referencedIds.includes(src.id));\r\n return (\r\n <div\r\n key={src.id ?? si}\r\n className={cn(\"hsk-cb-source\", isReferenced && \"hsk-cb-source--referenced\")}\r\n style={{ animationDelay: `${si * 50}ms` }}\r\n onClick={() => onSelectSource?.(src)}\r\n >\r\n {src.image ? (\r\n <div className=\"hsk-cb-src-imgwrap\" style={{ position: 'relative' }}>\r\n <SourceImg src={src.image} alt={src.name} onImageClick={onImageClick} />\r\n {isProperty && (\r\n <div style={{\r\n position: 'absolute',\r\n top: '6px',\r\n right: '6px',\r\n background: 'rgba(14, 14, 15, 0.75)',\r\n backdropFilter: 'blur(4px)',\r\n borderRadius: '50%',\r\n width: '24px',\r\n height: '24px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n color: '#fbbf24',\r\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)'\r\n }}>\r\n <SparkleIcon size={12} />\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"hsk-cb-src-imgwrap-empty\" style={{ position: 'relative' }}>\r\n <SparkleIcon />\r\n </div>\r\n )}\r\n <div className=\"hsk-cb-src-info\">\r\n <div className=\"hsk-cb-src-name\">{src.name}</div>\r\n {src.price && (\r\n <div className=\"hsk-cb-src-price\">\r\n {(src.currency || defaultCurrency) ? `${src.currency || defaultCurrency} ` : '$'}\r\n {parseFloat(String(src.price).replace(/[^0-9.]/g, '') || '0').toLocaleString()}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n\r\n {showNext && (\r\n <>\r\n <div className=\"hsk-cb-sources-fade-right\" />\r\n <button className=\"hsk-cb-sources-next\" onClick={scrollNext} aria-label=\"See more\">\r\n <ChevronRightIcon />\r\n </button>\r\n </>\r\n )}\r\n\r\n {display.length > 1 && (\r\n <div className=\"hsk-cb-carousel-dots\">\r\n {display.map((_, i) => (\r\n <div\r\n key={i}\r\n className={cn(\"hsk-cb-dot-item\", i === activeIndex && \"hsk-cb-dot-item--active\")}\r\n onClick={() => {\r\n const el = railRef.current;\r\n if (el) {\r\n const rtl = getComputedStyle(el).direction === 'rtl';\r\n el.scrollTo({ left: i * 190 * (rtl ? -1 : 1), behavior: 'smooth' });\r\n }\r\n }}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\nimport type { ChatSource } from '@akropolys/sdk';\r\nimport { useT } from '../types';\r\n\r\nexport interface SmartContextPillsProps {\r\n intent: string | null;\r\n sources: ChatSource[];\r\n onSend: (text: string) => void;\r\n loading: boolean;\r\n defaultCurrency?: string;\r\n}\r\n\r\nexport function SmartContextPills({\r\n intent,\r\n sources,\r\n onSend,\r\n loading,\r\n defaultCurrency = '',\r\n}: SmartContextPillsProps) {\r\n const tr = useT();\r\n if (!intent) return null;\r\n\r\n const pills: { label: string; query: string; emoji: string }[] = [];\r\n\r\n const cheapest =\r\n sources.length > 0\r\n ? sources.reduce((min, s) => {\r\n const p = parseFloat(String(s.price ?? '').replace(/[^0-9.]/g, ''));\r\n const m = parseFloat(String(min.price ?? '').replace(/[^0-9.]/g, ''));\r\n return !isNaN(p) && (isNaN(m) || p < m) ? s : min;\r\n }, sources[0])\r\n : null;\r\n\r\n const firstName = sources[0]?.name ?? '';\r\n const firstTwo = sources.slice(0, 2).map(s => s.name);\r\n\r\n const priceCeiling = (): string | null => {\r\n const nums = sources\r\n .map(s => parseFloat(String(s.price ?? '').replace(/[^0-9.]/g, '')))\r\n .filter(n => !isNaN(n) && n > 0);\r\n if (nums.length === 0) return null;\r\n const max = Math.max(...nums);\r\n const mag = Math.pow(10, Math.floor(Math.log10(max)));\r\n const rounded = Math.ceil(max / mag) * mag;\r\n const raw = String(sources.find(s => s.price)?.price ?? '');\r\n const symbol = raw.replace(/[0-9.,\\s]/g, '') || defaultCurrency;\r\n return `${symbol} ${rounded.toLocaleString()}`.trim();\r\n };\r\n\r\n if (intent === 'search' && sources.length > 0) {\r\n if (firstTwo.length >= 2) {\r\n pills.push({\r\n emoji: '⚖️',\r\n label: tr('pillCompareTop2'),\r\n query: tr('pillCompareTop2Query', { a: firstTwo[0], b: firstTwo[1] }),\r\n });\r\n }\r\n if (cheapest?.name) {\r\n const short = cheapest.name.split(' ').slice(0, 3).join(' ');\r\n pills.push({\r\n emoji: '💡',\r\n label: tr('pillMoreOn', { name: short }),\r\n query: tr('pillMoreOnQuery', { name: cheapest.name }),\r\n });\r\n }\r\n const ceiling = priceCeiling();\r\n if (ceiling) {\r\n pills.push({\r\n emoji: '💰',\r\n label: tr('pillUnder', { amount: ceiling }),\r\n query: tr('pillUnderQuery', { amount: ceiling }),\r\n });\r\n }\r\n } else if (intent === 'compare' && sources.length > 0) {\r\n if (firstName) {\r\n pills.push({\r\n emoji: '🔍',\r\n label: tr('pillSimilarOptions'),\r\n query: tr('pillSimilarOptionsQuery', { name: firstName }),\r\n });\r\n }\r\n pills.push({ emoji: '💡', label: tr('pillWhichBest'), query: tr('pillWhichBestQuery') });\r\n } else if (intent === 'specs' && sources.length > 0) {\r\n if (firstName) {\r\n pills.push({\r\n emoji: '🔄',\r\n label: tr('pillFindAlternatives'),\r\n query: tr('pillFindAlternativesQuery', { name: firstName }),\r\n });\r\n }\r\n } else if (intent === 'general') {\r\n pills.push({ emoji: '🔍', label: tr('pillShowPopular'), query: tr('pillShowPopularQuery') });\r\n pills.push({ emoji: '💡', label: tr('pillRecommend'), query: tr('pillRecommendQuery') });\r\n }\r\n\r\n if (pills.length === 0) return null;\r\n\r\n return (\r\n <div className=\"hsk-action-pills\">\r\n {pills.map(pill => (\r\n <button\r\n key={pill.query}\r\n className=\"hsk-action-pill\"\r\n onClick={() => onSend(pill.query)}\r\n disabled={loading}\r\n >\r\n <span className=\"hsk-pill-emoji\">{pill.emoji}</span>\r\n {pill.label}\r\n </button>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\nimport { SparkleIcon } from '../icons';\r\nimport type { UIStringKey } from '../types';\r\n\r\nexport interface PromptKeyCardProps {\r\n keyInput: string;\r\n setKeyInput: (val: string) => void;\r\n minting: boolean;\r\n handleUseExistingKey: () => void;\r\n handleCreateKey: () => void;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n}\r\n\r\nexport function PromptKeyCard({\r\n keyInput,\r\n setKeyInput,\r\n minting,\r\n handleUseExistingKey,\r\n handleCreateKey,\r\n t,\r\n}: PromptKeyCardProps) {\r\n return (\r\n <div className=\"hsk-cb-ai-msg\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-ai-body\">\r\n <div className=\"hsk-cb-ai-text\">\r\n <div className=\"hsk-cb-phone-form\">\r\n <label className=\"hsk-cb-phone-label\">{t('keyPastePrompt')}</label>\r\n <input\r\n type=\"text\"\r\n className=\"hsk-cb-phone-input\"\r\n placeholder={t('keyPastePlaceholder')}\r\n value={keyInput}\r\n onChange={e => setKeyInput(e.target.value)}\r\n onKeyDown={e => e.key === 'Enter' && handleUseExistingKey()}\r\n autoFocus\r\n />\r\n <div style={{ display: 'flex', gap: 8 }}>\r\n <button className=\"hsk-cb-phone-submit\" onClick={handleUseExistingKey} disabled={!keyInput.trim()}>\r\n {t('keyUseMine')}\r\n </button>\r\n <button className=\"hsk-cb-phone-submit\" onClick={handleCreateKey} disabled={minting}>\r\n {minting ? t('keyCreating') : t('keyCreateNew')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport interface MintedKeyCardProps {\r\n mintedKey: string;\r\n mintedPub: string | null;\r\n copied: string | null;\r\n keyCountdown: number;\r\n onDismiss: () => void;\r\n copyValue: (val: string, type: 'secret' | 'pub') => void;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n}\r\n\r\nexport function MintedKeyCard({\r\n mintedKey,\r\n mintedPub,\r\n copied,\r\n keyCountdown,\r\n onDismiss,\r\n copyValue,\r\n t,\r\n}: MintedKeyCardProps) {\r\n return (\r\n <div className=\"hsk-cb-ai-msg\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-ai-body\">\r\n <div className=\"hsk-cb-ai-text\">\r\n <div style={{ padding: '4px 0', display: 'flex', flexDirection: 'column', gap: 12 }}>\r\n <div>\r\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>\r\n <span style={{ fontSize: 12, fontWeight: 600 }}>{t('keySecretTitle')}</span>\r\n <button\r\n className=\"hsk-cb-phone-submit\"\r\n style={{ padding: '2px 8px', fontSize: 11, background: 'transparent', border: 0 }}\r\n onClick={onDismiss}\r\n >\r\n {t('keyDismiss')} ✕\r\n </button>\r\n </div>\r\n <code style={{ display: 'block', fontSize: 13, fontWeight: 700, marginBottom: 8, wordBreak: 'break-all' }}>{mintedKey}</code>\r\n <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>\r\n <button className=\"hsk-cb-phone-submit\" style={{ padding: '4px 10px', border: 0 }} onClick={() => copyValue(mintedKey, 'secret')}>\r\n {copied === 'secret' ? t('keyCopied') : t('keyCopySecret')}\r\n </button>\r\n <span style={{ fontSize: 11, opacity: 0.7, flex: '1 1 180px' }}>\r\n {t('keySecretHint')}\r\n </span>\r\n </div>\r\n </div>\r\n {mintedPub && (\r\n <div>\r\n <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 4 }}>{t('keyPublicTitle')}</div>\r\n <code style={{ display: 'block', fontSize: 12, fontWeight: 600, marginBottom: 6, wordBreak: 'break-all', opacity: 0.85 }}>{mintedPub}</code>\r\n <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>\r\n <button className=\"hsk-cb-phone-submit\" style={{ padding: '4px 10px', border: 0 }} onClick={() => copyValue(mintedPub, 'pub')}>\r\n {copied === 'pub' ? t('keyCopied') : t('keyCopyId')}\r\n </button>\r\n <span style={{ fontSize: 11, opacity: 0.7, flex: '1 1 180px' }}>\r\n {t('keyPublicHint')}\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n <div style={{ fontSize: 11, opacity: 0.6 }}>{t('keyAutoHide', { seconds: String(keyCountdown) })}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\nimport type { ChatMessage, ChatSource, ChatAction } from '@akropolys/sdk';\r\nimport { cn } from '../../utils/cn';\r\nimport { ContinueIcon } from './icons';\r\nimport { getFriendlyError, type UIStringKey } from './types';\r\nimport { MessageItem } from './components/MessageItem';\r\nimport { PromptKeyCard, MintedKeyCard } from './components/MemoryKeyCards';\r\n\r\nexport interface ChatMessagesProps {\r\n displayMessages: ChatMessage[];\r\n messageRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;\r\n isNarrow: boolean;\r\n loading: boolean;\r\n streaming: boolean;\r\n sources: ChatSource[];\r\n referencedIds: string[];\r\n discussedSources: ChatSource[];\r\n lastIntent: string | null;\r\n lastAction: ChatAction | null;\r\n defaultCurrency: string;\r\n stopped: boolean;\r\n interrupted: boolean;\r\n halted: boolean;\r\n haltedEmpty: boolean;\r\n error: string | null;\r\n errorCode: string | null;\r\n keyPhase: string;\r\n keyInput: string;\r\n setKeyInput: (val: string) => void;\r\n mintedKey: string | null;\r\n setMintedKey: (val: string | null) => void;\r\n mintedPub: string | null;\r\n setMintedPub: (val: string | null) => void;\r\n minting: boolean;\r\n copied: string | null;\r\n keyCountdown: number;\r\n handleUseExistingKey: () => void;\r\n handleCreateKey: () => void;\r\n copyValue: (val: string, type: 'secret' | 'pub') => void;\r\n queuedMessage: ChatMessage | null;\r\n sendQueuedNow: () => void;\r\n setLightboxSrc: (src: string | null) => void;\r\n setMarkupSrc: (src: string | null) => void;\r\n handleSend: (text?: string) => Promise<void>;\r\n handleSourceClick: (src: ChatSource) => void;\r\n continueGenerating: () => void;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n bottomRef: React.RefObject<HTMLDivElement | null>;\r\n vizState: Record<string, 'ok' | 'err'>;\r\n setVizState: React.Dispatch<React.SetStateAction<Record<string, 'ok' | 'err'>>>;\r\n messages: ChatMessage[];\r\n}\r\n\r\nexport function ChatMessages({\r\n displayMessages,\r\n messageRefs,\r\n isNarrow,\r\n loading,\r\n streaming,\r\n sources,\r\n referencedIds,\r\n discussedSources,\r\n lastIntent,\r\n lastAction,\r\n defaultCurrency,\r\n stopped,\r\n interrupted,\r\n halted,\r\n haltedEmpty,\r\n error,\r\n errorCode,\r\n keyPhase,\r\n keyInput,\r\n setKeyInput,\r\n mintedKey,\r\n setMintedKey,\r\n mintedPub,\r\n setMintedPub,\r\n minting,\r\n copied,\r\n keyCountdown,\r\n handleUseExistingKey,\r\n handleCreateKey,\r\n copyValue,\r\n queuedMessage,\r\n sendQueuedNow,\r\n setLightboxSrc,\r\n setMarkupSrc,\r\n handleSend,\r\n handleSourceClick,\r\n continueGenerating,\r\n t,\r\n bottomRef,\r\n vizState,\r\n setVizState,\r\n messages,\r\n}: ChatMessagesProps) {\r\n return (\r\n <>\r\n {(() => {\r\n let lastUserIdx = -1;\r\n for (let i = displayMessages.length - 1; i >= 0; i--) {\r\n if (displayMessages[i]?.role === 'user') {\r\n lastUserIdx = i;\r\n break;\r\n }\r\n }\r\n return displayMessages.map((msg: ChatMessage, idx: number) => {\r\n const isLast = idx === displayMessages.length - 1;\r\n const isUser = msg.role === 'user';\r\n const isLastUser = isUser && idx === lastUserIdx;\r\n const isRunEnd = isUser && displayMessages[idx + 1]?.role !== 'user';\r\n const runMid = isUser && !isRunEnd;\r\n const runCont = isUser && displayMessages[idx - 1]?.role === 'user';\r\n const key = (msg as any).id || `${msg.role}-${idx}`;\r\n\r\n return (\r\n <MessageItem\r\n key={key}\r\n msg={msg}\r\n idx={idx}\r\n isLast={isLast}\r\n isLastUser={isLastUser}\r\n isRunEnd={isRunEnd}\r\n runMid={runMid}\r\n runCont={runCont}\r\n isNarrow={isNarrow}\r\n loading={loading}\r\n streaming={streaming}\r\n stopped={stopped}\r\n interrupted={interrupted}\r\n sources={sources}\r\n referencedIds={referencedIds}\r\n discussedSources={discussedSources}\r\n lastIntent={lastIntent}\r\n lastAction={lastAction}\r\n defaultCurrency={defaultCurrency}\r\n vizState={vizState}\r\n setVizState={setVizState}\r\n setLightboxSrc={setLightboxSrc}\r\n setMarkupSrc={setMarkupSrc}\r\n handleSend={handleSend}\r\n handleSourceClick={handleSourceClick}\r\n t={t}\r\n messageRef={(el) => { messageRefs.current[idx] = el; }}\r\n />\r\n );\r\n });\r\n })()}\r\n\r\n {halted && messages.length > 0 && (\r\n <div className={cn(\"hsk-cb-stopped\", haltedEmpty && \"hsk-cb-stopped--empty\")}>\r\n {haltedEmpty && (\r\n <span className=\"hsk-cb-stopped-dots\" aria-hidden=\"true\">\r\n <i /><i /><i />\r\n </span>\r\n )}\r\n <span className=\"hsk-cb-stopped-label\">\r\n {stopped ? t('stoppedByYou') : t('stoppedInterrupted')}\r\n </span>\r\n <button className=\"hsk-cb-continue\" onClick={continueGenerating}>\r\n <ContinueIcon />\r\n {t(messages[messages.length - 1]?.role === 'assistant' ? 'continueGenerating' : 'generateResponse')}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {error && <div className=\"hsk-cb-error\">{getFriendlyError({ code: errorCode ?? undefined, message: error }, t)}</div>}\r\n\r\n {keyPhase === 'prompt_key' && (\r\n <PromptKeyCard\r\n keyInput={keyInput}\r\n setKeyInput={setKeyInput}\r\n minting={minting}\r\n handleUseExistingKey={handleUseExistingKey}\r\n handleCreateKey={handleCreateKey}\r\n t={t}\r\n />\r\n )}\r\n\r\n {mintedKey && (\r\n <MintedKeyCard\r\n mintedKey={mintedKey}\r\n mintedPub={mintedPub}\r\n copied={copied}\r\n keyCountdown={keyCountdown}\r\n onDismiss={() => { setMintedKey(null); setMintedPub(null); }}\r\n copyValue={copyValue}\r\n t={t}\r\n />\r\n )}\r\n\r\n {queuedMessage && (\r\n <div className={cn(\r\n 'hsk-cb-msg-group',\r\n displayMessages[displayMessages.length - 1]?.role === 'user' && 'hsk-cb-msg-group--run-cont',\r\n )}>\r\n <div className=\"hsk-cb-user-msg\">\r\n <div className=\"hsk-cb-user-bubble hsk-cb-user-bubble--tail hsk-cb-user-bubble--queued\">\r\n {queuedMessage.content}\r\n </div>\r\n <button type=\"button\" className=\"hsk-cb-queued-status\" onClick={sendQueuedNow}>\r\n <span className=\"hsk-cb-queued-dot\" />\r\n {t('queuedWaiting')}\r\n <span className=\"hsk-cb-queued-now\">{t('queuedSendNow')}</span>\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div ref={bottomRef as any} style={{ height: 1 }} />\r\n </>\r\n );\r\n}\r\n","import React, { useState, useRef, useEffect } from 'react';\r\nimport type { ChatSource, ChatAttachment } from '@akropolys/sdk';\r\nimport { cn } from '../../utils/cn';\r\nimport {\r\n SparkleIcon,\r\n BookmarkIcon,\r\n HistoryIcon,\r\n TrashIcon,\r\n PaperclipIcon,\r\n WaveformIcon,\r\n MicIcon,\r\n MicOffIcon,\r\n StopIcon,\r\n ArrowUpIcon,\r\n PlusIcon,\r\n XIcon,\r\n} from './icons';\r\nimport { ListeningWave } from './components/ListeningWave';\r\nimport { AnimatedPlaceholder, HSK_STAGGER_MS, splitPlaceholder } from './components/AnimatedPlaceholder';\r\nimport type { UIStringKey, VoicePhase } from './types';\r\n\r\nexport interface ChatComposerProps {\r\n gooId: string;\r\n input: string;\r\n setInput: React.Dispatch<React.SetStateAction<string>>;\r\n showKikuPicker: boolean;\r\n setShowKikuPicker: (show: boolean) => void;\r\n showAtPicker: boolean;\r\n setShowAtPicker: (show: boolean) => void;\r\n captureAllowed: boolean;\r\n discussedSources: ChatSource[];\r\n defaultCurrency: string;\r\n handleSelectExtension: (ext: string) => void;\r\n handleKikuCapture: (product: ChatSource) => void;\r\n handleKikuCaptureAll: (products: ChatSource[]) => void;\r\n handleKikuViewHistory: () => void;\r\n handleKikuDelete: () => void;\r\n attachments: ChatAttachment[];\r\n removeAttachment: (idx: number) => void;\r\n chromeLoading: boolean;\r\n imageInputRef: React.RefObject<HTMLInputElement | null>;\r\n handleImageFiles: (files: FileList | null) => void;\r\n enableVision: boolean;\r\n enableVoice: boolean;\r\n canConverse: boolean;\r\n voiceMode: 'off' | 'dictate' | 'converse';\r\n startVoice: (mode: 'dictate' | 'converse') => void;\r\n stopVoice: () => void;\r\n voiceBlocked: boolean;\r\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\r\n classNames?: { input?: string; sendButton?: string };\r\n handleInput: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\r\n handleKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\r\n voice: {\r\n active: boolean;\r\n supported: boolean;\r\n spectrumBins: () => number;\r\n micSpectrum: (out: Uint8Array) => boolean;\r\n };\r\n voicePhase: VoicePhase;\r\n activePlaceholder: string;\r\n loading: boolean;\r\n streaming: boolean;\r\n stop: () => void;\r\n handleSend: (text?: string) => Promise<void>;\r\n voiceError: string;\r\n setVoiceError?: (err: string) => void;\r\n shopperLanguage: string;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n rail?: React.ReactNode;\r\n}\r\n\r\nexport function ChatComposer({\r\n gooId,\r\n input,\r\n setInput,\r\n showKikuPicker,\r\n setShowKikuPicker,\r\n showAtPicker,\r\n setShowAtPicker,\r\n captureAllowed,\r\n discussedSources,\r\n defaultCurrency,\r\n handleSelectExtension,\r\n handleKikuCapture,\r\n handleKikuCaptureAll,\r\n handleKikuViewHistory,\r\n handleKikuDelete,\r\n attachments,\r\n removeAttachment,\r\n chromeLoading,\r\n imageInputRef,\r\n handleImageFiles,\r\n enableVision,\r\n enableVoice,\r\n canConverse,\r\n voiceMode,\r\n startVoice,\r\n stopVoice,\r\n voiceBlocked,\r\n textareaRef,\r\n classNames = {},\r\n handleInput,\r\n handleKeyDown,\r\n voice,\r\n voicePhase,\r\n activePlaceholder,\r\n loading,\r\n streaming,\r\n stop,\r\n handleSend,\r\n voiceError,\r\n setVoiceError,\r\n shopperLanguage,\r\n t,\r\n rail,\r\n}: ChatComposerProps) {\r\n const [placeholderReplay, setPlaceholderReplay] = React.useState(0);\r\n const [toolsOpen, setToolsOpen] = React.useState(false);\r\n\r\n React.useEffect(() => {\r\n if (!voiceError) return;\r\n const timer = setTimeout(() => {\r\n setVoiceError?.('');\r\n }, 6000);\r\n return () => clearTimeout(timer);\r\n }, [voiceError, setVoiceError]);\r\n\r\n React.useEffect(() => {\r\n if (!toolsOpen) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setToolsOpen(false);\r\n };\r\n window.addEventListener('keydown', onKey);\r\n return () => window.removeEventListener('keydown', onKey);\r\n }, [toolsOpen]);\r\n\r\n const placeholderText = activePlaceholder || 'Ask me anything…';\r\n const placeholderSweepMs =\r\n Math.max(splitPlaceholder(placeholderText).length - 1, 0) * HSK_STAGGER_MS;\r\n\r\n // the kite tears through the seam, the seam heals, a fresh kite glides in\r\n const [launching, setLaunching] = useState(false);\r\n const launchTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const launch = () => {\r\n if (launchTimer.current) clearTimeout(launchTimer.current);\r\n setLaunching(true);\r\n launchTimer.current = setTimeout(() => {\r\n setLaunching(false);\r\n launchTimer.current = null;\r\n }, 550);\r\n };\r\n useEffect(() => () => { if (launchTimer.current) clearTimeout(launchTimer.current); }, []);\r\n\r\n return (\r\n <div className=\"hsk-cb-input-wrap\">\r\n {toolsOpen && (\r\n <>\r\n <div className=\"hsk-cb-toolsheet-scrim\" onClick={() => setToolsOpen(false)} />\r\n <div className=\"hsk-cb-toolsheet-wrap\">\r\n <div className=\"hsk-cb-toolsheet\" role=\"menu\">\r\n {enableVision && (\r\n <button\r\n className=\"hsk-cb-toolsheet-item\"\r\n role=\"menuitem\"\r\n onClick={() => { setToolsOpen(false); imageInputRef.current?.click(); }}\r\n disabled={loading}\r\n >\r\n <PaperclipIcon />\r\n <span>{t('attachImage')}</span>\r\n </button>\r\n )}\r\n {enableVoice && canConverse && (\r\n <button\r\n className=\"hsk-cb-toolsheet-item\"\r\n role=\"menuitem\"\r\n onClick={() => { setToolsOpen(false); voiceMode === 'converse' ? stopVoice() : startVoice('converse'); }}\r\n disabled={loading || chromeLoading || voiceBlocked}\r\n >\r\n <WaveformIcon active={voiceMode === 'converse'} />\r\n <span>{voiceMode === 'converse' ? t('voiceModeExit') : t('voiceModeStart')}</span>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n <div className=\"hsk-cb-input-card\">\r\n {(/^@kiku\\b/i.test(input) || showKikuPicker || showAtPicker) && (\r\n <div className=\"hsk-cb-docked-header\">\r\n <span className=\"hsk-cb-docked-sub\">{t('captureAndRemember')}</span>\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-close\"\r\n onClick={() => {\r\n setInput(prev => prev.replace(/^@kiku\\s*/i, ''));\r\n setShowKikuPicker(false);\r\n setShowAtPicker(false);\r\n }}\r\n aria-label=\"Close mode\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n )}\r\n\r\n {(showKikuPicker || showAtPicker) && (\r\n <div className=\"hsk-cb-docked-options\" onMouseDown={e => e.preventDefault()}>\r\n {showAtPicker && captureAllowed && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => handleSelectExtension('@kiku')}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\"><SparkleIcon /></span>\r\n <span className=\"hsk-cb-docked-option-title\">kiku</span>\r\n <span className=\"hsk-cb-docked-option-desc\">capture &amp; remember</span>\r\n </button>\r\n )}\r\n\r\n {showKikuPicker && captureAllowed && (\r\n <>\r\n {discussedSources.map((src, i) => (\r\n <button\r\n key={src.id ?? i}\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => { handleKikuCapture(src); setShowKikuPicker(false); }}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\">\r\n {src.image ? <img src={src.image} alt=\"\" /> : <BookmarkIcon />}\r\n </span>\r\n <span className=\"hsk-cb-docked-option-title\">{src.name}</span>\r\n {src.price && (\r\n <span className=\"hsk-cb-docked-option-price\">\r\n {src.currency ?? defaultCurrency} {parseFloat(String(src.price).replace(/[^0-9.]/g, '') || '0').toLocaleString()}\r\n </span>\r\n )}\r\n </button>\r\n ))}\r\n {discussedSources.length > 1 && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => { handleKikuCaptureAll(discussedSources); setShowKikuPicker(false); }}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\"><BookmarkIcon /></span>\r\n <span className=\"hsk-cb-docked-option-title\">{t('captureAll', { count: String(discussedSources.length) })}</span>\r\n </button>\r\n )}\r\n {discussedSources.length === 0 && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => { handleKikuCapture({ name: 'current page', id: undefined }); setShowKikuPicker(false); }}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\"><BookmarkIcon /></span>\r\n <span className=\"hsk-cb-docked-option-title\">{t('captureCurrentPage')}</span>\r\n </button>\r\n )}\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => { handleKikuViewHistory(); setShowKikuPicker(false); }}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\"><HistoryIcon /></span>\r\n <span className=\"hsk-cb-docked-option-title\">{t('whatHaveYouSaved')}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-docked-option\"\r\n onClick={() => { handleKikuDelete(); setShowKikuPicker(false); }}\r\n >\r\n <span className=\"hsk-cb-docked-option-icon\"><TrashIcon /></span>\r\n <span className=\"hsk-cb-docked-option-title\">{t('deleteThis')}</span>\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n\r\n {attachments.length > 0 && (\r\n <div className=\"hsk-cb-img-strip\">\r\n {attachments.map((att, i) => (\r\n <div key={i} className=\"hsk-cb-img-thumb-wrap\">\r\n <img src={att.data} alt={`attachment ${i + 1}`} className=\"hsk-cb-img-thumb\" />\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-img-thumb-remove\"\r\n onClick={() => removeAttachment(i)}\r\n aria-label=\"Remove image\"\r\n >\r\n <XIcon size={10} />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div\r\n className={cn(\"hsk-cb-input-box\", chromeLoading && \"hsk-cb-input-box--waiting\")}\r\n data-cascade={placeholderReplay % 2 ? 'b' : 'a'}\r\n data-tools={toolsOpen ? 'open' : 'closed'}\r\n style={{ '--hsk-text-sweep': `${placeholderSweepMs}ms` } as React.CSSProperties}\r\n >\r\n <input\r\n ref={imageInputRef as any}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n className=\"hsk-sr-only\"\r\n onChange={e => {\r\n handleImageFiles(e.target.files);\r\n e.target.value = '';\r\n }}\r\n />\r\n {(enableVision || (enableVoice && canConverse)) && (\r\n <button\r\n className={cn('hsk-cb-tools-toggle', toolsOpen && 'hsk-cb-tools-toggle--open')}\r\n onClick={() => setToolsOpen(o => !o)}\r\n disabled={loading || chromeLoading}\r\n aria-label={toolsOpen ? 'Close options' : 'More options'}\r\n aria-expanded={toolsOpen}\r\n >\r\n <PlusIcon />\r\n </button>\r\n )}\r\n <>\r\n {enableVision && (\r\n <button\r\n className=\"hsk-cb-attach-btn\"\r\n onClick={() => imageInputRef.current?.click()}\r\n disabled={loading}\r\n aria-label=\"Attach image\"\r\n title=\"Attach image\"\r\n >\r\n <PaperclipIcon />\r\n </button>\r\n )}\r\n {enableVoice && canConverse && (\r\n <button\r\n className={cn(\"hsk-cb-voice-mode-btn\", voiceBlocked && \"hsk-cb-voice-mode-btn--blocked\")}\r\n onClick={() => voiceBlocked ? setVoiceError?.(t('errAccountRequired')) : startVoice('converse')}\r\n disabled={loading || chromeLoading}\r\n aria-label=\"Voice conversation\"\r\n title=\"Voice conversation\"\r\n >\r\n <WaveformIcon />\r\n </button>\r\n )}\r\n </>\r\n <div className=\"hsk-cb-field\">\r\n <textarea\r\n ref={textareaRef as any}\r\n value={input}\r\n onChange={handleInput}\r\n onKeyDown={handleKeyDown}\r\n rows={1}\r\n placeholder=\"\"\r\n className={cn(\"hsk-cb-textarea\", classNames.input)}\r\n aria-label={activePlaceholder}\r\n disabled={loading && !streaming}\r\n />\r\n <AnimatedPlaceholder\r\n placeholder={activePlaceholder}\r\n visible={!input}\r\n staggerMs={HSK_STAGGER_MS}\r\n replaySeed={placeholderReplay}\r\n />\r\n </div>\r\n {enableVoice && (\r\n <button\r\n className={cn(\"hsk-cb-mic-btn\", voiceMode === 'dictate' && \"hsk-cb-mic-btn--active\", voiceBlocked && \"hsk-cb-mic-btn--blocked\")}\r\n onClick={() => voiceMode === 'off' ? startVoice('dictate') : stopVoice()}\r\n disabled={loading || chromeLoading}\r\n aria-label={voiceMode === 'off' ? 'Start voice input' : 'Stop recording'}\r\n title={voiceMode === 'off' ? 'Voice input' : 'Stop'}\r\n >\r\n {voiceMode === 'off' ? <MicIcon /> : <MicOffIcon />}\r\n </button>\r\n )}\r\n {(loading || streaming) && !launching ? (\r\n <button\r\n className={cn(\"hsk-cb-send\", \"hsk-cb-send--stop\", classNames.sendButton)}\r\n onClick={stop}\r\n aria-label=\"Stop generating\"\r\n title=\"Stop generating\"\r\n >\r\n <StopIcon />\r\n </button>\r\n ) : (\r\n <button\r\n className={cn(\"hsk-cb-send\", launching && \"is-launching\", classNames.sendButton)}\r\n onClick={() => { launch(); handleSend(); }}\r\n disabled={chromeLoading || (!input.trim() && attachments.length === 0)}\r\n aria-label=\"Send message\"\r\n >\r\n <svg width=\"0\" height=\"0\" aria-hidden=\"true\" focusable=\"false\" style={{ position: 'absolute' }}>\r\n <defs>\r\n <filter id={gooId}>\r\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"1.6\" result=\"blur\" />\r\n <feColorMatrix in=\"blur\" type=\"matrix\"\r\n values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 16 -7\" result=\"goo\" />\r\n <feBlend in=\"SourceGraphic\" in2=\"goo\" />\r\n </filter>\r\n </defs>\r\n </svg>\r\n <span className=\"hsk-cb-send-sheath\" aria-hidden=\"true\" />\r\n <span className=\"hsk-cb-send-stage\" style={{ filter: `url(#${gooId})` }}>\r\n <span className=\"hsk-cb-send-seam\" aria-hidden=\"true\" />\r\n <span className=\"hsk-cb-send-kite\">\r\n <ArrowUpIcon />\r\n </span>\r\n </span>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n {voiceBlocked ? (\r\n <div className=\"hsk-cb-voice-error\" role=\"status\" onClick={() => setVoiceError?.('')}>\r\n <span>{t('errAccountRequired')}</span>\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-voice-error-dismiss\"\r\n onClick={(e) => { e.stopPropagation(); setVoiceError?.(''); }}\r\n aria-label=\"Dismiss error\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n ) : voiceError && (\r\n <div className=\"hsk-cb-voice-error\" role=\"status\" onClick={() => setVoiceError?.('')}>\r\n <span>{t(voiceError as UIStringKey)}</span>\r\n <button\r\n type=\"button\"\r\n className=\"hsk-cb-voice-error-dismiss\"\r\n onClick={(e) => { e.stopPropagation(); setVoiceError?.(''); }}\r\n aria-label=\"Dismiss error\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n )}\r\n <div className=\"hsk-cb-hint\">{shopperLanguage ? t('footerHint') : 'kiku · searches the whole catalogue in real time'}</div>\r\n </div>\r\n );\r\n}\r\n","import React, { useEffect, useRef } from 'react';\r\nimport type { VoicePhase } from '../utils/voiceSession';\r\n\r\nexport interface VoiceCanvasProps {\r\n phase: VoicePhase;\r\n\r\n level: () => number;\r\n\r\n spectrum?: (out: Uint8Array) => boolean;\r\n\r\n bins?: () => number;\r\n className?: string;\r\n}\r\n\r\ntype RGB = [number, number, number];\r\n\r\nfunction parseColor(css: string, fallback: RGB): RGB {\r\n const m = css.match(/-?[\\d.]+/g);\r\n if (!m || m.length < 3) return fallback;\r\n return [Number(m[0]), Number(m[1]), Number(m[2])];\r\n}\r\n\r\nfunction mix(a: RGB, b: RGB, t: number): RGB {\r\n return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];\r\n}\r\n\r\nfunction rgba(c: RGB, alpha: number): string {\r\n return `rgba(${c[0] | 0}, ${c[1] | 0}, ${c[2] | 0}, ${alpha})`;\r\n}\r\n\r\nconst BANDS = 24;\r\nconst SPECTRUM_FRACTION = 0.42;\r\n\r\nexport function VoiceCanvas({ phase, level, spectrum, bins, className }: VoiceCanvasProps) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const phaseRef = useRef(phase);\r\n const levelRef = useRef(level);\r\n const spectrumRef = useRef(spectrum);\r\n const binsRef = useRef(bins);\r\n useEffect(() => { phaseRef.current = phase; }, [phase]);\r\n useEffect(() => { levelRef.current = level; }, [level]);\r\n useEffect(() => { spectrumRef.current = spectrum; }, [spectrum]);\r\n useEffect(() => { binsRef.current = bins; }, [bins]);\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n\r\n const style = getComputedStyle(canvas);\r\n const accent = parseColor(style.getPropertyValue('--hsk-primary') || '', [255, 106, 51]);\r\n const ink = parseColor(style.getPropertyValue('--hsk-chat-text') || '', [31, 31, 31]);\r\n\r\n let raf = 0;\r\n let w = 0;\r\n let h = 0;\r\n\r\n const resize = () => {\r\n const dpr = Math.min(window.devicePixelRatio || 1, 3);\r\n const rect = canvas.getBoundingClientRect();\r\n w = Math.max(1, rect.width);\r\n h = Math.max(1, rect.height);\r\n canvas.width = Math.round(w * dpr);\r\n canvas.height = Math.round(h * dpr);\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n };\r\n resize();\r\n const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(resize) : null;\r\n ro?.observe(canvas);\r\n window.addEventListener('resize', resize);\r\n\r\n const reduced = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false;\r\n\r\n const bands = new Float32Array(BANDS);\r\n let strokes: CanvasGradient[] = [];\r\n let glow: CanvasGradient | null = null;\r\n let strokesFor = -1;\r\n let freqBuf: Uint8Array | null = null;\r\n let amp = 0;\r\n let sweep = 0;\r\n const start = performance.now();\r\n\r\n const follow = (cur: number, target: number, attack: number, release: number) =>\r\n cur + (target - cur) * (target > cur ? attack : release);\r\n\r\n const readSpectrum = () => {\r\n const read = spectrumRef.current;\r\n const n = binsRef.current?.() ?? 0;\r\n if (!read || !n) return false;\r\n if (!freqBuf || freqBuf.length !== n) freqBuf = new Uint8Array(n);\r\n if (!read(freqBuf)) return false;\r\n\r\n const usable = Math.max(BANDS, Math.floor(n * SPECTRUM_FRACTION));\r\n const per = usable / BANDS;\r\n for (let b = 0; b < BANDS; b++) {\r\n const from = Math.floor(b * per);\r\n const to = Math.max(from + 1, Math.floor((b + 1) * per));\r\n let sum = 0;\r\n for (let i = from; i < to; i++) sum += freqBuf[i];\r\n const v = sum / (to - from) / 255;\r\n bands[b] = follow(bands[b], v, reduced ? 0.2 : 0.55, reduced ? 0.06 : 0.14);\r\n }\r\n return true;\r\n };\r\n\r\n const synthesizeBands = (t: number, energy: number) => {\r\n for (let b = 0; b < BANDS; b++) {\r\n const m = b / (BANDS - 1);\r\n const shape = Math.pow(1 - m, 1.6) * (0.75 + 0.25 * Math.sin(t * 3.1 + b * 0.7));\r\n bands[b] = follow(bands[b], shape * energy, 0.3, 0.12);\r\n }\r\n };\r\n\r\n const bandAt = (m: number) => {\r\n const x = Math.min(BANDS - 1, Math.max(0, m * (BANDS - 1)));\r\n const i = Math.floor(x);\r\n const f = x - i;\r\n const a = bands[i];\r\n const b = bands[Math.min(BANDS - 1, i + 1)];\r\n return a + (b - a) * f * f * (3 - 2 * f);\r\n };\r\n\r\n const draw = (now: number) => {\r\n raf = requestAnimationFrame(draw);\r\n const t = (now - start) / 1000;\r\n const p = phaseRef.current;\r\n\r\n const live = Math.min(1, levelRef.current());\r\n const floor = p === 'speaking' ? 0.42 : p === 'listening' ? 0.3 : p === 'thinking' ? 0.28 : 0.12;\r\n amp = follow(amp, Math.max(floor, live), reduced ? 0.1 : 0.5, reduced ? 0.05 : 0.11);\r\n\r\n if (!readSpectrum()) synthesizeBands(t, Math.max(0.25, amp));\r\n\r\n ctx.clearRect(0, 0, w, h);\r\n const cy = h / 2;\r\n\r\n sweep = p === 'thinking' ? (sweep + 0.012) % 1.6 : 0;\r\n\r\n const layers = 3;\r\n if (strokesFor !== w) {\r\n strokes = [];\r\n for (let l = 0; l < layers; l++) {\r\n const depth = l / (layers - 1 || 1);\r\n const hue = mix(accent, ink, depth * 0.5);\r\n const g = ctx.createLinearGradient(0, 0, w, 0);\r\n g.addColorStop(0, rgba(hue, 0));\r\n g.addColorStop(0.5, rgba(hue, 0.9 - depth * 0.35));\r\n g.addColorStop(1, rgba(hue, 0));\r\n strokes.push(g);\r\n }\r\n glow = ctx.createLinearGradient(0, 0, w, 0);\r\n glow.addColorStop(0, rgba(accent, 0));\r\n glow.addColorStop(0.5, rgba(accent, 0.14));\r\n glow.addColorStop(1, rgba(accent, 0));\r\n strokesFor = w;\r\n }\r\n const maxAmp = h * 0.32;\r\n const step = Math.max(4, w / 130);\r\n\r\n for (let l = 0; l < layers; l++) {\r\n const depth = l / (layers - 1 || 1);\r\n const lag = l * 0.055;\r\n const scale = 1 - depth * 0.22;\r\n\r\n ctx.beginPath();\r\n let px = 0;\r\n let py = cy;\r\n for (let x = 0; x <= w; x += step) {\r\n const u = x / w;\r\n const envelope = Math.pow(Math.sin(Math.PI * u), 0.85);\r\n const focus = p === 'thinking'\r\n ? Math.exp(-Math.pow((u - (sweep - 0.3)) * 4.5, 2))\r\n : 1;\r\n\r\n const band = bandAt(Math.abs(u - 0.5) * 2);\r\n const tl = t - lag;\r\n const ripple =\r\n Math.sin(u * Math.PI * 2 * 2.1 + tl * 7.4) * 0.66 +\r\n Math.sin(u * Math.PI * 2 * 3.7 - tl * 5.6) * 0.26 +\r\n Math.sin(u * Math.PI * 2 * 5.9 + tl * 9.1) * 0.08;\r\n\r\n const y =\r\n cy +\r\n envelope * focus * scale * maxAmp * amp * (0.6 + band * 1.1) * ripple +\r\n Math.sin(u * Math.PI * 2 * 0.6 + (t - lag) * 2.2) * envelope * h * 0.01;\r\n\r\n if (x === 0) {\r\n ctx.moveTo(x, y);\r\n } else {\r\n ctx.quadraticCurveTo(px, py, (px + x) / 2, (py + y) / 2);\r\n }\r\n px = x;\r\n py = y;\r\n }\r\n ctx.quadraticCurveTo(px, py, w, py);\r\n\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n const width = (l === 0 ? 3 : 1.6) * (1 + amp * 0.6);\r\n if (l === 0) {\r\n ctx.strokeStyle = glow!;\r\n ctx.lineWidth = width * 5;\r\n ctx.stroke();\r\n }\r\n ctx.strokeStyle = strokes[l];\r\n ctx.lineWidth = width;\r\n ctx.stroke();\r\n }\r\n };\r\n\r\n raf = requestAnimationFrame(draw);\r\n return () => {\r\n cancelAnimationFrame(raf);\r\n ro?.disconnect();\r\n window.removeEventListener('resize', resize);\r\n };\r\n }, []);\r\n\r\n return <canvas ref={canvasRef} className={className} aria-hidden=\"true\" />;\r\n}\r\n","import React from 'react';\r\nimport type { ChatSource } from '@akropolys/sdk';\r\nimport { cn } from '../../utils/cn';\r\nimport { SparkleIcon, CloseIcon, MicIcon, MicOffIcon } from './icons';\r\nimport { LIVE_VOICES, type UIStringKey, type VoicePhase } from './types';\r\nimport { VoiceCanvas } from '../VoiceCanvas';\r\nimport KikuDoodles from '../KikuDoodles';\r\n\r\nexport interface VoiceOverlayProps {\r\n siteId: string;\r\n themeAttr?: 'light' | 'dark' | string;\r\n stopVoice: () => void;\r\n chooseVoice: (name: string) => void;\r\n liveVoiceName: string;\r\n voiceSecondsLeft: number | null;\r\n voiceConnecting: boolean;\r\n voicePhase: VoicePhase;\r\n live: {\r\n micLevel: () => number;\r\n micSpectrum: (out: Uint8Array) => boolean;\r\n spectrumBins: () => number;\r\n };\r\n voiceMuted: boolean;\r\n setVoiceMuted: React.Dispatch<React.SetStateAction<boolean>>;\r\n shownSources: ChatSource[];\r\n onSelectSource?: (src: ChatSource) => void;\r\n defaultCurrency: string;\r\n voiceError: string;\r\n t: (key: UIStringKey, vars?: Record<string, string>) => string;\r\n}\r\n\r\nexport function VoiceOverlay({\r\n siteId,\r\n themeAttr,\r\n stopVoice,\r\n chooseVoice,\r\n liveVoiceName,\r\n voiceSecondsLeft,\r\n voiceConnecting,\r\n voicePhase,\r\n live,\r\n voiceMuted,\r\n setVoiceMuted,\r\n shownSources,\r\n onSelectSource,\r\n defaultCurrency,\r\n voiceError,\r\n t,\r\n}: VoiceOverlayProps) {\r\n return (\r\n <div className=\"hsk-voice-overlay\" role=\"dialog\" aria-label={t('voiceModeStart')}>\r\n <KikuDoodles seed={siteId} theme={themeAttr} />\r\n\r\n <button\r\n className=\"hsk-voice-exit\"\r\n onClick={stopVoice}\r\n aria-label={t('voiceModeExit')}\r\n title={t('voiceModeExit')}\r\n >\r\n <CloseIcon />\r\n </button>\r\n\r\n <div className=\"hsk-voice-picker\" role=\"radiogroup\" aria-label={t('voicePickerLabel')}>\r\n {LIVE_VOICES.map((v, i) => (\r\n <button\r\n key={v.name}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={liveVoiceName === v.name}\r\n className={cn('hsk-voice-pill', liveVoiceName === v.name && 'hsk-voice-pill--on')}\r\n style={{ animationDelay: `${i * 60}ms` }}\r\n onClick={() => chooseVoice(v.name)}\r\n aria-label={`${v.label}, ${v.gender}`}\r\n >\r\n {v.label}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {voiceSecondsLeft !== null && (\r\n <div\r\n className={cn('hsk-voice-allowance', voiceSecondsLeft <= 5 && 'hsk-voice-allowance--low')}\r\n role=\"timer\"\r\n aria-live=\"off\"\r\n >\r\n {Math.max(0, Math.ceil(voiceSecondsLeft))}s\r\n </div>\r\n )}\r\n\r\n <div className={cn('hsk-voice-stage', voiceConnecting && 'hsk-voice-stage--connecting')}>\r\n <VoiceCanvas\r\n className=\"hsk-voice-canvas\"\r\n phase={voicePhase}\r\n level={live.micLevel}\r\n spectrum={live.micSpectrum}\r\n bins={live.spectrumBins}\r\n />\r\n </div>\r\n\r\n {voiceConnecting ? (\r\n <div className=\"hsk-voice-connecting\" role=\"status\">\r\n <span className=\"hsk-voice-connecting-dot\" />\r\n <span>{t('voiceConnecting')}</span>\r\n </div>\r\n ) : (\r\n <div className=\"hsk-voice-caption\" aria-live=\"polite\">\r\n <span className={cn('hsk-voice-phase', `hsk-voice-phase--${voicePhase}`)}>\r\n {voiceMuted ? t('voiceMuted')\r\n : voicePhase === 'speaking' ? t('voicePhaseSpeaking')\r\n : voicePhase === 'thinking' ? t('voicePhaseThinking')\r\n : t('voicePhaseListening')}\r\n </span>\r\n {voiceMuted && <span className=\"hsk-voice-heard\">{t('voiceMutedHint')}</span>}\r\n {!voiceMuted && voicePhase === 'listening' && (\r\n <span className=\"hsk-voice-hint-sub\">{t('voiceHint')}</span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {shownSources.length > 0 && (\r\n <div className=\"hsk-voice-items\">\r\n {shownSources.slice(0, 4).map((src, i) => (\r\n <button\r\n key={src.id ?? i}\r\n type=\"button\"\r\n className=\"hsk-voice-item\"\r\n style={{ animationDelay: `${i * 70}ms` }}\r\n onClick={() => onSelectSource?.(src)}\r\n >\r\n {src.image\r\n ? <img src={src.image} alt=\"\" className=\"hsk-voice-item-img\" loading=\"lazy\" />\r\n : <span className=\"hsk-voice-item-img hsk-voice-item-img--empty\"><SparkleIcon /></span>}\r\n <span className=\"hsk-voice-item-name\">{src.name}</span>\r\n {src.price && (\r\n <span className=\"hsk-voice-item-price\">\r\n {src.currency ?? defaultCurrency}{' '}\r\n {parseFloat(String(src.price).replace(/[^0-9.]/g, '') || '0').toLocaleString()}\r\n </span>\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {voiceError && <div className=\"hsk-voice-error\">{t(voiceError as UIStringKey)}</div>}\r\n\r\n <div className=\"hsk-voice-controls\">\r\n <button\r\n className={cn('hsk-voice-control', voiceMuted && 'hsk-voice-control--muted')}\r\n onClick={() => setVoiceMuted(m => !m)}\r\n aria-label={voiceMuted ? t('voicePhaseListening') : t('voiceModeExit')}\r\n title={voiceMuted ? t('voicePhaseListening') : t('voiceModeExit')}\r\n >\r\n <span key={voiceMuted ? 'off' : 'on'} className=\"hsk-voice-control-icon\">\r\n {voiceMuted ? <MicOffIcon /> : <MicIcon />}\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\nimport { CloseIcon } from '../icons';\r\n\r\nexport interface LightboxModalProps {\r\n src: string | null;\r\n onClose: () => void;\r\n}\r\n\r\nexport function LightboxModal({ src, onClose }: LightboxModalProps) {\r\n if (!src) return null;\r\n return (\r\n <div className=\"hsk-lightbox\" onClick={onClose}>\r\n <button className=\"hsk-lightbox-close\" onClick={onClose} aria-label=\"Close image\">\r\n <CloseIcon />\r\n </button>\r\n <img src={src} alt=\"\" className=\"hsk-lightbox-img\" onClick={e => e.stopPropagation()} />\r\n </div>\r\n );\r\n}\r\n","import React, { useRef, useEffect } from 'react';\r\nimport { cn } from '../../../utils/cn';\r\nimport { useT } from '../types';\r\n\r\nexport interface ConversationTimelineProps {\r\n items: { idx: number; text: string }[];\r\n activeIdx: number;\r\n progress: number;\r\n onJump: (idx: number) => void;\r\n side?: 'left' | 'right';\r\n}\r\n\r\nexport function ConversationTimeline({\r\n items,\r\n activeIdx,\r\n progress,\r\n onJump,\r\n side = 'right',\r\n}: ConversationTimelineProps) {\r\n const tr = useT();\r\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\r\n const cursorRef = useRef<HTMLSpanElement>(null);\r\n\r\n let anchor = 0;\r\n for (let i = 0; i < items.length; i++) {\r\n if (items[i].idx <= activeIdx) anchor = i;\r\n }\r\n\r\n useEffect(() => {\r\n const node = itemRefs.current[anchor];\r\n const cursor = cursorRef.current;\r\n if (!node || !cursor) return;\r\n cursor.style.transform = `translateY(${node.offsetTop + node.offsetHeight / 2}px)`;\r\n }, [anchor, items.length]);\r\n\r\n if (items.length < 2) return null;\r\n\r\n return (\r\n <nav\r\n className={cn(\"hsk-cb-timeline\", side === 'left' ? \"hsk-cb-timeline--left\" : \"hsk-cb-timeline--right\")}\r\n aria-label={tr('timelineLabel')}\r\n >\r\n <div className=\"hsk-cb-timeline-track\" style={{ '--hsk-tl-progress': progress } as React.CSSProperties}>\r\n <span className=\"hsk-cb-tl-cursor\" ref={cursorRef} aria-hidden=\"true\" />\r\n {items.map((item, i) => (\r\n <button\r\n key={item.idx}\r\n ref={(el) => { itemRefs.current[i] = el; }}\r\n type=\"button\"\r\n className={cn('hsk-cb-tl-item', i === anchor && 'hsk-cb-tl-item--on')}\r\n style={{ '--hsk-tl-d': Math.min(Math.abs(i - anchor), 4) } as React.CSSProperties}\r\n onClick={() => onJump(item.idx)}\r\n title={item.text}\r\n >\r\n <span className=\"hsk-cb-tl-dot\" />\r\n <span className=\"hsk-cb-tl-label\">{item.text}</span>\r\n </button>\r\n ))}\r\n </div>\r\n </nav>\r\n );\r\n}\r\n","import React, { useState, useEffect, useRef } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { getShadowContainer } from '../utils/shadowRoot';\r\nimport { useSearch, useKiku, useAkropolysContext } from '@akropolys/sdk';\r\nimport { renderMarkdown } from '../utils/markdown';\r\nimport { SearchResult, Product, AkropolysTheme } from '@akropolys/sdk';\r\nimport { cn } from '../utils/cn';\r\nimport { ArrowUpIcon } from '../utils/icons';\r\n\r\nexport interface SparkleProps {\r\n productName: string;\r\n limit?: number;\r\n onResult?: (results: SearchResult[]) => void;\r\n\r\n backdropColor?: string;\r\n \r\n backdropBlur?: string | number;\r\n \r\n className?: string;\r\n\r\n onNavigate?: (result: SearchResult) => boolean | void;\r\n theme?: AkropolysTheme;\r\n classNames?: {\r\n button?: string;\r\n backdrop?: string;\r\n card?: string;\r\n item?: string;\r\n };\r\n product?: Product;\r\n children?: React.ReactNode;\r\n}\r\n\r\ninterface ModalProps extends Pick<SparkleProps, 'productName' | 'limit' | 'backdropColor' | 'backdropBlur' | 'onNavigate' | 'onResult' | 'theme' | 'classNames' | 'product'> {\r\n onClose: () => void;\r\n}\r\n\r\nconst SparkleIcon = ({ className, size = 16 }: { className?: string; size?: number }) => (\r\n <svg\r\n className={cn(\"hsk-brand-mark\", className)}\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 100 100\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-label=\"kiku\"\r\n >\r\n <g transform=\"translate(22.7 19) scale(0.62)\" fill=\"currentColor\" fillRule=\"evenodd\">\r\n <path d=\"M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z\" />\r\n <circle cx=\"55\" cy=\"82\" r=\"3.4\" />\r\n </g>\r\n </svg>\r\n);\r\n\r\nconst CloseIcon = () => (\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n);\r\n\r\ninterface ModalProps extends Pick<SparkleProps, 'productName' | 'limit' | 'backdropColor' | 'backdropBlur' | 'onNavigate' | 'onResult' | 'theme' | 'classNames' | 'product'> {\r\n onClose: () => void;\r\n}\r\n\r\nconst getFriendlyError = (err: any) => {\r\n let str = '';\r\n if (typeof err === 'string') str = err;\r\n else if (err && typeof err === 'object' && err.message) str = err.message;\r\n else try { str = JSON.stringify(err); } catch { str = String(err); }\r\n\r\n if (str.toLowerCase().includes('token limit')) {\r\n return \"You've reached your usage limit. Please update your billing limits in your dashboard to continue.\";\r\n }\r\n\r\n try {\r\n const parsed = JSON.parse(str);\r\n return parsed.error || parsed.message || str;\r\n } catch {\r\n return str;\r\n }\r\n};\r\n\r\nfunction SparkleModal({\r\n productName,\r\n limit,\r\n backdropColor,\r\n backdropBlur,\r\n onClose,\r\n onNavigate,\r\n onResult,\r\n theme,\r\n classNames = {},\r\n product: initialProduct,\r\n}: ModalProps) {\r\n const client = useAkropolysContext();\r\n const [fetchedProduct, setFetchedProduct] = useState<Product | null>(null);\r\n const displayProduct = initialProduct || fetchedProduct;\r\n const { results, loading: searchLoading, search } = useSearch({ type: 'vector' });\r\n const { messages, sources, loading: chatLoading, error: chatError, send } = useKiku();\r\n const [chatInput, setChatInput] = useState('');\r\n const [isMobile, setIsMobile] = useState(false);\r\n const [showSpecs, setShowSpecs] = useState(false);\r\n const [collapseSimilar, setCollapseSimilar] = useState(false);\r\n const chatBottomRef = useRef<HTMLDivElement>(null);\r\n const chatTextareaRef = useRef<HTMLTextAreaElement>(null);\r\n\r\n \r\n useEffect(() => {\r\n if (!initialProduct && !fetchedProduct) {\r\n client.api.searchVector(productName, 1)\r\n .then(res => {\r\n if (res.results && res.results.length > 0) {\r\n setFetchedProduct(res.results[0].entity);\r\n }\r\n })\r\n .catch(err => console.error('[Akropolys] Failed to fetch product details', err));\r\n }\r\n search(productName, limit);\r\n }, [productName, initialProduct, fetchedProduct, client, limit, search]);\r\n\r\n \r\n useEffect(() => {\r\n const handleResize = () => setIsMobile(window.innerWidth <= 768);\r\n handleResize();\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('resize', handleResize);\r\n return () => window.removeEventListener('resize', handleResize);\r\n }\r\n }, []);\r\n\r\n \r\n useEffect(() => { if (results.length > 0) onResult?.(results); }, [results, onResult]);\r\n\r\n \r\n useEffect(() => {\r\n const h = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\r\n document.addEventListener('keydown', h);\r\n return () => document.removeEventListener('keydown', h);\r\n }, [onClose]);\r\n\r\n const overlayRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const prevOverflow = document.body.style.overflow;\r\n const prevPosition = document.body.style.position;\r\n const prevWidth = document.body.style.width;\r\n\r\n document.body.style.overflow = 'hidden';\r\n document.body.style.position = 'fixed';\r\n document.body.style.width = '100%';\r\n\r\n const handleScrollLock = () => {\r\n window.scrollTo(0, 0);\r\n if (overlayRef.current) overlayRef.current.scrollTop = 0;\r\n };\r\n\r\n window.addEventListener('scroll', handleScrollLock, { passive: true });\r\n\r\n return () => {\r\n document.body.style.overflow = prevOverflow;\r\n document.body.style.position = prevPosition;\r\n document.body.style.width = prevWidth;\r\n window.removeEventListener('scroll', handleScrollLock);\r\n };\r\n }, []);\r\n\r\n const chatBodyRef = useRef<HTMLDivElement>(null);\r\n\r\n \r\n useEffect(() => {\r\n if (chatBodyRef.current) {\r\n chatBodyRef.current.scrollTop = chatBodyRef.current.scrollHeight;\r\n }\r\n }, [messages, chatLoading]);\r\n\r\n const blurVal = typeof backdropBlur === 'number' ? `${backdropBlur}px` : (backdropBlur ?? '16px');\r\n const bg = backdropColor ?? undefined;\r\n\r\n const handleNav = (r: SearchResult) => {\r\n const prevent = onNavigate?.(r);\r\n if (prevent !== false) {\r\n onClose();\r\n if (r.entity.url) window.location.href = r.entity.url;\r\n }\r\n };\r\n\r\n const handleSend = async (text?: string) => {\r\n const q = (text ?? chatInput).trim();\r\n if (!q || chatLoading) return;\r\n setChatInput('');\r\n if (chatTextareaRef.current) {\r\n chatTextareaRef.current.style.height = 'auto';\r\n }\r\n\r\n if (messages.length === 0 && displayProduct) {\r\n const contextQuery = `[Context: Shopper is viewing \"${displayProduct.name}\". Price: ${displayProduct.price}. Description: ${displayProduct.description || ''}]\\n\\nQuestion: ${q}`;\r\n await send(contextQuery, q);\r\n } else {\r\n await send(q);\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) { e.preventDefault(); handleSend(); }\r\n };\r\n\r\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n setChatInput(e.target.value);\r\n const t = e.target;\r\n t.style.height = 'auto';\r\n t.style.height = `${Math.min(t.scrollHeight, 140)}px`;\r\n };\r\n\r\n const customStyles = {\r\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\r\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\r\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\r\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\r\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\r\n } as React.CSSProperties;\r\n\r\n const displayMessages = messages.length === 0 && displayProduct\r\n ? [\r\n {\r\n role: 'assistant' as const,\r\n content: `Hi! I can help you with **${displayProduct.name}**. Ask me about its specifications, features, compare it with other options, or find alternatives!`,\r\n },\r\n ]\r\n : messages;\r\n\r\n if (isMobile) {\r\n return (\r\n <div\r\n ref={overlayRef}\r\n className={cn(\"hsk-sp-backdrop hsk-sp-mobile-view\", classNames.backdrop)}\r\n onClick={onClose}\r\n style={{\r\n backdropFilter: `blur(${blurVal})`,\r\n WebkitBackdropFilter: `blur(${blurVal})`,\r\n background: bg ?? undefined,\r\n ...customStyles,\r\n }}\r\n >\r\n <div className={cn(\"hsk-sp-card hsk-sp-fullscreen hsk-sp-mobile-card\", classNames.card)} onClick={e => e.stopPropagation()}>\r\n {}\r\n <div className=\"hsk-sp-header\">\r\n <span className=\"hsk-sp-header-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </span>\r\n <div className=\"hsk-sp-header-body\">\r\n <div className=\"hsk-sp-header-title-row\">\r\n <div className=\"hsk-sp-header-title\">{displayProduct?.name || productName}</div>\r\n {displayProduct && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-sp-header-specs-btn\"\r\n onClick={() => setShowSpecs(true)}\r\n >\r\n Specs\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"hsk-sp-header-sub\">kiku</div>\r\n </div>\r\n <button className=\"hsk-sp-close\" onClick={onClose} aria-label=\"Close\">\r\n <CloseIcon />\r\n </button>\r\n </div>\r\n\r\n {searchLoading && <div className=\"hsk-sp-bar\" />}\r\n\r\n {}\r\n <div className=\"hsk-sp-mobile-chat-container\">\r\n <div className=\"hsk-cb-msgs\">\r\n {displayMessages.map((msg, idx) => {\r\n const isUser = msg.role === 'user';\r\n return (\r\n <div key={idx} className=\"hsk-cb-msg-group\">\r\n {isUser ? (\r\n <div className=\"hsk-cb-user-msg\">\r\n <div className=\"hsk-cb-user-bubble\">{msg.content}</div>\r\n </div>\r\n ) : (\r\n <div className=\"hsk-cb-ai-msg\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-ai-body\">\r\n <div className=\"hsk-cb-ai-text\">{renderMarkdown(msg.content)}</div>\r\n\r\n {}\r\n {idx === 0 && displayProduct && (\r\n <div className=\"hsk-sp-mobile-attachment-deck\">\r\n {}\r\n <div className=\"hsk-sp-mobile-main-card\">\r\n <div className=\"hsk-sp-mobile-main-card-img\">\r\n {displayProduct.images?.[0] ? (\r\n <img src={displayProduct.images[0]} alt={displayProduct.name} />\r\n ) : (\r\n <span>🛍</span>\r\n )}\r\n </div>\r\n <div className=\"hsk-sp-mobile-main-card-info\">\r\n <div className=\"hsk-sp-mobile-main-card-brand\">\r\n {displayProduct.brand || displayProduct.category || 'Product'}\r\n </div>\r\n <div className=\"hsk-sp-mobile-main-card-name\">{displayProduct.name}</div>\r\n <div className=\"hsk-sp-mobile-main-card-price\">\r\n {displayProduct.currency ?? 'KES'} {parseFloat(displayProduct.price?.replace(/[^0-9.]/g, '') || '0').toLocaleString()}\r\n </div>\r\n </div>\r\n {((displayProduct.specs && Object.keys(displayProduct.specs).length > 0) || displayProduct.description) && (\r\n <button\r\n type=\"button\"\r\n className=\"hsk-sp-mobile-main-card-specs-btn\"\r\n onClick={() => setShowSpecs(true)}\r\n >\r\n Specs\r\n </button>\r\n )}\r\n </div>\r\n\r\n {}\r\n {(() => {\r\n const similarProducts = results.filter(\r\n r => {\r\n const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());\r\n const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();\r\n return !isSameName && !isSameSlug;\r\n }\r\n );\r\n\r\n if (similarProducts.length === 0) return null;\r\n\r\n return (\r\n <div className=\"hsk-sp-mobile-similar-carousel-inline\">\r\n <div className=\"hsk-sp-mobile-similar-carousel-title\">Similar Products</div>\r\n <div className=\"hsk-sp-mobile-similar-carousel-list\">\r\n {similarProducts.map((r) => {\r\n const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, '') || '0');\r\n const currency = r.entity.currency ?? 'KES';\r\n return (\r\n <div\r\n key={r.id}\r\n className=\"hsk-sp-mobile-similar-carousel-item\"\r\n onClick={() => handleNav(r)}\r\n >\r\n <div className=\"hsk-sp-mobile-similar-carousel-img\">\r\n {r.entity.images?.[0] ? (\r\n <img src={r.entity.images[0]} alt={r.entity.name} />\r\n ) : (\r\n <span>🛍</span>\r\n )}\r\n </div>\r\n <div className=\"hsk-sp-mobile-similar-carousel-meta\">\r\n <div className=\"hsk-sp-mobile-similar-carousel-name\" title={r.entity.name}>\r\n {r.entity.name}\r\n </div>\r\n <div className=\"hsk-sp-mobile-similar-carousel-price\">\r\n {currency} {price.toLocaleString()}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n })()}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n\r\n {chatLoading && (\r\n <div className=\"hsk-cb-typing-row\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-typing\">\r\n <div className=\"hsk-cb-dot\" />\r\n <div className=\"hsk-cb-dot\" />\r\n <div className=\"hsk-cb-dot\" />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {chatError && <div className=\"hsk-cb-error\">{getFriendlyError(chatError)}</div>}\r\n <div ref={chatBottomRef} style={{ height: 1 }} />\r\n </div>\r\n\r\n <div className=\"hsk-cb-input-wrap\">\r\n <div className=\"hsk-cb-input-box\">\r\n <textarea\r\n ref={chatTextareaRef}\r\n className=\"hsk-cb-textarea\"\r\n value={chatInput}\r\n onChange={handleInput}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"Ask about this product, specs, or comparison...\"\r\n rows={1}\r\n disabled={chatLoading}\r\n />\r\n <button\r\n className=\"hsk-cb-send\"\r\n onClick={() => handleSend()}\r\n disabled={!chatInput.trim() || chatLoading}\r\n aria-label=\"Send message\"\r\n >\r\n <ArrowUpIcon />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {}\r\n {showSpecs && displayProduct && (\r\n <div className=\"hsk-sp-mobile-specs-overlay\" onClick={() => setShowSpecs(false)}>\r\n <div className=\"hsk-sp-mobile-specs-drawer\" onClick={e => e.stopPropagation()}>\r\n <div className=\"hsk-sp-mobile-specs-header\">\r\n <h3>Specifications</h3>\r\n <button type=\"button\" onClick={() => setShowSpecs(false)}>Close</button>\r\n </div>\r\n <div className=\"hsk-sp-mobile-specs-body\">\r\n <h4 className=\"hsk-sp-mobile-specs-title\">{displayProduct.name}</h4>\r\n {displayProduct.description && (\r\n <div className=\"hsk-sp-mobile-specs-desc\">\r\n <h5>Description</h5>\r\n <p>{displayProduct.description}</p>\r\n </div>\r\n )}\r\n {displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && (\r\n <div className=\"hsk-sp-mobile-specs-list\">\r\n <h5>Details</h5>\r\n {Object.entries(displayProduct.specs).map(([key, val]) => (\r\n <div key={key} className=\"hsk-sp-mobile-spec-row\">\r\n <span className=\"hsk-sp-mobile-spec-label\">{key}</span>\r\n <span className=\"hsk-sp-mobile-spec-value\">{val}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\"hsk-sp-backdrop\", classNames.backdrop)}\r\n onClick={onClose}\r\n style={{\r\n backdropFilter: `blur(${blurVal})`,\r\n WebkitBackdropFilter: `blur(${blurVal})`,\r\n background: bg ?? undefined,\r\n ...customStyles,\r\n }}\r\n >\r\n <div className={cn(\"hsk-sp-card hsk-sp-fullscreen\", classNames.card)} onClick={e => e.stopPropagation()}>\r\n <div className=\"hsk-sp-header\">\r\n <span className=\"hsk-sp-header-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </span>\r\n <div className=\"hsk-sp-header-body\">\r\n <div className=\"hsk-sp-header-title\">{displayProduct?.name || productName}</div>\r\n <div className=\"hsk-sp-header-sub\">Ask questions, compare specs, or check similar products</div>\r\n </div>\r\n <button className=\"hsk-sp-close\" onClick={onClose} aria-label=\"Close\">\r\n <CloseIcon />\r\n </button>\r\n </div>\r\n\r\n {searchLoading && <div className=\"hsk-sp-bar\" />}\r\n\r\n {}\r\n <div className=\"hsk-sp-body\">\r\n {}\r\n <div className=\"hsk-sp-details-pane\">\r\n {displayProduct && (\r\n <div className=\"hsk-sp-product-profile-container\">\r\n <div className=\"hsk-sp-product-profile\">\r\n <div className=\"hsk-sp-details-imgwrap\">\r\n {displayProduct.images?.[0] ? (\r\n <img src={displayProduct.images[0]} alt={displayProduct.name} />\r\n ) : (\r\n <span className=\"hsk-sp-img-placeholder\">🛍</span>\r\n )}\r\n </div>\r\n <div className=\"hsk-sp-details-meta\">\r\n {displayProduct.brand && <span className=\"hsk-sp-item-brand\">{displayProduct.brand}</span>}\r\n {displayProduct.category && <span className=\"hsk-sp-item-cat\">{displayProduct.category}</span>}\r\n <h2 className=\"hsk-sp-details-name\">{displayProduct.name}</h2>\r\n <div className=\"hsk-sp-item-price-row\">\r\n <span className=\"hsk-sp-item-currency\">{displayProduct.currency ?? 'KES'}</span>\r\n <span className=\"hsk-sp-item-price\">{parseFloat(displayProduct.price?.replace(/[^0-9.]/g, '') || '0').toLocaleString()}</span>\r\n {displayProduct.originalPrice && (\r\n <span className=\"hsk-sp-item-original-price\">\r\n {parseFloat(displayProduct.originalPrice.replace(/[^0-9.]/g, '') || '0').toLocaleString()}\r\n </span>\r\n )}\r\n {displayProduct.discount && (\r\n <span className=\"hsk-sp-item-discount\">({displayProduct.discount})</span>\r\n )}\r\n </div>\r\n\r\n <div className=\"hsk-sp-item-meta-badges\">\r\n {displayProduct.rating && (\r\n <span className=\"hsk-sp-meta-badge hsk-sp-meta-badge-rating\">\r\n ★ {parseFloat(displayProduct.rating.toString()).toFixed(1)} {displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ''}\r\n </span>\r\n )}\r\n {displayProduct.availability && (\r\n <span className={`hsk-sp-meta-badge hsk-sp-meta-badge-avail ${displayProduct.availability.toLowerCase().includes('in') ? 'in-stock' : 'out-stock'}`}>\r\n {displayProduct.availability}\r\n </span>\r\n )}\r\n {displayProduct.stock && !displayProduct.availability && (\r\n <span className=\"hsk-sp-meta-badge hsk-sp-meta-badge-stock\">\r\n Stock: {displayProduct.stock}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && (\r\n <div className=\"hsk-sp-specs-horizontal\">\r\n {Object.entries(displayProduct.specs).map(([key, val]) => (\r\n <div key={key} className=\"hsk-sp-spec-item-horizontal\">\r\n <span className=\"hsk-sp-spec-label-horizontal\">{key}:</span>\r\n <span className=\"hsk-sp-spec-value-horizontal\" title={val}>{val}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {displayProduct.description && (\r\n <div className=\"hsk-sp-details-desc\">\r\n <h4>Description</h4>\r\n <p>{displayProduct.description}</p>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {}\r\n <div className=\"hsk-sp-similar-section\">\r\n <h3>Similar Products</h3>\r\n <div className=\"hsk-sp-results\">\r\n {(() => {\r\n const similarProducts = results.filter(\r\n r => {\r\n const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());\r\n const isSameSlug = r.entity.slug && displayProduct?.slug && r.entity.slug.toLowerCase() === displayProduct.slug.toLowerCase();\r\n return !isSameName && !isSameSlug;\r\n }\r\n );\r\n\r\n if (!searchLoading && similarProducts.length === 0) {\r\n return <div className=\"hsk-sp-empty\">No similar products found.</div>;\r\n }\r\n\r\n return similarProducts.map((r, i) => {\r\n const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, '') || '0');\r\n const currency = r.entity.currency ?? 'KES';\r\n return (\r\n <div\r\n key={r.id}\r\n className={cn(\"hsk-sp-item\", classNames.item)}\r\n style={{ animationDelay: `${i * 55}ms`, cursor: 'pointer' }}\r\n onClick={() => handleNav(r)}\r\n >\r\n <div className=\"hsk-sp-img-wrap\">\r\n {r.entity.images?.[0] ? (\r\n <img src={r.entity.images[0]} alt={r.entity.name} />\r\n ) : (\r\n <span className=\"hsk-sp-img-placeholder\">🛍</span>\r\n )}\r\n </div>\r\n <div className=\"hsk-sp-item-body\">\r\n <div>\r\n {r.entity.category && (\r\n <div className=\"hsk-sp-item-cat\">{r.entity.category}</div>\r\n )}\r\n <div className=\"hsk-sp-item-name\" title={r.entity.name}>{r.entity.name}</div>\r\n </div>\r\n <div className=\"hsk-sp-item-price-row\">\r\n <span className=\"hsk-sp-item-currency\">{currency}</span>\r\n <span className=\"hsk-sp-item-price\">{price.toLocaleString()}</span>\r\n </div>\r\n <div className=\"hsk-sp-actions\">\r\n <button\r\n className=\"hsk-sp-action hsk-sp-action-primary\"\r\n onClick={(e) => { e.stopPropagation(); handleNav(r); }}\r\n >\r\n View\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n });\r\n })()}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {}\r\n <div className=\"hsk-sp-chat-pane\">\r\n <div className=\"hsk-cb-msgs\">\r\n {displayMessages.map((msg, idx) => {\r\n const isUser = msg.role === 'user';\r\n return (\r\n <div key={idx} className=\"hsk-cb-msg-group\">\r\n {isUser ? (\r\n <div className=\"hsk-cb-user-msg\">\r\n <div className=\"hsk-cb-user-bubble\">{msg.content}</div>\r\n </div>\r\n ) : (\r\n <div className=\"hsk-cb-ai-msg\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-ai-body\">\r\n <div className=\"hsk-cb-ai-text\">{renderMarkdown(msg.content)}</div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n\r\n {chatLoading && (\r\n <div className=\"hsk-cb-typing-row\">\r\n <div className=\"hsk-cb-ai-icon\" style={{ display: 'flex', alignItems: 'center' }}>\r\n <SparkleIcon />\r\n </div>\r\n <div className=\"hsk-cb-typing\">\r\n <div className=\"hsk-cb-dot\" />\r\n <div className=\"hsk-cb-dot\" />\r\n <div className=\"hsk-cb-dot\" />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {chatError && <div className=\"hsk-cb-error\">{getFriendlyError(chatError)}</div>}\r\n <div ref={chatBottomRef} style={{ height: 1 }} />\r\n </div>\r\n\r\n <div className=\"hsk-cb-input-wrap\">\r\n <div className=\"hsk-cb-input-box\">\r\n <textarea\r\n ref={chatTextareaRef}\r\n className=\"hsk-cb-textarea\"\r\n value={chatInput}\r\n onChange={handleInput}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"Ask about this product, specs, or comparison...\"\r\n rows={1}\r\n disabled={chatLoading}\r\n />\r\n <button\r\n className=\"hsk-cb-send\"\r\n onClick={() => handleSend()}\r\n disabled={!chatInput.trim() || chatLoading}\r\n aria-label=\"Send message\"\r\n >\r\n <ArrowUpIcon />\r\n </button>\r\n </div>\r\n <div className=\"hsk-cb-hint\">Akropolys &middot; instant product knowledge</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"hsk-sp-footer\">\r\n <span className=\"hsk-sp-esc\">Esc to close</span>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function Sparkle({\r\n productName,\r\n limit = 8,\r\n onResult,\r\n backdropColor,\r\n backdropBlur,\r\n className,\r\n onNavigate,\r\n theme,\r\n classNames = {},\r\n product,\r\n children,\r\n}: SparkleProps) {\r\n const [open, setOpen] = useState(false);\r\n const [mounted, setMounted] = useState(false);\r\n\r\n useEffect(() => { setMounted(true); }, []);\r\n\r\n const customStyles = {\r\n ...(theme?.primaryColor && { '--hsk-primary': theme.primaryColor }),\r\n ...(theme?.backgroundColor && { '--hsk-bg': theme.backgroundColor }),\r\n ...(theme?.textColor && { '--hsk-text': theme.textColor }),\r\n ...(theme?.fontFamily && { '--hsk-font': theme.fontFamily }),\r\n ...(theme?.borderRadius && { '--hsk-border-radius': theme.borderRadius }),\r\n } as React.CSSProperties;\r\n\r\n return (\r\n <>\r\n <button\r\n className={cn(\"hsk-sp-btn\", classNames.button, className)}\r\n onClick={() => setOpen(true)}\r\n style={customStyles}\r\n title=\"Find similar products\"\r\n aria-label=\"Find similar products\"\r\n >\r\n {children || <SparkleIcon />}\r\n </button>\r\n {open && mounted && createPortal(\r\n <SparkleModal\r\n productName={productName}\r\n limit={limit}\r\n onResult={onResult}\r\n backdropColor={backdropColor}\r\n backdropBlur={backdropBlur}\r\n onClose={() => setOpen(false)}\r\n onNavigate={onNavigate}\r\n theme={theme}\r\n classNames={classNames}\r\n product={product}\r\n />,\r\n getShadowContainer() ?? document.body\r\n )}\r\n </>\r\n );\r\n}\r\n\r\n","import React, { useEffect, useState, useRef } from 'react';\r\nimport { createRoot } from 'react-dom/client';\r\nimport { AkropolysProvider, getAkropolysClient, ChatSource } from '@akropolys/sdk';\r\nimport { KikuButton } from './components/KikuButton';\r\n\r\nexport interface ShopifyProduct {\r\n id?: number | string;\r\n title?: string;\r\n name?: string;\r\n handle?: string;\r\n url?: string;\r\n price?: number | string;\r\n compare_at_price?: number | string;\r\n price_min?: number | string;\r\n featured_image?: string;\r\n images?: string[] | { src: string }[];\r\n image?: string;\r\n type?: string;\r\n product_type?: string;\r\n category?: string;\r\n vendor?: string;\r\n brand?: string;\r\n tags?: string[] | string;\r\n description?: string;\r\n body_html?: string;\r\n variants?: Array<{\r\n id: number | string;\r\n title?: string;\r\n price?: number | string;\r\n sku?: string;\r\n available?: boolean;\r\n }>;\r\n available?: boolean;\r\n [key: string]: any;\r\n}\r\n\r\nexport interface StandaloneConfig {\r\n siteId?: string;\r\n apiToken?: string;\r\n apiUrl?: string;\r\n vertical?: string;\r\n shopperId?: string;\r\n theme?: 'dark' | 'light' | any;\r\n buttonLabel?: string;\r\n title?: string;\r\n placeholder?: string;\r\n defaultCurrency?: string;\r\n chips?: string[];\r\n enableVoice?: boolean;\r\n voiceLang?: string;\r\n enableVision?: boolean;\r\n visionCategoryHint?: string;\r\n enableAudioResponse?: boolean;\r\n ttsVoice?: string;\r\n autoSpeakResponses?: boolean;\r\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'hidden' | 'custom';\r\n containerId?: string;\r\n containerSelector?: string;\r\n dockable?: boolean;\r\n product?: ShopifyProduct;\r\n onAddToCart?: (items: ChatSource[]) => void;\r\n onAction?: (action: any) => void;\r\n [key: string]: any;\r\n}\r\n\r\ndeclare global {\r\n interface Window {\r\n AkropolysConfig?: StandaloneConfig;\r\n Kiku?: {\r\n version: string;\r\n open: () => void;\r\n close: () => void;\r\n toggle: () => void;\r\n ingest: (product: ShopifyProduct) => Promise<void>;\r\n resetPosition: () => void;\r\n getClient: () => any;\r\n config: StandaloneConfig;\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Normalizes a Shopify product object into Akropolys entity format.\r\n */\r\nexport function normalizeShopifyProduct(p: ShopifyProduct): Record<string, any> {\r\n if (!p || typeof p !== 'object') return {};\r\n\r\n const id = String(p.id ?? p.handle ?? p.url ?? '');\r\n const title = p.title || p.name || '';\r\n \r\n let priceStr: string | undefined;\r\n if (typeof p.price === 'number') {\r\n priceStr = p.price >= 100 && Number.isInteger(p.price) \r\n ? (p.price / 100).toFixed(2) \r\n : p.price.toString();\r\n } else if (typeof p.price === 'string') {\r\n priceStr = p.price;\r\n }\r\n\r\n let image = p.featured_image || p.image;\r\n if (!image && Array.isArray(p.images) && p.images.length > 0) {\r\n const first = p.images[0];\r\n image = typeof first === 'string' ? first : first?.src;\r\n }\r\n if (typeof image === 'string' && image.startsWith('//')) {\r\n image = 'https:' + image;\r\n }\r\n\r\n let url = p.url || '';\r\n if (!url && p.handle) {\r\n url = `/products/${p.handle}`;\r\n }\r\n if (url && typeof window !== 'undefined' && !url.startsWith('http')) {\r\n try {\r\n url = new URL(url, window.location.origin).href;\r\n } catch {\r\n // keep relative if URL parsing fails\r\n }\r\n }\r\n\r\n const category = p.type || p.product_type || p.category || '';\r\n const brand = p.vendor || p.brand || '';\r\n \r\n const tags = Array.isArray(p.tags) \r\n ? p.tags \r\n : typeof p.tags === 'string' \r\n ? p.tags.split(',').map(t => t.trim()).filter(Boolean)\r\n : [];\r\n\r\n const rawDescription = p.description || p.body_html || '';\r\n const cleanDescription = typeof rawDescription === 'string' \r\n ? rawDescription.replace(/<[^>]*>?/gm, '').trim()\r\n : '';\r\n\r\n const defaultVariant = Array.isArray(p.variants) && p.variants.length > 0 ? p.variants[0] : null;\r\n const variantId = defaultVariant ? defaultVariant.id : undefined;\r\n\r\n return {\r\n id,\r\n name: title,\r\n title,\r\n price: priceStr,\r\n image,\r\n url: url || (typeof window !== 'undefined' ? window.location.href : ''),\r\n category,\r\n brand,\r\n tags,\r\n description: cleanDescription,\r\n availability: p.available !== false ? 'in_stock' : 'out_of_stock',\r\n variant_id: variantId ? String(variantId) : undefined,\r\n shopify_product_id: p.id ? String(p.id) : undefined,\r\n handle: p.handle || undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Native Shopify Cart Integration.\r\n */\r\nexport function shopifyAddToCart(items: ChatSource[]): Promise<any> {\r\n if (!items || items.length === 0) return Promise.resolve();\r\n\r\n const cartItems = items.map(item => {\r\n const variantId = item.fields?.variant_id || item.fields?.shopify_variant_id || item.id;\r\n return {\r\n id: variantId,\r\n quantity: 1,\r\n };\r\n });\r\n\r\n return fetch('/cart/add.js', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n body: JSON.stringify({ items: cartItems }),\r\n })\r\n .then(async res => {\r\n if (!res.ok) {\r\n console.warn('[Akropolys Shopify] /cart/add.js returned error status:', res.status);\r\n }\r\n const data = await res.json().catch(() => null);\r\n \r\n if (typeof document !== 'undefined') {\r\n document.dispatchEvent(new CustomEvent('cart:updated', { bubbles: true, detail: { items: data } }));\r\n document.dispatchEvent(new CustomEvent('cart:refresh', { bubbles: true, detail: { items: data } }));\r\n document.dispatchEvent(new CustomEvent('cart:build', { bubbles: true }));\r\n window.dispatchEvent(new CustomEvent('cart:updated', { detail: { items: data } }));\r\n }\r\n return data;\r\n })\r\n .catch(err => {\r\n console.warn('[Akropolys Shopify] Add to cart network error:', err);\r\n });\r\n}\r\n\r\n/**\r\n * Native Shopify Get Cart.\r\n */\r\nexport function shopifyGetCart(): Promise<any> {\r\n return fetch('/cart.js', {\r\n headers: { 'Accept': 'application/json' },\r\n })\r\n .then(res => (res.ok ? res.json() : null))\r\n .catch(() => null);\r\n}\r\n\r\n/**\r\n * Draggable and Dockable container for Kiku floating launcher button.\r\n */\r\nfunction DraggableDockWrapper({\r\n children,\r\n position = 'bottom-right',\r\n dockable = true,\r\n isInline = false,\r\n}: {\r\n children: React.ReactNode;\r\n position?: StandaloneConfig['position'];\r\n dockable?: boolean;\r\n isInline?: boolean;\r\n}) {\r\n if (isInline || position === 'inline' || position === 'custom' || position === 'hidden' || dockable === false) {\r\n return (\r\n <div className=\"akropolys-kiku-inline-wrapper\" style={{ display: 'inline-flex', alignItems: 'center' }}>\r\n {children}\r\n </div>\r\n );\r\n }\r\n\r\n const [coords, setCoords] = useState<{ x: number; y: number } | null>(null);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const dragStartRef = useRef<{ startX: number; startY: number; initX: number; initY: number; moved: boolean } | null>(null);\r\n const wrapperRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n\r\n const computeDefault = () => {\r\n const margin = 20;\r\n const btnWidth = 140;\r\n const btnHeight = 44;\r\n let defX = window.innerWidth - btnWidth - margin;\r\n let defY = window.innerHeight - btnHeight - margin;\r\n\r\n if (position === 'bottom-left') {\r\n defX = margin;\r\n defY = window.innerHeight - btnHeight - margin;\r\n } else if (position === 'top-right') {\r\n defX = window.innerWidth - btnWidth - margin;\r\n defY = margin;\r\n } else if (position === 'top-left') {\r\n defX = margin;\r\n defY = margin;\r\n }\r\n\r\n try {\r\n const saved = localStorage.getItem('akropolys_dock_pos');\r\n if (saved) {\r\n const parsed = JSON.parse(saved);\r\n if (typeof parsed.x === 'number' && typeof parsed.y === 'number') {\r\n const clampedX = Math.max(10, Math.min(window.innerWidth - 60, parsed.x));\r\n const clampedY = Math.max(10, Math.min(window.innerHeight - 60, parsed.y));\r\n return { x: clampedX, y: clampedY };\r\n }\r\n }\r\n } catch {}\r\n\r\n return { x: Math.max(10, defX), y: Math.max(10, defY) };\r\n };\r\n\r\n setCoords(computeDefault());\r\n\r\n const onResize = () => {\r\n setCoords(prev => {\r\n if (!prev) return computeDefault();\r\n const clampedX = Math.max(10, Math.min(window.innerWidth - 60, prev.x));\r\n const clampedY = Math.max(10, Math.min(window.innerHeight - 60, prev.y));\r\n return { x: clampedX, y: clampedY };\r\n });\r\n };\r\n\r\n window.addEventListener('resize', onResize);\r\n return () => window.removeEventListener('resize', onResize);\r\n }, [position]);\r\n\r\n const onPointerDown = (e: React.PointerEvent) => {\r\n if (!wrapperRef.current) return;\r\n const rect = wrapperRef.current.getBoundingClientRect();\r\n dragStartRef.current = {\r\n startX: e.clientX,\r\n startY: e.clientY,\r\n initX: rect.left,\r\n initY: rect.top,\r\n moved: false,\r\n };\r\n try {\r\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\r\n } catch {}\r\n };\r\n\r\n const onPointerMove = (e: React.PointerEvent) => {\r\n if (!dragStartRef.current) return;\r\n const dx = e.clientX - dragStartRef.current.startX;\r\n const dy = e.clientY - dragStartRef.current.startY;\r\n if (!dragStartRef.current.moved && Math.hypot(dx, dy) > 6) {\r\n dragStartRef.current.moved = true;\r\n setIsDragging(true);\r\n }\r\n if (dragStartRef.current.moved) {\r\n const width = wrapperRef.current?.offsetWidth || 140;\r\n const height = wrapperRef.current?.offsetHeight || 44;\r\n const newX = Math.max(8, Math.min(window.innerWidth - width - 8, dragStartRef.current.initX + dx));\r\n const newY = Math.max(8, Math.min(window.innerHeight - height - 8, dragStartRef.current.initY + dy));\r\n setCoords({ x: newX, y: newY });\r\n }\r\n };\r\n\r\n const onPointerUp = () => {\r\n if (!dragStartRef.current) return;\r\n const hadMoved = dragStartRef.current.moved;\r\n dragStartRef.current = null;\r\n setIsDragging(false);\r\n\r\n if (hadMoved && coords) {\r\n try {\r\n localStorage.setItem('akropolys_dock_pos', JSON.stringify(coords));\r\n } catch {}\r\n\r\n const clickCapturer = (ev: MouseEvent) => {\r\n ev.stopPropagation();\r\n ev.preventDefault();\r\n window.removeEventListener('click', clickCapturer, true);\r\n };\r\n window.addEventListener('click', clickCapturer, true);\r\n setTimeout(() => window.removeEventListener('click', clickCapturer, true), 120);\r\n }\r\n };\r\n\r\n if (!coords) return null;\r\n\r\n return (\r\n <div\r\n ref={wrapperRef}\r\n className=\"akropolys-kiku-dock-wrapper\"\r\n onPointerDown={onPointerDown}\r\n onPointerMove={onPointerMove}\r\n onPointerUp={onPointerUp}\r\n onPointerCancel={onPointerUp}\r\n title=\"Drag to dock anywhere\"\r\n style={{\r\n position: 'fixed',\r\n left: `${coords.x}px`,\r\n top: `${coords.y}px`,\r\n zIndex: 2147483640,\r\n touchAction: 'none',\r\n cursor: isDragging ? 'grabbing' : 'grab',\r\n transition: isDragging ? 'none' : 'transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.2s ease',\r\n transform: isDragging ? 'scale(1.05)' : 'scale(1)',\r\n userSelect: 'none',\r\n WebkitUserSelect: 'none',\r\n }}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nfunction StandaloneKikuApp({ config, isInline }: { config: StandaloneConfig; isInline: boolean }) {\r\n useEffect(() => {\r\n const client = getAkropolysClient();\r\n if (!client) return;\r\n\r\n let prod = config.product;\r\n if (!prod && typeof (window as any).meta?.product === 'object') {\r\n prod = (window as any).meta.product;\r\n }\r\n\r\n if (prod) {\r\n const normalized = normalizeShopifyProduct(prod);\r\n if (normalized.id || normalized.url) {\r\n client.ingest(normalized).catch((err) => {\r\n console.debug('[Akropolys Shopify] Auto-ingest notice:', err);\r\n });\r\n }\r\n }\r\n }, [config.product]);\r\n\r\n const defaultOnAddToCart = (items: ChatSource[]) => {\r\n if (config.onAddToCart) {\r\n config.onAddToCart(items);\r\n return;\r\n }\r\n shopifyAddToCart(items);\r\n };\r\n\r\n return (\r\n <AkropolysProvider\r\n siteId={config.siteId}\r\n apiUrl={config.apiUrl}\r\n apiToken={config.apiToken}\r\n vertical={config.vertical || 'commerce'}\r\n shopperId={config.shopperId}\r\n onAddToCart={defaultOnAddToCart}\r\n onAction={config.onAction}\r\n getCart={shopifyGetCart}\r\n >\r\n <DraggableDockWrapper\r\n position={config.position}\r\n dockable={config.dockable !== false}\r\n isInline={isInline}\r\n >\r\n <KikuButton\r\n label={config.buttonLabel || 'Ask Kiku'}\r\n title={config.title || 'kiku'}\r\n placeholder={config.placeholder}\r\n defaultCurrency={config.defaultCurrency || '$'}\r\n chips={config.chips}\r\n theme={config.theme || 'dark'}\r\n enableVoice={config.enableVoice !== false}\r\n voiceLang={config.voiceLang}\r\n enableVision={config.enableVision !== false}\r\n visionCategoryHint={config.visionCategoryHint}\r\n enableAudioResponse={config.enableAudioResponse !== false}\r\n ttsVoice={config.ttsVoice || 'Puck'}\r\n autoSpeakResponses={config.autoSpeakResponses !== false}\r\n />\r\n </DraggableDockWrapper>\r\n </AkropolysProvider>\r\n );\r\n}\r\n\r\n/**\r\n * Attaches global click listeners for any element with [data-kiku-open] or [data-kiku-toggle]\r\n */\r\nfunction setupGlobalTriggers() {\r\n if (typeof document === 'undefined') return;\r\n\r\n document.addEventListener('click', (e) => {\r\n const target = e.target as HTMLElement | null;\r\n const trigger = target?.closest('[data-kiku-open], [data-kiku-toggle], .kiku-trigger');\r\n if (trigger) {\r\n e.preventDefault();\r\n window.Kiku?.open();\r\n }\r\n });\r\n}\r\n\r\nexport function initKiku(customConfig?: StandaloneConfig): void {\r\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\r\n\r\n let scriptConfig: Partial<StandaloneConfig> = {};\r\n const scriptTag = document.getElementById('akropolys-kiku-script') as HTMLScriptElement | null;\r\n if (scriptTag) {\r\n const ds = scriptTag.dataset;\r\n scriptConfig = {\r\n siteId: ds.siteId,\r\n apiToken: ds.apiToken,\r\n apiUrl: ds.apiUrl,\r\n theme: ds.theme as any,\r\n buttonLabel: ds.buttonLabel,\r\n position: ds.position as any,\r\n containerId: ds.containerId,\r\n containerSelector: ds.containerSelector,\r\n dockable: ds.dockable !== 'false',\r\n enableVoice: ds.enableVoice === 'true' || ds.enableVoice === '1',\r\n enableVision: ds.enableVision === 'true' || ds.enableVision === '1',\r\n };\r\n }\r\n\r\n const mergedConfig: StandaloneConfig = {\r\n ...scriptConfig,\r\n ...(window.AkropolysConfig || {}),\r\n ...(customConfig || {}),\r\n };\r\n\r\n if (!mergedConfig.siteId || !mergedConfig.apiToken) {\r\n console.warn(\r\n '[Akropolys] Missing siteId or apiToken. Configure window.AkropolysConfig = { siteId: \"...\", apiToken: \"...\" }'\r\n );\r\n }\r\n\r\n // Determine container and mounting mode\r\n let container: HTMLElement | null = null;\r\n let isInline = false;\r\n\r\n if (mergedConfig.containerSelector) {\r\n container = document.querySelector(mergedConfig.containerSelector);\r\n if (container) isInline = true;\r\n }\r\n if (!container && mergedConfig.containerId) {\r\n container = document.getElementById(mergedConfig.containerId);\r\n if (container) isInline = true;\r\n }\r\n if (!container) {\r\n container = document.getElementById('kiku-mount') || document.querySelector('[data-kiku-mount]');\r\n if (container) isInline = true;\r\n }\r\n\r\n // If no custom inline container was provided and not positioned inline, create floating host\r\n if (!container) {\r\n container = document.createElement('div');\r\n container.id = 'akropolys-kiku-host';\r\n document.body.appendChild(container);\r\n }\r\n\r\n const root = createRoot(container);\r\n root.render(<StandaloneKikuApp config={mergedConfig} isInline={isInline} />);\r\n\r\n setupGlobalTriggers();\r\n\r\n window.Kiku = {\r\n version: '1.7.19',\r\n open: () => {\r\n const btn = document.querySelector('.hsk-cb-btn') as HTMLButtonElement | null;\r\n btn?.click();\r\n },\r\n close: () => {\r\n const closeBtn = document.querySelector('.hsk-cb-topbar-btn[aria-label=\"Close\"]') as HTMLButtonElement | null;\r\n closeBtn?.click();\r\n },\r\n toggle: () => {\r\n const modal = document.querySelector('.hsk-cb-overlay');\r\n if (modal) {\r\n window.Kiku?.close();\r\n } else {\r\n window.Kiku?.open();\r\n }\r\n },\r\n resetPosition: () => {\r\n try {\r\n localStorage.removeItem('akropolys_dock_pos');\r\n window.location.reload();\r\n } catch {}\r\n },\r\n ingest: async (product: ShopifyProduct) => {\r\n const client = getAkropolysClient();\r\n if (client && product) {\r\n const normalized = normalizeShopifyProduct(product);\r\n await client.ingest(normalized);\r\n }\r\n },\r\n getClient: () => getAkropolysClient(),\r\n config: mergedConfig,\r\n };\r\n}\r\n\r\nif (typeof window !== 'undefined') {\r\n const shouldAutoInit = () => {\r\n return Boolean(\r\n window.AkropolysConfig ||\r\n document.getElementById('akropolys-kiku-script') ||\r\n document.getElementById('kiku-mount') ||\r\n document.querySelector('[data-kiku-mount]')\r\n );\r\n };\r\n\r\n const autoRun = () => {\r\n if (shouldAutoInit()) initKiku();\r\n };\r\n\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', autoRun);\r\n } else {\r\n setTimeout(autoRun, 0);\r\n }\r\n}\r\n"],"mappings":"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","names":["src_exports","__export","ChatWidget","KikuButton","SearchBar","Sparkle","VisualSearch","VoiceButton","initKiku","normalizeShopifyProduct","shopifyAddToCart","shopifyGetCart","__toCommonJS","import_react","import_sdk","r","t","f","n","clsx","cn","inputs","clsx","import_jsx_runtime","SearchIcon","SearchBar","placeholder","limit","debounceMs","onSelect","className","inputClassName","dropdownClassName","renderResult","theme","classNames","query","setQuery","open","setOpen","results","loading","search","clear","client","wrap","ignoreNextQueryChange","h","e","handleSelect","r","handleCommitSearch","showDrop","customStyles","cn","i","thumb","import_react","import_sdk","import_react","import_jsx_runtime","SPACING_DOUBLE_REGEX","SPACING_PUNCT_REGEX","SPACING_OPEN_PAREN_REGEX","SPACING_CLOSE_PAREN_REGEX","SPACING_UNIT_REGEX","TOKEN_SPLIT_REGEX","IMAGE_PARSE_REGEX","LINK_PARSE_REGEX","SAFE_IMG_REGEX","SAFE_LINK_REGEX","MEMORY_LINK_FILTER_REGEX","MEMORY_URL_FILTER_REGEX","normalizeSpacing","text","parseInline","keyPrefix","part","index","key","imageMatch","alt","url","e","linkMatch","linkText","isTableLine","line","inTable","splitTableCells","rowLine","t","c","TableWrapper","children","ref","React","scrollState","setScrollState","isDragging","setIsDragging","dragRef","checkScroll","el","rtl","travelled","atStart","atEnd","ro","onMouseDown","onMouseMove","walk","onMouseUp","renderMarkdown","content","streaming","buildMarkdown","lines","last","blocks","currentTextNodes","bubbleIndex","flushTextBubble","i","standaloneImageMatch","headerMatch","level","Tag","listItems","itemText","headerCells","rawBodyRows","alignments","isHeader","cell","trimmed","startColon","endColon","cells","colCount","r","finalAlignments","numericCount","val","headerRow","cIdx","bodyRows","rIdx","import_jsx_runtime","ArrowUpIcon","resolveTheme","theme","vars","import_react","import_react","ctx","analyser","duckGain","timeData","generation","speaking","smoothed","usingFallback","audio","AC","duckSpeech","level","fadeMs","g","now","speechLevel","t","sum","i","v","rms","stopSpeech","generation","speaking","duckGain","ctx","cleanTextForSpeech","text","SENTENCE_END","CHUNK_TARGET","chunkForSpeech","target","pieces","chunks","buf","piece","cut","c","playBuffer","a","gen","resolve","src","watchdog","speak","client","voice","language","bcp47","onStart","onEnd","onError","onRefused","onSecondsLeft","usingFallback","clean","audio","fallbackWebSpeech","synth","t","started","pending","i","result","decoded","e","pickVoice","tag","voices","want","base","candidates","v","loose","utterance","DEFAULT_SILENCE_MS","SPEECH_MARGIN","BARGE_IN_MS","ECHO_REJECT","DUCK_LEVEL","DUCK_FADE_MS","CONFIRM_MS","CONFIRM_FRAMES","MOD_WINDOW","W_ENERGY","W_MODULATION","W_BAND","DUCK_SCORE","useVoiceSession","lang","onUtterance","onError","onBargeIn","silenceMs","paused","active","setActive","hearing","setHearing","interim","setInterim","supported","setSupported","recognitionRef","streamRef","audioCtxRef","analyserRef","rafRef","dataRef","levelRef","floorRef","lastLoudRef","loudSinceRef","transcriptRef","consumedRef","resultLenRef","activeRef","pausedRef","wantRestartRef","stoppingRef","onUtteranceRef","onErrorRef","onBargeInRef","micLevel","micSpectrum","out","a","spectrumBins","envRef","freqRef","duckedRef","duckAtRef","bargeEvidenceRef","voiceLikeness","rms","analyser","env","modulation","mean","v","variance","band","freq","per","lo","hi","inBand","total","i","energy","commit","text","monitor","data","sum","lvl","now","echo","speechLevel","duckSpeech","startRecognition","SR","recognition","event","code","stopRecognition","r","stop","t","start","stream","AC","ctx","e","id","alive","hearingSomething","import_jsx_runtime","MicIcon","active","VoiceButton","onTranscript","onInterim","lang","className","disabled","onError","onTranscriptRef","stopRef","handleUtterance","text","voice","useVoiceSession","import_react","approxBytesOfDataURL","dataURL","i","b64","downscaleImage","file","original","resolve","reject","reader","bitmap","scale","w","h","canvas","cx","keepPNG","out","import_sdk","import_jsx_runtime","CameraIcon","SpinnerIcon","fileToBase64","file","downscaleImage","VisualSearch","onResults","onError","categoryHint","className","disabled","client","inputRef","loading","setLoading","handleFile","base64","res","e","import_jsx_runtime","SparkleIcon","SpeakerIcon","active","SourceCard","source","defaultCurrency","onSelect","isReferenced","cn","ChatWidget","title","placeholder","emptyStateText","emptyStateSuggestions","className","theme","classNames","onSelectSource","enableVoice","enableVision","visionCategoryHint","enableAudioResponse","ttsVoice","autoSpeakResponses","client","messages","sources","referencedIds","chatLoading","streaming","error","send","reset","input","setInput","visualLoading","setVisualLoading","bottomRef","textareaRef","audioEnabled","setAudioEnabled","speakingMsgIndex","setSpeakingMsgIndex","prevStreamingRef","userInitiatedVoiceRef","loading","chatHistory","setChatHistory","lastSyncedCount","newMsgs","prev","next","hookIdx","historyIdx","wasStreaming","spoken","lastMsgIndex","lastMsg","speak","handleSend","q","stopSpeech","handleKey","e","handleInput","t","handleSpeakToggle","idx","text","handleVisualResults","res","preview","userMsg","dna","content","results","assistantMsg","r","fields","d","customStyles","resolveTheme","msg","renderMarkdown","tag","ti","src","si","featured","general","parsed","VisualSearch","err","VoiceButton","ArrowUpIcon","import_react","import_react_dom","cssText_default","CONTAINER_ID","container","shadow","applyStyles","root","sheet","cssText_default","style","getShadowContainer","import_sdk","BASE_FONT","cachedBaseFont","client","hit","p","warmChrome","shopperLanguage","defaults","import_react","MOUNTED","formatFor","url","ext","safeUrl","u","RANGE_SEGMENT","safeRange","r","parts","s","p","safeWeight","w","useMountedFaces","key","css","h","i","id","el","left","scriptFontCSS","font","f","useScriptFontFace","faces","preloadScriptFont","timeoutMs","fonts","loads","resolve","useHostFontFace","theme","t","family","urls","normal","bold","variable","weights","weight","raw","fmt","import_react","DEFAULT_CHIPS","LANGUAGE_CHOICES","endonymFor","lang","typed","l","hit","x","isRTLText","s","ch","code","LANGUAGE_METAS","formatLangName","str","trimmed","getLoadingMeta","k","v","rawName","nativeName","rtl","LIVE_VOICES","VOICE_STORAGE_KEY","DEFAULT_UI_STRINGS","UIStringsContext","React","key","vars","useT","extractName","raw","words","q","w","name","SERVER_ERROR_STRINGS","getFriendlyError","err","tr","code","SERVER_ERROR_STRINGS","str","lower","isSecureOrigin","KIKU_KEY_REVEAL_SECONDS","import_react","import_jsx_runtime","KikuIcon","className","size","tight","cn","SparkleIcon","StopIcon","ExternalIcon","ContinueIcon","CloseIcon","ChevronLeftIcon","ChevronRightIcon","HistoryIcon","BookmarkIcon","TrashIcon","PlusIcon","PaperclipIcon","CopyIcon","size","CheckIcon","MicIcon","className","MicOffIcon","WaveformIcon","active","ArrowUpIcon","SunIcon","MoonIcon","WoodIcon","HeartIcon","CoffeeIcon","StarIcon","XIcon","size","THEMES","SunIcon","MoonIcon","WoodIcon","HeartIcon","CoffeeIcon","StarIcon","DEFAULT_DARK","DEFAULT_LIGHT","isThemeId","value","t","themeDef","id","import_sdk","import_react","rubberBand","offset","dimension","coeff","createSpring","stiffness","damping","onFrame","onRest","value","velocity","target","raf","last","tick","now","dt","steps","h","i","a","start","v","t","v0","useDragToDismiss","panel","scroller","onDismiss","quiescent","enabled","dismissRef","el","dragging","startY","startX","pointerId","lastY","lastT","decided","exiting","spring","host","atTop","s","onDown","e","onMove","dy","dx","raw","onUp","import_react","dist","a","b","pathLength","pts","n","i","bbox","minX","minY","maxX","maxY","p","clamp1000","v","norm","w","h","overlaps","ay0","ax0","ay1","ax1","by0","bx0","by1","bx1","iw","ih","smaller","union","classifyStroke","box","diag","len","endGap","straightness","buildMarkRegions","actions","width","height","strokes","texts","c","used","out","cur","j","import_jsx_runtime","COLORS","MAX_EXPORT_DIM","MarkupEditor","src","onCancel","onSend","t","img","setImg","loadError","setLoadError","tool","setTool","color","setColor","actions","setActions","pendingText","setPendingText","textValue","setTextValue","instruction","setInstruction","exportError","setExportError","canvasRef","drawingRef","textInputRef","el","dims","scale","markLayer","paint","live","canvas","ctx","layer","lctx","all","a","p","i","toCanvasPoint","e","rect","strokeSize","textSize","onPointerDown","onPointerMove","onPointerUp","done","prev","commitText","handleSend","clean","cctx","dataUrl","drawn","buildMarkRegions","hasMarks","c","import_react","import_jsx_runtime","hashSeed","s","h","i","mulberry32","seed","smooth","t","makeNoise","rng","lat","at","x","y","xi","yi","xf","yf","a","b","c","poisson","w","r","cell","gw","gh","grid","pts","active","place","fits","cx","cy","gy","gx","j","dx","dy","ai","px","py","placed","k","ang","rad","wob","motifs","ctx","cap","q","eave","belly","n","dir","l","drupes","ox","oy","side","ax","ay","off","lift","scribbles","nx","ny","turns","rr","lean","len","step","specks","o","accents","rgb","p","mix","A","B","getShimmerColor","normDist","isDarkMode","generateGlyphs","ink","tint","isRTL","themeId","accent","noise","area","raw","fa","fb","reach","angle","ca","sa","poleX","poleY","glyphs","maxDist","ir","ig","ib","d","roll","bloom","axis","isLightMode","alpha","baseColor","glyphSeed","shimmerColor","rotation","lineWidth","size","drawFn","alphaMul","renderDoodles","shimmerProgress","isShimmering","wavePos","waveWidth","g","stroke","lw","diff","surge","glyphRng","KikuDoodles","React","theme","ref","isAnimatingRef","animFrameRef","cachedGlyphsRef","lastWidthRef","cv","numeric","timer","tick","startTime","duration","now","elapsed","rawProgress","progress","dpr","targetW","targetH","updateCanvas","cs","fullScreenH","handleResize","ro","scheme","handleSchemeChange","KikuDoodles_default","import_react","import_sdk","locales_default","import_jsx_runtime","getBuiltinLocale","lang","l","key","locales_default","resolveFirstFamily","varRef","name","el","value","useScriptFont","shopperLanguage","theme","client","chromeStrings","setChromeStrings","chromeCurated","setChromeCurated","chromeReady","setChromeReady","dirKey","isRTL","setIsRTL","builtin","getLoadingMeta","speechLang","setSpeechLang","scriptFont","setScriptFont","baseFont","setBaseFont","meta","cancelled","res","DEFAULT_UI_STRINGS","prev","preloadScriptFont","f","cachedBaseFont","useScriptFontFace","fontStack","React","first","isVarRef","hostName","resolved","host","isNonLatin","latin","other","v","ch","c","fontEpoch","setFontEpoch","live","e","hostFontCovers","sample","text","ctx","hostFamily","withHost","withoutHost","t","vars","s","k","tNode","part","i","m","import_react","useChatScroll","messages","loading","messageRefs","msgsContainerRef","lastExternalScrollRef","showJumpToBottom","setShowJumpToBottom","scrollProgress","setScrollProgress","activeMsgIdx","setActiveMsgIdx","resyncScrollRef","glideScrollRef","touchScrollingRef","stickToBottomRef","alertTick","setAlertTick","awayEpochRef","lastAlertKeyRef","dismissJumpAlertRef","resetAlertArmingRef","el","idle","settle","onTouchStart","onScroll","JUMP_THRESHOLD","STICK_ON","queued","measure","distance","clearUnreadRef","max","line","active","i","node","ro","notifyNewBelow","turn","key","t","unreadBelow","setUnreadBelow","unreadBelowRef","markUnread","clearUnread","jumpAlert","setJumpAlert","jumpAlertRef","alertShownAtRef","clearAlert","resetAlertArming","dismissJumpAlert","jumpToMessage","idx","to","jumpToBottom","bottom","container","raf","before","LAMBDA","LINE_PX","step","snap","v","target","current","written","lastTime","rafId","write","resync","next","update","now","dt","handleWheel","e","scale","maxScroll","lastTop","handleScroll","external","import_react","import_sdk","useKikuKey","lastAction","retryLastMessage","client","keyInput","setKeyInput","keyPhase","setKeyPhase","mintedKey","setMintedKey","mintedPub","setMintedPub","copied","setCopied","keyCountdown","setKeyCountdown","KIKU_KEY_REVEAL_SECONDS","minting","setMinting","copyValue","val","type","t","s","handleUseExistingKey","pub","handleCreateKey","secret","publicId","import_react","useChatCommands","attachments","setAttachments","setInput","send","defaultCurrency","t","handleKikuCapture","product","name","display","q","toSend","handleKikuCaptureAll","products","targets","p","names","handleKikuViewHistory","handleKikuDelete","import_react","import_sdk","import_react","INPUT_RATE","WORKLET_SRC","toBase64","buf","bytes","s","i","fromBase64","b64","bin","useLiveVoice","opts","state","setState","hearing","setHearing","sources","setSources","secondsLeft","setSecondsLeft","wsRef","ctxRef","streamRef","nodeRef","analyserRef","playAtRef","sourcesRef","outAnalyserRef","outRateRef","optsRef","readyRef","armCaptureRef","turnHeardRef","turnSaidRef","flushExchange","heard","said","chirp","beginCapture","arm","micLevel","a","d","sum","v","outbound","micSpectrum","out","spectrumBins","flushPlayback","src","enqueue","pcm","ctx","rate","ch","len","fade","sample","now","at","stopHold","startHold","teardown","finalState","t","stop","start","o","base","url","ws","ev","f","abandoned","stream","e","AC","inAnalyser","outAnalyser","blobUrl","node","srcNode","track","toVoicePhase","s","useVoiceController","voiceLang","speechLang","shopperLanguage","ttsVoice","handleSendUtterance","appendSpokenExchange","client","voiceMode","setVoiceMode","dictateState","setDictateState","voiceError","setVoiceError","voiceMuted","setVoiceMuted","voiceSecondsLeft","setVoiceSecondsLeft","voiceBlocked","setVoiceBlocked","liveVoiceName","setLiveVoiceName","stored","VOICE_STORAGE_KEY","LIVE_VOICES","v","chooseVoice","name","voice","useVoiceSession","text","code","stopSpeech","apiUrl","siteId","token","kikuId","live","useLiveVoice","exchange","err","canConverse","startVoice","mode","isSecureOrigin","stopVoice","voicePhase","voiceConnecting","import_react","import_react","import_jsx_runtime","BODY","MOOD","HOP","hopAt","f","i","t0","s0","l0","t1","s1","l1","u","e","SLOTS","KEYS","clamp","v","b","side","x","y0","y1","bow","n","ym","xb","a","bodyPath","bw","bh","tr","br","rt","rb","p","y","k","ft","fb","NEUTRALS","POPS","RARE_SHADES","pickShade","current","options","s","toRGB","hex","rgbCSS","c","mix","base","tint","amount","MARBLE_PAPER","MARBLE_TINT","MARBLE_FLOOD","ALERT_SHADE","KikuAvatar","state","size","alert","theme","feminine","accessories","onImpact","triggerRef","stateRef","alertRef","isFeminine","showFlower","showLashes","showBlush","bodyRef","maskRef","figRef","decorRef","flowerGRef","cheeksGRef","lashesGRef","lashLRef","lashRRef","warmRef","contactRef","stop1Ref","stop2Ref","stop3Ref","marbleRefs","slotRefs","slotGRef","uid","onImpactRef","reduced","at","vel","slotAt","slotVel","blinkAt","blinkPhase","wander","wanderAt","raf","gooOn","hopDue","hopPhase","lean","leanVel","leanWant","leanAt","peek","peekVel","peekWant","peekAt","shade","deep","pale","deepWant","paleWant","DOUBLE_MS","lastHopAt","pendingEncore","singlesSince","queuedHop","now","puff","puffVel","wasAlert","nagDue","startHop","t","layout","lid","gx","gy","phase","out","eye","cx","dy","h","cycle","fuse","R","frame","shape","mood","facing","puffWant","breath","want","key","stiff","damp","squash","lift","splat","to","currentShade","deepCSS","paleCSS","baseWash","contactOpacity","lastSplat","wobble","bwF","bhF","d","wantGoo","targets","T","A","V","breathe","planted","tilt","shift","dip","flowerX","flowerY","flowerTilt","cheekY","isEyeFacing","lashes","cy","deg","len","th","sx","sy","ex","ey","cxp","cyp","offset","el","_","import_jsx_runtime","ChatTopbar","title","hasMessages","avatarState","unread","awayFromBottom","themeMenuOpen","themeMenuClosing","isNarrow","currentTheme","onJumpToLatest","onReset","onClose","onToggleThemeMenu","onSelectTheme","tr","useT","isImpacting","setIsImpacting","React","impactColor","setImpactColor","impactGlow","setImpactGlow","triggerRef","longPressTimerRef","isLongPressRef","touchStartTimeRef","startPress","endPress","cancelPress","handleClick","e","handleImpact","splat","color","glow","ChevronLeftIcon","cn","KikuAvatar","THEMES","id","label","Icon","import_react","import_react","import_react","import_jsx_runtime","HSK_WORD_STAGGER_MS","plainText","node","React","cascade","count","baseMs","keyPrefix","chunk","ci","delay","child","el","CascadeText","children","text","hash","prefix","import_jsx_runtime","ChromeLoading","language","onBack","meta","getLoadingMeta","CascadeText","import_jsx_runtime","HSK_STAGGER_MS","HSK_FIELD_BASE_MS","JOINING_SCRIPT","splitPlaceholder","text","I","seg","s","AnimatedPlaceholder","placeholder","visible","replay","replaySeed","staggerMs","content","seed","units","last","unit","i","import_jsx_runtime","countShimmerUnits","node","splitPlaceholder","n","c","React","shimmerTree","cursor","last","baseIdx","unit","child","k","ShimmerText","text","OnboardingView","inOnboarding","justCompleted","onboardingMood","awaitingLang","awaitingName","awaitingEntityLang","awaitingConsent","termsAgreed","shopperLanguage","shopperName","entityLangPref","chromeReady","activeChips","t","tNode","chooseLanguage","chooseEntityLang","agreeTerms","handleSend","currentStep","countdown","setCountdown","timer","prev","CascadeText","LANGUAGE_CHOICES","l","i","ChromeLoading","mode","cn","chip","import_react","import_react","import_sdk","import_jsx_runtime","useLiveValues","keys","bump","joined","k","n","id","LiveQuoteCard","record","now","stale","fields","rawTitle","shortTitle","hasYesPrice","hasNoPrice","quotePills","volVal","closeDate","formattedClose","p","flash","LiveTable","seen","ordered","records","_","i","shown","r","import_react","import_jsx_runtime","parseThinking","text","openMatch","openIdx","openTagLength","start","contentBefore","textAfterOpen","closeMatch","closeIdx","closeTagLength","ThinkingBlock","isComplete","fixedSeconds","tr","useT","startRef","seconds","setSeconds","isOpen","setIsOpen","t","finalSeconds","label","expandable","cn","o","import_react","import_sdk","import_jsx_runtime","SourceImg","src","alt","onImageClick","failed","setFailed","SparkleIcon","e","SourcesCarousel","sources","defaultCurrency","onSelectSource","referencedIds","compact","isProperty","railRef","showPrev","setShowPrev","showNext","setShowNext","activeIndex","setActiveIndex","display","s","measure","el","travelled","maxScroll","idx","ro","railStep","dir","rtl","scrollNext","scrollPrev","cn","ChevronLeftIcon","si","isReferenced","ChevronRightIcon","_","i","import_jsx_runtime","SmartContextPills","intent","sources","onSend","loading","defaultCurrency","tr","useT","pills","cheapest","min","s","p","m","firstName","firstTwo","priceCeiling","nums","n","max","mag","rounded","short","ceiling","pill","import_jsx_runtime","MarkdownBlock","React","content","streaming","renderMarkdown","a","b","MessageItem","msg","idx","isLast","isLastUser","isRunEnd","runMid","runCont","isNarrow","loading","stopped","interrupted","sources","referencedIds","discussedSources","lastIntent","lastAction","defaultCurrency","vizState","setVizState","setLightboxSrc","setMarkupSrc","handleSend","handleSourceClick","t","messageRef","isUser","displayContent","cn","img","i","MicIcon","parsed","parseThinking","thinking","CALC_DISCLAIMER_REGEX","hasCalcDisclaimer","cleanContent","isComplete","ThinkingBlock","p","ref","e","LiveTable","n","msgReferencedIds","msgSources","msgIntent","hiddenIntent","SourcesCarousel","ExternalIcon","SmartContextPills","import_jsx_runtime","PromptKeyCard","keyInput","setKeyInput","minting","handleUseExistingKey","handleCreateKey","t","SparkleIcon","e","MintedKeyCard","mintedKey","mintedPub","copied","keyCountdown","onDismiss","copyValue","import_jsx_runtime","ChatMessages","displayMessages","messageRefs","isNarrow","loading","streaming","sources","referencedIds","discussedSources","lastIntent","lastAction","defaultCurrency","stopped","interrupted","halted","haltedEmpty","error","errorCode","keyPhase","keyInput","setKeyInput","mintedKey","setMintedKey","mintedPub","setMintedPub","minting","copied","keyCountdown","handleUseExistingKey","handleCreateKey","copyValue","queuedMessage","sendQueuedNow","setLightboxSrc","setMarkupSrc","handleSend","handleSourceClick","continueGenerating","t","bottomRef","vizState","setVizState","messages","lastUserIdx","i","msg","idx","isLast","isUser","isLastUser","isRunEnd","runMid","runCont","key","MessageItem","el","cn","ContinueIcon","getFriendlyError","PromptKeyCard","MintedKeyCard","import_react","import_jsx_runtime","ChatComposer","gooId","input","setInput","showKikuPicker","setShowKikuPicker","showAtPicker","setShowAtPicker","captureAllowed","discussedSources","defaultCurrency","handleSelectExtension","handleKikuCapture","handleKikuCaptureAll","handleKikuViewHistory","handleKikuDelete","attachments","removeAttachment","chromeLoading","imageInputRef","handleImageFiles","enableVision","enableVoice","canConverse","voiceMode","startVoice","stopVoice","voiceBlocked","textareaRef","classNames","handleInput","handleKeyDown","voice","voicePhase","activePlaceholder","loading","streaming","stop","handleSend","voiceError","setVoiceError","shopperLanguage","t","rail","placeholderReplay","setPlaceholderReplay","React","toolsOpen","setToolsOpen","timer","onKey","e","placeholderSweepMs","splitPlaceholder","HSK_STAGGER_MS","launching","setLaunching","launchTimer","launch","PaperclipIcon","WaveformIcon","prev","SparkleIcon","src","i","BookmarkIcon","HistoryIcon","TrashIcon","att","XIcon","cn","o","PlusIcon","AnimatedPlaceholder","MicIcon","MicOffIcon","StopIcon","ArrowUpIcon","import_react","import_jsx_runtime","parseColor","css","fallback","m","mix","a","b","rgba","c","alpha","BANDS","SPECTRUM_FRACTION","VoiceCanvas","phase","level","spectrum","bins","className","canvasRef","phaseRef","levelRef","spectrumRef","binsRef","canvas","ctx","style","accent","ink","raf","w","h","resize","dpr","rect","ro","reduced","bands","strokes","glow","strokesFor","freqBuf","amp","sweep","start","follow","cur","target","attack","release","readSpectrum","read","n","per","from","to","sum","i","v","synthesizeBands","t","energy","shape","bandAt","x","f","draw","now","p","live","cy","layers","l","depth","hue","maxAmp","step","lag","scale","px","py","u","envelope","focus","band","tl","ripple","y","width","import_jsx_runtime","VoiceOverlay","siteId","themeAttr","stopVoice","chooseVoice","liveVoiceName","voiceSecondsLeft","voiceConnecting","voicePhase","live","voiceMuted","setVoiceMuted","shownSources","onSelectSource","defaultCurrency","voiceError","t","KikuDoodles_default","CloseIcon","LIVE_VOICES","v","i","cn","VoiceCanvas","src","SparkleIcon","m","MicOffIcon","MicIcon","import_jsx_runtime","LightboxModal","src","onClose","CloseIcon","e","import_react","import_jsx_runtime","ConversationTimeline","items","activeIdx","progress","onJump","side","tr","useT","itemRefs","cursorRef","anchor","i","node","cursor","cn","item","el","import_jsx_runtime","ChatModal","title","placeholder","backdropColor","backdropBlur","onClose","onSelectSource","defaultCurrency","chips","DEFAULT_CHIPS","theme","classNames","enableVoice","voiceLang","enableVision","visionCategoryHint","enableAudioResponse","ttsVoice","autoSpeakResponses","origin","client","messages","sources","loading","streaming","error","errorCode","lastAction","lastIntent","allowedActions","send","queuedMessage","sendQueuedNow","appendSpokenExchange","stop","stopped","interrupted","continueGenerating","reset","referencedIds","shopperName","setShopperNameState","shopperLanguage","setShopperLanguageState","entityLangPref","setEntityLangPrefState","justCompleted","setJustCompleted","chromeReady","isRTL","speechLang","scriptFont","fontStack","isNonLatin","hostFontCovers","t","tNode","useScriptFont","discussedSources","React","byRef","s","answer","m","seen","hay","aliases","name","n","w","out","a","named","captureAllowed","input","setInput","showKikuPicker","setShowKikuPicker","showAtPicker","setShowAtPicker","attachments","setAttachments","imageInputRef","vizState","setVizState","lightboxSrc","setLightboxSrc","markupSrc","setMarkupSrc","termsAgreed","setTermsAgreed","onboarding","awaitingLang","awaitingName","awaitingEntityLang","awaitingConsent","inOnboarding","hasLiveData","isNarrow","setIsNarrow","mq","apply","chooseLanguage","lang","v","chooseEntityLang","mode","agreeTerms","activeTitle","activePlaceholder","activeChips","onboardingMood","currentTheme","setCurrentTheme","isThemeId","saved","DEFAULT_LIGHT","DEFAULT_DARK","handleToggleTheme","next","alsoCloseMenu","setThemeMenuOpen","setThemeMenuClosing","customStyles","resolveTheme","hskThemeAttr","useHostFontFace","handleSendRef","handleSend","text","extraAttachments","forcedIntent","captureTargets","raw","extractName","toSend","retryLastMessage","lastUserMsg","keyInput","setKeyInput","keyPhase","setKeyPhase","mintedKey","setMintedKey","mintedPub","setMintedPub","copied","keyCountdown","minting","copyValue","handleUseExistingKey","handleCreateKey","useKikuKey","getStoredKikuId","fromSession","fromLocal","match","displayKikuPub","handleKikuCapture","handleKikuCaptureAll","handleKikuViewHistory","handleKikuDelete","useChatCommands","voiceMode","voicePhase","voiceConnecting","voiceError","setVoiceError","voiceMuted","setVoiceMuted","voiceSecondsLeft","voiceBlocked","liveVoiceName","chooseVoice","canConverse","startVoice","stopVoice","voice","live","useVoiceController","panelRef","themeMenuOpen","themeMenuClosing","themeMenuCloseTimer","themeMenuRef","mobileThemeRef","messageRefs","textareaRef","bottomRef","overlayRef","gooId","closeThemeMenu","handleOutside","e","path","isInsideRail","isInsideMobile","targetEl","isInsideTopbarMark","isInsideOoze","el","msgsContainerRef","lastExternalScrollRef","showJumpToBottom","scrollProgress","activeMsgIdx","unreadBelow","jumpToMessage","jumpToBottom","useChatScroll","useDragToDismiss","prev","vv","root","h","handleReset","handleSourceClick","src","lastAssistant","price","handleSelectExtension","ext","handleKeyDown","composerHeight","singleRowFieldWidth","measureCanvasRef","getTextWidth","font","ctx","autoGrow","box","val","cs","textWidth","threshold","hasNewline","shouldExpand","targetHeight","handleInput","trimmed","handleImageFiles","files","list","file","dataUrl","downscaleImage","removeAttachment","idx","_","i","shownSources","hasTranslucentBackdrop","backdropFilterStyle","halted","displayMessages","inFlight","timelineItems","clean","haltedEmpty","mountTimeRef","UIStringsContext","cn","target","LightboxModal","MarkupEditor","instruction","marks","preview","KikuDoodles_default","ChatTopbar","OnboardingView","ChatMessages","ChatComposer","ConversationTimeline","CheckIcon","CopyIcon","THEMES","id","label","Icon","themeDef","VoiceOverlay","import_jsx_runtime","KikuButton","label","children","icon","title","placeholder","backdropColor","backdropBlur","className","onSelectSource","defaultCurrency","chips","DEFAULT_CHIPS","theme","classNames","enableVoice","voiceLang","enableVision","visionCategoryHint","enableAudioResponse","ttsVoice","autoSpeakResponses","client","open","setOpen","mounted","setMounted","origin","setOrigin","warmShadow","getShadowContainer","warmChrome","DEFAULT_UI_STRINGS","openFrom","el","b","style","br","x","y","w","h","r","ric","warmId","lastPath","originalPush","originalReplace","args","handleNavigation","cic","hskThemeAttr","customStyles","resolveTheme","useHostFontFace","cn","e","ChatModal","import_react","import_react_dom","import_sdk","import_jsx_runtime","SparkleIcon","className","size","cn","CloseIcon","getFriendlyError","err","str","parsed","SparkleModal","productName","limit","backdropColor","backdropBlur","onClose","onNavigate","onResult","theme","classNames","initialProduct","client","fetchedProduct","setFetchedProduct","displayProduct","results","searchLoading","search","messages","sources","chatLoading","chatError","send","chatInput","setChatInput","isMobile","setIsMobile","showSpecs","setShowSpecs","collapseSimilar","setCollapseSimilar","chatBottomRef","chatTextareaRef","res","handleResize","h","e","overlayRef","prevOverflow","prevPosition","prevWidth","handleScrollLock","chatBodyRef","blurVal","bg","handleNav","r","handleSend","text","q","contextQuery","handleKeyDown","handleInput","t","customStyles","displayMessages","msg","idx","isUser","renderMarkdown","similarProducts","isSameName","isSameSlug","price","currency","ArrowUpIcon","key","val","i","Sparkle","product","children","open","setOpen","mounted","setMounted","getShadowContainer","import_react","import_client","import_sdk","import_jsx_runtime","normalizeShopifyProduct","p","id","title","priceStr","image","first","url","category","brand","tags","t","rawDescription","cleanDescription","defaultVariant","variantId","shopifyAddToCart","items","cartItems","item","res","data","err","shopifyGetCart","DraggableDockWrapper","children","position","dockable","isInline","coords","setCoords","isDragging","setIsDragging","dragStartRef","wrapperRef","computeDefault","defX","defY","saved","parsed","clampedX","clampedY","onResize","prev","onPointerDown","e","rect","onPointerMove","dx","dy","width","height","newX","newY","onPointerUp","hadMoved","clickCapturer","ev","StandaloneKikuApp","config","client","prod","normalized","defaultOnAddToCart","KikuButton","setupGlobalTriggers","initKiku","customConfig","scriptConfig","scriptTag","ds","mergedConfig","container","product","shouldAutoInit","autoRun"]}