ttp-agent-sdk 2.39.0 → 2.43.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.
@@ -13,143 +13,370 @@
13
13
 
14
14
  body {
15
15
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
16
- background: #f9fafb;
16
+ background: #0f0f1a;
17
17
  min-height: 100vh;
18
18
  overflow-x: hidden;
19
+ color: #e2e8f0;
19
20
  }
20
21
 
21
22
  .header {
22
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
23
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
23
24
  color: white;
24
- padding: 40px 20px;
25
- text-align: center;
26
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
25
+ padding: 20px 24px;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: space-between;
29
+ border-bottom: 1px solid rgba(255,255,255,0.06);
30
+ position: sticky;
31
+ top: 0;
32
+ z-index: 100;
33
+ }
34
+
35
+ .header-left {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 16px;
27
39
  }
28
40
 
29
41
  .header h1 {
30
- font-size: 36px;
42
+ font-size: 20px;
31
43
  font-weight: 700;
32
- margin-bottom: 8px;
44
+ letter-spacing: -0.3px;
33
45
  }
34
46
 
35
47
  .header p {
36
- font-size: 18px;
37
- opacity: 0.9;
48
+ font-size: 14px;
49
+ opacity: 0.6;
50
+ display: none;
38
51
  }
39
52
 
40
53
  .back-link {
41
- position: absolute;
42
- top: 20px;
43
- left: 20px;
44
- color: white;
54
+ color: rgba(255,255,255,0.7);
45
55
  text-decoration: none;
46
56
  font-weight: 500;
47
- padding: 8px 16px;
48
- background: rgba(255, 255, 255, 0.2);
57
+ font-size: 14px;
58
+ padding: 6px 14px;
59
+ background: rgba(255, 255, 255, 0.08);
49
60
  border-radius: 8px;
50
- transition: background 0.2s;
61
+ transition: all 0.2s;
62
+ border: 1px solid rgba(255,255,255,0.06);
51
63
  }
52
64
 
53
65
  .back-link:hover {
54
- background: rgba(255, 255, 255, 0.3);
66
+ background: rgba(255, 255, 255, 0.14);
67
+ color: white;
55
68
  }
56
69
 
57
70
  .container {
58
- max-width: 1800px;
71
+ max-width: 1600px;
59
72
  margin: 0 auto;
60
- padding: 40px 20px;
73
+ padding: 20px;
61
74
  display: grid;
62
- grid-template-columns: minmax(600px, 1fr) 420px;
63
- gap: 24px;
75
+ grid-template-columns: minmax(0, 1fr) 360px;
76
+ gap: 16px;
64
77
  align-items: start;
78
+ min-height: calc(100vh - 62px);
79
+ position: relative;
80
+ z-index: 20;
65
81
  }
66
82
 
67
83
  .preview-section {
68
- background: white;
84
+ background: #1a1a2e;
69
85
  border-radius: 16px;
70
- padding: 24px;
71
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
86
+ padding: 0;
87
+ border: 1px solid rgba(255,255,255,0.06);
72
88
  min-height: 600px;
73
- height: 100%;
89
+ height: fit-content;
74
90
  position: relative;
75
91
  overflow: visible;
76
92
  display: flex;
77
93
  flex-direction: column;
78
94
  }
79
95
 
