hanc-webrtc-widgets 2.0.2 → 2.1.1

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 CHANGED
@@ -1,503 +1,166 @@
1
- # Hanc-webrtc-widgets
1
+ # Hanc WebRTC Widgets
2
2
 
3
- **Hanc-webrtc-widgets** is a Web Components library for easily integrating **Hanc AI call widgets** into your website or web application.
3
+ Audio-reactive AI call widgets powered by the **hanc-ai-orb** renderer and LiveKit voice calls. Ship a glossy, stateful orb that reacts to voice, respects system themes, and exposes a full programmatic API.
4
4
 
5
- It provides ready-to-use, customizable, and lightweight UI widgets for initiating AI-driven voice calls, without the need for any frontend frameworks.
5
+ ## Highlights
6
+ - Three.js + GLSL orb with real audio reactivity (agent voice, mic, or simulated)
7
+ - LiveKit calling flow with start/end sounds and clear state handling
8
+ - 3 display modes: inline (hero), float (docked), pill (compact CTA)
9
+ - Theme-aware color presets, custom palettes, and advanced orb tuning via JSON
10
+ - Web Components plus direct `HancAiWidget` class for low-level control
6
11
 
7
- You can use it in **plain HTML**, or integrate it with **React**, **Next.js**, or any other modern frontend stack.
8
-
9
- ## What's New
10
-
11
- - Light/dark orb color overrides via `orb-color-light` and `orb-color-dark`.
12
- - Active-state overrides per theme via `active-orb-color-light` and `active-orb-color-dark`.
13
- - Smoother neural-network transitions between connected and idle states.
14
-
15
- ### Examples
16
-
17
- Inline (different colors per theme):
12
+ ## Quick Start (Web Component)
18
13
 
19
14
  ```html
15
+ <script type="module" src="https://unpkg.com/hanc-webrtc-widgets"></script>
16
+
20
17
  <hanc-ai-inline-call
21
18
  agent-id="YOUR_AGENT_ID"
22
- orb-color-light="#6d28d9"
23
- orb-color-dark="#8b5cf6"
24
- active-orb-color-light="#16a34a"
25
- active-orb-color-dark="#22c55e"
19
+ voice-service-url="https://voice.hanc.ai"
20
+ size="320"
21
+ color-preset="indigo"
22
+ theme="auto"
26
23
  ></hanc-ai-inline-call>
27
24
  ```
28
25
 
29
- Floating (same behavior, colors optional per theme):
26
+ ### Other layouts
30
27
 
31
28
  ```html
29
+ <!-- Floating orb -->
32
30
  <hanc-ai-floating-call
33
31
  agent-id="YOUR_AGENT_ID"
34
- orb-color-light="var(--brand-accent-600)"
35
- orb-color-dark="var(--brand-accent-400)"
36
- active-orb-color-light="#0ea5e9"
37
- active-orb-color-dark="#38bdf8"
32
+ voice-service-url="https://voice.hanc.ai"
33
+ color-preset="cyan"
34
+ theme="auto"
38
35
  ></hanc-ai-floating-call>
39
- ```
40
-
41
- ## Quick Start
42
-
43
- ### HTML Example
44
-
45
- ```html
46
- <!DOCTYPE html>
47
- <html lang="en">
48
- <head>
49
- <meta charset="UTF-8" />
50
- <script
51
- src="https://unpkg.com/hanc-webrtc-widgets"
52
- async
53
- type="text/javascript"
54
- ></script>
55
- </head>
56
- <body>
57
- <!-- Inline Call Widget -->
58
- <hanc-ai-inline-call agent-id="YOUR_AGENT_ID"></hanc-ai-inline-call>
59
-
60
- <!-- Floating Call Widget -->
61
- <hanc-ai-floating-call agent-id="YOUR_AGENT_ID"></hanc-ai-floating-call>
62
- </body>
63
- </html>
64
- ```
65
-
66
- ### React Example
67
-
68
- 1. Installation lit/react & hanc-webrtc-widgets
69
36
 
