@hachther/akilio-widget 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +301 -0
- package/dist/AkilioWidget.d.ts +4 -0
- package/dist/akilio-widget.css +1 -0
- package/dist/akilio-widget.min.js +45 -0
- package/dist/components/BrandLogo.d.ts +6 -0
- package/dist/components/ChatPanel.d.ts +28 -0
- package/dist/components/Icons.d.ts +9 -0
- package/dist/components/Launcher.d.ts +4 -0
- package/dist/components/MarkdownAnswer.d.ts +3 -0
- package/dist/components/MessageBubble.d.ts +12 -0
- package/dist/components/ProductCards.d.ts +10 -0
- package/dist/driver.js-CVJgNCO-.js +534 -0
- package/dist/hooks/responsive.d.ts +2 -0
- package/dist/hooks/storage.d.ts +18 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.min.js +26479 -0
- package/dist/index.umd.min.cjs +37 -0
- package/dist/lib/client.d.ts +42 -0
- package/dist/lib/copy.d.ts +9 -0
- package/dist/logos/AkilioMark.d.ts +7 -0
- package/dist/logos/AkilioWordmark.d.ts +8 -0
- package/dist/style.css +1 -0
- package/dist/types.d.ts +289 -0
- package/dist/vanilla.d.ts +30 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Akilio Widget
|
|
2
|
+
|
|
3
|
+
Production React and standalone JavaScript widget for the Akilio backend.
|
|
4
|
+
|
|
5
|
+
## Included modes
|
|
6
|
+
|
|
7
|
+
- `floating`: compact chat popover anchored above the floating launcher.
|
|
8
|
+
- `side-panel`: persistent desktop side panel with a mobile drawer fallback.
|
|
9
|
+
- `inline`: renders inside the supplied container.
|
|
10
|
+
- `hybrid`: backward-compatible alias for side panel on desktop and drawer on mobile.
|
|
11
|
+
- `drawer`: full-height overlay drawer opened from the floating launcher.
|
|
12
|
+
|
|
13
|
+
## Build
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
npm run typecheck
|
|
18
|
+
npm run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Production files:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
dist/index.min.js
|
|
25
|
+
dist/index.umd.min.cjs
|
|
26
|
+
dist/index.d.ts
|
|
27
|
+
dist/style.css
|
|
28
|
+
dist/akilio-widget.min.js
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## React
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { AkilioWidget } from '@hachther/akilio-widget';
|
|
35
|
+
import '@hachther/akilio-widget/style.css';
|
|
36
|
+
|
|
37
|
+
<AkilioWidget
|
|
38
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
39
|
+
projectKey='ask_pk_xxx'
|
|
40
|
+
mode='floating'
|
|
41
|
+
colorMode='system'
|
|
42
|
+
auth={{
|
|
43
|
+
getAccessToken: async () => sessionStorage.getItem('akilio_access_token'),
|
|
44
|
+
}}
|
|
45
|
+
requireConsent
|
|
46
|
+
privacyNotice='Questions are processed to provide an AI-generated answer.'
|
|
47
|
+
privacyNoticeUrl='https://example.com/privacy'
|
|
48
|
+
/>;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Custom launcher and controlled state
|
|
52
|
+
|
|
53
|
+
Hide the built-in launcher and control the floating popup from any host element,
|
|
54
|
+
such as a header navigation button:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
const [chatOpen, setChatOpen] = useState(false);
|
|
58
|
+
|
|
59
|
+
<button onClick={() => setChatOpen(true)}>Ask Akilio</button>
|
|
60
|
+
<AkilioWidget
|
|
61
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
62
|
+
projectKey='ask_pk_xxx'
|
|
63
|
+
mode='floating'
|
|
64
|
+
launcher='hidden'
|
|
65
|
+
open={chatOpen}
|
|
66
|
+
onOpenChange={setChatOpen}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or supply a custom React launcher:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<AkilioWidget
|
|
74
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
75
|
+
projectKey='ask_pk_xxx'
|
|
76
|
+
mode='floating'
|
|
77
|
+
launcher={({ open, toggleChat }) => (
|
|
78
|
+
<button className='header-assistant' onClick={toggleChat}>
|
|
79
|
+
{open ? 'Close assistant' : 'Ask Akilio'}
|
|
80
|
+
</button>
|
|
81
|
+
)}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Authentication supports:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
auth={{ accessToken: 'short-lived-jwt' }}
|
|
89
|
+
auth={{ getAccessToken: refreshAndReturnToken }}
|
|
90
|
+
auth={{ apiKey: 'widget-key', apiKeyHeader: 'X-Akilio-Key' }}
|
|
91
|
+
auth={{ credentials: 'include' }}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The token resolver is evaluated for every request, so a host application can rotate short-lived backend tokens without remounting the widget.
|
|
95
|
+
|
|
96
|
+
## Standalone script
|
|
97
|
+
|
|
98
|
+
```html
|
|
99
|
+
<script
|
|
100
|
+
data-akilio-widget
|
|
101
|
+
src="/assets/akilio-widget.min.js"
|
|
102
|
+
data-api-base-url="https://api.akilio-ai.com"
|
|
103
|
+
data-project-key="ask_pk_xxx"
|
|
104
|
+
data-mode="floating"
|
|
105
|
+
data-color-mode="system"
|
|
106
|
+
data-access-token="short-lived-widget-token"
|
|
107
|
+
data-require-consent="true"
|
|
108
|
+
data-privacy-notice="Questions are processed to provide an AI-generated answer."
|
|
109
|
+
data-privacy-notice-url="https://example.com/privacy"
|
|
110
|
+
></script>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For an inline widget:
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<div id="support-assistant" style="height: 680px"></div>
|
|
117
|
+
<script src="/assets/akilio-widget.min.js" data-auto-init="false"></script>
|
|
118
|
+
<script>
|
|
119
|
+
window.Akilio.mount({
|
|
120
|
+
target: '#support-assistant',
|
|
121
|
+
apiBaseUrl: 'https://api.akilio-ai.com',
|
|
122
|
+
projectKey: 'ask_pk_xxx',
|
|
123
|
+
mode: 'inline',
|
|
124
|
+
colorMode: 'system',
|
|
125
|
+
accessToken: 'short-lived-widget-token',
|
|
126
|
+
});
|
|
127
|
+
</script>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The standalone API can hide the launcher and control the chat imperatively:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
const widget = window.Akilio.mount({
|
|
134
|
+
target: '#akilio-root',
|
|
135
|
+
apiBaseUrl: 'https://api.akilio-ai.com',
|
|
136
|
+
projectKey: 'ask_pk_xxx',
|
|
137
|
+
mode: 'floating',
|
|
138
|
+
launcher: 'hidden',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
document.querySelector('#header-chat').addEventListener('click', widget.toggle);
|
|
142
|
+
// widget.open(); widget.close(); widget.destroy();
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Script-tag configuration also accepts `data-launcher="hidden"`.
|
|
146
|
+
|
|
147
|
+
Supported authentication attributes are `data-access-token`, `data-widget-token`, `data-api-key`, and `data-api-key-header`.
|
|
148
|
+
|
|
149
|
+
## Backend contract
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
GET /api/v1/projects/{project_key}/config/
|
|
153
|
+
POST /api/v1/chat/
|
|
154
|
+
GET /api/v1/conversations/{conversation_id}/?project_key=...
|
|
155
|
+
POST /api/v1/messages/{message_id}/feedback/
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Every request uses the configured authentication headers. Chat requests also include consent metadata when available.
|
|
159
|
+
|
|
160
|
+
## Rendering performance
|
|
161
|
+
|
|
162
|
+
The composer maintains its own local input state. Typing therefore does not update the widget root or re-render the message history. Message bubbles and Markdown answers are memoized, and automatic scrolling depends on message count rather than text input changes.
|
|
163
|
+
|
|
164
|
+
Local history retains the latest 60 messages. Server history is restored from the persisted conversation ID when the local message cache is empty.
|
|
165
|
+
|
|
166
|
+
## Manual light/dark switch
|
|
167
|
+
|
|
168
|
+
The widget displays an accessible light/dark toggle in its header by default. The visitor's choice is persisted per project in local storage. When no manual choice exists, `colorMode="system"` follows the operating-system preference.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<AkilioWidget
|
|
172
|
+
apiBaseUrl='https://api.example.com'
|
|
173
|
+
projectKey='project-key'
|
|
174
|
+
colorMode='system'
|
|
175
|
+
allowColorModeToggle
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
For the standalone build, use `data-allow-color-mode-toggle="true"`. Set the React prop or data attribute to `false` to hide the control.
|
|
180
|
+
|
|
181
|
+
## Widget authentication flow
|
|
182
|
+
|
|
183
|
+
By default, the widget now implements the Akilio Public API bootstrap flow automatically:
|
|
184
|
+
|
|
185
|
+
1. Load public configuration from `GET /api/v1/projects/{public_key}/config/`.
|
|
186
|
+
2. Create or reuse a stable browser subject.
|
|
187
|
+
3. Request a short-lived token from `POST /api/v1/projects/{public_key}/widget-token/`.
|
|
188
|
+
4. Send `Authorization: Bearer <token>` to chat, conversation, and feedback endpoints.
|
|
189
|
+
5. Refresh the token before `expires_in` elapses, and retry once after an HTTP 401.
|
|
190
|
+
|
|
191
|
+
No token configuration is required for a normal public widget:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
<AkilioWidget
|
|
195
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
196
|
+
projectKey='your-public-project-key'
|
|
197
|
+
/>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Use a known subject when the host application has one:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
<AkilioWidget
|
|
204
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
205
|
+
projectKey='your-public-project-key'
|
|
206
|
+
externalUserId='customer-123'
|
|
207
|
+
/>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Host-managed tokens remain supported and take precedence over automatic issuance:
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
<AkilioWidget
|
|
214
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
215
|
+
projectKey='your-public-project-key'
|
|
216
|
+
auth={{ getAccessToken: refreshAndReturnToken }}
|
|
217
|
+
/>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Advanced token controls:
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
<AkilioWidget
|
|
224
|
+
apiBaseUrl='https://api.akilio-ai.com'
|
|
225
|
+
projectKey='your-public-project-key'
|
|
226
|
+
auth={{
|
|
227
|
+
autoIssueWidgetToken: true,
|
|
228
|
+
tokenRefreshLeewaySeconds: 30,
|
|
229
|
+
onWidgetToken: ({ expiresAt }) =>
|
|
230
|
+
console.debug('Akilio token expires at', expiresAt),
|
|
231
|
+
}}
|
|
232
|
+
/>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Next.js (App Router)
|
|
236
|
+
|
|
237
|
+
Render the widget from a Client Component because it uses browser functionality after hydration:
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
'use client';
|
|
241
|
+
|
|
242
|
+
import { AkilioWidget } from '@hachther/akilio-widget';
|
|
243
|
+
import '@hachther/akilio-widget/style.css';
|
|
244
|
+
|
|
245
|
+
export function AkilioAssistant() {
|
|
246
|
+
return (
|
|
247
|
+
<AkilioWidget
|
|
248
|
+
apiBaseUrl={process.env.NEXT_PUBLIC_AKILIO_API_URL!}
|
|
249
|
+
projectKey={process.env.NEXT_PUBLIC_AKILIO_PROJECT_KEY!}
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The package itself is now safe to import in an SSR module. The component must still be rendered beneath a `use client` boundary. A dynamic import with `ssr: false` is optional, not required.
|
|
256
|
+
|
|
257
|
+
## Ecommerce responses
|
|
258
|
+
|
|
259
|
+
When the chat API returns a `commerce` capability, the widget automatically displays its products below the assistant answer. No additional configuration is required.
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
<AkilioWidget
|
|
263
|
+
apiBaseUrl="https://api.example.com"
|
|
264
|
+
projectKey="public-project-key"
|
|
265
|
+
onProductClick={(product, variant) => {
|
|
266
|
+
console.log('Product selected', product, variant);
|
|
267
|
+
}}
|
|
268
|
+
/>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Product links open in a new tab. The widget also sends an authenticated commerce event to `/api/v1/commerce/events/` using the response capability (`search` or `recommendation`).
|
|
272
|
+
|
|
273
|
+
## Assistant mode
|
|
274
|
+
|
|
275
|
+
Use `assistantMode` to pass the optional `assistant_mode` routing hint to the chat endpoint:
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
<AkilioWidget
|
|
279
|
+
apiBaseUrl="https://api.example.com"
|
|
280
|
+
projectKey="public-project-key"
|
|
281
|
+
assistantMode="ecommerce"
|
|
282
|
+
/>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Supported values are `auto`, `general`, `knowledge`, `ecommerce`, and `hybrid`. The project configuration remains authoritative; this option only narrows behavior permitted by the backend.
|
|
286
|
+
|
|
287
|
+
For the standalone build:
|
|
288
|
+
|
|
289
|
+
```html
|
|
290
|
+
<script
|
|
291
|
+
src="/akilio-widget.min.js"
|
|
292
|
+
data-akilio-widget
|
|
293
|
+
data-api-base-url="https://api.example.com"
|
|
294
|
+
data-project-key="public-project-key"
|
|
295
|
+
data-assistant-mode="ecommerce"
|
|
296
|
+
></script>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Follow-up suggestions
|
|
300
|
+
|
|
301
|
+
When `/api/v1/chat/` returns a `suggestions` array, the widget displays accessible suggestion chips under that assistant response. Selecting a chip sends it as the next user message. Suggestions are retained in local history and restored from server conversation message metadata or structured content when supplied by the API.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import 'driver.js/dist/driver.css';
|
|
2
|
+
import './styles.css';
|
|
3
|
+
import type { AkilioWidgetProps } from './types';
|
|
4
|
+
export declare function AkilioWidget({ apiBaseUrl, projectKey, locale, mode, colorMode, allowColorModeToggle, defaultOpen, open: controlledOpen, launcher, persistOpenState, enableTour, enableLocalHistory, enableServerHistorySync, anonymousId, externalUserId, channel, audience, productArea, assistantMode, pageContext, auth, accessToken, privacyNotice, privacyNoticeUrl, requireConsent, consentNoticeVersion, initialConsent, onConsentChange, copy: copyOverrides, theme, className, onOpenChange, onMessage, onProductClick, onError, }: AkilioWidgetProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.driver-popover{all:unset;font-family:var(--driver-popover-font-family,"Helvetica Neue", Inter, ui-sans-serif, "Apple Color Emoji", Helvetica, Arial, sans-serif);box-sizing:border-box;color:#2d2d2d;z-index:1000000000;background-color:#fff;border-radius:5px;min-width:250px;max-width:300px;margin:0;padding:15px;position:fixed;top:0;right:0;box-shadow:0 1px 10px #0006}.driver-popover-title{zoom:1;margin:0;font-size:19px;font-weight:700;line-height:1.5;display:block;position:relative}.driver-popover-close-btn{all:unset;cursor:pointer;color:#d2d2d2;z-index:1;text-align:center;width:32px;height:28px;font-size:18px;font-weight:500;transition:color .2s;position:absolute;top:0;right:0}.driver-popover-close-btn:hover,.driver-popover-close-btn:focus{color:#2d2d2d}.driver-popover-title[style*=block]+.driver-popover-description{margin-top:5px}.driver-popover-description{zoom:1;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.5}.driver-popover-footer{text-align:right;zoom:1;justify-content:space-between;align-items:center;margin-top:15px;display:flex}.driver-popover-progress-text{color:#727272;zoom:1;font-size:13px;font-weight:400}.driver-popover-footer-btn{all:unset;box-sizing:border-box;color:#2d2d2d;cursor:pointer;zoom:1;background-color:#fff;border:1px solid #ccc;border-radius:3px;outline:0;padding:3px 7px;font-size:12px;line-height:1.3;text-decoration:none;display:inline-block}.driver-popover-footer .driver-popover-btn-disabled{opacity:.5;pointer-events:none}.driver-popover-footer-btn:hover,.driver-popover-footer-btn:focus{background-color:#f7f7f7}.driver-popover-navigation-btns{flex-grow:1;justify-content:flex-end;display:flex}.driver-popover-navigation-btns button+button{margin-left:4px}.driver-popover-arrow{content:"";border:5px solid #fff;position:absolute}.driver-popover-arrow-side-over{display:none}.driver-popover-arrow-side-left{border-top-color:#0000;border-bottom-color:#0000;border-right-color:#0000;left:100%}.driver-popover-arrow-side-right{border-top-color:#0000;border-bottom-color:#0000;border-left-color:#0000;right:100%}.driver-popover-arrow-side-top{border-bottom-color:#0000;border-left-color:#0000;border-right-color:#0000;top:100%}.driver-popover-arrow-side-bottom{border-top-color:#0000;border-left-color:#0000;border-right-color:#0000;bottom:100%}.driver-popover-arrow-side-center,.driver-popover-arrow-none{display:none}.driver-active .driver-overlay{pointer-events:none}.driver-active.driver-no-scroll{overflow:hidden}.driver-active *{pointer-events:none}.driver-active .driver-active-element,.driver-active .driver-active-element *,.driver-popover,.driver-popover *{pointer-events:auto}@keyframes animate-fade-in{0%{opacity:0}to{opacity:1}}.driver-fade .driver-overlay{animation:animate-fade-in var(--driver-animation-duration,.4s) ease-in-out}.driver-fade .driver-popover{animation:animate-fade-in var(--driver-animation-duration,.4s)}.driver-active-element-parent-no-scroll{overflow:hidden!important}.driver-no-interaction,.driver-no-interaction *{pointer-events:none!important}:root{--akilio-primary: #0891b2;--akilio-primary-foreground: #ffffff;--akilio-accent: #2563eb;--akilio-radius: 22px;--akilio-panel-width: 440px;--akilio-z-index: 2147483000}@media(min-width:1280px){html.akilio-panel-open body{padding-right:var(--akilio-panel-width);transition:padding-right .26s ease}html.akilio-panel-open #akilio-launcher{transform:translate(calc(-1 * var(--akilio-panel-width)))}}.akilio-root,.akilio-root *{box-sizing:border-box}.akilio-root{color:#18181b;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.akilio-launcher{position:fixed;right:22px;bottom:22px;z-index:calc(var(--akilio-z-index) - 10);display:inline-flex;align-items:center;gap:10px;border:1px solid rgba(255,255,255,.22);border-radius:999px;background:linear-gradient(135deg,#09090b,#27272a);color:#fff;padding:11px 16px 11px 12px;cursor:pointer;box-shadow:0 24px 60px #18181b40,0 0 0 1px #09090b14;transition:transform .26s ease,box-shadow .18s ease,background .18s ease}.akilio-launcher:hover{transform:translateY(-2px);box-shadow:0 28px 70px #0891b240,0 0 0 1px #09090b14}.akilio-launcher span{display:grid;width:30px;height:30px;place-items:center;overflow:hidden;border-radius:999px;background:#fff}.akilio-launcher-logo{display:block;width:22px;height:22px;object-fit:contain}.akilio-launcher strong{font-size:14px;font-weight:750;letter-spacing:-.01em}.akilio-overlay{position:fixed;inset:0;z-index:calc(var(--akilio-z-index) - 2);border:0;background:#09090b75;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);cursor:default}.akilio-panel{position:fixed;top:0;right:0;z-index:var(--akilio-z-index);display:flex;width:min(100vw,var(--akilio-panel-width));height:100dvh;transform:translate(103%);flex-direction:column;overflow:hidden;border-left:1px solid rgba(212,212,216,.9);background:#f8fafc;box-shadow:-30px 0 90px #0f172a3d;transition:transform .26s cubic-bezier(.2,.8,.2,1)}.akilio-panel--open{transform:translate(0)}.akilio-root[data-akilio-mode=floating] .akilio-panel{top:auto;right:22px;bottom:88px;width:min(400px,calc(100vw - 32px));height:min(650px,calc(100dvh - 116px));min-height:420px;transform:translateY(18px) scale(.98);transform-origin:right bottom;border:1px solid rgba(212,212,216,.9);border-radius:var(--akilio-radius);box-shadow:0 28px 80px #0f172a3d;opacity:0;visibility:hidden;pointer-events:none;transition:transform .22s cubic-bezier(.2,.8,.2,1),opacity .18s ease,visibility .18s ease}.akilio-root[data-akilio-mode=floating] .akilio-panel--open{transform:translateY(0) scale(1);opacity:1;visibility:visible;pointer-events:auto}.akilio-panel-glow{position:absolute;inset:0 0 auto;height:185px;pointer-events:none;background:radial-gradient(circle at 0% 0%,color-mix(in srgb,var(--akilio-primary) 35%,transparent),transparent 36%),radial-gradient(circle at 100% 0%,rgba(37,99,235,.22),transparent 34%)}.akilio-panel-header{position:relative;display:flex;align-items:flex-start;gap:12px;border-bottom:1px solid rgba(212,212,216,.82);background:#ffffffc7;padding:16px;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.akilio-logo,.akilio-empty-icon{display:grid;flex-shrink:0;place-items:center}.akilio-logo{width:94px;height:34px}.akilio-logo img{display:block;width:100%;height:100%;object-fit:contain;object-position:left center}.akilio-empty-icon{width:64px;height:64px;border:1px solid rgba(124,58,237,.12);border-radius:calc(var(--akilio-radius) - 4px);background:#ffffffe0;box-shadow:0 18px 42px #6d28d929}.akilio-empty-icon img{display:block;width:42px;height:42px;object-fit:contain}.akilio-header-content{min-width:0;flex:1}.akilio-header-topline{display:flex;min-width:0;align-items:center;justify-content:space-between;gap:10px}.akilio-header-title{display:flex;min-width:0;align-items:center;gap:8px}.akilio-header-title h2{overflow:hidden;margin:0;color:#09090b;font-size:14px;font-weight:800;letter-spacing:-.015em;text-overflow:ellipsis;white-space:nowrap}.akilio-online{display:inline-flex;align-items:center;gap:5px;border-radius:999px;background:#10b9811f;color:#047857;padding:3px 8px;font-size:10px;font-weight:800;white-space:nowrap}.akilio-online i{width:6px;height:6px;border-radius:999px;background:#10b981}.akilio-header-description{display:-webkit-box;margin:6px 0 0;overflow:hidden;color:#71717a;font-size:12px;line-height:1.55;-webkit-box-orient:vertical;-webkit-line-clamp:3}.akilio-header-actions{display:flex;flex-shrink:0;align-items:center;gap:4px}.akilio-header-actions button{display:grid;width:36px;height:36px;place-items:center;border:0;border-radius:999px;background:transparent;color:#71717a;cursor:pointer;transition:background .16s ease,color .16s ease}.akilio-header-actions button:hover{background:#f4f4f5;color:#09090b}.akilio-header-actions svg{width:18px;height:18px}.akilio-thread{position:relative;display:flex;flex:1;flex-direction:column;gap:14px;overflow-y:auto;padding:18px 16px 22px}.akilio-message-row{display:flex;width:100%}.akilio-message-row--user{justify-content:flex-end}.akilio-message-row--assistant{justify-content:flex-start}.akilio-bubble{max-width:88%;overflow:hidden;border:1px solid rgba(212,212,216,.86);border-radius:26px 26px 26px 8px;background:#fffffff0;color:#27272a;padding:13px 15px;box-shadow:0 10px 28px #0f172a12}.akilio-bubble--user{border-color:#ffffff26;border-bottom-right-radius:8px;border-bottom-left-radius:26px;background:linear-gradient(135deg,#09090b,#27272a);color:#fff}.akilio-bubble--error{border-color:#f8717159;background:#fef2f2;color:#991b1b}.akilio-bubble-meta{display:flex;align-items:center;gap:7px;margin-bottom:8px;color:var(--akilio-primary);font-size:10px;font-weight:850;letter-spacing:.15em;text-transform:uppercase}.akilio-mini-icon{width:14px;height:14px}.akilio-confidence{margin-left:auto;border-radius:999px;background:color-mix(in srgb,var(--akilio-primary) 11%,transparent);padding:2px 7px;color:var(--akilio-primary);letter-spacing:0;text-transform:none}.akilio-answer{color:inherit;font-size:14px;line-height:1.7}.akilio-answer p{margin:.5rem 0}.akilio-answer p:first-child{margin-top:0}.akilio-answer p:last-child{margin-bottom:0}.akilio-answer ul,.akilio-answer ol{margin:.625rem 0 .625rem 1.25rem;padding-left:.75rem}.akilio-answer ul{list-style:disc}.akilio-answer ol{list-style:decimal}.akilio-answer li{margin:.25rem 0}.akilio-answer a{color:var(--akilio-primary);font-weight:700;text-decoration:underline;text-underline-offset:3px}.akilio-answer code{border-radius:7px;background:#0f172a14;padding:.12rem .35rem;font-size:.86em}.akilio-answer pre{margin:.75rem 0;overflow-x:auto;border:1px solid rgba(148,163,184,.2);border-radius:16px;background:#020617;padding:13px}.akilio-answer pre code{background:transparent;color:#e2e8f0;padding:0}.akilio-answer .hljs-keyword,.akilio-answer .hljs-selector-tag,.akilio-answer .hljs-built_in{color:#f0abfc}.akilio-answer .hljs-string,.akilio-answer .hljs-attr,.akilio-answer .hljs-symbol{color:#86efac}.akilio-answer .hljs-number,.akilio-answer .hljs-literal{color:#fcd34d}.akilio-answer .hljs-comment{color:#64748b;font-style:italic}.akilio-answer .hljs-title,.akilio-answer .hljs-function{color:#7dd3fc}.akilio-answer .hljs-variable{color:#fdba74}.akilio-answer--user{white-space:pre-wrap}.akilio-answer--user code{background:#ffffff29}.akilio-sources{margin-top:11px;overflow:hidden;border:1px solid rgba(212,212,216,.85);border-radius:16px;background:#f4f4f5c7}.akilio-sources summary{cursor:pointer;padding:9px 11px;color:#52525b;font-size:12px;font-weight:800}.akilio-sources-list{display:grid;gap:8px;border-top:1px solid rgba(212,212,216,.85);padding:8px}.akilio-source-card{display:grid;gap:3px;border:1px solid rgba(212,212,216,.82);border-radius:13px;background:#fff;padding:8px;font-size:12px}.akilio-source-card strong{color:#18181b}.akilio-source-card span{color:#71717a}.akilio-source-card a{overflow:hidden;color:var(--akilio-primary);text-overflow:ellipsis;white-space:nowrap}.akilio-feedback{display:flex;align-items:center;gap:7px;margin-top:11px;color:#71717a;font-size:11px}.akilio-feedback span{margin-right:auto}.akilio-feedback button{display:grid;width:28px;height:28px;place-items:center;border:1px solid rgba(212,212,216,.9);border-radius:999px;background:#fff;color:#71717a;cursor:pointer}.akilio-feedback button:hover,.akilio-feedback .akilio-feedback-active{border-color:color-mix(in srgb,var(--akilio-primary) 35%,#d4d4d8);color:var(--akilio-primary)}.akilio-feedback svg{width:14px;height:14px}.akilio-dots{display:flex;gap:6px;padding:2px 0}.akilio-dots span{width:8px;height:8px;border-radius:999px;background:var(--akilio-primary);animation:akilio-bounce .9s infinite ease-in-out}.akilio-dots span:nth-child(2){animation-delay:.1s}.akilio-dots span:nth-child(3){animation-delay:.2s}@keyframes akilio-bounce{0%,80%,to{transform:translateY(0);opacity:.45}40%{transform:translateY(-4px);opacity:1}}.akilio-empty{margin:auto;display:flex;max-width:340px;flex-direction:column;align-items:center;padding:34px 0;text-align:center}.akilio-empty-icon{width:58px;height:58px;margin-bottom:16px}.akilio-empty h3{margin:0;color:#09090b;font-size:17px;font-weight:850;letter-spacing:-.02em}.akilio-empty p{margin:8px 0 0;color:#71717a;font-size:14px;line-height:1.65}.akilio-suggestions{display:grid;width:100%;gap:9px;margin-top:18px}.akilio-suggestions button{border:1px solid rgba(212,212,216,.9);border-radius:16px;background:#fff;color:#3f3f46;cursor:pointer;padding:10px 12px;text-align:left;font-size:12px;font-weight:700;box-shadow:0 5px 14px #0f172a0a;transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease}.akilio-suggestions button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--akilio-primary) 35%,#d4d4d8);box-shadow:0 12px 22px #0f172a14}.akilio-composer{position:relative;border-top:1px solid rgba(212,212,216,.85);background:#ffffffdb;padding:12px;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.akilio-composer-box{border:1px solid rgba(212,212,216,.95);border-radius:24px;background:#f8fafc;padding:8px;box-shadow:inset 0 1px 2px #0f172a0a;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease}.akilio-composer-box:focus-within{border-color:color-mix(in srgb,var(--akilio-primary) 55%,#d4d4d8);background:#fff;box-shadow:0 0 0 4px color-mix(in srgb,var(--akilio-primary) 13%,transparent),inset 0 1px 2px #0f172a08}.akilio-composer textarea{width:100%;min-height:48px;max-height:148px;resize:none;border:0;outline:0;background:transparent;color:#09090b;padding:8px 10px;font:inherit;font-size:14px;line-height:1.55}.akilio-composer textarea::placeholder{color:#a1a1aa}.akilio-composer-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 2px 2px 7px}.akilio-composer-footer span{color:#71717a;font-size:11px}.akilio-composer-footer button{display:inline-flex;align-items:center;gap:8px;border:0;border-radius:999px;background:#09090b;color:#fff;cursor:pointer;padding:10px 15px;font-size:12px;font-weight:850;box-shadow:0 10px 24px #0f172a24;transition:transform .15s ease,opacity .15s ease}.akilio-composer-footer button:hover:not(:disabled){transform:translateY(-1px)}.akilio-composer-footer button:disabled{cursor:not-allowed;opacity:.45}.akilio-composer-footer svg{width:15px;height:15px}.akilio-tour{max-width:360px;border-radius:18px!important}@media(max-width:640px){.akilio-launcher{right:16px;bottom:16px;padding:10px 12px}.akilio-launcher strong{display:none}.akilio-panel{width:100vw}.akilio-bubble{max-width:94%}.akilio-composer-footer span{display:none}}.akilio-root[data-akilio-mode=inline]{width:100%;height:100%;min-height:520px}.akilio-panel--inline{position:relative;inset:auto;width:100%;height:100%;min-height:520px;transform:none;border:1px solid rgba(212,212,216,.9);border-radius:var(--akilio-radius);box-shadow:0 18px 50px #0f172a1f}.akilio-privacy{display:grid;gap:8px;border-top:1px solid rgba(212,212,216,.82);background:#ffffffe6;padding:10px 14px;font-size:11px;line-height:1.45}.akilio-privacy strong{color:#18181b}.akilio-privacy p{margin:2px 0 0;color:#71717a}.akilio-privacy a{color:var(--akilio-primary);font-weight:700}.akilio-privacy label{display:flex;align-items:flex-start;gap:8px;color:#3f3f46;cursor:pointer}.akilio-privacy input{margin-top:2px;accent-color:var(--akilio-primary)}.akilio-composer textarea:disabled{cursor:not-allowed;opacity:.65}.akilio-root button:focus-visible,.akilio-root a:focus-visible,.akilio-root input:focus-visible{outline:3px solid color-mix(in srgb,var(--akilio-primary) 45%,transparent);outline-offset:2px}.akilio-root .akilio-composer textarea:focus,.akilio-root .akilio-composer textarea:focus-visible{border:0;outline:none;box-shadow:none}@media(prefers-reduced-motion:reduce){.akilio-root *,.akilio-root *:before,.akilio-root *:after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.akilio-root[data-akilio-color-mode=dark]{color:#e4e4e7}.akilio-root[data-akilio-color-mode=dark] .akilio-panel,.akilio-root[data-akilio-color-mode=dark] .akilio-panel--inline{background:var(--akilio-surface, #09090b);border-color:#27272a}.akilio-root[data-akilio-color-mode=dark] .akilio-panel-header,.akilio-root[data-akilio-color-mode=dark] .akilio-privacy{background:#18181beb;border-color:#3f3f46}.akilio-root[data-akilio-color-mode=dark] .akilio-header-title h2,.akilio-root[data-akilio-color-mode=dark] .akilio-empty h3,.akilio-root[data-akilio-color-mode=dark] .akilio-privacy strong{color:var(--akilio-text, #fafafa)}.akilio-root[data-akilio-color-mode=dark] .akilio-header-description,.akilio-root[data-akilio-color-mode=dark] .akilio-empty p,.akilio-root[data-akilio-color-mode=dark] .akilio-privacy p,.akilio-root[data-akilio-color-mode=dark] .akilio-privacy label{color:var(--akilio-muted, #a1a1aa)}.akilio-root[data-akilio-color-mode=dark] .akilio-bubble{background:#18181b;border-color:#3f3f46;color:#e4e4e7;box-shadow:none}.akilio-root[data-akilio-color-mode=dark] .akilio-bubble--user{background:linear-gradient(135deg,var(--akilio-primary),var(--akilio-accent));color:var(--akilio-primary-foreground)}.akilio-root[data-akilio-color-mode=dark] .akilio-sources{background:#09090b;border-color:#3f3f46}.akilio-root[data-akilio-color-mode=dark] .akilio-sources-list{border-color:#3f3f46}.akilio-root[data-akilio-color-mode=dark] .akilio-source-card,.akilio-root[data-akilio-color-mode=dark] .akilio-feedback button,.akilio-root[data-akilio-color-mode=dark] .akilio-composer-box{background:#18181b;border-color:#3f3f46;color:#e4e4e7}.akilio-root[data-akilio-color-mode=dark] .akilio-source-card strong{color:#fafafa}.akilio-root[data-akilio-color-mode=dark] .akilio-source-card span,.akilio-root[data-akilio-color-mode=dark] .akilio-feedback{color:#a1a1aa}@media(prefers-color-scheme:dark){.akilio-root[data-akilio-color-mode=system] .akilio-panel,.akilio-root[data-akilio-color-mode=system] .akilio-panel--inline{background:#09090b;border-color:#27272a}.akilio-root[data-akilio-color-mode=system] .akilio-panel-header,.akilio-root[data-akilio-color-mode=system] .akilio-privacy{background:#18181beb;border-color:#3f3f46}.akilio-root[data-akilio-color-mode=system] .akilio-header-title h2,.akilio-root[data-akilio-color-mode=system] .akilio-empty h3,.akilio-root[data-akilio-color-mode=system] .akilio-privacy strong{color:#fafafa}.akilio-root[data-akilio-color-mode=system] .akilio-header-description,.akilio-root[data-akilio-color-mode=system] .akilio-empty p,.akilio-root[data-akilio-color-mode=system] .akilio-privacy p,.akilio-root[data-akilio-color-mode=system] .akilio-privacy label{color:#a1a1aa}.akilio-root[data-akilio-color-mode=system] .akilio-bubble{background:#18181b;border-color:#3f3f46;color:#e4e4e7;box-shadow:none}.akilio-root[data-akilio-color-mode=system] .akilio-bubble--user{background:linear-gradient(135deg,var(--akilio-primary),var(--akilio-accent));color:var(--akilio-primary-foreground)}.akilio-root[data-akilio-color-mode=system] .akilio-source-card,.akilio-root[data-akilio-color-mode=system] .akilio-feedback button,.akilio-root[data-akilio-color-mode=system] .akilio-composer-box{background:#18181b;border-color:#3f3f46;color:#e4e4e7}}@media(max-width:640px){.akilio-launcher{right:14px;bottom:max(14px,env(safe-area-inset-bottom));padding:10px}.akilio-launcher strong{display:none}.akilio-panel{width:100vw;height:100dvh;border-left:0}.akilio-root[data-akilio-mode=floating] .akilio-panel{right:14px;bottom:calc(76px + env(safe-area-inset-bottom));width:calc(100vw - 28px);height:min(640px,calc(100dvh - 104px - env(safe-area-inset-bottom)));min-height:min(420px,calc(100dvh - 104px));border:1px solid rgba(212,212,216,.9);border-radius:18px}.akilio-panel-header{padding-top:max(14px,env(safe-area-inset-top))}.akilio-thread{padding-inline:12px}.akilio-bubble{max-width:94%}.akilio-composer{padding-bottom:max(10px,env(safe-area-inset-bottom))}.akilio-root[data-akilio-mode=inline]{min-height:480px}.akilio-panel--inline{min-height:480px;border-radius:16px}}.akilio-root[data-akilio-color-mode=dark] .akilio-composer{background:#18181beb;border-color:#3f3f46}.akilio-root[data-akilio-color-mode=dark] .akilio-composer textarea{color:var(--akilio-text, #fafafa);caret-color:var(--akilio-text, #fafafa);-webkit-text-fill-color:var(--akilio-text, #fafafa)}.akilio-root[data-akilio-color-mode=dark] .akilio-composer textarea::placeholder{color:var(--akilio-muted, #a1a1aa);-webkit-text-fill-color:var(--akilio-muted, #a1a1aa);opacity:1}.akilio-root[data-akilio-color-mode=dark] .akilio-composer-footer span{color:var(--akilio-muted, #a1a1aa)}.akilio-root[data-akilio-color-mode=dark] .akilio-composer-box:focus-within{background:#18181b}@media(max-width:420px){.akilio-logo{width:78px;height:30px}}.akilio-privacy-consent-copy{margin-top:6px!important}.akilio-privacy-actions{display:flex;justify-content:flex-end;gap:8px}.akilio-privacy-actions button{border:1px solid rgba(161,161,170,.65);border-radius:999px;padding:6px 12px;font:inherit;font-weight:700;cursor:pointer}.akilio-privacy-decline{background:transparent;color:#52525b}.akilio-privacy-accept{border-color:var(--akilio-primary)!important;background:var(--akilio-primary);color:#fff}.akilio-privacy-review{border:0;background:transparent;color:var(--akilio-primary);font:inherit;font-weight:700;text-decoration:underline;cursor:pointer;padding:0}.akilio-products{margin-top:14px;min-width:0}.akilio-products-heading{display:flex;align-items:center;justify-content:space-between;margin-bottom:9px;font-size:12px;color:#64748b}.akilio-products-heading span{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 7px;border-radius:999px;background:#eef2ff;color:#4338ca;font-weight:700}.akilio-product-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.akilio-product-card{min-width:0;overflow:hidden;border:1px solid #e2e8f0;border-radius:16px;background:#fff;box-shadow:0 6px 20px #0f172a0f}.akilio-product-media{position:relative;aspect-ratio:4 / 3;overflow:hidden;background:#f1f5f9}.akilio-product-media img{width:100%;height:100%;display:block;object-fit:cover;transition:transform .18s ease}.akilio-product-card:hover .akilio-product-media img{transform:scale(1.025)}.akilio-product-placeholder{width:100%;height:100%;display:grid;place-items:center;color:var(--akilio-primary);font-size:30px;font-weight:800;background:linear-gradient(145deg,#0891b21f,#2563eb14)}.akilio-stock{position:absolute;top:8px;right:8px;max-width:calc(100% - 16px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px 7px;border-radius:999px;background:#7f1d1de6;color:#fff;font-size:9px;font-weight:700}.akilio-stock--available{background:#065f46e6}.akilio-product-body{padding:11px}.akilio-product-vendor,.akilio-product-variant{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#64748b;font-size:10px}.akilio-product-card h4{margin:4px 0 8px;min-height:34px;overflow:hidden;color:#0f172a;font-size:13px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.akilio-product-price{min-height:37px;display:flex;flex-wrap:wrap;align-items:baseline;gap:5px;margin-bottom:9px}.akilio-product-price strong{color:#0f172a;font-size:14px}.akilio-product-price del{color:#94a3b8;font-size:10px}.akilio-product-action{width:100%;min-height:34px;display:inline-flex;align-items:center;justify-content:center;padding:7px 10px;border:0;border-radius:10px;background:var(--akilio-primary);color:var(--akilio-primary-foreground);font:inherit;font-size:11px;font-weight:700;text-decoration:none;cursor:pointer}.akilio-product-action:hover{filter:brightness(.96)}.akilio-product-action:focus-visible{outline:3px solid color-mix(in srgb,var(--akilio-primary) 28%,transparent);outline-offset:2px}.akilio-product-action:disabled{opacity:.55;cursor:not-allowed}.akilio-root[data-akilio-color-mode=dark] .akilio-products-heading{color:#94a3b8}.akilio-root[data-akilio-color-mode=dark] .akilio-products-heading span{background:#312e81;color:#e0e7ff}.akilio-root[data-akilio-color-mode=dark] .akilio-product-card{background:#111827;border-color:#334155;box-shadow:none}.akilio-root[data-akilio-color-mode=dark] .akilio-product-media{background:#1e293b}.akilio-root[data-akilio-color-mode=dark] .akilio-product-card h4,.akilio-root[data-akilio-color-mode=dark] .akilio-product-price strong{color:#f8fafc}.akilio-root[data-akilio-color-mode=dark] .akilio-product-vendor,.akilio-root[data-akilio-color-mode=dark] .akilio-product-variant{color:#94a3b8}@media(max-width:390px){.akilio-product-grid{grid-template-columns:1fr}.akilio-product-media{aspect-ratio:16 / 9}}.akilio-response-suggestions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.akilio-response-suggestions button{appearance:none;border:1px solid color-mix(in srgb,var(--akilio-primary) 26%,#d4d4d8);border-radius:999px;background:color-mix(in srgb,var(--akilio-primary) 7%,#ffffff);color:color-mix(in srgb,var(--akilio-primary) 72%,#18181b);cursor:pointer;padding:8px 11px;text-align:left;font:inherit;font-size:12px;font-weight:700;line-height:1.35;transition:transform .15s ease,border-color .15s ease,background .15s ease}.akilio-response-suggestions button:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--akilio-primary) 52%,#d4d4d8);background:color-mix(in srgb,var(--akilio-primary) 12%,#ffffff)}.akilio-response-suggestions button:focus-visible{outline:3px solid color-mix(in srgb,var(--akilio-primary) 24%,transparent);outline-offset:2px}.akilio-root[data-akilio-color-mode=dark] .akilio-response-suggestions button{border-color:color-mix(in srgb,var(--akilio-primary) 34%,#3f3f46);background:color-mix(in srgb,var(--akilio-primary) 14%,#18181b);color:#f4f4f5}
|