@oxvo/ai-live-assist 7.4.36 → 7.4.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/ui.js CHANGED
@@ -16,6 +16,7 @@ const CAPTION_HEIGHT_GLIDE_MS = 250;
16
16
  const ASSISTANT_READY_VISUAL_GRACE_MS = 1200;
17
17
  const FEEDBACK_EXIT_FADE_MS = 180;
18
18
  const AMBIENT_IDLE_GRACE_MS = 700;
19
+ const VOICE_CARD_EFFECT_SETTLE_MS = 720;
19
20
  const OMAGO_SOURCE_CONTENT_FADE_MS = 16;
20
21
  const OMAGO_BOX_IN_HOLD_MS = 130;
21
22
  const OMAGO_BOX_IN_GEOMETRY_MS = 550;
@@ -79,6 +80,21 @@ const style = `
79
80
  --glass-control-border: rgba(255, 255, 255, .76);
80
81
  --conversation-bubble-background: #fff;
81
82
  --conversation-bubble-text: #3a3542;
83
+ --conversation-bubble-shadow: 0 2px 10px rgba(103, 42, 150, .06);
84
+ --caption-background: rgba(255, 255, 255, .82);
85
+ --caption-border: rgba(255, 255, 255, .65);
86
+ --caption-text: #17151b;
87
+ --prompt-pill-background: #1d1031;
88
+ --prompt-pill-border: #3c2359;
89
+ --prompt-pill-text: #ecdffa;
90
+ --input-material-background: #010201;
91
+ --glass-highlight: rgba(255, 255, 255, .65);
92
+ --glass-highlight-subtle: rgba(255, 255, 255, .64);
93
+ --glass-highlight-strong: rgba(255, 255, 255, .8);
94
+ --glass-highlight-terminal: rgba(255, 255, 255, .72);
95
+ --danger-control-text: #9d2947;
96
+ --danger-control-background: rgba(255, 245, 248, .7);
97
+ --danger-control-border: rgba(196, 87, 117, .24);
82
98
  --soft-surface-background: rgba(255, 255, 255, .48);
83
99
  --soft-surface-border: rgba(255, 255, 255, .72);
84
100
  --soft-surface-strong-background: rgba(255, 255, 255, .58);
@@ -86,6 +102,10 @@ const style = `
86
102
  linear-gradient(145deg, rgba(255, 255, 255, .94), rgba(250, 244, 252, .88));
87
103
  --dialog-surface-border: rgba(255, 255, 255, .86);
88
104
  --mode-active-background: #fff;
105
+ --non-iridescent-panel-background: #f7f4f8;
106
+ --non-iridescent-panel-border: #d9d4dc;
107
+ --non-iridescent-panel-shadow: 0 12px 28px rgba(15, 23, 42, .16);
108
+ --brand-mark-border: rgba(255, 255, 255, .8);
89
109
  --surface-material-plane: 0;
90
110
  --surface-content-plane: 10;
91
111
  --skel: rgba(255, 255, 255, .55);
@@ -93,50 +113,95 @@ const style = `
93
113
  }
94
114
  :host([data-theme="dark"]) {
95
115
  color-scheme: dark;
96
- --assist-text: #f6f1f8;
97
- --assist-muted: #b9b0bf;
98
- --assist-border: rgba(255, 255, 255, .12);
99
- --assist-surface: #17131b;
100
- --assist-surface-muted: #201a25;
101
- --conversation-glass-background: rgba(28, 22, 34, .7);
102
- --conversation-glass-border: 1px solid rgba(255, 255, 255, .12);
116
+ --assist-text: #f2edf8;
117
+ --assist-muted: #9c92ad;
118
+ --assist-border: rgba(255, 255, 255, .08);
119
+ --assist-surface: #150a22;
120
+ --assist-surface-muted: #1d102e;
121
+ --conversation-glass-background: rgba(255, 255, 255, .05);
122
+ --conversation-glass-border: 1px solid rgba(255, 255, 255, .16);
103
123
  --expanded-panel-background:
104
- radial-gradient(72% 48% at 50% 45%, rgba(116, 82, 136, .2), transparent 72%),
105
- linear-gradient(
106
- 168deg,
107
- color-mix(in srgb, var(--accent) 8%, #211a26) 0%,
108
- color-mix(in srgb, var(--accent) 12%, #1b151f) 48%,
109
- color-mix(in srgb, var(--accent) 15%, #141017) 100%
110
- );
111
- --expanded-panel-border: rgba(255, 255, 255, .12);
124
+ radial-gradient(65% 42% at 52% 46%, rgba(168, 85, 247, .13), rgba(255, 255, 255, 0) 70%),
125
+ linear-gradient(168deg, #271741 0%, #1d102e 45%, #150a22 100%);
126
+ --expanded-panel-border: rgba(255, 255, 255, .08);
112
127
  --expanded-panel-shadow:
113
- 0 24px 70px rgba(4, 2, 8, .48),
114
- 0 4px 16px color-mix(in srgb, var(--accent) 15%, transparent);
115
- --glass-control-background: rgba(34, 27, 40, .72);
116
- --glass-control-border: rgba(255, 255, 255, .13);
117
- --conversation-bubble-background: rgba(31, 25, 36, .94);
118
- --conversation-bubble-text: #f3eef6;
119
- --soft-surface-background: rgba(31, 24, 37, .68);
120
- --soft-surface-border: rgba(255, 255, 255, .12);
121
- --soft-surface-strong-background: rgba(38, 30, 45, .82);
128
+ 0 24px 70px rgba(0, 0, 0, .55),
129
+ 0 4px 14px rgba(0, 0, 0, .3);
130
+ --glass-control-background: rgba(255, 255, 255, .05);
131
+ --glass-control-border: rgba(255, 255, 255, .12);
132
+ --conversation-bubble-background: #2a1c3e;
133
+ --conversation-bubble-text: #e6def2;
134
+ --conversation-bubble-shadow: 0 2px 10px rgba(0, 0, 0, .28);
135
+ --caption-background: rgba(40, 25, 62, .88);
136
+ --caption-border: rgba(255, 255, 255, .08);
137
+ --caption-text: #f2edf8;
138
+ --prompt-pill-background: rgba(255, 255, 255, .05);
139
+ --prompt-pill-border: rgba(255, 255, 255, .16);
140
+ --prompt-pill-text: #d9a1f5;
141
+ --input-material-background: linear-gradient(176deg, #221136, #12081f);
142
+ --glass-highlight: rgba(255, 255, 255, .08);
143
+ --glass-highlight-subtle: rgba(255, 255, 255, .08);
144
+ --glass-highlight-strong: rgba(255, 255, 255, .08);
145
+ --glass-highlight-terminal: rgba(255, 255, 255, .08);
146
+ --danger-control-text: #ff9aad;
147
+ --danger-control-background: rgba(255, 122, 143, .08);
148
+ --danger-control-border: rgba(255, 122, 143, .22);
149
+ --soft-surface-background: rgba(255, 255, 255, .05);
150
+ --soft-surface-border: rgba(255, 255, 255, .16);
151
+ --soft-surface-strong-background: rgba(255, 255, 255, .05);
122
152
  --dialog-surface-background:
123
- linear-gradient(145deg, rgba(39, 31, 46, .98), rgba(24, 19, 29, .96));
124
- --dialog-surface-border: rgba(255, 255, 255, .13);
125
- --mode-active-background: rgba(45, 36, 52, .98);
153
+ linear-gradient(145deg, rgba(42, 28, 62, .98), rgba(21, 10, 34, .96));
154
+ --dialog-surface-border: rgba(255, 255, 255, .16);
155
+ --mode-active-background: #33214a;
156
+ --non-iridescent-panel-background: #1d102e;
157
+ --non-iridescent-panel-border: rgba(255, 255, 255, .08);
158
+ --non-iridescent-panel-shadow:
159
+ 0 24px 70px rgba(0, 0, 0, .55),
160
+ 0 4px 14px rgba(0, 0, 0, .3);
161
+ --brand-mark-border: transparent;
126
162
  --skel: rgba(255, 255, 255, .06);
127
163
  --shimmer: rgba(255, 255, 255, .1);
128
164
  }
129
165
  :host([data-theme="dark"]) .mode-option:not([aria-pressed="true"]):not(:disabled):hover {
130
166
  background: rgba(255, 255, 255, .08);
131
167
  }
168
+ :host([data-theme="dark"]) .brand-mark {
169
+ border-color: var(--brand-mark-border);
170
+ }
171
+ :host([data-theme="dark"]) .tags button,
172
+ :host([data-theme="dark"]) .tags.welcome-actions button {
173
+ color: var(--prompt-pill-text);
174
+ background: var(--prompt-pill-background);
175
+ border-color: var(--prompt-pill-border);
176
+ }
177
+ :host([data-theme="dark"]) .tags button:not(:disabled):hover,
178
+ :host([data-theme="dark"]) .tags button:not(:disabled):focus-visible,
179
+ :host([data-theme="dark"]) .tags.welcome-actions button:not(:disabled):hover,
180
+ :host([data-theme="dark"]) .tags.welcome-actions button:not(:disabled):focus-visible {
181
+ background: var(--mode-active-background);
182
+ }
183
+ :host([data-theme="dark"]) .intro-composer,
184
+ :host([data-theme="dark"]) .compact-chat-actions,
185
+ :host([data-theme="dark"]) .compact-chat-card::before,
186
+ :host([data-theme="dark"]) .composer::before,
187
+ :host([data-theme="dark"]) .panel-transition-inner-clone .chatbox,
188
+ :host([data-theme="dark"]) .panel.open:not(.compact) .chatbox,
189
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .header,
190
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice)::before {
191
+ background: var(--input-material-background);
192
+ }
193
+ :host([data-theme="dark"]) .intro-composer-frame.omago-transition-source,
194
+ :host([data-theme="dark"]) .panel.panel-transition-compact-clone:not(.voice-session) .compact-chat-actions {
195
+ background: var(--input-material-background) !important;
196
+ }
132
197
  :host([data-theme="dark"]) .panel.open.voice-session:not(.compact) .line:not(.bubble) {
133
- color: var(--assist-text);
134
- background: rgba(32, 25, 38, .9);
135
- border-color: rgba(255, 255, 255, .11);
198
+ color: var(--caption-text);
199
+ background: var(--caption-background);
200
+ border-color: var(--caption-border);
136
201
  }
137
202
  :host([data-theme="dark"]) .panel.open.voice-session:not(.compact) .line.user:not(.bubble) {
138
- color: var(--assist-text);
139
- background: rgba(40, 32, 47, .88);
203
+ color: var(--caption-text);
204
+ background: var(--caption-background);
140
205
  }
141
206
  .support-reply-notice,
142
207
  .compact-support-reply,
@@ -255,10 +320,15 @@ const style = `
255
320
  }