70
- ```bash
71
- npm i @lit/react hanc-webrtc-widgets
72
- ```
73
-
74
- 2. Creating a React wrapper and using
75
-
76
- ```tsx
77
- import React from 'react';
78
- import { createComponent } from '@lit/react';
79
- import { InlineCall, FloatingCall } from 'hanc-webrtc-widgets';
80
-
81
- export const HancAiInlineCall = createComponent({
82
- tagName: 'hanc-ai-inline-call',
83
- elementClass: InlineCall,
84
- react: React,
85
- events: {
86
- onCallStart: 'call-start',
87
- onCallEnd: 'call-end',
88
- },
37
+ <!-- Pill CTA -->
38
+ <hanc-ai-pill-call
39
+ agent-id="YOUR_AGENT_ID"
40
+ voice-service-url="https://voice.hanc.ai"
41
+ button-text="Talk to AI"
42
+ active-button-text="End call"
43
+ color-preset="rose"
44
+ ></hanc-ai-pill-call>
45
+ ```
46
+
47
+ ### Attributes (shared across widgets)
48
+ - `agent-id` *(string, required for real calls)*
49
+ - `voice-service-url` *(string, required for real calls)*
50
+ - `size` *(number, default 280 — not used in pill mode)*
51
+ - `mode` *(inline \| float \| pill — only on `<hanc-ai-orb>`)*
52
+ - `position` *(center \| bottom-right \| bottom-left \| top-right \| top-left — used in float mode)*
53
+ - `button-text` / `active-button-text` / `connecting-text` *(strings)*
54
+ - `color-preset` *(indigo | cyan | emerald | rose | amber — uses dark/light versions automatically when `theme="auto"`)*
55
+ - `colors` *(JSON string `{"primary":"#...","secondary":"#..."}` to override the preset)*
56
+ - `orb-config` *(JSON string for advanced control: `morphStrength`, `glowIntensity`, `audioReactivity`, `idleGlowMultiplier`, etc.)*
57
+ - `theme` *(`auto` | `dark` | `light`, default `auto` — adjusts palette and glow)*
58
+ - `enable-sounds` *(boolean, default true)*
59
+ - `sound-volume` *(number 0.0–1.0, default 0.3)*
60
+ - Legacy aliases are still accepted: `button-start-text`, `button-end-text`, `button-connecting-text`.
61
+
62
+ ### Events
63
+ - `call-start` — `{ agentId, timestamp }`
64
+ - `call-end` — `{ agentId, duration, reason, timestamp }`
65
+ - `state-change` — `{ state: 'idle' | 'connecting' | 'active' | 'ending' | 'error', previousState }`
66
+ - `error` — `{ error }`
67
+
68
+ ```js
69
+ const orb = document.querySelector('hanc-ai-inline-call');
70
+
71
+ orb.addEventListener('state-change', e => {
72
+ console.log('state', e.detail.state);
89
73
  });
90
74
 
91
- export const HancAiFloatingCall = createComponent({
92
- tagName: 'hanc-ai-floating-call',
93
- elementClass: FloatingCall,
94
- react: React,
95
- events: {
96
- onCallStart: 'call-start',
97
- onCallEnd: 'call-end',
98
- },
75
+ orb.addEventListener('call-start', e => {
76
+ console.log('connected to', e.detail.agentId);
99
77
  });
100
-
101
- // An example of a component where both widgets are used
102
- export default function Example() {
103
- return (
104
- <>
105
- <HancAiInlineCall agentId="YOUR_AGENT_ID" />
106
- <HancAiFloatingCall agentId="YOUR_AGENT_ID" />
107
- </>
108
- );
109
- }
110
78
  ```
111
79
 
112
- ### Next.js Example
113
-
114
- 1. Installation lit/react & hanc-webrtc-widgets
80
+ ## Direct API (HancAiWidget)
115
81
 
116
- ```bash
117
- npm i @lit/react hanc-webrtc-widgets
118
- ```
119
-
120
- 2. Creating a Next.js wrapper and using
82
+ Import the low-level class when you need manual control, external media streams, or custom placement.
121
83
 
122
- ```tsx
123
- 'use client';
84
+ ```ts
85
+ import { HancAiWidget } from 'hanc-webrtc-widgets';
124
86
 
125
- import React from 'react';
126
- import dynamic from 'next/dynamic';
127
- import { createComponent } from '@lit/react';
87
+ const widget = new HancAiWidget('#container', {
88
+ agentId: 'YOUR_AGENT_ID',
89
+ voiceServiceUrl: 'https://voice.hanc.ai',
90
+ mode: 'float',
91
+ position: 'bottom-right',
92
+ size: 280,
93
+ buttonText: 'Start call',
94
+ activeButtonText: 'End call',
95
+ colors: { primary: '#38bdf8', accent: '#c084fc' },
96
+ orbConfig: { audioReactivity: 3.5, glowIntensity: 0.8 },
97
+ onStateChange: (state, prev) => console.log(state, prev),
98
+ onCallStart: e => console.log('started', e.agentId),
99
+ onCallEnd: e => console.log('ended after', e.duration, 'ms'),
100
+ });
128
101
 
