ttp-agent-sdk 2.38.4 → 2.40.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,289 @@
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;
418
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;
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;
746
+ }
747
+
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);
419
763
  }
420
764
 
421
- /* Mock widget styles - will be dynamically generated */
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
+ .mock-pill-text {
820
+ display: flex;
821
+ flex-direction: column;
822
+ gap: 1px;
823
+ }
824
+
825
+ .mock-pill-title {
826
+ font-size: 13px;
827
+ font-weight: 600;
828
+ color: #fff;
829
+ line-height: 1.2;
830
+ }
831
+
832
+ .mock-pill-status {
833
+ display: flex;
834
+ align-items: center;
835
+ gap: 5px;
836
+ font-size: 11px;
837
+ color: rgba(255,255,255,0.55);
838
+ line-height: 1.2;
839
+ }
840
+
841
+ .mock-pill-dot {
842
+ width: 7px;
843
+ height: 7px;
844
+ border-radius: 50%;
845
+ background: #4ade80;
846
+ flex-shrink: 0;
847
+ animation: mock-dot-pulse 2s ease-in-out infinite;
848
+ }
849
+
850
+ @keyframes mock-dot-pulse {
851
+ 0%, 100% { opacity: 1; }
852
+ 50% { opacity: 0.4; }
853
+ }
854
+
855
+ /* Legacy circle button (hidden by default, used for backward compat) */
856
+ .mock-widget-button {
857
+ display: none;
450
858
  }
451
859
 
452
860
  /* Prompt bubble styles */
@@ -583,12 +991,12 @@
583
991
 
584
992
  .mock-widget-panel {
585
993
  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);
994
+ width: 340px;
995
+ max-width: calc(100vw - 40px);
996
+ background: #16161e;
997
+ border-radius: 20px;
998
+ box-shadow: 0 24px 60px rgba(0,0,0,0.6);
999
+ border: 1px solid rgba(255,255,255,0.08);
592
1000
  display: none;
593
1001
  overflow: hidden;
594
1002
  flex-direction: column;
@@ -599,20 +1007,14 @@
599
1007
  }
600
1008
 
601
1009
  .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;
1010
+ display: none;
609
1011
  }
610
1012
 
611
1013
  .mock-panel-close {
612
1014
  background: none;
613
1015
  border: none;
614
- color: white;
615
- font-size: 24px;
1016
+ color: rgba(255,255,255,0.6);
1017
+ font-size: 20px;
616
1018
  cursor: pointer;
617
1019
  padding: 0;
618
1020
  width: 32px;
@@ -620,18 +1022,117 @@
620
1022
  display: flex;
621
1023
  align-items: center;
622
1024
  justify-content: center;
623
- border-radius: 4px;
624
- transition: background 0.2s;
1025
+ border-radius: 50%;
1026
+ transition: all 0.2s;
625
1027
  }
626
1028
 
627
1029
  .mock-panel-close:hover {
628
- background: rgba(255, 255, 255, 0.2);
1030
+ background: rgba(255,255,255,0.1);
1031
+ color: #fff;
629
1032
  }
630
1033
 