256
321
  .panel.omago-awaiting {
257
322
  opacity: 0;
323
+ visibility: hidden;
258
324
  pointer-events: none;
259
325
  transition: none !important;
260
326
  }
327
+ .panel.omago-awaiting * {
328
+ visibility: hidden !important;
329
+ }
261
330
  .panel.omago-destination-reveal {
331
+ visibility: visible;
262
332
  transition: opacity .24s ease;
263
333
  }
264
334
  .panel.compact.omago-destination-reveal {
@@ -755,9 +825,9 @@ const style = `
755
825
  max-height: 180px;
756
826
  max-width: 100%;
757
827
  padding: 9px 13px;
758
- color: #17151b;
759
- background: rgba(255, 255, 255, .82);
760
- border: 1px solid rgba(255, 255, 255, .65);
828
+ color: var(--caption-text);
829
+ background: var(--caption-background);
830
+ border: 1px solid var(--caption-border);
761
831
  border-radius: 16px;
762
832
  box-shadow: 0 10px 30px rgba(60, 20, 100, .25);
763
833
  backdrop-filter: blur(14px);
@@ -874,7 +944,7 @@ const style = `
874
944
  background:
875
945
  radial-gradient(circle at 30% 18%, rgba(255, 255, 255, .62), transparent 28%),
876
946
  linear-gradient(145deg, color-mix(in srgb, var(--accent) 72%, #c85ddf), var(--accent));
877
- border: 1px solid rgba(255, 255, 255, .8);
947
+ border: 1px solid var(--brand-mark-border);
878
948
  border-radius: 50%;
879
949
  box-shadow: 0 7px 18px color-mix(in srgb, var(--accent) 30%, transparent);
880
950
  }
@@ -929,6 +999,15 @@ const style = `
929
999
  border-radius: 50%;
930
1000
  }
931
1001
  .panel.open:not(.compact) .close:hover { background: #24232a; }
1002
+ :host([data-theme="dark"]) .panel.open:not(.compact) .close {
1003
+ color: var(--assist-text);
1004
+ background: var(--glass-control-background);
1005
+ border-color: var(--glass-control-border);
1006
+ box-shadow: none;
1007
+ }
1008
+ :host([data-theme="dark"]) .panel.open:not(.compact) .close:hover {
1009
+ background: var(--mode-active-background);
1010
+ }
932
1011
  .panel.active-session.compact .brand-mark {
933
1012
  width: 42px;
934
1013
  height: 42px;
@@ -1220,7 +1299,7 @@ const style = `
1220
1299
  border-radius: 999px;
1221
1300
  box-shadow:
1222
1301
  0 12px 30px rgba(15, 23, 42, .15),
1223
- inset 0 1px 0 rgba(255, 255, 255, .72);
1302
+ inset 0 1px 0 var(--glass-highlight-terminal);
1224
1303
  -webkit-backdrop-filter: blur(16px) saturate(1.08);
1225
1304
  backdrop-filter: blur(16px) saturate(1.08);
1226
1305
  font-size: 12px;
@@ -1339,7 +1418,7 @@ const style = `
1339
1418
  line-height: 0;
1340
1419
  }
1341
1420
  .button-icon svg, .menu-icon svg, .turn-icon svg { display: block; }
1342
- .body { min-height: 0; padding: 12px; overflow: auto; overflow-x: hidden; }
1421
+ .body { grid-area: 2 / 1; min-height: 0; padding: 12px; overflow: auto; overflow-x: hidden; }
1343
1422
  .intro {
1344
1423
  position: fixed;
1345
1424
  inset-inline-end: 20px;
@@ -2048,6 +2127,16 @@ const style = `
2048
2127
  :host(:is([data-activity="connecting"], [data-activity="listening"], [data-activity="thinking"], [data-activity="speaking"], [data-activity="acting"]):not([data-effects-paused="true"]):not([data-effect-motion="off"])) .input-effect-host > :is(.intro-effect, .composer-effect)::before {
2049
2128
  animation: original-border-busy 3.2s linear infinite;
2050
2129
  }
2130
+ :host([data-voice-effect-settle="captured"]) .panel.active-session.compact.voice-session > .voice-card-fx.intro-effect::before {
2131
+ animation: none !important;
2132
+ transform: var(--voice-effect-captured-transform) !important;
2133
+ transition: none !important;
2134
+ }
2135
+ :host([data-voice-effect-settle="settling"]) .panel.active-session.compact.voice-session > .voice-card-fx.intro-effect::before {
2136
+ animation: none !important;
2137
+ transform: translate(-50%, -50%) rotate(var(--effect-rest-angle)) !important;
2138
+ transition: transform .72s cubic-bezier(.22, .72, .28, 1) !important;
2139
+ }
2051
2140
  .intro-composer-frame:focus-within {
2052
2141
  outline: 1px solid rgba(160, 153, 216, .55);
2053
2142
  outline-offset: 3px;
@@ -2324,30 +2413,49 @@ const style = `
2324
2413
  .legal-links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }
2325
2414
  .legal-links a { color: #185ea8; font-size: 11px; font-weight: 600; }
2326
2415
  .page-assistance-overlay {
2327
- position: absolute;
2328
- inset: 0;
2416
+ position: relative;
2417
+ grid-area: 2 / 1;
2329
2418
  z-index: 6;
2330
2419
  display: grid;
2420
+ width: 100%;
2421
+ height: 100%;
2331
2422
  min-width: 0;
2332
- place-items: center;
2333
- padding: 14px;
2334
- background: rgba(15, 23, 42, .42);
2335
- border-radius: inherit;
2423
+ min-height: 0;
2424
+ place-items: end center;
2425
+ padding: 12px 8px 8px;
2426
+ background:
2427
+ radial-gradient(80% 52% at 50% 100%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 72%),
2428
+ color-mix(in srgb, var(--assist-surface) 48%, transparent);
2429
+ border-radius: 18px;
2336
2430
  overflow: hidden;
2337
- animation: page-assistance-backdrop-in .16s ease-out both;
2431
+ overscroll-behavior: contain;
2432
+ -webkit-backdrop-filter: blur(10px) saturate(1.08);
2433
+ backdrop-filter: blur(10px) saturate(1.08);
2434
+ animation: page-assistance-backdrop-in .24s ease-out both;
2338
2435
  }
2339
2436
  .page-assistance-dialog {
2340
2437
  width: min(100%, 430px);
2341
- max-height: calc(100% - 12px);
2438
+ max-height: calc(100% - 8px);
2342
2439
  min-width: 0;
2343
2440
  overflow: auto;
2344
- padding: 18px;
2441
+ overscroll-behavior: contain;
2442
+ padding: 16px;
2345
2443
  color: var(--assist-text);
2346
- background: var(--assist-surface);
2347
- border: 1px solid var(--assist-border);
2348
- border-radius: inherit;
2349
- box-shadow: 0 18px 42px rgba(15, 23, 42, .26);
2350
- animation: page-assistance-dialog-in .18s cubic-bezier(.2, .8, .3, 1) both;
2444
+ background:
2445
+ linear-gradient(
2446
+ 145deg,
2447
+ color-mix(in srgb, var(--assist-surface) 86%, transparent),
2448
+ color-mix(in srgb, var(--assist-surface-muted) 74%, transparent)
2449
+ );
2450
+ border: 1px solid var(--dialog-surface-border);
2451
+ border-radius: 20px;
2452
+ box-shadow:
2453
+ 0 20px 48px color-mix(in srgb, var(--accent) 16%, transparent),
2454
+ 0 4px 16px rgba(15, 23, 42, .14),
2455
+ inset 0 1px 0 var(--glass-highlight-strong);
2456
+ -webkit-backdrop-filter: blur(18px) saturate(1.1);
2457
+ backdrop-filter: blur(18px) saturate(1.1);
2458
+ animation: page-assistance-dialog-in .32s cubic-bezier(.2, .8, .3, 1) both;
2351
2459
  }
2352
2460
  .page-assistance-header {
2353
2461
  display: grid;
@@ -2358,8 +2466,8 @@ const style = `
2358
2466
  .page-assistance-header-copy { min-width: 0; }
2359
2467
  .page-assistance-header h3 {
2360
2468
  margin: 0;
2361
- font-size: 18px;
2362
- line-height: 24px;
2469
+ font-size: 16px;
2470
+ line-height: 22px;
2363
2471
  font-weight: 720;
2364
2472
  }
2365
2473
  .page-assistance-action-copy {
@@ -2378,11 +2486,12 @@ const style = `
2378
2486
  .page-assistance-footer {
2379
2487
  display: grid;
2380
2488
  gap: 6px;
2381
- margin-top: 12px;
2382
- padding: 10px 12px;
2383
- background: var(--assist-surface-muted);
2384
- border: 1px solid var(--assist-border);
2385
- border-radius: 12px;
2489
+ margin-top: 13px;
2490
+ padding: 11px 0 0;
2491
+ background: transparent;
2492
+ border: 0;
2493
+ border-top: 1px solid var(--soft-surface-border);
2494
+ border-radius: 0;
2386
2495
  }
2387
2496
  .page-assistance-always {
2388
2497
  display: grid;
@@ -2470,6 +2579,38 @@ const style = `
2470
2579
  color: #fbbf24;
2471
2580
  background: rgba(245, 158, 11, .18);
2472
2581
  }
2582
+ :host([data-theme="dark"]) .end,
2583
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .end {
2584
+ color: #ff7a8f;
2585
+ background: rgba(255, 255, 255, .06);
2586
+ border-color: rgba(255, 255, 255, .12);
2587
+ box-shadow: none;
2588
+ backdrop-filter: blur(8px);
2589
+ }
2590
+ :host([data-theme="dark"]) .end:not(:disabled):hover,
2591
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .end:not(:disabled):hover {
2592
+ color: #ff7a8f;
2593
+ background: rgba(255, 255, 255, .13);
2594
+ border-color: rgba(255, 255, 255, .12);
2595
+ box-shadow: none;
2596
+ }
2597
+ :host([data-theme="dark"]) .end:focus-visible,
2598
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .end:focus-visible {
2599
+ color: #ff7a8f;
2600
+ background: rgba(255, 255, 255, .13);
2601
+ border-color: rgba(255, 255, 255, .12);
2602
+ box-shadow: none;
2603
+ outline-color: rgba(217, 161, 245, .72);
2604
+ }
2605
+ :host([data-theme="dark"]) .end:disabled,
2606
+ :host([data-theme="dark"]) .end[aria-busy="true"],
2607
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .end:disabled,
2608
+ :host([data-theme="dark"]) .panel.active-session.compact:is(.voice-session, .starting-voice) .end[aria-busy="true"] {
2609
+ color: rgba(255, 122, 143, .68);
2610
+ background: rgba(255, 255, 255, .04);
2611
+ border-color: rgba(255, 255, 255, .08);
2612
+ box-shadow: none;
2613
+ }
2473
2614
  .page-assistance-actions {
2474
2615
  display: flex;
2475
2616
  justify-content: flex-end;
@@ -2623,7 +2764,7 @@ const style = `
2623
2764
  background: var(--conversation-bubble-background);
2624
2765
  border: 0;
2625
2766
  border-radius: 16px;
2626
- box-shadow: 0 2px 10px rgba(103, 42, 150, .06);
2767
+ box-shadow: var(--conversation-bubble-shadow);
2627
2768
  font-family: Poppins, system-ui, "Segoe UI", sans-serif;
2628
2769
  font-size: 12.5px;
2629
2770
  line-height: 1.6;
@@ -2791,6 +2932,7 @@ const style = `
2791
2932
  .empty { display: grid; min-height: 140px; place-items: center; color: #6a7480; font-size: 12px; text-align: center; }
2792
2933
  .controls {
2793
2934
  position: relative;
2935
+ grid-area: 3 / 1;
2794
2936
  z-index: 4;
2795
2937
  display: none;
2796
2938
  padding: 0 12px max(10px, env(safe-area-inset-bottom));
@@ -3289,7 +3431,7 @@ const style = `
3289
3431
  }
3290
3432
  @keyframes page-assistance-backdrop-in { from { opacity: 0; } }
3291
3433
  @keyframes page-assistance-dialog-in {
3292
- from { opacity: 0; transform: translateY(6px) scale(.985); }
3434
+ from { opacity: 0; transform: translateY(10px) scale(.98); }
3293
3435
  }
3294
3436
  @keyframes pop { from { opacity: 0; transform: translateY(8px); } }
3295
3437
  @keyframes attribution-in { from { opacity: 0; transform: translateY(3px); } }
@@ -3329,7 +3471,11 @@ const style = `
3329
3471
  .confirmation strong { color: #17212b; }
3330
3472
  .confirmation-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
3331
3473
  .confirmation [data-role="approve"], .visual-request [data-role="visual-share"] { background: #16a34a; border-color: #16a34a; }
3332
- .confirmation [data-role="decline"], .visual-request [data-role="visual-decline"] { color: #b91c1c; background: #fef2f2; border-color: #fecaca; }
3474
+ .confirmation [data-role="decline"], .visual-request [data-role="visual-decline"] {
3475
+ color: var(--danger-control-text);
3476
+ background: var(--danger-control-background);
3477
+ border-color: var(--danger-control-border);
3478
+ }
3333
3479
  .visual-request { display: none; padding: 12px; border: 2px solid #55758c; border-radius: 12px; background: white; }
3334
3480
  .visual-request.visible { display: block; }
3335
3481
  .visual-request.preparing .confirmation-actions { display: none; }
@@ -3394,7 +3540,7 @@ const style = `
3394
3540
  background: var(--soft-surface-background);
3395
3541
  border: 1px solid var(--soft-surface-border);
3396
3542
  border-radius: 18px;
3397
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, .64);
3543
+ box-shadow: inset 0 1px 0 var(--glass-highlight-subtle);
3398
3544
  backdrop-filter: blur(12px);
3399
3545
  }
3400
3546
  .panel.open:not(.compact) .status-card.visible { padding: 14px 16px; }
@@ -3408,26 +3554,16 @@ const style = `
3408
3554
  background: rgba(39, 22, 47, .34);
3409
3555
  backdrop-filter: blur(12px);
3410
3556
  }
3411
- .panel.open:not(.compact) .page-assistance-overlay {
3412
- inset: 0;
3413
- padding: 16px;
3414
- background: rgba(39, 22, 47, .34);
3415
- border-radius: inherit;
3416
- overflow: hidden;
3417
- backdrop-filter: blur(12px);
3418
- }
3419
- .panel.open:not(.compact) .legal-dialog,
3420
- .panel.open:not(.compact) .page-assistance-dialog {
3557
+ .panel.open:not(.compact) .legal-dialog {
3421
3558
  padding: 18px;
3422
3559
  background: var(--dialog-surface-background);
3423
3560
  border: 1px solid var(--dialog-surface-border);
3424
3561
  box-shadow:
3425
3562
  0 24px 60px rgba(49, 26, 58, .24),
3426
- inset 0 1px 0 rgba(255, 255, 255, .8);
3563
+ inset 0 1px 0 var(--glass-highlight-strong);
3427
3564
  backdrop-filter: blur(18px);
3428
3565
  }
3429
3566
  .panel.open:not(.compact) .legal-dialog { border-radius: 22px; }
3430
- .panel.open:not(.compact) .page-assistance-dialog { border-radius: inherit; }
3431
3567
  .panel.open:not(.compact) .legal-header h3 {
3432
3568
  color: color-mix(in srgb, var(--assist-text) 88%, var(--accent));
3433
3569
  font-size: 16px;
@@ -3435,8 +3571,8 @@ const style = `
3435
3571
  }
3436
3572
  .panel.open:not(.compact) .page-assistance-header h3 {
3437
3573
  color: color-mix(in srgb, var(--assist-text) 88%, var(--accent));
3438
- font-size: 18px;
3439
- line-height: 24px;
3574
+ font-size: 16px;
3575
+ line-height: 22px;
3440
3576
  }
3441
3577
  .panel.open:not(.compact) .legal-close {
3442
3578
  color: var(--assist-text);
@@ -3481,7 +3617,7 @@ const style = `
3481
3617
  background: var(--soft-surface-background);
3482
3618
  border: 1px solid var(--soft-surface-border);
3483
3619
  border-radius: 18px;
3484
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65);
3620
+ box-shadow: inset 0 1px 0 var(--glass-highlight);
3485
3621
  backdrop-filter: blur(12px);
3486
3622
  }
3487
3623
  .panel.open:not(.compact) .confirmation p,
@@ -3491,11 +3627,13 @@ const style = `
3491
3627
  .panel.open:not(.compact) .confirmation strong { color: var(--assist-text); }
3492
3628
  .panel.open:not(.compact) .confirmation [data-role="decline"],
3493
3629
  .panel.open:not(.compact) .visual-request [data-role="visual-decline"] {
3494
- color: #9d2947;
3495
- background: rgba(255, 245, 248, .7);
3496
- border-color: rgba(196, 87, 117, .24);
3630
+ color: var(--danger-control-text);
3631
+ background: var(--danger-control-background);
3632
+ border-color: var(--danger-control-border);
3497
3633
  }
3498
3634
  .panel.open:not(.compact) .feedback.visible { margin-top: 2px; }
3635
+ .panel.page-assistance-state .header,
3636
+ .panel.page-assistance-state .controls { pointer-events: none; }
3499
3637
  .panel.open:not(.compact) .feedback-options button {
3500
3638
  color: color-mix(in srgb, var(--assist-text) 74%, var(--accent));
3501
3639
  background: var(--soft-surface-strong-background);
@@ -3512,9 +3650,9 @@ const style = `
3512
3650
  display: none;
3513
3651
  }
3514
3652
  .panel.active-session.compact .compact-caption {
3515
- color: #17151b;
3516
- background: rgba(255, 255, 255, .82);
3517
- border-color: rgba(255, 255, 255, .65);
3653
+ color: var(--caption-text);
3654
+ background: var(--caption-background);
3655
+ border-color: var(--caption-border);
3518
3656
  border-radius: 16px;
3519
3657
  box-shadow: 0 10px 30px rgba(60, 20, 100, .25);
3520
3658
  backdrop-filter: blur(14px);
@@ -3522,9 +3660,9 @@ const style = `
3522
3660
  .panel.active-session.compact .compact-caption.assistant { border-end-start-radius: 6px; }
3523
3661
  .panel.active-session.compact .compact-caption.user,
3524
3662
  .panel.active-session.compact .compact-caption.user.pending {
3525
- color: #17151b;
3526
- background: rgba(255, 255, 255, .82);
3527
- border-color: rgba(255, 255, 255, .65);
3663
+ color: var(--caption-text);
3664
+ background: var(--caption-background);
3665
+ border-color: var(--caption-border);
3528
3666
  border-end-end-radius: 6px;
3529
3667
  }
3530
3668
  .widget-corner-glow {
@@ -3683,6 +3821,17 @@ const style = `
3683
3821
  border-color: var(--assist-border);
3684
3822
  box-shadow: 0 12px 28px rgba(15, 23, 42, .16);
3685
3823
  }
3824
+ .panel.open:not(.compact) .page-assistance-overlay {
3825
+ background: color-mix(in srgb, var(--assist-surface) 90%, transparent);
3826
+ -webkit-backdrop-filter: none;
3827
+ backdrop-filter: none;
3828
+ }
3829
+ .panel.open:not(.compact) .page-assistance-dialog {
3830
+ background: var(--assist-surface);
3831
+ box-shadow: 0 12px 28px rgba(15, 23, 42, .16);
3832
+ -webkit-backdrop-filter: none;
3833
+ backdrop-filter: none;
3834
+ }
3686
3835
  .panel.open:not(.compact) .brand-mark,
3687
3836
  .panel.open:not(.compact) .mode-switch,
3688
3837
  .panel.open:not(.compact) .voice-state-chip {
@@ -3716,9 +3865,9 @@ const style = `
3716
3865
  .intro-composer-frame:focus-within,
3717
3866
  .compact-chat-card:focus-within { box-shadow: none; }
3718
3867
  .panel.open.compact.ending-state .compact-error-notice.visible {
3719
- background: #fff;
3720
- border-color: #d9d4dc;
3721
- box-shadow: 0 8px 20px rgba(15, 23, 42, .12);
3868
+ background: var(--assist-surface);
3869
+ border-color: var(--assist-border);
3870
+ box-shadow: var(--non-iridescent-panel-shadow);
3722
3871
  -webkit-backdrop-filter: none;
3723
3872
  backdrop-filter: none;
3724
3873
  }
@@ -3743,6 +3892,20 @@ const style = `
3743
3892
  border: 2px solid CanvasText !important;
3744
3893
  box-shadow: none !important;
3745
3894
  }
3895
+ .panel.open:not(.compact) .page-assistance-overlay {
3896
+ background: transparent;
3897
+ -webkit-backdrop-filter: none;
3898
+ backdrop-filter: none;
3899
+ }
3900
+ .panel.open:not(.compact) .page-assistance-dialog {
3901
+ color: CanvasText;
3902
+ background: Canvas;
3903
+ border: 2px solid CanvasText;
3904
+ box-shadow: none;
3905
+ -webkit-backdrop-filter: none;
3906
+ backdrop-filter: none;
3907
+ forced-color-adjust: auto;
3908
+ }
3746
3909
  .panel.active-session.compact:is(.voice-session, .starting-voice) .header {
3747
3910
  background: Canvas;
3748
3911
  border: 2px solid CanvasText;
@@ -3816,7 +3979,7 @@ const style = `
3816
3979
  .header-actions { gap: 4px; }
3817
3980
  .duration { min-width: 48px; padding-inline: 6px; }
3818
3981
  .feedback-options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
3819
- .page-assistance-overlay { place-items: end center; padding: 8px; }
3982
+ .page-assistance-overlay { place-items: end center; padding: 8px 6px 6px; }
3820
3983
  .page-assistance-dialog { width: 100%; max-height: calc(100% - 4px); }
3821
3984
  .page-assistance-actions { display: grid; grid-template-columns: minmax(0, 1fr); }
3822
3985
  .page-assistance-actions button { width: 100%; }
@@ -3929,7 +4092,7 @@ const style = `
3929
4092
  height: auto;
3930
4093
  max-height: calc(100dvh - 16px - env(safe-area-inset-bottom));
3931
4094
  padding: 14px;
3932
- border: 1px solid rgba(255, 255, 255, .72);
4095
+ border: 1px solid var(--expanded-panel-border);
3933
4096
  border-radius: 24px;
3934
4097
  }
3935
4098
  .panel.open.compact.error-state {
@@ -3959,9 +4122,9 @@ const style = `
3959
4122
  }
3960
4123
  }
3961
4124
  :host([data-iridescence="false"]) .panel.open:not(.compact) {
3962
- background: #f7f4f8;
3963
- border-color: #d9d4dc;
3964
- box-shadow: 0 12px 28px rgba(15, 23, 42, .16);
4125
+ background: var(--non-iridescent-panel-background);
4126
+ border-color: var(--non-iridescent-panel-border);
4127
+ box-shadow: var(--non-iridescent-panel-shadow);
3965
4128
  }
3966
4129
  :host([data-iridescence="false"]) .panel.open:not(.compact) .brand-mark,
3967
4130
  :host([data-iridescence="false"]) .panel.open:not(.compact) .mode-switch,
@@ -4019,6 +4182,7 @@ class WidgetView {
4019
4182
  this.currentHandoffContextRequest = null;
4020
4183
  this.handoffRequestPreparing = false;
4021
4184
  this.currentPageAssistanceRequest = null;
4185
+ this.pageAssistancePresentationSnapshot = null;
4022
4186
  this.safetyInteractionIdentity = null;
4023
4187
  this.introComposing = false;
4024
4188
  this.legalOpenedPanel = false;
@@ -4033,6 +4197,7 @@ class WidgetView {
4033
4197
  this.tooltipTarget = null;
4034
4198
  this.tooltipTimer = null;
4035
4199
  this.ambientHideTimer = null;
4200
+ this.voiceCardEffectSettleTimer = null;
4036
4201
  this.attributionTimer = null;
4037
4202
  this.feedbackExitTimer = null;
4038
4203
  this.assistantReadyVisualTimer = null;
@@ -4394,6 +4559,16 @@ class WidgetView {
4394
4559
  void this.playRemoteAudio();
4395
4560
  }
4396
4561
  playRemoteAudio() {
4562
+ // Text sessions keep a receive-only audio section for the realtime
4563
+ // transport, so an attached stream alone never authorizes playback.
4564
+ const remoteStream = this.audio.srcObject;
4565
+ const hasLiveAudioTrack = typeof remoteStream?.getAudioTracks === "function" &&
4566
+ remoteStream
4567
+ .getAudioTracks()
4568
+ .some((track) => track.readyState === "live");
4569
+ if (!this.active || !this.voiceActive || !hasLiveAudioTrack) {
4570
+ return Promise.resolve();
4571
+ }
4397
4572
  if (this.playbackResumePending)
4398
4573
  return Promise.resolve();
4399
4574
  const generation = this.playbackGeneration;
@@ -4425,9 +4600,12 @@ class WidgetView {
4425
4600
  this.playbackBlocked = false;
4426
4601
  this.playbackResumePending = false;
4427
4602
  }
4428
- resetRemotePlayback() {
4603
+ pauseRemotePlayback() {
4429
4604
  this.invalidateRemotePlayback();
4430
4605
  this.audio.pause();
4606
+ }
4607
+ resetRemotePlayback() {
4608
+ this.pauseRemotePlayback();
4431
4609
  this.audio.srcObject = null;
4432
4610
  }
4433
4611
  playbackEventIsCurrent() {
@@ -4519,9 +4697,75 @@ class WidgetView {
4519
4697
  applyActivity(value) {
4520
4698
  if (this.activity === value)
4521
4699
  return;
4700
+ const wasBusy = this.effectActivityIsBusy(this.activity);
4701
+ const willBeBusy = this.effectActivityIsBusy(value);
4702
+ if (willBeBusy) {
4703
+ this.clearVoiceCardEffectSettle();
4704
+ }
4705
+ else if (wasBusy && value === "ready") {
4706
+ this.beginVoiceCardEffectSettle();
4707
+ }
4708
+ else {
4709
+ this.clearVoiceCardEffectSettle();
4710
+ }
4522
4711
  this.activity = value;
4523
4712
  this.host.dataset.activity = value;
4524
4713
  }
4714
+ effectActivityIsBusy(value) {
4715
+ return (value === "connecting" ||
4716
+ value === "listening" ||
4717
+ value === "thinking" ||
4718
+ value === "speaking" ||
4719
+ value === "acting");
4720
+ }
4721
+ beginVoiceCardEffectSettle() {
4722
+ this.clearVoiceCardEffectSettle();
4723
+ if (!this.active ||
4724
+ !this.voiceActive ||
4725
+ !this.compact ||
4726
+ !this.panel.classList.contains("voice-session") ||
4727
+ !this.effectsCanRun()) {
4728
+ return;
4729
+ }
4730
+ const effects = this.voiceCardEffectElements();
4731
+ if (effects.length === 0)
4732
+ return;
4733
+ let captures;
4734
+ try {
4735
+ captures = effects.map((effect) => ({
4736
+ effect,
4737
+ transform: getComputedStyle(effect, "::before").transform,
4738
+ }));
4739
+ }
4740
+ catch {
4741
+ return;
4742
+ }
4743
+ if (captures.some(({ transform }) => !transform || transform === "none")) {
4744
+ return;
4745
+ }
4746
+ for (const { effect, transform } of captures) {
4747
+ effect.style.setProperty("--voice-effect-captured-transform", transform);
4748
+ }
4749
+ this.host.dataset.voiceEffectSettle = "captured";
4750
+ void this.panel.offsetWidth;
4751
+ this.host.dataset.voiceEffectSettle = "settling";
4752
+ this.voiceCardEffectSettleTimer = setTimeout(() => {
4753
+ this.voiceCardEffectSettleTimer = null;
4754
+ this.clearVoiceCardEffectSettle();
4755
+ }, VOICE_CARD_EFFECT_SETTLE_MS);
4756
+ }
4757
+ clearVoiceCardEffectSettle() {
4758
+ if (this.voiceCardEffectSettleTimer !== null) {
4759
+ clearTimeout(this.voiceCardEffectSettleTimer);
4760
+ this.voiceCardEffectSettleTimer = null;
4761
+ }
4762
+ delete this.host.dataset.voiceEffectSettle;
4763
+ this.voiceCardEffectElements().forEach((effect) => effect.style.removeProperty("--voice-effect-captured-transform"));
4764
+ }
4765
+ voiceCardEffectElements() {
4766
+ return [...this.panel.children].filter((element) => element instanceof HTMLElement &&
4767
+ element.matches(".voice-card-fx.intro-effect"));
4768
+ }
4525
4769
  effectsCanRun() {
4526
4770
  return (this.capabilityTier === "standard" &&
4527
4771
  !this.isReducedMotionRequested() &&
@@ -4538,6 +4782,8 @@ class WidgetView {
4538
4782
  ? "on"
4539
4783
  : "off";
4540
4784
  this.host.dataset.effectsPaused = String(!shouldRun);
4785
+ if (!shouldRun)
4786
+ this.clearVoiceCardEffectSettle();
4541
4787
  }
4542
4788
  message(key) {
4543
4789
  return this.messages[key];
@@ -4549,8 +4795,9 @@ class WidgetView {
4549
4795
  open(mode = "text") {
4550
4796
  const requestedMode = mode === "voice" && this.config.capabilities?.voice ? "voice" : "text";
4551
4797
  if (!this.active) {
4552
- if (this.introMinimized)
4798
+ if (this.introMinimized && !this.compactEntryEnabled()) {
4553
4799
  this.setIntroMinimized(false);
4800
+ }
4554
4801
  this.syncLauncherState();
4555
4802
  queueMicrotask(() => this.focusIntroControl(requestedMode));
4556
4803
  return;
@@ -5674,10 +5921,8 @@ class WidgetView {
5674
5921
  const alwaysControl = this.require('[data-role="page-assistance-always-control"]');
5675
5922
  alwaysControl.hidden = !value.persistenceEligible;
5676
5923
  this.syncPageAssistanceFooter();
5677
- this.require('[data-role="page-assistance-overlay"]').hidden =
5678
- false;
5924
+ const overlay = this.syncPageAssistancePresentation();
5679
5925
  this.syncHeaderActions();
5680
- const overlay = this.require('[data-role="page-assistance-overlay"]');
5681
5926
  this.dialogFocus.present({
5682
5927
  surface: overlay,
5683
5928
  initialFocus: () => this.require('[data-role="page-assistance-decline"]'),
@@ -5687,6 +5932,55 @@ class WidgetView {
5687
5932
  },
5688
5933
  });
5689
5934
  }
5935
+ syncPageAssistancePresentation() {
5936
+ const overlay = this.require('[data-role="page-assistance-overlay"]');
5937
+ const visible = this.currentPageAssistanceRequest !== null;
5938
+ overlay.hidden = !visible;
5939
+ this.panel.classList.toggle("page-assistance-state", visible);
5940
+ const backgroundElements = [
5941
+ this.require(".header"),
5942
+ ...[...this.body.children].filter((child) => child instanceof HTMLElement),
5943
+ this.controls,
5944
+ ];
5945
+ if (visible) {
5946
+ if (!this.pageAssistancePresentationSnapshot) {
5947
+ this.pageAssistancePresentationSnapshot = {
5948
+ inert: new Map(),
5949
+ bodyOverflow: this.body.style.overflow,
5950
+ bodyOverflowX: this.body.style.overflowX,
5951
+ bodyOverflowY: this.body.style.overflowY,
5952
+ bodyOverscrollBehavior: this.body.style.overscrollBehavior,
5953
+ bodyScrollTop: this.body.scrollTop,
5954
+ bodyScrollLeft: this.body.scrollLeft,
5955
+ };
5956
+ }
5957
+ for (const element of backgroundElements) {
5958
+ if (!this.pageAssistancePresentationSnapshot.inert.has(element)) {
5959
+ this.pageAssistancePresentationSnapshot.inert.set(element, element.inert);
5960
+ }
5961
+ element.inert = true;
5962
+ }
5963
+ this.body.style.overflow = "hidden";
5964
+ this.body.style.overflowX = "hidden";
5965
+ this.body.style.overflowY = "hidden";
5966
+ this.body.style.overscrollBehavior = "contain";
5967
+ return overlay;
5968
+ }
5969
+ const snapshot = this.pageAssistancePresentationSnapshot;
5970
+ if (!snapshot)
5971
+ return overlay;
5972
+ for (const [element, inert] of snapshot.inert) {
5973
+ element.inert = inert;
5974
+ }
5975
+ this.body.style.overflow = snapshot.bodyOverflow;
5976
+ this.body.style.overflowX = snapshot.bodyOverflowX;
5977
+ this.body.style.overflowY = snapshot.bodyOverflowY;
5978
+ this.body.style.overscrollBehavior = snapshot.bodyOverscrollBehavior;
5979
+ this.body.scrollTop = snapshot.bodyScrollTop;
5980
+ this.body.scrollLeft = snapshot.bodyScrollLeft;
5981
+ this.pageAssistancePresentationSnapshot = null;
5982
+ return overlay;
5983
+ }
5690
5984
  syncPageAssistanceFooter() {
5691
5985
  const alwaysControl = this.require('[data-role="page-assistance-always-control"]');
5692
5986
  const agreement = this.require('[data-role="page-assistance-agreement"]');
@@ -5805,6 +6099,12 @@ class WidgetView {
5805
6099
  ? this.createPrimarySurfaceTransitionClone(compactModeSource, true)
5806
6100
  : null;
5807
6101
  this.voiceActive = voiceActive;
6102
+ if (wasVoiceActive && !voiceActive) {
6103
+ this.resetRemotePlayback();
6104
+ }
6105
+ else if (!wasVoiceActive && voiceActive) {
6106
+ void this.playRemoteAudio();
6107
+ }
5808
6108
  this.modeTransitionPending = null;
5809
6109
  if (committingStartingVoice) {
5810
6110
  this.discardStartingVoicePresentation();
@@ -5877,8 +6177,13 @@ class WidgetView {
5877
6177
  this.syncHeaderActions();
5878
6178
  }
5879
6179
  setModeTransitionPending(mode) {
6180
+ const previousMode = this.modeTransitionPending;
5880
6181
  this.modeTransitionPending = mode;
5881
6182
  if (mode === "voice" && this.active && !this.voiceActive) {
6183
+ // A text session can still own a live recv-only stream. Detach it before
6184
+ // the prepared Voice transport supplies its own authoritative stream.
6185
+ if (previousMode !== "voice")
6186
+ this.resetRemotePlayback();
5882
6187
  this.beginStartingVoicePresentation();
5883
6188
  }
5884
6189
  else if (mode === null &&
@@ -6379,11 +6684,14 @@ class WidgetView {
6379
6684
  document.visibilityState === "hidden") {
6380
6685
  return false;
6381
6686
  }
6382
- const surface = this.confirmation.classList.contains("visible")
6383
- ? this.confirmation
6384
- : this.visualRequest.classList.contains("visible")
6385
- ? this.visualRequest
6386
- : this.panel;
6687
+ const pageAssistance = this.require('[data-role="page-assistance-overlay"]');
6688
+ const surface = this.currentPageAssistanceRequest && !pageAssistance.hidden
6689
+ ? pageAssistance
6690
+ : this.confirmation.classList.contains("visible")
6691
+ ? this.confirmation
6692
+ : this.visualRequest.classList.contains("visible")
6693
+ ? this.visualRequest
6694
+ : this.panel;
6387
6695
  const rect = surface.getBoundingClientRect();
6388
6696
  const computed = getComputedStyle(surface);
6389
6697
  if (rect.width < 2 ||
@@ -6413,7 +6721,7 @@ class WidgetView {
6413
6721
  return false;
6414
6722
  }
6415
6723
  const shadowTop = shadowFromPoint?.(x, y) ?? null;
6416
- return !shadowTop || this.panel.contains(shadowTop);
6724
+ return !shadowTop || surface.contains(shadowTop);
6417
6725
  });
6418
6726
  }
6419
6727
  destroy() {
@@ -6428,6 +6736,7 @@ class WidgetView {
6428
6736
  this.reducedMotionQuery?.removeEventListener?.("change", this.onReducedMotionChange);
6429
6737
  this.hideTooltip();
6430
6738
  this.clearAssistantReadyVisualTimer();
6739
+ this.clearVoiceCardEffectSettle();
6431
6740
  this.clearFeedbackExitFade();
6432
6741
  this.cancelPanelDrag();
6433
6742
  this.resetRemotePlayback();
@@ -6454,6 +6763,7 @@ class WidgetView {
6454
6763
  this.hideAttribution();
6455
6764
  this.panel.removeEventListener("pointerdown", this.onPlaybackActivation, true);
6456
6765
  this.currentPageAssistanceRequest = null;
6766
+ this.pageAssistancePresentationSnapshot = null;
6457
6767
  this.dialogFocus.destroy();
6458
6768
  this.host.remove();
6459
6769
  this.currentConfirmation = null;
@@ -6560,28 +6870,6 @@ class WidgetView {
6560
6870
  <div class="legal-links" data-role="legal-links"><a data-role="legal-privacy" target="_blank" rel="noopener noreferrer"></a><a data-role="legal-terms" target="_blank" rel="noopener noreferrer"></a></div>
6561
6871
  </section>
6562
6872
  </div>
6563
- <div class="page-assistance-overlay" data-role="page-assistance-overlay" hidden>
6564
- <section class="page-assistance-dialog" role="dialog" aria-modal="true" aria-labelledby="oxvo-ai-page-assistance-title" aria-describedby="oxvo-ai-page-assistance-action">
6565
- <div class="page-assistance-header">
6566
- <div class="page-assistance-header-copy">
6567
- <h3 id="oxvo-ai-page-assistance-title" data-role="page-assistance-title"></h3>
6568
- <p id="oxvo-ai-page-assistance-action" class="page-assistance-action-copy"><span data-role="page-assistance-action"></span><span class="page-assistance-target" data-role="page-assistance-target"></span></p>
6569
- </div>
6570
- <button type="button" class="legal-close icon-button" data-role="page-assistance-close"><span class="button-icon" data-icon aria-hidden="true"></span></button>
6571
- </div>
6572
- <div class="page-assistance-footer" hidden>
6573
- <label class="page-assistance-always" data-role="page-assistance-always-control" hidden>
6574
- <input type="checkbox" data-role="page-assistance-always">
6575
- <span data-role="page-assistance-always-label"></span>
6576
- </label>
6577
- <p id="oxvo-ai-page-assistance-agreement" class="page-assistance-agreement" data-role="page-assistance-agreement"><span data-role="page-assistance-agreement-prefix"></span><a data-role="privacy" target="_blank" rel="noopener noreferrer"></a><span data-role="page-assistance-agreement-connector"></span><a data-role="terms" target="_blank" rel="noopener noreferrer"></a><span data-role="page-assistance-agreement-terminator"></span></p>
6578
- </div>
6579
- <div class="page-assistance-actions">
6580
- <button type="button" class="secondary" data-role="page-assistance-decline"></button>
6581
- <button type="button" class="primary" data-role="page-assistance-allow"></button>
6582
- </div>
6583
- </section>
6584
- </div>
6585
6873
  <div class="body" id="oxvo-ai-live-assist-content">
6586
6874
  <div class="support-reply-notice" data-role="support-reply-notice" role="status" aria-live="polite" aria-atomic="true" hidden>
6587
6875
  <span data-role="support-reply-message"></span>
@@ -6616,6 +6904,28 @@ class WidgetView {
6616
6904
  <div class="attribution-bubble" data-role="attribution" role="status" hidden><a href="https://oxvo.com/" target="_blank" rel="noopener noreferrer">OXVO</a></div>
6617
6905
  </div>
6618
6906
  </div>
6907
+ <div class="page-assistance-overlay" data-role="page-assistance-overlay" hidden>
6908
+ <section class="page-assistance-dialog" role="dialog" aria-modal="true" aria-labelledby="oxvo-ai-page-assistance-title" aria-describedby="oxvo-ai-page-assistance-action">
6909
+ <div class="page-assistance-header">
6910
+ <div class="page-assistance-header-copy">
6911
+ <h3 id="oxvo-ai-page-assistance-title" data-role="page-assistance-title"></h3>
6912
+ <p id="oxvo-ai-page-assistance-action" class="page-assistance-action-copy"><span data-role="page-assistance-action"></span><span class="page-assistance-target" data-role="page-assistance-target"></span></p>
6913
+ </div>
6914
+ <button type="button" class="legal-close icon-button" data-role="page-assistance-close"><span class="button-icon" data-icon aria-hidden="true"></span></button>
6915
+ </div>
6916
+ <div class="page-assistance-footer" hidden>
6917
+ <label class="page-assistance-always" data-role="page-assistance-always-control" hidden>
6918
+ <input type="checkbox" data-role="page-assistance-always">
6919
+ <span data-role="page-assistance-always-label"></span>
6920
+ </label>
6921
+ <p id="oxvo-ai-page-assistance-agreement" class="page-assistance-agreement" data-role="page-assistance-agreement"><span data-role="page-assistance-agreement-prefix"></span><a data-role="privacy" target="_blank" rel="noopener noreferrer"></a><span data-role="page-assistance-agreement-connector"></span><a data-role="terms" target="_blank" rel="noopener noreferrer"></a><span data-role="page-assistance-agreement-terminator"></span></p>
6922
+ </div>
6923
+ <div class="page-assistance-actions">
6924
+ <button type="button" class="secondary" data-role="page-assistance-decline"></button>
6925
+ <button type="button" class="primary" data-role="page-assistance-allow"></button>
6926
+ </div>
6927
+ </section>
6928
+ </div>
6619
6929
  <footer class="controls">
6620
6930
  <div class="composer-shell">
6621
6931
  <div class="voice-hud" data-role="voice-hud" hidden>
@@ -6657,7 +6967,7 @@ class WidgetView {
6657
6967
  </div>
6658
6968
  </div>
6659
6969
  </footer>
6660
- <audio autoplay></audio>
6970
+ <audio></audio>
6661
6971
  `;
6662
6972
  fragment.append(intro, highlight, panel, tooltip);
6663
6973
  return fragment;
@@ -6709,12 +7019,8 @@ class WidgetView {
6709
7019
  }
6710
7020
  if (!this.active || this.voiceActive || !this.compact)
6711
7021
  return;
7022
+ this.preferredFocusAfterTransition = this.require('[data-role="text-input"]');
6712
7023
  this.setCompact(false);
6713
- queueMicrotask(() => {
6714
- if (this.active && !this.voiceActive && !this.compact) {
6715
- this.require('[data-role="text-input"]').focus();
6716
- }
6717
- });
6718
7024
  });
6719
7025
  this.require('[data-role="compact-voice"]').addEventListener("click", () => {
6720
7026
  if (this.panel.classList.contains("error-state")) {
@@ -6877,8 +7183,11 @@ class WidgetView {
6877
7183
  });
6878
7184
  composer.addEventListener("submit", (event) => {
6879
7185
  event.preventDefault();
6880
- if (textInput.disabled)
7186
+ if (textInput.disabled ||
7187
+ this.panel.inert ||
7188
+ this.panel.getAttribute("aria-hidden") === "true") {
6881
7189
  return;
7190
+ }
6882
7191
  const value = textInput.value.trim();
6883
7192
  if (!value)
6884
7193
  return;
@@ -7044,8 +7353,10 @@ class WidgetView {
7044
7353
  this.messages.privacyPolicy;
7045
7354
  this.require('[data-role="legal-terms"]').textContent =
7046
7355
  this.messages.termsOfService;
7047
- this.require('[data-role="empty"]').textContent =
7048
- this.messages.emptyConversation;
7356
+ const emptyConversation = this.captions.querySelector('[data-role="empty"]');
7357
+ if (emptyConversation) {
7358
+ emptyConversation.textContent = this.messages.emptyConversation;
7359
+ }
7049
7360
  const end = this.require('[data-role="end"]');
7050
7361
  end.setAttribute("aria-label", this.messages.end);
7051
7362
  this.setTooltip(end, this.messages.end);
@@ -7098,10 +7409,12 @@ class WidgetView {
7098
7409
  const introMinimize = this.require('[data-role="intro-minimize"]');
7099
7410
  const introExpand = this.require('[data-role="intro-expand"]');
7100
7411
  const introCompactVoice = this.require('[data-role="intro-compact-voice"]');
7412
+ const compactEntryEnabled = appearance?.compactEntryEnabled === true;
7101
7413
  const textEntryEnabled = this.config.capabilities?.text === true;
7102
7414
  const voiceEntryEnabled = this.config.capabilities?.voice === true;
7103
7415
  introEntry.hidden = !textEntryEnabled && !voiceEntryEnabled;
7104
7416
  introEntry.dataset.textEnabled = String(textEntryEnabled);
7417
+ introEntry.dataset.compactEntryEnabled = String(compactEntryEnabled);
7105
7418
  introInput.hidden = !textEntryEnabled;
7106
7419
  introInput.placeholder =
7107
7420
  entryEnabled && entry?.inputPlaceholder.trim()
@@ -7133,6 +7446,10 @@ class WidgetView {
7133
7446
  this.require('[data-role="intro-compact-group"]').setAttribute("aria-label", this.messages.conversationStarters);
7134
7447
  this.require('[data-role="proactive-prompts"]').setAttribute("aria-label", this.messages.conversationStarters);
7135
7448
  this.require('[data-role="suggested-prompts"]').setAttribute("aria-label", this.messages.conversationStarters);
7449
+ if (!this.active) {
7450
+ this.clearIntroTransition();
7451
+ this.introMinimized = compactEntryEnabled;
7452
+ }
7136
7453
  this.syncIntroMinimizedState();
7137
7454
  this.syncIntroSendState();
7138
7455
  const send = this.require('[data-role="send"]');
@@ -7380,6 +7697,11 @@ class WidgetView {
7380
7697
  setIntroMinimized(value, moveFocus = false) {
7381
7698
  if (value && (this.active || this.launcherSuppressed))
7382
7699
  return;
7700
+ if (!value && this.compactEntryEnabled()) {
7701
+ if (moveFocus)
7702
+ this.focusIntroView(true);
7703
+ return;
7704
+ }
7383
7705
  if (this.introTransitionTarget === value)
7384
7706
  return;
7385
7707
  if (this.introTransitionTarget !== null && this.introMinimized === value) {
@@ -7564,6 +7886,20 @@ class WidgetView {
7564
7886
  focusIntroControl(mode) {
7565
7887
  const input = this.require('[data-role="intro-text-input"]');
7566
7888
  const voice = this.require('[data-role="intro-voice"]');
7889
+ const compactChat = this.require('[data-role="intro-expand"]');
7890
+ const compactVoice = this.require('[data-role="intro-compact-voice"]');
7891
+ if (this.introMinimized && this.compactEntryEnabled()) {
7892
+ const compactCandidates = mode === "voice"
7893
+ ? [compactVoice, compactChat]
7894
+ : [compactChat, compactVoice];
7895
+ for (const candidate of compactCandidates) {
7896
+ if (candidate.hidden || candidate.hasAttribute("disabled"))
7897
+ continue;
7898
+ candidate.focus({ preventScroll: true });
7899
+ return;
7900
+ }
7901
+ return;
7902
+ }
7567
7903
  const candidates = mode === "voice" ? [voice, input] : [input, voice];
7568
7904
  for (const candidate of candidates) {
7569
7905
  if (candidate.hidden || candidate.hasAttribute("disabled"))
@@ -7577,10 +7913,8 @@ class WidgetView {
7577
7913
  if (!request)
7578
7914
  return;
7579
7915
  this.currentPageAssistanceRequest = null;
7580
- this.require('[data-role="page-assistance-overlay"]').hidden =
7581
- true;
7916
+ const overlay = this.syncPageAssistancePresentation();
7582
7917
  this.require('[data-role="page-assistance-always"]').checked = false;
7583
- const overlay = this.require('[data-role="page-assistance-overlay"]');
7584
7918
  this.dialogFocus.dismiss(overlay);
7585
7919
  this.restoreVoicePresenceAfterPrompt();
7586
7920
  this.syncHeaderActions();
@@ -8866,6 +9200,9 @@ class WidgetView {
8866
9200
  this.syncProactiveEngagementVisibility();
8867
9201
  this.syncSurfaceEffectOwner();
8868
9202
  }
9203
+ compactEntryEnabled() {
9204
+ return this.config.appearance?.compactEntryEnabled === true;
9205
+ }
8869
9206
  cancelPendingConfirmation() {
8870
9207
  if (!this.resolvePendingConfirmation(false))
8871
9208
  return false;
@@ -9059,7 +9396,7 @@ class WidgetView {
9059
9396
  introInput.value = "";
9060
9397
  introInput.setAttribute("aria-invalid", "false");
9061
9398
  this.clearIntroTransition();
9062
- this.introMinimized = false;
9399
+ this.introMinimized = this.compactEntryEnabled();
9063
9400
  this.syncIntroMinimizedState();
9064
9401
  this.panel.classList.remove("voice-session");
9065
9402
  this.panel.removeAttribute("data-presentation");