129
- export const HancAiInlineCall = dynamic(
130
- async () => {
131
- const { InlineCall } = await import('hanc-webrtc-widgets');
132
-
133
- return createComponent({
134
- tagName: 'hanc-ai-inline-call',
135
- elementClass: InlineCall,
136
- react: React,
137
- events: {
138
- onCallStart: 'call-start',
139
- onCallEnd: 'call-end',
140
- },
141
- });
142
- },
143
- { ssr: false },
144
- );
145
-
146
- export const HancAiFloatingCall = dynamic(
147
- async () => {
148
- const { FloatingCall } = await import('hanc-webrtc-widgets');
149
-
150
- return createComponent({
151
- tagName: 'hanc-ai-floating-call',
152
- elementClass: FloatingCall,
153
- react: React,
154
- events: {
155
- onCallStart: 'call-start',
156
- onCallEnd: 'call-end',
157
- },
158
- });
159
- },
160
- { ssr: false },
161
- );
162
-
163
- // An example of a component where both widgets are used
164
- export default function Example() {
165
- return (
166
- <>
167
- <HancAiInlineCall agentId="YOUR_AGENT_ID" />
168
- <HancAiFloatingCall agentId="YOUR_AGENT_ID" />
169
- </>
170
- );
171
- }
102
+ // Control
103
+ await widget.startCall();
104
+ widget.setColors({ glow: '#c7d2fe' });
105
+ widget.setGlowSettings(0.8, 0.4); // e.g. dark theme
106
+ await widget.endCall();
107
+ widget.destroy();
172
108
  ```
173
109
 
174
- ## Components props & styles
175
-
176
- ### `<hanc-ai-inline-call>`
177
-
178
- **Description:**
179
- An “inline” widget that you embed directly in page content (often as a hero CTA). “Bubble” hints at the round, branded graphic.
180
-
181
- #### Available Attributes:
182
-
183
- | Attribute | Type | Description |
184
- | ------------------------ | ------ | -------------------------------------------------------- |
185
- | `agent-id` (required) | string | Agent ID for Twilio calls |
186
- | `button-start-text` | string | Custom start button text (default: `Start Call with ai`) |
187
- | `button-connecting-text` | string | Custom connecting button text (default: `Connecting...`) |
188
- | `button-end-text` | string | End button text (default: `End call`) |
189
- | `hide-button` | bool | Hide the button (orb click still toggles the call) |
190
- | `button-position` | string | Button placement: `top` or `bottom` |
191
- | `orb-color` | string | Base orb color in idle state |
192
- | `active-orb-color` | string | Orb color applied when the call becomes active |
193
- | `button-color` | string | Base button color (also used to derive hover/active) |
194
- | `button-hover-color` | string | Button hover color override |
195
- | `button-active-color` | string | Button active color override |
196
- | `button-text-color` | string | Button text color |
197
-
198
- #### Available Events:
199
-
200
- | Event Name | Description |
201
- | ------------ | ------------------------------------------------------------ |
202
- | `call-start` | Fired when a call is successfully connected and starts. |
203
- | `call-end` | Fired when a call ends, either by hangup or due to an error. |
204
-
205
- #### Available CSS Parts for Styling:
206
-
207
- | Part Name | Description |
208
- | ----------------- | --------------------------------- |
209
- | `wrapper` | Outer wrapper container |
210
- | `filter-light` | Light background filter |
211
- | `filter-gradient` | Gradient overlay |
212
- | `filter-overlay` | Active call overlay (state-based) |
213
- | `video` | The avatar video element |
214
- | `content-wrapper` | Button and content wrapper |
215
- | `button` | The main call button |
216
- | `icon-button` | The call icon inside the button |
217
- | `call-off-icon` | The "end call" icon |
218
- | `button-text` | Text inside the button |
219
-
220
- #### Example:
221
-
222
- ```html
223
- <hanc-ai-inline-call
224
- agent-id="67c34fa38ef2105d28bb287c"
225
- button-start-text="Call Agent"
226
- ></hanc-ai-inline-call>
110
+ ### Audio helpers
111
+ - `connectAudioStream(stream: MediaStream)` — drive the orb from any audio stream
112
+ - `connectMicrophone()` / `disconnectMicrophone()` — mic-driven visuals (demo mode)
113
+ - `isConnected()` / `getState()` — quick state checks
227
114
 
