@akropolys/kiku 1.7.12 → 1.7.13

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 };\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 {renderMarkdown(msg.content)}\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","../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 };\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.statusMessage && idx === chatHistory.length - 1 && !msg.content && (\n <div className=\"hsk-status-live\">\n <span className=\"hsk-status-dot\" />\n <span>{msg.statusMessage}</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"]}