@umituz/web-dashboard 3.2.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +228 -14
  2. package/package.json +23 -30
  3. package/src/domains/analytics/components/AnalyticsCard.tsx +43 -42
  4. package/src/domains/analytics/components/AnalyticsChart.tsx +345 -149
  5. package/src/domains/analytics/components/AnalyticsLayout.tsx +93 -112
  6. package/src/domains/analytics/components/MetricCard.tsx +29 -87
  7. package/src/domains/analytics/hooks/index.ts +7 -1
  8. package/src/domains/analytics/hooks/useAnalytics.ts +144 -139
  9. package/src/domains/analytics/index.ts +11 -0
  10. package/src/domains/analytics/services/AnalyticsEngineService.ts +103 -55
  11. package/src/domains/analytics/services/PerformanceService.ts +117 -69
  12. package/src/domains/analytics/types/analytics.ts +20 -6
  13. package/src/domains/analytics/types/index.ts +3 -0
  14. package/src/domains/analytics/utils/analytics.test.ts +183 -0
  15. package/src/domains/analytics/utils/analytics.ts +26 -9
  16. package/src/domains/analytics/utils/i18nKeys.ts +40 -0
  17. package/src/domains/analytics/utils/index.ts +2 -0
  18. package/src/domains/auth/components/AuthLayout.tsx +63 -54
  19. package/src/domains/auth/components/ForgotPasswordForm.tsx +96 -98
  20. package/src/domains/auth/components/LoginForm.tsx +167 -226
  21. package/src/domains/auth/components/RegisterForm.tsx +202 -272
  22. package/src/domains/auth/components/ResetPasswordForm.tsx +105 -151
  23. package/src/domains/auth/components/shared/AuthErrorBanner.tsx +35 -0
  24. package/src/domains/auth/components/shared/EmailInput.tsx +91 -0
  25. package/src/domains/auth/components/shared/PasswordInput.tsx +119 -0
  26. package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +75 -0
  27. package/src/domains/auth/components/shared/SocialLoginButtons.tsx +58 -0
  28. package/src/domains/auth/components/shared/SocialProviderIcons.tsx +48 -0
  29. package/src/domains/auth/components/shared/index.ts +20 -0
  30. package/src/domains/auth/hooks/index.ts +1 -0
  31. package/src/domains/auth/hooks/useAuth.ts +151 -232
  32. package/src/domains/auth/index.ts +8 -4
  33. package/src/domains/auth/types/auth.ts +26 -5
  34. package/src/domains/auth/types/index.ts +1 -0
  35. package/src/domains/auth/utils/auth.test.ts +182 -0
  36. package/src/domains/auth/utils/auth.ts +71 -130
  37. package/src/domains/auth/utils/i18nKeys.ts +127 -0
  38. package/src/domains/auth/utils/index.ts +7 -1
  39. package/src/domains/auth/utils/secureToken.ts +33 -0
  40. package/src/domains/auth/utils/validationKeys.ts +23 -0
  41. package/src/domains/calendar/hooks/useCalendar.ts +145 -151
  42. package/src/domains/calendar/index.ts +0 -1
  43. package/src/domains/calendar/services/CalendarService.ts +122 -179
  44. package/src/domains/calendar/utils/contentItemMapper.test.ts +108 -0
  45. package/src/domains/calendar/utils/contentItemMapper.ts +99 -0
  46. package/src/domains/calendar/utils/index.ts +33 -30
  47. package/src/domains/layouts/components/BrandLogo.tsx +12 -9
  48. package/src/domains/layouts/components/DashboardHeader.tsx +78 -80
  49. package/src/domains/layouts/components/DashboardLayout.tsx +45 -21
  50. package/src/domains/layouts/components/DashboardSidebar.tsx +48 -51
  51. package/src/domains/layouts/types/layout.ts +7 -1
  52. package/src/domains/layouts/types/user.ts +3 -1
  53. package/src/domains/modules/build.test.tsx +97 -0
  54. package/src/domains/modules/build.tsx +71 -0
  55. package/src/domains/modules/index.ts +2 -0
  56. package/src/domains/modules/types.ts +29 -0
  57. package/src/domains/onboarding/components/AppFocusStep.tsx +99 -68
  58. package/src/domains/onboarding/components/OnboardingWizard.tsx +109 -183
  59. package/src/domains/onboarding/components/PlanStep.tsx +156 -123
  60. package/src/domains/onboarding/components/PlatformsStep.tsx +74 -54
  61. package/src/domains/onboarding/components/StepNavigation.tsx +108 -0
  62. package/src/domains/onboarding/components/StepProgress.tsx +62 -0
  63. package/src/domains/onboarding/components/UserTypeStep.tsx +59 -80
  64. package/src/domains/onboarding/components/index.ts +4 -0
  65. package/src/domains/onboarding/hooks/useOnboarding.ts +76 -66
  66. package/src/domains/onboarding/index.ts +1 -0
  67. package/src/domains/onboarding/types/onboarding.ts +57 -17
  68. package/src/domains/onboarding/utils/i18nKeys.ts +72 -0
  69. package/src/domains/onboarding/utils/index.ts +2 -0
  70. package/src/domains/permissions/PermissionsContext.tsx +103 -0
  71. package/src/domains/permissions/hasPermission.test.ts +50 -0
  72. package/src/domains/permissions/hasPermission.ts +38 -0
  73. package/src/domains/permissions/index.ts +19 -0
  74. package/src/domains/permissions/types.ts +35 -0
  75. package/src/domains/permissions/utils/i18nKeys.ts +11 -0
  76. package/src/domains/session/DemoLogin.tsx +50 -0
  77. package/src/domains/session/OrgSwitcher.tsx +110 -0
  78. package/src/domains/session/SessionContext.tsx +150 -0
  79. package/src/domains/session/inMemoryAuthAdapter.ts +53 -0
  80. package/src/domains/session/index.ts +18 -0
  81. package/src/domains/session/types.ts +47 -0
  82. package/src/domains/session/utils/i18nKeys.ts +12 -0
  83. package/src/domains/settings/components/AuditLogList.tsx +59 -0
  84. package/src/domains/settings/components/PermissionMatrixScreen.tsx +80 -0
  85. package/src/domains/settings/components/SettingsLayout.tsx +75 -60
  86. package/src/domains/settings/components/SettingsSection.tsx +35 -22
  87. package/src/domains/settings/components/UserManagementTable.tsx +69 -0
  88. package/src/domains/settings/components/index.ts +10 -0
  89. package/src/domains/settings/hooks/useSettings.ts +77 -52
  90. package/src/domains/settings/types/settings.ts +2 -0
  91. package/src/domains/settings/utils/i18nKeys.ts +18 -0
  92. package/src/domains/settings/utils/index.ts +1 -0
  93. package/src/domains/settings/utils/settings.ts +11 -4
  94. package/src/i18n/I18nContext.tsx +33 -0
  95. package/src/i18n/defaultT.test.ts +43 -0
  96. package/src/i18n/defaultT.ts +34 -0
  97. package/src/i18n/index.ts +7 -0
  98. package/src/i18n/types.ts +13 -0
  99. package/src/index.ts +1 -7
  100. package/src/primitives/Button.tsx +24 -0
  101. package/src/primitives/Checkbox.tsx +17 -0
  102. package/src/primitives/Input.tsx +23 -0
  103. package/src/primitives/Skeleton.tsx +6 -0
  104. package/src/primitives/cn.ts +10 -0
  105. package/src/primitives/index.ts +23 -0
  106. package/src/styles/dashboard.css +2731 -0
  107. package/src/styles/tokens.contract.test.ts +91 -0
  108. package/src/styles/tokens.css +116 -0
  109. package/src/domains/billing/components/BillingLayout.tsx +0 -63
  110. package/src/domains/billing/components/BillingPage.tsx +0 -49
  111. package/src/domains/billing/components/BillingPortal.tsx +0 -198
  112. package/src/domains/billing/components/InvoiceCard.tsx +0 -143
  113. package/src/domains/billing/components/PaymentMethodsList.tsx +0 -116
  114. package/src/domains/billing/components/PlanComparison.tsx +0 -199
  115. package/src/domains/billing/components/UsageCard.tsx +0 -103
  116. package/src/domains/billing/components/index.ts +0 -13
  117. package/src/domains/billing/constants/billing.ts +0 -69
  118. package/src/domains/billing/hooks/index.ts +0 -7
  119. package/src/domains/billing/hooks/useBilling.ts +0 -385
  120. package/src/domains/billing/index.ts +0 -73
  121. package/src/domains/billing/types/billing.ts +0 -342
  122. package/src/domains/billing/types/index.ts +0 -30
  123. package/src/domains/billing/utils/billing.ts +0 -360
  124. package/src/domains/billing/utils/index.ts +0 -31
  125. package/src/domains/billing/utils/polar.ts +0 -63
  126. package/src/domains/calendar/components/index.ts +0 -7