228
- <style>
229
- hanc-ai-inline-call::part(button) {
230
- /* your styles here */
231
- }
115
+ ## Voice Service Requirements
232
116
 
233
- hanc-ai-inline-call::part(button-text) {
234
- /* your styles here */
235
- }
117
+ The widget expects a `/connect` endpoint on your voice service:
236
118
 
237
- hanc-ai-inline-call::part(filter-overlay)[data-calling='true'] {
238
- /* your styles here */
239
- }
240
- </style>
241
119
  ```
242
-
243
- ## Additional customization options (append-only)
244
-
245
- Below are the new properties and examples you can add to the widgets.
246
-
247
- ### Theme and visual style
248
-
249
- Themes: `liquid-purple` , `liquid-cyan`, `liquid-pink`, `neural-green`,
250
- `neural-blue`(default), `orbit-blue`, `synaptic-purple`, `minimal-dark`, `minimal-light`, `custom`.
251
-
252
- Visual styles: `liquid-glass` , `liquid-glass-premium`, `neural-liquid`,
253
- `neural-orbit`, `neural-network`(default), `synaptic-core`, `organic-sphere`, `morphing-blob`.
254
-
255
- ```html
256
- <hanc-ai-inline-call
257
- agent-id="YOUR_AGENT_ID"
258
- theme="liquid-cyan"
259
- visual-style="neural-liquid"
260
- orb-size="200"
261
- ></hanc-ai-inline-call>
120
+ POST /connect
121
+ Body: { "agentId": "<your-agent-id>" }
122
+ Response: { "token": "<livekit-token>", "url": "<wss://...>" }
262
123
  ```
263
124
 
264
- ### Inline widget new attributes
265
-
266
- - `voice-service-url`
267
- - `theme`
268
- - `visual-style`
269
- - `orb-size`
270
- - `button-end-text`
271
- - `hide-button`
272
- - `button-position`
273
- - `orb-color`
274
- - `orb-color-light`
275
- - `orb-color-dark`
276
- - `active-orb-color`
277
- - `active-orb-color-light`
278
- - `active-orb-color-dark`
279
- - `button-color`
280
- - `button-hover-color`
281
- - `button-active-color`
282
- - `button-text-color`
125
+ Set `voice-service-url` (or `VITE_VOICE_SERVICE_URL`) to point at this service.
283
126
 
284
- ```html
285
- <hanc-ai-inline-call
286
- agent-id="YOUR_AGENT_ID"
287
- voice-service-url="https://voice.example.com"
288
- theme="minimal-light"
289
- visual-style="morphing-blob"
290
- orb-size="220"
291
- button-end-text="Stop"
292
- ></hanc-ai-inline-call>
293
- ```
294
-
295
- ### Floating widget new attributes
296
-
297
- - `voice-service-url`
298
- - `theme`
299
- - `visual-style`
300
- - `position`
301
- - `offset-x`
302
- - `offset-y`
303
- - `orb-size`
304
- - `hide-button`
305
- - `button-position`
306
- - `orb-color`
307
- - `orb-color-light`
308
- - `orb-color-dark`
309
- - `active-orb-color`
310
- - `active-orb-color-light`
311
- - `active-orb-color-dark`
312
- - `button-color`
313
- - `button-hover-color`
314
- - `button-active-color`
315
- - `button-text-color`
316
- - `minimized`
317
-
318
- ```html
319
- <hanc-ai-floating-call
320
- agent-id="YOUR_AGENT_ID"
321
- voice-service-url="https://voice.example.com"
322
- theme="neural-green"
323
- visual-style="neural-network"
324
- position="top-left"
325
- offset-x="32"
326
- offset-y="32"
327
- orb-size="140"
328
- minimized
329
- ></hanc-ai-floating-call>
330
- ```
331
-
332
- ### CSS variables (when using theme="custom")
333
-
334
- ```css
335
- hanc-ai-inline-call {
336
- --hanc-button: linear-gradient(135deg, #0ea5e9 0%, #22d3ee 100%);
337
- --hanc-button-hover: linear-gradient(135deg, #0284c7 0%, #0ea5e9 100%);
338
- --hanc-button-active: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
339
- --hanc-button-text: #ffffff;
340
- --hanc-button-radius: 16px;
341
- --hanc-button-shadow: rgba(14, 165, 233, 0.35);
342
- --hanc-button-shadow-hover: rgba(14, 165, 233, 0.45);
343
- --hanc-button-shadow-active: rgba(239, 68, 68, 0.45);
344
- --hanc-orb-active-glow: rgba(14, 165, 233, 0.35);
345
- --hanc-orb-z-index: 10000;
346
- --hanc-widget-z-index: 9999;
347
- }
348
-
349
- hanc-ai-floating-call {
350
- --hanc-background: rgba(10, 10, 20, 0.9);
351
- --hanc-glow-shadow: rgba(14, 165, 233, 0.2);
352
- --hanc-orb-size: 140px;
353
- --hanc-orb-active-glow: rgba(14, 165, 233, 0.35);
354
- --hanc-orb-z-index: 10000;
355
- --hanc-widget-z-index: 9999;
356
- }
357
- ```
127
+ ## Framework Usage
358
128
 
359
- #### Custom theme examples
129
+ Register the custom elements once and use them anywhere. Example for React with `@lit/react`:
360
130
 
361
- Tip: set `theme="custom"` and override only the variables you need. All other values fall back to defaults.
362
-
363
- ```html
364
- <hanc-ai-inline-call
365
- agent-id="YOUR_AGENT_ID"
366
- theme="custom"
367
- visual-style="neural-network"
368
- active-orb-color="#22c55e"
369
- ></hanc-ai-inline-call>
370
-
371
- <style>
372
- hanc-ai-inline-call {
373
- --hanc-background: rgba(10, 15, 20, 0.8);
374
- --hanc-orb-size: 220px;
375
- --hanc-button: linear-gradient(135deg, #0ea5e9 0%, #22c55e 100%);
376
- --hanc-button-hover: linear-gradient(135deg, #0284c7 0%, #16a34a 100%);
377
- --hanc-button-active: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
378
- --hanc-button-text: #ffffff;
379
- --hanc-orb-active-glow: rgba(34, 197, 94, 0.4);
380
- }
381
- </style>
382
- ```
383
-
384
- ```html
385
- <hanc-ai-inline-call
386
- agent-id="YOUR_AGENT_ID"
387
- theme="custom"
388
- visual-style="neural-orbit"
389
- button-position="top"
390
- ></hanc-ai-inline-call>
131
+ ```ts
132
+ import React from 'react';
133
+ import { createComponent } from '@lit/react';
134
+ import { InlineCall, FloatingCall, PillCall } from 'hanc-webrtc-widgets';
391
135
 
392
- <style>
393
- hanc-ai-inline-call {
394
- --hanc-orb-size: 260px;
395
- --hanc-button-radius: 999px;
396
- --hanc-button: linear-gradient(135deg, #111827 0%, #374151 100%);
397
- --hanc-button-hover: linear-gradient(135deg, #1f2937 0%, #111827 100%);
398
- --hanc-button-active: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%);
399
- --hanc-button-text: #f9fafb;
400
- --hanc-orb-active-glow: rgba(59, 130, 246, 0.35);
401
- }
402
- </style>
403
- ```
136
+ export const HancInline = createComponent({
137
+ tagName: 'hanc-ai-inline-call',
138
+ elementClass: InlineCall,
139
+ react: React,
140
+ events: { onCallStart: 'call-start', onCallEnd: 'call-end' },
141
+ });
404
142
 
405
- ```html
406
- <hanc-ai-floating-call
407
- agent-id="YOUR_AGENT_ID"
408
- theme="custom"
409
- position="top-right"
410
- button-position="top"
411
- active-orb-color="#f97316"
412
- ></hanc-ai-floating-call>
143
+ export const HancFloating = createComponent({
144
+ tagName: 'hanc-ai-floating-call',
145
+ elementClass: FloatingCall,
146
+ react: React,
147
+ events: { onCallStart: 'call-start', onCallEnd: 'call-end' },
148
+ });
413
149
 
414
- <style>
415
- hanc-ai-floating-call {
416
- --hanc-background: rgba(255, 255, 255, 0.92);
417
- --hanc-text: rgba(24, 24, 27, 0.8);
418
- --hanc-glow-shadow: rgba(249, 115, 22, 0.2);
419
- --hanc-orb-size: 120px;
420
- --hanc-button: linear-gradient(135deg, #f97316 0%, #f59e0b 100%);
421
- --hanc-button-hover: linear-gradient(135deg, #ea580c 0%, #f97316 100%);
422
- --hanc-button-active: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);
423
- --hanc-button-text: #ffffff;
424
- }
425
- </style>
150
+ export const HancPill = createComponent({
151
+ tagName: 'hanc-ai-pill-call',
152
+ elementClass: PillCall,
153
+ react: React,
154
+ events: { onCallStart: 'call-start', onCallEnd: 'call-end' },
155
+ });
426
156
  ```
427
157
 
428
- ---
429
-
430
- ### `<hanc-ai-floating-call>`
431
-
432
- **Description:**
433
- A persistent, docked widget that floats in the corner and launches the same voice-call flow from anywhere on the page.
434
-
435
- #### Available Attributes:
436
-
437
- | Attribute | Type | Description |
438
- | ------------------------ | ------ | -------------------------------------------------------- |
439
- | `agent-id` (required) | string | Agent ID for Twilio calls |
440
- | `label-text` | string | Label above the button (default: `Need a help?`) |
441
- | `button-start-text` | string | Start button text (default: `Start Call with ai`) |
442
- | `button-connecting-text` | string | Custom connecting button text (default: `Connecting...`) |
443
- | `button-end-text` | string | End button text (default: `End call`) |
444
- | `hide-button` | bool | Hide the button (orb click still toggles the call) |
445
- | `button-position` | string | Button placement: `top` or `bottom` |
446
- | `orb-color` | string | Base orb color in idle state |
447
- | `active-orb-color` | string | Orb color applied when the call becomes active |
448
- | `button-color` | string | Base button color (also used to derive hover/active) |
449
- | `button-hover-color` | string | Button hover color override |
450
- | `button-active-color` | string | Button active color override |
451
- | `button-text-color` | string | Button text color |
452
-
453
- #### Available Events:
454
-
455
- | Event Name | Description |
456
- | ------------ | ------------------------------------------------------------ |
457
- | `call-start` | Fired when a call is successfully connected and starts. |
458
- | `call-end` | Fired when a call ends, either by hangup or due to an error. |
459
-
460
- #### Available CSS Parts for Styling:
461
-
462
- | Part Name | Description |
463
- | ----------------- | --------------------------------- |
464
- | `root` | Outer container |
465
- | `avatar-wrapper` | Wrapper for avatar/video |
466
- | `filter-light` | Light background filter |
467
- | `filter-gradient` | Gradient overlay |
468
- | `filter-overlay` | Active call overlay (state-based) |
469
- | `avatar-video` | The avatar video element |
470
- | `content` | Container for label and button |
471
- | `title` | The label/title text |
472
- | `button` | The main call button |
473
- | `icon-button` | The call icon inside the button |
474
- | `button-text` | Text inside the button |
475
-
476
- #### Example:
477
-
478
- ```html
479
- <hanc-ai-floating-call
480
- agent-id="67c34fa38ef2105d28bb287c"
481
- label-text="Need Assistance?"
482
- button-start-text="Start Call"
483
- button-end-text="End Call"
484
- ></hanc-ai-floating-call>
158
+ ## Theming Tips
159
+ - `theme="auto"` listens to `prefers-color-scheme` and switches presets/glow for you.
160
+ - Use `color-preset` for quick palettes (`indigo`, `cyan`, `emerald`, `rose`, `amber`).
161
+ - Override any color with `colors='{"accent":"#8b5cf6","glow":"#c084fc"}'`.
162
+ - For light themes, pair with `orb-config='{"idleGlowMultiplier":0.2,"glowIntensity":0.4}'`.
485
163
 
486
- <style>
487
- hanc-ai-floating-call::part(root) {
488
- /* your styles here */
489
- }
164
+ ## License
490
165
 
491
- hanc-ai-floating-call::part(title) {
492
- /* your styles here */
493
- }
494
-
495
- hanc-ai-floating-call::part(button) {
496
- /* your styles here */
497
- }
498
-
499
- hanc-ai-floating-call::part(filter-overlay)[data-calling='true'] {
500
- /* your styles here */
501
- }
502
- </style>
503
- ```
166
+ MIT