80
- .preview-section h2 {
81
- font-size: 24px;
82
- font-weight: 700;
83
- color: #111827;
84
- margin-bottom: 20px;
96
+ .preview-header {
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: space-between;
100
+ padding: 16px 20px;
101
+ border-bottom: 1px solid rgba(255,255,255,0.06);
85
102
  flex-shrink: 0;
86
103
  }
87
104
 
105
+ .preview-header h2 {
106
+ font-size: 15px;
107
+ font-weight: 600;
108
+ color: #94a3b8;
109
+ text-transform: uppercase;
110
+ letter-spacing: 0.8px;
111
+ }
112
+
113
+ .device-toggle {
114
+ display: flex;
115
+ background: rgba(255,255,255,0.06);
116
+ border-radius: 10px;
117
+ padding: 3px;
118
+ gap: 2px;
119
+ }
120
+
121
+ .device-toggle-btn {
122
+ display: flex;
123
+ align-items: center;
124
+ gap: 6px;
125
+ padding: 7px 14px;
126
+ border: none;
127
+ border-radius: 8px;
128
+ font-size: 13px;
129
+ font-weight: 500;
130
+ cursor: pointer;
131
+ transition: all 0.2s;
132
+ background: transparent;
133
+ color: #94a3b8;
134
+ }
135
+
136
+ .device-toggle-btn.active {
137
+ background: #7c3aed;
138
+ color: white;
139
+ box-shadow: 0 2px 8px rgba(124, 58, 237, 0.3);
140
+ }
141
+
142
+ .device-toggle-btn:not(.active):hover {
143
+ background: rgba(255,255,255,0.06);
144
+ color: #e2e8f0;
145
+ }
146
+
147
+ .device-toggle-btn svg {
148
+ width: 16px;
149
+ height: 16px;
150
+ }
151
+
88
152
  .preview-area {
89
- background: #f3f4f6;
90
- border-radius: 12px;
91
- height: 600px;
153
+ background: linear-gradient(180deg, #0f0f1a 0%, #141425 100%);
154
+ border-radius: 0 0 16px 16px;
155
+ min-height: 650px;
92
156
  position: relative;
93
- overflow: scroll !important;
94
- border: 2px dashed #d1d5db;
95
- padding: 60px;
157
+ overflow: visible;
158
+ padding: 40px;
96
159
  box-sizing: border-box;
97
- /* Ensure enough space for widget (360px width + margins) */
98
- min-width: 500px;
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: center;
99
163
  flex: 1;
100
- /* Force scrollbar to always be visible */
101
- scrollbar-width: auto;
102
- -webkit-overflow-scrolling: touch;
103
164
  }
104
-
105
- /* Inner container that's taller than the preview area to enable scrolling */
106
- .preview-area > div {
107
- min-height: 800px;
165
+
166
+ .preview-area.desktop-mode {
167
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
168
+ padding: 30px;
169
+ }
170
+
171
+ .preview-area.mobile-mode {
172
+ background: linear-gradient(180deg, #0f0f1a 0%, #141425 100%);
173
+ padding: 40px 20px;
174
+ }
175
+
176
+ .device-frame-desktop {
177
+ width: 100%;
178
+ min-height: 560px;
108
179
  position: relative;
180
+ border-radius: 12px;
181
+ background: white;
182
+ box-shadow: 0 8px 32px rgba(0,0,0,0.12);
183
+ overflow: hidden;
109
184
  }
110
185
 
111
- .customization-panel {
186
+ .desktop-chrome {
187
+ background: #f1f3f5;
188
+ border-radius: 12px 12px 0 0;
189
+ padding: 10px 16px;
190
+ display: flex;
191
+ align-items: center;
192
+ gap: 8px;
193
+ border-bottom: 1px solid #dee2e6;
194
+ }
195
+
196
+ .desktop-dots {
197
+ display: flex;
198
+ gap: 6px;
199
+ }
200
+
201
+ .desktop-dots span {
202
+ width: 10px;
203
+ height: 10px;
204
+ border-radius: 50%;
205
+ }
206
+
207
+ .desktop-dots span:nth-child(1) { background: #ff5f57; }
208
+ .desktop-dots span:nth-child(2) { background: #febc2e; }
209
+ .desktop-dots span:nth-child(3) { background: #28c840; }
210
+
211
+ .desktop-url-bar {
212
+ flex: 1;
213
+ background: white;
214
+ border-radius: 6px;
215
+ padding: 5px 12px;
216
+ font-size: 12px;
217
+ color: #6b7280;
218
+ border: 1px solid #dee2e6;
219
+ }
220
+
221
+ .desktop-content {
222
+ height: 700px;
223
+ position: relative;
224
+ background: white;
225
+ border-radius: 0 0 12px 12px;
226
+ overflow: hidden;
227
+ }
228
+
229
+ .desktop-placeholder {
230
+ padding: 40px;
231
+ color: #9ca3af;
232
+ }
233
+
234
+ .desktop-placeholder h3 {
235
+ font-size: 18px;
236
+ color: #d1d5db;
237
+ margin-bottom: 12px;
238
+ }
239
+
240
+ .desktop-placeholder p {
241
+ font-size: 14px;
242
+ line-height: 1.6;
243
+ color: #d1d5db;
244
+ }
245
+
246
+ .desktop-placeholder .placeholder-line {
247
+ height: 10px;
248
+ background: #f3f4f6;
249
+ border-radius: 4px;
250
+ margin-bottom: 10px;
251
+ }
252
+
253
+ .desktop-placeholder .placeholder-line:nth-child(1) { width: 70%; }
254
+ .desktop-placeholder .placeholder-line:nth-child(2) { width: 100%; }
255
+ .desktop-placeholder .placeholder-line:nth-child(3) { width: 85%; }
256
+ .desktop-placeholder .placeholder-line:nth-child(4) { width: 60%; }
257
+ .desktop-placeholder .placeholder-line:nth-child(5) { width: 90%; }
258
+
259
+ .device-frame-mobile {
260
+ width: 375px;
261
+ height: 750px;
262
+ background: #1c1c1e;
263
+ border-radius: 44px;
264
+ padding: 12px;
265
+ box-shadow: 0 20px 60px rgba(0,0,0,0.5), inset 0 0 0 2px rgba(255,255,255,0.1);
266
+ position: relative;
267
+ }
268
+
269
+ .phone-notch {
270
+ position: absolute;
271
+ top: 12px;
272
+ left: 50%;
273
+ transform: translateX(-50%);
274
+ width: 120px;
275
+ height: 28px;
276
+ background: #1c1c1e;
277
+ border-radius: 0 0 16px 16px;
278
+ z-index: 10;
279
+ }
280
+
281
+ .phone-screen {
282
+ width: 100%;
283
+ height: 100%;
284
+ border-radius: 34px;
112
285
  background: white;
286
+ overflow: visible;
287
+ position: relative;
288
+ }
289
+
290
+ .phone-status-bar {
291
+ height: 44px;
292
+ display: flex;
293
+ align-items: center;
294
+ justify-content: space-between;
295
+ padding: 0 24px;
296
+ font-size: 13px;
297
+ font-weight: 600;
298
+ color: #1c1c1e;
299
+ }
300
+
301
+ .phone-content {
302
+ height: calc(100% - 44px);
303
+ position: relative;
304
+ overflow: hidden;
305
+ }
306
+
307
+ .phone-placeholder {
308
+ padding: 20px;
309
+ color: #9ca3af;
310
+ }
311
+
312
+ .phone-placeholder .placeholder-line {
313
+ height: 8px;
314
+ background: #f3f4f6;
315
+ border-radius: 4px;
316
+ margin-bottom: 8px;
317
+ }
318
+
319
+ .phone-placeholder .placeholder-line:nth-child(1) { width: 60%; }
320
+ .phone-placeholder .placeholder-line:nth-child(2) { width: 100%; }
321
+ .phone-placeholder .placeholder-line:nth-child(3) { width: 75%; }
322
+ .phone-placeholder .placeholder-line:nth-child(4) { width: 50%; }
323
+
324
+ .device-frame-mobile .mock-widget {
325
+ transform: scale(0.95);
326
+ transform-origin: bottom right;
327
+ }
328
+
329
+ .customization-panel {
330
+ background: #1a1a2e;
113
331
  border-radius: 16px;
114
- padding: 24px;
115
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
116
- overflow-y: visible;
332
+ border: 1px solid rgba(255,255,255,0.06);
333
+ overflow-y: auto;
117
334
  overflow-x: hidden;
118
335
  display: flex;
119
336
  flex-direction: column;
120
337
  position: relative;
121
- min-height: fit-content;
338
+ max-height: calc(100vh - 102px);
339
+ position: sticky;
340
+ top: 82px;
122
341
  }
123
-
124
- /* Ensure code output is always visible at bottom */
125
- .customization-panel > div:last-child {
126
- margin-top: auto;
127
- padding-top: 16px;
128
- border-top: 1px solid #e5e7eb;
342
+
343
+ .customization-panel-header {
344
+ padding: 16px 20px;
345
+ border-bottom: 1px solid rgba(255,255,255,0.06);
129
346
  flex-shrink: 0;
130
347
  }
131
-
132
- /* Removed custom scrollbars - using main window scroll only */
133
348
 
134
- .customization-panel h2 {
135
- font-size: 20px;
136
- font-weight: 700;
137
- color: #111827;
138
- margin-bottom: 20px;
139
- padding-bottom: 12px;
140
- border-bottom: 2px solid #e5e7eb;
141
- flex-shrink: 0;
349
+ .customization-panel-header h2 {
350
+ font-size: 15px;
351
+ font-weight: 600;
352
+ color: #94a3b8;
353
+ text-transform: uppercase;
354
+ letter-spacing: 0.8px;
355
+ }
356
+
357
+ .customization-panel-body {
358
+ padding: 16px 20px;
359
+ flex: 1;
360
+ overflow-y: auto;
142
361
  }
143
362
 
144
363
  .customization-group {
145
- margin-bottom: 24px;
364
+ margin-bottom: 20px;
365
+ padding-bottom: 16px;
366
+ border-bottom: 1px solid rgba(255,255,255,0.04);
367
+ }
368
+
369
+ .customization-group:last-child {
370
+ border-bottom: none;
146
371
  }
147
372
 
148
373
  .customization-group h3 {
149
- font-size: 16px;
374
+ font-size: 13px;
150
375
  font-weight: 600;
151
- color: #374151;
376
+ color: #94a3b8;
152
377
  margin-bottom: 12px;
378
+ text-transform: uppercase;
379
+ letter-spacing: 0.6px;
153
380
  display: flex;
154
381
  align-items: center;
155
382
  gap: 8px;
@@ -157,22 +384,22 @@
157
384
 
158
385
  .customization-group h3::before {
159
386
  content: '';
160
- width: 4px;
161
- height: 16px;
162
- background: #667eea;
387
+ width: 3px;
388
+ height: 14px;
389
+ background: #7c3aed;
163
390
  border-radius: 2px;
164
391
  }
165
392
 
166
393
  .control-item {
167
- margin-bottom: 16px;
394
+ margin-bottom: 12px;
168
395
  }
169
396
 
170
397
  .control-item label {
171
398
  display: block;
172
- font-size: 14px;
399
+ font-size: 13px;
173
400
  font-weight: 500;
174
- color: #6b7280;
175
- margin-bottom: 6px;
401
+ color: #94a3b8;
402
+ margin-bottom: 5px;
176
403
  }
177
404
 
178
405
  .control-item input[type="text"],
@@ -180,156 +407,163 @@
180
407
  .control-item select {
181
408
  width: 100%;
182
409
  padding: 8px 12px;
183
- border: 1px solid #d1d5db;
410
+ border: 1px solid rgba(255,255,255,0.1);
184
411
  border-radius: 8px;
185
- font-size: 14px;
412
+ font-size: 13px;
186
413
  transition: border-color 0.2s;
414
+ background: rgba(255,255,255,0.04);
415
+ color: #e2e8f0;
187
416
  }
188
417
 
189
418
  .control-item input[type="text"]:focus,
190
419
  .control-item input[type="number"]:focus,
191
420
  .control-item select:focus {
192
421
  outline: none;
193
- border-color: #667eea;
422
+ border-color: #7c3aed;
423
+ background: rgba(124, 58, 237, 0.06);
424
+ }
425
+
426
+ .control-item select option {
427
+ background: #1a1a2e;
428
+ color: #e2e8f0;
194
429
  }
195
430
 
196
431
  .control-item input[type="color"] {
197
432
  width: 100%;
198
- height: 40px;
199
- border: 1px solid #d1d5db;
433
+ height: 36px;
434
+ border: 1px solid rgba(255,255,255,0.1);
200
435
  border-radius: 8px;
201
436
  cursor: pointer;
437
+ background: rgba(255,255,255,0.04);
202
438
  }
203
439
 
204
440
  .control-item input[type="checkbox"] {
205
441
  margin-right: 8px;
442
+ accent-color: #7c3aed;
206
443
  }
207
444
 
208
445
  .button-group {
209
446
  display: flex;
210
- gap: 12px;
211
- margin-top: 24px;
447
+ gap: 8px;
212
448
  flex-shrink: 0;
213
449
  }
214
450
 
215
451
  .btn {
216
452
  flex: 1;
217
- padding: 12px 24px;
453
+ padding: 10px 16px;
218
454
  border: none;
219
455
  border-radius: 8px;
220
- font-size: 14px;
456
+ font-size: 13px;
221
457
  font-weight: 600;
222
458
  cursor: pointer;
223
459
  transition: all 0.2s;
224
460
  }
225
461
 
226
462
  .btn-primary {
227
- background: #667eea;
463
+ background: #7c3aed;
228
464
  color: white;
229
465
  }
230
466
 
231
467
  .btn-primary:hover {
232
- background: #5568d3;
468
+ background: #6d28d9;
233
469
  }
234
470
 
235
471
  .btn-secondary {
236
- background: #e5e7eb;
237
- color: #374151;
472
+ background: rgba(255,255,255,0.06);
473
+ color: #94a3b8;
474
+ border: 1px solid rgba(255,255,255,0.08);
238
475
  }
239
476
 
240
477
  .btn-secondary:hover {
241
- background: #d1d5db;
478
+ background: rgba(255,255,255,0.1);
479
+ color: #e2e8f0;
242
480
  }
243
481
 
244
482
  .info-box {
245
- background: #eff6ff;
246
- border-left: 4px solid #3b82f6;
247
- padding: 16px;
483
+ background: rgba(124, 58, 237, 0.06);
484
+ border-left: 3px solid #7c3aed;
485
+ padding: 12px 14px;
248
486
  border-radius: 8px;
249
- margin-bottom: 24px;
487
+ margin-bottom: 16px;
250
488
  }
251
489
 
252
490
  .info-box p {
253
- font-size: 14px;
254
- color: #1e40af;
255
- line-height: 1.6;
491
+ font-size: 12px;
492
+ color: #a78bfa;
493
+ line-height: 1.5;
256
494
  }
257
495
 
258
496
  .code-output {
259
- background: #1f2937;
260
- color: #f9fafb;
261
- padding: 20px;
262
- border-radius: 8px;
263
- font-family: 'Monaco', 'Courier New', monospace;
264
- font-size: 13px;
497
+ background: #0f0f1a;
498
+ color: #e2e8f0;
499
+ padding: 16px;
500
+ border-radius: 10px;
501
+ font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
502
+ font-size: 12px;
265
503
  overflow-x: auto;
266
- overflow-y: visible;
504
+ overflow-y: auto;
267
505
  flex-shrink: 0;
268
506
  position: relative;
269
- border: 2px solid #374151;
270
- min-height: 400px;
271
- height: auto;
272
- max-height: none;
507
+ border: 1px solid rgba(255,255,255,0.06);
508
+ max-height: 300px;
273
509
  }
274
-
510
+
275
511
  .code-output pre {
276
512
  white-space: pre-wrap;
277
513
  word-wrap: break-word;
278
514
  margin: 0;
279
515
  padding: 0;
280
- line-height: 1.6;
281
- font-size: 13px;
516
+ line-height: 1.5;
517
+ font-size: 12px;
282
518
  }
283
-
519
+
284
520
  .code-output h3 {
285
- margin-bottom: 16px;
286
- font-size: 16px;
287
- font-weight: 700;
521
+ margin-bottom: 10px;
522
+ font-size: 12px;
523
+ font-weight: 600;
524
+ color: #94a3b8;
525
+ text-transform: uppercase;
526
+ letter-spacing: 0.5px;
288
527
  }
289
-
528
+
290
529
  .code-output::-webkit-scrollbar {
291
- width: 8px;
292
- height: 8px;
530
+ width: 6px;
531
+ height: 6px;
293
532
  }
294
-
533
+
295
534
  .code-output::-webkit-scrollbar-track {
296
- background: #374151;
297
- border-radius: 4px;
535
+ background: transparent;
298
536
  }
299
-
537
+
300
538
  .code-output::-webkit-scrollbar-thumb {
301
- background: #6b7280;
302
- border-radius: 4px;
303
- }
304
-
305
- .code-output::-webkit-scrollbar-thumb:hover {
306
- background: #9ca3af;
539
+ background: rgba(255,255,255,0.1);
540
+ border-radius: 3px;
307
541
  }
308
542
 
309
- .code-output pre {
310
- margin: 0;
311
- white-space: pre-wrap;
312
- word-wrap: break-word;
543
+ .code-output::-webkit-scrollbar-thumb:hover {
544
+ background: rgba(255,255,255,0.2);
313
545
  }
314
546
 
315
547
  .element-highlight {
316
- outline: 2px solid #667eea;
548
+ outline: 2px solid #7c3aed;
317
549
  outline-offset: 2px;
318
550
  cursor: pointer;
319
551
  transition: outline-color 0.2s;
320
552
  }
321
553
 
322
554
  .element-highlight:hover {
323
- outline-color: #ef4444;
555
+ outline-color: #a78bfa;
556
+ }
557
+
558
+ /* Real SDK widget - visible above page content */
559
+ #ttp-widget-shadow-host {
560
+ z-index: 9999 !important;
324
561
  }
325
562
 
326
563
  .mock-widget {
327
564
  position: absolute;
328
- /* Position is set dynamically via updateMockWidgetPosition() */
329
565
  z-index: 1000;
330
- /* Ensure widget doesn't get clipped */
331
- min-width: 360px;
332
- /* Ensure widget is fully visible - adjust position if needed */
566
+ min-width: 200px;
333
567
  transform: translateZ(0);
334
568
  cursor: pointer;
335
569
  padding: 4px;
@@ -338,115 +572,316 @@
338
572
  }
339
573
 
340
574
  .mock-widget:hover {
341
- background: rgba(102, 126, 234, 0.05);
575
+ background: rgba(124, 58, 237, 0.05);
342
576
  }
343
577
 
344
578
  .mock-widget.element-highlight {
345
- background: rgba(102, 126, 234, 0.1);
346
- outline: 2px solid #667eea;
579
+ background: rgba(124, 58, 237, 0.08);
580
+ outline: 2px solid #7c3aed;
347
581
  outline-offset: 4px;
348
582
  }
349
-
350
- /* Ensure panel has enough space and is fully visible */
583
+
351
584
  .mock-widget-panel {
352
585
  position: relative;
353
- margin-bottom: 100px; /* Extra space for button below */
586
+ margin-bottom: 12px;
354
587
  }
355
-
356
- /* Ensure preview section doesn't clip content */
588
+
357
589
  .preview-section {
358
590
  overflow-x: visible;
359
591
  overflow-y: visible;
360
592
  }
361
-
362
- /* Custom scrollbar styling for preview area */
363
- .preview-area::-webkit-scrollbar {
364
- width: 14px;
365
- height: 14px;
366
- }
367
-
368
- .preview-area::-webkit-scrollbar-track {
369
- background: #e5e7eb;
370
- border-radius: 7px;
371
- margin: 4px;
372
- }
373
-
374
- .preview-area::-webkit-scrollbar-thumb {
375
- background: #6b7280;
376
- border-radius: 7px;
377
- border: 2px solid #e5e7eb;
378
- }
379
-
380
- .preview-area::-webkit-scrollbar-thumb:hover {
381
- background: #4b5563;
382
- }
383
-
384
- .preview-area::-webkit-scrollbar-corner {
385
- background: #e5e7eb;
386
- }
387
-
388
- /* Firefox scrollbar */
389
- .preview-area {
390
- scrollbar-width: auto;
391
- scrollbar-color: #6b7280 #e5e7eb;
392
- }
393
593
 
394
- @media (max-width: 1400px) {
594
+ @media (max-width: 860px) {
395
595
  .container {
396
- grid-template-columns: 1fr 380px;
596
+ grid-template-columns: 1fr;
597
+ gap: 16px;
397
598
  }
398
-
599
+
600
+ .customization-panel {
601
+ max-height: none;
602
+ position: static;
603
+ }
604
+
399
605
  .preview-area {
400
- padding: 20px;
401
- min-width: 450px;
606
+ min-height: 500px;
402
607
  }
403
-
404
- /* Position is set dynamically via updateMockWidgetPosition() */
405
608
  }
406
609
 
407
- @media (max-width: 1200px) {
610
+ @media (max-width: 768px) {
611
+ .header {
612
+ padding: 12px 16px;
613
+ flex-direction: column;
614
+ gap: 10px;
615
+ }
616
+
617
+ .header-left {
618
+ flex-direction: column;
619
+ gap: 8px;
620
+ }
621
+
408
622
  .container {
409
- grid-template-columns: 1fr;
623
+ padding: 12px;
410
624
  }
411
625
 
412
- .customization-panel {
413
- max-height: none;
626
+ .device-frame-mobile {
627
+ width: 320px;
628
+ height: 640px;
629
+ border-radius: 36px;
630
+ padding: 10px;
414
631
  }
415
-
632
+
633
+ .phone-screen {
634
+ border-radius: 28px;
635
+ }
636
+
416
637
  .preview-area {
417
- min-height: 500px;
638
+ padding: 20px 10px;
639
+ min-height: 400px;
640
+ }
641
+
642
+ .device-toggle-btn {
643
+ padding: 6px 10px;
644
+ font-size: 12px;
645
+ }
646
+
647
+ .device-toggle-btn span.device-label {
648
+ display: none;
649
+ }
650
+
651
+ .customization-panel-body {
652
+ padding: 12px 16px;
418
653
  }
654
+
655
+ .code-output {
656
+ max-height: 200px;
657
+ }
658
+ }
659
+
660
+ /* Scrollbar for customization panel */
661
+ /* Quick Themes */
662
+ .quick-themes {
663
+ margin-bottom: 16px;
664
+ }
665
+ .quick-themes h3 {
666
+ font-size: 11px;
667
+ font-weight: 600;
668
+ color: #94a3b8;
669
+ text-transform: uppercase;
670
+ letter-spacing: 0.8px;
671
+ margin-bottom: 10px;
672
+ }
673
+ .theme-cards {
674
+ display: grid;
675
+ grid-template-columns: repeat(5, 1fr);
676
+ gap: 8px;
677
+ }
678
+ .theme-card {
679
+ cursor: pointer;
680
+ border-radius: 10px;
681
+ border: 2px solid rgba(255,255,255,0.06);
682
+ overflow: hidden;
683
+ transition: border-color 0.2s, transform 0.15s;
684
+ background: #0f0f1a;
685
+ padding: 0;
686
+ font-family: inherit;
687
+ text-align: left;
688
+ color: inherit;
689
+ }
690
+ .theme-card:hover {
691
+ border-color: rgba(139,92,246,0.4);
692
+ transform: translateY(-1px);
693
+ }
694
+ .theme-card.active {
695
+ border-color: #8b5cf6;
696
+ }
697
+ .theme-card-preview {
698
+ height: 64px;
699
+ padding: 8px;
700
+ display: flex;
701
+ flex-direction: column;
702
+ justify-content: space-between;
703
+ position: relative;
704
+ overflow: hidden;
705
+ }
706
+ .theme-card-preview::after {
707
+ content: '';
708
+ position: absolute;
709
+ top: -15px; right: -15px;
710
+ width: 50px; height: 50px;
711
+ border-radius: 50%;
712
+ pointer-events: none;
713
+ }
714
+ .theme-card-top {
715
+ display: flex;
716
+ align-items: center;
717
+ gap: 4px;
718
+ }
719
+ .theme-card-avatar {
720
+ width: 14px; height: 14px;
721
+ border-radius: 50%;
722
+ display: flex; align-items: center; justify-content: center;
723
+ font-size: 6px; font-weight: 700; color: #fff;
724
+ }
725
+ .theme-card-lines {
726
+ display: flex;
727
+ flex-direction: column;
728
+ gap: 2px;
729
+ }
730
+ .theme-card-line {
731
+ height: 2px;
732
+ border-radius: 1px;
733
+ }
734
+ .theme-card-btn {
735
+ height: 8px;
736
+ border-radius: 4px;
737
+ width: 70%;
738
+ }
739
+ .theme-card-label {
740
+ text-align: center;
741
+ padding: 5px 4px;
742
+ font-size: 10px;
743
+ font-weight: 600;
744
+ color: #94a3b8;
745
+ letter-spacing: 0.3px;
419
746
  }
420
747
 
421
- /* Mock widget styles - will be dynamically generated */
748
+ .customization-panel::-webkit-scrollbar {
749
+ width: 5px;
750
+ }
751
+
752
+ .customization-panel::-webkit-scrollbar-track {
753
+ background: transparent;
754
+ }
755
+
756
+ .customization-panel::-webkit-scrollbar-thumb {
757
+ background: rgba(255,255,255,0.08);
758
+ border-radius: 3px;
759
+ }
760
+
761
+ .customization-panel::-webkit-scrollbar-thumb:hover {
762
+ background: rgba(255,255,255,0.15);
763
+ }
764
+
765
+ /* Mock widget styles - Pill Launcher (new design) */
422
766
  .mock-button-container {
423
767
  position: relative;
424
768
  display: inline-flex;
425
769
  align-items: center;
426
770
  justify-content: center;
427
771
  }
428
-
429
- .mock-widget-button {
772
+
773
+ .mock-pill-launcher {
430
774
  position: relative;
431
- width: 60px;
432
- height: 60px;
433
- border-radius: 50%;
434
- background: #FFFFFF;
435
- border: none;
436
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
775
+ display: flex;
776
+ align-items: center;
777
+ gap: 10px;
778
+ padding: 7px 16px 7px 7px;
779
+ background: linear-gradient(135deg, #581c87, #312e81, #1e1b4b);
780
+ border: 1px solid rgba(139,92,246,0.15);
781
+ border-radius: 999px;
782
+ box-shadow: 0 8px 32px rgba(88,28,135,0.35), 0 2px 8px rgba(0,0,0,0.2);
437
783
  cursor: pointer;
784
+ transition: box-shadow 0.25s, transform 0.2s;
785
+ font-family: inherit;
786
+ color: #fff;
787
+ overflow: hidden;
788
+ white-space: nowrap;
789
+ }
790
+
791
+ .mock-pill-launcher:hover {
792
+ transform: translateY(-1px);
793
+ box-shadow: 0 10px 40px rgba(88,28,135,0.45), 0 4px 12px rgba(0,0,0,0.25);
794
+ }
795
+
796
+ .mock-pill-icon {
797
+ width: 36px;
798
+ height: 36px;
799
+ border-radius: 50%;
800
+ background: #ffffff;
438
801
  display: flex;
439
802
  align-items: center;
440
803
  justify-content: center;
441
- font-size: 24px;
442
- transition: all 0.3s;
443
- margin: 0;
444
804
  flex-shrink: 0;
445
805
  }
446
806
 
447
- .mock-widget-button:hover {
448
- transform: scale(1.1);
449
- box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
807
+ .mock-pill-icon img {
808
+ width: 22px;
809
+ height: 22px;
810
+ border-radius: 50%;
811
+ object-fit: cover;
812
+ }
813
+
814
+ .mock-pill-icon .pill-emoji {
815
+ font-size: 18px;
816
+ line-height: 1;
817
+ }
818
+
819
+ /* Match SDK default pill: waveform in frosted circle */
820
+ .mock-pill-icon.mock-pill-icon--wave {
821
+ background: rgba(255, 255, 255, 0.15);
822
+ }
823
+ .mock-pill-waveform {
824
+ display: flex;
825
+ align-items: center;
826
+ gap: 2px;
827
+ height: 16px;
828
+ }
829
+ .mock-pill-waveform .bar {
830
+ width: 2px;
831
+ background: #fff;
832
+ border-radius: 1px;
833
+ animation: mockPillWaveAnim 0.8s ease-in-out infinite;
834
+ transform-origin: center bottom;
835
+ }
836
+ .mock-pill-waveform .bar:nth-child(1) { height: 5px; animation-delay: 0s; }
837
+ .mock-pill-waveform .bar:nth-child(2) { height: 10px; animation-delay: 0.1s; }
838
+ .mock-pill-waveform .bar:nth-child(3) { height: 16px; animation-delay: 0.2s; }
839
+ .mock-pill-waveform .bar:nth-child(4) { height: 8px; animation-delay: 0.3s; }
840
+ .mock-pill-waveform .bar:nth-child(5) { height: 12px; animation-delay: 0.4s; }
841
+ @keyframes mockPillWaveAnim {
842
+ 0%, 100% { transform: scaleY(0.4); }
843
+ 50% { transform: scaleY(1); }
844
+ }
845
+
846
+ .mock-pill-text {
847
+ display: flex;
848
+ flex-direction: column;
849
+ gap: 1px;
850
+ }
851
+
852
+ .mock-pill-title {
853
+ font-size: 13px;
854
+ font-weight: 600;
855
+ color: #fff;
856
+ line-height: 1.2;
857
+ }
858
+
859
+ .mock-pill-status {
860
+ display: flex;
861
+ align-items: center;
862
+ gap: 5px;
863
+ font-size: 11px;
864
+ color: rgba(255,255,255,0.55);
865
+ line-height: 1.2;
866
+ }
867
+
868
+ .mock-pill-dot {
869
+ width: 7px;
870
+ height: 7px;
871
+ border-radius: 50%;
872
+ background: #4ade80;
873
+ flex-shrink: 0;
874
+ animation: mock-dot-pulse 2s ease-in-out infinite;
875
+ }
876
+
877
+ @keyframes mock-dot-pulse {
878
+ 0%, 100% { opacity: 1; }
879
+ 50% { opacity: 0.4; }
880
+ }
881
+
882
+ /* Legacy circle button (hidden by default, used for backward compat) */
883
+ .mock-widget-button {
884
+ display: none;
450
885
  }
451
886
 
452
887
  /* Prompt bubble styles */
@@ -583,12 +1018,12 @@
583
1018
 
584
1019
  .mock-widget-panel {
585
1020
  position: relative;
586
- /* Position is controlled by parent .mock-widget */
587
- width: 360px;
588
- height: 550px;
589
- background: white;
590
- border-radius: 24px;
591
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
1021
+ width: 340px;
1022
+ max-width: calc(100vw - 40px);
1023
+ background: #16161e;
1024
+ border-radius: 20px;
1025
+ box-shadow: 0 24px 60px rgba(0,0,0,0.6);
1026
+ border: 1px solid rgba(255,255,255,0.08);
592
1027
  display: none;
593
1028
  overflow: hidden;
594
1029
  flex-direction: column;
@@ -599,20 +1034,14 @@
599
1034
  }
600
1035
 
601
1036
  .mock-panel-header {
602
- background: #7C3AED;
603
- color: white;
604
- padding: 16px 20px;
605
- display: flex;
606
- align-items: center;
607
- justify-content: space-between;
608
- font-weight: 600;
1037
+ display: none;
609
1038
  }
610
1039
 
611
1040
  .mock-panel-close {
612
1041
  background: none;
613
1042
  border: none;
614
- color: white;
615
- font-size: 24px;
1043
+ color: rgba(255,255,255,0.6);
1044
+ font-size: 20px;
616
1045
  cursor: pointer;
617
1046
  padding: 0;
618
1047
  width: 32px;
@@ -620,18 +1049,117 @@
620
1049
  display: flex;
621
1050
  align-items: center;
622
1051
  justify-content: center;
623
- border-radius: 4px;
624
- transition: background 0.2s;
1052
+ border-radius: 50%;
1053
+ transition: all 0.2s;
625
1054
  }
626
1055
 
627
1056
  .mock-panel-close:hover {
628
- background: rgba(255, 255, 255, 0.2);
1057
+ background: rgba(255,255,255,0.1);
1058
+ color: #fff;
629
1059
  }
630
1060
 
631
1061
  .mock-panel-content {
632
1062
  flex: 1;
633
1063
  overflow-y: auto;
634
- padding: 0; /* Remove padding so landing screen fills entire area */
1064
+ padding: 0;
1065
+ }
1066
+
1067
+ /* Voice Idle Hero - matches real widget */
1068
+ .mock-hero {
1069
+ position: relative;
1070
+ padding: 24px 22px 22px;
1071
+ background: linear-gradient(160deg, #2a2550 0%, #1a1a2e 100%);
1072
+ border-bottom: 1px solid rgba(255,255,255,0.06);
1073
+ overflow: hidden;
1074
+ border-radius: 18px 18px 0 0;
1075
+ }
1076
+ .mock-hero::after {
1077
+ content: '';
1078
+ position: absolute;
1079
+ top: -40px; right: -40px;
1080
+ width: 140px; height: 140px;
1081
+ border-radius: 50%;
1082
+ background: radial-gradient(circle, rgba(109,86,245,0.18) 0%, transparent 70%);
1083
+ pointer-events: none;
1084
+ }
1085
+ .mock-hero-header {
1086
+ display: flex;
1087
+ align-items: center;
1088
+ justify-content: space-between;
1089
+ margin-bottom: 20px;
1090
+ position: relative;
1091
+ z-index: 1;
1092
+ }
1093
+ .mock-hero-agent {
1094
+ display: flex;
1095
+ align-items: center;
1096
+ gap: 10px;
1097
+ }
1098
+ .mock-hero-avatar-wrap {
1099
+ position: relative;
1100
+ }
1101
+ .mock-hero-avatar {
1102
+ width: 36px; height: 36px; border-radius: 50%;
1103
+ background: linear-gradient(135deg, #6d56f5, #a78bfa);
1104
+ display: flex; align-items: center; justify-content: center;
1105
+ font-size: 14px; font-weight: 500; color: #fff;
1106
+ }
1107
+ .mock-hero-online-dot {
1108
+ position: absolute; bottom: 0; right: 0;
1109
+ width: 10px; height: 10px; border-radius: 50%;
1110
+ background: #22c55e; border: 2px solid #1e1b38;
1111
+ }
1112
+ .mock-hero-agent-name {
1113
+ font-size: 14px; font-weight: 500; color: #f0eff8;
1114
+ }
1115
+ .mock-hero-agent-role {
1116
+ font-size: 10px; color: rgba(255,255,255,0.35); margin-top: 1px;
1117
+ }
1118
+ .mock-hero-close {
1119
+ width: 26px; height: 26px; border-radius: 50%;
1120
+ background: rgba(255,255,255,0.07); border: none; cursor: pointer;
1121
+ color: rgba(255,255,255,0.4);
1122
+ display: flex; align-items: center; justify-content: center;
1123
+ transition: background 0.2s;
1124
+ }
1125
+ .mock-hero-close:hover {
1126
+ background: rgba(255,255,255,0.14);
1127
+ }
1128
+ .mock-hero-headline {
1129
+ font-size: 22px; font-weight: 500; color: #fff;
1130
+ line-height: 1.2; margin-bottom: 6px; position: relative; z-index: 1;
1131
+ }
1132
+ .mock-hero-subline {
1133
+ font-size: 13px; color: rgba(255,255,255,0.45);
1134
+ line-height: 1.5; position: relative; z-index: 1;
1135
+ }
1136
+ .mock-hero-body {
1137
+ padding: 10px 18px 14px;
1138
+ display: flex; flex-direction: column; gap: 6px;
1139
+ }
1140
+ .mock-hero-btn-primary {
1141
+ width: 100%; padding: 11px; border-radius: 12px;
1142
+ background: linear-gradient(135deg, #6d56f5, #9d8df8);
1143
+ border: none; cursor: pointer;
1144
+ font-size: 13px; font-weight: 500; color: #fff;
1145
+ display: flex; align-items: center; justify-content: center; gap: 8px;
1146
+ box-shadow: 0 4px 18px rgba(109,86,245,0.35);
1147
+ transition: opacity 0.2s, transform 0.15s;
1148
+ font-family: inherit;
1149
+ }
1150
+ .mock-hero-btn-primary:hover {
1151
+ opacity: 0.9; transform: translateY(-1px);
1152
+ }
1153
+ .mock-hero-btn-secondary {
1154
+ width: 100%; padding: 10px; border-radius: 12px;
1155
+ background: rgba(255,255,255,0.05);
1156
+ border: 1px solid rgba(255,255,255,0.09);
1157
+ cursor: pointer; font-size: 13px; color: rgba(255,255,255,0.6);
1158
+ display: flex; align-items: center; justify-content: center; gap: 8px;
1159
+ transition: background 0.2s; font-family: inherit;
1160
+ }
1161
+ .mock-hero-btn-secondary:hover {
1162
+ background: rgba(255,255,255,0.09);
635
1163
  }
636
1164
 
637
1165
  .mock-landing-screen {
@@ -1268,29 +1796,87 @@
1268
1796
  </head>
1269
1797
  <body>
1270
1798
  <div class="header">
1271
- <a href="test-index.html" class="back-link">← Back to Demos</a>
1272
- <h1>🎨 Widget Live Customization</h1>
1273
- <div style="margin-top: 16px; display: flex; align-items: center; justify-content: center; gap: 24px; flex-wrap: wrap;">
1274
- <div id="modeInstructions" style="background: rgba(255,255,255,0.2); padding: 12px 20px; border-radius: 12px; font-size: 15px; font-weight: 500;">
1275
- <span id="instructionText">✏️ <strong>Single click</strong> to customize <strong>Double click</strong> to interact</span>
1276
- </div>
1799
+ <div class="header-left">
1800
+ <a href="test-index.html" class="back-link">← Back</a>
1801
+ <h1>Widget Customizer</h1>
1802
+ </div>
1803
+ <div id="modeInstructions" style="background: rgba(255,255,255,0.08); padding: 6px 14px; border-radius: 8px; font-size: 12px; font-weight: 500; color: #94a3b8; border: 1px solid rgba(255,255,255,0.06);">
1804
+ <span id="instructionText"><strong>Click</strong> to customize · <strong>Double-click</strong> to interact</span>
1277
1805
  </div>
1278
1806
  </div>
1279
1807
 
1280
1808
  <div class="container">
1281
1809
  <div class="preview-section">
1282
- <h2>Preview</h2>
1283
- <div class="preview-area" id="previewArea">
1284
- <!-- Container to ensure proper scrolling - must be taller than preview area -->
1285
- <div style="position: relative; min-height: 800px; width: 100%; padding-bottom: 200px;">
1286
- <div class="mock-widget" id="mockWidget" data-element-type="position">
1287
- <div class="mock-widget-panel" id="mockPanel">
1288
- <!-- Panel content will be dynamically generated -->
1810
+ <div class="preview-header">
1811
+ <h2>Preview</h2>
1812
+ <div class="device-toggle">
1813
+ <button class="device-toggle-btn active" id="desktopToggle" onclick="switchDevice('desktop')">
1814
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
1815
+ <span class="device-label">Desktop</span>
1816
+ </button>
1817
+ <button class="device-toggle-btn" id="mobileToggle" onclick="switchDevice('mobile')">
1818
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>
1819
+ <span class="device-label">Mobile</span>
1820
+ </button>
1821
+ </div>
1822
+ </div>
1823
+ <div class="preview-area desktop-mode" id="previewArea">
1824
+ <!-- Desktop device frame -->
1825
+ <div class="device-frame-desktop" id="deviceFrameDesktop">
1826
+ <div class="desktop-chrome">
1827
+ <div class="desktop-dots"><span></span><span></span><span></span></div>
1828
+ <div class="desktop-url-bar">yourwebsite.com</div>
1829
+ </div>
1830
+ <div class="desktop-content" id="desktopContent">
1831
+ <div class="desktop-placeholder">
1832
+ <div class="placeholder-line"></div>
1833
+ <div class="placeholder-line"></div>
1834
+ <div class="placeholder-line"></div>
1835
+ <div class="placeholder-line"></div>
1836
+ <div class="placeholder-line"></div>
1837
+ </div>
1838
+ <div class="mock-widget" id="mockWidget" data-element-type="position">
1839
+ <div class="mock-widget-panel" id="mockPanel">
1840
+ </div>
1841
+ <div class="mock-button-container" id="mockButtonContainer">
1842
+ <div class="mock-prompt-bubble" id="mockPromptBubble" style="display: none;"></div>
1843
+ <div class="mock-pulse-rings" id="mockPulseRings" style="display: none;"></div>
1844
+ <button class="mock-pill-launcher" id="mockButton" data-element-type="button">
1845
+ <div class="mock-pill-icon mock-pill-icon--wave" id="mockPillIcon">
1846
+ <div class="mock-pill-waveform" aria-hidden="true">
1847
+ <span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span>
1848
+ </div>
1849
+ </div>
1850
+ <div class="mock-pill-text" id="mockPillText">
1851
+ <span class="mock-pill-title" id="mockPillTitle">Chat Assistant</span>
1852
+ <span class="mock-pill-status">
1853
+ <span class="mock-pill-dot"></span>
1854
+ <span id="mockPillStatusText">Online</span>
1855
+ </span>
1856
+ </div>
1857
+ </button>
1858
+ </div>
1859
+ </div>
1860
+ </div>
1861
+ </div>
1862
+ <!-- Mobile device frame (hidden by default) -->
1863
+ <div class="device-frame-mobile" id="deviceFrameMobile" style="display: none;">
1864
+ <div class="phone-notch"></div>
1865
+ <div class="phone-screen">
1866
+ <div class="phone-status-bar">
1867
+ <span>9:41</span>
1868
+ <span style="display: flex; gap: 4px; font-size: 11px;">
1869
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z"/></svg>
1870
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="2" y="6" width="18" height="12" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><rect x="20" y="10" width="2" height="4" rx="1"/><rect x="4" y="8" width="10" height="8" rx="1"/></svg>
1871
+ </span>
1289
1872
  </div>
1290
- <div class="mock-button-container" id="mockButtonContainer">
1291
- <div class="mock-prompt-bubble" id="mockPromptBubble" style="display: none;"></div>
1292
- <div class="mock-pulse-rings" id="mockPulseRings" style="display: none;"></div>
1293
- <button class="mock-widget-button" id="mockButton">🎤</button>
1873
+ <div class="phone-content" id="phoneContent">
1874
+ <div class="phone-placeholder">
1875
+ <div class="placeholder-line"></div>
1876
+ <div class="placeholder-line"></div>
1877
+ <div class="placeholder-line"></div>
1878
+ <div class="placeholder-line"></div>
1879
+ </div>
1294
1880
  </div>
1295
1881
  </div>
1296
1882
  </div>
@@ -1298,40 +1884,109 @@
1298
1884
  </div>
1299
1885
 
1300
1886
  <div class="customization-panel">
1301
- <h2>Customization</h2>
1302
-
1303
- <div class="info-box" id="instructionsBox">
1304
- <p id="instructionsText">
1305
- <strong>How to use:</strong><br>
1306
- <span style="display: block; margin-top: 8px;">
1307
- <strong>Single Click:</strong> Select any widget element to customize its appearance. Changes apply instantly.<br>
1308
- <strong>Double Click:</strong> Interact with elements normally (open widget, switch views, etc.)
1309
- </span>
1310
- <span style="display: block; margin-top: 12px; font-size: 13px; color: #1e40af;">
1311
- 💡 <strong>Tip:</strong> Single click any element to see customization options. Double click to use it normally.
1312
- </span>
1313
- </p>
1887
+ <div class="customization-panel-header">
1888
+ <h2>Customize</h2>
1314
1889
  </div>
1315
-
1316
- <div id="customizationControls" style="flex: 0 0 auto; overflow: visible; margin-bottom: 16px;">
1317
- <!-- Controls will be dynamically generated based on selected element -->
1318
- <div class="customization-group">
1319
- <h3>Select an Element</h3>
1320
- <p style="color: #6b7280; font-size: 14px; margin-top: 8px;">
1321
- Click on any widget element in the preview to start customizing.
1890
+ <div class="customization-panel-body">
1891
+ <div class="info-box" id="instructionsBox">
1892
+ <p id="instructionsText">
1893
+ <strong>Click</strong> any widget element to customize it. <strong>Double-click</strong> to interact normally.
1322
1894
  </p>
1323
1895
  </div>
1324
- </div>
1325
1896
 
1326
- <div style="flex-shrink: 0; display: flex; flex-direction: column; gap: 16px; margin-top: auto;">
1327
- <div class="button-group" style="flex-shrink: 0;">
1328
- <button class="btn btn-primary" id="resetBtn">Reset to Defaults</button>
1897
+ <div class="quick-themes">
1898
+ <h3>Quick Themes</h3>
1899
+ <div class="theme-cards" id="themeCards">
1900
+ <!-- Default Dark -->
1901
+ <button class="theme-card active" data-theme="default" id="themeDefault">
1902
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #2a1f4e 0%, #0d0d1a 100%);">
1903
+ <div class="theme-card-top">
1904
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #a78bfa, #7c3aed);">S</div>
1905
+ <div class="theme-card-lines">
1906
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1907
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1908
+ </div>
1909
+ </div>
1910
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #8b5cf6, #6d28d9);"></div>
1911
+ </div>
1912
+ <div class="theme-card-label">Default</div>
1913
+ </button>
1914
+ <!-- Light -->
1915
+ <button class="theme-card" data-theme="light" id="themeLight">
1916
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #ede9fe 0%, #f5f3ff 100%);">
1917
+ <div class="theme-card-top">
1918
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #7c3aed, #a78bfa);">S</div>
1919
+ <div class="theme-card-lines">
1920
+ <div class="theme-card-line" style="width: 24px; background: #1e1b4b;"></div>
1921
+ <div class="theme-card-line" style="width: 16px; background: rgba(30,27,75,0.35);"></div>
1922
+ </div>
1923
+ </div>
1924
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #7c3aed, #a78bfa);"></div>
1925
+ </div>
1926
+ <div class="theme-card-label">Light</div>
1927
+ </button>
1928
+ <!-- Sunset -->
1929
+ <button class="theme-card" data-theme="sunset" id="themeSunset">
1930
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #4a1942 0%, #1a0a2e 100%);">
1931
+ <div class="theme-card-top">
1932
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #f97316, #ec4899);">S</div>
1933
+ <div class="theme-card-lines">
1934
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1935
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1936
+ </div>
1937
+ </div>
1938
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #f97316, #ec4899);"></div>
1939
+ </div>
1940
+ <div class="theme-card-label">Sunset</div>
1941
+ </button>
1942
+ <!-- Hebrew RTL -->
1943
+ <button class="theme-card" data-theme="hebrew" id="themeHebrew">
1944
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #1a2744 0%, #0f172a 100%); direction: rtl;">
1945
+ <div class="theme-card-top" style="flex-direction: row-reverse;">
1946
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #3b82f6, #1d4ed8);">ש</div>
1947
+ <div class="theme-card-lines" style="align-items: flex-end;">
1948
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1949
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1950
+ </div>
1951
+ </div>
1952
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #3b82f6, #1d4ed8);"></div>
1953
+ </div>
1954
+ <div class="theme-card-label">עברית</div>
1955
+ </button>
1956
+ <!-- Sasha / S-Law -->
1957
+ <button class="theme-card" data-theme="sasha" id="themeSasha">
1958
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #f8f5ef 0%, #ebe6de 100%); direction: rtl;">
1959
+ <div class="theme-card-top" style="flex-direction: row-reverse;">
1960
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #c4a265, #9e7e4f);">S</div>
1961
+ <div class="theme-card-lines" style="align-items: flex-end;">
1962
+ <div class="theme-card-line" style="width: 24px; background: #2d3748;"></div>
1963
+ <div class="theme-card-line" style="width: 16px; background: rgba(45,55,72,0.35);"></div>
1964
+ </div>
1965
+ </div>
1966
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #c4a265, #9e7e4f);"></div>
1967
+ </div>
1968
+ <div class="theme-card-label">S-Law</div>
1969
+ </button>
1970
+ </div>
1971
+ </div>
1972
+
1973
+ <div id="customizationControls" style="margin-bottom: 12px;">
1974
+ <div class="customization-group">
1975
+ <h3>Select an Element</h3>
1976
+ <p style="color: #64748b; font-size: 13px; margin-top: 8px;">
1977
+ Click on any widget element in the preview to start customizing.
1978
+ </p>
1979
+ </div>
1980
+ </div>
1981
+
1982
+ <div class="button-group" style="margin-bottom: 12px;">
1983
+ <button class="btn btn-primary" id="resetBtn">Reset</button>
1329
1984
  <button class="btn btn-secondary" id="togglePanelBtn">Toggle Panel</button>
1330
1985
  </div>
1331
1986
 
1332
- <div class="code-output" style="flex-shrink: 0; height: auto; min-height: 400px; max-height: none; overflow-y: visible; overflow-x: auto; margin-bottom: 0;">
1333
- <h3 style="color: #f9fafb; margin-bottom: 12px; font-size: 16px; font-weight: 700;">Configuration Code:</h3>
1334
- <pre id="configCode" style="margin: 0; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 1.6;">// Select an element to see its configuration</pre>
1987
+ <div class="code-output">
1988
+ <h3>Configuration Code</h3>
1989
+ <pre id="configCode">// Select an element to see its configuration</pre>
1335
1990
  </div>
1336
1991
  </div>
1337
1992
  </div>
@@ -1340,6 +1995,7 @@
1340
1995
  <script>
1341
1996
  // Mock widget configuration
1342
1997
  let widgetConfig = {
1998
+ agentName: 'Sasha',
1343
1999
  button: {
1344
2000
  size: 'medium',
1345
2001
  shape: 'circle',
@@ -1350,16 +2006,15 @@
1350
2006
  },
1351
2007
  icon: {
1352
2008
  type: 'custom',
1353
- customImage: 'https://talktopc.com/logo192.png',
1354
2009
  size: 'medium',
1355
2010
  backgroundColor: '#FFFFFF'
1356
2011
  },
1357
2012
  panel: {
1358
- width: 360,
1359
- height: 550, // Updated from SDK default 500
1360
- borderRadius: 24,
1361
- backgroundColor: '#FFFFFF',
1362
- border: '1px solid #E5E7EB'
2013
+ width: 340,
2014
+ height: 550,
2015
+ borderRadius: 20,
2016
+ backgroundColor: '#16161e',
2017
+ border: '1px solid rgba(255,255,255,0.08)'
1363
2018
  },
1364
2019
  direction: 'ltr', // 'ltr' or 'rtl'
1365
2020
  position: {
@@ -1395,6 +2050,9 @@
1395
2050
  inputFocusColor: '#7C3AED'
1396
2051
  },
1397
2052
  voice: {
2053
+ agentRole: 'AI Voice Assistant',
2054
+ headline: 'Hi there 👋',
2055
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
1398
2056
  micButtonColor: '#7C3AED',
1399
2057
  micButtonActiveColor: '#EF4444',
1400
2058
  speakerButtonColor: '#FFFFFF',
@@ -1403,7 +2061,7 @@
1403
2061
  avatarType: 'icon', // 'icon' or 'image'
1404
2062
  avatarIcon: '🤖',
1405
2063
  avatarImageUrl: '',
1406
- startCallButtonText: 'Start Call',
2064
+ startCallButtonText: 'Start Voice Call',
1407
2065
  startCallButtonColor: '#667eea',
1408
2066
  startCallButtonTextColor: '#FFFFFF',
1409
2067
  statusTitleColor: '#1e293b',
@@ -1416,7 +2074,11 @@
1416
2074
  liveIndicatorTextColor: '#10b981',
1417
2075
  waveformType: 'waveform', // 'waveform', 'icon', or 'image'
1418
2076
  waveformIcon: '🎤',
1419
- waveformImageUrl: ''
2077
+ waveformImageUrl: '',
2078
+ waveformBarColor: '#7C3AED',
2079
+ pillGradient: '',
2080
+ pillTextColor: '#ffffff',
2081
+ pillDotColor: '#4ade80'
1420
2082
  },
1421
2083
  landing: {
1422
2084
  backgroundColor: 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', // Default gradient matching real widget
@@ -1454,7 +2116,8 @@
1454
2116
  };
1455
2117
 
1456
2118
  let selectedElement = null;
1457
- let currentView = 'landing'; // 'landing', 'text', 'voice'
2119
+ let currentView = 'voiceIdle'; // 'voiceIdle', 'landing', 'text', 'voice'
2120
+ let currentDevice = 'desktop'; // 'desktop', 'mobile'
1458
2121
  let panelOpen = true; // Start with panel open to show defaults
1459
2122
  let clickTimeout = null; // Track single vs double click
1460
2123
  let historyExpanded = false; // Track conversation history state
@@ -1463,6 +2126,37 @@
1463
2126
  let lastClickElement = null;
1464
2127
  let lastClickType = null;
1465
2128
 
2129
+ function switchDevice(device) {
2130
+ currentDevice = device;
2131
+ const desktopBtn = document.getElementById('desktopToggle');
2132
+ const mobileBtn = document.getElementById('mobileToggle');
2133
+ const previewArea = document.getElementById('previewArea');
2134
+ const desktopFrame = document.getElementById('deviceFrameDesktop');
2135
+ const mobileFrame = document.getElementById('deviceFrameMobile');
2136
+ const mockWidget = document.getElementById('mockWidget');
2137
+
2138
+ desktopBtn.classList.toggle('active', device === 'desktop');
2139
+ mobileBtn.classList.toggle('active', device === 'mobile');
2140
+ previewArea.classList.toggle('desktop-mode', device === 'desktop');
2141
+ previewArea.classList.toggle('mobile-mode', device === 'mobile');
2142
+
2143
+ if (device === 'desktop') {
2144
+ desktopFrame.style.display = '';
2145
+ mobileFrame.style.display = 'none';
2146
+ if (mockWidget.parentElement !== document.getElementById('desktopContent')) {
2147
+ document.getElementById('desktopContent').appendChild(mockWidget);
2148
+ }
2149
+ } else {
2150
+ desktopFrame.style.display = 'none';
2151
+ mobileFrame.style.display = '';
2152
+ if (mockWidget.parentElement !== document.getElementById('phoneContent')) {
2153
+ document.getElementById('phoneContent').appendChild(mockWidget);
2154
+ }
2155
+ }
2156
+ updateMockWidgetPosition();
2157
+ }
2158
+ window.switchDevice = switchDevice;
2159
+
1466
2160
  // Initialize mock widget
1467
2161
  function initMockWidget() {
1468
2162
  const mockButton = document.getElementById('mockButton');
@@ -1506,58 +2200,64 @@
1506
2200
  }
1507
2201
 
1508
2202
  function applyButtonStyles(button) {
1509
- const config = widgetConfig.button;
1510
- button.style.width = getSizeValue(config.size) + 'px';
1511
- button.style.height = getSizeValue(config.size) + 'px';
1512
- button.style.backgroundColor = config.backgroundColor;
1513
- button.style.borderRadius = config.shape === 'circle' ? '50%' : config.shape === 'rounded' ? '12px' : '0';
1514
-
1515
- if (config.shadow) {
1516
- button.style.boxShadow = `0 4px 12px ${config.shadowColor}`;
1517
- } else {
1518
- button.style.boxShadow = 'none';
2203
+ const iconConfig = widgetConfig.icon;
2204
+ const headerConfig = widgetConfig.header;
2205
+
2206
+ // Update pill icon (SDK: custom URL → image; else animated waveform like mobile FAB)
2207
+ const pillIcon = document.getElementById('mockPillIcon');
2208
+ if (pillIcon) {
2209
+ const hasCustomUrl = iconConfig.type === 'custom' && iconConfig.customImage != null && String(iconConfig.customImage).trim() !== '';
2210
+ if (hasCustomUrl) {
2211
+ pillIcon.className = 'mock-pill-icon';
2212
+ pillIcon.innerHTML = `<img src="${iconConfig.customImage}" alt="" style="width:22px;height:22px;border-radius:50%;object-fit:cover;">`;
2213
+ pillIcon.style.backgroundColor = iconConfig.backgroundColor || '#ffffff';
2214
+ } else if (iconConfig.type === 'emoji') {
2215
+ pillIcon.className = 'mock-pill-icon';
2216
+ pillIcon.innerHTML = `<span class="pill-emoji">${iconConfig.emoji || '🤖'}</span>`;
2217
+ pillIcon.style.backgroundColor = iconConfig.backgroundColor || '#ffffff';
2218
+ } else {
2219
+ pillIcon.className = 'mock-pill-icon mock-pill-icon--wave';
2220
+ pillIcon.innerHTML = '<div class="mock-pill-waveform" aria-hidden="true"><span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span></div>';
2221
+ pillIcon.style.backgroundColor = '';
2222
+ }
1519
2223
  }
1520
2224
 
1521
- // Apply icon
1522
- const iconConfig = widgetConfig.icon;
1523
- button.innerHTML = ''; // Clear previous content
1524
-
1525
- if (iconConfig.type === 'custom' && iconConfig.customImage) {
1526
- const img = document.createElement('img');
1527
- img.src = iconConfig.customImage;
1528
- img.alt = 'Chat Assistant';
1529
- const iconSize = Math.floor(getSizeValue(config.size) * 0.6);
1530
- img.style.width = iconSize + 'px';
1531
- img.style.height = iconSize + 'px';
1532
- img.style.objectFit = 'contain';
1533
- button.appendChild(img);
1534
- } else if (iconConfig.type === 'emoji') {
1535
- button.textContent = iconConfig.emoji;
1536
- } else if (iconConfig.type === 'text') {
1537
- button.textContent = iconConfig.text;
1538
- } else if (iconConfig.type === 'microphone') {
1539
- // Default microphone SVG
1540
- const iconSize = Math.floor(getSizeValue(config.size) * 0.5);
1541
- button.innerHTML = `<svg viewBox="0 0 24 24" style="width: ${iconSize}px; height: ${iconSize}px; fill: #7C3AED;">
1542
- <path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/>
1543
- <path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/>
1544
- </svg>`;
2225
+ // Update pill title and status
2226
+ const pillTitle = document.getElementById('mockPillTitle');
2227
+ if (pillTitle) pillTitle.textContent = headerConfig.title || 'Chat Assistant';
2228
+
2229
+ const pillStatusText = document.getElementById('mockPillStatusText');
2230
+ if (pillStatusText) pillStatusText.textContent = headerConfig.onlineIndicatorText || 'Online';
2231
+
2232
+ // Update pill launcher background
2233
+ const pillGrad = widgetConfig.voice?.pillGradient;
2234
+ if (pillGrad) {
2235
+ button.style.background = pillGrad;
1545
2236
  } else {
1546
- // Fallback to custom image if type is custom but no image specified
1547
- const img = document.createElement('img');
1548
- img.src = 'https://talktopc.com/logo192.png';
1549
- img.alt = 'Chat Assistant';
1550
- const iconSize = Math.floor(getSizeValue(config.size) * 0.6);
1551
- img.style.width = iconSize + 'px';
1552
- img.style.height = iconSize + 'px';
1553
- img.style.objectFit = 'contain';
1554
- button.appendChild(img);
2237
+ const bgColor = widgetConfig.button.backgroundColor;
2238
+ if (bgColor && bgColor !== '#FFFFFF' && bgColor !== '#ffffff') {
2239
+ button.style.background = bgColor;
2240
+ }
2241
+ }
2242
+
2243
+ // Update pill direction
2244
+ button.style.direction = widgetConfig.direction || 'ltr';
2245
+
2246
+ // Update pill text colors
2247
+ const pillTextColor = widgetConfig.voice?.pillTextColor;
2248
+ if (pillTextColor) {
2249
+ if (pillTitle) pillTitle.style.color = pillTextColor;
2250
+ const pillStatus = button.querySelector('.mock-pill-status');
2251
+ if (pillStatus) pillStatus.style.color = pillTextColor.replace('1)', '0.55)').replace('#fff', 'rgba(255,255,255,0.55)');
2252
+ }
2253
+ const pillDotColor = widgetConfig.voice?.pillDotColor;
2254
+ const pillDot = button.querySelector('.mock-pill-dot');
2255
+ if (pillDotColor && pillDot) {
2256
+ pillDot.style.background = pillDotColor;
1555
2257
  }
1556
2258
 
1557
- // Make button highlightable
1558
2259
  button.dataset.elementType = 'button';
1559
2260
 
1560
- // Update prompt bubble if enabled
1561
2261
  updatePromptBubble(button);
1562
2262
 
1563
2263
  // Remove old event listeners by replacing the button
@@ -1570,25 +2270,19 @@
1570
2270
  e.preventDefault();
1571
2271
  e.stopPropagation();
1572
2272
 
1573
- // For button, single click should toggle panel immediately
1574
- // Double click will still select for editing (without double-toggling)
1575
2273
  const currentTime = Date.now();
1576
2274
  const timeSinceLastClick = currentTime - lastClickTime;
1577
2275
 
1578
- // Check if this is a double click (within 400ms and same element)
1579
2276
  if (timeSinceLastClick < 400 && lastClickElement === newButton && lastClickType === 'button') {
1580
- // Double click - just select for editing (don't toggle panel again)
1581
2277
  lastClickTime = 0;
1582
2278
  lastClickElement = null;
1583
2279
  lastClickType = null;
1584
2280
  selectElement('button', newButton, e);
1585
2281
  } else {
1586
- // Single click - toggle panel immediately and select button
1587
2282
  lastClickTime = currentTime;
1588
2283
  lastClickElement = newButton;
1589
2284
  lastClickType = 'button';
1590
2285
 
1591
- // Toggle panel
1592
2286
  panelOpen = !panelOpen;
1593
2287
  const panel = document.getElementById('mockPanel');
1594
2288
  panel.classList.toggle('open');
@@ -1596,12 +2290,8 @@
1596
2290
  renderPanelContent();
1597
2291
  }
1598
2292
 
1599
- // Update prompt bubble visibility based on panel state
1600
2293
  updatePromptBubble(newButton);
1601
- // Sync actual widget state with mock panel
1602
2294
  syncWidgetWithMockPanel();
1603
-
1604
- // Select the button for editing (so user can customize it)
1605
2295
  selectElement('button', newButton, e);
1606
2296
  }
1607
2297
  });
@@ -1686,46 +2376,52 @@
1686
2376
 
1687
2377
  const pos = widgetConfig.position;
1688
2378
  const offset = pos.offset || { x: 20, y: 20 };
1689
-
1690
- // Clear any existing positioning
2379
+
1691
2380
  mockWidget.style.top = '';
1692
2381
  mockWidget.style.bottom = '';
1693
2382
  mockWidget.style.left = '';
1694
2383
  mockWidget.style.right = '';
1695
-
1696
- // Set position
1697
2384
  mockWidget.style.position = 'absolute';
1698
-
1699
- // Vertical positioning - use config value
1700
- if (pos.vertical === 'top') {
1701
- mockWidget.style.setProperty('top', `${offset.y}px`, 'important');
1702
- mockWidget.style.setProperty('bottom', 'auto', 'important');
1703
- } else if (pos.vertical === 'bottom') {
1704
- mockWidget.style.setProperty('bottom', `${offset.y}px`, 'important');
1705
- mockWidget.style.setProperty('top', 'auto', 'important');
2385
+
2386
+ if (currentDevice === 'mobile') {
2387
+ const mobileOffset = { x: Math.min(offset.x, 12), y: Math.min(offset.y, 12) };
2388
+ if (pos.vertical === 'top') {
2389
+ mockWidget.style.setProperty('top', `${mobileOffset.y}px`, 'important');
2390
+ mockWidget.style.setProperty('bottom', 'auto', 'important');
2391
+ } else {
2392
+ mockWidget.style.setProperty('bottom', `${mobileOffset.y}px`, 'important');
2393
+ mockWidget.style.setProperty('top', 'auto', 'important');
2394
+ }
2395
+ mockWidget.style.setProperty('right', `${mobileOffset.x}px`, 'important');
2396
+ mockWidget.style.setProperty('left', 'auto', 'important');
2397
+ } else {
2398
+ if (pos.vertical === 'top') {
2399
+ mockWidget.style.setProperty('top', `${offset.y}px`, 'important');
2400
+ mockWidget.style.setProperty('bottom', 'auto', 'important');
2401
+ } else {
2402
+ mockWidget.style.setProperty('bottom', `${offset.y}px`, 'important');
2403
+ mockWidget.style.setProperty('top', 'auto', 'important');
2404
+ }
2405
+ mockWidget.style.setProperty('right', `${offset.x}px`, 'important');
2406
+ mockWidget.style.setProperty('left', 'auto', 'important');
1706
2407
  }
1707
-
1708
- // Horizontal positioning - ALWAYS keep mock widget on the right side
1709
- mockWidget.style.setProperty('right', `${offset.x}px`, 'important');
1710
- mockWidget.style.setProperty('left', 'auto', 'important');
1711
2408
  }
1712
2409
 
1713
2410
  function renderPanelContent() {
1714
2411
  const mockPanel = document.getElementById('mockPanel');
1715
2412
 
1716
- // Apply panel styles
2413
+ // Apply panel styles - dark shell (matches real widget: width 340px, auto height)
1717
2414
  mockPanel.style.width = widgetConfig.panel.width + 'px';
1718
- mockPanel.style.height = widgetConfig.panel.height + 'px';
1719
- mockPanel.style.borderRadius = widgetConfig.panel.borderRadius + 'px';
1720
- // Panel background should match landing background to avoid double-frame effect
1721
- const landingBg = widgetConfig.landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)';
1722
- mockPanel.style.backgroundColor = landingBg;
1723
- mockPanel.style.border = widgetConfig.panel.border;
1724
- // Apply direction (LTR/RTL)
2415
+ mockPanel.style.height = 'auto';
2416
+ mockPanel.style.borderRadius = (widgetConfig.panel.borderRadius || 20) + 'px';
2417
+ mockPanel.style.background = widgetConfig.panel.backgroundColor || '#16161e';
2418
+ mockPanel.style.border = widgetConfig.panel.border || '1px solid rgba(255,255,255,0.08)';
1725
2419
  mockPanel.style.direction = widgetConfig.direction || 'ltr';
1726
2420
 
1727
2421
  // Render based on current view
1728
- if (currentView === 'landing') {
2422
+ if (currentView === 'voiceIdle') {
2423
+ renderVoiceIdleScreen(mockPanel);
2424
+ } else if (currentView === 'landing') {
1729
2425
  renderLandingScreen(mockPanel);
1730
2426
  } else if (currentView === 'text') {
1731
2427
  renderTextInterface(mockPanel);
@@ -1737,9 +2433,97 @@
1737
2433
  addPanelSelector();
1738
2434
  }
1739
2435
 
2436
+ function isLightBackground(hex) {
2437
+ if (!hex || hex.charAt(0) !== '#') return false;
2438
+ const r = parseInt(hex.substr(1,2), 16);
2439
+ const g = parseInt(hex.substr(3,2), 16);
2440
+ const b = parseInt(hex.substr(5,2), 16);
2441
+ return (r * 299 + g * 587 + b * 114) / 1000 > 160;
2442
+ }
2443
+
2444
+ function renderVoiceIdleScreen(panel) {
2445
+ const v = widgetConfig.voice || {};
2446
+ const agentName = widgetConfig.agentName || 'Sasha';
2447
+ const agentRole = v.agentRole || 'AI Voice Assistant';
2448
+ const headline = v.headline || 'Hi there 👋';
2449
+ const subline = v.subline || 'Ask me anything — I respond instantly<br>in voice or text.';
2450
+ const avatarInitial = agentName.charAt(0).toUpperCase();
2451
+ const avatarGrad1 = v.avatarGradient1 || '#6d56f5';
2452
+ const avatarGrad2 = v.avatarGradient2 || '#a78bfa';
2453
+ const onlineDotColor = v.onlineDotColor || '#22c55e';
2454
+ const heroGrad1 = v.heroGradient1 || '#2a2550';
2455
+ const heroGrad2 = v.heroGradient2 || '#1a1a2e';
2456
+ const nameColor = v.agentNameColor || '#f0eff8';
2457
+ const roleColor = v.agentRoleColor || 'rgba(255,255,255,0.35)';
2458
+ const headlineColor = v.headlineColor || '#ffffff';
2459
+ const sublineColor = v.sublineColor || 'rgba(255,255,255,0.45)';
2460
+ const primaryBtnGrad1 = v.primaryBtnGradient1 || '#6d56f5';
2461
+ const primaryBtnGrad2 = v.primaryBtnGradient2 || '#9d8df8';
2462
+ const primaryBtnTextColor = v.startCallButtonTextColor || '#ffffff';
2463
+ const secondaryBtnBg = v.secondaryBtnBg || 'rgba(255,255,255,0.05)';
2464
+ const secondaryBtnBorder = v.secondaryBtnBorder || 'rgba(255,255,255,0.09)';
2465
+ const secondaryBtnTextColor = v.secondaryBtnTextColor || 'rgba(255,255,255,0.6)';
2466
+ const sendMessageText = v.sendMessageText || 'Send a Message';
2467
+
2468
+ const panelBg = widgetConfig.panel?.backgroundColor || '#16161e';
2469
+ const light = isLightBackground(panelBg);
2470
+ const closeColor = light ? '#6b7280' : 'currentColor';
2471
+ const footerBorderColor = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2472
+ const footerTextColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2473
+ const footerLinkColor = light ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
2474
+
2475
+ panel.innerHTML = `
2476
+ <div class="mock-hero" data-element-type="heroBackground" style="background: linear-gradient(160deg, ${heroGrad1} 0%, ${heroGrad2} 100%);">
2477
+ <div class="mock-hero-header">
2478
+ <div class="mock-hero-agent">
2479
+ <div class="mock-hero-avatar-wrap">
2480
+ <div class="mock-hero-avatar" data-element-type="heroAvatar" style="background: linear-gradient(135deg, ${avatarGrad1}, ${avatarGrad2});">${avatarInitial}</div>
2481
+ <div class="mock-hero-online-dot" style="background: ${onlineDotColor};"></div>
2482
+ </div>
2483
+ <div>
2484
+ <div class="mock-hero-agent-name" data-element-type="heroAgentName" style="color: ${nameColor};">${agentName}</div>
2485
+ <div class="mock-hero-agent-role" data-element-type="heroAgentRole" style="color: ${roleColor};">${agentRole}</div>
2486
+ </div>
2487
+ </div>
2488
+ <button class="mock-hero-close" data-element-type="closeButton" style="color: ${closeColor};">
2489
+ <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2">
2490
+ <path d="M10 2L2 10M2 2l8 8"/>
2491
+ </svg>
2492
+ </button>
2493
+ </div>
2494
+ <div class="mock-hero-headline" data-element-type="heroHeadline" style="color: ${headlineColor};">${headline}</div>
2495
+ <div class="mock-hero-subline" data-element-type="heroSubline" style="color: ${sublineColor};">${subline}</div>
2496
+ </div>
2497
+ <div class="mock-hero-body" style="background: ${panelBg};">
2498
+ <button class="mock-hero-btn-primary" data-element-type="heroPrimaryBtn" style="background: linear-gradient(135deg, ${primaryBtnGrad1}, ${primaryBtnGrad2}); color: ${primaryBtnTextColor};">
2499
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${primaryBtnTextColor}" stroke-width="2">
2500
+ <path d="M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z"/>
2501
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8"/>
2502
+ </svg>
2503
+ ${v.startCallButtonText || 'Start Voice Call'}
2504
+ </button>
2505
+ <button class="mock-hero-btn-secondary" data-element-type="heroSecondaryBtn" style="background: ${secondaryBtnBg}; border: 1px solid ${secondaryBtnBorder}; color: ${secondaryBtnTextColor};">
2506
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="${secondaryBtnTextColor}" stroke-width="2">
2507
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
2508
+ </svg>
2509
+ ${sendMessageText}
2510
+ </button>
2511
+ </div>
2512
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${footerBorderColor}; background: transparent; flex-shrink: 0;">
2513
+ <span style="font-size: 10px; color: ${footerTextColor};">Powered by <a href="#" style="color: ${footerLinkColor}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2514
+ </div>
2515
+ `;
2516
+
2517
+ setupElementListeners(panel);
2518
+ }
2519
+
1740
2520
  function renderLandingScreen(panel) {
1741
2521
  const config = widgetConfig.landing;
1742
2522
  const iconBgColor = config.modeCardIconBackgroundColor || '#7C3AED';
2523
+ const landingLight = true; // landing screen always has a light background
2524
+ const landFooterBorder = 'rgba(0,0,0,0.08)';
2525
+ const landFooterText = 'rgba(0,0,0,0.4)';
2526
+ const landFooterLink = iconBgColor;
1743
2527
  // Determine logo background - use logoBackgroundColor if enabled, otherwise transparent
1744
2528
  let logoBg = 'transparent';
1745
2529
  if (config.logoType === 'image' && config.logoBackgroundEnabled !== false) {
@@ -1750,18 +2534,8 @@
1750
2534
  }
1751
2535
 
1752
2536
  panel.innerHTML = `
1753
- <div class="mock-panel-header" style="background: ${widgetConfig.header.backgroundColor}; color: ${widgetConfig.header.textColor}; direction: ${widgetConfig.direction || 'ltr'};" data-element-type="header">
1754
- <div style="display: flex; align-items: center; gap: 8px;">
1755
- <span>${widgetConfig.header.title}</span>
1756
- <div style="display: flex; align-items: center; gap: 6px; margin-left: 8px;" data-element-type="onlineIndicator">
1757
- <div style="width: 6px; height: 6px; background: ${widgetConfig.header.onlineIndicatorDotColor || '#10b981'}; border-radius: 50%; animation: pulse 2s ease-in-out infinite;"></div>
1758
- <span style="font-size: 12px; opacity: 0.9; color: ${widgetConfig.header.onlineIndicatorColor || widgetConfig.header.textColor};">${widgetConfig.header.onlineIndicatorText || 'Online'}</span>
1759
- </div>
1760
- </div>
1761
- ${widgetConfig.header.showCloseButton ? '<button class="mock-panel-close" data-element-type="closeButton">×</button>' : ''}
1762
- </div>
1763
2537
  <div class="mock-panel-content" style="direction: ${widgetConfig.direction || 'ltr'};">
1764
- <div class="mock-landing-screen" style="background: ${config.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)'}; height: 100%;" data-element-type="landingBackground">
2538
+ <div class="mock-landing-screen" style="background: ${config.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)'}; height: 100%; border-radius: 18px 18px 0 0;" data-element-type="landingBackground">
1765
2539
  <div class="mock-landing-logo" style="background: ${logoBg}; ${logoBg !== 'transparent' ? 'box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none !important;' : 'box-shadow: none !important; border: none !important; outline: none !important;'}" data-element-type="landingLogo">
1766
2540
  ${config.logoType === 'image' && config.logoImageUrl ? `
1767
2541
  <img src="${config.logoImageUrl}" alt="Logo" style="max-width: 44px; max-height: 44px; object-fit: contain;">
@@ -1794,11 +2568,8 @@
1794
2568
  </div>
1795
2569
  </div>
1796
2570
  </div>
1797
- <div class="mock-footer" style="padding: 10px 16px; text-align: center; border-top: 1px solid rgba(0,0,0,0.06); font-size: 11px; color: #64748b; background: #fff; flex-shrink: 0;">
1798
- <span style="display: inline-flex; align-items: center; gap: 4px;">
1799
- <span>⚡</span>
1800
- <span>Powered by TalkToPC</span>
1801
- </span>
2571
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${landFooterBorder}; background: transparent; flex-shrink: 0;">
2572
+ <span style="font-size: 10px; color: ${landFooterText};">Powered by <a href="#" style="color: ${landFooterLink}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
1802
2573
  </div>
1803
2574
  `;
1804
2575
 
@@ -1808,13 +2579,14 @@
1808
2579
 
1809
2580
  function renderTextInterface(panel) {
1810
2581
  const config = widgetConfig.text;
2582
+ const panelBgText = widgetConfig.panel.backgroundColor || '#16161e';
2583
+ const lightText = isLightBackground(panelBgText);
2584
+ const textFooterBorder = lightText ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2585
+ const textFooterColor = lightText ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2586
+ const textFooterLink = lightText ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
1811
2587
  panel.innerHTML = `
1812
- <div class="mock-panel-header" style="background: ${widgetConfig.header.backgroundColor}; color: ${widgetConfig.header.textColor}; direction: ${widgetConfig.direction || 'ltr'};" data-element-type="header">
1813
- <span>${widgetConfig.header.title}</span>
1814
- ${widgetConfig.header.showCloseButton ? '<button class="mock-panel-close" data-element-type="closeButton" onclick="switchView(\'landing\')">×</button>' : ''}
1815
- </div>
1816
2588
  <div class="mock-text-interface" style="direction: ${widgetConfig.direction || 'ltr'};">
1817
- <div class="mock-messages">
2589
+ <div class="mock-messages" style="background: #f8fafc;">
1818
2590
  <div class="mock-message user" data-element-type="userMessage">
1819
2591
  <div class="mock-message-avatar">${widgetConfig.messages.userAvatarIcon || '👤'}</div>
1820
2592
  <div class="mock-message-bubble" style="background: ${widgetConfig.messages.userBackgroundColor}; color: ${widgetConfig.messages.userTextColor || widgetConfig.messages.textColor || '#1F2937'}; border-radius: ${widgetConfig.messages.borderRadius}px; font-size: ${widgetConfig.messages.fontSize};">
@@ -1839,6 +2611,9 @@
1839
2611
  <button class="mock-send-button" style="background: ${config.sendButtonColor};" data-element-type="sendButton">${config.sendButtonText || '→'}</button>
1840
2612
  </div>
1841
2613
  </div>
2614
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${textFooterBorder}; background: transparent; flex-shrink: 0;">
2615
+ <span style="font-size: 10px; color: ${textFooterColor};">Powered by <a href="#" style="color: ${textFooterLink}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2616
+ </div>
1842
2617
  `;
1843
2618
 
1844
2619
  // Make elements selectable
@@ -1847,22 +2622,38 @@
1847
2622
 
1848
2623
  function renderVoiceInterface(panel) {
1849
2624
  const config = widgetConfig.voice;
1850
- // Show active call state matching real widget structure
2625
+ const callBg1 = config.heroGradient1 || '#2a2550';
2626
+ const callBg2 = config.heroGradient2 || '#1a1a2e';
2627
+ const waveColor = config.waveformBarColor || config.primaryBtnGradient1 || '#7C3AED';
2628
+ const timerTextColor = config.headlineColor || '#fff';
2629
+ const statusTextColor = config.sublineColor || 'rgba(255,255,255,0.7)';
2630
+ const panelBg = widgetConfig.panel?.backgroundColor || '#16161e';
2631
+ const light = isLightBackground(panelBg);
2632
+ const sectionBorder = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.08)';
2633
+ const convHeaderColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.4)';
2634
+ const bubbleBg = light ? '#f3f4f6' : 'rgba(255,255,255,0.08)';
2635
+ const bubbleColor = light ? '#1f2937' : 'rgba(255,255,255,0.85)';
2636
+ const inputBg = light ? '#f3f4f6' : 'rgba(255,255,255,0.06)';
2637
+ const inputBorder = light ? 'rgba(0,0,0,0.1)' : 'rgba(255,255,255,0.1)';
2638
+ const inputColor = light ? '#111827' : '#fff';
2639
+ const footerBorder = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2640
+ const footerTextColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2641
+ const footerAccent = light ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
1851
2642
  panel.innerHTML = `
1852
- <div class="mock-panel-header" style="background: ${widgetConfig.header.backgroundColor}; color: ${widgetConfig.header.textColor}; direction: ${widgetConfig.direction || 'ltr'};" data-element-type="header">
1853
- <div style="display: flex; align-items: center; gap: 8px;">
1854
- <span>${widgetConfig.header.title}</span>
1855
- <div style="display: flex; align-items: center; gap: 6px; margin-left: 8px;" data-element-type="onlineIndicator">
1856
- <div style="width: 6px; height: 6px; background: ${widgetConfig.header.onlineIndicatorDotColor || '#10b981'}; border-radius: 50%;"></div>
1857
- <span style="font-size: 12px; opacity: 0.9; color: ${widgetConfig.header.onlineIndicatorColor || widgetConfig.header.textColor};">${widgetConfig.header.onlineIndicatorText || 'Online'}</span>
1858
- </div>
1859
- </div>
1860
- <div style="display: flex; align-items: center; gap: 8px;">
1861
- <button style="background: none; border: none; color: ${widgetConfig.header.textColor}; cursor: pointer; padding: 4px; display: flex; align-items: center;" data-element-type="backButton">←</button>
1862
- ${widgetConfig.header.showCloseButton ? '<button class="mock-panel-close" data-element-type="closeButton">×</button>' : ''}
1863
- </div>
1864
- </div>
1865
- <div class="mock-voice-interface" style="direction: ${widgetConfig.direction || 'ltr'};">
2643
+ <style>
2644
+ .mock-voice-interface .mock-waveform-bar,
2645
+ .mock-compact-waveform .mock-waveform-bar { background: ${waveColor} !important; }
2646
+ .mock-voice-interface .mock-voice-section { border-bottom-color: ${sectionBorder}; }
2647
+ .mock-voice-interface .mock-voice-section-compact { border-bottom-color: ${sectionBorder}; }
2648
+ .mock-voice-interface .mock-conversation-section { background: ${panelBg}; }
2649
+ .mock-voice-interface .mock-conversation-header { color: ${convHeaderColor}; }
2650
+ .mock-voice-interface .mock-conversation-toggle { color: ${convHeaderColor}; }
2651
+ .mock-voice-interface .mock-history-bubble { background: ${bubbleBg}; color: ${bubbleColor}; }
2652
+ .mock-voice-interface .mock-voice-text-input { background: ${inputBg} !important; border-color: ${inputBorder} !important; color: ${inputColor} !important; }
2653
+ .mock-voice-interface .mock-voice-input-area { border-top-color: ${sectionBorder}; background: ${panelBg}; }
2654
+ .mock-voice-interface .mock-voice-send-btn { background: ${waveColor} !important; }
2655
+ </style>
2656
+ <div class="mock-voice-interface" style="direction: ${widgetConfig.direction || 'ltr'}; background: linear-gradient(160deg, ${callBg1} 0%, ${callBg2} 100%); color: ${timerTextColor};">
1866
2657
  <!-- Voice Section -->
1867
2658
  <!-- Multi-row layout when history is collapsed -->
1868
2659
  <div class="mock-voice-section" id="mockVoiceSectionExpanded">
@@ -2083,9 +2874,8 @@
2083
2874
  </div>
2084
2875
 
2085
2876
  <!-- Powered By -->
2086
- <div class="mock-powered-by">
2087
- <span>⚡</span>
2088
- <span>Powered by <strong>TalkToPC</strong></span>
2877
+ <div class="mock-powered-by" style="color: ${footerTextColor}; border-top: 1px solid ${footerBorder};">
2878
+ <span>Powered by <a href="#" style="color: ${footerAccent}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2089
2879
  </div>
2090
2880
  </div>
2091
2881
  `;
@@ -2252,8 +3042,11 @@
2252
3042
 
2253
3043
  function performNormalInteraction(elementType, element, event) {
2254
3044
  if (elementType === 'closeButton' || elementType === 'endCallButton' || elementType === 'backButton') {
2255
- // End call or close should go back to landing screen
2256
- switchView('landing');
3045
+ switchView('voiceIdle');
3046
+ } else if (elementType === 'startCallButton' || elementType === 'heroPrimaryBtn') {
3047
+ switchView('voice');
3048
+ } else if (elementType === 'sendMessageButton' || elementType === 'heroSecondaryBtn') {
3049
+ switchView('text');
2257
3050
  } else if (elementType === 'modeCard') {
2258
3051
  const mode = element.getAttribute('data-mode');
2259
3052
  if (mode === 'voice') {
@@ -2354,31 +3147,14 @@
2354
3147
  case 'button':
2355
3148
  controlsHTML = `
2356
3149
  <div class="customization-group">
2357
- <h3>Floating Button</h3>
2358
- <div class="control-item">
2359
- <label>Size</label>
2360
- <select id="btnSize">
2361
- <option value="small">Small</option>
2362
- <option value="medium" selected>Medium</option>
2363
- <option value="large">Large</option>
2364
- <option value="xl">Extra Large</option>
2365
- </select>
2366
- </div>
2367
- <div class="control-item">
2368
- <label>Shape</label>
2369
- <select id="btnShape">
2370
- <option value="circle" selected>Circle</option>
2371
- <option value="rounded">Rounded</option>
2372
- <option value="square">Square</option>
2373
- </select>
2374
- </div>
3150
+ <h3>Pill Launcher</h3>
2375
3151
  <div class="control-item">
2376
- <label>Background Color</label>
2377
- <input type="color" id="btnBgColor" value="${widgetConfig.button.backgroundColor}">
3152
+ <label>Title</label>
3153
+ <input type="text" id="pillTitle" value="${widgetConfig.header.title || 'Chat Assistant'}" placeholder="Chat Assistant">
2378
3154
  </div>
2379
3155
  <div class="control-item">
2380
- <label>Hover Color</label>
2381
- <input type="color" id="btnHoverColor" value="${widgetConfig.button.hoverColor}">
3156
+ <label>Online Status Text</label>
3157
+ <input type="text" id="pillStatusText" value="${widgetConfig.header.onlineIndicatorText || 'Online'}" placeholder="Online">
2382
3158
  </div>
2383
3159
  </div>
2384
3160
  <div class="customization-group">
@@ -2396,7 +3172,7 @@
2396
3172
  <div class="control-item" id="promptBgColorControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2397
3173
  <label>Background Color/Gradient</label>
2398
3174
  <input type="text" id="promptBgColor" value="${widgetConfig.promptAnimation?.backgroundColor || 'linear-gradient(135deg, #7c3aed, #4f46e5)'}" placeholder="linear-gradient(135deg, #7c3aed, #4f46e5)">
2399
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">Supports solid colors (e.g., #7c3aed) or gradients</p>
3175
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Supports solid colors (e.g., #7c3aed) or gradients</p>
2400
3176
  </div>
2401
3177
  <div class="control-item" id="promptTextColorControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2402
3178
  <label>Text Color</label>
@@ -2413,7 +3189,7 @@
2413
3189
  <div class="control-item" id="promptHideAfterSecondsControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2414
3190
  <label>Auto-Hide After (seconds)</label>
2415
3191
  <input type="number" id="promptHideAfterSeconds" value="${widgetConfig.promptAnimation?.hideAfterSeconds || ''}" placeholder="Leave empty for never" min="0" step="1">
2416
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">Leave empty to never auto-hide</p>
3192
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Leave empty to never auto-hide</p>
2417
3193
  </div>
2418
3194
  <div class="control-item" id="promptPositionControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2419
3195
  <label>Position</label>
@@ -2437,7 +3213,7 @@
2437
3213
  </div>
2438
3214
  <div class="control-item" id="iconCustomImageControl" style="display: ${widgetConfig.icon.type === 'custom' ? 'block' : 'none'};">
2439
3215
  <label>Image URL</label>
2440
- <input type="text" id="iconCustomImage" value="${widgetConfig.icon.customImage || 'https://talktopc.com/logo192.png'}" placeholder="https://talktopc.com/logo192.png">
3216
+ <input type="text" id="iconCustomImage" value="${widgetConfig.icon.customImage || ''}" placeholder="Optional image URL — leave empty for waveform">
2441
3217
  </div>
2442
3218
  <div class="control-item" id="iconEmojiControl" style="display: ${widgetConfig.icon.type === 'emoji' ? 'block' : 'none'};">
2443
3219
  <label>Emoji</label>
@@ -2454,39 +3230,19 @@
2454
3230
  case 'header':
2455
3231
  controlsHTML = `
2456
3232
  <div class="customization-group">
2457
- <h3>Header</h3>
3233
+ <h3>Widget Identity</h3>
3234
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Controls the title and status shown in the pill launcher.</p>
2458
3235
  <div class="control-item">
2459
3236
  <label>Title Text</label>
2460
3237
  <input type="text" id="headerTitle" value="${widgetConfig.header.title}" placeholder="Chat Assistant">
2461
3238
  </div>
2462
3239
  <div class="control-item">
2463
- <label>Background Color</label>
2464
- <input type="color" id="headerBgColor" value="${widgetConfig.header.backgroundColor}">
2465
- </div>
2466
- <div class="control-item">
2467
- <label>Text Color</label>
2468
- <input type="color" id="headerTextColor" value="${widgetConfig.header.textColor}">
3240
+ <label>Online Status Text</label>
3241
+ <input type="text" id="onlineIndicatorText" value="${widgetConfig.header.onlineIndicatorText || 'Online'}" placeholder="Online">
2469
3242
  </div>
2470
3243
  <div class="control-item">
2471
- <label>
2472
- <input type="checkbox" id="headerShowClose" ${widgetConfig.header.showCloseButton ? 'checked' : ''}>
2473
- Show Close Button
2474
- </label>
2475
- </div>
2476
- <div class="control-item" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #374151;">
2477
- <label style="font-weight: 600; color: #f9fafb; margin-bottom: 8px; display: block;">Online Indicator</label>
2478
- <div class="control-item">
2479
- <label>Indicator Text</label>
2480
- <input type="text" id="onlineIndicatorText" value="${widgetConfig.header.onlineIndicatorText || 'Online'}" placeholder="Online">
2481
- </div>
2482
- <div class="control-item">
2483
- <label>Indicator Text Color</label>
2484
- <input type="color" id="onlineIndicatorColor" value="${widgetConfig.header.onlineIndicatorColor || widgetConfig.header.textColor}">
2485
- </div>
2486
- <div class="control-item">
2487
- <label>Indicator Dot Color</label>
2488
- <input type="color" id="onlineIndicatorDotColor" value="${widgetConfig.header.onlineIndicatorDotColor || '#10b981'}">
2489
- </div>
3244
+ <label>Online Dot Color</label>
3245
+ <input type="color" id="onlineIndicatorDotColor" value="${widgetConfig.header.onlineIndicatorDotColor || '#10b981'}">
2490
3246
  </div>
2491
3247
  </div>
2492
3248
  `;
@@ -2532,7 +3288,7 @@
2532
3288
  <label>Offset Y (px)</label>
2533
3289
  <input type="number" id="positionOffsetY" value="${widgetConfig.position.offset.y}">
2534
3290
  </div>
2535
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3291
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2536
3292
  Position of the floating button and widget on the page.
2537
3293
  </p>
2538
3294
  </div>
@@ -2545,7 +3301,7 @@
2545
3301
  <option value="rtl" ${widgetConfig.direction === 'rtl' ? 'selected' : ''}>Right to Left (RTL)</option>
2546
3302
  </select>
2547
3303
  </div>
2548
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3304
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2549
3305
  Text direction for the widget. Use RTL for languages like Arabic or Hebrew.
2550
3306
  </p>
2551
3307
  </div>
@@ -2577,7 +3333,7 @@
2577
3333
  <label>Offset Y (px)</label>
2578
3334
  <input type="number" id="positionOffsetY" value="${widgetConfig.position.offset.y}">
2579
3335
  </div>
2580
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3336
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2581
3337
  Position of the floating button and widget on the page.
2582
3338
  </p>
2583
3339
  </div>
@@ -2594,7 +3350,7 @@
2594
3350
  <option value="rtl" ${widgetConfig.direction === 'rtl' ? 'selected' : ''}>Right to Left (RTL)</option>
2595
3351
  </select>
2596
3352
  </div>
2597
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3353
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2598
3354
  Text direction for the widget. Use RTL for languages like Arabic or Hebrew.
2599
3355
  </p>
2600
3356
  </div>
@@ -2621,17 +3377,17 @@
2621
3377
  <label>Agent Message Text Color</label>
2622
3378
  <input type="color" id="msgAgentTextColor" value="${widgetConfig.messages.agentTextColor || widgetConfig.messages.textColor || '#1F2937'}">
2623
3379
  </div>
2624
- <div class="control-item" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #374151;">
2625
- <label style="font-weight: 600; color: #f9fafb; margin-bottom: 8px; display: block;">Message Avatars</label>
3380
+ <div class="control-item" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(255,255,255,0.08);">
3381
+ <label style="font-weight: 600; color: #e2e8f0; margin-bottom: 8px; display: block;">Message Avatars</label>
2626
3382
  <div class="control-item">
2627
3383
  <label>User Avatar Icon</label>
2628
3384
  <input type="text" id="msgUserAvatarIcon" value="${widgetConfig.messages.userAvatarIcon || '👤'}" placeholder="👤">
2629
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">Emoji or text to display next to user messages</p>
3385
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Emoji or text to display next to user messages</p>
2630
3386
  </div>
2631
3387
  <div class="control-item">
2632
3388
  <label>Agent Avatar Icon</label>
2633
3389
  <input type="text" id="msgAgentAvatarIcon" value="${widgetConfig.messages.agentAvatarIcon || '🤖'}" placeholder="🤖">
2634
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">Emoji or text to display next to agent messages</p>
3390
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Emoji or text to display next to agent messages</p>
2635
3391
  </div>
2636
3392
  </div>
2637
3393
  <div class="control-item">
@@ -2642,7 +3398,7 @@
2642
3398
  <label>Border Radius (px)</label>
2643
3399
  <input type="number" id="msgRadius" value="${widgetConfig.messages.borderRadius}">
2644
3400
  </div>
2645
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3401
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2646
3402
  Note: Message text content is controlled by your agent, not the widget configuration.
2647
3403
  </p>
2648
3404
  </div>
@@ -2804,7 +3560,7 @@
2804
3560
  <label>Font Size</label>
2805
3561
  <input type="text" id="liveTranscriptFontSize" value="${widgetConfig.voice.liveTranscriptFontSize || '14px'}" placeholder="14px">
2806
3562
  </div>
2807
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3563
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2808
3564
  This is the live transcript shown when history is collapsed. It displays only the current spoken text (max 2 lines).
2809
3565
  </p>
2810
3566
  </div>
@@ -2841,167 +3597,165 @@
2841
3597
  controlsHTML = `
2842
3598
  <div class="customization-group">
2843
3599
  <h3>Conversation History</h3>
2844
- <p style="color: #6b7280; font-size: 14px; margin-top: 8px;">
3600
+ <p style="color: #64748b; font-size: 14px; margin-top: 8px;">
2845
3601
  This is the expanded conversation history view showing all messages.
2846
3602
  </p>
2847
3603
  </div>
2848
3604
  `;
2849
3605
  break;
2850
- case 'agentAvatar':
3606
+ case 'heroAvatar':
2851
3607
  controlsHTML = `
2852
3608
  <div class="customization-group">
2853
- <h3>Agent Avatar (Next to Messages)</h3>
3609
+ <h3>Hero Avatar</h3>
3610
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The avatar circle in the hero header. Shows the first letter of the agent name.</p>
2854
3611
  <div class="control-item">
2855
- <label>Display Type</label>
2856
- <select id="agentAvatarType">
2857
- <option value="icon" ${widgetConfig.voice.avatarType === 'icon' || !widgetConfig.voice.avatarType ? 'selected' : ''}>Icon</option>
2858
- <option value="image" ${widgetConfig.voice.avatarType === 'image' ? 'selected' : ''}>Image URL</option>
2859
- </select>
2860
- </div>
2861
- <div class="control-item" id="agentAvatarIconControl" style="display: ${widgetConfig.voice.avatarType === 'image' ? 'none' : 'block'};">
2862
- <label>Icon (Emoji or Text)</label>
2863
- <input type="text" id="agentAvatarIcon" value="${widgetConfig.voice.avatarIcon || '🤖'}" placeholder="🤖">
3612
+ <label>Gradient Start Color</label>
3613
+ <input type="color" id="heroAvatarGrad1" value="${widgetConfig.voice?.avatarGradient1 || '#6d56f5'}">
2864
3614
  </div>
2865
- <div class="control-item" id="agentAvatarImageControl" style="display: ${widgetConfig.voice.avatarType === 'image' ? 'block' : 'none'};">
2866
- <label>Image URL</label>
2867
- <input type="text" id="agentAvatarImageUrl" value="${widgetConfig.voice.avatarImageUrl || ''}" placeholder="https://example.com/avatar.png">
3615
+ <div class="control-item">
3616
+ <label>Gradient End Color</label>
3617
+ <input type="color" id="heroAvatarGrad2" value="${widgetConfig.voice?.avatarGradient2 || '#a78bfa'}">
2868
3618
  </div>
2869
3619
  <div class="control-item">
2870
- <label>Background Color</label>
2871
- <input type="color" id="agentAvatarBg" value="${widgetConfig.voice.avatarBackgroundColor}">
3620
+ <label>Online Dot Color</label>
3621
+ <input type="color" id="heroOnlineDotColor" value="${widgetConfig.voice?.onlineDotColor || '#22c55e'}">
2872
3622
  </div>
2873
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
2874
- This icon appears next to agent messages in the conversation history.
2875
- </p>
2876
3623
  </div>
2877
3624
  `;
2878
3625
  break;
2879
- case 'liveIndicator':
3626
+ case 'heroAgentName':
2880
3627
  controlsHTML = `
2881
3628
  <div class="customization-group">
2882
- <h3>Live Indicator</h3>
3629
+ <h3>Agent Name</h3>
3630
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The agent name shown in the hero header.</p>
2883
3631
  <div class="control-item">
2884
- <label>Live Dot Color</label>
2885
- <input type="color" id="liveDotColor" value="${widgetConfig.voice.liveIndicatorDotColor || '#10b981'}">
3632
+ <label>Name Text</label>
3633
+ <input type="text" id="heroAgentNameText" value="${widgetConfig.agentName || 'Sasha'}" placeholder="Sasha">
2886
3634
  </div>
2887
3635
  <div class="control-item">
2888
- <label>Live Text Color</label>
2889
- <input type="color" id="liveTextColor" value="${widgetConfig.voice.liveIndicatorTextColor || '#10b981'}">
3636
+ <label>Text Color</label>
3637
+ <input type="color" id="heroAgentNameColor" value="${widgetConfig.voice?.agentNameColor || '#f0eff8'}">
2890
3638
  </div>
2891
3639
  </div>
2892
3640
  `;
2893
3641
  break;
2894
- case 'landingLogo':
3642
+ case 'heroAgentRole':
2895
3643
  controlsHTML = `
2896
3644
  <div class="customization-group">
2897
- <h3>Landing Screen - Logo</h3>
3645
+ <h3>Agent Role</h3>
3646
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The subtitle under the agent name.</p>
2898
3647
  <div class="control-item">
2899
- <label>Display Type</label>
2900
- <select id="logoType">
2901
- <option value="icon" ${widgetConfig.landing.logoType === 'icon' || !widgetConfig.landing.logoType ? 'selected' : ''}>Icon</option>
2902
- <option value="image" ${widgetConfig.landing.logoType === 'image' ? 'selected' : ''}>Image URL</option>
2903
- </select>
3648
+ <label>Role Text</label>
3649
+ <input type="text" id="heroAgentRoleText" value="${widgetConfig.voice?.agentRole || 'AI Voice Assistant'}" placeholder="AI Voice Assistant">
2904
3650
  </div>
2905
- <div class="control-item" id="logoIconControl" style="display: ${widgetConfig.landing.logoType === 'image' ? 'none' : 'block'};">
2906
- <label>Icon (Emoji or Text)</label>
2907
- <input type="text" id="landingLogoIcon" value="${widgetConfig.landing.logoIcon || widgetConfig.landing.logo || '🤖'}" placeholder="🤖">
3651
+ <div class="control-item">
3652
+ <label>Text Color</label>
3653
+ <input type="color" id="heroAgentRoleColor" value="${widgetConfig.voice?.agentRoleColor || '#594d80'}">
3654
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white.</p>
2908
3655
  </div>
2909
- <div class="control-item" id="logoImageControl" style="display: ${widgetConfig.landing.logoType === 'image' ? 'block' : 'none'};">
2910
- <label>Image URL</label>
2911
- <input type="text" id="landingLogoImageUrl" value="${widgetConfig.landing.logoImageUrl || ''}" placeholder="https://example.com/logo.png">
3656
+ </div>
3657
+ `;
3658
+ break;
3659
+ case 'heroHeadline':
3660
+ controlsHTML = `
3661
+ <div class="customization-group">
3662
+ <h3>Hero Headline</h3>
3663
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The main greeting text in the hero.</p>
3664
+ <div class="control-item">
3665
+ <label>Headline Text</label>
3666
+ <input type="text" id="heroHeadlineText" value="${widgetConfig.voice?.headline || 'Hi there 👋'}" placeholder="Hi there 👋">
2912
3667
  </div>
2913
- <div class="control-item" id="logoBackgroundControl" style="display: ${widgetConfig.landing.logoType === 'image' ? 'block' : 'none'}; margin-top: 16px; padding-top: 16px; border-top: 1px solid #374151;">
2914
- <label style="font-weight: 600; color: #f9fafb; margin-bottom: 8px; display: block;">Background</label>
2915
- <div class="control-item">
2916
- <label>
2917
- <input type="checkbox" id="logoBackgroundEnabled" ${widgetConfig.landing.logoBackgroundEnabled !== false ? 'checked' : ''}>
2918
- Enable Background
2919
- </label>
2920
- </div>
2921
- <div class="control-item" id="logoBackgroundColorControl" style="display: ${widgetConfig.landing.logoBackgroundEnabled !== false ? 'block' : 'none'};">
2922
- <label>Background Color</label>
2923
- <input type="color" id="logoBackgroundColor" value="${widgetConfig.landing.logoBackgroundColor && widgetConfig.landing.logoBackgroundColor.startsWith('#') ? widgetConfig.landing.logoBackgroundColor : '#667eea'}">
2924
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">
2925
- Background color for the logo container. Uncheck "Enable Background" to make it transparent.
2926
- </p>
2927
- </div>
3668
+ <div class="control-item">
3669
+ <label>Text Color</label>
3670
+ <input type="color" id="heroHeadlineColor" value="${widgetConfig.voice?.headlineColor || '#ffffff'}">
2928
3671
  </div>
2929
3672
  </div>
2930
3673
  `;
2931
3674
  break;
2932
- case 'landingTitle':
3675
+ case 'heroSubline':
2933
3676
  controlsHTML = `
2934
3677
  <div class="customization-group">
2935
- <h3>Landing Screen - Title</h3>
3678
+ <h3>Hero Subline</h3>
3679
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The description text below the headline.</p>
2936
3680
  <div class="control-item">
2937
- <label>Title Text</label>
2938
- <input type="text" id="landingTitleText" value="${widgetConfig.landing.title || 'Welcome to AI Assistant'}" placeholder="Welcome to AI Assistant">
3681
+ <label>Subline Text</label>
3682
+ <input type="text" id="heroSublineText" value="${(widgetConfig.voice?.subline || 'Ask me anything — I respond instantly in voice or text.').replace(/<br>/g, ' ')}" placeholder="Ask me anything...">
2939
3683
  </div>
2940
3684
  <div class="control-item">
2941
- <label>Title Color</label>
2942
- <input type="color" id="landingTitleColor" value="${widgetConfig.landing.titleColor}">
3685
+ <label>Text Color</label>
3686
+ <input type="color" id="heroSublineColor" value="${widgetConfig.voice?.sublineColor || '#736b8a'}">
3687
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white.</p>
2943
3688
  </div>
2944
3689
  </div>
2945
3690
  `;
2946
3691
  break;
2947
- case 'landingSubtitle':
3692
+ case 'heroBackground':
2948
3693
  controlsHTML = `
2949
3694
  <div class="customization-group">
2950
- <h3>Landing Screen - Subtitle</h3>
3695
+ <h3>Hero Background</h3>
3696
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The gradient background of the hero section.</p>
2951
3697
  <div class="control-item">
2952
- <label>Subtitle Text</label>
2953
- <input type="text" id="landingSubtitleText" value="${widgetConfig.landing.subtitle || 'Choose how you\'d like to interact'}" placeholder="Choose how you'd like to interact">
3698
+ <label>Gradient Start Color</label>
3699
+ <input type="color" id="heroBgGrad1" value="${widgetConfig.voice?.heroGradient1 || '#2a2550'}">
2954
3700
  </div>
2955
3701
  <div class="control-item">
2956
- <label>Subtitle Color</label>
2957
- <input type="color" id="landingSubtitleColor" value="${widgetConfig.landing.subtitleColor}">
3702
+ <label>Gradient End Color</label>
3703
+ <input type="color" id="heroBgGrad2" value="${widgetConfig.voice?.heroGradient2 || '#1a1a2e'}">
2958
3704
  </div>
2959
3705
  </div>
2960
3706
  `;
2961
3707
  break;
2962
- case 'landingBackground':
2963
- // Extract color from gradient or use default
2964
- const currentBg = widgetConfig.landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)';
2965
- let defaultColor = '#ffffff';
2966
- if (currentBg.startsWith('#')) {
2967
- defaultColor = currentBg;
2968
- } else if (currentBg.includes('#')) {
2969
- // Extract the first hex color from gradient (usually the main color)
2970
- const hexMatch = currentBg.match(/#[0-9a-fA-F]{6}/);
2971
- if (hexMatch) defaultColor = hexMatch[0];
2972
- }
3708
+ case 'heroPrimaryBtn':
2973
3709
  controlsHTML = `
2974
3710
  <div class="customization-group">
2975
- <h3>Landing Screen - Background</h3>
3711
+ <h3>Start Voice Call Button</h3>
3712
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Primary action button in the hero.</p>
2976
3713
  <div class="control-item">
2977
- <label>Background Color</label>
2978
- <input type="color" id="landingBgColor" value="${defaultColor}">
2979
- <p style="color: #6b7280; font-size: 11px; margin-top: 4px;">
2980
- Pick a solid color for the background. Default uses a subtle gradient.
2981
- </p>
3714
+ <label>Button Text</label>
3715
+ <input type="text" id="heroPrimaryBtnText" value="${widgetConfig.voice?.startCallButtonText || 'Start Voice Call'}" placeholder="Start Voice Call">
3716
+ </div>
3717
+ <div class="control-item">
3718
+ <label>Gradient Start Color</label>
3719
+ <input type="color" id="heroPrimaryBtnGrad1" value="${widgetConfig.voice?.primaryBtnGradient1 || '#6d56f5'}">
3720
+ </div>
3721
+ <div class="control-item">
3722
+ <label>Gradient End Color</label>
3723
+ <input type="color" id="heroPrimaryBtnGrad2" value="${widgetConfig.voice?.primaryBtnGradient2 || '#9d8df8'}">
3724
+ </div>
3725
+ <div class="control-item">
3726
+ <label>Text Color</label>
3727
+ <input type="color" id="heroPrimaryBtnTextColor" value="${widgetConfig.voice?.startCallButtonTextColor || '#ffffff'}">
2982
3728
  </div>
2983
3729
  </div>
2984
3730
  `;
2985
3731
  break;
2986
- case 'modeCard':
3732
+ case 'heroSecondaryBtn':
2987
3733
  controlsHTML = `
2988
3734
  <div class="customization-group">
2989
- <h3>Mode Cards (Voice/Text Buttons)</h3>
3735
+ <h3>Send a Message Button</h3>
3736
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Secondary action button in the hero.</p>
2990
3737
  <div class="control-item">
2991
- <label>Voice Card Title</label>
2992
- <input type="text" id="voiceCardTitle" value="Voice Call" placeholder="Voice Call">
3738
+ <label>Button Text</label>
3739
+ <input type="text" id="heroSecondaryBtnText" value="${widgetConfig.voice?.sendMessageText || 'Send a Message'}" placeholder="Send a Message">
2993
3740
  </div>
2994
3741
  <div class="control-item">
2995
- <label>Text Card Title</label>
2996
- <input type="text" id="textCardTitle" value="Text Chat" placeholder="Text Chat">
3742
+ <label>Background Color</label>
3743
+ <input type="color" id="heroSecondaryBtnBg" value="${widgetConfig.voice?.secondaryBtnBg || '#1a1a2e'}">
3744
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white overlay.</p>
2997
3745
  </div>
2998
3746
  <div class="control-item">
2999
- <label>Background Color</label>
3000
- <input type="color" id="modeCardBg" value="${widgetConfig.landing.modeCardBackgroundColor}">
3747
+ <label>Text Color</label>
3748
+ <input type="color" id="heroSecondaryBtnTextColor" value="${widgetConfig.voice?.secondaryBtnTextColor || '#9994ad'}">
3749
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is muted white.</p>
3001
3750
  </div>
3002
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3003
- These are the buttons on the landing screen that let users choose between voice and text chat.
3004
- </p>
3751
+ </div>
3752
+ `;
3753
+ break;
3754
+ case 'closeButton':
3755
+ controlsHTML = `
3756
+ <div class="customization-group">
3757
+ <h3>Close Button</h3>
3758
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Closes the widget panel. Double-click to test the interaction.</p>
3005
3759
  </div>
3006
3760
  `;
3007
3761
  break;
@@ -3009,12 +3763,9 @@
3009
3763
  controlsHTML = `
3010
3764
  <div class="customization-group">
3011
3765
  <h3>Select an Element</h3>
3012
- <p style="color: #6b7280; font-size: 14px; margin-top: 8px;">
3766
+ <p style="color: #64748b; font-size: 13px; margin-top: 8px;">
3013
3767
  Click on any widget element in the preview to start customizing.
3014
3768
  </p>
3015
- <p style="color: #6b7280; font-size: 13px; margin-top: 12px;">
3016
- 💡 <strong>Tip:</strong> Click the ⚙️ settings icon on the widget panel to configure panel size, position, and text direction.
3017
- </p>
3018
3769
  </div>
3019
3770
  `;
3020
3771
  }
@@ -3044,20 +3795,15 @@
3044
3795
  const controlsDiv = document.getElementById('customizationControls');
3045
3796
  if (!controlsDiv) return;
3046
3797
 
3047
- // Button controls
3798
+ // Button controls (Pill Launcher)
3048
3799
  if (elementType === 'button') {
3049
- document.getElementById('btnSize')?.addEventListener('change', (e) => {
3050
- widgetConfig.button.size = e.target.value;
3051
- applyButtonStyles(document.getElementById('mockButton'));
3052
- updateConfigCode();
3053
- });
3054
- document.getElementById('btnShape')?.addEventListener('change', (e) => {
3055
- widgetConfig.button.shape = e.target.value;
3800
+ document.getElementById('pillTitle')?.addEventListener('input', (e) => {
3801
+ widgetConfig.header.title = e.target.value;
3056
3802
  applyButtonStyles(document.getElementById('mockButton'));
3057
3803
  updateConfigCode();
3058
3804
  });
3059
- document.getElementById('btnBgColor')?.addEventListener('input', (e) => {
3060
- widgetConfig.button.backgroundColor = e.target.value;
3805
+ document.getElementById('pillStatusText')?.addEventListener('input', (e) => {
3806
+ widgetConfig.header.onlineIndicatorText = e.target.value;
3061
3807
  applyButtonStyles(document.getElementById('mockButton'));
3062
3808
  updateConfigCode();
3063
3809
  });
@@ -3149,37 +3895,17 @@
3149
3895
  });
3150
3896
  }
3151
3897
 
3152
- // Header controls (also applies to onlineIndicator)
3898
+ // Header / Widget Identity controls
3153
3899
  if (elementType === 'header' || elementType === 'onlineIndicator') {
3154
3900
  document.getElementById('headerTitle')?.addEventListener('input', (e) => {
3155
3901
  widgetConfig.header.title = e.target.value;
3156
- renderPanelContent();
3157
- updateConfigCode();
3158
- });
3159
- document.getElementById('headerBgColor')?.addEventListener('input', (e) => {
3160
- const newColor = e.target.value;
3161
- console.log('🎨 Header color changed to:', newColor);
3162
- widgetConfig.header.backgroundColor = newColor;
3163
- renderPanelContent();
3164
- updateConfigCode();
3165
- });
3166
- document.getElementById('headerTextColor')?.addEventListener('input', (e) => {
3167
- widgetConfig.header.textColor = e.target.value;
3168
- renderPanelContent();
3169
- updateConfigCode();
3170
- });
3171
- document.getElementById('headerShowClose')?.addEventListener('change', (e) => {
3172
- widgetConfig.header.showCloseButton = e.target.checked;
3902
+ applyButtonStyles(document.getElementById('mockButton'));
3173
3903
  renderPanelContent();
3174
3904
  updateConfigCode();
3175
3905
  });
3176
3906
  document.getElementById('onlineIndicatorText')?.addEventListener('input', (e) => {
3177
3907
  widgetConfig.header.onlineIndicatorText = e.target.value;
3178
- renderPanelContent();
3179
- updateConfigCode();
3180
- });
3181
- document.getElementById('onlineIndicatorColor')?.addEventListener('input', (e) => {
3182
- widgetConfig.header.onlineIndicatorColor = e.target.value;
3908
+ applyButtonStyles(document.getElementById('mockButton'));
3183
3909
  renderPanelContent();
3184
3910
  updateConfigCode();
3185
3911
  });
@@ -3354,6 +4080,157 @@
3354
4080
  });
3355
4081
  }
3356
4082
 
4083
+ // Hero Avatar controls
4084
+ if (elementType === 'heroAvatar') {
4085
+ document.getElementById('heroAvatarGrad1')?.addEventListener('input', (e) => {
4086
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4087
+ widgetConfig.voice.avatarGradient1 = e.target.value;
4088
+ renderPanelContent();
4089
+ updateConfigCode();
4090
+ });
4091
+ document.getElementById('heroAvatarGrad2')?.addEventListener('input', (e) => {
4092
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4093
+ widgetConfig.voice.avatarGradient2 = e.target.value;
4094
+ renderPanelContent();
4095
+ updateConfigCode();
4096
+ });
4097
+ document.getElementById('heroOnlineDotColor')?.addEventListener('input', (e) => {
4098
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4099
+ widgetConfig.voice.onlineDotColor = e.target.value;
4100
+ renderPanelContent();
4101
+ updateConfigCode();
4102
+ });
4103
+ }
4104
+
4105
+ // Hero Agent Name controls
4106
+ if (elementType === 'heroAgentName') {
4107
+ document.getElementById('heroAgentNameText')?.addEventListener('input', (e) => {
4108
+ widgetConfig.agentName = e.target.value;
4109
+ renderPanelContent();
4110
+ updateConfigCode();
4111
+ });
4112
+ document.getElementById('heroAgentNameColor')?.addEventListener('input', (e) => {
4113
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4114
+ widgetConfig.voice.agentNameColor = e.target.value;
4115
+ renderPanelContent();
4116
+ updateConfigCode();
4117
+ });
4118
+ }
4119
+
4120
+ // Hero Agent Role controls
4121
+ if (elementType === 'heroAgentRole') {
4122
+ document.getElementById('heroAgentRoleText')?.addEventListener('input', (e) => {
4123
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4124
+ widgetConfig.voice.agentRole = e.target.value;
4125
+ renderPanelContent();
4126
+ updateConfigCode();
4127
+ });
4128
+ document.getElementById('heroAgentRoleColor')?.addEventListener('input', (e) => {
4129
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4130
+ widgetConfig.voice.agentRoleColor = e.target.value;
4131
+ renderPanelContent();
4132
+ updateConfigCode();
4133
+ });
4134
+ }
4135
+
4136
+ // Hero Headline controls
4137
+ if (elementType === 'heroHeadline') {
4138
+ document.getElementById('heroHeadlineText')?.addEventListener('input', (e) => {
4139
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4140
+ widgetConfig.voice.headline = e.target.value;
4141
+ renderPanelContent();
4142
+ updateConfigCode();
4143
+ });
4144
+ document.getElementById('heroHeadlineColor')?.addEventListener('input', (e) => {
4145
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4146
+ widgetConfig.voice.headlineColor = e.target.value;
4147
+ renderPanelContent();
4148
+ updateConfigCode();
4149
+ });
4150
+ }
4151
+
4152
+ // Hero Subline controls
4153
+ if (elementType === 'heroSubline') {
4154
+ document.getElementById('heroSublineText')?.addEventListener('input', (e) => {
4155
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4156
+ widgetConfig.voice.subline = e.target.value;
4157
+ renderPanelContent();
4158
+ updateConfigCode();
4159
+ });
4160
+ document.getElementById('heroSublineColor')?.addEventListener('input', (e) => {
4161
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4162
+ widgetConfig.voice.sublineColor = e.target.value;
4163
+ renderPanelContent();
4164
+ updateConfigCode();
4165
+ });
4166
+ }
4167
+
4168
+ // Hero Background controls
4169
+ if (elementType === 'heroBackground') {
4170
+ document.getElementById('heroBgGrad1')?.addEventListener('input', (e) => {
4171
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4172
+ widgetConfig.voice.heroGradient1 = e.target.value;
4173
+ renderPanelContent();
4174
+ updateConfigCode();
4175
+ });
4176
+ document.getElementById('heroBgGrad2')?.addEventListener('input', (e) => {
4177
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4178
+ widgetConfig.voice.heroGradient2 = e.target.value;
4179
+ renderPanelContent();
4180
+ updateConfigCode();
4181
+ });
4182
+ }
4183
+
4184
+ // Hero Primary Button (Start Voice Call) controls
4185
+ if (elementType === 'heroPrimaryBtn') {
4186
+ document.getElementById('heroPrimaryBtnText')?.addEventListener('input', (e) => {
4187
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4188
+ widgetConfig.voice.startCallButtonText = e.target.value;
4189
+ renderPanelContent();
4190
+ updateConfigCode();
4191
+ });
4192
+ document.getElementById('heroPrimaryBtnGrad1')?.addEventListener('input', (e) => {
4193
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4194
+ widgetConfig.voice.primaryBtnGradient1 = e.target.value;
4195
+ renderPanelContent();
4196
+ updateConfigCode();
4197
+ });
4198
+ document.getElementById('heroPrimaryBtnGrad2')?.addEventListener('input', (e) => {
4199
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4200
+ widgetConfig.voice.primaryBtnGradient2 = e.target.value;
4201
+ renderPanelContent();
4202
+ updateConfigCode();
4203
+ });
4204
+ document.getElementById('heroPrimaryBtnTextColor')?.addEventListener('input', (e) => {
4205
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4206
+ widgetConfig.voice.startCallButtonTextColor = e.target.value;
4207
+ renderPanelContent();
4208
+ updateConfigCode();
4209
+ });
4210
+ }
4211
+
4212
+ // Hero Secondary Button (Send a Message) controls
4213
+ if (elementType === 'heroSecondaryBtn') {
4214
+ document.getElementById('heroSecondaryBtnText')?.addEventListener('input', (e) => {
4215
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4216
+ widgetConfig.voice.sendMessageText = e.target.value;
4217
+ renderPanelContent();
4218
+ updateConfigCode();
4219
+ });
4220
+ document.getElementById('heroSecondaryBtnBg')?.addEventListener('input', (e) => {
4221
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4222
+ widgetConfig.voice.secondaryBtnBg = e.target.value;
4223
+ renderPanelContent();
4224
+ updateConfigCode();
4225
+ });
4226
+ document.getElementById('heroSecondaryBtnTextColor')?.addEventListener('input', (e) => {
4227
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4228
+ widgetConfig.voice.secondaryBtnTextColor = e.target.value;
4229
+ renderPanelContent();
4230
+ updateConfigCode();
4231
+ });
4232
+ }
4233
+
3357
4234
  // Mic button controls
3358
4235
  if (elementType === 'micButton') {
3359
4236
  document.getElementById('micBtnColor')?.addEventListener('input', (e) => {
@@ -3663,6 +4540,7 @@
3663
4540
 
3664
4541
  // Default configuration values (used to compare and only show changed values)
3665
4542
  const defaultConfig = {
4543
+ agentName: 'Sasha',
3666
4544
  direction: 'ltr',
3667
4545
  button: {
3668
4546
  size: 'medium',
@@ -3674,16 +4552,15 @@
3674
4552
  },
3675
4553
  icon: {
3676
4554
  type: 'custom',
3677
- customImage: 'https://talktopc.com/logo192.png',
3678
4555
  size: 'medium',
3679
4556
  backgroundColor: '#FFFFFF'
3680
4557
  },
3681
4558
  panel: {
3682
- width: 360,
4559
+ width: 340,
3683
4560
  height: 550,
3684
- borderRadius: 24,
3685
- backgroundColor: '#FFFFFF',
3686
- border: '1px solid #E5E7EB'
4561
+ borderRadius: 20,
4562
+ backgroundColor: '#16161e',
4563
+ border: '1px solid rgba(255,255,255,0.08)'
3687
4564
  },
3688
4565
  position: {
3689
4566
  vertical: 'bottom',
@@ -3718,6 +4595,9 @@
3718
4595
  inputFocusColor: '#7C3AED'
3719
4596
  },
3720
4597
  voice: {
4598
+ agentRole: 'AI Voice Assistant',
4599
+ headline: 'Hi there 👋',
4600
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
3721
4601
  micButtonColor: '#7C3AED',
3722
4602
  micButtonActiveColor: '#EF4444',
3723
4603
  speakerButtonColor: '#FFFFFF',
@@ -3726,7 +4606,7 @@
3726
4606
  avatarType: 'icon',
3727
4607
  avatarIcon: '🤖',
3728
4608
  avatarImageUrl: '',
3729
- startCallButtonText: 'Start Call',
4609
+ startCallButtonText: 'Start Voice Call',
3730
4610
  startCallButtonColor: '#667eea',
3731
4611
  startCallButtonTextColor: '#FFFFFF',
3732
4612
  statusTitleColor: '#1e293b',
@@ -3739,7 +4619,26 @@
3739
4619
  liveIndicatorTextColor: '#10b981',
3740
4620
  waveformType: 'waveform',
3741
4621
  waveformIcon: '🎤',
3742
- waveformImageUrl: ''
4622
+ waveformImageUrl: '',
4623
+ waveformBarColor: '#7C3AED',
4624
+ pillGradient: '',
4625
+ pillTextColor: '#ffffff',
4626
+ pillDotColor: '#4ade80',
4627
+ avatarGradient1: '#6d56f5',
4628
+ avatarGradient2: '#a78bfa',
4629
+ onlineDotColor: '#22c55e',
4630
+ heroGradient1: '#2a2550',
4631
+ heroGradient2: '#1a1a2e',
4632
+ agentNameColor: '#f0eff8',
4633
+ agentRoleColor: 'rgba(255,255,255,0.35)',
4634
+ headlineColor: '#ffffff',
4635
+ sublineColor: 'rgba(255,255,255,0.45)',
4636
+ primaryBtnGradient1: '#6d56f5',
4637
+ primaryBtnGradient2: '#9d8df8',
4638
+ secondaryBtnBg: 'rgba(255,255,255,0.05)',
4639
+ secondaryBtnBorder: 'rgba(255,255,255,0.09)',
4640
+ secondaryBtnTextColor: 'rgba(255,255,255,0.6)',
4641
+ sendMessageText: 'Send a Message'
3743
4642
  },
3744
4643
  landing: {
3745
4644
  backgroundColor: 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)',
@@ -4035,6 +4934,9 @@
4035
4934
 
4036
4935
  // Remove widget elements from DOM (multiple possible selectors)
4037
4936
  const selectors = [
4937
+ '#ttp-widget-shadow-host',
4938
+ '#ttp-widget-container',
4939
+ '#ttp-widget-styles',
4038
4940
  '[id^="ttp-chat-widget-button"]',
4039
4941
  '[id^="ttp-chat-widget-panel"]',
4040
4942
  '[id*="ttp-chat"]',
@@ -4164,28 +5066,222 @@
4164
5066
  isInitializing = false;
4165
5067
  }
4166
5068
 
5069
+ const themePresets = {
5070
+ default: {
5071
+ direction: 'ltr',
5072
+ agentName: 'Sasha',
5073
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5074
+ panel: { backgroundColor: '#16161e', border: '1px solid rgba(255,255,255,0.08)' },
5075
+ voice: {
5076
+ pillGradient: '',
5077
+ pillTextColor: '#ffffff',
5078
+ pillDotColor: '#4ade80',
5079
+ avatarGradient1: '#6d56f5', avatarGradient2: '#a78bfa',
5080
+ onlineDotColor: '#22c55e',
5081
+ heroGradient1: '#2a2550', heroGradient2: '#1a1a2e',
5082
+ agentNameColor: '#f0eff8',
5083
+ agentRoleColor: 'rgba(255,255,255,0.35)',
5084
+ headlineColor: '#ffffff',
5085
+ sublineColor: 'rgba(255,255,255,0.45)',
5086
+ primaryBtnGradient1: '#6d56f5', primaryBtnGradient2: '#9d8df8',
5087
+ startCallButtonTextColor: '#FFFFFF',
5088
+ startCallButtonText: 'Start Voice Call',
5089
+ sendMessageText: 'Send a Message',
5090
+ secondaryBtnBg: 'rgba(255,255,255,0.05)',
5091
+ secondaryBtnBorder: 'rgba(255,255,255,0.09)',
5092
+ secondaryBtnTextColor: 'rgba(255,255,255,0.6)',
5093
+ agentRole: 'AI Voice Assistant',
5094
+ headline: 'Hi there 👋',
5095
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5096
+ waveformBarColor: '#7C3AED',
5097
+ micButtonColor: '#7C3AED',
5098
+ speakerButtonColor: '#FFFFFF',
5099
+ endCallButtonColor: '#ef4444'
5100
+ }
5101
+ },
5102
+ light: {
5103
+ direction: 'ltr',
5104
+ agentName: 'Sasha',
5105
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5106
+ panel: { backgroundColor: '#ffffff', border: '1px solid rgba(0,0,0,0.06)' },
5107
+ voice: {
5108
+ // Pill launcher
5109
+ pillGradient: 'linear-gradient(135deg, #7c3aed, #6d28d9)',
5110
+ pillTextColor: '#ffffff',
5111
+ pillDotColor: '#4ade80',
5112
+ // Hero idle screen
5113
+ avatarGradient1: '#7c3aed', avatarGradient2: '#a78bfa',
5114
+ onlineDotColor: '#22c55e',
5115
+ heroGradient1: '#ede9fe', heroGradient2: '#f5f3ff',
5116
+ agentNameColor: '#1e1b4b',
5117
+ agentRoleColor: '#7c7c8a',
5118
+ headlineColor: '#1e1b4b',
5119
+ sublineColor: '#6b7280',
5120
+ primaryBtnGradient1: '#7c3aed', primaryBtnGradient2: '#a78bfa',
5121
+ startCallButtonTextColor: '#ffffff',
5122
+ startCallButtonText: 'Start Voice Call',
5123
+ sendMessageText: 'Send a Message',
5124
+ secondaryBtnBg: '#f5f3ff',
5125
+ secondaryBtnBorder: 'rgba(124,58,237,0.15)',
5126
+ secondaryBtnTextColor: '#6d28d9',
5127
+ agentRole: 'AI Voice Assistant',
5128
+ headline: 'Hi there 👋',
5129
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5130
+ // Voice call view
5131
+ waveformBarColor: '#8b5cf6',
5132
+ micButtonColor: '#f5f3ff',
5133
+ speakerButtonColor: '#f5f3ff',
5134
+ endCallButtonColor: '#ef4444'
5135
+ }
5136
+ },
5137
+ hebrew: {
5138
+ direction: 'rtl',
5139
+ agentName: 'שרה',
5140
+ header: { title: 'עוזרת חכמה', onlineIndicatorText: 'מחוברת' },
5141
+ panel: { backgroundColor: '#0f172a', border: '1px solid rgba(59,130,246,0.12)' },
5142
+ voice: {
5143
+ pillGradient: 'linear-gradient(135deg, #1e3a5f, #1e40af, #0f172a)',
5144
+ pillTextColor: '#ffffff',
5145
+ pillDotColor: '#34d399',
5146
+ avatarGradient1: '#3b82f6', avatarGradient2: '#1d4ed8',
5147
+ onlineDotColor: '#34d399',
5148
+ heroGradient1: '#1a2744', heroGradient2: '#0f172a',
5149
+ agentNameColor: '#e0e7ff',
5150
+ agentRoleColor: 'rgba(191,219,254,0.4)',
5151
+ headlineColor: '#f0f4ff',
5152
+ sublineColor: 'rgba(191,219,254,0.5)',
5153
+ primaryBtnGradient1: '#3b82f6', primaryBtnGradient2: '#1d4ed8',
5154
+ startCallButtonTextColor: '#ffffff',
5155
+ startCallButtonText: 'התחל שיחה קולית',
5156
+ sendMessageText: 'שלח הודעה',
5157
+ secondaryBtnBg: 'rgba(59,130,246,0.08)',
5158
+ secondaryBtnBorder: 'rgba(59,130,246,0.18)',
5159
+ secondaryBtnTextColor: 'rgba(147,197,253,0.7)',
5160
+ agentRole: 'עוזרת קולית חכמה',
5161
+ headline: 'היי, מה שלומך? 👋',
5162
+ subline: 'שאל/י אותי הכל — אני עונה<br>מיידית בקול או בטקסט.',
5163
+ waveformBarColor: '#3b82f6',
5164
+ micButtonColor: 'rgba(255,255,255,0.9)',
5165
+ speakerButtonColor: 'rgba(255,255,255,0.9)',
5166
+ endCallButtonColor: '#ef4444'
5167
+ }
5168
+ },
5169
+ sunset: {
5170
+ direction: 'ltr',
5171
+ agentName: 'Sasha',
5172
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5173
+ panel: { backgroundColor: '#140a1e', border: '1px solid rgba(249,115,22,0.12)' },
5174
+ voice: {
5175
+ // Pill launcher
5176
+ pillGradient: 'linear-gradient(135deg, #9f1239, #7c2d12, #581c87)',
5177
+ pillTextColor: '#ffffff',
5178
+ pillDotColor: '#fb923c',
5179
+ // Hero idle screen
5180
+ avatarGradient1: '#f97316', avatarGradient2: '#ec4899',
5181
+ onlineDotColor: '#f59e0b',
5182
+ heroGradient1: '#4a1942', heroGradient2: '#1a0a2e',
5183
+ agentNameColor: '#fde8d0',
5184
+ agentRoleColor: 'rgba(255,200,160,0.45)',
5185
+ headlineColor: '#fff1e6',
5186
+ sublineColor: 'rgba(255,200,160,0.55)',
5187
+ primaryBtnGradient1: '#f97316', primaryBtnGradient2: '#ec4899',
5188
+ startCallButtonTextColor: '#ffffff',
5189
+ startCallButtonText: 'Start Voice Call',
5190
+ sendMessageText: 'Send a Message',
5191
+ secondaryBtnBg: 'rgba(249,115,22,0.08)',
5192
+ secondaryBtnBorder: 'rgba(249,115,22,0.18)',
5193
+ secondaryBtnTextColor: 'rgba(255,180,130,0.7)',
5194
+ agentRole: 'AI Voice Assistant',
5195
+ headline: 'Hi there 👋',
5196
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5197
+ // Voice call view
5198
+ waveformBarColor: '#f97316',
5199
+ micButtonColor: 'rgba(255,255,255,0.9)',
5200
+ speakerButtonColor: 'rgba(255,255,255,0.9)',
5201
+ endCallButtonColor: '#e11d48'
5202
+ }
5203
+ },
5204
+ sasha: {
5205
+ direction: 'rtl',
5206
+ agentName: 'סשה',
5207
+ header: { title: 'S-Law | ייעוץ משפטי', onlineIndicatorText: 'מקוונת' },
5208
+ panel: { backgroundColor: '#f8f5ef', border: '1px solid rgba(196,162,101,0.18)' },
5209
+ voice: {
5210
+ pillGradient: 'linear-gradient(135deg, #c4a265, #9e7e4f)',
5211
+ pillTextColor: '#ffffff',
5212
+ pillDotColor: '#22c55e',
5213
+ avatarGradient1: '#c4a265', avatarGradient2: '#9e7e4f',
5214
+ onlineDotColor: '#22c55e',
5215
+ heroGradient1: '#f8f5ef', heroGradient2: '#ebe6de',
5216
+ agentNameColor: '#1e293b',
5217
+ agentRoleColor: '#78716c',
5218
+ headlineColor: '#1e293b',
5219
+ sublineColor: '#6b7280',
5220
+ primaryBtnGradient1: '#c4a265', primaryBtnGradient2: '#9e7e4f',
5221
+ startCallButtonTextColor: '#ffffff',
5222
+ startCallButtonText: 'התחל שיחה קולית',
5223
+ sendMessageText: 'שלח הודעה',
5224
+ secondaryBtnBg: 'rgba(196,162,101,0.08)',
5225
+ secondaryBtnBorder: 'rgba(196,162,101,0.2)',
5226
+ secondaryBtnTextColor: '#9e7e4f',
5227
+ agentRole: 'עורכת דין | S-Law',
5228
+ headline: 'שלום, אני סשה 👋',
5229
+ subline: 'אני כאן לעזור בכל שאלה משפטית —<br>דיני עבודה ומשפט מסחרי.',
5230
+ waveformBarColor: '#c4a265',
5231
+ micButtonColor: '#1e293b',
5232
+ speakerButtonColor: '#1e293b',
5233
+ endCallButtonColor: '#ef4444'
5234
+ }
5235
+ }
5236
+ };
5237
+
5238
+ let activeTheme = 'default';
5239
+
5240
+ function applyTheme(themeName) {
5241
+ const theme = themePresets[themeName];
5242
+ if (!theme) return;
5243
+ activeTheme = themeName;
5244
+
5245
+ Object.assign(widgetConfig.panel, theme.panel);
5246
+ Object.assign(widgetConfig.voice, theme.voice);
5247
+ if (theme.direction !== undefined) widgetConfig.direction = theme.direction;
5248
+ if (theme.agentName !== undefined) widgetConfig.agentName = theme.agentName;
5249
+ if (theme.header) Object.assign(widgetConfig.header, theme.header);
5250
+
5251
+ document.querySelectorAll('.theme-card').forEach(c => c.classList.remove('active'));
5252
+ const card = document.querySelector(`.theme-card[data-theme="${themeName}"]`);
5253
+ if (card) card.classList.add('active');
5254
+
5255
+ applyButtonStyles(document.getElementById('mockButton'));
5256
+ renderPanelContent();
5257
+ updateConfigCode();
5258
+
5259
+ const sel = selectedElement;
5260
+ if (sel) showCustomizationControls(sel);
5261
+ }
5262
+
4167
5263
  function resetToDefaults() {
4168
5264
  widgetConfig = {
5265
+ agentName: 'Sasha',
4169
5266
  button: {
4170
5267
  size: 'medium',
4171
5268
  shape: 'circle',
4172
5269
  backgroundColor: '#FFFFFF',
4173
- hoverColor: '#D3D3D3', // SDK default: light gray
5270
+ hoverColor: '#D3D3D3',
4174
5271
  shadow: true,
4175
5272
  shadowColor: 'rgba(0,0,0,0.15)'
4176
5273
  },
4177
5274
  icon: {
4178
5275
  type: 'custom',
4179
- customImage: 'https://talktopc.com/logo192.png',
4180
5276
  size: 'medium',
4181
5277
  backgroundColor: '#FFFFFF'
4182
5278
  },
4183
5279
  panel: {
4184
- width: 360,
4185
- height: 550, // Updated from SDK default 500
4186
- borderRadius: 24,
4187
- backgroundColor: '#FFFFFF',
4188
- border: '1px solid #E5E7EB'
5280
+ width: 340,
5281
+ height: 550,
5282
+ borderRadius: 20,
5283
+ backgroundColor: '#16161e',
5284
+ border: '1px solid rgba(255,255,255,0.08)'
4189
5285
  },
4190
5286
  direction: 'ltr',
4191
5287
  position: {
@@ -4205,7 +5301,7 @@
4205
5301
  messages: {
4206
5302
  userBackgroundColor: '#E5E7EB',
4207
5303
  agentBackgroundColor: '#F3F4F6',
4208
- textColor: '#1F2937', // Fallback for backward compatibility
5304
+ textColor: '#1F2937',
4209
5305
  userTextColor: '#1F2937',
4210
5306
  agentTextColor: '#1F2937',
4211
5307
  userAvatarIcon: '👤',
@@ -4221,6 +5317,9 @@
4221
5317
  inputFocusColor: '#7C3AED'
4222
5318
  },
4223
5319
  voice: {
5320
+ agentRole: 'AI Voice Assistant',
5321
+ headline: 'Hi there 👋',
5322
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
4224
5323
  micButtonColor: '#7C3AED',
4225
5324
  micButtonActiveColor: '#EF4444',
4226
5325
  speakerButtonColor: '#FFFFFF',
@@ -4229,7 +5328,7 @@
4229
5328
  avatarType: 'icon',
4230
5329
  avatarIcon: '🤖',
4231
5330
  avatarImageUrl: '',
4232
- startCallButtonText: 'Start Call',
5331
+ startCallButtonText: 'Start Voice Call',
4233
5332
  startCallButtonColor: '#667eea',
4234
5333
  startCallButtonTextColor: '#FFFFFF',
4235
5334
  statusTitleColor: '#1e293b',
@@ -4242,7 +5341,11 @@
4242
5341
  liveIndicatorTextColor: '#10b981',
4243
5342
  waveformType: 'waveform',
4244
5343
  waveformIcon: '🎤',
4245
- waveformImageUrl: ''
5344
+ waveformImageUrl: '',
5345
+ waveformBarColor: '#7C3AED',
5346
+ pillGradient: '',
5347
+ pillTextColor: '#ffffff',
5348
+ pillDotColor: '#4ade80'
4246
5349
  },
4247
5350
  landing: {
4248
5351
  logo: '🤖',
@@ -4262,6 +5365,11 @@
4262
5365
  }
4263
5366
  };
4264
5367
 
5368
+ activeTheme = 'default';
5369
+ document.querySelectorAll('.theme-card').forEach(c => c.classList.remove('active'));
5370
+ const defCard = document.querySelector('.theme-card[data-theme="default"]');
5371
+ if (defCard) defCard.classList.add('active');
5372
+
4265
5373
  initMockWidget();
4266
5374
  updateMockWidgetPosition();
4267
5375
  updateConfigCode();
@@ -4275,6 +5383,11 @@
4275
5383
  // No edit mode toggle needed - single click = edit, double click = interact
4276
5384
 
4277
5385
  // Initialize
5386
+ document.getElementById('themeDefault').addEventListener('click', () => applyTheme('default'));
5387
+ document.getElementById('themeLight').addEventListener('click', () => applyTheme('light'));
5388
+ document.getElementById('themeSunset').addEventListener('click', () => applyTheme('sunset'));
5389
+ document.getElementById('themeHebrew').addEventListener('click', () => applyTheme('hebrew'));
5390
+ document.getElementById('themeSasha').addEventListener('click', () => applyTheme('sasha'));
4278
5391
  document.getElementById('resetBtn').addEventListener('click', resetToDefaults);
4279
5392
  document.getElementById('togglePanelBtn').addEventListener('click', () => {
4280
5393
  panelOpen = !panelOpen;