631
1034
  .mock-panel-content {
632
1035
  flex: 1;
633
1036
  overflow-y: auto;
634
- padding: 0; /* Remove padding so landing screen fills entire area */
1037
+ padding: 0;
1038
+ }
1039
+
1040
+ /* Voice Idle Hero - matches real widget */
1041
+ .mock-hero {
1042
+ position: relative;
1043
+ padding: 24px 22px 22px;
1044
+ background: linear-gradient(160deg, #2a2550 0%, #1a1a2e 100%);
1045
+ border-bottom: 1px solid rgba(255,255,255,0.06);
1046
+ overflow: hidden;
1047
+ border-radius: 18px 18px 0 0;
1048
+ }
1049
+ .mock-hero::after {
1050
+ content: '';
1051
+ position: absolute;
1052
+ top: -40px; right: -40px;
1053
+ width: 140px; height: 140px;
1054
+ border-radius: 50%;
1055
+ background: radial-gradient(circle, rgba(109,86,245,0.18) 0%, transparent 70%);
1056
+ pointer-events: none;
1057
+ }
1058
+ .mock-hero-header {
1059
+ display: flex;
1060
+ align-items: center;
1061
+ justify-content: space-between;
1062
+ margin-bottom: 20px;
1063
+ position: relative;
1064
+ z-index: 1;
1065
+ }
1066
+ .mock-hero-agent {
1067
+ display: flex;
1068
+ align-items: center;
1069
+ gap: 10px;
1070
+ }
1071
+ .mock-hero-avatar-wrap {
1072
+ position: relative;
1073
+ }
1074
+ .mock-hero-avatar {
1075
+ width: 36px; height: 36px; border-radius: 50%;
1076
+ background: linear-gradient(135deg, #6d56f5, #a78bfa);
1077
+ display: flex; align-items: center; justify-content: center;
1078
+ font-size: 14px; font-weight: 500; color: #fff;
1079
+ }
1080
+ .mock-hero-online-dot {
1081
+ position: absolute; bottom: 0; right: 0;
1082
+ width: 10px; height: 10px; border-radius: 50%;
1083
+ background: #22c55e; border: 2px solid #1e1b38;
1084
+ }
1085
+ .mock-hero-agent-name {
1086
+ font-size: 14px; font-weight: 500; color: #f0eff8;
1087
+ }
1088
+ .mock-hero-agent-role {
1089
+ font-size: 10px; color: rgba(255,255,255,0.35); margin-top: 1px;
1090
+ }
1091
+ .mock-hero-close {
1092
+ width: 26px; height: 26px; border-radius: 50%;
1093
+ background: rgba(255,255,255,0.07); border: none; cursor: pointer;
1094
+ color: rgba(255,255,255,0.4);
1095
+ display: flex; align-items: center; justify-content: center;
1096
+ transition: background 0.2s;
1097
+ }
1098
+ .mock-hero-close:hover {
1099
+ background: rgba(255,255,255,0.14);
1100
+ }
1101
+ .mock-hero-headline {
1102
+ font-size: 22px; font-weight: 500; color: #fff;
1103
+ line-height: 1.2; margin-bottom: 6px; position: relative; z-index: 1;
1104
+ }
1105
+ .mock-hero-subline {
1106
+ font-size: 13px; color: rgba(255,255,255,0.45);
1107
+ line-height: 1.5; position: relative; z-index: 1;
1108
+ }
1109
+ .mock-hero-body {
1110
+ padding: 10px 18px 14px;
1111
+ display: flex; flex-direction: column; gap: 6px;
1112
+ }
1113
+ .mock-hero-btn-primary {
1114
+ width: 100%; padding: 11px; border-radius: 12px;
1115
+ background: linear-gradient(135deg, #6d56f5, #9d8df8);
1116
+ border: none; cursor: pointer;
1117
+ font-size: 13px; font-weight: 500; color: #fff;
1118
+ display: flex; align-items: center; justify-content: center; gap: 8px;
1119
+ box-shadow: 0 4px 18px rgba(109,86,245,0.35);
1120
+ transition: opacity 0.2s, transform 0.15s;
1121
+ font-family: inherit;
1122
+ }
1123
+ .mock-hero-btn-primary:hover {
1124
+ opacity: 0.9; transform: translateY(-1px);
1125
+ }
1126
+ .mock-hero-btn-secondary {
1127
+ width: 100%; padding: 10px; border-radius: 12px;
1128
+ background: rgba(255,255,255,0.05);
1129
+ border: 1px solid rgba(255,255,255,0.09);
1130
+ cursor: pointer; font-size: 13px; color: rgba(255,255,255,0.6);
1131
+ display: flex; align-items: center; justify-content: center; gap: 8px;
1132
+ transition: background 0.2s; font-family: inherit;
1133
+ }
1134
+ .mock-hero-btn-secondary:hover {
1135
+ background: rgba(255,255,255,0.09);
635
1136
  }
636
1137
 
637
1138
  .mock-landing-screen {
@@ -1268,29 +1769,85 @@
1268
1769
  </head>
1269
1770
  <body>
1270
1771
  <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>
1772
+ <div class="header-left">
1773
+ <a href="test-index.html" class="back-link">← Back</a>
1774
+ <h1>Widget Customizer</h1>
1775
+ </div>
1776
+ <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);">
1777
+ <span id="instructionText"><strong>Click</strong> to customize · <strong>Double-click</strong> to interact</span>
1277
1778
  </div>
1278
1779
  </div>
1279
1780
 
1280
1781
  <div class="container">
1281
1782
  <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 -->
1783
+ <div class="preview-header">
1784
+ <h2>Preview</h2>
1785
+ <div class="device-toggle">
1786
+ <button class="device-toggle-btn active" id="desktopToggle" onclick="switchDevice('desktop')">
1787
+ <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>
1788
+ <span class="device-label">Desktop</span>
1789
+ </button>
1790
+ <button class="device-toggle-btn" id="mobileToggle" onclick="switchDevice('mobile')">
1791
+ <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>
1792
+ <span class="device-label">Mobile</span>
1793
+ </button>
1794
+ </div>
1795
+ </div>
1796
+ <div class="preview-area desktop-mode" id="previewArea">
1797
+ <!-- Desktop device frame -->
1798
+ <div class="device-frame-desktop" id="deviceFrameDesktop">
1799
+ <div class="desktop-chrome">
1800
+ <div class="desktop-dots"><span></span><span></span><span></span></div>
1801
+ <div class="desktop-url-bar">yourwebsite.com</div>
1802
+ </div>
1803
+ <div class="desktop-content" id="desktopContent">
1804
+ <div class="desktop-placeholder">
1805
+ <div class="placeholder-line"></div>
1806
+ <div class="placeholder-line"></div>
1807
+ <div class="placeholder-line"></div>
1808
+ <div class="placeholder-line"></div>
1809
+ <div class="placeholder-line"></div>
1810
+ </div>
1811
+ <div class="mock-widget" id="mockWidget" data-element-type="position">
1812
+ <div class="mock-widget-panel" id="mockPanel">
1813
+ </div>
1814
+ <div class="mock-button-container" id="mockButtonContainer">
1815
+ <div class="mock-prompt-bubble" id="mockPromptBubble" style="display: none;"></div>
1816
+ <div class="mock-pulse-rings" id="mockPulseRings" style="display: none;"></div>
1817
+ <button class="mock-pill-launcher" id="mockButton" data-element-type="button">
1818
+ <div class="mock-pill-icon" id="mockPillIcon">
1819
+ <img src="https://talktopc.com/logo192.png" alt="" style="width:22px;height:22px;border-radius:50%;object-fit:cover;">
1820
+ </div>
1821
+ <div class="mock-pill-text" id="mockPillText">
1822
+ <span class="mock-pill-title" id="mockPillTitle">Chat Assistant</span>
1823
+ <span class="mock-pill-status">
1824
+ <span class="mock-pill-dot"></span>
1825
+ <span id="mockPillStatusText">Online</span>
1826
+ </span>
1827
+ </div>
1828
+ </button>
1829
+ </div>
1830
+ </div>
1831
+ </div>
1832
+ </div>
1833
+ <!-- Mobile device frame (hidden by default) -->
1834
+ <div class="device-frame-mobile" id="deviceFrameMobile" style="display: none;">
1835
+ <div class="phone-notch"></div>
1836
+ <div class="phone-screen">
1837
+ <div class="phone-status-bar">
1838
+ <span>9:41</span>
1839
+ <span style="display: flex; gap: 4px; font-size: 11px;">
1840
+ <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>
1841
+ <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>
1842
+ </span>
1289
1843
  </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>
1844
+ <div class="phone-content" id="phoneContent">
1845
+ <div class="phone-placeholder">
1846
+ <div class="placeholder-line"></div>
1847
+ <div class="placeholder-line"></div>
1848
+ <div class="placeholder-line"></div>
1849
+ <div class="placeholder-line"></div>
1850
+ </div>
1294
1851
  </div>
1295
1852
  </div>
1296
1853
  </div>
@@ -1298,40 +1855,109 @@
1298
1855
  </div>
1299
1856
 
1300
1857
  <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>
1858
+ <div class="customization-panel-header">
1859
+ <h2>Customize</h2>
1314
1860
  </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.
1861
+ <div class="customization-panel-body">
1862
+ <div class="info-box" id="instructionsBox">
1863
+ <p id="instructionsText">
1864
+ <strong>Click</strong> any widget element to customize it. <strong>Double-click</strong> to interact normally.
1322
1865
  </p>
1323
1866
  </div>
1324
- </div>
1325
1867
 
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>
1868
+ <div class="quick-themes">
1869
+ <h3>Quick Themes</h3>
1870
+ <div class="theme-cards" id="themeCards">
1871
+ <!-- Default Dark -->
1872
+ <button class="theme-card active" data-theme="default" id="themeDefault">
1873
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #2a1f4e 0%, #0d0d1a 100%);">
1874
+ <div class="theme-card-top">
1875
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #a78bfa, #7c3aed);">S</div>
1876
+ <div class="theme-card-lines">
1877
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1878
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1879
+ </div>
1880
+ </div>
1881
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #8b5cf6, #6d28d9);"></div>
1882
+ </div>
1883
+ <div class="theme-card-label">Default</div>
1884
+ </button>
1885
+ <!-- Light -->
1886
+ <button class="theme-card" data-theme="light" id="themeLight">
1887
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #ede9fe 0%, #f5f3ff 100%);">
1888
+ <div class="theme-card-top">
1889
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #7c3aed, #a78bfa);">S</div>
1890
+ <div class="theme-card-lines">
1891
+ <div class="theme-card-line" style="width: 24px; background: #1e1b4b;"></div>
1892
+ <div class="theme-card-line" style="width: 16px; background: rgba(30,27,75,0.35);"></div>
1893
+ </div>
1894
+ </div>
1895
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #7c3aed, #a78bfa);"></div>
1896
+ </div>
1897
+ <div class="theme-card-label">Light</div>
1898
+ </button>
1899
+ <!-- Sunset -->
1900
+ <button class="theme-card" data-theme="sunset" id="themeSunset">
1901
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #4a1942 0%, #1a0a2e 100%);">
1902
+ <div class="theme-card-top">
1903
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #f97316, #ec4899);">S</div>
1904
+ <div class="theme-card-lines">
1905
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1906
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1907
+ </div>
1908
+ </div>
1909
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #f97316, #ec4899);"></div>
1910
+ </div>
1911
+ <div class="theme-card-label">Sunset</div>
1912
+ </button>
1913
+ <!-- Hebrew RTL -->
1914
+ <button class="theme-card" data-theme="hebrew" id="themeHebrew">
1915
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #1a2744 0%, #0f172a 100%); direction: rtl;">
1916
+ <div class="theme-card-top" style="flex-direction: row-reverse;">
1917
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #3b82f6, #1d4ed8);">ש</div>
1918
+ <div class="theme-card-lines" style="align-items: flex-end;">
1919
+ <div class="theme-card-line" style="width: 24px; background: rgba(255,255,255,0.7);"></div>
1920
+ <div class="theme-card-line" style="width: 16px; background: rgba(255,255,255,0.3);"></div>
1921
+ </div>
1922
+ </div>
1923
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #3b82f6, #1d4ed8);"></div>
1924
+ </div>
1925
+ <div class="theme-card-label">עברית</div>
1926
+ </button>
1927
+ <!-- Sasha / S-Law -->
1928
+ <button class="theme-card" data-theme="sasha" id="themeSasha">
1929
+ <div class="theme-card-preview" style="background: linear-gradient(160deg, #f8f5ef 0%, #ebe6de 100%); direction: rtl;">
1930
+ <div class="theme-card-top" style="flex-direction: row-reverse;">
1931
+ <div class="theme-card-avatar" style="background: linear-gradient(135deg, #c4a265, #9e7e4f);">S</div>
1932
+ <div class="theme-card-lines" style="align-items: flex-end;">
1933
+ <div class="theme-card-line" style="width: 24px; background: #2d3748;"></div>
1934
+ <div class="theme-card-line" style="width: 16px; background: rgba(45,55,72,0.35);"></div>
1935
+ </div>
1936
+ </div>
1937
+ <div class="theme-card-btn" style="background: linear-gradient(135deg, #c4a265, #9e7e4f);"></div>
1938
+ </div>
1939
+ <div class="theme-card-label">S-Law</div>
1940
+ </button>
1941
+ </div>
1942
+ </div>
1943
+
1944
+ <div id="customizationControls" style="margin-bottom: 12px;">
1945
+ <div class="customization-group">
1946
+ <h3>Select an Element</h3>
1947
+ <p style="color: #64748b; font-size: 13px; margin-top: 8px;">
1948
+ Click on any widget element in the preview to start customizing.
1949
+ </p>
1950
+ </div>
1951
+ </div>
1952
+
1953
+ <div class="button-group" style="margin-bottom: 12px;">
1954
+ <button class="btn btn-primary" id="resetBtn">Reset</button>
1329
1955
  <button class="btn btn-secondary" id="togglePanelBtn">Toggle Panel</button>
1330
1956
  </div>
1331
1957
 
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>
1958
+ <div class="code-output">
1959
+ <h3>Configuration Code</h3>
1960
+ <pre id="configCode">// Select an element to see its configuration</pre>
1335
1961
  </div>
1336
1962
  </div>
1337
1963
  </div>
@@ -1340,6 +1966,7 @@
1340
1966
  <script>
1341
1967
  // Mock widget configuration
1342
1968
  let widgetConfig = {
1969
+ agentName: 'Sasha',
1343
1970
  button: {
1344
1971
  size: 'medium',
1345
1972
  shape: 'circle',
@@ -1355,11 +1982,11 @@
1355
1982
  backgroundColor: '#FFFFFF'
1356
1983
  },
1357
1984
  panel: {
1358
- width: 360,
1359
- height: 550, // Updated from SDK default 500
1360
- borderRadius: 24,
1361
- backgroundColor: '#FFFFFF',
1362
- border: '1px solid #E5E7EB'
1985
+ width: 340,
1986
+ height: 550,
1987
+ borderRadius: 20,
1988
+ backgroundColor: '#16161e',
1989
+ border: '1px solid rgba(255,255,255,0.08)'
1363
1990
  },
1364
1991
  direction: 'ltr', // 'ltr' or 'rtl'
1365
1992
  position: {
@@ -1395,6 +2022,9 @@
1395
2022
  inputFocusColor: '#7C3AED'
1396
2023
  },
1397
2024
  voice: {
2025
+ agentRole: 'AI Voice Assistant',
2026
+ headline: 'Hi there 👋',
2027
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
1398
2028
  micButtonColor: '#7C3AED',
1399
2029
  micButtonActiveColor: '#EF4444',
1400
2030
  speakerButtonColor: '#FFFFFF',
@@ -1403,7 +2033,7 @@
1403
2033
  avatarType: 'icon', // 'icon' or 'image'
1404
2034
  avatarIcon: '🤖',
1405
2035
  avatarImageUrl: '',
1406
- startCallButtonText: 'Start Call',
2036
+ startCallButtonText: 'Start Voice Call',
1407
2037
  startCallButtonColor: '#667eea',
1408
2038
  startCallButtonTextColor: '#FFFFFF',
1409
2039
  statusTitleColor: '#1e293b',
@@ -1416,7 +2046,11 @@
1416
2046
  liveIndicatorTextColor: '#10b981',
1417
2047
  waveformType: 'waveform', // 'waveform', 'icon', or 'image'
1418
2048
  waveformIcon: '🎤',
1419
- waveformImageUrl: ''
2049
+ waveformImageUrl: '',
2050
+ waveformBarColor: '#7C3AED',
2051
+ pillGradient: '',
2052
+ pillTextColor: '#ffffff',
2053
+ pillDotColor: '#4ade80'
1420
2054
  },
1421
2055
  landing: {
1422
2056
  backgroundColor: 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', // Default gradient matching real widget
@@ -1454,7 +2088,8 @@
1454
2088
  };
1455
2089
 
1456
2090
  let selectedElement = null;
1457
- let currentView = 'landing'; // 'landing', 'text', 'voice'
2091
+ let currentView = 'voiceIdle'; // 'voiceIdle', 'landing', 'text', 'voice'
2092
+ let currentDevice = 'desktop'; // 'desktop', 'mobile'
1458
2093
  let panelOpen = true; // Start with panel open to show defaults
1459
2094
  let clickTimeout = null; // Track single vs double click
1460
2095
  let historyExpanded = false; // Track conversation history state
@@ -1463,6 +2098,37 @@
1463
2098
  let lastClickElement = null;
1464
2099
  let lastClickType = null;
1465
2100
 
2101
+ function switchDevice(device) {
2102
+ currentDevice = device;
2103
+ const desktopBtn = document.getElementById('desktopToggle');
2104
+ const mobileBtn = document.getElementById('mobileToggle');
2105
+ const previewArea = document.getElementById('previewArea');
2106
+ const desktopFrame = document.getElementById('deviceFrameDesktop');
2107
+ const mobileFrame = document.getElementById('deviceFrameMobile');
2108
+ const mockWidget = document.getElementById('mockWidget');
2109
+
2110
+ desktopBtn.classList.toggle('active', device === 'desktop');
2111
+ mobileBtn.classList.toggle('active', device === 'mobile');
2112
+ previewArea.classList.toggle('desktop-mode', device === 'desktop');
2113
+ previewArea.classList.toggle('mobile-mode', device === 'mobile');
2114
+
2115
+ if (device === 'desktop') {
2116
+ desktopFrame.style.display = '';
2117
+ mobileFrame.style.display = 'none';
2118
+ if (mockWidget.parentElement !== document.getElementById('desktopContent')) {
2119
+ document.getElementById('desktopContent').appendChild(mockWidget);
2120
+ }
2121
+ } else {
2122
+ desktopFrame.style.display = 'none';
2123
+ mobileFrame.style.display = '';
2124
+ if (mockWidget.parentElement !== document.getElementById('phoneContent')) {
2125
+ document.getElementById('phoneContent').appendChild(mockWidget);
2126
+ }
2127
+ }
2128
+ updateMockWidgetPosition();
2129
+ }
2130
+ window.switchDevice = switchDevice;
2131
+
1466
2132
  // Initialize mock widget
1467
2133
  function initMockWidget() {
1468
2134
  const mockButton = document.getElementById('mockButton');
@@ -1506,58 +2172,58 @@
1506
2172
  }
1507
2173
 
1508
2174
  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';
2175
+ const iconConfig = widgetConfig.icon;
2176
+ const headerConfig = widgetConfig.header;
2177
+
2178
+ // Update pill icon
2179
+ const pillIcon = document.getElementById('mockPillIcon');
2180
+ if (pillIcon) {
2181
+ if (iconConfig.type === 'custom' && iconConfig.customImage) {
2182
+ pillIcon.innerHTML = `<img src="${iconConfig.customImage}" alt="" style="width:22px;height:22px;border-radius:50%;object-fit:cover;">`;
2183
+ } else if (iconConfig.type === 'emoji') {
2184
+ pillIcon.innerHTML = `<span class="pill-emoji">${iconConfig.emoji || '🤖'}</span>`;
2185
+ } else {
2186
+ pillIcon.innerHTML = `<img src="${iconConfig.customImage || 'https://talktopc.com/logo192.png'}" alt="" style="width:22px;height:22px;border-radius:50%;object-fit:cover;">`;
2187
+ }
2188
+ pillIcon.style.backgroundColor = iconConfig.backgroundColor || '#ffffff';
1519
2189
  }
1520
2190
 
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>`;
2191
+ // Update pill title and status
2192
+ const pillTitle = document.getElementById('mockPillTitle');
2193
+ if (pillTitle) pillTitle.textContent = headerConfig.title || 'Chat Assistant';
2194
+
2195
+ const pillStatusText = document.getElementById('mockPillStatusText');
2196
+ if (pillStatusText) pillStatusText.textContent = headerConfig.onlineIndicatorText || 'Online';
2197
+
2198
+ // Update pill launcher background
2199
+ const pillGrad = widgetConfig.voice?.pillGradient;
2200
+ if (pillGrad) {
2201
+ button.style.background = pillGrad;
1545
2202
  } 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);
2203
+ const bgColor = widgetConfig.button.backgroundColor;
2204
+ if (bgColor && bgColor !== '#FFFFFF' && bgColor !== '#ffffff') {
2205
+ button.style.background = bgColor;
2206
+ }
2207
+ }
2208
+
2209
+ // Update pill direction
2210
+ button.style.direction = widgetConfig.direction || 'ltr';
2211
+
2212
+ // Update pill text colors
2213
+ const pillTextColor = widgetConfig.voice?.pillTextColor;
2214
+ if (pillTextColor) {
2215
+ if (pillTitle) pillTitle.style.color = pillTextColor;
2216
+ const pillStatus = button.querySelector('.mock-pill-status');
2217
+ if (pillStatus) pillStatus.style.color = pillTextColor.replace('1)', '0.55)').replace('#fff', 'rgba(255,255,255,0.55)');
2218
+ }
2219
+ const pillDotColor = widgetConfig.voice?.pillDotColor;
2220
+ const pillDot = button.querySelector('.mock-pill-dot');
2221
+ if (pillDotColor && pillDot) {
2222
+ pillDot.style.background = pillDotColor;
1555
2223
  }
1556
2224
 
1557
- // Make button highlightable
1558
2225
  button.dataset.elementType = 'button';
1559
2226
 
1560
- // Update prompt bubble if enabled
1561
2227
  updatePromptBubble(button);
1562
2228
 
1563
2229
  // Remove old event listeners by replacing the button
@@ -1570,25 +2236,19 @@
1570
2236
  e.preventDefault();
1571
2237
  e.stopPropagation();
1572
2238
 
1573
- // For button, single click should toggle panel immediately
1574
- // Double click will still select for editing (without double-toggling)
1575
2239
  const currentTime = Date.now();
1576
2240
  const timeSinceLastClick = currentTime - lastClickTime;
1577
2241
 
1578
- // Check if this is a double click (within 400ms and same element)
1579
2242
  if (timeSinceLastClick < 400 && lastClickElement === newButton && lastClickType === 'button') {
1580
- // Double click - just select for editing (don't toggle panel again)
1581
2243
  lastClickTime = 0;
1582
2244
  lastClickElement = null;
1583
2245
  lastClickType = null;
1584
2246
  selectElement('button', newButton, e);
1585
2247
  } else {
1586
- // Single click - toggle panel immediately and select button
1587
2248
  lastClickTime = currentTime;
1588
2249
  lastClickElement = newButton;
1589
2250
  lastClickType = 'button';
1590
2251
 
1591
- // Toggle panel
1592
2252
  panelOpen = !panelOpen;
1593
2253
  const panel = document.getElementById('mockPanel');
1594
2254
  panel.classList.toggle('open');
@@ -1596,12 +2256,8 @@
1596
2256
  renderPanelContent();
1597
2257
  }
1598
2258
 
1599
- // Update prompt bubble visibility based on panel state
1600
2259
  updatePromptBubble(newButton);
1601
- // Sync actual widget state with mock panel
1602
2260
  syncWidgetWithMockPanel();
1603
-
1604
- // Select the button for editing (so user can customize it)
1605
2261
  selectElement('button', newButton, e);
1606
2262
  }
1607
2263
  });
@@ -1686,46 +2342,52 @@
1686
2342
 
1687
2343
  const pos = widgetConfig.position;
1688
2344
  const offset = pos.offset || { x: 20, y: 20 };
1689
-
1690
- // Clear any existing positioning
2345
+
1691
2346
  mockWidget.style.top = '';
1692
2347
  mockWidget.style.bottom = '';
1693
2348
  mockWidget.style.left = '';
1694
2349
  mockWidget.style.right = '';
1695
-
1696
- // Set position
1697
2350
  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');
2351
+
2352
+ if (currentDevice === 'mobile') {
2353
+ const mobileOffset = { x: Math.min(offset.x, 12), y: Math.min(offset.y, 12) };
2354
+ if (pos.vertical === 'top') {
2355
+ mockWidget.style.setProperty('top', `${mobileOffset.y}px`, 'important');
2356
+ mockWidget.style.setProperty('bottom', 'auto', 'important');
2357
+ } else {
2358
+ mockWidget.style.setProperty('bottom', `${mobileOffset.y}px`, 'important');
2359
+ mockWidget.style.setProperty('top', 'auto', 'important');
2360
+ }
2361
+ mockWidget.style.setProperty('right', `${mobileOffset.x}px`, 'important');
2362
+ mockWidget.style.setProperty('left', 'auto', 'important');
2363
+ } else {
2364
+ if (pos.vertical === 'top') {
2365
+ mockWidget.style.setProperty('top', `${offset.y}px`, 'important');
2366
+ mockWidget.style.setProperty('bottom', 'auto', 'important');
2367
+ } else {
2368
+ mockWidget.style.setProperty('bottom', `${offset.y}px`, 'important');
2369
+ mockWidget.style.setProperty('top', 'auto', 'important');
2370
+ }
2371
+ mockWidget.style.setProperty('right', `${offset.x}px`, 'important');
2372
+ mockWidget.style.setProperty('left', 'auto', 'important');
1706
2373
  }
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
2374
  }
1712
2375
 
1713
2376
  function renderPanelContent() {
1714
2377
  const mockPanel = document.getElementById('mockPanel');
1715
2378
 
1716
- // Apply panel styles
2379
+ // Apply panel styles - dark shell (matches real widget: width 340px, auto height)
1717
2380
  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)
2381
+ mockPanel.style.height = 'auto';
2382
+ mockPanel.style.borderRadius = (widgetConfig.panel.borderRadius || 20) + 'px';
2383
+ mockPanel.style.background = widgetConfig.panel.backgroundColor || '#16161e';
2384
+ mockPanel.style.border = widgetConfig.panel.border || '1px solid rgba(255,255,255,0.08)';
1725
2385
  mockPanel.style.direction = widgetConfig.direction || 'ltr';
1726
2386
 
1727
2387
  // Render based on current view
1728
- if (currentView === 'landing') {
2388
+ if (currentView === 'voiceIdle') {
2389
+ renderVoiceIdleScreen(mockPanel);
2390
+ } else if (currentView === 'landing') {
1729
2391
  renderLandingScreen(mockPanel);
1730
2392
  } else if (currentView === 'text') {
1731
2393
  renderTextInterface(mockPanel);
@@ -1737,9 +2399,97 @@
1737
2399
  addPanelSelector();
1738
2400
  }
1739
2401
 
2402
+ function isLightBackground(hex) {
2403
+ if (!hex || hex.charAt(0) !== '#') return false;
2404
+ const r = parseInt(hex.substr(1,2), 16);
2405
+ const g = parseInt(hex.substr(3,2), 16);
2406
+ const b = parseInt(hex.substr(5,2), 16);
2407
+ return (r * 299 + g * 587 + b * 114) / 1000 > 160;
2408
+ }
2409
+
2410
+ function renderVoiceIdleScreen(panel) {
2411
+ const v = widgetConfig.voice || {};
2412
+ const agentName = widgetConfig.agentName || 'Sasha';
2413
+ const agentRole = v.agentRole || 'AI Voice Assistant';
2414
+ const headline = v.headline || 'Hi there 👋';
2415
+ const subline = v.subline || 'Ask me anything — I respond instantly<br>in voice or text.';
2416
+ const avatarInitial = agentName.charAt(0).toUpperCase();
2417
+ const avatarGrad1 = v.avatarGradient1 || '#6d56f5';
2418
+ const avatarGrad2 = v.avatarGradient2 || '#a78bfa';
2419
+ const onlineDotColor = v.onlineDotColor || '#22c55e';
2420
+ const heroGrad1 = v.heroGradient1 || '#2a2550';
2421
+ const heroGrad2 = v.heroGradient2 || '#1a1a2e';
2422
+ const nameColor = v.agentNameColor || '#f0eff8';
2423
+ const roleColor = v.agentRoleColor || 'rgba(255,255,255,0.35)';
2424
+ const headlineColor = v.headlineColor || '#ffffff';
2425
+ const sublineColor = v.sublineColor || 'rgba(255,255,255,0.45)';
2426
+ const primaryBtnGrad1 = v.primaryBtnGradient1 || '#6d56f5';
2427
+ const primaryBtnGrad2 = v.primaryBtnGradient2 || '#9d8df8';
2428
+ const primaryBtnTextColor = v.startCallButtonTextColor || '#ffffff';
2429
+ const secondaryBtnBg = v.secondaryBtnBg || 'rgba(255,255,255,0.05)';
2430
+ const secondaryBtnBorder = v.secondaryBtnBorder || 'rgba(255,255,255,0.09)';
2431
+ const secondaryBtnTextColor = v.secondaryBtnTextColor || 'rgba(255,255,255,0.6)';
2432
+ const sendMessageText = v.sendMessageText || 'Send a Message';
2433
+
2434
+ const panelBg = widgetConfig.panel?.backgroundColor || '#16161e';
2435
+ const light = isLightBackground(panelBg);
2436
+ const closeColor = light ? '#6b7280' : 'currentColor';
2437
+ const footerBorderColor = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2438
+ const footerTextColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2439
+ const footerLinkColor = light ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
2440
+
2441
+ panel.innerHTML = `
2442
+ <div class="mock-hero" data-element-type="heroBackground" style="background: linear-gradient(160deg, ${heroGrad1} 0%, ${heroGrad2} 100%);">
2443
+ <div class="mock-hero-header">
2444
+ <div class="mock-hero-agent">
2445
+ <div class="mock-hero-avatar-wrap">
2446
+ <div class="mock-hero-avatar" data-element-type="heroAvatar" style="background: linear-gradient(135deg, ${avatarGrad1}, ${avatarGrad2});">${avatarInitial}</div>
2447
+ <div class="mock-hero-online-dot" style="background: ${onlineDotColor};"></div>
2448
+ </div>
2449
+ <div>
2450
+ <div class="mock-hero-agent-name" data-element-type="heroAgentName" style="color: ${nameColor};">${agentName}</div>
2451
+ <div class="mock-hero-agent-role" data-element-type="heroAgentRole" style="color: ${roleColor};">${agentRole}</div>
2452
+ </div>
2453
+ </div>
2454
+ <button class="mock-hero-close" data-element-type="closeButton" style="color: ${closeColor};">
2455
+ <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2">
2456
+ <path d="M10 2L2 10M2 2l8 8"/>
2457
+ </svg>
2458
+ </button>
2459
+ </div>
2460
+ <div class="mock-hero-headline" data-element-type="heroHeadline" style="color: ${headlineColor};">${headline}</div>
2461
+ <div class="mock-hero-subline" data-element-type="heroSubline" style="color: ${sublineColor};">${subline}</div>
2462
+ </div>
2463
+ <div class="mock-hero-body" style="background: ${panelBg};">
2464
+ <button class="mock-hero-btn-primary" data-element-type="heroPrimaryBtn" style="background: linear-gradient(135deg, ${primaryBtnGrad1}, ${primaryBtnGrad2}); color: ${primaryBtnTextColor};">
2465
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${primaryBtnTextColor}" stroke-width="2">
2466
+ <path d="M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z"/>
2467
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8"/>
2468
+ </svg>
2469
+ ${v.startCallButtonText || 'Start Voice Call'}
2470
+ </button>
2471
+ <button class="mock-hero-btn-secondary" data-element-type="heroSecondaryBtn" style="background: ${secondaryBtnBg}; border: 1px solid ${secondaryBtnBorder}; color: ${secondaryBtnTextColor};">
2472
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="${secondaryBtnTextColor}" stroke-width="2">
2473
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
2474
+ </svg>
2475
+ ${sendMessageText}
2476
+ </button>
2477
+ </div>
2478
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${footerBorderColor}; background: transparent; flex-shrink: 0;">
2479
+ <span style="font-size: 10px; color: ${footerTextColor};">Powered by <a href="#" style="color: ${footerLinkColor}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2480
+ </div>
2481
+ `;
2482
+
2483
+ setupElementListeners(panel);
2484
+ }
2485
+
1740
2486
  function renderLandingScreen(panel) {
1741
2487
  const config = widgetConfig.landing;
1742
2488
  const iconBgColor = config.modeCardIconBackgroundColor || '#7C3AED';
2489
+ const landingLight = true; // landing screen always has a light background
2490
+ const landFooterBorder = 'rgba(0,0,0,0.08)';
2491
+ const landFooterText = 'rgba(0,0,0,0.4)';
2492
+ const landFooterLink = iconBgColor;
1743
2493
  // Determine logo background - use logoBackgroundColor if enabled, otherwise transparent
1744
2494
  let logoBg = 'transparent';
1745
2495
  if (config.logoType === 'image' && config.logoBackgroundEnabled !== false) {
@@ -1750,18 +2500,8 @@
1750
2500
  }
1751
2501
 
1752
2502
  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
2503
  <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">
2504
+ <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
2505
  <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
2506
  ${config.logoType === 'image' && config.logoImageUrl ? `
1767
2507
  <img src="${config.logoImageUrl}" alt="Logo" style="max-width: 44px; max-height: 44px; object-fit: contain;">
@@ -1794,11 +2534,8 @@
1794
2534
  </div>
1795
2535
  </div>
1796
2536
  </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>
2537
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${landFooterBorder}; background: transparent; flex-shrink: 0;">
2538
+ <span style="font-size: 10px; color: ${landFooterText};">Powered by <a href="#" style="color: ${landFooterLink}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
1802
2539
  </div>
1803
2540
  `;
1804
2541
 
@@ -1808,13 +2545,14 @@
1808
2545
 
1809
2546
  function renderTextInterface(panel) {
1810
2547
  const config = widgetConfig.text;
2548
+ const panelBgText = widgetConfig.panel.backgroundColor || '#16161e';
2549
+ const lightText = isLightBackground(panelBgText);
2550
+ const textFooterBorder = lightText ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2551
+ const textFooterColor = lightText ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2552
+ const textFooterLink = lightText ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
1811
2553
  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
2554
  <div class="mock-text-interface" style="direction: ${widgetConfig.direction || 'ltr'};">
1817
- <div class="mock-messages">
2555
+ <div class="mock-messages" style="background: #f8fafc;">
1818
2556
  <div class="mock-message user" data-element-type="userMessage">
1819
2557
  <div class="mock-message-avatar">${widgetConfig.messages.userAvatarIcon || '👤'}</div>
1820
2558
  <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 +2577,9 @@
1839
2577
  <button class="mock-send-button" style="background: ${config.sendButtonColor};" data-element-type="sendButton">${config.sendButtonText || '→'}</button>
1840
2578
  </div>
1841
2579
  </div>
2580
+ <div class="mock-footer" style="padding: 6px 18px 10px; display: flex; justify-content: center; border-top: 1px solid ${textFooterBorder}; background: transparent; flex-shrink: 0;">
2581
+ <span style="font-size: 10px; color: ${textFooterColor};">Powered by <a href="#" style="color: ${textFooterLink}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2582
+ </div>
1842
2583
  `;
1843
2584
 
1844
2585
  // Make elements selectable
@@ -1847,22 +2588,38 @@
1847
2588
 
1848
2589
  function renderVoiceInterface(panel) {
1849
2590
  const config = widgetConfig.voice;
1850
- // Show active call state matching real widget structure
2591
+ const callBg1 = config.heroGradient1 || '#2a2550';
2592
+ const callBg2 = config.heroGradient2 || '#1a1a2e';
2593
+ const waveColor = config.waveformBarColor || config.primaryBtnGradient1 || '#7C3AED';
2594
+ const timerTextColor = config.headlineColor || '#fff';
2595
+ const statusTextColor = config.sublineColor || 'rgba(255,255,255,0.7)';
2596
+ const panelBg = widgetConfig.panel?.backgroundColor || '#16161e';
2597
+ const light = isLightBackground(panelBg);
2598
+ const sectionBorder = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.08)';
2599
+ const convHeaderColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.4)';
2600
+ const bubbleBg = light ? '#f3f4f6' : 'rgba(255,255,255,0.08)';
2601
+ const bubbleColor = light ? '#1f2937' : 'rgba(255,255,255,0.85)';
2602
+ const inputBg = light ? '#f3f4f6' : 'rgba(255,255,255,0.06)';
2603
+ const inputBorder = light ? 'rgba(0,0,0,0.1)' : 'rgba(255,255,255,0.1)';
2604
+ const inputColor = light ? '#111827' : '#fff';
2605
+ const footerBorder = light ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
2606
+ const footerTextColor = light ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
2607
+ const footerAccent = light ? (widgetConfig.voice.primaryBtnGradient1 || '#7C3AED') : '#a78bfa';
1851
2608
  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'};">
2609
+ <style>
2610
+ .mock-voice-interface .mock-waveform-bar,
2611
+ .mock-compact-waveform .mock-waveform-bar { background: ${waveColor} !important; }
2612
+ .mock-voice-interface .mock-voice-section { border-bottom-color: ${sectionBorder}; }
2613
+ .mock-voice-interface .mock-voice-section-compact { border-bottom-color: ${sectionBorder}; }
2614
+ .mock-voice-interface .mock-conversation-section { background: ${panelBg}; }
2615
+ .mock-voice-interface .mock-conversation-header { color: ${convHeaderColor}; }
2616
+ .mock-voice-interface .mock-conversation-toggle { color: ${convHeaderColor}; }
2617
+ .mock-voice-interface .mock-history-bubble { background: ${bubbleBg}; color: ${bubbleColor}; }
2618
+ .mock-voice-interface .mock-voice-text-input { background: ${inputBg} !important; border-color: ${inputBorder} !important; color: ${inputColor} !important; }
2619
+ .mock-voice-interface .mock-voice-input-area { border-top-color: ${sectionBorder}; background: ${panelBg}; }
2620
+ .mock-voice-interface .mock-voice-send-btn { background: ${waveColor} !important; }
2621
+ </style>
2622
+ <div class="mock-voice-interface" style="direction: ${widgetConfig.direction || 'ltr'}; background: linear-gradient(160deg, ${callBg1} 0%, ${callBg2} 100%); color: ${timerTextColor};">
1866
2623
  <!-- Voice Section -->
1867
2624
  <!-- Multi-row layout when history is collapsed -->
1868
2625
  <div class="mock-voice-section" id="mockVoiceSectionExpanded">
@@ -2083,9 +2840,8 @@
2083
2840
  </div>
2084
2841
 
2085
2842
  <!-- Powered By -->
2086
- <div class="mock-powered-by">
2087
- <span>⚡</span>
2088
- <span>Powered by <strong>TalkToPC</strong></span>
2843
+ <div class="mock-powered-by" style="color: ${footerTextColor}; border-top: 1px solid ${footerBorder};">
2844
+ <span>Powered by <a href="#" style="color: ${footerAccent}; text-decoration: none; font-weight: 700;">TalkToPC</a></span>
2089
2845
  </div>
2090
2846
  </div>
2091
2847
  `;
@@ -2252,8 +3008,11 @@
2252
3008
 
2253
3009
  function performNormalInteraction(elementType, element, event) {
2254
3010
  if (elementType === 'closeButton' || elementType === 'endCallButton' || elementType === 'backButton') {
2255
- // End call or close should go back to landing screen
2256
- switchView('landing');
3011
+ switchView('voiceIdle');
3012
+ } else if (elementType === 'startCallButton' || elementType === 'heroPrimaryBtn') {
3013
+ switchView('voice');
3014
+ } else if (elementType === 'sendMessageButton' || elementType === 'heroSecondaryBtn') {
3015
+ switchView('text');
2257
3016
  } else if (elementType === 'modeCard') {
2258
3017
  const mode = element.getAttribute('data-mode');
2259
3018
  if (mode === 'voice') {
@@ -2354,31 +3113,14 @@
2354
3113
  case 'button':
2355
3114
  controlsHTML = `
2356
3115
  <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>
3116
+ <h3>Pill Launcher</h3>
2375
3117
  <div class="control-item">
2376
- <label>Background Color</label>
2377
- <input type="color" id="btnBgColor" value="${widgetConfig.button.backgroundColor}">
3118
+ <label>Title</label>
3119
+ <input type="text" id="pillTitle" value="${widgetConfig.header.title || 'Chat Assistant'}" placeholder="Chat Assistant">
2378
3120
  </div>
2379
3121
  <div class="control-item">
2380
- <label>Hover Color</label>
2381
- <input type="color" id="btnHoverColor" value="${widgetConfig.button.hoverColor}">
3122
+ <label>Online Status Text</label>
3123
+ <input type="text" id="pillStatusText" value="${widgetConfig.header.onlineIndicatorText || 'Online'}" placeholder="Online">
2382
3124
  </div>
2383
3125
  </div>
2384
3126
  <div class="customization-group">
@@ -2396,7 +3138,7 @@
2396
3138
  <div class="control-item" id="promptBgColorControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2397
3139
  <label>Background Color/Gradient</label>
2398
3140
  <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>
3141
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Supports solid colors (e.g., #7c3aed) or gradients</p>
2400
3142
  </div>
2401
3143
  <div class="control-item" id="promptTextColorControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2402
3144
  <label>Text Color</label>
@@ -2413,7 +3155,7 @@
2413
3155
  <div class="control-item" id="promptHideAfterSecondsControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2414
3156
  <label>Auto-Hide After (seconds)</label>
2415
3157
  <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>
3158
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Leave empty to never auto-hide</p>
2417
3159
  </div>
2418
3160
  <div class="control-item" id="promptPositionControl" style="display: ${widgetConfig.promptAnimation?.enabled === true ? 'block' : 'none'};">
2419
3161
  <label>Position</label>
@@ -2454,39 +3196,19 @@
2454
3196
  case 'header':
2455
3197
  controlsHTML = `
2456
3198
  <div class="customization-group">
2457
- <h3>Header</h3>
3199
+ <h3>Widget Identity</h3>
3200
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Controls the title and status shown in the pill launcher.</p>
2458
3201
  <div class="control-item">
2459
3202
  <label>Title Text</label>
2460
3203
  <input type="text" id="headerTitle" value="${widgetConfig.header.title}" placeholder="Chat Assistant">
2461
3204
  </div>
2462
3205
  <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}">
3206
+ <label>Online Status Text</label>
3207
+ <input type="text" id="onlineIndicatorText" value="${widgetConfig.header.onlineIndicatorText || 'Online'}" placeholder="Online">
2469
3208
  </div>
2470
3209
  <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>
3210
+ <label>Online Dot Color</label>
3211
+ <input type="color" id="onlineIndicatorDotColor" value="${widgetConfig.header.onlineIndicatorDotColor || '#10b981'}">
2490
3212
  </div>
2491
3213
  </div>
2492
3214
  `;
@@ -2532,7 +3254,7 @@
2532
3254
  <label>Offset Y (px)</label>
2533
3255
  <input type="number" id="positionOffsetY" value="${widgetConfig.position.offset.y}">
2534
3256
  </div>
2535
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3257
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2536
3258
  Position of the floating button and widget on the page.
2537
3259
  </p>
2538
3260
  </div>
@@ -2545,7 +3267,7 @@
2545
3267
  <option value="rtl" ${widgetConfig.direction === 'rtl' ? 'selected' : ''}>Right to Left (RTL)</option>
2546
3268
  </select>
2547
3269
  </div>
2548
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3270
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2549
3271
  Text direction for the widget. Use RTL for languages like Arabic or Hebrew.
2550
3272
  </p>
2551
3273
  </div>
@@ -2577,7 +3299,7 @@
2577
3299
  <label>Offset Y (px)</label>
2578
3300
  <input type="number" id="positionOffsetY" value="${widgetConfig.position.offset.y}">
2579
3301
  </div>
2580
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3302
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2581
3303
  Position of the floating button and widget on the page.
2582
3304
  </p>
2583
3305
  </div>
@@ -2594,7 +3316,7 @@
2594
3316
  <option value="rtl" ${widgetConfig.direction === 'rtl' ? 'selected' : ''}>Right to Left (RTL)</option>
2595
3317
  </select>
2596
3318
  </div>
2597
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3319
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2598
3320
  Text direction for the widget. Use RTL for languages like Arabic or Hebrew.
2599
3321
  </p>
2600
3322
  </div>
@@ -2621,17 +3343,17 @@
2621
3343
  <label>Agent Message Text Color</label>
2622
3344
  <input type="color" id="msgAgentTextColor" value="${widgetConfig.messages.agentTextColor || widgetConfig.messages.textColor || '#1F2937'}">
2623
3345
  </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>
3346
+ <div class="control-item" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(255,255,255,0.08);">
3347
+ <label style="font-weight: 600; color: #e2e8f0; margin-bottom: 8px; display: block;">Message Avatars</label>
2626
3348
  <div class="control-item">
2627
3349
  <label>User Avatar Icon</label>
2628
3350
  <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>
3351
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Emoji or text to display next to user messages</p>
2630
3352
  </div>
2631
3353
  <div class="control-item">
2632
3354
  <label>Agent Avatar Icon</label>
2633
3355
  <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>
3356
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Emoji or text to display next to agent messages</p>
2635
3357
  </div>
2636
3358
  </div>
2637
3359
  <div class="control-item">
@@ -2642,7 +3364,7 @@
2642
3364
  <label>Border Radius (px)</label>
2643
3365
  <input type="number" id="msgRadius" value="${widgetConfig.messages.borderRadius}">
2644
3366
  </div>
2645
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3367
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2646
3368
  Note: Message text content is controlled by your agent, not the widget configuration.
2647
3369
  </p>
2648
3370
  </div>
@@ -2804,7 +3526,7 @@
2804
3526
  <label>Font Size</label>
2805
3527
  <input type="text" id="liveTranscriptFontSize" value="${widgetConfig.voice.liveTranscriptFontSize || '14px'}" placeholder="14px">
2806
3528
  </div>
2807
- <p style="color: #6b7280; font-size: 12px; margin-top: 8px;">
3529
+ <p style="color: #64748b; font-size: 12px; margin-top: 8px;">
2808
3530
  This is the live transcript shown when history is collapsed. It displays only the current spoken text (max 2 lines).
2809
3531
  </p>
2810
3532
  </div>
@@ -2841,167 +3563,165 @@
2841
3563
  controlsHTML = `
2842
3564
  <div class="customization-group">
2843
3565
  <h3>Conversation History</h3>
2844
- <p style="color: #6b7280; font-size: 14px; margin-top: 8px;">
3566
+ <p style="color: #64748b; font-size: 14px; margin-top: 8px;">
2845
3567
  This is the expanded conversation history view showing all messages.
2846
3568
  </p>
2847
3569
  </div>
2848
3570
  `;
2849
3571
  break;
2850
- case 'agentAvatar':
3572
+ case 'heroAvatar':
2851
3573
  controlsHTML = `
2852
3574
  <div class="customization-group">
2853
- <h3>Agent Avatar (Next to Messages)</h3>
3575
+ <h3>Hero Avatar</h3>
3576
+ <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
3577
  <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="🤖">
3578
+ <label>Gradient Start Color</label>
3579
+ <input type="color" id="heroAvatarGrad1" value="${widgetConfig.voice?.avatarGradient1 || '#6d56f5'}">
2864
3580
  </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">
3581
+ <div class="control-item">
3582
+ <label>Gradient End Color</label>
3583
+ <input type="color" id="heroAvatarGrad2" value="${widgetConfig.voice?.avatarGradient2 || '#a78bfa'}">
2868
3584
  </div>
2869
3585
  <div class="control-item">
2870
- <label>Background Color</label>
2871
- <input type="color" id="agentAvatarBg" value="${widgetConfig.voice.avatarBackgroundColor}">
3586
+ <label>Online Dot Color</label>
3587
+ <input type="color" id="heroOnlineDotColor" value="${widgetConfig.voice?.onlineDotColor || '#22c55e'}">
2872
3588
  </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
3589
  </div>
2877
3590
  `;
2878
3591
  break;
2879
- case 'liveIndicator':
3592
+ case 'heroAgentName':
2880
3593
  controlsHTML = `
2881
3594
  <div class="customization-group">
2882
- <h3>Live Indicator</h3>
3595
+ <h3>Agent Name</h3>
3596
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The agent name shown in the hero header.</p>
2883
3597
  <div class="control-item">
2884
- <label>Live Dot Color</label>
2885
- <input type="color" id="liveDotColor" value="${widgetConfig.voice.liveIndicatorDotColor || '#10b981'}">
3598
+ <label>Name Text</label>
3599
+ <input type="text" id="heroAgentNameText" value="${widgetConfig.agentName || 'Sasha'}" placeholder="Sasha">
2886
3600
  </div>
2887
3601
  <div class="control-item">
2888
- <label>Live Text Color</label>
2889
- <input type="color" id="liveTextColor" value="${widgetConfig.voice.liveIndicatorTextColor || '#10b981'}">
3602
+ <label>Text Color</label>
3603
+ <input type="color" id="heroAgentNameColor" value="${widgetConfig.voice?.agentNameColor || '#f0eff8'}">
2890
3604
  </div>
2891
3605
  </div>
2892
3606
  `;
2893
3607
  break;
2894
- case 'landingLogo':
3608
+ case 'heroAgentRole':
2895
3609
  controlsHTML = `
2896
3610
  <div class="customization-group">
2897
- <h3>Landing Screen - Logo</h3>
3611
+ <h3>Agent Role</h3>
3612
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The subtitle under the agent name.</p>
2898
3613
  <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>
3614
+ <label>Role Text</label>
3615
+ <input type="text" id="heroAgentRoleText" value="${widgetConfig.voice?.agentRole || 'AI Voice Assistant'}" placeholder="AI Voice Assistant">
2904
3616
  </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="🤖">
3617
+ <div class="control-item">
3618
+ <label>Text Color</label>
3619
+ <input type="color" id="heroAgentRoleColor" value="${widgetConfig.voice?.agentRoleColor || '#594d80'}">
3620
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white.</p>
2908
3621
  </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">
3622
+ </div>
3623
+ `;
3624
+ break;
3625
+ case 'heroHeadline':
3626
+ controlsHTML = `
3627
+ <div class="customization-group">
3628
+ <h3>Hero Headline</h3>
3629
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The main greeting text in the hero.</p>
3630
+ <div class="control-item">
3631
+ <label>Headline Text</label>
3632
+ <input type="text" id="heroHeadlineText" value="${widgetConfig.voice?.headline || 'Hi there 👋'}" placeholder="Hi there 👋">
2912
3633
  </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>
3634
+ <div class="control-item">
3635
+ <label>Text Color</label>
3636
+ <input type="color" id="heroHeadlineColor" value="${widgetConfig.voice?.headlineColor || '#ffffff'}">
2928
3637
  </div>
2929
3638
  </div>
2930
3639
  `;
2931
3640
  break;
2932
- case 'landingTitle':
3641
+ case 'heroSubline':
2933
3642
  controlsHTML = `
2934
3643
  <div class="customization-group">
2935
- <h3>Landing Screen - Title</h3>
3644
+ <h3>Hero Subline</h3>
3645
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The description text below the headline.</p>
2936
3646
  <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">
3647
+ <label>Subline Text</label>
3648
+ <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
3649
  </div>
2940
3650
  <div class="control-item">
2941
- <label>Title Color</label>
2942
- <input type="color" id="landingTitleColor" value="${widgetConfig.landing.titleColor}">
3651
+ <label>Text Color</label>
3652
+ <input type="color" id="heroSublineColor" value="${widgetConfig.voice?.sublineColor || '#736b8a'}">
3653
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white.</p>
2943
3654
  </div>
2944
3655
  </div>
2945
3656
  `;
2946
3657
  break;
2947
- case 'landingSubtitle':
3658
+ case 'heroBackground':
2948
3659
  controlsHTML = `
2949
3660
  <div class="customization-group">
2950
- <h3>Landing Screen - Subtitle</h3>
3661
+ <h3>Hero Background</h3>
3662
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">The gradient background of the hero section.</p>
2951
3663
  <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">
3664
+ <label>Gradient Start Color</label>
3665
+ <input type="color" id="heroBgGrad1" value="${widgetConfig.voice?.heroGradient1 || '#2a2550'}">
2954
3666
  </div>
2955
3667
  <div class="control-item">
2956
- <label>Subtitle Color</label>
2957
- <input type="color" id="landingSubtitleColor" value="${widgetConfig.landing.subtitleColor}">
3668
+ <label>Gradient End Color</label>
3669
+ <input type="color" id="heroBgGrad2" value="${widgetConfig.voice?.heroGradient2 || '#1a1a2e'}">
2958
3670
  </div>
2959
3671
  </div>
2960
3672
  `;
2961
3673
  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
- }
3674
+ case 'heroPrimaryBtn':
2973
3675
  controlsHTML = `
2974
3676
  <div class="customization-group">
2975
- <h3>Landing Screen - Background</h3>
3677
+ <h3>Start Voice Call Button</h3>
3678
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Primary action button in the hero.</p>
2976
3679
  <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>
3680
+ <label>Button Text</label>
3681
+ <input type="text" id="heroPrimaryBtnText" value="${widgetConfig.voice?.startCallButtonText || 'Start Voice Call'}" placeholder="Start Voice Call">
3682
+ </div>
3683
+ <div class="control-item">
3684
+ <label>Gradient Start Color</label>
3685
+ <input type="color" id="heroPrimaryBtnGrad1" value="${widgetConfig.voice?.primaryBtnGradient1 || '#6d56f5'}">
3686
+ </div>
3687
+ <div class="control-item">
3688
+ <label>Gradient End Color</label>
3689
+ <input type="color" id="heroPrimaryBtnGrad2" value="${widgetConfig.voice?.primaryBtnGradient2 || '#9d8df8'}">
3690
+ </div>
3691
+ <div class="control-item">
3692
+ <label>Text Color</label>
3693
+ <input type="color" id="heroPrimaryBtnTextColor" value="${widgetConfig.voice?.startCallButtonTextColor || '#ffffff'}">
2982
3694
  </div>
2983
3695
  </div>
2984
3696
  `;
2985
3697
  break;
2986
- case 'modeCard':
3698
+ case 'heroSecondaryBtn':
2987
3699
  controlsHTML = `
2988
3700
  <div class="customization-group">
2989
- <h3>Mode Cards (Voice/Text Buttons)</h3>
3701
+ <h3>Send a Message Button</h3>
3702
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Secondary action button in the hero.</p>
2990
3703
  <div class="control-item">
2991
- <label>Voice Card Title</label>
2992
- <input type="text" id="voiceCardTitle" value="Voice Call" placeholder="Voice Call">
3704
+ <label>Button Text</label>
3705
+ <input type="text" id="heroSecondaryBtnText" value="${widgetConfig.voice?.sendMessageText || 'Send a Message'}" placeholder="Send a Message">
2993
3706
  </div>
2994
3707
  <div class="control-item">
2995
- <label>Text Card Title</label>
2996
- <input type="text" id="textCardTitle" value="Text Chat" placeholder="Text Chat">
3708
+ <label>Background Color</label>
3709
+ <input type="color" id="heroSecondaryBtnBg" value="${widgetConfig.voice?.secondaryBtnBg || '#1a1a2e'}">
3710
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is semi-transparent white overlay.</p>
2997
3711
  </div>
2998
3712
  <div class="control-item">
2999
- <label>Background Color</label>
3000
- <input type="color" id="modeCardBg" value="${widgetConfig.landing.modeCardBackgroundColor}">
3713
+ <label>Text Color</label>
3714
+ <input type="color" id="heroSecondaryBtnTextColor" value="${widgetConfig.voice?.secondaryBtnTextColor || '#9994ad'}">
3715
+ <p style="color: #64748b; font-size: 11px; margin-top: 4px;">Default is muted white.</p>
3001
3716
  </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>
3717
+ </div>
3718
+ `;
3719
+ break;
3720
+ case 'closeButton':
3721
+ controlsHTML = `
3722
+ <div class="customization-group">
3723
+ <h3>Close Button</h3>
3724
+ <p style="color: #64748b; font-size: 12px; margin-bottom: 12px;">Closes the widget panel. Double-click to test the interaction.</p>
3005
3725
  </div>
3006
3726
  `;
3007
3727
  break;
@@ -3009,12 +3729,9 @@
3009
3729
  controlsHTML = `
3010
3730
  <div class="customization-group">
3011
3731
  <h3>Select an Element</h3>
3012
- <p style="color: #6b7280; font-size: 14px; margin-top: 8px;">
3732
+ <p style="color: #64748b; font-size: 13px; margin-top: 8px;">
3013
3733
  Click on any widget element in the preview to start customizing.
3014
3734
  </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
3735
  </div>
3019
3736
  `;
3020
3737
  }
@@ -3044,20 +3761,15 @@
3044
3761
  const controlsDiv = document.getElementById('customizationControls');
3045
3762
  if (!controlsDiv) return;
3046
3763
 
3047
- // Button controls
3764
+ // Button controls (Pill Launcher)
3048
3765
  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;
3766
+ document.getElementById('pillTitle')?.addEventListener('input', (e) => {
3767
+ widgetConfig.header.title = e.target.value;
3056
3768
  applyButtonStyles(document.getElementById('mockButton'));
3057
3769
  updateConfigCode();
3058
3770
  });
3059
- document.getElementById('btnBgColor')?.addEventListener('input', (e) => {
3060
- widgetConfig.button.backgroundColor = e.target.value;
3771
+ document.getElementById('pillStatusText')?.addEventListener('input', (e) => {
3772
+ widgetConfig.header.onlineIndicatorText = e.target.value;
3061
3773
  applyButtonStyles(document.getElementById('mockButton'));
3062
3774
  updateConfigCode();
3063
3775
  });
@@ -3149,37 +3861,17 @@
3149
3861
  });
3150
3862
  }
3151
3863
 
3152
- // Header controls (also applies to onlineIndicator)
3864
+ // Header / Widget Identity controls
3153
3865
  if (elementType === 'header' || elementType === 'onlineIndicator') {
3154
3866
  document.getElementById('headerTitle')?.addEventListener('input', (e) => {
3155
3867
  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;
3868
+ applyButtonStyles(document.getElementById('mockButton'));
3173
3869
  renderPanelContent();
3174
3870
  updateConfigCode();
3175
3871
  });
3176
3872
  document.getElementById('onlineIndicatorText')?.addEventListener('input', (e) => {
3177
3873
  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;
3874
+ applyButtonStyles(document.getElementById('mockButton'));
3183
3875
  renderPanelContent();
3184
3876
  updateConfigCode();
3185
3877
  });
@@ -3354,6 +4046,157 @@
3354
4046
  });
