@arcblock/did-connect-service 4.0.6 → 4.0.7

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.
Files changed (67) hide show
  1. package/dist/_generated/asset-bytes.d.ts +3 -0
  2. package/dist/_generated/asset-bytes.d.ts.map +1 -0
  3. package/dist/_generated/asset-bytes.js +2 -0
  4. package/dist/_generated/asset-bytes.js.map +1 -0
  5. package/dist/_generated/asset-manifest.d.ts +3 -0
  6. package/dist/_generated/asset-manifest.d.ts.map +1 -0
  7. package/dist/_generated/asset-manifest.js +12 -0
  8. package/dist/_generated/asset-manifest.js.map +1 -0
  9. package/dist/asset-registry.d.ts +38 -0
  10. package/dist/asset-registry.d.ts.map +1 -0
  11. package/dist/asset-registry.js +73 -0
  12. package/dist/asset-registry.js.map +1 -0
  13. package/dist/assets/admin-core.c0b5af61.js +1393 -0
  14. package/dist/assets/admin-extra.7ca9c16b.js +2529 -0
  15. package/dist/assets/admin.c26bb17a.css +2219 -0
  16. package/dist/assets/design.99dc4ddc.css +97 -0
  17. package/dist/assets/did-address.7df30f28.js +51 -0
  18. package/dist/assets/header.94d9e46b.js +136 -0
  19. package/dist/assets/login.7b12c6dc.css +662 -0
  20. package/dist/assets/login.d3f05790.js +720 -0
  21. package/dist/assets/qr.c0d203ca.js +3 -0
  22. package/dist/handlers/auth-handler.d.ts.map +1 -1
  23. package/dist/handlers/auth-handler.js +10 -10
  24. package/dist/handlers/auth-handler.js.map +1 -1
  25. package/dist/pages/admin/index.d.ts.map +1 -1
  26. package/dist/pages/admin/index.js +25 -41
  27. package/dist/pages/admin/index.js.map +1 -1
  28. package/dist/pages/admin/tab-access.d.ts +1 -1
  29. package/dist/pages/admin/tab-access.d.ts.map +1 -1
  30. package/dist/pages/admin/tab-access.js +5 -2
  31. package/dist/pages/admin/tab-access.js.map +1 -1
  32. package/dist/pages/admin/tab-appearance.d.ts +1 -1
  33. package/dist/pages/admin/tab-appearance.d.ts.map +1 -1
  34. package/dist/pages/admin/tab-appearance.js +4 -2
  35. package/dist/pages/admin/tab-appearance.js.map +1 -1
  36. package/dist/pages/admin/tab-branding.d.ts.map +1 -1
  37. package/dist/pages/admin/tab-branding.js +4 -2
  38. package/dist/pages/admin/tab-branding.js.map +1 -1
  39. package/dist/pages/admin/tab-profile-accounts.d.ts.map +1 -1
  40. package/dist/pages/admin/tab-profile-accounts.js +4 -2
  41. package/dist/pages/admin/tab-profile-accounts.js.map +1 -1
  42. package/dist/pages/admin/tab-settings.d.ts.map +1 -1
  43. package/dist/pages/admin/tab-settings.js +4 -2
  44. package/dist/pages/admin/tab-settings.js.map +1 -1
  45. package/dist/pages/admin-instances-page.d.ts.map +1 -1
  46. package/dist/pages/admin-instances-page.js +4 -6
  47. package/dist/pages/admin-instances-page.js.map +1 -1
  48. package/dist/pages/error-page.d.ts.map +1 -1
  49. package/dist/pages/error-page.js +3 -2
  50. package/dist/pages/error-page.js.map +1 -1
  51. package/dist/pages/gen-access-key-page.d.ts.map +1 -1
  52. package/dist/pages/gen-access-key-page.js +3 -4
  53. package/dist/pages/gen-access-key-page.js.map +1 -1
  54. package/dist/pages/homepage.d.ts.map +1 -1
  55. package/dist/pages/homepage.js +4 -3
  56. package/dist/pages/homepage.js.map +1 -1
  57. package/dist/pages/invite-page.d.ts.map +1 -1
  58. package/dist/pages/invite-page.js +4 -4
  59. package/dist/pages/invite-page.js.map +1 -1
  60. package/dist/pages/login-page.d.ts.map +1 -1
  61. package/dist/pages/login-page.js +3 -4
  62. package/dist/pages/login-page.js.map +1 -1
  63. package/package.json +6 -4
  64. package/dist/identity/csrf.d.ts +0 -17
  65. package/dist/identity/csrf.d.ts.map +0 -1
  66. package/dist/identity/csrf.js +0 -56
  67. package/dist/identity/csrf.js.map +0 -1