@@ -0,0 +1,2731 @@
1
+ /**
2
+ * @umituz/web-dashboard — component stylesheet (udb-* BEM)
3
+ *
4
+ * Camp-agnostic by construction:
5
+ * - Every rule sets its own box-sizing / background / border explicitly,
6
+ * so a host's Tailwind preflight (or any other reset) cannot leak in.
7
+ * - Load order still matters with resets that use `*` selectors: import
8
+ * this file AFTER your base layer.
9
+ * - Colors, spacing and typography come exclusively from the `--u-*`
10
+ * tokens (see `tokens.css`); override them for theming and dark mode.
11
+ *
12
+ * Sections:
13
+ * 1. Scope & reset 5. Header/menus 9. Settings
14
+ * 2. Layout helpers 6. Auth 10. Analytics
15
+ * 3. App shell 7. Forms (auth) 11. Shared blocks
16
+ * 4. Sidebar 8. Onboarding
17
+ */
18
+
19
+ @import "@umituz/web-design-system/styles.css";
20
+ @import "./tokens.css";
21
+
22
+ /* ============================================================
23
+ * 1. Scope & reset
24
+ * ============================================================ */
25
+
26
+ .udb-root,
27
+ .udb-root *,
28
+ .udb-root *::before,
29
+ .udb-root *::after {
30
+ box-sizing: border-box;
31
+ }
32
+
33
+ .udb-root {
34
+ font-family: var(--u-font-sans);
35
+ color: var(--u-color-text);
36
+ background: var(--u-color-bg);
37
+ font-size: var(--u-font-size-md);
38
+ line-height: 1.5;
39
+ -webkit-font-smoothing: antialiased;
40
+ }
41
+
42
+ /* Screen-reader-only helper (replaces utility-framework sr-only). */
43
+ .udb-sr-only {
44
+ position: absolute;
45
+ width: 1px;
46
+ height: 1px;
47
+ padding: 0;
48
+ margin: -1px;
49
+ overflow: hidden;
50
+ clip: rect(0 0 0 0);
51
+ white-space: nowrap;
52
+ border: 0;
53
+ }
54
+
55
+ /* ============================================================
56
+ * 2. Layout helpers
57
+ * ============================================================ */
58
+
59
+ .udb-stack {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: var(--u-space-5);
63
+ }
64
+
65
+ .udb-row {
66
+ display: flex;
67
+ align-items: center;
68
+ }
69
+
70
+ .udb-grid {
71
+ display: grid;
72
+ gap: var(--u-space-5);
73
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
74
+ }
75
+
76
+ .udb-card--sm {
77
+ padding: var(--u-space-4);
78
+ }
79
+
80
+ .udb-card--lg {
81
+ padding: var(--u-space-8);
82
+ }
83
+
84
+ /* ============================================================
85
+ * 3. App shell
86
+ * ============================================================ */
87
+
88
+ .udb-layout {
89
+ display: flex;
90
+ height: 100vh;
91
+ width: 100%;
92
+ overflow: hidden;
93
+ }
94
+
95
+ .udb-layout__sidebar {
96
+ display: none;
97
+ flex-direction: column;
98
+ flex-shrink: 0;
99
+ width: var(--u-sidebar-width);
100
+ border-right: 1px solid var(--u-sidebar-border);
101
+ background: var(--u-sidebar-bg);
102
+ transition: width 0.3s ease;
103
+ }
104
+
105
+ .udb-layout__sidebar--collapsed {
106
+ width: var(--u-sidebar-width-collapsed);
107
+ }
108
+
109
+ .udb-layout__mobile {
110
+ position: fixed;
111
+ inset: 0;
112
+ z-index: 50;
113
+ }
114
+
115
+ .udb-layout__backdrop {
116
+ position: absolute;
117
+ inset: 0;
118
+ background: rgba(15, 23, 42, 0.45);
119
+ }
120
+
121
+ .udb-layout__mobile-sidebar {
122
+ position: absolute;
123
+ left: 0;
124
+ top: 0;
125
+ height: 100%;
126
+ width: var(--u-sidebar-width);
127
+ border-right: 1px solid var(--u-sidebar-border);
128
+ background: var(--u-sidebar-bg);
129
+ box-shadow: var(--u-shadow-lg);
130
+ }
131
+
132
+ .udb-layout__main {
133
+ display: flex;
134
+ flex: 1;
135
+ flex-direction: column;
136
+ overflow: hidden;
137
+ min-width: 0;
138
+ }
139
+
140
+ .udb-layout__content {
141
+ flex: 1;
142
+ overflow-y: auto;
143
+ padding: var(--u-space-4);
144
+ }
145
+
146
+ /* Full desktop behavior from 768px up. */
147
+ @media (min-width: 768px) {
148
+ .udb-layout__sidebar {
149
+ display: flex;
150
+ }
151
+
152
+ .udb-layout__content {
153
+ padding: var(--u-space-7);
154
+ }
155
+ }
156
+
157
+ /* Route-transition skeleton page. */
158
+ .udb-page-skeleton {
159
+ margin: 0 auto;
160
+ width: 100%;
161
+ max-width: 1280px;
162
+ display: flex;
163
+ flex-direction: column;
164
+ gap: var(--u-space-6);
165
+ }
166
+
167
+ .udb-skeleton--title {
168
+ height: 32px;
169
+ width: 33%;
170
+ border-radius: var(--u-radius-lg);
171
+ }
172
+
173
+ .udb-skeleton-grid {
174
+ display: grid;
175
+ gap: var(--u-space-4);
176
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
177
+ }
178
+
179
+ .udb-skeleton--card {
180
+ height: 112px;
181
+ border-radius: var(--u-radius-xl);
182
+ }
183
+
184
+ .udb-skeleton--section {
185
+ height: 256px;
186
+ border-radius: var(--u-radius-xl);
187
+ }
188
+
189
+ /* ============================================================
190
+ * 4. Sidebar
191
+ * ============================================================ */
192
+
193
+ .udb-sidebar {
194
+ display: flex;
195
+ flex-direction: column;
196
+ height: 100%;
197
+ width: 100%;
198
+ color: var(--u-sidebar-text);
199
+ }
200
+
201
+ .udb-sidebar__brand {
202
+ display: flex;
203
+ height: var(--u-header-height);
204
+ align-items: center;
205
+ gap: var(--u-space-3);
206
+ border-bottom: 1px solid var(--u-sidebar-border);
207
+ padding: 0 var(--u-space-4);
208
+ }
209
+
210
+ .udb-brand-logo {
211
+ flex-shrink: 0;
212
+ }
213
+
214
+ .udb-sidebar__brand-text {
215
+ display: flex;
216
+ flex-direction: column;
217
+ min-width: 0;
218
+ }
219
+
220
+ .udb-sidebar__brand-name {
221
+ font-size: var(--u-font-size-2xl);
222
+ font-weight: 900;
223
+ letter-spacing: -0.04em;
224
+ line-height: 1;
225
+ color: var(--u-sidebar-text);
226
+ }
227
+
228
+ .udb-sidebar__brand-tagline {
229
+ margin-top: var(--u-space-2);
230
+ margin-left: var(--u-space-1);
231
+ font-size: var(--u-font-size-xs);
232
+ font-weight: var(--u-font-weight-bold);
233
+ text-transform: lowercase;
234
+ letter-spacing: -0.02em;
235
+ color: var(--u-color-primary);
236
+ opacity: 0.75;
237
+ user-select: none;
238
+ }
239
+
240
+ .udb-sidebar__create {
241
+ padding: var(--u-space-4) var(--u-space-3);
242
+ border-bottom: 1px solid var(--u-sidebar-border);
243
+ }
244
+
245
+ .udb-sidebar__create-btn {
246
+ width: 100%;
247
+ height: 44px;
248
+ justify-content: flex-start;
249
+ padding: 0 var(--u-space-4);
250
+ border-radius: var(--u-radius-lg);
251
+ box-shadow: var(--u-shadow-md);
252
+ }
253
+
254
+ .udb-sidebar__create-btn--collapsed {
255
+ width: 40px;
256
+ height: 40px;
257
+ padding: 0;
258
+ margin: 0 auto;
259
+ justify-content: center;
260
+ }
261
+
262
+ .udb-sidebar__create-icon {
263
+ width: 16px;
264
+ height: 16px;
265
+ flex-shrink: 0;
266
+ }
267
+
268
+ .udb-sidebar__create-label {
269
+ font-weight: var(--u-font-weight-bold);
270
+ letter-spacing: -0.02em;
271
+ }
272
+
273
+ .udb-sidebar__nav {
274
+ flex: 1;
275
+ overflow-y: auto;
276
+ padding: var(--u-space-3) var(--u-space-2);
277
+ }
278
+
279
+ .udb-sidebar__groups {
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: var(--u-space-6);
283
+ }
284
+
285
+ .udb-sidebar__group {
286
+ display: flex;
287
+ flex-direction: column;
288
+ gap: var(--u-space-1);
289
+ }
290
+
291
+ .udb-sidebar__group-toggle {
292
+ display: flex;
293
+ width: 100%;
294
+ align-items: center;
295
+ justify-content: space-between;
296
+ margin-bottom: var(--u-space-1);
297
+ padding: var(--u-space-2) var(--u-space-3);
298
+ border: none;
299
+ border-radius: var(--u-radius-md);
300
+ background: transparent;
301
+ cursor: pointer;
302
+ }
303
+
304
+ .udb-sidebar__group-toggle:hover {
305
+ background: var(--u-sidebar-accent);
306
+ }
307
+
308
+ .udb-sidebar__group-title {
309
+ font-size: 10px;
310
+ font-weight: var(--u-font-weight-bold);
311
+ text-transform: uppercase;
312
+ letter-spacing: 0.12em;
313
+ color: var(--u-sidebar-muted);
314
+ opacity: 0.75;
315
+ }
316
+
317
+ .udb-sidebar__group-chevron {
318
+ display: flex;
319
+ flex-shrink: 0;
320
+ }
321
+
322
+ .udb-sidebar__chevron-icon {
323
+ width: 14px;
324
+ height: 14px;
325
+ color: var(--u-sidebar-muted);
326
+ }
327
+
328
+ .udb-sidebar__item {
329
+ display: flex;
330
+ align-items: center;
331
+ gap: var(--u-space-3);
332
+ padding: 10px var(--u-space-3);
333
+ border-radius: var(--u-radius-md);
334
+ font-size: var(--u-font-size-md);
335
+ font-weight: var(--u-font-weight-medium);
336
+ color: var(--u-sidebar-text);
337
+ opacity: 0.75;
338
+ text-decoration: none;
339
+ transition: background-color 0.2s ease, color 0.2s ease;
340
+ }
341
+
342
+ .udb-sidebar__item:hover {
343
+ background: var(--u-sidebar-accent);
344
+ color: var(--u-sidebar-accent-text);
345
+ opacity: 1;
346
+ }
347
+
348
+ .udb-sidebar__item--active {
349
+ background: var(--u-sidebar-accent);
350
+ color: var(--u-sidebar-accent-text);
351
+ opacity: 1;
352
+ box-shadow: var(--u-shadow-sm);
353
+ }
354
+
355
+ .udb-sidebar__item-icon {
356
+ width: 16px;
357
+ height: 16px;
358
+ flex-shrink: 0;
359
+ }
360
+
361
+ .udb-sidebar--collapsed .udb-sidebar__item {
362
+ justify-content: center;
363
+ }
364
+
365
+ .udb-sidebar--collapsed .udb-sidebar__brand,
366
+ .udb-sidebar--collapsed .udb-sidebar__create {
367
+ justify-content: center;
368
+ padding-left: 0;
369
+ padding-right: 0;
370
+ }
371
+
372
+ .udb-sidebar__footer {
373
+ border-top: 1px solid var(--u-sidebar-border);
374
+ padding: var(--u-space-3);
375
+ display: flex;
376
+ align-items: center;
377
+ justify-content: space-between;
378
+ }
379
+
380
+ .udb-sidebar--collapsed .udb-sidebar__footer {
381
+ justify-content: center;
382
+ }
383
+
384
+ .udb-sidebar__footer-label {
385
+ padding: 0 var(--u-space-2);
386
+ font-size: 10px;
387
+ font-weight: var(--u-font-weight-bold);
388
+ text-transform: uppercase;
389
+ letter-spacing: 0.1em;
390
+ color: var(--u-sidebar-muted);
391
+ }
392
+
393
+ .udb-sidebar__footer-btn {
394
+ color: var(--u-sidebar-text);
395
+ }
396
+
397
+ .udb-sidebar__footer-icon {
398
+ width: 16px;
399
+ height: 16px;
400
+ }
401
+
402
+ /* ============================================================
403
+ * 5. Header / menus / notifications / profile
404
+ * ============================================================ */
405
+
406
+ .udb-header {
407
+ display: flex;
408
+ height: var(--u-header-height);
409
+ align-items: center;
410
+ justify-content: space-between;
411
+ flex-shrink: 0;
412
+ gap: var(--u-space-3);
413
+ border-bottom: 1px solid var(--u-color-border);
414
+ background: var(--u-color-surface);
415
+ padding: 0 var(--u-space-4);
416
+ z-index: 30;
417
+ }
418
+
419
+ .udb-header__lead {
420
+ display: flex;
421
+ align-items: center;
422
+ gap: var(--u-space-3);
423
+ min-width: 0;
424
+ }
425
+
426
+ .udb-header__title {
427
+ margin: 0;
428
+ font-size: var(--u-font-size-md);
429
+ font-weight: 600;
430
+ color: var(--u-color-text);
431
+ overflow: hidden;
432
+ text-overflow: ellipsis;
433
+ white-space: nowrap;
434
+ }
435
+
436
+ .udb-header__mobile-toggle {
437
+ display: inline-flex;
438
+ }
439
+
440
+ .udb-header__desktop-toggle {
441
+ display: none;
442
+ }
443
+
444
+ @media (min-width: 768px) {
445
+ .udb-header__mobile-toggle {
446
+ display: none;
447
+ }
448
+
449
+ .udb-header__desktop-toggle {
450
+ display: inline-flex;
451
+ }
452
+ }
453
+
454
+ .udb-header__actions {
455
+ display: flex;
456
+ align-items: center;
457
+ gap: var(--u-space-2);
458
+ }
459
+
460
+ .udb-header__icon-btn {
461
+ height: 36px;
462
+ width: 36px;
463
+ color: var(--u-color-muted);
464
+ }
465
+
466
+ .udb-header__icon {
467
+ width: 16px;
468
+ height: 16px;
469
+ }
470
+
471
+ .udb-header__toggle-icon {
472
+ width: 20px;
473
+ height: 20px;
474
+ }
475
+
476
+ .udb-header__anchor {
477
+ position: relative;
478
+ display: inline-flex;
479
+ }
480
+
481
+ .udb-header__unread {
482
+ position: absolute;
483
+ top: 6px;
484
+ right: 6px;
485
+ display: flex;
486
+ width: 8px;
487
+ height: 8px;
488
+ }
489
+
490
+ .udb-header__unread-core {
491
+ position: relative;
492
+ display: inline-flex;
493
+ width: 8px;
494
+ height: 8px;
495
+ border-radius: 50%;
496
+ background: var(--u-color-danger);
497
+ }
498
+
499
+ .udb-header__unread-core::before {
500
+ content: "";
501
+ position: absolute;
502
+ inset: 0;
503
+ border-radius: 50%;
504
+ background: var(--u-color-danger);
505
+ animation: udb-ping 1.2s cubic-bezier(0, 0, 0.2, 1) infinite;
506
+ }
507
+
508
+ @keyframes udb-ping {
509
+ 0% {
510
+ transform: scale(1);
511
+ opacity: 0.7;
512
+ }
513
+ 75%,
514
+ 100% {
515
+ transform: scale(2.2);
516
+ opacity: 0;
517
+ }
518
+ }
519
+
520
+ .udb-header__divider {
521
+ width: 1px;
522
+ height: 24px;
523
+ margin: 0 var(--u-space-1);
524
+ background: var(--u-color-border);
525
+ }
526
+
527
+ /* Click-outside layer for popover menus. */
528
+ .udb-overlay {
529
+ position: fixed;
530
+ inset: 0;
531
+ z-index: 40;
532
+ }
533
+
534
+ /* Generic popover menu. */
535
+ .udb-menu {
536
+ position: absolute;
537
+ top: 48px;
538
+ right: 0;
539
+ min-width: 224px;
540
+ background: var(--u-color-surface);
541
+ border: 1px solid var(--u-color-border);
542
+ border-radius: var(--u-radius-lg);
543
+ box-shadow: var(--u-shadow-lg);
544
+ overflow: hidden;
545
+ z-index: 50;
546
+ animation: udb-pop 0.18s ease;
547
+ }
548
+
549
+ @keyframes udb-pop {
550
+ from {
551
+ opacity: 0;
552
+ transform: scale(0.96) translateY(-4px);
553
+ }
554
+ to {
555
+ opacity: 1;
556
+ transform: none;
557
+ }
558
+ }
559
+
560
+ .udb-menu__header {
561
+ display: flex;
562
+ align-items: center;
563
+ justify-content: space-between;
564
+ padding: var(--u-space-3) var(--u-space-4);
565
+ border-bottom: 1px solid var(--u-color-border);
566
+ background: var(--u-color-surface-muted);
567
+ }
568
+
569
+ .udb-menu__heading {
570
+ margin: 0;
571
+ font-size: var(--u-font-size-sm);
572
+ font-weight: var(--u-font-weight-bold);
573
+ text-transform: uppercase;
574
+ letter-spacing: 0.08em;
575
+ color: var(--u-color-text);
576
+ }
577
+
578
+ .udb-menu__action {
579
+ border: none;
580
+ background: transparent;
581
+ padding: 0;
582
+ font-size: 10px;
583
+ font-weight: var(--u-font-weight-bold);
584
+ text-transform: uppercase;
585
+ color: var(--u-color-primary);
586
+ cursor: pointer;
587
+ }
588
+
589
+ .udb-menu__action:hover {
590
+ text-decoration: underline;
591
+ }
592
+
593
+ .udb-menu__item {
594
+ display: flex;
595
+ width: 100%;
596
+ align-items: center;
597
+ gap: 10px;
598
+ padding: var(--u-space-2) var(--u-space-3);
599
+ border: none;
600
+ border-radius: var(--u-radius-md);
601
+ background: transparent;
602
+ font-family: inherit;
603
+ font-size: var(--u-font-size-md);
604
+ color: var(--u-color-text);
605
+ cursor: pointer;
606
+ text-align: left;
607
+ }
608
+
609
+ .udb-menu__item:hover {
610
+ background: var(--u-color-surface-muted);
611
+ }
612
+
613
+ .udb-menu__item--danger {
614
+ color: var(--u-color-danger);
615
+ font-weight: var(--u-font-weight-medium);
616
+ }
617
+
618
+ .udb-menu__item--danger:hover {
619
+ background: var(--u-color-danger-soft);
620
+ }
621
+
622
+ .udb-menu__item-icon {
623
+ width: 16px;
624
+ height: 16px;
625
+ color: var(--u-color-muted);
626
+ flex-shrink: 0;
627
+ }
628
+
629
+ .udb-menu__item--danger .udb-menu__item-icon {
630
+ color: var(--u-color-danger);
631
+ }
632
+
633
+ /* Notifications popover. */
634
+ .udb-notif {
635
+ width: 320px;
636
+ }
637
+
638
+ .udb-notif__list {
639
+ max-height: 400px;
640
+ overflow-y: auto;
641
+ }
642
+
643
+ .udb-notif__item {
644
+ display: flex;
645
+ align-items: flex-start;
646
+ gap: var(--u-space-3);
647
+ padding: var(--u-space-3) var(--u-space-4);
648
+ border-bottom: 1px solid var(--u-color-border);
649
+ }
650
+
651
+ .udb-notif__item:last-child {
652
+ border-bottom: none;
653
+ }
654
+
655
+ .udb-notif__item:hover {
656
+ background: var(--u-color-surface-muted);
657
+ }
658
+
659
+ .udb-notif__item--unread {
660
+ background: var(--u-color-primary-soft);
661
+ }
662
+
663
+ .udb-notif__body {
664
+ flex: 1;
665
+ min-width: 0;
666
+ }
667
+
668
+ .udb-notif__text {
669
+ margin: 0;
670
+ font-size: var(--u-font-size-md);
671
+ line-height: 1.35;
672
+ color: var(--u-color-text);
673
+ }
674
+
675
+ .udb-notif__meta {
676
+ display: flex;
677
+ align-items: center;
678
+ gap: var(--u-space-1);
679
+ margin: var(--u-space-1) 0 0;
680
+ font-size: 10px;
681
+ color: var(--u-color-muted);
682
+ }
683
+
684
+ .udb-notif__dot {
685
+ display: inline-block;
686
+ width: 4px;
687
+ height: 4px;
688
+ border-radius: 50%;
689
+ background: var(--u-color-muted);
690
+ opacity: 0.5;
691
+ }
692
+
693
+ .udb-notif__dismiss {
694
+ display: flex;
695
+ flex-shrink: 0;
696
+ border: none;
697
+ padding: 0;
698
+ background: transparent;
699
+ color: var(--u-color-muted);
700
+ cursor: pointer;
701
+ }
702
+
703
+ .udb-notif__dismiss:hover {
704
+ color: var(--u-color-text);
705
+ }
706
+
707
+ .udb-notif__dismiss-icon {
708
+ width: 12px;
709
+ height: 12px;
710
+ }
711
+
712
+ .udb-notif__empty {
713
+ padding: var(--u-space-8) var(--u-space-4);
714
+ text-align: center;
715
+ }
716
+
717
+ .udb-notif__empty-icon {
718
+ display: flex;
719
+ width: 40px;
720
+ height: 40px;
721
+ align-items: center;
722
+ justify-content: center;
723
+ margin: 0 auto var(--u-space-3);
724
+ border-radius: 50%;
725
+ background: var(--u-color-surface-muted);
726
+ }
727
+
728
+ .udb-notif__empty-bell {
729
+ width: 20px;
730
+ height: 20px;
731
+ color: var(--u-color-muted);
732
+ opacity: 0.6;
733
+ }
734
+
735
+ .udb-notif__empty-text {
736
+ margin: 0;
737
+ font-size: var(--u-font-size-md);
738
+ color: var(--u-color-muted);
739
+ }
740
+
741
+ /* Profile trigger & menu. */
742
+ .udb-profile-btn {
743
+ display: flex;
744
+ align-items: center;
745
+ gap: var(--u-space-2);
746
+ padding: var(--u-space-1);
747
+ border: none;
748
+ border-radius: var(--u-radius-pill);
749
+ background: transparent;
750
+ cursor: pointer;
751
+ }
752
+
753
+ .udb-profile-btn:hover {
754
+ background: var(--u-color-surface-muted);
755
+ }
756
+
757
+ .udb-avatar {
758
+ display: flex;
759
+ width: 32px;
760
+ height: 32px;
761
+ align-items: center;
762
+ justify-content: center;
763
+ border-radius: 50%;
764
+ border: 1px solid var(--u-color-primary);
765
+ background: var(--u-color-primary-soft);
766
+ color: var(--u-color-primary);
767
+ font-size: 10px;
768
+ font-weight: var(--u-font-weight-bold);
769
+ overflow: hidden;
770
+ }
771
+
772
+ .udb-avatar__img {
773
+ width: 100%;
774
+ height: 100%;
775
+ object-fit: cover;
776
+ display: block;
777
+ }
778
+
779
+ .udb-profile-btn__chevron {
780
+ width: 16px;
781
+ height: 16px;
782
+ color: var(--u-color-muted);
783
+ transition: transform 0.2s ease;
784
+ }
785
+
786
+ .udb-profile-btn__chevron--open {
787
+ transform: rotate(180deg);
788
+ }
789
+
790
+ .udb-profile-menu {
791
+ width: 224px;
792
+ padding: var(--u-space-2);
793
+ }
794
+
795
+ .udb-profile-menu__id {
796
+ padding: var(--u-space-2) var(--u-space-3);
797
+ border-bottom: 1px solid var(--u-color-border);
798
+ margin-bottom: var(--u-space-1);
799
+ }
800
+
801
+ .udb-profile-menu__name {
802
+ margin: 0;
803
+ font-size: var(--u-font-size-md);
804
+ font-weight: var(--u-font-weight-bold);
805
+ color: var(--u-color-text);
806
+ }
807
+
808
+ .udb-profile-menu__email {
809
+ margin: 0;
810
+ font-size: var(--u-font-size-sm);
811
+ color: var(--u-color-muted);
812
+ overflow: hidden;
813
+ text-overflow: ellipsis;
814
+ white-space: nowrap;
815
+ }
816
+
817
+ .udb-profile-menu__items {
818
+ display: flex;
819
+ flex-direction: column;
820
+ }
821
+
822
+ .udb-profile-menu__separator {
823
+ height: 1px;
824
+ margin: var(--u-space-2) 0;
825
+ background: var(--u-color-border);
826
+ }
827
+
828
+ /* ============================================================
829
+ * 6. Auth pages
830
+ * ============================================================ */
831
+
832
+ .udb-auth {
833
+ display: flex;
834
+ flex-direction: column;
835
+ min-height: 100dvh;
836
+ background: var(--u-color-bg);
837
+ }
838
+
839
+ .udb-auth__header {
840
+ display: flex;
841
+ align-items: center;
842
+ justify-content: space-between;
843
+ gap: var(--u-space-3);
844
+ padding: var(--u-space-4) var(--u-space-6);
845
+ }
846
+
847
+ .udb-auth__brand {
848
+ display: flex;
849
+ align-items: center;
850
+ gap: var(--u-space-2);
851
+ }
852
+
853
+ .udb-auth__brand-name {
854
+ font-size: var(--u-font-size-lg);
855
+ font-weight: var(--u-font-weight-bold);
856
+ letter-spacing: -0.02em;
857
+ color: var(--u-color-text);
858
+ }
859
+
860
+ .udb-auth__home-link {
861
+ font-size: var(--u-font-size-md);
862
+ color: var(--u-color-muted);
863
+ text-decoration: none;
864
+ }
865
+
866
+ .udb-auth__home-link:hover {
867
+ color: var(--u-color-text);
868
+ text-decoration: underline;
869
+ }
870
+
871
+ .udb-auth__main {
872
+ display: flex;
873
+ flex: 1;
874
+ align-items: center;
875
+ justify-content: center;
876
+ padding: var(--u-space-6) var(--u-space-4);
877
+ }
878
+
879
+ .udb-auth__column {
880
+ display: flex;
881
+ flex-direction: column;
882
+ width: 100%;
883
+ max-width: 420px;
884
+ }
885
+
886
+ .udb-auth__card {
887
+ background: var(--u-color-surface);
888
+ border: 1px solid var(--u-color-border);
889
+ border-radius: var(--u-radius-xl);
890
+ box-shadow: var(--u-shadow-lg);
891
+ padding: var(--u-space-8) var(--u-space-7);
892
+ }
893
+
894
+ .udb-auth__tagline {
895
+ margin: 0 0 var(--u-space-5);
896
+ text-align: center;
897
+ font-size: var(--u-font-size-xs);
898
+ font-weight: var(--u-font-weight-bold);
899
+ text-transform: uppercase;
900
+ letter-spacing: 0.1em;
901
+ color: var(--u-color-primary);
902
+ }
903
+
904
+ .udb-auth__social {
905
+ margin-top: var(--u-space-5);
906
+ }
907
+
908
+ .udb-auth__footer {
909
+ padding: var(--u-space-4) var(--u-space-6);
910
+ }
911
+
912
+ .udb-auth__footer-inner {
913
+ display: flex;
914
+ flex-direction: column;
915
+ align-items: center;
916
+ gap: var(--u-space-2);
917
+ text-align: center;
918
+ font-size: var(--u-font-size-xs);
919
+ color: var(--u-color-muted);
920
+ }
921
+
922
+ .udb-auth__footer-inner > p {
923
+ margin: 0;
924
+ }
925
+
926
+ .udb-auth__footer-links {
927
+ display: flex;
928
+ align-items: center;
929
+ justify-content: center;
930
+ flex-wrap: wrap;
931
+ gap: var(--u-space-4);
932
+ }
933
+
934
+ .udb-auth__footer-link {
935
+ font-size: var(--u-font-size-xs);
936
+ color: var(--u-color-muted);
937
+ text-decoration: none;
938
+ }
939
+
940
+ .udb-auth__footer-link:hover {
941
+ color: var(--u-color-text);
942
+ text-decoration: underline;
943
+ }
944
+
945
+ /* "Or continue with" divider. */
946
+ .udb-divider-row {
947
+ display: flex;
948
+ align-items: center;
949
+ gap: var(--u-space-3);
950
+ margin: var(--u-space-5) 0;
951
+ }
952
+
953
+ .udb-divider-row::before,
954
+ .udb-divider-row::after {
955
+ content: "";
956
+ flex: 1;
957
+ height: 1px;
958
+ background: var(--u-color-border);
959
+ }
960
+
961
+ .udb-divider-row__label {
962
+ font-size: var(--u-font-size-xs);
963
+ font-weight: var(--u-font-weight-medium);
964
+ text-transform: uppercase;
965
+ letter-spacing: 0.06em;
966
+ color: var(--u-color-muted);
967
+ white-space: nowrap;
968
+ }
969
+
970
+ /* Social provider buttons. */
971
+ .udb-social-grid {
972
+ display: grid;
973
+ grid-template-columns: repeat(2, minmax(0, 1fr));
974
+ gap: var(--u-space-3);
975
+ }
976
+
977
+ .udb-social-grid__btn {
978
+ width: 100%;
979
+ }
980
+
981
+ .udb-social-grid__icon {
982
+ width: 16px;
983
+ height: 16px;
984
+ flex-shrink: 0;
985
+ }
986
+
987
+ /* Standalone social button (AuthLayout provider grid). */
988
+ .udb-social-btn {
989
+ display: inline-flex;
990
+ align-items: center;
991
+ justify-content: center;
992
+ gap: var(--u-space-2);
993
+ height: 40px;
994
+ padding: 0 var(--u-space-3);
995
+ border: 1px solid var(--u-color-border-strong);
996
+ border-radius: var(--u-radius-md);
997
+ background: var(--u-color-surface);
998
+ color: var(--u-color-text);
999
+ font-family: inherit;
1000
+ font-size: var(--u-font-size-md);
1001
+ font-weight: var(--u-font-weight-medium);
1002
+ cursor: pointer;
1003
+ }
1004
+
1005
+ .udb-social-btn:hover {
1006
+ background: var(--u-color-surface-muted);
1007
+ }
1008
+
1009
+ .udb-social-btn__icon {
1010
+ display: inline-flex;
1011
+ align-items: center;
1012
+ justify-content: center;
1013
+ flex-shrink: 0;
1014
+ }
1015
+
1016
+ .udb-social-btn__icon svg {
1017
+ width: 16px;
1018
+ height: 16px;
1019
+ }
1020
+
1021
+ /* ============================================================
1022
+ * 7. Forms (auth + generic fields)
1023
+ * ============================================================ */
1024
+
1025
+ /* Shared spinner (also used by onboarding/analytics icons). */
1026
+ @keyframes udb-spin {
1027
+ to {
1028
+ transform: rotate(360deg);
1029
+ }
1030
+ }
1031
+
1032
+ .udb-spin {
1033
+ animation: udb-spin 1s linear infinite;
1034
+ }
1035
+
1036
+ .udb-form {
1037
+ display: flex;
1038
+ flex-direction: column;
1039
+ gap: var(--u-space-4);
1040
+ width: 100%;
1041
+ }
1042
+
1043
+ .udb-form__header {
1044
+ display: flex;
1045
+ flex-direction: column;
1046
+ gap: var(--u-space-1);
1047
+ text-align: center;
1048
+ }
1049
+
1050
+ .udb-form__title {
1051
+ margin: 0;
1052
+ font-size: var(--u-font-size-2xl);
1053
+ font-weight: var(--u-font-weight-bold);
1054
+ letter-spacing: -0.02em;
1055
+ line-height: 1.2;
1056
+ color: var(--u-color-text);
1057
+ }
1058
+
1059
+ .udb-form__title--lg {
1060
+ font-size: var(--u-font-size-3xl);
1061
+ }
1062
+
1063
+ .udb-form__subtitle {
1064
+ margin: 0;
1065
+ font-size: var(--u-font-size-md);
1066
+ color: var(--u-color-muted);
1067
+ }
1068
+
1069
+ .udb-form__subtitle-strong {
1070
+ color: var(--u-color-text);
1071
+ font-weight: var(--u-font-weight-medium);
1072
+ }
1073
+
1074
+ .udb-form__row {
1075
+ display: flex;
1076
+ align-items: center;
1077
+ justify-content: space-between;
1078
+ gap: var(--u-space-3);
1079
+ font-size: var(--u-font-size-md);
1080
+ }
1081
+
1082
+ .udb-form__footer-text {
1083
+ margin: 0;
1084
+ text-align: center;
1085
+ font-size: var(--u-font-size-md);
1086
+ color: var(--u-color-muted);
1087
+ }
1088
+
1089
+ /* Tighter group inside a form (e.g. password + strength meter). */
1090
+ .udb-form__group {
1091
+ display: flex;
1092
+ flex-direction: column;
1093
+ gap: var(--u-space-3);
1094
+ }
1095
+
1096
+ /* Single labeled field. */
1097
+ .udb-field {
1098
+ display: flex;
1099
+ flex-direction: column;
1100
+ gap: 6px;
1101
+ }
1102
+
1103
+ .udb-field__label {
1104
+ font-size: var(--u-font-size-md);
1105
+ font-weight: var(--u-font-weight-medium);
1106
+ color: var(--u-color-text);
1107
+ }
1108
+
1109
+ .udb-field__required {
1110
+ margin-left: 2px;
1111
+ color: var(--u-color-danger);
1112
+ }
1113
+
1114
+ .udb-field__error {
1115
+ margin: 0;
1116
+ font-size: var(--u-font-size-sm);
1117
+ color: var(--u-color-danger);
1118
+ }
1119
+
1120
+ /* Inline error banner. */
1121
+ .udb-form-alert {
1122
+ display: flex;
1123
+ align-items: flex-start;
1124
+ gap: var(--u-space-2);
1125
+ padding: 10px var(--u-space-3);
1126
+ border-radius: var(--u-radius-md);
1127
+ background: var(--u-color-danger-soft);
1128
+ color: var(--u-color-danger);
1129
+ font-size: var(--u-font-size-md);
1130
+ }
1131
+
1132
+ .udb-form-alert__icon {
1133
+ width: 16px;
1134
+ height: 16px;
1135
+ flex-shrink: 0;
1136
+ margin-top: 2px;
1137
+ }
1138
+
1139
+ /* Checkbox line (remember me, terms). */
1140
+ .udb-check-label {
1141
+ display: flex;
1142
+ align-items: center;
1143
+ gap: var(--u-space-2);
1144
+ font-size: var(--u-font-size-md);
1145
+ color: var(--u-color-muted);
1146
+ cursor: pointer;
1147
+ }
1148
+
1149
+ .udb-check-label--multiline {
1150
+ align-items: flex-start;
1151
+ }
1152
+
1153
+ .udb-check-label__text {
1154
+ flex: 1;
1155
+ line-height: 1.45;
1156
+ }
1157
+
1158
+ /* Inline text buttons ("Forgot password?", "Sign up"). */
1159
+ .udb-link-btn {
1160
+ display: inline;
1161
+ border: none;
1162
+ padding: 0;
1163
+ background: transparent;
1164
+ font-family: inherit;
1165
+ font-size: var(--u-font-size-md);
1166
+ color: var(--u-color-primary);
1167
+ cursor: pointer;
1168
+ }
1169
+
1170
+ .udb-link-btn:hover {
1171
+ text-decoration: underline;
1172
+ }
1173
+
1174
+ .udb-link-btn:disabled {
1175
+ pointer-events: none;
1176
+ opacity: 0.55;
1177
+ }
1178
+
1179
+ .udb-link-btn--strong {
1180
+ font-weight: 600;
1181
+ }
1182
+
1183
+ .udb-text-link {
1184
+ color: var(--u-color-primary);
1185
+ text-decoration: none;
1186
+ }
1187
+
1188
+ .udb-text-link:hover {
1189
+ text-decoration: underline;
1190
+ }
1191
+
1192
+ /* Full-width submit button. */
1193
+ .udb-submit-btn {
1194
+ width: 100%;
1195
+ height: 44px;
1196
+ }
1197
+
1198
+ .udb-submit-btn--pill {
1199
+ height: 48px;
1200
+ border-radius: var(--u-radius-pill);
1201
+ }
1202
+
1203
+ .udb-btn__spinner {
1204
+ animation: udb-spin 1s linear infinite;
1205
+ }
1206
+
1207
+ /* Password field with visibility toggle. */
1208
+ .udb-password-wrap {
1209
+ position: relative;
1210
+ width: 100%;
1211
+ }
1212
+
1213
+ .udb-input--with-toggle {
1214
+ padding-right: 44px;
1215
+ }
1216
+
1217
+ .udb-password-toggle {
1218
+ position: absolute;
1219
+ right: 2px;
1220
+ top: 50%;
1221
+ transform: translateY(-50%);
1222
+ }
1223
+
1224
+ .udb-password-toggle__icon {
1225
+ width: 16px;
1226
+ height: 16px;
1227
+ color: var(--u-color-muted);
1228
+ }
1229
+
1230
+ .udb-input--error {
1231
+ border-color: var(--u-color-danger);
1232
+ }
1233
+
1234
+ .udb-input--error:focus-visible {
1235
+ border-color: var(--u-color-danger);
1236
+ box-shadow: 0 0 0 3px var(--u-color-danger-soft);
1237
+ }
1238
+
1239
+ /* Password strength meter. */
1240
+ .udb-strength {
1241
+ display: flex;
1242
+ flex-direction: column;
1243
+ gap: 6px;
1244
+ margin-top: var(--u-space-1);
1245
+ }
1246
+
1247
+ .udb-strength__bars {
1248
+ display: grid;
1249
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1250
+ gap: var(--u-space-2);
1251
+ }
1252
+
1253
+ .udb-strength__bar {
1254
+ height: 4px;
1255
+ border-radius: var(--u-radius-pill);
1256
+ background: var(--u-color-border-strong);
1257
+ transition: background-color 0.2s ease;
1258
+ }
1259
+
1260
+ .udb-strength__bar--weak {
1261
+ background: var(--u-color-danger);
1262
+ }
1263
+
1264
+ .udb-strength__bar--fair {
1265
+ background: var(--u-color-warning);
1266
+ }
1267
+
1268
+ .udb-strength__bar--good {
1269
+ background: var(--u-color-primary);
1270
+ }
1271
+
1272
+ .udb-strength__bar--strong {
1273
+ background: var(--u-color-success);
1274
+ }
1275
+
1276
+ .udb-strength__label {
1277
+ margin: 0;
1278
+ font-size: var(--u-font-size-xs);
1279
+ color: var(--u-color-muted);
1280
+ }
1281
+
1282
+ .udb-strength__label--weak {
1283
+ color: var(--u-color-danger);
1284
+ }
1285
+
1286
+ .udb-strength__label--fair {
1287
+ color: var(--u-color-warning);
1288
+ }
1289
+
1290
+ .udb-strength__label--good {
1291
+ color: var(--u-color-primary);
1292
+ }
1293
+
1294
+ .udb-strength__label--strong {
1295
+ color: var(--u-color-success);
1296
+ }
1297
+
1298
+ /* Success badge + ordered steps (forgot-password done state). */
1299
+ .udb-success-badge {
1300
+ display: flex;
1301
+ align-items: center;
1302
+ justify-content: center;
1303
+ width: 48px;
1304
+ height: 48px;
1305
+ margin: 0 auto var(--u-space-4);
1306
+ border-radius: 50%;
1307
+ background: var(--u-color-success-soft);
1308
+ }
1309
+
1310
+ .udb-success-badge__icon {
1311
+ width: 24px;
1312
+ height: 24px;
1313
+ color: var(--u-color-success);
1314
+ }
1315
+
1316
+ .udb-steps-list {
1317
+ display: flex;
1318
+ flex-direction: column;
1319
+ gap: var(--u-space-3);
1320
+ margin: var(--u-space-4) 0 0;
1321
+ padding: 0;
1322
+ list-style: none;
1323
+ }
1324
+
1325
+ .udb-steps-list__item {
1326
+ display: flex;
1327
+ align-items: flex-start;
1328
+ gap: var(--u-space-2);
1329
+ font-size: var(--u-font-size-md);
1330
+ color: var(--u-color-text);
1331
+ }
1332
+
1333
+ .udb-steps-list__icon {
1334
+ width: 16px;
1335
+ height: 16px;
1336
+ flex-shrink: 0;
1337
+ margin-top: 2px;
1338
+ color: var(--u-color-success);
1339
+ }
1340
+
1341
+ .udb-back-link {
1342
+ display: inline-flex;
1343
+ align-items: center;
1344
+ gap: 6px;
1345
+ margin-top: var(--u-space-4);
1346
+ border: none;
1347
+ padding: 0;
1348
+ background: transparent;
1349
+ font-family: inherit;
1350
+ font-size: var(--u-font-size-md);
1351
+ color: var(--u-color-muted);
1352
+ cursor: pointer;
1353
+ }
1354
+
1355
+ .udb-back-link:hover {
1356
+ color: var(--u-color-text);
1357
+ }
1358
+
1359
+ .udb-back-link__icon {
1360
+ width: 14px;
1361
+ height: 14px;
1362
+ }
1363
+
1364
+ /* ============================================================
1365
+ * 8. Onboarding wizard
1366
+ * ============================================================ */
1367
+
1368
+ .udb-onboarding {
1369
+ display: flex;
1370
+ flex-direction: column;
1371
+ min-height: 100dvh;
1372
+ background: var(--u-color-bg);
1373
+ }
1374
+
1375
+ .udb-onboarding__header {
1376
+ display: flex;
1377
+ align-items: center;
1378
+ justify-content: space-between;
1379
+ gap: var(--u-space-3);
1380
+ padding: var(--u-space-3) var(--u-space-5);
1381
+ border-bottom: 1px solid var(--u-color-border);
1382
+ background: var(--u-color-surface);
1383
+ }
1384
+
1385
+ .udb-onboarding__brand {
1386
+ display: flex;
1387
+ align-items: center;
1388
+ gap: var(--u-space-2);
1389
+ }
1390
+
1391
+ .udb-onboarding__brand-name {
1392
+ font-size: var(--u-font-size-lg);
1393
+ font-weight: var(--u-font-weight-bold);
1394
+ letter-spacing: -0.02em;
1395
+ color: var(--u-color-text);
1396
+ }
1397
+
1398
+ .udb-onboarding__header-actions {
1399
+ display: flex;
1400
+ align-items: center;
1401
+ gap: var(--u-space-2);
1402
+ }
1403
+
1404
+ .udb-onboarding__main {
1405
+ display: flex;
1406
+ flex: 1;
1407
+ justify-content: center;
1408
+ align-items: flex-start;
1409
+ overflow-y: auto;
1410
+ padding: var(--u-space-6) var(--u-space-4);
1411
+ }
1412
+
1413
+ .udb-onboarding__content {
1414
+ display: flex;
1415
+ flex-direction: column;
1416
+ gap: var(--u-space-6);
1417
+ width: 100%;
1418
+ }
1419
+
1420
+ .udb-onboarding__error {
1421
+ display: flex;
1422
+ align-items: flex-start;
1423
+ gap: var(--u-space-2);
1424
+ padding: 10px var(--u-space-3);
1425
+ border-radius: var(--u-radius-md);
1426
+ background: var(--u-color-danger-soft);
1427
+ color: var(--u-color-danger);
1428
+ font-size: var(--u-font-size-md);
1429
+ }
1430
+
1431
+ .udb-onboarding__error svg {
1432
+ width: 16px;
1433
+ height: 16px;
1434
+ flex-shrink: 0;
1435
+ margin-top: 2px;
1436
+ }
1437
+
1438
+ .udb-onboarding__empty {
1439
+ padding: var(--u-space-8) var(--u-space-6);
1440
+ text-align: center;
1441
+ color: var(--u-color-muted);
1442
+ }
1443
+
1444
+ .udb-onboarding__footer {
1445
+ display: flex;
1446
+ align-items: center;
1447
+ justify-content: space-between;
1448
+ gap: var(--u-space-3);
1449
+ padding: var(--u-space-4) var(--u-space-5);
1450
+ border-top: 1px solid var(--u-color-border);
1451
+ background: var(--u-color-surface);
1452
+ }
1453
+
1454
+ .udb-onboarding__footer-actions {
1455
+ display: flex;
1456
+ align-items: center;
1457
+ gap: var(--u-space-2);
1458
+ }
1459
+
1460
+ .udb-onboarding__footer-icon {
1461
+ width: 16px;
1462
+ height: 16px;
1463
+ }
1464
+
1465
+ .udb-onboarding__footer-btn,
1466
+ .udb-onboarding__footer-next {
1467
+ min-width: 96px;
1468
+ }
1469
+
1470
+ /* Step progress rail (node + connector per segment). */
1471
+ .udb-progress {
1472
+ display: flex;
1473
+ align-items: center;
1474
+ width: 100%;
1475
+ max-width: 420px;
1476
+ margin: 0 auto;
1477
+ }
1478
+
1479
+ .udb-progress__segment {
1480
+ display: flex;
1481
+ align-items: center;
1482
+ flex: 1;
1483
+ min-width: 0;
1484
+ }
1485
+
1486
+ .udb-progress__segment:last-child {
1487
+ flex: 0;
1488
+ }
1489
+
1490
+ .udb-progress__node {
1491
+ display: flex;
1492
+ align-items: center;
1493
+ justify-content: center;
1494
+ width: 28px;
1495
+ height: 28px;
1496
+ flex-shrink: 0;
1497
+ border: 2px solid var(--u-color-border-strong);
1498
+ border-radius: 50%;
1499
+ background: var(--u-color-surface);
1500
+ color: var(--u-color-muted);
1501
+ font-size: var(--u-font-size-sm);
1502
+ font-weight: var(--u-font-weight-bold);
1503
+ transition: background-color 0.2s ease, border-color 0.2s ease,
1504
+ color 0.2s ease;
1505
+ }
1506
+
1507
+ .udb-progress__node--on {
1508
+ border-color: var(--u-color-primary);
1509
+ background: var(--u-color-primary);
1510
+ color: var(--u-color-primary-contrast);
1511
+ }
1512
+
1513
+ .udb-progress__check {
1514
+ width: 14px;
1515
+ height: 14px;
1516
+ }
1517
+
1518
+ .udb-progress__connector {
1519
+ flex: 1;
1520
+ height: 2px;
1521
+ min-width: 12px;
1522
+ margin: 0 var(--u-space-2);
1523
+ border-radius: var(--u-radius-pill);
1524
+ background: var(--u-color-border-strong);
1525
+ transition: background-color 0.2s ease;
1526
+ }
1527
+
1528
+ .udb-progress__connector--on {
1529
+ background: var(--u-color-primary);
1530
+ }
1531
+
1532
+ /* Single step card. Width modifiers keep wide option grids readable. */
1533
+ .udb-step {
1534
+ display: flex;
1535
+ flex-direction: column;
1536
+ gap: var(--u-space-5);
1537
+ width: 100%;
1538
+ max-width: 560px;
1539
+ margin: 0 auto;
1540
+ }
1541
+
1542
+ .udb-step--wide {
1543
+ max-width: 720px;
1544
+ }
1545
+
1546
+ .udb-step--widest {
1547
+ max-width: 840px;
1548
+ }
1549
+
1550
+ .udb-step__header {
1551
+ display: flex;
1552
+ flex-direction: column;
1553
+ gap: 6px;
1554
+ text-align: center;
1555
+ }
1556
+
1557
+ .udb-step__title {
1558
+ margin: 0;
1559
+ font-size: var(--u-font-size-3xl);
1560
+ font-weight: var(--u-font-weight-bold);
1561
+ letter-spacing: -0.02em;
1562
+ line-height: 1.2;
1563
+ color: var(--u-color-text);
1564
+ }
1565
+
1566
+ .udb-step__description {
1567
+ margin: 0;
1568
+ font-size: var(--u-font-size-md);
1569
+ color: var(--u-color-muted);
1570
+ }
1571
+
1572
+ .udb-step__description--lg {
1573
+ font-size: var(--u-font-size-lg);
1574
+ }
1575
+
1576
+ .udb-step__options {
1577
+ display: grid;
1578
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1579
+ gap: var(--u-space-3);
1580
+ }
1581
+
1582
+ .udb-step__options--list {
1583
+ grid-template-columns: 1fr;
1584
+ }
1585
+
1586
+ .udb-step__hint {
1587
+ display: flex;
1588
+ align-items: flex-start;
1589
+ gap: var(--u-space-2);
1590
+ margin-top: var(--u-space-1);
1591
+ font-size: var(--u-font-size-sm);
1592
+ color: var(--u-color-muted);
1593
+ }
1594
+
1595
+ .udb-step__hint-icon {
1596
+ width: 16px;
1597
+ height: 16px;
1598
+ flex-shrink: 0;
1599
+ margin-top: 2px;
1600
+ }
1601
+
1602
+ /* Selectable option card (user type, focus area...). */
1603
+ .udb-choice {
1604
+ position: relative;
1605
+ display: flex;
1606
+ align-items: flex-start;
1607
+ gap: var(--u-space-3);
1608
+ padding: var(--u-space-4);
1609
+ border: 1px solid var(--u-color-border-strong);
1610
+ border-radius: var(--u-radius-lg);
1611
+ background: var(--u-color-surface);
1612
+ font-family: inherit;
1613
+ text-align: left;
1614
+ cursor: pointer;
1615
+ transition: border-color 0.15s ease, background-color 0.15s ease,
1616
+ box-shadow 0.15s ease;
1617
+ }
1618
+
1619
+ .udb-choice:hover {
1620
+ border-color: var(--u-color-primary);
1621
+ }
1622
+
1623
+ .udb-choice--selected {
1624
+ border-color: var(--u-color-primary);
1625
+ background: var(--u-color-primary-soft);
1626
+ box-shadow: inset 0 0 0 1px var(--u-color-primary);
1627
+ }
1628
+
1629
+ .udb-choice__check {
1630
+ position: absolute;
1631
+ top: var(--u-space-3);
1632
+ right: var(--u-space-3);
1633
+ display: flex;
1634
+ align-items: center;
1635
+ justify-content: center;
1636
+ width: 20px;
1637
+ height: 20px;
1638
+ border: 1px solid var(--u-color-border-strong);
1639
+ border-radius: 50%;
1640
+ background: var(--u-color-surface);
1641
+ transition: background-color 0.15s ease, border-color 0.15s ease;
1642
+ }
1643
+
1644
+ .udb-choice__check--on {
1645
+ border-color: var(--u-color-primary);
1646
+ background: var(--u-color-primary);
1647
+ }
1648
+
1649
+ .udb-choice__check-icon {
1650
+ width: 12px;
1651
+ height: 12px;
1652
+ color: var(--u-color-primary-contrast);
1653
+ }
1654
+
1655
+ .udb-choice__icon-box {
1656
+ display: flex;
1657
+ align-items: center;
1658
+ justify-content: center;
1659
+ width: 40px;
1660
+ height: 40px;
1661
+ flex-shrink: 0;
1662
+ border-radius: var(--u-radius-md);
1663
+ background: var(--u-color-surface-muted);
1664
+ }
1665
+
1666
+ .udb-choice__icon-box--lg {
1667
+ width: 48px;
1668
+ height: 48px;
1669
+ }
1670
+
1671
+ .udb-choice__icon-box--on {
1672
+ background: var(--u-color-primary-soft);
1673
+ }
1674
+
1675
+ .udb-choice__icon {
1676
+ width: 20px;
1677
+ height: 20px;
1678
+ color: var(--u-color-text);
1679
+ }
1680
+
1681
+ .udb-choice__icon--lg {
1682
+ width: 24px;
1683
+ height: 24px;
1684
+ }
1685
+
1686
+ .udb-choice__body {
1687
+ display: flex;
1688
+ flex-direction: column;
1689
+ gap: 4px;
1690
+ flex: 1;
1691
+ min-width: 0;
1692
+ }
1693
+
1694
+ .udb-choice__label-row {
1695
+ display: flex;
1696
+ align-items: center;
1697
+ justify-content: space-between;
1698
+ gap: var(--u-space-2);
1699
+ }
1700
+
1701
+ .udb-choice__label {
1702
+ font-size: var(--u-font-size-md);
1703
+ font-weight: var(--u-font-weight-medium);
1704
+ color: var(--u-color-text);
1705
+ }
1706
+
1707
+ .udb-choice__label--lg {
1708
+ font-size: var(--u-font-size-lg);
1709
+ font-weight: 600;
1710
+ }
1711
+
1712
+ .udb-choice__badge {
1713
+ padding: 2px var(--u-space-2);
1714
+ border-radius: var(--u-radius-pill);
1715
+ background: var(--u-color-surface-muted);
1716
+ font-size: var(--u-font-size-xs);
1717
+ font-weight: var(--u-font-weight-medium);
1718
+ color: var(--u-color-muted);
1719
+ white-space: nowrap;
1720
+ }
1721
+
1722
+ .udb-choice__description {
1723
+ margin: 0;
1724
+ font-size: var(--u-font-size-sm);
1725
+ color: var(--u-color-muted);
1726
+ }
1727
+
1728
+ /* Platform connection grid. */
1729
+ .udb-platforms {
1730
+ display: grid;
1731
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
1732
+ gap: var(--u-space-3);
1733
+ }
1734
+
1735
+ .udb-platform {
1736
+ display: flex;
1737
+ align-items: center;
1738
+ gap: var(--u-space-3);
1739
+ padding: var(--u-space-3);
1740
+ border: 1px solid var(--u-color-border-strong);
1741
+ border-radius: var(--u-radius-lg);
1742
+ background: var(--u-color-surface);
1743
+ font-family: inherit;
1744
+ text-align: left;
1745
+ cursor: pointer;
1746
+ transition: border-color 0.15s ease, background-color 0.15s ease;
1747
+ }
1748
+
1749
+ .udb-platform:hover {
1750
+ border-color: var(--u-color-primary);
1751
+ }
1752
+
1753
+ .udb-platform--connected {
1754
+ border-color: var(--u-color-primary);
1755
+ background: var(--u-color-primary-soft);
1756
+ }
1757
+
1758
+ .udb-platform__icon-box {
1759
+ display: flex;
1760
+ align-items: center;
1761
+ justify-content: center;
1762
+ width: 40px;
1763
+ height: 40px;
1764
+ flex-shrink: 0;
1765
+ border-radius: 50%;
1766
+ background: var(--u-color-surface-muted);
1767
+ }
1768
+
1769
+ .udb-platform__icon {
1770
+ width: 20px;
1771
+ height: 20px;
1772
+ }
1773
+
1774
+ .udb-platform__meta {
1775
+ display: flex;
1776
+ flex-direction: column;
1777
+ gap: 2px;
1778
+ flex: 1;
1779
+ min-width: 0;
1780
+ }
1781
+
1782
+ .udb-platform__name {
1783
+ font-size: var(--u-font-size-md);
1784
+ font-weight: var(--u-font-weight-medium);
1785
+ color: var(--u-color-text);
1786
+ }
1787
+
1788
+ .udb-platform__state {
1789
+ font-size: var(--u-font-size-xs);
1790
+ color: var(--u-color-muted);
1791
+ }
1792
+
1793
+ .udb-platform__state--on {
1794
+ color: var(--u-color-success);
1795
+ font-weight: var(--u-font-weight-medium);
1796
+ }
1797
+
1798
+ /* Billing cycle switch (monthly / yearly + save badge). */
1799
+ .udb-cycle-toggle-row {
1800
+ display: flex;
1801
+ align-items: center;
1802
+ justify-content: space-between;
1803
+ flex-wrap: wrap;
1804
+ gap: var(--u-space-2);
1805
+ }
1806
+
1807
+ .udb-cycle-toggle {
1808
+ display: inline-flex;
1809
+ align-items: center;
1810
+ gap: 2px;
1811
+ padding: 3px;
1812
+ border: 1px solid var(--u-color-border);
1813
+ border-radius: var(--u-radius-pill);
1814
+ background: var(--u-color-surface-muted);
1815
+ }
1816
+
1817
+ .udb-cycle-toggle__pill {
1818
+ display: inline-flex;
1819
+ align-items: center;
1820
+ gap: var(--u-space-1);
1821
+ border: none;
1822
+ padding: 6px var(--u-space-4);
1823
+ border-radius: var(--u-radius-pill);
1824
+ background: transparent;
1825
+ font-family: inherit;
1826
+ font-size: var(--u-font-size-sm);
1827
+ font-weight: var(--u-font-weight-medium);
1828
+ color: var(--u-color-muted);
1829
+ cursor: pointer;
1830
+ transition: background-color 0.15s ease, color 0.15s ease,
1831
+ box-shadow 0.15s ease;
1832
+ }
1833
+
1834
+ .udb-cycle-toggle__pill--on {
1835
+ background: var(--u-color-surface);
1836
+ color: var(--u-color-text);
1837
+ box-shadow: var(--u-shadow-sm);
1838
+ }
1839
+
1840
+ /* Yearly pill hosts the save badge; keep it on one line when it appears. */
1841
+ .udb-cycle-toggle__pill--with-badge {
1842
+ white-space: nowrap;
1843
+ }
1844
+
1845
+ .udb-cycle-toggle__save {
1846
+ display: none;
1847
+ font-size: 10px;
1848
+ font-weight: var(--u-font-weight-bold);
1849
+ color: var(--u-color-success);
1850
+ }
1851
+
1852
+ .udb-cycle-toggle__save--on {
1853
+ display: inline;
1854
+ }
1855
+
1856
+ /* Plan cards. */
1857
+ .udb-plans {
1858
+ display: grid;
1859
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
1860
+ gap: var(--u-space-4);
1861
+ align-items: stretch;
1862
+ }
1863
+
1864
+ .udb-plan {
1865
+ position: relative;
1866
+ display: flex;
1867
+ flex-direction: column;
1868
+ gap: var(--u-space-3);
1869
+ padding: var(--u-space-5);
1870
+ border: 1px solid var(--u-color-border-strong);
1871
+ border-radius: var(--u-radius-lg);
1872
+ background: var(--u-color-surface);
1873
+ font-family: inherit;
1874
+ text-align: left;
1875
+ cursor: pointer;
1876
+ transition: border-color 0.15s ease, background-color 0.15s ease,
1877
+ box-shadow 0.15s ease;
1878
+ }
1879
+
1880
+ .udb-plan:hover {
1881
+ border-color: var(--u-color-primary);
1882
+ }
1883
+
1884
+ .udb-plan--selected {
1885
+ border-color: var(--u-color-primary);
1886
+ background: var(--u-color-primary-soft);
1887
+ box-shadow: inset 0 0 0 1px var(--u-color-primary);
1888
+ }
1889
+
1890
+ .udb-plan--highlight {
1891
+ border-color: var(--u-color-primary);
1892
+ box-shadow: var(--u-shadow-md);
1893
+ }
1894
+
1895
+ .udb-plan__recommended {
1896
+ position: absolute;
1897
+ top: calc(-1 * var(--u-space-3));
1898
+ left: 50%;
1899
+ transform: translateX(-50%);
1900
+ padding: 2px var(--u-space-3);
1901
+ border-radius: var(--u-radius-pill);
1902
+ background: var(--u-color-primary);
1903
+ color: var(--u-color-primary-contrast);
1904
+ font-size: 10px;
1905
+ font-weight: var(--u-font-weight-bold);
1906
+ text-transform: uppercase;
1907
+ letter-spacing: 0.06em;
1908
+ white-space: nowrap;
1909
+ }
1910
+
1911
+ .udb-plan__heading {
1912
+ display: flex;
1913
+ align-items: center;
1914
+ justify-content: space-between;
1915
+ gap: var(--u-space-2);
1916
+ }
1917
+
1918
+ .udb-plan__name {
1919
+ margin: 0;
1920
+ font-size: var(--u-font-size-lg);
1921
+ font-weight: var(--u-font-weight-bold);
1922
+ color: var(--u-color-text);
1923
+ }
1924
+
1925
+ .udb-plan__badge {
1926
+ padding: 2px var(--u-space-2);
1927
+ border-radius: var(--u-radius-pill);
1928
+ font-size: var(--u-font-size-xs);
1929
+ font-weight: var(--u-font-weight-medium);
1930
+ white-space: nowrap;
1931
+ }
1932
+
1933
+ .udb-plan__badge--muted {
1934
+ background: var(--u-color-surface-muted);
1935
+ color: var(--u-color-muted);
1936
+ }
1937
+
1938
+ .udb-plan__badge--primary {
1939
+ background: var(--u-color-primary-soft);
1940
+ color: var(--u-color-primary);
1941
+ }
1942
+
1943
+ .udb-plan__badge--accent {
1944
+ background: var(--u-color-success-soft);
1945
+ color: var(--u-color-success);
1946
+ }
1947
+
1948
+ .udb-plan__description {
1949
+ margin: 0;
1950
+ font-size: var(--u-font-size-sm);
1951
+ color: var(--u-color-muted);
1952
+ }
1953
+
1954
+ .udb-plan__price-row {
1955
+ display: flex;
1956
+ align-items: baseline;
1957
+ gap: var(--u-space-1);
1958
+ }
1959
+
1960
+ .udb-plan__price {
1961
+ font-size: var(--u-font-size-3xl);
1962
+ font-weight: var(--u-font-weight-bold);
1963
+ letter-spacing: -0.02em;
1964
+ color: var(--u-color-text);
1965
+ }
1966
+
1967
+ .udb-plan__price-unit {
1968
+ font-size: var(--u-font-size-sm);
1969
+ color: var(--u-color-muted);
1970
+ }
1971
+
1972
+ .udb-plan__features {
1973
+ display: flex;
1974
+ flex-direction: column;
1975
+ gap: var(--u-space-2);
1976
+ margin: 0;
1977
+ padding: 0;
1978
+ list-style: none;
1979
+ }
1980
+
1981
+ .udb-plan__feature {
1982
+ display: flex;
1983
+ align-items: flex-start;
1984
+ gap: var(--u-space-2);
1985
+ font-size: var(--u-font-size-sm);
1986
+ color: var(--u-color-text);
1987
+ }
1988
+
1989
+ .udb-plan__feature-check {
1990
+ display: flex;
1991
+ align-items: center;
1992
+ justify-content: center;
1993
+ width: 16px;
1994
+ height: 16px;
1995
+ flex-shrink: 0;
1996
+ margin-top: 2px;
1997
+ border-radius: 50%;
1998
+ background: var(--u-color-success-soft);
1999
+ }
2000
+
2001
+ .udb-plan__feature-check-icon {
2002
+ width: 10px;
2003
+ height: 10px;
2004
+ color: var(--u-color-success);
2005
+ }
2006
+
2007
+ .udb-plan__feature-text {
2008
+ line-height: 1.4;
2009
+ }
2010
+
2011
+ .udb-plan__feature-text--bold {
2012
+ font-weight: var(--u-font-weight-medium);
2013
+ }
2014
+
2015
+ /* ============================================================
2016
+ * 9. Settings
2017
+ * ============================================================ */
2018
+
2019
+ .udb-settings {
2020
+ display: flex;
2021
+ width: 100%;
2022
+ height: 100vh;
2023
+ overflow: hidden;
2024
+ background: var(--u-color-bg);
2025
+ }
2026
+
2027
+ .udb-settings__sidebar {
2028
+ display: none;
2029
+ flex-direction: column;
2030
+ flex-shrink: 0;
2031
+ width: 280px;
2032
+ border-right: 1px solid var(--u-color-border);
2033
+ background: var(--u-color-surface);
2034
+ transition: width 0.3s ease;
2035
+ }
2036
+
2037
+ .udb-settings__sidebar--collapsed {
2038
+ width: 72px;
2039
+ overflow: hidden;
2040
+ }
2041
+
2042
+ .udb-settings__sidebar-header {
2043
+ display: flex;
2044
+ align-items: center;
2045
+ justify-content: space-between;
2046
+ gap: var(--u-space-2);
2047
+ padding: var(--u-space-4);
2048
+ border-bottom: 1px solid var(--u-color-border);
2049
+ }
2050
+
2051
+ .udb-settings__sidebar-title {
2052
+ margin: 0;
2053
+ font-size: var(--u-font-size-lg);
2054
+ font-weight: var(--u-font-weight-bold);
2055
+ color: var(--u-color-text);
2056
+ white-space: nowrap;
2057
+ overflow: hidden;
2058
+ text-overflow: ellipsis;
2059
+ }
2060
+
2061
+ .udb-settings__sidebar-toggle {
2062
+ display: inline-flex;
2063
+ flex-shrink: 0;
2064
+ }
2065
+
2066
+ .udb-settings__toggle-icon {
2067
+ width: 20px;
2068
+ height: 20px;
2069
+ }
2070
+
2071
+ .udb-settings__toggle-icon-lg {
2072
+ width: 24px;
2073
+ height: 24px;
2074
+ }
2075
+
2076
+ .udb-settings__nav {
2077
+ flex: 1;
2078
+ overflow-y: auto;
2079
+ padding: var(--u-space-3) var(--u-space-2);
2080
+ }
2081
+
2082
+ .udb-settings__mobile {
2083
+ position: fixed;
2084
+ inset: 0;
2085
+ z-index: 50;
2086
+ }
2087
+
2088
+ .udb-settings__mobile-sidebar {
2089
+ position: absolute;
2090
+ left: 0;
2091
+ top: 0;
2092
+ height: 100%;
2093
+ width: 280px;
2094
+ overflow-y: auto;
2095
+ border-right: 1px solid var(--u-color-border);
2096
+ background: var(--u-color-surface);
2097
+ box-shadow: var(--u-shadow-lg);
2098
+ }
2099
+
2100
+ .udb-backdrop {
2101
+ position: absolute;
2102
+ inset: 0;
2103
+ background: rgba(15, 23, 42, 0.45);
2104
+ }
2105
+
2106
+ .udb-settings__main {
2107
+ display: flex;
2108
+ flex: 1;
2109
+ flex-direction: column;
2110
+ overflow: hidden;
2111
+ min-width: 0;
2112
+ }
2113
+
2114
+ .udb-settings__mobile-header {
2115
+ display: flex;
2116
+ align-items: center;
2117
+ justify-content: space-between;
2118
+ gap: var(--u-space-3);
2119
+ padding: var(--u-space-3) var(--u-space-4);
2120
+ border-bottom: 1px solid var(--u-color-border);
2121
+ background: var(--u-color-surface);
2122
+ }
2123
+
2124
+ .udb-settings__mobile-lead {
2125
+ display: flex;
2126
+ align-items: center;
2127
+ gap: var(--u-space-2);
2128
+ min-width: 0;
2129
+ }
2130
+
2131
+ .udb-settings__mobile-title {
2132
+ margin: 0;
2133
+ font-size: var(--u-font-size-md);
2134
+ font-weight: 600;
2135
+ color: var(--u-color-text);
2136
+ white-space: nowrap;
2137
+ overflow: hidden;
2138
+ text-overflow: ellipsis;
2139
+ }
2140
+
2141
+ .udb-settings__content {
2142
+ flex: 1;
2143
+ overflow-y: auto;
2144
+ padding: var(--u-space-5) var(--u-space-4);
2145
+ }
2146
+
2147
+ .udb-settings__skeleton {
2148
+ display: flex;
2149
+ flex-direction: column;
2150
+ gap: var(--u-space-4);
2151
+ max-width: 640px;
2152
+ }
2153
+
2154
+ .udb-settings__skeleton-list {
2155
+ display: flex;
2156
+ flex-direction: column;
2157
+ gap: var(--u-space-2);
2158
+ }
2159
+
2160
+ .udb-settings__skeleton-row {
2161
+ height: 14px;
2162
+ width: 100%;
2163
+ border-radius: var(--u-radius-sm);
2164
+ }
2165
+
2166
+ @media (min-width: 768px) {
2167
+ .udb-settings__sidebar {
2168
+ display: flex;
2169
+ }
2170
+
2171
+ .udb-settings__mobile,
2172
+ .udb-settings__mobile-header {
2173
+ display: none;
2174
+ }
2175
+
2176
+ .udb-settings__content {
2177
+ padding: var(--u-space-8);
2178
+ }
2179
+ }
2180
+
2181
+ /* Settings nav sections (shared by desktop & mobile drawers). */
2182
+ .udb-settings-nav {
2183
+ display: flex;
2184
+ flex-direction: column;
2185
+ gap: var(--u-space-5);
2186
+ }
2187
+
2188
+ .udb-settings-nav__title {
2189
+ margin: 0;
2190
+ padding: 0 var(--u-space-3);
2191
+ font-size: 10px;
2192
+ font-weight: var(--u-font-weight-bold);
2193
+ text-transform: uppercase;
2194
+ letter-spacing: 0.1em;
2195
+ color: var(--u-color-muted);
2196
+ }
2197
+
2198
+ .udb-settings-nav__items {
2199
+ display: flex;
2200
+ flex-direction: column;
2201
+ gap: 2px;
2202
+ }
2203
+
2204
+ .udb-settings-nav__item {
2205
+ display: flex;
2206
+ width: 100%;
2207
+ align-items: center;
2208
+ gap: var(--u-space-3);
2209
+ padding: var(--u-space-2) var(--u-space-3);
2210
+ border: none;
2211
+ border-radius: var(--u-radius-md);
2212
+ background: transparent;
2213
+ font-family: inherit;
2214
+ font-size: var(--u-font-size-md);
2215
+ color: var(--u-color-text);
2216
+ opacity: 0.75;
2217
+ text-align: left;
2218
+ text-decoration: none;
2219
+ cursor: pointer;
2220
+ transition: background-color 0.15s ease, color 0.15s ease;
2221
+ }
2222
+
2223
+ .udb-settings-nav__item:hover {
2224
+ background: var(--u-color-surface-muted);
2225
+ opacity: 1;
2226
+ }
2227
+
2228
+ .udb-settings-nav__item--active {
2229
+ background: var(--u-color-primary-soft);
2230
+ color: var(--u-color-primary);
2231
+ opacity: 1;
2232
+ font-weight: var(--u-font-weight-medium);
2233
+ }
2234
+
2235
+ .udb-settings-nav__item-icon {
2236
+ width: 16px;
2237
+ height: 16px;
2238
+ flex-shrink: 0;
2239
+ }
2240
+
2241
+ .udb-settings-nav__item-label {
2242
+ flex: 1;
2243
+ min-width: 0;
2244
+ white-space: nowrap;
2245
+ overflow: hidden;
2246
+ text-overflow: ellipsis;
2247
+ }
2248
+
2249
+ .udb-settings-nav__badge {
2250
+ padding: 1px var(--u-space-2);
2251
+ border-radius: var(--u-radius-pill);
2252
+ background: var(--u-color-primary-soft);
2253
+ color: var(--u-color-primary);
2254
+ font-size: 10px;
2255
+ font-weight: var(--u-font-weight-bold);
2256
+ }
2257
+
2258
+ .udb-settings-nav__chevron {
2259
+ width: 14px;
2260
+ height: 14px;
2261
+ color: var(--u-color-muted);
2262
+ flex-shrink: 0;
2263
+ }
2264
+
2265
+ /* ============================================================
2266
+ * 10. Analytics
2267
+ * ============================================================ */
2268
+
2269
+ .udb-analytics {
2270
+ display: flex;
2271
+ flex-direction: column;
2272
+ gap: var(--u-space-6);
2273
+ width: 100%;
2274
+ }
2275
+
2276
+ .udb-analytics__header {
2277
+ display: flex;
2278
+ align-items: center;
2279
+ justify-content: space-between;
2280
+ flex-wrap: wrap;
2281
+ gap: var(--u-space-3);
2282
+ }
2283
+
2284
+ .udb-analytics__heading {
2285
+ min-width: 0;
2286
+ }
2287
+
2288
+ .udb-analytics__title {
2289
+ margin: 0;
2290
+ font-size: var(--u-font-size-3xl);
2291
+ font-weight: var(--u-font-weight-bold);
2292
+ letter-spacing: -0.02em;
2293
+ line-height: 1.2;
2294
+ color: var(--u-color-text);
2295
+ }
2296
+
2297
+ .udb-analytics__description {
2298
+ margin: var(--u-space-1) 0 0;
2299
+ font-size: var(--u-font-size-md);
2300
+ color: var(--u-color-muted);
2301
+ }
2302
+
2303
+ .udb-analytics__actions {
2304
+ display: flex;
2305
+ align-items: center;
2306
+ flex-wrap: wrap;
2307
+ gap: var(--u-space-2);
2308
+ }
2309
+
2310
+ .udb-analytics__action-icon {
2311
+ width: 16px;
2312
+ height: 16px;
2313
+ }
2314
+
2315
+ .udb-analytics__loading {
2316
+ display: flex;
2317
+ align-items: center;
2318
+ justify-content: center;
2319
+ padding: var(--u-space-8) 0;
2320
+ }
2321
+
2322
+ .udb-analytics__loading-spinner {
2323
+ width: 48px;
2324
+ height: 48px;
2325
+ color: var(--u-color-muted);
2326
+ }
2327
+
2328
+ .udb-analytics__metrics {
2329
+ display: grid;
2330
+ grid-template-columns: 1fr;
2331
+ gap: var(--u-space-4);
2332
+ }
2333
+
2334
+ .udb-analytics__charts {
2335
+ display: grid;
2336
+ grid-template-columns: 1fr;
2337
+ gap: var(--u-space-6);
2338
+ }
2339
+
2340
+ @media (min-width: 640px) {
2341
+ .udb-analytics__metrics {
2342
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2343
+ }
2344
+ }
2345
+
2346
+ @media (min-width: 1024px) {
2347
+ .udb-analytics__metrics--wide {
2348
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2349
+ }
2350
+
2351
+ .udb-analytics__charts {
2352
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2353
+ }
2354
+ }
2355
+
2356
+ /* Period selector chip. */
2357
+ .udb-period-select {
2358
+ display: flex;
2359
+ align-items: center;
2360
+ gap: var(--u-space-2);
2361
+ height: 36px;
2362
+ padding: 0 var(--u-space-3);
2363
+ border: 1px solid var(--u-color-border-strong);
2364
+ border-radius: var(--u-radius-md);
2365
+ background: var(--u-color-surface);
2366
+ }
2367
+
2368
+ .udb-period-select__icon {
2369
+ width: 16px;
2370
+ height: 16px;
2371
+ color: var(--u-color-muted);
2372
+ flex-shrink: 0;
2373
+ }
2374
+
2375
+ .udb-period-select__select {
2376
+ height: 100%;
2377
+ border: none;
2378
+ background: transparent;
2379
+ font-family: inherit;
2380
+ font-size: var(--u-font-size-sm);
2381
+ color: var(--u-color-text);
2382
+ outline: none;
2383
+ cursor: pointer;
2384
+ }
2385
+
2386
+ /* Chart card internals. */
2387
+ .udb-analytics-card__status {
2388
+ display: flex;
2389
+ align-items: center;
2390
+ justify-content: center;
2391
+ gap: var(--u-space-3);
2392
+ min-height: 192px;
2393
+ }
2394
+
2395
+ .udb-analytics-card__status--error {
2396
+ color: var(--u-color-danger);
2397
+ }
2398
+
2399
+ .udb-analytics-card__spinner {
2400
+ width: 32px;
2401
+ height: 32px;
2402
+ color: var(--u-color-muted);
2403
+ }
2404
+
2405
+ .udb-analytics-card__error-icon {
2406
+ width: 20px;
2407
+ height: 20px;
2408
+ flex-shrink: 0;
2409
+ }
2410
+
2411
+ .udb-analytics-card__error-text {
2412
+ margin: 0;
2413
+ font-size: var(--u-font-size-md);
2414
+ }
2415
+
2416
+ .udb-analytics-card__header {
2417
+ margin-bottom: var(--u-space-6);
2418
+ }
2419
+
2420
+ .udb-analytics-card__title {
2421
+ margin: 0;
2422
+ font-size: var(--u-font-size-lg);
2423
+ font-weight: 600;
2424
+ color: var(--u-color-text);
2425
+ }
2426
+
2427
+ .udb-analytics-card__description {
2428
+ margin: var(--u-space-1) 0 0;
2429
+ font-size: var(--u-font-size-sm);
2430
+ color: var(--u-color-muted);
2431
+ }
2432
+
2433
+ .udb-analytics-card__metrics {
2434
+ display: grid;
2435
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
2436
+ gap: var(--u-space-4);
2437
+ margin-top: var(--u-space-4);
2438
+ }
2439
+
2440
+ /* Chart container + dependency-free SVG renderer surfaces. */
2441
+ .udb-chart {
2442
+ position: relative;
2443
+ width: 100%;
2444
+ }
2445
+
2446
+ .udb-chart__empty {
2447
+ display: flex;
2448
+ align-items: center;
2449
+ justify-content: center;
2450
+ height: 100%;
2451
+ min-height: 192px;
2452
+ padding: var(--u-space-6);
2453
+ text-align: center;
2454
+ font-size: var(--u-font-size-md);
2455
+ color: var(--u-color-muted);
2456
+ }
2457
+
2458
+ .udb-chart__axis {
2459
+ font-size: var(--u-font-size-sm);
2460
+ fill: var(--u-color-muted);
2461
+ }
2462
+
2463
+ .udb-chart__grid {
2464
+ stroke: var(--u-color-border);
2465
+ }
2466
+
2467
+ .udb-chart__svg {
2468
+ display: block;
2469
+ width: 100%;
2470
+ height: 100%;
2471
+ overflow: visible;
2472
+ }
2473
+
2474
+ .udb-chart__legend {
2475
+ display: flex;
2476
+ align-items: center;
2477
+ justify-content: center;
2478
+ flex-wrap: wrap;
2479
+ gap: var(--u-space-3);
2480
+ margin-top: var(--u-space-3);
2481
+ }
2482
+
2483
+ .udb-chart__chip {
2484
+ display: inline-flex;
2485
+ align-items: center;
2486
+ gap: var(--u-space-2);
2487
+ font-size: var(--u-font-size-sm);
2488
+ color: var(--u-color-muted);
2489
+ }
2490
+
2491
+ .udb-chart__chip-dot {
2492
+ width: 8px;
2493
+ height: 8px;
2494
+ border-radius: 50%;
2495
+ flex-shrink: 0;
2496
+ }
2497
+
2498
+ /* ============================================================
2499
+ * 11. Shared blocks — empty state, tables, org switcher, matrix,
2500
+ * audit list (used by guards, session and settings skeletons)
2501
+ * ============================================================ */
2502
+
2503
+ /* Generic empty / forbidden state. */
2504
+ .udb-empty {
2505
+ display: flex;
2506
+ flex-direction: column;
2507
+ align-items: center;
2508
+ justify-content: center;
2509
+ gap: var(--u-space-3);
2510
+ padding: var(--u-space-8) var(--u-space-6);
2511
+ text-align: center;
2512
+ color: var(--u-color-muted);
2513
+ }
2514
+
2515
+ .udb-empty__icon {
2516
+ display: flex;
2517
+ align-items: center;
2518
+ justify-content: center;
2519
+ width: 40px;
2520
+ height: 40px;
2521
+ border-radius: 50%;
2522
+ background: var(--u-color-surface-muted);
2523
+ }
2524
+
2525
+ .udb-empty__glyph {
2526
+ width: 20px;
2527
+ height: 20px;
2528
+ color: var(--u-color-muted);
2529
+ opacity: 0.7;
2530
+ }
2531
+
2532
+ .udb-empty__text {
2533
+ margin: 0;
2534
+ font-size: var(--u-font-size-md);
2535
+ font-weight: var(--u-font-weight-medium);
2536
+ color: var(--u-color-text);
2537
+ }
2538
+
2539
+ .udb-empty__hint {
2540
+ margin: 0;
2541
+ font-size: var(--u-font-size-sm);
2542
+ color: var(--u-color-muted);
2543
+ }
2544
+
2545
+ /* Data tables (user management, permission matrix). */
2546
+ .udb-table__wrap {
2547
+ width: 100%;
2548
+ overflow-x: auto;
2549
+ border: 1px solid var(--u-color-border);
2550
+ border-radius: var(--u-radius-lg);
2551
+ background: var(--u-color-surface);
2552
+ }
2553
+
2554
+ .udb-table {
2555
+ width: 100%;
2556
+ border-collapse: collapse;
2557
+ font-size: var(--u-font-size-md);
2558
+ }
2559
+
2560
+ .udb-table__th {
2561
+ padding: var(--u-space-2) var(--u-space-3);
2562
+ border-bottom: 1px solid var(--u-color-border-strong);
2563
+ text-align: left;
2564
+ font-size: var(--u-font-size-xs);
2565
+ font-weight: var(--u-font-weight-bold);
2566
+ text-transform: uppercase;
2567
+ letter-spacing: 0.06em;
2568
+ color: var(--u-color-muted);
2569
+ white-space: nowrap;
2570
+ }
2571
+
2572
+ .udb-table__th--code {
2573
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
2574
+ text-transform: none;
2575
+ letter-spacing: 0;
2576
+ }
2577
+
2578
+ .udb-table__td {
2579
+ padding: var(--u-space-3);
2580
+ border-bottom: 1px solid var(--u-color-border);
2581
+ color: var(--u-color-text);
2582
+ }
2583
+
2584
+ .udb-table__row:last-child .udb-table__td {
2585
+ border-bottom: none;
2586
+ }
2587
+
2588
+ .udb-table__row:hover .udb-table__td {
2589
+ background: var(--u-color-surface-muted);
2590
+ }
2591
+
2592
+ .udb-table__td--strong {
2593
+ font-weight: var(--u-font-weight-medium);
2594
+ white-space: nowrap;
2595
+ }
2596
+
2597
+ .udb-table__td--center {
2598
+ text-align: center;
2599
+ }
2600
+
2601
+ /* Org switcher (reuses udb-profile-btn / udb-avatar / udb-menu). */
2602
+ .udb-org {
2603
+ display: flex;
2604
+ flex-direction: column;
2605
+ align-items: flex-start;
2606
+ line-height: 1.2;
2607
+ }
2608
+
2609
+ .udb-org__name {
2610
+ font-size: var(--u-font-size-md);
2611
+ font-weight: var(--u-font-weight-medium);
2612
+ color: var(--u-color-text);
2613
+ }
2614
+
2615
+ .udb-org__meta {
2616
+ font-size: 10px;
2617
+ text-transform: capitalize;
2618
+ color: var(--u-color-muted);
2619
+ }
2620
+
2621
+ .udb-org-menu {
2622
+ padding: var(--u-space-2);
2623
+ }
2624
+
2625
+ .udb-org-menu__label {
2626
+ flex: 1;
2627
+ min-width: 0;
2628
+ overflow: hidden;
2629
+ text-overflow: ellipsis;
2630
+ white-space: nowrap;
2631
+ }
2632
+
2633
+ .udb-org-menu__check {
2634
+ width: 14px;
2635
+ height: 14px;
2636
+ color: var(--u-color-primary);
2637
+ }
2638
+
2639
+ .udb-menu__item--active {
2640
+ background: var(--u-color-primary-soft);
2641
+ color: var(--u-color-primary);
2642
+ font-weight: var(--u-font-weight-medium);
2643
+ }
2644
+
2645
+ /* Permission matrix cells. */
2646
+ .udb-matrix__cell {
2647
+ display: inline-flex;
2648
+ align-items: center;
2649
+ justify-content: center;
2650
+ width: 28px;
2651
+ height: 28px;
2652
+ border: 1px solid var(--u-color-border-strong);
2653
+ border-radius: var(--u-radius-sm);
2654
+ background: var(--u-color-surface);
2655
+ cursor: pointer;
2656
+ }
2657
+
2658
+ .udb-matrix__cell:hover {
2659
+ border-color: var(--u-color-primary);
2660
+ }
2661
+
2662
+ .udb-matrix__cell--on {
2663
+ border-color: var(--u-color-primary);
2664
+ background: var(--u-color-primary-soft);
2665
+ }
2666
+
2667
+ .udb-matrix__check {
2668
+ width: 14px;
2669
+ height: 14px;
2670
+ color: var(--u-color-success);
2671
+ }
2672
+
2673
+ .udb-matrix__deny {
2674
+ width: 14px;
2675
+ height: 14px;
2676
+ color: var(--u-color-muted);
2677
+ opacity: 0.5;
2678
+ }
2679
+
2680
+ /* Audit log rows. */
2681
+ .udb-audit {
2682
+ display: flex;
2683
+ flex-direction: column;
2684
+ margin: 0;
2685
+ padding: 0;
2686
+ list-style: none;
2687
+ border: 1px solid var(--u-color-border);
2688
+ border-radius: var(--u-radius-lg);
2689
+ background: var(--u-color-surface);
2690
+ overflow: hidden;
2691
+ }
2692
+
2693
+ .udb-audit__item {
2694
+ display: flex;
2695
+ align-items: baseline;
2696
+ gap: var(--u-space-4);
2697
+ padding: var(--u-space-3) var(--u-space-4);
2698
+ border-bottom: 1px solid var(--u-color-border);
2699
+ font-size: var(--u-font-size-md);
2700
+ }
2701
+
2702
+ .udb-audit__item:last-child {
2703
+ border-bottom: none;
2704
+ }
2705
+
2706
+ .udb-audit__at {
2707
+ flex-shrink: 0;
2708
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
2709
+ font-size: var(--u-font-size-sm);
2710
+ color: var(--u-color-muted);
2711
+ }
2712
+
2713
+ .udb-audit__actor {
2714
+ flex-shrink: 0;
2715
+ font-weight: var(--u-font-weight-medium);
2716
+ color: var(--u-color-text);
2717
+ }
2718
+
2719
+ .udb-audit__action {
2720
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
2721
+ font-size: var(--u-font-size-sm);
2722
+ color: var(--u-color-primary);
2723
+ }
2724
+
2725
+ .udb-audit__target {
2726
+ min-width: 0;
2727
+ overflow: hidden;
2728
+ text-overflow: ellipsis;
2729
+ white-space: nowrap;
2730
+ color: var(--u-color-muted);
2731
+ }