3355
4047
  }
3356
4048
 
4049
+ // Hero Avatar controls
4050
+ if (elementType === 'heroAvatar') {
4051
+ document.getElementById('heroAvatarGrad1')?.addEventListener('input', (e) => {
4052
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4053
+ widgetConfig.voice.avatarGradient1 = e.target.value;
4054
+ renderPanelContent();
4055
+ updateConfigCode();
4056
+ });
4057
+ document.getElementById('heroAvatarGrad2')?.addEventListener('input', (e) => {
4058
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4059
+ widgetConfig.voice.avatarGradient2 = e.target.value;
4060
+ renderPanelContent();
4061
+ updateConfigCode();
4062
+ });
4063
+ document.getElementById('heroOnlineDotColor')?.addEventListener('input', (e) => {
4064
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4065
+ widgetConfig.voice.onlineDotColor = e.target.value;
4066
+ renderPanelContent();
4067
+ updateConfigCode();
4068
+ });
4069
+ }
4070
+
4071
+ // Hero Agent Name controls
4072
+ if (elementType === 'heroAgentName') {
4073
+ document.getElementById('heroAgentNameText')?.addEventListener('input', (e) => {
4074
+ widgetConfig.agentName = e.target.value;
4075
+ renderPanelContent();
4076
+ updateConfigCode();
4077
+ });
4078
+ document.getElementById('heroAgentNameColor')?.addEventListener('input', (e) => {
4079
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4080
+ widgetConfig.voice.agentNameColor = e.target.value;
4081
+ renderPanelContent();
4082
+ updateConfigCode();
4083
+ });
4084
+ }
4085
+
4086
+ // Hero Agent Role controls
4087
+ if (elementType === 'heroAgentRole') {
4088
+ document.getElementById('heroAgentRoleText')?.addEventListener('input', (e) => {
4089
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4090
+ widgetConfig.voice.agentRole = e.target.value;
4091
+ renderPanelContent();
4092
+ updateConfigCode();
4093
+ });
4094
+ document.getElementById('heroAgentRoleColor')?.addEventListener('input', (e) => {
4095
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4096
+ widgetConfig.voice.agentRoleColor = e.target.value;
4097
+ renderPanelContent();
4098
+ updateConfigCode();
4099
+ });
4100
+ }
4101
+
4102
+ // Hero Headline controls
4103
+ if (elementType === 'heroHeadline') {
4104
+ document.getElementById('heroHeadlineText')?.addEventListener('input', (e) => {
4105
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4106
+ widgetConfig.voice.headline = e.target.value;
4107
+ renderPanelContent();
4108
+ updateConfigCode();
4109
+ });
4110
+ document.getElementById('heroHeadlineColor')?.addEventListener('input', (e) => {
4111
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4112
+ widgetConfig.voice.headlineColor = e.target.value;
4113
+ renderPanelContent();
4114
+ updateConfigCode();
4115
+ });
4116
+ }
4117
+
4118
+ // Hero Subline controls
4119
+ if (elementType === 'heroSubline') {
4120
+ document.getElementById('heroSublineText')?.addEventListener('input', (e) => {
4121
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4122
+ widgetConfig.voice.subline = e.target.value;
4123
+ renderPanelContent();
4124
+ updateConfigCode();
4125
+ });
4126
+ document.getElementById('heroSublineColor')?.addEventListener('input', (e) => {
4127
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4128
+ widgetConfig.voice.sublineColor = e.target.value;
4129
+ renderPanelContent();
4130
+ updateConfigCode();
4131
+ });
4132
+ }
4133
+
4134
+ // Hero Background controls
4135
+ if (elementType === 'heroBackground') {
4136
+ document.getElementById('heroBgGrad1')?.addEventListener('input', (e) => {
4137
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4138
+ widgetConfig.voice.heroGradient1 = e.target.value;
4139
+ renderPanelContent();
4140
+ updateConfigCode();
4141
+ });
4142
+ document.getElementById('heroBgGrad2')?.addEventListener('input', (e) => {
4143
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4144
+ widgetConfig.voice.heroGradient2 = e.target.value;
4145
+ renderPanelContent();
4146
+ updateConfigCode();
4147
+ });
4148
+ }
4149
+
4150
+ // Hero Primary Button (Start Voice Call) controls
4151
+ if (elementType === 'heroPrimaryBtn') {
4152
+ document.getElementById('heroPrimaryBtnText')?.addEventListener('input', (e) => {
4153
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4154
+ widgetConfig.voice.startCallButtonText = e.target.value;
4155
+ renderPanelContent();
4156
+ updateConfigCode();
4157
+ });
4158
+ document.getElementById('heroPrimaryBtnGrad1')?.addEventListener('input', (e) => {
4159
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4160
+ widgetConfig.voice.primaryBtnGradient1 = e.target.value;
4161
+ renderPanelContent();
4162
+ updateConfigCode();
4163
+ });
4164
+ document.getElementById('heroPrimaryBtnGrad2')?.addEventListener('input', (e) => {
4165
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4166
+ widgetConfig.voice.primaryBtnGradient2 = e.target.value;
4167
+ renderPanelContent();
4168
+ updateConfigCode();
4169
+ });
4170
+ document.getElementById('heroPrimaryBtnTextColor')?.addEventListener('input', (e) => {
4171
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4172
+ widgetConfig.voice.startCallButtonTextColor = e.target.value;
4173
+ renderPanelContent();
4174
+ updateConfigCode();
4175
+ });
4176
+ }
4177
+
4178
+ // Hero Secondary Button (Send a Message) controls
4179
+ if (elementType === 'heroSecondaryBtn') {
4180
+ document.getElementById('heroSecondaryBtnText')?.addEventListener('input', (e) => {
4181
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4182
+ widgetConfig.voice.sendMessageText = e.target.value;
4183
+ renderPanelContent();
4184
+ updateConfigCode();
4185
+ });
4186
+ document.getElementById('heroSecondaryBtnBg')?.addEventListener('input', (e) => {
4187
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4188
+ widgetConfig.voice.secondaryBtnBg = e.target.value;
4189
+ renderPanelContent();
4190
+ updateConfigCode();
4191
+ });
4192
+ document.getElementById('heroSecondaryBtnTextColor')?.addEventListener('input', (e) => {
4193
+ if (!widgetConfig.voice) widgetConfig.voice = {};
4194
+ widgetConfig.voice.secondaryBtnTextColor = e.target.value;
4195
+ renderPanelContent();
4196
+ updateConfigCode();
4197
+ });
4198
+ }
4199
+
3357
4200
  // Mic button controls
