Glitche commited on
Commit
670b591
·
verified ·
1 Parent(s): 29944ea

Upload style.css

Browse files
Files changed (1) hide show
  1. static/css/style.css +1120 -0
static/css/style.css ADDED
@@ -0,0 +1,1120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ TalkToDoc design system.
3
+ Palette: "Olive Garden Feast" (user-supplied Coolors palette):
4
+ #606C38 (olive), #283618 (dark forest green), #FEFAE0 (cream),
5
+ #DDA15E (tan/gold), #BC6C25 (rust).
6
+
7
+ Patient view uses the olive as its primary color, provider view uses a
8
+ darkened variant of the rust, one color family per role, same approach
9
+ as the previous palette. Raw #BC6C25 and raw #DDA15E both fail WCAG
10
+ contrast as text on light backgrounds, so darkened variants are used
11
+ anywhere either color needs to be read as text rather than a fill.
12
+
13
+ System fonts only, no external font download, this matters for the
14
+ low-bandwidth rural settings this system is built for.
15
+ */
16
+
17
+ :root {
18
+ /* Base */
19
+ --color-bg: #FEFAE0;
20
+ --color-surface: #FFFFFF;
21
+ --color-border: #E8DFC0;
22
+
23
+ /* Text */
24
+ --color-text: #283618;
25
+ --color-text-secondary: #5C6650;
26
+ --color-text-on-primary: #FFFFFF;
27
+ --color-text-on-provider-accent: #FFFFFF;
28
+
29
+ /* Primary (shared, patient role) */
30
+ --color-primary: #606C38;
31
+ --color-primary-dark: #283618;
32
+ --color-primary-light: #E8ECDC;
33
+
34
+ /* Accent */
35
+ --color-accent: #DDA15E;
36
+ /* Raw #DDA15E fails WCAG contrast as text (2.14:1), this darkened
37
+ variant clears AA at 5.33:1, used anywhere it needs to be text. */
38
+ --color-accent-text: #8A5F26;
39
+
40
+ /* Provider-only accent */
41
+ /* Raw #BC6C25 gives only 3.95:1 with white text, not enough for
42
+ normal-size text, this darkened variant clears AA at 5.25:1. */
43
+ --color-provider-accent: #A15A1F;
44
+ --color-provider-accent-light: #FBEADB;
45
+ --color-provider-accent-text: #7A431A;
46
+
47
+ /* Semantic */
48
+ --color-success: #2E7D32;
49
+ --color-error: #B3261E;
50
+ --color-error-light: #FBEAE9;
51
+
52
+ /* Spacing scale */
53
+ --space-1: 4px;
54
+ --space-2: 8px;
55
+ --space-3: 12px;
56
+ --space-4: 16px;
57
+ --space-5: 24px;
58
+ --space-6: 32px;
59
+ --space-7: 48px;
60
+ --space-8: 64px;
61
+
62
+ /* Type scale */
63
+ --text-sm: 0.875rem;
64
+ --text-base: 1rem;
65
+ --text-lg: 1.125rem;
66
+ --text-xl: 1.5rem;
67
+ --text-2xl: 2rem;
68
+
69
+ --radius: 20px;
70
+ --radius-sm: 14px;
71
+ --radius-lg: 28px;
72
+
73
+ /* Soft elevation, replaces hard 1px borders on cards and controls */
74
+ --shadow-sm: 0 1px 2px rgba(40, 54, 24, 0.05), 0 2px 6px rgba(40, 54, 24, 0.04);
75
+ --shadow-md: 0 6px 20px rgba(40, 54, 24, 0.08), 0 2px 6px rgba(40, 54, 24, 0.05);
76
+ --shadow-lg: 0 16px 40px rgba(40, 54, 24, 0.14);
77
+ }
78
+
79
+ * {
80
+ box-sizing: border-box;
81
+ }
82
+
83
+ body {
84
+ margin: 0;
85
+ font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
86
+ background: var(--color-bg);
87
+ color: var(--color-text);
88
+ font-size: var(--text-base);
89
+ line-height: 1.5;
90
+ -webkit-font-smoothing: antialiased;
91
+ }
92
+
93
+ h1, h2, h3 {
94
+ margin: 0 0 var(--space-2) 0;
95
+ font-weight: 700;
96
+ line-height: 1.25;
97
+ letter-spacing: -0.02em;
98
+ }
99
+
100
+ h1 { font-size: var(--text-2xl); }
101
+ h2 { font-size: var(--text-xl); }
102
+ h3 { font-size: var(--text-lg); letter-spacing: -0.01em; }
103
+
104
+ p {
105
+ margin: 0 0 var(--space-4) 0;
106
+ color: var(--color-text-secondary);
107
+ }
108
+
109
+ .app-shell {
110
+ max-width: 480px;
111
+ margin: 0 auto;
112
+ min-height: 100vh;
113
+ display: flex;
114
+ flex-direction: column;
115
+ background: var(--color-bg);
116
+ }
117
+
118
+ .app-header {
119
+ padding: var(--space-5) var(--space-4) var(--space-6);
120
+ background: linear-gradient(155deg, var(--color-primary) 0%, var(--color-primary-dark) 130%);
121
+ color: var(--color-text-on-primary);
122
+ border-radius: 0 0 var(--radius-lg) var(--radius-lg);
123
+ }
124
+
125
+ .app-header.provider {
126
+ background: linear-gradient(155deg, var(--color-provider-accent) 0%, var(--color-provider-accent-text) 160%);
127
+ color: var(--color-text-on-provider-accent);
128
+ }
129
+
130
+ .brand {
131
+ display: flex;
132
+ align-items: center;
133
+ gap: var(--space-2);
134
+ }
135
+
136
+ .brand-mark {
137
+ width: 28px;
138
+ height: 28px;
139
+ border-radius: 50%;
140
+ background: rgba(255, 255, 255, 0.18);
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ flex-shrink: 0;
145
+ }
146
+
147
+ .brand-mark svg {
148
+ width: 16px;
149
+ height: 16px;
150
+ }
151
+
152
+ .app-header h1 {
153
+ font-size: var(--text-lg);
154
+ margin: 0;
155
+ }
156
+
157
+ .app-header .role-tag {
158
+ display: inline-block;
159
+ margin-top: var(--space-1);
160
+ font-size: var(--text-sm);
161
+ opacity: 0.85;
162
+ }
163
+
164
+ .app-main {
165
+ flex: 1;
166
+ padding: var(--space-5) var(--space-4) var(--space-7);
167
+ }
168
+
169
+ .card {
170
+ background: var(--color-surface);
171
+ border-radius: var(--radius);
172
+ padding: var(--space-5);
173
+ margin-bottom: var(--space-4);
174
+ box-shadow: var(--shadow-sm);
175
+ }
176
+
177
+ .step {
178
+ display: none;
179
+ }
180
+
181
+ .step.active {
182
+ display: block;
183
+ animation: step-in 220ms ease;
184
+ }
185
+
186
+ @keyframes step-in {
187
+ from { opacity: 0; transform: translateY(6px); }
188
+ to { opacity: 1; transform: translateY(0); }
189
+ }
190
+
191
+ @media (prefers-reduced-motion: reduce) {
192
+ .step.active {
193
+ animation: none;
194
+ }
195
+ }
196
+
197
+ /* Buttons */
198
+ .btn {
199
+ display: inline-flex;
200
+ align-items: center;
201
+ justify-content: center;
202
+ gap: var(--space-2);
203
+ width: 100%;
204
+ padding: var(--space-3) var(--space-4);
205
+ font-size: var(--text-base);
206
+ font-weight: 600;
207
+ border-radius: var(--radius-sm);
208
+ border: none;
209
+ cursor: pointer;
210
+ transition: background-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
211
+ }
212
+
213
+ .btn:active {
214
+ transform: scale(0.98);
215
+ }
216
+
217
+ .btn:focus-visible {
218
+ outline: 2px solid var(--color-primary-dark);
219
+ outline-offset: 2px;
220
+ }
221
+
222
+ .btn-primary {
223
+ background: var(--color-primary);
224
+ color: var(--color-text-on-primary);
225
+ box-shadow: 0 4px 14px rgba(96, 108, 56, 0.32);
226
+ }
227
+ .btn-primary:hover { background: var(--color-primary-dark); }
228
+ .btn-primary:disabled {
229
+ background: var(--color-border);
230
+ color: var(--color-text-secondary);
231
+ box-shadow: none;
232
+ cursor: not-allowed;
233
+ }
234
+
235
+ .btn-secondary {
236
+ background: var(--color-primary-light);
237
+ color: var(--color-primary-dark);
238
+ }
239
+ .btn-secondary:hover { background: #DAE1CD; }
240
+
241
+ .btn-provider {
242
+ background: var(--color-provider-accent);
243
+ color: var(--color-text-on-provider-accent);
244
+ box-shadow: 0 4px 14px rgba(161, 90, 31, 0.32);
245
+ }
246
+ .btn-provider:hover { background: var(--color-provider-accent-text); }
247
+
248
+ .btn-row {
249
+ display: flex;
250
+ gap: var(--space-3);
251
+ margin-top: var(--space-4);
252
+ }
253
+
254
+ /* Language grid */
255
+ .language-grid {
256
+ display: grid;
257
+ grid-template-columns: 1fr 1fr;
258
+ gap: var(--space-3);
259
+ margin-top: var(--space-4);
260
+ }
261
+
262
+ .language-option {
263
+ padding: var(--space-4);
264
+ text-align: center;
265
+ font-weight: 600;
266
+ border: none;
267
+ border-radius: var(--radius-sm);
268
+ background: var(--color-surface);
269
+ box-shadow: var(--shadow-sm);
270
+ cursor: pointer;
271
+ transition: box-shadow 120ms ease, transform 120ms ease, background-color 120ms ease;
272
+ }
273
+
274
+ .language-option:hover {
275
+ box-shadow: var(--shadow-md);
276
+ transform: translateY(-1px);
277
+ }
278
+
279
+ .language-option:active {
280
+ transform: scale(0.96);
281
+ }
282
+
283
+ .language-option[aria-pressed="true"] {
284
+ background: var(--color-primary);
285
+ color: var(--color-text-on-primary);
286
+ box-shadow: 0 4px 14px rgba(96, 108, 56, 0.32);
287
+ animation: select-pop 260ms ease;
288
+ }
289
+
290
+ @keyframes select-pop {
291
+ 0% { transform: scale(1); }
292
+ 40% { transform: scale(1.06); }
293
+ 100% { transform: scale(1); }
294
+ }
295
+
296
+ @media (prefers-reduced-motion: reduce) {
297
+ .language-option[aria-pressed="true"] { animation: none; }
298
+ }
299
+
300
+ /* Inputs */
301
+ label {
302
+ display: block;
303
+ font-weight: 600;
304
+ font-size: var(--text-sm);
305
+ margin-bottom: var(--space-2);
306
+ }
307
+
308
+ textarea, input[type="text"] {
309
+ width: 100%;
310
+ padding: var(--space-3) var(--space-4);
311
+ font-size: var(--text-base);
312
+ font-family: inherit;
313
+ border: 1.5px solid var(--color-border);
314
+ border-radius: var(--radius-sm);
315
+ background: var(--color-surface);
316
+ color: var(--color-text);
317
+ resize: vertical;
318
+ transition: border-color 120ms ease, box-shadow 120ms ease;
319
+ }
320
+
321
+ textarea:focus, input[type="text"]:focus {
322
+ outline: none;
323
+ border-color: var(--color-primary);
324
+ box-shadow: 0 0 0 4px var(--color-primary-light);
325
+ }
326
+
327
+ .helper-text {
328
+ font-size: var(--text-sm);
329
+ color: var(--color-text-secondary);
330
+ margin-top: var(--space-2);
331
+ }
332
+
333
+ .divider {
334
+ display: flex;
335
+ align-items: center;
336
+ gap: var(--space-3);
337
+ margin: var(--space-4) 0;
338
+ color: var(--color-text-secondary);
339
+ font-size: var(--text-sm);
340
+ }
341
+ .divider::before, .divider::after {
342
+ content: "";
343
+ flex: 1;
344
+ height: 1px;
345
+ background: var(--color-border);
346
+ }
347
+
348
+ /* Recording indicator */
349
+ .record-btn {
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: center;
353
+ gap: var(--space-2);
354
+ }
355
+
356
+ .record-dot {
357
+ width: 10px;
358
+ height: 10px;
359
+ border-radius: 50%;
360
+ background: var(--color-error);
361
+ display: none;
362
+ }
363
+
364
+ .record-btn.recording .record-dot {
365
+ display: inline-block;
366
+ animation: pulse 1s infinite;
367
+ }
368
+
369
+ @keyframes pulse {
370
+ 0%, 100% { opacity: 1; }
371
+ 50% { opacity: 0.35; }
372
+ }
373
+
374
+ /* Status / results */
375
+ .status-banner {
376
+ padding: var(--space-3) var(--space-4);
377
+ border-radius: var(--radius-sm);
378
+ font-size: var(--text-sm);
379
+ margin-bottom: var(--space-4);
380
+ }
381
+
382
+ .status-banner.error {
383
+ background: var(--color-error-light);
384
+ color: var(--color-error);
385
+ }
386
+
387
+ .status-banner.info {
388
+ background: var(--color-primary-light);
389
+ color: var(--color-primary-dark);
390
+ }
391
+
392
+ .result-block {
393
+ margin-bottom: var(--space-4);
394
+ }
395
+
396
+ .result-label {
397
+ font-size: var(--text-sm);
398
+ font-weight: 600;
399
+ color: var(--color-text-secondary);
400
+ margin-bottom: var(--space-1);
401
+ }
402
+
403
+ .result-text {
404
+ font-size: var(--text-lg);
405
+ color: var(--color-text);
406
+ }
407
+
408
+ audio {
409
+ width: 100%;
410
+ margin-top: var(--space-3);
411
+ }
412
+
413
+ .interaction-id {
414
+ font-family: ui-monospace, monospace;
415
+ background: var(--color-primary-light);
416
+ color: var(--color-primary-dark);
417
+ padding: 2px 8px;
418
+ border-radius: 4px;
419
+ font-size: var(--text-sm);
420
+ }
421
+
422
+ .provider .interaction-id {
423
+ background: var(--color-provider-accent-light);
424
+ color: var(--color-provider-accent-text);
425
+ }
426
+
427
+ .nlu-summary {
428
+ background: var(--color-provider-accent-light);
429
+ border-left: 3px solid var(--color-provider-accent-text);
430
+ padding: var(--space-3) var(--space-4);
431
+ border-radius: var(--radius-sm);
432
+ font-size: var(--text-base);
433
+ margin-bottom: var(--space-4);
434
+ }
435
+
436
+ .nav-link {
437
+ display: block;
438
+ text-align: center;
439
+ margin-top: var(--space-5);
440
+ font-size: var(--text-sm);
441
+ color: var(--color-text-secondary);
442
+ }
443
+
444
+ .nav-link a {
445
+ color: var(--color-primary);
446
+ font-weight: 600;
447
+ text-decoration: none;
448
+ }
449
+
450
+ .nav-link.provider a {
451
+ color: var(--color-provider-accent-text);
452
+ }
453
+
454
+ /* ============================================================
455
+ Hero section: greeting + ambient presence orb
456
+ ============================================================ */
457
+
458
+ .hero {
459
+ text-align: center;
460
+ padding: var(--space-4) 0 var(--space-6);
461
+ }
462
+
463
+ .hero-orb-wrap {
464
+ position: relative;
465
+ width: 132px;
466
+ height: 132px;
467
+ margin: 0 auto var(--space-5);
468
+ display: flex;
469
+ align-items: center;
470
+ justify-content: center;
471
+ }
472
+
473
+ .hero-orb-glow {
474
+ position: absolute;
475
+ inset: -20px;
476
+ border-radius: 50%;
477
+ background: radial-gradient(circle, var(--color-primary) 0%, rgba(96, 108, 56, 0) 70%);
478
+ opacity: 0.35;
479
+ animation: breathe 3400ms ease-in-out infinite;
480
+ }
481
+
482
+ .provider .hero-orb-glow {
483
+ background: radial-gradient(circle, var(--color-provider-accent) 0%, rgba(161, 90, 31, 0) 70%);
484
+ }
485
+
486
+ .hero-orb {
487
+ position: relative;
488
+ width: 96px;
489
+ height: 96px;
490
+ border-radius: 50%;
491
+ background: linear-gradient(155deg, #7C8A47 0%, var(--color-primary) 45%, var(--color-primary-dark) 100%);
492
+ display: flex;
493
+ align-items: center;
494
+ justify-content: center;
495
+ box-shadow: 0 12px 32px rgba(40, 54, 24, 0.32), inset 0 1px 1px rgba(255, 255, 255, 0.25);
496
+ }
497
+
498
+ .provider .hero-orb {
499
+ background: linear-gradient(155deg, #C97D3A 0%, var(--color-provider-accent) 45%, var(--color-provider-accent-text) 100%);
500
+ box-shadow: 0 12px 32px rgba(122, 67, 26, 0.32), inset 0 1px 1px rgba(255, 255, 255, 0.25);
501
+ }
502
+
503
+ .hero-orb svg {
504
+ width: 36px;
505
+ height: 36px;
506
+ color: var(--color-bg);
507
+ }
508
+
509
+ @keyframes breathe {
510
+ 0%, 100% { transform: scale(1); opacity: 0.35; }
511
+ 50% { transform: scale(1.12); opacity: 0.55; }
512
+ }
513
+
514
+ @media (prefers-reduced-motion: reduce) {
515
+ .hero-orb-glow { animation: none; }
516
+ }
517
+
518
+ .hero h2 {
519
+ margin-bottom: var(--space-1);
520
+ }
521
+
522
+ .hero p {
523
+ max-width: 320px;
524
+ margin-left: auto;
525
+ margin-right: auto;
526
+ }
527
+
528
+ /* ============================================================
529
+ Unified input bar (textarea + inline mic button)
530
+ ============================================================ */
531
+
532
+ .input-bar {
533
+ position: relative;
534
+ }
535
+
536
+ .input-bar textarea {
537
+ padding-right: 52px;
538
+ }
539
+
540
+ .mic-inline-btn {
541
+ position: absolute;
542
+ right: 8px;
543
+ bottom: 8px;
544
+ width: 38px;
545
+ height: 38px;
546
+ border-radius: 50%;
547
+ border: none;
548
+ background: var(--color-primary);
549
+ color: var(--color-text-on-primary);
550
+ display: flex;
551
+ align-items: center;
552
+ justify-content: center;
553
+ cursor: pointer;
554
+ box-shadow: 0 4px 12px rgba(96, 108, 56, 0.35);
555
+ transition: background-color 120ms ease, transform 120ms ease;
556
+ }
557
+
558
+ .mic-inline-btn:hover {
559
+ background: var(--color-primary-dark);
560
+ }
561
+
562
+ .mic-inline-btn.recording {
563
+ background: var(--color-error);
564
+ animation: pulse-ring 1400ms ease-in-out infinite;
565
+ }
566
+
567
+ @keyframes pulse-ring {
568
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(179, 38, 30, 0.35); }
569
+ 50% { box-shadow: 0 0 0 8px rgba(179, 38, 30, 0); }
570
+ }
571
+
572
+ .mic-inline-btn svg {
573
+ width: 18px;
574
+ height: 18px;
575
+ }
576
+
577
+ /* ============================================================
578
+ Listening state: replaces the input bar while recording
579
+ ============================================================ */
580
+
581
+ .listening-panel {
582
+ text-align: center;
583
+ padding: var(--space-6) 0 var(--space-4);
584
+ }
585
+
586
+ .listening-orb-wrap {
587
+ position: relative;
588
+ width: 128px;
589
+ height: 128px;
590
+ margin: 0 auto var(--space-4);
591
+ display: flex;
592
+ align-items: center;
593
+ justify-content: center;
594
+ }
595
+
596
+ .listening-ring {
597
+ position: absolute;
598
+ inset: 0;
599
+ border-radius: 50%;
600
+ border: 2px solid var(--color-primary);
601
+ opacity: 0;
602
+ animation: ripple 2200ms ease-out infinite;
603
+ }
604
+
605
+ .listening-ring:nth-child(2) { animation-delay: 700ms; }
606
+ .listening-ring:nth-child(3) { animation-delay: 1400ms; }
607
+
608
+ @keyframes ripple {
609
+ 0% { transform: scale(0.55); opacity: 0.5; }
610
+ 100% { transform: scale(1); opacity: 0; }
611
+ }
612
+
613
+ .listening-core {
614
+ position: relative;
615
+ width: 72px;
616
+ height: 72px;
617
+ border-radius: 50%;
618
+ background: var(--color-primary);
619
+ color: var(--color-text-on-primary);
620
+ border: none;
621
+ display: flex;
622
+ align-items: center;
623
+ justify-content: center;
624
+ cursor: pointer;
625
+ }
626
+
627
+ .listening-core svg {
628
+ width: 28px;
629
+ height: 28px;
630
+ }
631
+
632
+ @media (prefers-reduced-motion: reduce) {
633
+ .listening-ring { animation: none; opacity: 0.25; transform: scale(0.8); }
634
+ }
635
+
636
+ .listening-caption {
637
+ font-weight: 600;
638
+ margin-bottom: var(--space-1);
639
+ }
640
+
641
+ /* ============================================================
642
+ Quick symptom chips
643
+ ============================================================ */
644
+
645
+ .chip-row {
646
+ display: flex;
647
+ flex-wrap: wrap;
648
+ gap: var(--space-2);
649
+ margin: var(--space-3) 0 var(--space-4);
650
+ }
651
+
652
+ .chip {
653
+ padding: 8px 16px;
654
+ border-radius: 999px;
655
+ border: none;
656
+ background: var(--color-surface);
657
+ color: var(--color-text);
658
+ font-size: var(--text-sm);
659
+ font-weight: 600;
660
+ box-shadow: var(--shadow-sm);
661
+ cursor: pointer;
662
+ transition: box-shadow 120ms ease, transform 120ms ease, background-color 120ms ease;
663
+ }
664
+
665
+ .chip:hover {
666
+ box-shadow: var(--shadow-md);
667
+ background: var(--color-primary-light);
668
+ transform: translateY(-1px);
669
+ }
670
+
671
+ .chip:active {
672
+ transform: scale(0.95);
673
+ }
674
+
675
+ /* ============================================================
676
+ Chat bubbles, used for the conversation view and history
677
+ ============================================================ */
678
+
679
+ .chat-thread {
680
+ display: flex;
681
+ flex-direction: column;
682
+ gap: var(--space-3);
683
+ }
684
+
685
+ .chat-bubble {
686
+ max-width: 85%;
687
+ padding: var(--space-3) var(--space-4);
688
+ border-radius: var(--radius);
689
+ font-size: var(--text-base);
690
+ line-height: 1.45;
691
+ }
692
+
693
+ .chat-bubble .chat-label {
694
+ display: block;
695
+ font-size: var(--text-sm);
696
+ font-weight: 600;
697
+ margin-bottom: 2px;
698
+ opacity: 0.75;
699
+ }
700
+
701
+ .chat-bubble.from-patient {
702
+ align-self: flex-end;
703
+ background: var(--color-primary);
704
+ color: var(--color-text-on-primary);
705
+ border-bottom-right-radius: 4px;
706
+ }
707
+
708
+ .chat-bubble.from-provider {
709
+ align-self: flex-start;
710
+ background: var(--color-surface);
711
+ box-shadow: var(--shadow-sm);
712
+ color: var(--color-text);
713
+ border-bottom-left-radius: 4px;
714
+ }
715
+
716
+ .provider .chat-bubble.from-provider {
717
+ background: var(--color-provider-accent-light);
718
+ box-shadow: none;
719
+ }
720
+
721
+ /* ============================================================
722
+ Provider queue cards
723
+ ============================================================ */
724
+
725
+ .queue-card {
726
+ display: flex;
727
+ align-items: flex-start;
728
+ gap: var(--space-3);
729
+ width: 100%;
730
+ text-align: left;
731
+ padding: var(--space-3) var(--space-4);
732
+ margin-bottom: var(--space-3);
733
+ background: var(--color-surface);
734
+ border: none;
735
+ border-radius: var(--radius-sm);
736
+ box-shadow: var(--shadow-sm);
737
+ cursor: pointer;
738
+ transition: box-shadow 120ms ease, transform 120ms ease;
739
+ }
740
+
741
+ .queue-card:hover {
742
+ box-shadow: var(--shadow-md);
743
+ transform: translateY(-1px);
744
+ }
745
+
746
+ .queue-card:active {
747
+ transform: scale(0.98);
748
+ }
749
+
750
+ .queue-avatar {
751
+ width: 36px;
752
+ height: 36px;
753
+ border-radius: 50%;
754
+ background: var(--color-provider-accent-light);
755
+ color: var(--color-provider-accent-text);
756
+ display: flex;
757
+ align-items: center;
758
+ justify-content: center;
759
+ font-weight: 700;
760
+ flex-shrink: 0;
761
+ }
762
+
763
+ .queue-body {
764
+ flex: 1;
765
+ min-width: 0;
766
+ }
767
+
768
+ .queue-top-row {
769
+ display: flex;
770
+ justify-content: space-between;
771
+ align-items: center;
772
+ gap: var(--space-2);
773
+ margin-bottom: 2px;
774
+ }
775
+
776
+ .queue-top-right {
777
+ display: flex;
778
+ align-items: center;
779
+ gap: var(--space-2);
780
+ flex-shrink: 0;
781
+ }
782
+
783
+ .queue-lang {
784
+ font-size: var(--text-sm);
785
+ font-weight: 600;
786
+ color: var(--color-text-secondary);
787
+ text-transform: capitalize;
788
+ }
789
+
790
+ .queue-preview {
791
+ color: var(--color-text);
792
+ overflow: hidden;
793
+ text-overflow: ellipsis;
794
+ white-space: nowrap;
795
+ }
796
+
797
+ /* ============================================================
798
+ Micro-animations: list entrance, mic ripple, skeleton loading
799
+ ============================================================ */
800
+
801
+ .list-item-in {
802
+ animation: list-item-in 260ms ease both;
803
+ }
804
+
805
+ @keyframes list-item-in {
806
+ from { opacity: 0; transform: translateY(10px); }
807
+ to { opacity: 1; transform: translateY(0); }
808
+ }
809
+
810
+ @media (prefers-reduced-motion: reduce) {
811
+ .list-item-in { animation: none; }
812
+ }
813
+
814
+ /* One-shot ripple on the inline mic button when tapped */
815
+ .mic-inline-btn {
816
+ position: absolute;
817
+ right: 8px;
818
+ bottom: 8px;
819
+ width: 38px;
820
+ height: 38px;
821
+ border-radius: 50%;
822
+ overflow: visible;
823
+ }
824
+
825
+ .mic-inline-btn::after {
826
+ content: "";
827
+ position: absolute;
828
+ inset: 0;
829
+ border-radius: 50%;
830
+ border: 2px solid var(--color-primary);
831
+ opacity: 0;
832
+ }
833
+
834
+ .mic-inline-btn.tapped::after {
835
+ animation: mic-ripple 500ms ease-out;
836
+ }
837
+
838
+ @keyframes mic-ripple {
839
+ 0% { opacity: 0.6; transform: scale(1); }
840
+ 100% { opacity: 0; transform: scale(1.9); }
841
+ }
842
+
843
+ @media (prefers-reduced-motion: reduce) {
844
+ .mic-inline-btn.tapped::after { animation: none; }
845
+ }
846
+
847
+ /* Skeleton loading shimmer, shown briefly while the queue or history
848
+ is being fetched, instead of a blank gap */
849
+ .skeleton-row {
850
+ height: 64px;
851
+ border-radius: var(--radius-sm);
852
+ margin-bottom: var(--space-3);
853
+ background: linear-gradient(100deg, var(--color-border) 30%, #F3EDD3 50%, var(--color-border) 70%);
854
+ background-size: 200% 100%;
855
+ animation: skeleton-shimmer 1300ms ease-in-out infinite;
856
+ }
857
+
858
+ @keyframes skeleton-shimmer {
859
+ from { background-position: 140% 0; }
860
+ to { background-position: -40% 0; }
861
+ }
862
+
863
+ @media (prefers-reduced-motion: reduce) {
864
+ .skeleton-row { animation: none; opacity: 0.6; }
865
+ }
866
+
867
+ /* Queue heading count, smooth transition when the number changes */
868
+ .queue-heading-text {
869
+ display: inline-block;
870
+ animation: count-change 220ms ease;
871
+ }
872
+
873
+ @keyframes count-change {
874
+ from { opacity: 0; transform: translateY(-4px); }
875
+ to { opacity: 1; transform: translateY(0); }
876
+ }
877
+
878
+ /* Relative timestamps on queue cards and history entries */
879
+ .timestamp {
880
+ font-size: var(--text-sm);
881
+ color: var(--color-text-secondary);
882
+ white-space: nowrap;
883
+ flex-shrink: 0;
884
+ }
885
+
886
+ /* Offline banner */
887
+ .offline-banner {
888
+ display: none;
889
+ align-items: center;
890
+ gap: var(--space-2);
891
+ background: var(--color-error-light);
892
+ color: var(--color-error);
893
+ padding: var(--space-3) var(--space-4);
894
+ border-radius: var(--radius-sm);
895
+ font-size: var(--text-sm);
896
+ font-weight: 600;
897
+ margin-bottom: var(--space-4);
898
+ animation: step-in 220ms ease;
899
+ }
900
+
901
+ .offline-banner.visible {
902
+ display: flex;
903
+ }
904
+
905
+ .offline-dot {
906
+ width: 8px;
907
+ height: 8px;
908
+ border-radius: 50%;
909
+ background: var(--color-error);
910
+ flex-shrink: 0;
911
+ animation: pulse 1.4s ease-in-out infinite;
912
+ }
913
+
914
+ /* ============================================================
915
+ Web / desktop environment (min-width: 900px)
916
+ Mobile layout above this point is untouched.
917
+ ============================================================ */
918
+
919
+ @media (min-width: 900px) {
920
+ body {
921
+ background:
922
+ radial-gradient(640px circle at 12% 8%, rgba(96, 108, 56, 0.10), transparent 60%),
923
+ radial-gradient(520px circle at 92% 85%, rgba(221, 161, 94, 0.16), transparent 60%),
924
+ var(--color-bg);
925
+ min-height: 100vh;
926
+ padding: var(--space-7) var(--space-5);
927
+ }
928
+
929
+ .app-shell {
930
+ max-width: 640px;
931
+ margin: 0 auto;
932
+ min-height: auto;
933
+ border-radius: 20px;
934
+ box-shadow: 0 30px 70px rgba(40, 54, 24, 0.16);
935
+ overflow: hidden;
936
+ }
937
+
938
+ /* The provider shell is wider, to make room for the two-column layout */
939
+ .app-shell.provider-shell {
940
+ max-width: 1080px;
941
+ }
942
+
943
+ .provider-page .app-main {
944
+ padding-bottom: var(--space-6);
945
+ }
946
+
947
+ .provider-layout {
948
+ display: grid;
949
+ grid-template-columns: 380px 1fr;
950
+ gap: var(--space-5);
951
+ align-items: start;
952
+ }
953
+
954
+ /* On desktop both panes stay visible, mobile's one-at-a-time step
955
+ system is only used below this breakpoint. */
956
+ .provider-layout .step {
957
+ display: block !important;
958
+ animation: none !important;
959
+ }
960
+
961
+ .provider-layout [data-step="list"] .hero {
962
+ text-align: left;
963
+ padding: 0 0 var(--space-4);
964
+ }
965
+
966
+ .provider-layout [data-step="list"] .hero-orb-wrap {
967
+ margin: 0 0 var(--space-3);
968
+ width: 64px;
969
+ height: 64px;
970
+ }
971
+
972
+ .provider-layout [data-step="list"] .hero-orb {
973
+ width: 56px;
974
+ height: 56px;
975
+ }
976
+
977
+ .provider-layout [data-step="list"] .hero-orb svg {
978
+ width: 24px;
979
+ height: 24px;
980
+ }
981
+
982
+ .provider-layout [data-step="list"] .hero-orb-glow {
983
+ inset: -10px;
984
+ }
985
+
986
+ .provider-layout [data-step="respond"] #back-to-list {
987
+ display: none;
988
+ }
989
+
990
+ .provider-layout [data-step="respond"] .btn-row {
991
+ justify-content: flex-end;
992
+ }
993
+
994
+ .provider-layout [data-step="respond"] .btn-provider {
995
+ width: auto;
996
+ padding-left: var(--space-6);
997
+ padding-right: var(--space-6);
998
+ }
999
+
1000
+ .detail-placeholder {
1001
+ display: flex;
1002
+ flex-direction: column;
1003
+ align-items: center;
1004
+ justify-content: center;
1005
+ text-align: center;
1006
+ gap: var(--space-3);
1007
+ min-height: 320px;
1008
+ border: 1px dashed var(--color-border);
1009
+ border-radius: var(--radius);
1010
+ padding: var(--space-6);
1011
+ color: var(--color-text-secondary);
1012
+ }
1013
+
1014
+ .detail-placeholder-mark {
1015
+ position: static;
1016
+ width: 44px;
1017
+ height: 44px;
1018
+ background: var(--color-provider-accent-light);
1019
+ }
1020
+
1021
+ .detail-placeholder-mark svg {
1022
+ width: 20px;
1023
+ height: 20px;
1024
+ color: var(--color-provider-accent-text);
1025
+ }
1026
+
1027
+ /* Patient shell: a composed, contained card on a filled background,
1028
+ rather than a phone screen stretched across a wide window. */
1029
+ .patient-shell .hero {
1030
+ padding-top: var(--space-3);
1031
+ }
1032
+ }
1033
+
1034
+ /* Icons inside buttons and labels */
1035
+ .icon {
1036
+ width: 18px;
1037
+ height: 18px;
1038
+ flex-shrink: 0;
1039
+ }
1040
+
1041
+ .icon-sm {
1042
+ width: 14px;
1043
+ height: 14px;
1044
+ }
1045
+
1046
+ /* Loading spinner, shown inside buttons while an AI step is running */
1047
+ .spinner {
1048
+ width: 16px;
1049
+ height: 16px;
1050
+ border-radius: 50%;
1051
+ border: 2px solid rgba(255, 255, 255, 0.4);
1052
+ border-top-color: currentColor;
1053
+ animation: spin 700ms linear infinite;
1054
+ flex-shrink: 0;
1055
+ }
1056
+
1057
+ .btn-secondary .spinner,
1058
+ .btn[disabled] .spinner {
1059
+ border: 2px solid rgba(0, 0, 0, 0.15);
1060
+ border-top-color: currentColor;
1061
+ }
1062
+
1063
+ @keyframes spin {
1064
+ to { transform: rotate(360deg); }
1065
+ }
1066
+
1067
+ @media (prefers-reduced-motion: reduce) {
1068
+ .spinner { animation-duration: 1400ms; }
1069
+ }
1070
+
1071
+ /* Recording timer */
1072
+ .record-timer {
1073
+ font-variant-numeric: tabular-nums;
1074
+ font-weight: 600;
1075
+ }
1076
+
1077
+ /* Status badges, used in the provider queue and patient history */
1078
+ .status-badge {
1079
+ display: inline-flex;
1080
+ align-items: center;
1081
+ gap: 4px;
1082
+ font-size: var(--text-sm);
1083
+ font-weight: 600;
1084
+ padding: 2px 10px;
1085
+ border-radius: 999px;
1086
+ }
1087
+
1088
+ .status-badge.waiting {
1089
+ background: var(--color-provider-accent-light);
1090
+ color: var(--color-provider-accent-text);
1091
+ }
1092
+
1093
+ .status-badge.answered {
1094
+ background: #E3EDE3;
1095
+ color: var(--color-success);
1096
+ }
1097
+
1098
+ /* Toast confirmation, appears briefly after an action completes */
1099
+ .toast {
1100
+ position: fixed;
1101
+ left: 50%;
1102
+ bottom: var(--space-6);
1103
+ transform: translateX(-50%) translateY(12px);
1104
+ background: var(--color-text);
1105
+ color: var(--color-bg);
1106
+ padding: var(--space-3) var(--space-5);
1107
+ border-radius: var(--radius);
1108
+ font-size: var(--text-sm);
1109
+ font-weight: 600;
1110
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
1111
+ opacity: 0;
1112
+ pointer-events: none;
1113
+ transition: opacity 200ms ease, transform 200ms ease;
1114
+ z-index: 100;
1115
+ }
1116
+
1117
+ .toast.visible {
1118
+ opacity: 1;
1119
+ transform: translateX(-50%) translateY(0);
1120
+ }