@@ -0,0 +1,662 @@
1
+
2
+
3
+ :root {
4
+ /* Backgrounds — layered depth */
5
+ --bg-root: #0a0a0b;
6
+ --bg-surface: #141416;
7
+ --bg-card: #1c1c20;
8
+ --bg-elevated: #232328;
9
+ --bg-hover: #2b2b34;
10
+ --bg-active: #33333e;
11
+ --bg-input: rgba(255,255,255,0.06);
12
+
13
+ /* Borders — semi-transparent for adaptability */
14
+ --border: rgba(255,255,255,0.10);
15
+ --border-subtle:rgba(255,255,255,0.06);
16
+ --border-strong:rgba(255,255,255,0.15);
17
+ --border-focus: rgba(255,255,255,0.25);
18
+
19
+ /* Text hierarchy */
20
+ --text: #f5f5f7;
21
+ --text-secondary:#9394a1;
22
+ --text-tertiary:#767684;
23
+ --text-placeholder:#5e5f6e;
24
+ --text-white: #ffffff;
25
+
26
+ /* Accents */
27
+ --blue: #6c47ff;
28
+ --blue-hover: #5f15fe;
29
+ --blue-light: rgba(108,71,255,0.15);
30
+ --blue-muted: #9280ff;
31
+ --red: #e02e2e;
32
+ --red-light: rgba(224,46,46,0.15);
33
+ --red-text: #f98a8a;
34
+ --green: #15892b;
35
+ --green-light: rgba(21,137,43,0.15);
36
+ --green-text: #49dc6e;
37
+ --yellow: #fd7224;
38
+ --yellow-light: rgba(253,114,36,0.15);
39
+ --yellow-text: #fd9357;
40
+ --info: #236dd7;
41
+ --info-light: rgba(35,109,215,0.15);
42
+ --info-text: #73acfa;
43
+
44
+ /* Radii */
45
+ --radius-xs: 4px;
46
+ --radius-sm: 6px;
47
+ --radius: 8px;
48
+ --radius-lg: 12px;
49
+ --radius-full: 9999px;
50
+
51
+ /* Shadows */
52
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px -1px rgba(0,0,0,0.2);
53
+ --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.4), 0 2px 4px -2px rgba(0,0,0,0.3);
54
+ --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.5), 0 4px 6px -4px rgba(0,0,0,0.4);
55
+ --shadow-focus: 0 0 0 1px rgba(255,255,255,0.12), 0 0 0 3px rgba(108,71,255,0.3);
56
+ }
57
+
58
+
59
+ [data-theme="light"] {
60
+ --bg-root: #f8f9fa;
61
+ --bg-surface: #ffffff;
62
+ --bg-card: #ffffff;
63
+ --bg-elevated: #f0f1f3;
64
+ --bg-hover: #e9eaec;
65
+ --bg-active: #dddee1;
66
+ --bg-input: rgba(0,0,0,0.04);
67
+
68
+ --border: rgba(0,0,0,0.10);
69
+ --border-subtle:rgba(0,0,0,0.06);
70
+ --border-strong:rgba(0,0,0,0.15);
71
+ --border-focus: rgba(0,0,0,0.25);
72
+
73
+ --text: #1a1a1a;
74
+ --text-secondary:#6b7280;
75
+ --text-tertiary:#9ca3af;
76
+ --text-placeholder:#c0c5ce;
77
+ --text-white: #1a1a1a;
78
+
79
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px -1px rgba(0,0,0,0.06);
80
+ --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.06);
81
+ --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.12), 0 4px 6px -4px rgba(0,0,0,0.08);
82
+ --shadow-focus: 0 0 0 1px rgba(0,0,0,0.08), 0 0 0 3px rgba(108,71,255,0.2);
83
+ }
84
+
85
+
86
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
87
+ html { color-scheme: dark; }
88
+ html[data-theme="light"] { color-scheme: light; }
89
+ body {
90
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
91
+ background: var(--bg-root);
92
+ color: var(--text);
93
+ -webkit-font-smoothing: antialiased;
94
+ -moz-osx-font-smoothing: grayscale;
95
+ font-size: 14px;
96
+ line-height: 1.43;
97
+ }
98
+ a { color: var(--blue-muted); text-decoration: none; }
99
+ a:hover { text-decoration: underline; }
100
+ .hidden { display: none; }
101
+
102
+
103
+ /* Layout */
104
+ body {
105
+ min-height: 100vh;
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ background-image: radial-gradient(ellipse at 50% 0%, rgba(108,71,255,0.08) 0%, transparent 60%);
110
+ }
111
+
112
+ /* Card — fixed width prevents shrinking when views switch */
113
+ .card {
114
+ background: var(--bg-card);
115
+ border: 1px solid var(--border);
116
+ border-radius: var(--radius-lg);
117
+ padding: 48px 40px;
118
+ width: min(400px, calc(100vw - 32px));
119
+ text-align: center;
120
+ box-shadow: var(--shadow-lg), 0 0 80px -20px rgba(108,71,255,0.15);
121
+ }
122
+
123
+ /* Brand header */
124
+ .brand-header { margin-bottom: 24px; }
125
+ .app-logo {
126
+ width: 48px;
127
+ height: 48px;
128
+ border-radius: var(--radius-sm);
129
+ object-fit: contain;
130
+ margin-bottom: 16px;
131
+ }
132
+ h1 {
133
+ font-size: 24px;
134
+ font-weight: 600;
135
+ margin-bottom: 8px;
136
+ color: var(--text-white);
137
+ letter-spacing: -0.01em;
138
+ line-height: 1.25;
139
+ /* Never let a long "Sign in to {appName}" blow past two lines — clamp with
140
+ an ellipsis so the card height stays stable. */
141
+ display: -webkit-box;
142
+ -webkit-line-clamp: 2;
143
+ line-clamp: 2;
144
+ -webkit-box-orient: vertical;
145
+ overflow: hidden;
146
+ }
147
+ .subtitle {
148
+ font-size: 14px;
149
+ color: var(--text-secondary);
150
+ margin-bottom: 0;
151
+ line-height: 1.5;
152
+ }
153
+ .federated-hint {
154
+ font-size: 12px;
155
+ color: var(--text-secondary);
156
+ margin-top: 6px;
157
+ margin-bottom: 0;
158
+ opacity: 0.7;
159
+ }
160
+
161
+ /* Input */
162
+ .input {
163
+ width: 100%;
164
+ height: 36px;
165
+ padding: 0 12px;
166
+ font-size: 14px;
167
+ color: var(--text);
168
+ background: var(--bg-input);
169
+ border: 1px solid var(--border-strong);
170
+ border-radius: var(--radius-sm);
171
+ outline: none;
172
+ margin-bottom: 16px;
173
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
174
+ }
175
+ .input:focus { border-color: var(--blue); box-shadow: var(--shadow-focus); }
176
+ .input::placeholder { color: var(--text-placeholder); }
177
+
178
+ /* Button */
179
+ .btn {
180
+ display: inline-flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ gap: 6px;
184
+ width: 100%;
185
+ height: 36px;
186
+ padding: 0 16px;
187
+ font-size: 14px;
188
+ font-weight: 500;
189
+ color: #fff;
190
+ background: var(--blue);
191
+ border: none;
192
+ border-radius: var(--radius-sm);
193
+ cursor: pointer;
194
+ transition: background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
195
+ line-height: 1;
196
+ }
197
+ .btn:hover { background: var(--blue-hover); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(108,71,255,0.3); }
198
+ .btn:disabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; transform: none; box-shadow: none; }
199
+ .btn:focus-visible { box-shadow: var(--shadow-focus); }
200
+ .btn svg { width: 18px; height: 18px; flex-shrink: 0; }
201
+ .btn-secondary {
202
+ background: transparent;
203
+ border: 1px solid var(--border-strong);
204
+ color: var(--text);
205
+ }
206
+ .btn-secondary:hover { background: var(--bg-hover); border-color: rgba(255,255,255,0.20); }
207
+
208
+ /* Status */
209
+ .status {
210
+ margin-top: 16px;
211
+ font-size: 13px;
212
+ min-height: 20px;
213
+ color: var(--text-secondary);
214
+ }
215
+ .status.error { color: var(--red-text); }
216
+
217
+ /* Name row (passkey registration) */
218
+ .name-row { display: none; }
219
+ .name-row.visible { display: block; }
220
+
221
+ /* Passkey section + secondary text action ("First time? Create a passkey") */
222
+ .passkey-section > .btn + .passkey-alt,
223
+ .passkey-section > .name-row + .btn { margin-top: 10px; }
224
+ .passkey-alt {
225
+ display: block;
226
+ width: 100%;
227
+ margin-top: 10px;
228
+ padding: 4px;
229
+ background: none;
230
+ border: none;
231
+ font-size: 13px;
232
+ color: var(--text-secondary);
233
+ cursor: pointer;
234
+ text-align: center;
235
+ transition: color 0.15s ease;
236
+ }
237
+ .passkey-alt:hover { color: var(--text); text-decoration: underline; }
238
+ .passkey-alt:focus-visible { box-shadow: var(--shadow-focus); border-radius: var(--radius-sm); outline: none; }
239
+
240
+ /* Divider */
241
+ .divider {
242
+ display: flex;
243
+ align-items: center;
244
+ margin: 20px 0;
245
+ color: var(--text-secondary);
246
+ font-size: 13px;
247
+ }
248
+ .divider::before, .divider::after {
249
+ content: '';
250
+ flex: 1;
251
+ border-bottom: 1px solid var(--border);
252
+ }
253
+ .divider::before { margin-right: 12px; }
254
+ .divider::after { margin-left: 12px; }
255
+
256
+ /* DID Wallet section (methods view) */
257
+ .did-wallet-section { margin-top: 8px; }
258
+
259
+ /* QR view */
260
+ .qr-view {
261
+ position: relative;
262
+ margin: 20px auto;
263
+ display: flex;
264
+ justify-content: center;
265
+ min-height: 220px;
266
+ align-items: center;
267
+ }
268
+ .qr-placeholder {
269
+ width: 220px;
270
+ height: 220px;
271
+ display: flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ border: 1px solid var(--border-subtle);
275
+ border-radius: var(--radius);
276
+ background: var(--bg-elevated);
277
+ }
278
+ .qr-spinner {
279
+ display: inline-block;
280
+ width: 32px; height: 32px;
281
+ border: 3px solid var(--border-strong);
282
+ border-top-color: var(--blue-muted);
283
+ border-radius: 50%;
284
+ animation: spin 0.6s linear infinite;
285
+ }
286
+ #did-connect-status {
287
+ font-size: 13px;
288
+ color: var(--text-secondary);
289
+ }
290
+
291
+ /* Connect result state */
292
+ .connect-result {
293
+ display: flex;
294
+ justify-content: center;
295
+ align-items: center;
296
+ min-height: 120px;
297
+ margin: 32px 0;
298
+ animation: fadeIn 200ms ease-out;
299
+ }
300
+ .result-icon {
301
+ width: 64px;
302
+ height: 64px;
303
+ border-radius: 50%;
304
+ display: flex;
305
+ align-items: center;
306
+ justify-content: center;
307
+ font-size: 28px;
308
+ font-weight: bold;
309
+ }
310
+ .result-error {
311
+ background: rgba(239, 68, 68, 0.15);
312
+ color: var(--red-text);
313
+ border: 2px solid rgba(239, 68, 68, 0.3);
314
+ }
315
+ .result-loading {
316
+ background: transparent;
317
+ }
318
+ .result-loading .qr-spinner {
319
+ width: 36px;
320
+ height: 36px;
321
+ }
322
+ .result-back-btn {
323
+ margin-top: 16px;
324
+ }
325
+ @keyframes fadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
326
+
327
+ /* QR timeout overlay */
328
+ .qr-timeout-overlay {
329
+ position: absolute;
330
+ inset: 0;
331
+ display: flex;
332
+ flex-direction: column;
333
+ align-items: center;
334
+ justify-content: center;
335
+ gap: 12px;
336
+ background: rgba(0, 0, 0, 0.65);
337
+ border-radius: var(--radius);
338
+ backdrop-filter: blur(2px);
339
+ }
340
+ .qr-timeout-overlay .timeout-text {
341
+ font-size: 13px;
342
+ color: #fff;
343
+ }
344
+ .qr-timeout-overlay .refresh-btn {
345
+ display: inline-flex;
346
+ align-items: center;
347
+ justify-content: center;
348
+ gap: 6px;
349
+ padding: 6px 20px;
350
+ font-size: 14px;
351
+ font-weight: 500;
352
+ color: #fff;
353
+ background: var(--blue);
354
+ border: none;
355
+ border-radius: var(--radius-sm);
356
+ cursor: pointer;
357
+ transition: background-color 0.15s ease;
358
+ }
359
+ .qr-timeout-overlay .refresh-btn:hover {
360
+ background: var(--blue-hover);
361
+ }
362
+ /* Connect status views (scanned / success) */
363
+ .connect-status-icon {
364
+ position: relative;
365
+ width: 72px;
366
+ height: 72px;
367
+ margin: 16px auto;
368
+ display: flex;
369
+ align-items: center;
370
+ justify-content: center;
371
+ }
372
+ @keyframes connectSpin { to { transform: rotate(360deg); } }
373
+ .connect-spinner-ring {
374
+ position: absolute;
375
+ inset: 0;
376
+ width: 72px;
377
+ height: 72px;
378
+ border-radius: 50%;
379
+ border: 3px solid rgba(255,255,255,0.1);
380
+ border-top-color: var(--blue, #6c47ff);
381
+ animation: connectSpin 0.8s linear infinite;
382
+ }
383
+ .connect-status-badge {
384
+ position: relative;
385
+ display: flex;
386
+ align-items: center;
387
+ justify-content: center;
388
+ width: 44px;
389
+ height: 44px;
390
+ }
391
+ .connect-status-badge svg { width: 36px; height: 36px; }
392
+ .connect-status-icon.connect-success svg { animation: fadeIn 0.3s ease; }
393
+ .connect-subtitle {
394
+ font-size: 13px;
395
+ color: var(--text-secondary, #9394a1);
396
+ text-align: center;
397
+ margin: 4px 0 0;
398
+ }
399
+ .status.success { color: #49dc6e; font-weight: 500; }
400
+ .deep-link-btn {
401
+ margin-top: 12px;
402
+ text-decoration: none;
403
+ }
404
+
405
+ /* Email section (methods view) */
406
+ .email-section { margin-top: 8px; }
407
+
408
+ /* Back button */
409
+ .back-btn {
410
+ display: inline-flex;
411
+ align-items: center;
412
+ gap: 4px;
413
+ background: none;
414
+ border: none;
415
+ color: var(--text-secondary);
416
+ font-size: 14px;
417
+ cursor: pointer;
418
+ padding: 0;
419
+ margin-bottom: 16px;
420
+ float: left;
421
+ }
422
+ .back-btn:hover { color: var(--text); }
423
+ .back-btn svg { width: 18px; height: 18px; }
424
+ /* Escape hatch — a quiet "Cancel" link, top-left of the card, mirroring the
425
+ locale switcher (top-right). Conventional spot for a standalone auth card.
426
+ Low in the hierarchy (tertiary color, small) so it never competes with the
427
+ auth methods; it's an exit, not an action. */
428
+ .home-link {
429
+ position: absolute;
430
+ top: 16px;
431
+ /* Align the arrow's left edge to the content column (card's 40px padding), so
432
+ Cancel sits on the same left line as the title and buttons — no left padding
433
+ of its own, which would push it off that line. */
434
+ left: 40px;
435
+ display: inline-flex;
436
+ align-items: center;
437
+ gap: 3px;
438
+ background: none;
439
+ border: none;
440
+ color: var(--text-tertiary);
441
+ font-size: 13px;
442
+ line-height: 1;
443
+ text-decoration: none;
444
+ cursor: pointer;
445
+ padding: 2px 4px 2px 0;
446
+ transition: color 0.15s ease;
447
+ }
448
+ .home-link:hover { color: var(--text-secondary); }
449
+ .home-link svg { width: 16px; height: 16px; }
450
+
451
+ /* View title */
452
+ .view-title {
453
+ font-size: 20px;
454
+ font-weight: 600;
455
+ color: var(--text-white);
456
+ margin-bottom: 8px;
457
+ clear: both;
458
+ padding-top: 8px;
459
+ }
460
+
461
+ /* OAuth section — single provider (legacy) */
462
+ .oauth-section { margin-top: 0; }
463
+
464
+ /* OAuth grid — 2+ providers in 2-column layout (legacy) */
465
+ .oauth-grid {
466
+ display: grid;
467
+ grid-template-columns: 1fr 1fr;
468
+ gap: 8px;
469
+ margin-bottom: 8px;
470
+ }
471
+ .oauth-grid .oauth-btn:last-child:nth-child(odd) {
472
+ grid-column: 1 / -1;
473
+ }
474
+
475
+ /* Unified secondary methods grid — 2-column layout */
476
+ .methods-grid {
477
+ display: grid;
478
+ grid-template-columns: 1fr 1fr;
479
+ gap: 8px;
480
+ }
481
+ /* Odd last child (e.g. DID Wallet when total is odd) spans full width */
482
+ .methods-grid .method-btn:last-child:nth-child(odd) {
483
+ grid-column: 1 / -1;
484
+ }
485
+
486
+ .method-btn {
487
+ display: inline-flex;
488
+ align-items: center;
489
+ justify-content: center;
490
+ gap: 8px;
491
+ width: 100%;
492
+ min-height: 36px;
493
+ padding: 6px 16px;
494
+ font-size: 14px;
495
+ font-weight: 500;
496
+ color: var(--text);
497
+ background: var(--bg-elevated);
498
+ border: 1px solid var(--border-strong);
499
+ border-radius: var(--radius-sm);
500
+ cursor: pointer;
501
+ transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.2s ease;
502
+ white-space: normal;
503
+ }
504
+ .method-btn:hover { background: var(--bg-hover); border-color: var(--blue-muted); }
505
+ .method-btn:disabled { cursor: default; pointer-events: none; }
506
+ .method-btn svg { width: 18px; height: 18px; flex-shrink: 0; }
507
+
508
+ .oauth-btn {
509
+ display: inline-flex;
510
+ align-items: center;
511
+ justify-content: center;
512
+ gap: 8px;
513
+ width: 100%;
514
+ height: 36px;
515
+ padding: 0 16px;
516
+ font-size: 14px;
517
+ font-weight: 500;
518
+ color: var(--text);
519
+ background: var(--bg-card);
520
+ border: 1px solid var(--border);
521
+ border-radius: var(--radius-sm);
522
+ cursor: pointer;
523
+ transition: background-color 0.15s ease, opacity 0.2s ease, border-color 0.2s ease;
524
+ margin-bottom: 0;
525
+ }
526
+ .oauth-section .oauth-btn { margin-bottom: 8px; }
527
+ .oauth-btn:hover { background: var(--bg-hover); }
528
+ .oauth-btn:disabled { cursor: default; pointer-events: none; }
529
+ .oauth-btn svg { width: 18px; height: 18px; flex-shrink: 0; }
530
+ .oauth-btn-loading {
531
+ opacity: 0.8;
532
+ border-color: var(--blue);
533
+ color: var(--text-secondary);
534
+ }
535
+ @keyframes oauth-spin { to { transform: rotate(360deg); } }
536
+ .oauth-spinner {
537
+ display: inline-block;
538
+ width: 14px; height: 14px;
539
+ border: 2px solid var(--border-strong);
540
+ border-top-color: var(--blue-muted);
541
+ border-radius: 50%;
542
+ animation: oauth-spin 0.6s linear infinite;
543
+ }
544
+ .oauth-check { color: var(--green-text); font-size: 16px; }
545
+
546
+ /* Browser compatibility warning */
547
+ .compat-warning {
548
+ font-size: 13px;
549
+ color: var(--text-tertiary);
550
+ padding: 12px;
551
+ background: var(--bg-elevated);
552
+ border-radius: var(--radius-sm);
553
+ margin-bottom: 16px;
554
+ }
555
+
556
+ /* Trust footer */
557
+ .login-footer {
558
+ margin-top: 24px;
559
+ padding-top: 20px;
560
+ border-top: 1px solid var(--border);
561
+ }
562
+ .secured-badge {
563
+ display: flex;
564
+ align-items: center;
565
+ justify-content: center;
566
+ gap: 6px;
567
+ font-size: 12px;
568
+ color: var(--text-tertiary);
569
+ }
570
+ .secured-badge svg { width: 14px; height: 14px; flex-shrink: 0; }
571
+ .footer-links {
572
+ margin-top: 8px;
573
+ font-size: 12px;
574
+ color: var(--text-tertiary);
575
+ }
576
+ .footer-links a {
577
+ color: var(--text-secondary);
578
+ text-decoration: none;
579
+ }
580
+ .footer-links a:hover { text-decoration: underline; }
581
+
582
+ /* ─── Animations ─────────────────────────────────────────────── */
583
+ @keyframes fadeIn {
584
+ from { opacity: 0; transform: translateY(4px); }
585
+ to { opacity: 1; transform: translateY(0); }
586
+ }
587
+ @keyframes fadeOut {
588
+ from { opacity: 1; }
589
+ to { opacity: 0; }
590
+ }
591
+ .card[data-view] { animation: fadeIn 200ms ease-out; }
592
+
593
+ /* QR code scale-in */
594
+ .qr-view { animation: qrScaleIn 300ms ease-out; }
595
+ @keyframes qrScaleIn {
596
+ from { opacity: 0; transform: scale(0.95); }
597
+ to { opacity: 1; transform: scale(1); }
598
+ }
599
+
600
+ /* Button loading spinner */
601
+ @keyframes spin { to { transform: rotate(360deg); } }
602
+ .btn-spinner {
603
+ display: inline-block;
604
+ width: 16px; height: 16px;
605
+ border: 2px solid rgba(255,255,255,0.3);
606
+ border-top-color: #fff;
607
+ border-radius: 50%;
608
+ animation: spin 0.6s linear infinite;
609
+ }
610
+
611
+ /* Success checkmark */
612
+ @keyframes checkDraw {
613
+ from { stroke-dashoffset: 24; }
614
+ to { stroke-dashoffset: 0; }
615
+ }
616
+ .success-check {
617
+ display: inline-block;
618
+ width: 20px; height: 20px;
619
+ vertical-align: middle;
620
+ }
621
+ .success-check path {
622
+ stroke-dasharray: 24;
623
+ stroke-dashoffset: 24;
624
+ animation: checkDraw 400ms ease-out forwards;
625
+ }
626
+
627
+ /* Light theme background gradient adjustment */
628
+ [data-theme="light"] body {
629
+ background-image: radial-gradient(ellipse at 50% 0%, rgba(108,71,255,0.05) 0%, transparent 60%);
630
+ }
631
+ [data-theme="light"] .card {
632
+ box-shadow: var(--shadow-lg), 0 0 80px -20px rgba(108,71,255,0.08);
633
+ }
634
+ [data-theme="light"] .btn:hover {
635
+ box-shadow: 0 2px 8px rgba(108,71,255,0.15);
636
+ }
637
+
638
+ /* Language switcher */
639
+ .locale-switcher {
640
+ position: absolute;
641
+ top: 16px;
642
+ right: 16px;
643
+ }
644
+ .locale-btn {
645
+ display: inline-flex;
646
+ align-items: center;
647
+ gap: 4px;
648
+ padding: 4px 10px;
649
+ font-size: 12px;
650
+ color: var(--text-secondary);
651
+ background: var(--bg-elevated);
652
+ border: 1px solid var(--border-subtle);
653
+ border-radius: var(--radius-full);
654
+ cursor: pointer;
655
+ transition: color 0.15s, border-color 0.15s;
656
+ }
657
+ .locale-btn:hover {
658
+ color: var(--text);
659
+ border-color: var(--border-strong);
660
+ }
661
+ .locale-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
662
+ .card { position: relative; }