3358
4201
  if (elementType === 'micButton') {
3359
4202
  document.getElementById('micBtnColor')?.addEventListener('input', (e) => {
@@ -3663,6 +4506,7 @@
3663
4506
 
3664
4507
  // Default configuration values (used to compare and only show changed values)
3665
4508
  const defaultConfig = {
4509
+ agentName: 'Sasha',
3666
4510
  direction: 'ltr',
3667
4511
  button: {
3668
4512
  size: 'medium',
@@ -3679,11 +4523,11 @@
3679
4523
  backgroundColor: '#FFFFFF'
3680
4524
  },
3681
4525
  panel: {
3682
- width: 360,
4526
+ width: 340,
3683
4527
  height: 550,
3684
- borderRadius: 24,
3685
- backgroundColor: '#FFFFFF',
3686
- border: '1px solid #E5E7EB'
4528
+ borderRadius: 20,
4529
+ backgroundColor: '#16161e',
4530
+ border: '1px solid rgba(255,255,255,0.08)'
3687
4531
  },
3688
4532
  position: {
3689
4533
  vertical: 'bottom',
@@ -3718,6 +4562,9 @@
3718
4562
  inputFocusColor: '#7C3AED'
3719
4563
  },
3720
4564
  voice: {
4565
+ agentRole: 'AI Voice Assistant',
4566
+ headline: 'Hi there 👋',
4567
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
3721
4568
  micButtonColor: '#7C3AED',
3722
4569
  micButtonActiveColor: '#EF4444',
3723
4570
  speakerButtonColor: '#FFFFFF',
@@ -3726,7 +4573,7 @@
3726
4573
  avatarType: 'icon',
3727
4574
  avatarIcon: '🤖',
3728
4575
  avatarImageUrl: '',
3729
- startCallButtonText: 'Start Call',
4576
+ startCallButtonText: 'Start Voice Call',
3730
4577
  startCallButtonColor: '#667eea',
3731
4578
  startCallButtonTextColor: '#FFFFFF',
3732
4579
  statusTitleColor: '#1e293b',
@@ -3739,7 +4586,26 @@
3739
4586
  liveIndicatorTextColor: '#10b981',
3740
4587
  waveformType: 'waveform',
3741
4588
  waveformIcon: '🎤',
3742
- waveformImageUrl: ''
4589
+ waveformImageUrl: '',
4590
+ waveformBarColor: '#7C3AED',
4591
+ pillGradient: '',
4592
+ pillTextColor: '#ffffff',
4593
+ pillDotColor: '#4ade80',
4594
+ avatarGradient1: '#6d56f5',
4595
+ avatarGradient2: '#a78bfa',
4596
+ onlineDotColor: '#22c55e',
4597
+ heroGradient1: '#2a2550',
4598
+ heroGradient2: '#1a1a2e',
4599
+ agentNameColor: '#f0eff8',
4600
+ agentRoleColor: 'rgba(255,255,255,0.35)',
4601
+ headlineColor: '#ffffff',
4602
+ sublineColor: 'rgba(255,255,255,0.45)',
4603
+ primaryBtnGradient1: '#6d56f5',
4604
+ primaryBtnGradient2: '#9d8df8',
4605
+ secondaryBtnBg: 'rgba(255,255,255,0.05)',
4606
+ secondaryBtnBorder: 'rgba(255,255,255,0.09)',
4607
+ secondaryBtnTextColor: 'rgba(255,255,255,0.6)',
4608
+ sendMessageText: 'Send a Message'
3743
4609
  },
3744
4610
  landing: {
3745
4611
  backgroundColor: 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)',
@@ -4035,6 +4901,9 @@
4035
4901
 
4036
4902
  // Remove widget elements from DOM (multiple possible selectors)
4037
4903
  const selectors = [
4904
+ '#ttp-widget-shadow-host',
4905
+ '#ttp-widget-container',
4906
+ '#ttp-widget-styles',
4038
4907
  '[id^="ttp-chat-widget-button"]',
4039
4908
  '[id^="ttp-chat-widget-panel"]',
4040
4909
  '[id*="ttp-chat"]',
@@ -4164,13 +5033,208 @@
4164
5033
  isInitializing = false;
4165
5034
  }
4166
5035
 
5036
+ const themePresets = {
5037
+ default: {
5038
+ direction: 'ltr',
5039
+ agentName: 'Sasha',
5040
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5041
+ panel: { backgroundColor: '#16161e', border: '1px solid rgba(255,255,255,0.08)' },
5042
+ voice: {
5043
+ pillGradient: '',
5044
+ pillTextColor: '#ffffff',
5045
+ pillDotColor: '#4ade80',
5046
+ avatarGradient1: '#6d56f5', avatarGradient2: '#a78bfa',
5047
+ onlineDotColor: '#22c55e',
5048
+ heroGradient1: '#2a2550', heroGradient2: '#1a1a2e',
5049
+ agentNameColor: '#f0eff8',
5050
+ agentRoleColor: 'rgba(255,255,255,0.35)',
5051
+ headlineColor: '#ffffff',
5052
+ sublineColor: 'rgba(255,255,255,0.45)',
5053
+ primaryBtnGradient1: '#6d56f5', primaryBtnGradient2: '#9d8df8',
5054
+ startCallButtonTextColor: '#FFFFFF',
5055
+ startCallButtonText: 'Start Voice Call',
5056
+ sendMessageText: 'Send a Message',
5057
+ secondaryBtnBg: 'rgba(255,255,255,0.05)',
5058
+ secondaryBtnBorder: 'rgba(255,255,255,0.09)',
5059
+ secondaryBtnTextColor: 'rgba(255,255,255,0.6)',
5060
+ agentRole: 'AI Voice Assistant',
5061
+ headline: 'Hi there 👋',
5062
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5063
+ waveformBarColor: '#7C3AED',
5064
+ micButtonColor: '#7C3AED',
5065
+ speakerButtonColor: '#FFFFFF',
5066
+ endCallButtonColor: '#ef4444'
5067
+ }
5068
+ },
5069
+ light: {
5070
+ direction: 'ltr',
5071
+ agentName: 'Sasha',
5072
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5073
+ panel: { backgroundColor: '#ffffff', border: '1px solid rgba(0,0,0,0.06)' },
5074
+ voice: {
5075
+ // Pill launcher
5076
+ pillGradient: 'linear-gradient(135deg, #7c3aed, #6d28d9)',
5077
+ pillTextColor: '#ffffff',
5078
+ pillDotColor: '#4ade80',
5079
+ // Hero idle screen
5080
+ avatarGradient1: '#7c3aed', avatarGradient2: '#a78bfa',
5081
+ onlineDotColor: '#22c55e',
5082
+ heroGradient1: '#ede9fe', heroGradient2: '#f5f3ff',
5083
+ agentNameColor: '#1e1b4b',
5084
+ agentRoleColor: '#7c7c8a',
5085
+ headlineColor: '#1e1b4b',
5086
+ sublineColor: '#6b7280',
5087
+ primaryBtnGradient1: '#7c3aed', primaryBtnGradient2: '#a78bfa',
5088
+ startCallButtonTextColor: '#ffffff',
5089
+ startCallButtonText: 'Start Voice Call',
5090
+ sendMessageText: 'Send a Message',
5091
+ secondaryBtnBg: '#f5f3ff',
5092
+ secondaryBtnBorder: 'rgba(124,58,237,0.15)',
5093
+ secondaryBtnTextColor: '#6d28d9',
5094
+ agentRole: 'AI Voice Assistant',
5095
+ headline: 'Hi there 👋',
5096
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5097
+ // Voice call view
5098
+ waveformBarColor: '#8b5cf6',
5099
+ micButtonColor: '#f5f3ff',
5100
+ speakerButtonColor: '#f5f3ff',
5101
+ endCallButtonColor: '#ef4444'
5102
+ }
5103
+ },
5104
+ hebrew: {
5105
+ direction: 'rtl',
5106
+ agentName: 'שרה',
5107
+ header: { title: 'עוזרת חכמה', onlineIndicatorText: 'מחוברת' },
5108
+ panel: { backgroundColor: '#0f172a', border: '1px solid rgba(59,130,246,0.12)' },
5109
+ voice: {
5110
+ pillGradient: 'linear-gradient(135deg, #1e3a5f, #1e40af, #0f172a)',
5111
+ pillTextColor: '#ffffff',
5112
+ pillDotColor: '#34d399',
5113
+ avatarGradient1: '#3b82f6', avatarGradient2: '#1d4ed8',
5114
+ onlineDotColor: '#34d399',
5115
+ heroGradient1: '#1a2744', heroGradient2: '#0f172a',
5116
+ agentNameColor: '#e0e7ff',
5117
+ agentRoleColor: 'rgba(191,219,254,0.4)',
5118
+ headlineColor: '#f0f4ff',
5119
+ sublineColor: 'rgba(191,219,254,0.5)',
5120
+ primaryBtnGradient1: '#3b82f6', primaryBtnGradient2: '#1d4ed8',
5121
+ startCallButtonTextColor: '#ffffff',
5122
+ startCallButtonText: 'התחל שיחה קולית',
5123
+ sendMessageText: 'שלח הודעה',
5124
+ secondaryBtnBg: 'rgba(59,130,246,0.08)',
5125
+ secondaryBtnBorder: 'rgba(59,130,246,0.18)',
5126
+ secondaryBtnTextColor: 'rgba(147,197,253,0.7)',
5127
+ agentRole: 'עוזרת קולית חכמה',
5128
+ headline: 'היי, מה שלומך? 👋',
5129
+ subline: 'שאל/י אותי הכל — אני עונה<br>מיידית בקול או בטקסט.',
5130
+ waveformBarColor: '#3b82f6',
5131
+ micButtonColor: 'rgba(255,255,255,0.9)',
5132
+ speakerButtonColor: 'rgba(255,255,255,0.9)',
5133
+ endCallButtonColor: '#ef4444'
5134
+ }
5135
+ },
5136
+ sunset: {
5137
+ direction: 'ltr',
5138
+ agentName: 'Sasha',
5139
+ header: { title: 'Chat Assistant', onlineIndicatorText: 'Online' },
5140
+ panel: { backgroundColor: '#140a1e', border: '1px solid rgba(249,115,22,0.12)' },
5141
+ voice: {
5142
+ // Pill launcher
5143
+ pillGradient: 'linear-gradient(135deg, #9f1239, #7c2d12, #581c87)',
5144
+ pillTextColor: '#ffffff',
5145
+ pillDotColor: '#fb923c',
5146
+ // Hero idle screen
5147
+ avatarGradient1: '#f97316', avatarGradient2: '#ec4899',
5148
+ onlineDotColor: '#f59e0b',
5149
+ heroGradient1: '#4a1942', heroGradient2: '#1a0a2e',
5150
+ agentNameColor: '#fde8d0',
5151
+ agentRoleColor: 'rgba(255,200,160,0.45)',
5152
+ headlineColor: '#fff1e6',
5153
+ sublineColor: 'rgba(255,200,160,0.55)',
5154
+ primaryBtnGradient1: '#f97316', primaryBtnGradient2: '#ec4899',
5155
+ startCallButtonTextColor: '#ffffff',
5156
+ startCallButtonText: 'Start Voice Call',
5157
+ sendMessageText: 'Send a Message',
5158
+ secondaryBtnBg: 'rgba(249,115,22,0.08)',
5159
+ secondaryBtnBorder: 'rgba(249,115,22,0.18)',
5160
+ secondaryBtnTextColor: 'rgba(255,180,130,0.7)',
5161
+ agentRole: 'AI Voice Assistant',
5162
+ headline: 'Hi there 👋',
5163
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
5164
+ // Voice call view
5165
+ waveformBarColor: '#f97316',
5166
+ micButtonColor: 'rgba(255,255,255,0.9)',
5167
+ speakerButtonColor: 'rgba(255,255,255,0.9)',
5168
+ endCallButtonColor: '#e11d48'
5169
+ }
5170
+ },
5171
+ sasha: {
5172
+ direction: 'rtl',
5173
+ agentName: 'סשה',
5174
+ header: { title: 'S-Law | ייעוץ משפטי', onlineIndicatorText: 'מקוונת' },
5175
+ panel: { backgroundColor: '#f8f5ef', border: '1px solid rgba(196,162,101,0.18)' },
5176
+ voice: {
5177
+ pillGradient: 'linear-gradient(135deg, #c4a265, #9e7e4f)',
5178
+ pillTextColor: '#ffffff',
5179
+ pillDotColor: '#22c55e',
5180
+ avatarGradient1: '#c4a265', avatarGradient2: '#9e7e4f',
5181
+ onlineDotColor: '#22c55e',
5182
+ heroGradient1: '#f8f5ef', heroGradient2: '#ebe6de',
5183
+ agentNameColor: '#1e293b',
5184
+ agentRoleColor: '#78716c',
5185
+ headlineColor: '#1e293b',
5186
+ sublineColor: '#6b7280',
5187
+ primaryBtnGradient1: '#c4a265', primaryBtnGradient2: '#9e7e4f',
5188
+ startCallButtonTextColor: '#ffffff',
5189
+ startCallButtonText: 'התחל שיחה קולית',
5190
+ sendMessageText: 'שלח הודעה',
5191
+ secondaryBtnBg: 'rgba(196,162,101,0.08)',
5192
+ secondaryBtnBorder: 'rgba(196,162,101,0.2)',
5193
+ secondaryBtnTextColor: '#9e7e4f',
5194
+ agentRole: 'עורכת דין | S-Law',
5195
+ headline: 'שלום, אני סשה 👋',
5196
+ subline: 'אני כאן לעזור בכל שאלה משפטית —<br>דיני עבודה ומשפט מסחרי.',
5197
+ waveformBarColor: '#c4a265',
5198
+ micButtonColor: '#1e293b',
5199
+ speakerButtonColor: '#1e293b',
5200
+ endCallButtonColor: '#ef4444'
5201
+ }
5202
+ }
5203
+ };
5204
+
5205
+ let activeTheme = 'default';
5206
+
5207
+ function applyTheme(themeName) {
5208
+ const theme = themePresets[themeName];
5209
+ if (!theme) return;
5210
+ activeTheme = themeName;
5211
+
5212
+ Object.assign(widgetConfig.panel, theme.panel);
5213
+ Object.assign(widgetConfig.voice, theme.voice);
5214
+ if (theme.direction !== undefined) widgetConfig.direction = theme.direction;
5215
+ if (theme.agentName !== undefined) widgetConfig.agentName = theme.agentName;
5216
+ if (theme.header) Object.assign(widgetConfig.header, theme.header);
5217
+
5218
+ document.querySelectorAll('.theme-card').forEach(c => c.classList.remove('active'));
5219
+ const card = document.querySelector(`.theme-card[data-theme="${themeName}"]`);
5220
+ if (card) card.classList.add('active');
5221
+
5222
+ applyButtonStyles(document.getElementById('mockButton'));
5223
+ renderPanelContent();
5224
+ updateConfigCode();
5225
+
5226
+ const sel = selectedElement;
5227
+ if (sel) showCustomizationControls(sel);
5228
+ }
5229
+
4167
5230
  function resetToDefaults() {
4168
5231
  widgetConfig = {
5232
+ agentName: 'Sasha',
4169
5233
  button: {
4170
5234
  size: 'medium',
4171
5235
  shape: 'circle',
4172
5236
  backgroundColor: '#FFFFFF',
4173
- hoverColor: '#D3D3D3', // SDK default: light gray
5237
+ hoverColor: '#D3D3D3',
4174
5238
  shadow: true,
4175
5239
  shadowColor: 'rgba(0,0,0,0.15)'
4176
5240
  },
@@ -4181,11 +5245,11 @@
4181
5245
  backgroundColor: '#FFFFFF'
4182
5246
  },
4183
5247
  panel: {
4184
- width: 360,
4185
- height: 550, // Updated from SDK default 500
4186
- borderRadius: 24,
4187
- backgroundColor: '#FFFFFF',
4188
- border: '1px solid #E5E7EB'
5248
+ width: 340,
5249
+ height: 550,
5250
+ borderRadius: 20,
5251
+ backgroundColor: '#16161e',
5252
+ border: '1px solid rgba(255,255,255,0.08)'
4189
5253
  },
4190
5254
  direction: 'ltr',
4191
5255
  position: {
@@ -4205,7 +5269,7 @@
4205
5269
  messages: {
4206
5270
  userBackgroundColor: '#E5E7EB',
4207
5271
  agentBackgroundColor: '#F3F4F6',
4208
- textColor: '#1F2937', // Fallback for backward compatibility
5272
+ textColor: '#1F2937',
4209
5273
  userTextColor: '#1F2937',
4210
5274
  agentTextColor: '#1F2937',
4211
5275
  userAvatarIcon: '👤',
@@ -4221,6 +5285,9 @@
4221
5285
  inputFocusColor: '#7C3AED'
4222
5286
  },
4223
5287
  voice: {
5288
+ agentRole: 'AI Voice Assistant',
5289
+ headline: 'Hi there 👋',
5290
+ subline: 'Ask me anything — I respond instantly<br>in voice or text.',
4224
5291
  micButtonColor: '#7C3AED',
4225
5292
  micButtonActiveColor: '#EF4444',
4226
5293
  speakerButtonColor: '#FFFFFF',
@@ -4229,7 +5296,7 @@
4229
5296
  avatarType: 'icon',
4230
5297
  avatarIcon: '🤖',
4231
5298
  avatarImageUrl: '',
4232
- startCallButtonText: 'Start Call',
5299
+ startCallButtonText: 'Start Voice Call',
4233
5300
  startCallButtonColor: '#667eea',
4234
5301
  startCallButtonTextColor: '#FFFFFF',
4235
5302
  statusTitleColor: '#1e293b',
@@ -4242,7 +5309,11 @@
4242
5309
  liveIndicatorTextColor: '#10b981',
4243
5310
  waveformType: 'waveform',
4244
5311
  waveformIcon: '🎤',
4245
- waveformImageUrl: ''
5312
+ waveformImageUrl: '',
5313
+ waveformBarColor: '#7C3AED',
5314
+ pillGradient: '',
5315
+ pillTextColor: '#ffffff',
5316
+ pillDotColor: '#4ade80'
4246
5317
  },
4247
5318
  landing: {
4248
5319
  logo: '🤖',
@@ -4262,6 +5333,11 @@
4262
5333
  }
4263
5334
  };
4264
5335
 
5336
+ activeTheme = 'default';
5337
+ document.querySelectorAll('.theme-card').forEach(c => c.classList.remove('active'));
5338
+ const defCard = document.querySelector('.theme-card[data-theme="default"]');
5339
+ if (defCard) defCard.classList.add('active');
5340
+
4265
5341
  initMockWidget();
4266
5342
  updateMockWidgetPosition();
4267
5343
  updateConfigCode();
@@ -4275,6 +5351,11 @@
4275
5351
  // No edit mode toggle needed - single click = edit, double click = interact
4276
5352
 
4277
5353
  // Initialize
5354
+ document.getElementById('themeDefault').addEventListener('click', () => applyTheme('default'));
5355
+ document.getElementById('themeLight').addEventListener('click', () => applyTheme('light'));
5356
+ document.getElementById('themeSunset').addEventListener('click', () => applyTheme('sunset'));
5357
+ document.getElementById('themeHebrew').addEventListener('click', () => applyTheme('hebrew'));
5358
+ document.getElementById('themeSasha').addEventListener('click', () => applyTheme('sasha'));
4278
5359
  document.getElementById('resetBtn').addEventListener('click', resetToDefaults);
4279
5360
  document.getElementById('togglePanelBtn').addEventListener('click', () => {
4280
5361
  panelOpen = !panelOpen;