@questpie/admin 3.0.3 → 3.0.4

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 (249) hide show
  1. package/README.md +34 -5
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/blocks/block-renderer.mjs +4 -1
  4. package/dist/client/builder/types/action-types.d.mts +31 -3
  5. package/dist/client/builder/types/collection-types.d.mts +140 -0
  6. package/dist/client/builder/types/ui-config.d.mts +16 -2
  7. package/dist/client/builder/types/views.d.mts +57 -0
  8. package/dist/client/builder/types/widget-types.d.mts +5 -0
  9. package/dist/client/components/actions/action-button.mjs +137 -199
  10. package/dist/client/components/actions/action-dialog.mjs +198 -156
  11. package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
  12. package/dist/client/components/actions/header-actions.mjs +52 -53
  13. package/dist/client/components/admin-link.d.mts +2 -2
  14. package/dist/client/components/auth/auth-loading.mjs +41 -18
  15. package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
  16. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  17. package/dist/client/components/blocks/block-item.mjs +2 -2
  18. package/dist/client/components/blocks/block-library-sidebar.mjs +2 -2
  19. package/dist/client/components/component-renderer.mjs +1 -1
  20. package/dist/client/components/fields/array-field.mjs +14 -14
  21. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  22. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  23. package/dist/client/components/fields/json-field.mjs +2 -2
  24. package/dist/client/components/fields/object-array-field.mjs +22 -22
  25. package/dist/client/components/fields/object-field.mjs +5 -5
  26. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  27. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  28. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  29. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  30. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  31. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  32. package/dist/client/components/fields/relation-picker.mjs +7 -6
  33. package/dist/client/components/fields/relation-select.mjs +71 -47
  34. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  35. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  36. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  37. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  38. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  39. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  40. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  41. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  42. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  43. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  44. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  45. package/dist/client/components/fields/upload-field.mjs +45 -49
  46. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  47. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  48. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  49. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  50. package/dist/client/components/history-sidebar.mjs +850 -340
  51. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  52. package/dist/client/components/locale-switcher.mjs +8 -8
  53. package/dist/client/components/media/media-grid.mjs +12 -9
  54. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  55. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  56. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  57. package/dist/client/components/primitives/date-input.mjs +212 -249
  58. package/dist/client/components/primitives/dropzone.mjs +192 -159
  59. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  60. package/dist/client/components/primitives/select-multi.mjs +251 -230
  61. package/dist/client/components/primitives/select-single.mjs +345 -290
  62. package/dist/client/components/primitives/time-input.mjs +2 -2
  63. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  64. package/dist/client/components/ui/accordion.mjs +4 -4
  65. package/dist/client/components/ui/alert.mjs +3 -3
  66. package/dist/client/components/ui/badge.mjs +4 -4
  67. package/dist/client/components/ui/button.mjs +47 -37
  68. package/dist/client/components/ui/card.mjs +2 -2
  69. package/dist/client/components/ui/checkbox.mjs +1 -1
  70. package/dist/client/components/ui/command.mjs +5 -5
  71. package/dist/client/components/ui/dialog.mjs +3 -3
  72. package/dist/client/components/ui/drawer.mjs +1 -1
  73. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  74. package/dist/client/components/ui/empty-state.mjs +88 -59
  75. package/dist/client/components/ui/field.mjs +2 -2
  76. package/dist/client/components/ui/input-group.mjs +3 -3
  77. package/dist/client/components/ui/input.mjs +1 -1
  78. package/dist/client/components/ui/kbd.mjs +1 -1
  79. package/dist/client/components/ui/label.mjs +1 -1
  80. package/dist/client/components/ui/popover.mjs +19 -11
  81. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  82. package/dist/client/components/ui/search-input.mjs +1 -1
  83. package/dist/client/components/ui/select.mjs +129 -27
  84. package/dist/client/components/ui/sheet.mjs +54 -34
  85. package/dist/client/components/ui/sidebar.mjs +15 -14
  86. package/dist/client/components/ui/skeleton.mjs +28 -12
  87. package/dist/client/components/ui/switch.mjs +2 -2
  88. package/dist/client/components/ui/table.mjs +82 -74
  89. package/dist/client/components/ui/tabs.mjs +26 -31
  90. package/dist/client/components/ui/textarea.mjs +1 -1
  91. package/dist/client/components/ui/tooltip.mjs +1 -1
  92. package/dist/client/components/widgets/chart-widget.mjs +134 -96
  93. package/dist/client/components/widgets/progress-widget.mjs +59 -34
  94. package/dist/client/components/widgets/quick-actions-widget.mjs +184 -113
  95. package/dist/client/components/widgets/recent-items-widget.mjs +144 -102
  96. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  97. package/dist/client/components/widgets/table-widget.mjs +159 -246
  98. package/dist/client/components/widgets/timeline-widget.mjs +66 -43
  99. package/dist/client/components/widgets/value-widget.mjs +261 -152
  100. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  101. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  102. package/dist/client/contexts/focus-context.d.mts +2 -2
  103. package/dist/client/hooks/use-action.mjs +63 -55
  104. package/dist/client/hooks/use-audit-history.mjs +1 -65
  105. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  106. package/dist/client/hooks/use-collection.mjs +96 -1
  107. package/dist/client/hooks/use-saved-views.mjs +70 -49
  108. package/dist/client/hooks/use-server-actions.mjs +59 -40
  109. package/dist/client/hooks/use-server-validation.mjs +156 -41
  110. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  111. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  112. package/dist/client/hooks/use-setup-status.mjs +2 -2
  113. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  114. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  115. package/dist/client/hooks/use-view-state.mjs +238 -174
  116. package/dist/client/i18n/date-locale.mjs +33 -0
  117. package/dist/client/i18n/hooks.mjs +17 -1
  118. package/dist/client/lib/utils.mjs +3 -2
  119. package/dist/client/preview/block-scope-context.d.mts +2 -2
  120. package/dist/client/preview/preview-banner.d.mts +2 -2
  121. package/dist/client/preview/preview-field.d.mts +4 -4
  122. package/dist/client/preview/preview-field.mjs +2 -2
  123. package/dist/client/runtime/provider.mjs +8 -1
  124. package/dist/client/runtime/translations-provider.mjs +1 -1
  125. package/dist/client/scope/picker.d.mts +2 -2
  126. package/dist/client/scope/provider.d.mts +2 -2
  127. package/dist/client/styles/base.css +1022 -0
  128. package/dist/client/styles/index.css +3 -589
  129. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  130. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  131. package/dist/client/utils/use-lazy-component.mjs +80 -0
  132. package/dist/client/views/auth/auth-layout.d.mts +18 -11
  133. package/dist/client/views/auth/auth-layout.mjs +291 -80
  134. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  135. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  136. package/dist/client/views/auth/login-form.d.mts +2 -2
  137. package/dist/client/views/auth/login-form.mjs +1 -1
  138. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  139. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  140. package/dist/client/views/auth/setup-form.d.mts +2 -2
  141. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  142. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  143. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  144. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  145. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  146. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  147. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  148. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  149. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  150. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  151. package/dist/client/views/collection/field-renderer.mjs +50 -89
  152. package/dist/client/views/collection/form-view.mjs +237 -227
  153. package/dist/client/views/collection/table-view.mjs +1162 -229
  154. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  155. package/dist/client/views/common/global-search.mjs +29 -18
  156. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  157. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  158. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  159. package/dist/client/views/globals/global-form-view.mjs +634 -589
  160. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  161. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  162. package/dist/client/views/layout/admin-layout.mjs +149 -172
  163. package/dist/client/views/layout/admin-router.mjs +747 -544
  164. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  165. package/dist/client/views/layout/admin-sidebar.mjs +751 -591
  166. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  167. package/dist/client/views/layout/admin-theme.mjs +84 -0
  168. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  169. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  170. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  171. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  172. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  173. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  174. package/dist/client/views/pages/invite-page.d.mts +2 -2
  175. package/dist/client/views/pages/invite-page.mjs +2 -19
  176. package/dist/client/views/pages/login-page.d.mts +1 -1
  177. package/dist/client/views/pages/login-page.mjs +4 -21
  178. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  179. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  180. package/dist/client/views/pages/setup-page.d.mts +2 -2
  181. package/dist/client/views/pages/setup-page.mjs +3 -20
  182. package/dist/client.d.mts +6 -2
  183. package/dist/client.mjs +2 -1
  184. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  185. package/dist/index.d.mts +6 -2
  186. package/dist/index.mjs +2 -1
  187. package/dist/server/augmentation/dashboard.d.mts +67 -3
  188. package/dist/server/augmentation/form-layout.d.mts +21 -0
  189. package/dist/server/augmentation/index.d.mts +1 -1
  190. package/dist/server/codegen/admin-client-template.mjs +4 -0
  191. package/dist/server/fields/blocks.d.mts +1 -1
  192. package/dist/server/fields/blocks.mjs +12 -0
  193. package/dist/server/fields/rich-text.d.mts +1 -1
  194. package/dist/server/fields/rich-text.mjs +8 -0
  195. package/dist/server/i18n/index.mjs +17 -1
  196. package/dist/server/i18n/messages/cs.mjs +23 -0
  197. package/dist/server/i18n/messages/de.mjs +23 -0
  198. package/dist/server/i18n/messages/en.mjs +64 -1
  199. package/dist/server/i18n/messages/es.mjs +23 -0
  200. package/dist/server/i18n/messages/fr.mjs +23 -0
  201. package/dist/server/i18n/messages/pl.mjs +23 -0
  202. package/dist/server/i18n/messages/pt.mjs +23 -0
  203. package/dist/server/i18n/messages/sk.mjs +83 -1
  204. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  205. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  206. package/dist/server/modules/admin/collections/account.d.mts +50 -50
  207. package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
  208. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  209. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  210. package/dist/server/modules/admin/collections/apikey.d.mts +68 -68
  211. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  212. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  213. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/user.d.mts +12 -0
  215. package/dist/server/modules/admin/collections/user.mjs +40 -9
  216. package/dist/server/modules/admin/collections/verification.d.mts +2 -2
  217. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  218. package/dist/server/modules/admin/factories.mjs +7 -18
  219. package/dist/server/modules/admin/index.d.mts +1 -1
  220. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  221. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  222. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  223. package/dist/server/modules/admin/routes/execute-action.mjs +33 -0
  224. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  225. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  226. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  227. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  228. package/dist/server/modules/admin/routes/setup.mjs +7 -7
  229. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  230. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  231. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  232. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  233. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +27 -27
  234. package/dist/server/modules/audit/.generated/module.d.mts +1 -1
  235. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  236. package/dist/server/modules/audit/collections/audit-log.d.mts +2 -2
  237. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  238. package/dist/server/modules/audit/config/app.mjs +99 -42
  239. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  240. package/dist/server/plugin.mjs +4 -2
  241. package/dist/server/proxy-factories.d.mts +4 -3
  242. package/dist/server/proxy-factories.mjs +34 -8
  243. package/dist/shared/types/saved-views.types.d.mts +2 -0
  244. package/package.json +6 -4
  245. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  246. package/dist/client/components/ui/spinner.mjs +0 -52
  247. package/dist/client/components/ui/toolbar.mjs +0 -136
  248. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  249. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -0,0 +1,1022 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @import "@fontsource-variable/geist";
5
+ @import "@fontsource-variable/jetbrains-mono";
6
+
7
+ /* ================================================================
8
+ QUESTPIE ADMIN THEME — Base
9
+ ================================================================
10
+
11
+ This file contains the admin design tokens, Tailwind mappings, and shared
12
+ utilities. It is the single supported admin stylesheet for now.
13
+
14
+ VARIABLE REFERENCE
15
+ ------------------
16
+
17
+ -- Surface Colors -----------------------------------------
18
+ --background Page background (darkest/lightest surface)
19
+ --foreground Primary text color on background
20
+ --card Elevated surface: cards, panels, sidebar
21
+ --card-foreground Text on card surfaces
22
+ --popover Floating surfaces: dropdowns, tooltips, dialogs
23
+ --popover-foreground Text on floating surfaces
24
+ --input Form input backgrounds
25
+ --muted Subtle backgrounds: hover, table headers, toggles
26
+ --muted-foreground Secondary/dimmed text (helper text, placeholders)
27
+ --accent Interactive hover backgrounds
28
+ --accent-foreground Text on accent backgrounds
29
+
30
+ -- Brand Colors -------------------------------------------
31
+ --primary Company CTA color; reserve for solid primary actions
32
+ --primary-foreground Text on primary color backgrounds
33
+ --secondary Secondary action backgrounds
34
+ --secondary-foreground Text on secondary backgrounds
35
+
36
+ -- Semantic Colors ----------------------------------------
37
+ --destructive Errors, delete actions, danger states
38
+ --success Confirmations, positive states
39
+ --warning Caution states
40
+ --info Informational emphasis
41
+
42
+ -- Structure ----------------------------------------------
43
+ --border Default border color (all structural borders)
44
+ --ring Neutral focus ring color
45
+
46
+ -- Sidebar ------------------------------------------------
47
+ Separate tokens for sidebar to allow independent theming.
48
+ --sidebar, --sidebar-foreground, --sidebar-primary,
49
+ --sidebar-accent, --sidebar-border, --sidebar-ring,
50
+ --sidebar-active-background, --sidebar-active-foreground,
51
+ --sidebar-active-indicator, etc.
52
+
53
+ -- Shape -------------------------------------------------
54
+ --radius Base border-radius (neutral default: 0.5rem / 8px)
55
+ --shadow-* Default shadow scale for elevated surfaces
56
+
57
+ -- Typography ---------------------------------------------
58
+ --font-sans Default for all UI body text and content
59
+ --font-mono Technical content: code, kbd, IDs, timestamps
60
+ --font-chrome UI chrome (buttons, labels, inputs, tabs, badges)
61
+
62
+ -- Spacing ------------------------------------------------
63
+ --spacing-card Internal card/panel padding (default: 16px)
64
+ --spacing-section Section gaps (default: 24px)
65
+ --spacing-input Input internal padding (default: 12px)
66
+
67
+ -- Texture -----------------------------------------------
68
+ Base intentionally does not add background texture. Apps can add their own
69
+ body::before layer if they need branded texture.
70
+ ================================================================ */
71
+
72
+ /* Dark-first Autopilot base. :root is dark; .light opt-in mirrors hierarchy. */
73
+ :root,
74
+ .dark {
75
+ --background: #121212;
76
+ --foreground: #ececec;
77
+ --foreground-muted: #a0a0a0;
78
+ --foreground-subtle: #737373;
79
+ --foreground-disabled: #5a5a5a;
80
+ --surface: #161616;
81
+ --surface-low: #1b1b1b;
82
+ --surface-mid: #222222;
83
+ --surface-high: #2a2a2a;
84
+ --surface-highest: #333333;
85
+ --card: #1b1b1b;
86
+ --card-foreground: #ececec;
87
+ --popover: #1b1b1b;
88
+ --popover-foreground: #ececec;
89
+ --input: #343434;
90
+ --muted: #222222;
91
+ --muted-foreground: #a0a0a0;
92
+ --accent: #2a2a2a;
93
+ --accent-foreground: #ececec;
94
+ --secondary: #222222;
95
+ --secondary-foreground: #ececec;
96
+ --primary: #b700ff;
97
+ --primary-foreground: #ffffff;
98
+ --destructive: #ff5f6d;
99
+ --destructive-foreground: #1c0b0f;
100
+ --success: #4ade80;
101
+ --success-foreground: #062d16;
102
+ --warning: #222222;
103
+ --warning-foreground: #ececec;
104
+ --info: #222222;
105
+ --info-foreground: #ececec;
106
+ --border-subtle: #262626;
107
+ --border: #343434;
108
+ --border-strong: #4a4a4a;
109
+ --ring: #737373;
110
+ --selection: #333333;
111
+ --radius: 0.75rem;
112
+ --control-height: 2.5rem;
113
+ --control-radius: 0.75rem;
114
+ --control-radius-inner: 0.5rem;
115
+ --control-background: var(--card);
116
+ --control-border: var(--border);
117
+ --control-shadow: none;
118
+ --surface-radius: 0.875rem;
119
+ --surface-shadow: none;
120
+ --floating-radius: 0.875rem;
121
+ --floating-shadow: 0 18px 40px -28px rgba(0, 0, 0, 0.72);
122
+ --motion-duration-fast: 100ms;
123
+ --motion-duration-base: 150ms;
124
+ --motion-duration-slow: 200ms;
125
+ --motion-ease-enter: cubic-bezier(0.22, 1, 0.36, 1);
126
+ --motion-ease-move: cubic-bezier(0.25, 1, 0.5, 1);
127
+ --motion-ease-standard: cubic-bezier(0.2, 0, 0, 1);
128
+ --motion-scale-enter: 0.98;
129
+
130
+ /* Neutral charts/statuses: color is not primary communication. */
131
+ --chart-1: #ececec;
132
+ --chart-2: #a0a0a0;
133
+ --chart-3: #737373;
134
+ --chart-4: #5a5a5a;
135
+ --chart-5: #4a4a4a;
136
+
137
+ /* Typography */
138
+ --font-sans: "Geist Variable", "Inter", sans-serif;
139
+ --font-mono:
140
+ "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, monospace;
141
+ --font-chrome: var(--font-sans);
142
+
143
+ /* Spacing Scale */
144
+ --spacing-section: 1.5rem;
145
+ --spacing-card: 1rem;
146
+ --spacing-input: 0.75rem;
147
+ --spacing-shell-gap: 0.75rem;
148
+ --spacing-shell-padding: 0.75rem;
149
+ --spacing-panel: 1.25rem;
150
+
151
+ /* Sidebar / left rail: neutral active states, no purple navigation. */
152
+ --sidebar: #161616;
153
+ --sidebar-foreground: #ececec;
154
+ --sidebar-primary: #ececec;
155
+ --sidebar-primary-foreground: #121212;
156
+ --sidebar-accent: #2a2a2a;
157
+ --sidebar-accent-foreground: #ececec;
158
+ --sidebar-border: #262626;
159
+ --sidebar-ring: var(--ring);
160
+ --sidebar-active-background: var(--surface-high);
161
+ --sidebar-active-foreground: var(--foreground);
162
+ --sidebar-active-indicator: var(--border-strong);
163
+ --sidebar-submenu: color-mix(in srgb, var(--surface-high) 48%, transparent);
164
+
165
+ --chrome-text-transform: none;
166
+ --chrome-letter-spacing: normal;
167
+ }
168
+
169
+ .light,
170
+ :root.light {
171
+ --background: #fafafa;
172
+ --foreground: #1c1c1c;
173
+ --foreground-muted: #616161;
174
+ --foreground-subtle: #858585;
175
+ --foreground-disabled: #a0a0a0;
176
+ --surface: #f7f7f7;
177
+ --surface-low: #ffffff;
178
+ --surface-mid: #f0f0f0;
179
+ --surface-high: #e8e8e8;
180
+ --surface-highest: #dedede;
181
+ --card: #ffffff;
182
+ --card-foreground: #1c1c1c;
183
+ --popover: #ffffff;
184
+ --popover-foreground: #1c1c1c;
185
+ --input: #e2e2e2;
186
+ --muted: #f0f0f0;
187
+ --muted-foreground: #616161;
188
+ --accent: #e8e8e8;
189
+ --accent-foreground: #1c1c1c;
190
+ --secondary: #f0f0f0;
191
+ --secondary-foreground: #1c1c1c;
192
+ --primary: #b700ff;
193
+ --primary-foreground: #ffffff;
194
+ --destructive: #d92d3a;
195
+ --destructive-foreground: #ffffff;
196
+ --success: #16a34a;
197
+ --success-foreground: #ffffff;
198
+ --warning: #f0f0f0;
199
+ --warning-foreground: #1c1c1c;
200
+ --info: #f0f0f0;
201
+ --info-foreground: #1c1c1c;
202
+ --border-subtle: #ebebeb;
203
+ --border: #e2e2e2;
204
+ --border-strong: #c9c9c9;
205
+ --ring: #858585;
206
+ --selection: #e8e8e8;
207
+ --control-background: var(--card);
208
+ --control-border: var(--border);
209
+ --control-shadow: none;
210
+ --surface-shadow: none;
211
+ --floating-shadow: 0 16px 36px -30px rgba(0, 0, 0, 0.38);
212
+
213
+ --chart-1: #1c1c1c;
214
+ --chart-2: #616161;
215
+ --chart-3: #858585;
216
+ --chart-4: #a0a0a0;
217
+ --chart-5: #c9c9c9;
218
+
219
+ --sidebar: #f7f7f7;
220
+ --sidebar-foreground: #1c1c1c;
221
+ --sidebar-primary: #1c1c1c;
222
+ --sidebar-primary-foreground: #ffffff;
223
+ --sidebar-accent: #e8e8e8;
224
+ --sidebar-accent-foreground: #1c1c1c;
225
+ --sidebar-border: #ebebeb;
226
+ --sidebar-ring: var(--ring);
227
+ --sidebar-active-background: var(--surface-high);
228
+ --sidebar-active-foreground: var(--foreground);
229
+ --sidebar-active-indicator: var(--border-strong);
230
+ --sidebar-submenu: color-mix(in srgb, var(--surface-high) 55%, transparent);
231
+ }
232
+
233
+ @theme inline {
234
+ /* Typography */
235
+ --font-sans: "Geist Variable", "Inter", sans-serif;
236
+ --font-mono:
237
+ "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, monospace;
238
+ --font-chrome: var(--font-sans);
239
+
240
+ /* Radius: Autopilot neutral-soft ladder */
241
+ --radius-xs: 4px;
242
+ --radius-sm: var(--control-radius-inner);
243
+ --radius-md: var(--control-radius);
244
+ --radius-lg: var(--surface-radius);
245
+ --radius-xl: 20px;
246
+ --radius-2xl: 24px;
247
+ --radius-3xl: 28px;
248
+ --radius-4xl: 28px;
249
+ --radius-full: 9999px;
250
+
251
+ /* Shadow scale: neutral black-alpha only. */
252
+ --shadow-xs: var(--control-shadow);
253
+ --shadow-sm: var(--surface-shadow);
254
+ --shadow: var(--surface-shadow);
255
+ --shadow-md: var(--floating-shadow);
256
+ --shadow-lg: var(--floating-shadow);
257
+ --shadow-xl: var(--floating-shadow);
258
+ --shadow-2xl: var(--floating-shadow);
259
+
260
+ /* Color mappings */
261
+ --color-sidebar-ring: var(--sidebar-ring);
262
+ --color-sidebar-border: var(--sidebar-border);
263
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
264
+ --color-sidebar-accent: var(--sidebar-accent);
265
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
266
+ --color-sidebar-primary: var(--sidebar-primary);
267
+ --color-sidebar-foreground: var(--sidebar-foreground);
268
+ --color-sidebar: var(--sidebar);
269
+ --color-chart-5: var(--chart-5);
270
+ --color-chart-4: var(--chart-4);
271
+ --color-chart-3: var(--chart-3);
272
+ --color-chart-2: var(--chart-2);
273
+ --color-chart-1: var(--chart-1);
274
+ --color-ring: var(--ring);
275
+ --color-input: var(--input);
276
+ --color-border: var(--border);
277
+ --color-border-subtle: var(--border-subtle);
278
+ --color-border-strong: var(--border-strong);
279
+ --color-destructive: var(--destructive);
280
+ --color-destructive-foreground: var(--destructive-foreground);
281
+ --color-success: var(--success);
282
+ --color-success-foreground: var(--success-foreground);
283
+ --color-warning: var(--warning);
284
+ --color-warning-foreground: var(--warning-foreground);
285
+ --color-info: var(--info);
286
+ --color-info-foreground: var(--info-foreground);
287
+ --color-accent-foreground: var(--accent-foreground);
288
+ --color-accent: var(--accent);
289
+ --color-muted-foreground: var(--muted-foreground);
290
+ --color-muted: var(--muted);
291
+ --color-foreground-muted: var(--foreground-muted);
292
+ --color-foreground-subtle: var(--foreground-subtle);
293
+ --color-foreground-disabled: var(--foreground-disabled);
294
+ --color-surface: var(--surface);
295
+ --color-surface-low: var(--surface-low);
296
+ --color-surface-mid: var(--surface-mid);
297
+ --color-surface-high: var(--surface-high);
298
+ --color-surface-highest: var(--surface-highest);
299
+ --color-secondary-foreground: var(--secondary-foreground);
300
+ --color-secondary: var(--secondary);
301
+ --color-primary-foreground: var(--primary-foreground);
302
+ --color-primary: var(--primary);
303
+ --color-popover-foreground: var(--popover-foreground);
304
+ --color-popover: var(--popover);
305
+ --color-card-foreground: var(--card-foreground);
306
+ --color-card: var(--card);
307
+ --color-foreground: var(--foreground);
308
+ --color-background: var(--background);
309
+ }
310
+
311
+ @utility control-surface {
312
+ height: var(--control-height);
313
+ border: 1px solid var(--control-border);
314
+ border-radius: var(--control-radius);
315
+ background-color: var(--control-background);
316
+ box-shadow: var(--control-shadow);
317
+ transition-property: background-color, border-color, color, box-shadow;
318
+ transition-duration: var(--motion-duration-base);
319
+ transition-timing-function: var(--motion-ease-standard);
320
+ }
321
+
322
+ @utility floating-surface {
323
+ border: 1px solid var(--border-subtle);
324
+ border-radius: var(--floating-radius);
325
+ background-color: var(--popover);
326
+ box-shadow: var(--floating-shadow);
327
+ }
328
+
329
+ @utility motion-interactive {
330
+ transition-property:
331
+ background-color, border-color, color, box-shadow, opacity, transform;
332
+ transition-duration: var(--motion-duration-base);
333
+ transition-timing-function: var(--motion-ease-standard);
334
+ }
335
+
336
+ @utility motion-floating {
337
+ transition-property: opacity, transform;
338
+ transition-duration: var(--motion-duration-base);
339
+ transition-timing-function: var(--motion-ease-enter);
340
+ }
341
+
342
+ @utility motion-floating-fast {
343
+ transition-property: opacity, transform;
344
+ transition-duration: var(--motion-duration-fast);
345
+ transition-timing-function: var(--motion-ease-enter);
346
+ }
347
+
348
+ @utility motion-sheet {
349
+ transition-property: opacity, transform;
350
+ transition-duration: var(--motion-duration-slow);
351
+ transition-timing-function: var(--motion-ease-move);
352
+ }
353
+
354
+ @utility motion-overlay {
355
+ transition-property: opacity, backdrop-filter;
356
+ transition-duration: var(--motion-duration-base);
357
+ transition-timing-function: var(--motion-ease-standard);
358
+ }
359
+
360
+ /* =============================================================================
361
+ Rich Text Editor Styles
362
+ ============================================================================= */
363
+
364
+ .qp-rich-text-editor {
365
+ position: relative;
366
+ border-color: var(--border-subtle);
367
+ background: var(--surface-low);
368
+ transition-property: background-color, border-color, box-shadow;
369
+ transition-duration: var(--motion-duration-base);
370
+ transition-timing-function: var(--motion-ease-standard);
371
+ }
372
+
373
+ .qp-rich-text-editor:focus-within {
374
+ border-color: var(--border-strong);
375
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 18%, transparent);
376
+ }
377
+
378
+ .qp-rich-text-editor [data-rich-text-toolbar-button] {
379
+ flex: 0 0 auto;
380
+ }
381
+
382
+ .qp-rich-text-editor__toolbar {
383
+ scrollbar-width: none;
384
+ -webkit-overflow-scrolling: touch;
385
+ }
386
+
387
+ .qp-rich-text-editor__toolbar::-webkit-scrollbar {
388
+ display: none;
389
+ }
390
+
391
+ .qp-rich-text-editor__toolbar > [role="group"] {
392
+ flex: 0 0 auto;
393
+ }
394
+
395
+ .qp-rich-text-editor__bubble {
396
+ display: flex;
397
+ align-items: center;
398
+ gap: 0.25rem;
399
+ padding: 0.25rem;
400
+ border-radius: calc(var(--control-radius-inner) + 0.25rem);
401
+ }
402
+
403
+ .qp-rich-text-editor__bubble-block {
404
+ border-color: transparent;
405
+ background: transparent;
406
+ box-shadow: none;
407
+ }
408
+
409
+ .qp-rich-text-editor__bubble-separator {
410
+ width: 1px;
411
+ height: 1.5rem;
412
+ background: var(--border-subtle);
413
+ }
414
+
415
+ .qp-rich-text-editor__link-form {
416
+ display: grid;
417
+ grid-template-columns: auto minmax(12rem, 18rem) auto auto;
418
+ align-items: center;
419
+ gap: 0.375rem;
420
+ padding: 0.125rem;
421
+ }
422
+
423
+ .qp-rich-text-editor__link-input {
424
+ height: 2rem;
425
+ border-color: transparent;
426
+ background: transparent;
427
+ box-shadow: none;
428
+ font-size: 0.8125rem;
429
+ }
430
+
431
+ .qp-rich-text-editor__upload-status {
432
+ position: absolute;
433
+ right: 0.75rem;
434
+ bottom: 0.75rem;
435
+ z-index: 1;
436
+ border: 1px solid var(--border-subtle);
437
+ border-radius: var(--control-radius);
438
+ background: var(--popover);
439
+ box-shadow: var(--floating-shadow);
440
+ padding: 0.375rem 0.625rem;
441
+ color: var(--popover-foreground);
442
+ font-family: var(--font-chrome);
443
+ font-size: 0.75rem;
444
+ }
445
+
446
+ .qp-rich-text-editor__content {
447
+ min-height: 240px;
448
+ padding: 1rem 1.25rem 1.25rem;
449
+ outline: none;
450
+ color: var(--foreground);
451
+ font-size: 0.9375rem;
452
+ line-height: 1.65;
453
+ text-wrap: pretty;
454
+ caret-color: var(--foreground);
455
+ }
456
+
457
+ .qp-rich-text-editor__content.ProseMirror-focused {
458
+ outline: none;
459
+ }
460
+
461
+ .qp-rich-text-editor__content p.is-editor-empty:first-child::before {
462
+ content: attr(data-placeholder);
463
+ float: left;
464
+ height: 0;
465
+ color: var(--muted-foreground);
466
+ pointer-events: none;
467
+ }
468
+
469
+ .qp-rich-text-editor__content > *:first-child {
470
+ margin-top: 0;
471
+ }
472
+
473
+ .qp-rich-text-editor__content > *:last-child {
474
+ margin-bottom: 0;
475
+ }
476
+
477
+ .qp-rich-text-editor__content p {
478
+ margin: 0 0 0.8rem;
479
+ }
480
+
481
+ .qp-rich-text-editor__content h1 {
482
+ margin: 1.5rem 0 0.85rem;
483
+ font-size: 1.625rem;
484
+ font-weight: 650;
485
+ letter-spacing: 0;
486
+ line-height: 1.2;
487
+ text-wrap: balance;
488
+ }
489
+
490
+ .qp-rich-text-editor__content h2 {
491
+ margin: 1.35rem 0 0.75rem;
492
+ font-size: 1.375rem;
493
+ font-weight: 650;
494
+ letter-spacing: 0;
495
+ line-height: 1.25;
496
+ text-wrap: balance;
497
+ }
498
+
499
+ .qp-rich-text-editor__content h3 {
500
+ margin: 1.15rem 0 0.65rem;
501
+ font-size: 1.125rem;
502
+ font-weight: 650;
503
+ letter-spacing: 0;
504
+ line-height: 1.3;
505
+ text-wrap: balance;
506
+ }
507
+
508
+ .qp-rich-text-editor__content h4,
509
+ .qp-rich-text-editor__content h5,
510
+ .qp-rich-text-editor__content h6 {
511
+ margin: 1rem 0 0.5rem;
512
+ font-size: 1rem;
513
+ font-weight: 650;
514
+ letter-spacing: 0;
515
+ line-height: 1.35;
516
+ text-wrap: balance;
517
+ }
518
+
519
+ .qp-rich-text-editor__content ul,
520
+ .qp-rich-text-editor__content ol {
521
+ margin: 0.75rem 0;
522
+ padding-left: 1.35rem;
523
+ }
524
+
525
+ .qp-rich-text-editor__content li {
526
+ margin: 0.25rem 0;
527
+ padding-left: 0.15rem;
528
+ }
529
+
530
+ .qp-rich-text-editor__content blockquote {
531
+ margin: 1rem 0;
532
+ border-left: 3px solid var(--border-strong);
533
+ padding: 0.15rem 0 0.15rem 0.85rem;
534
+ color: var(--muted-foreground);
535
+ }
536
+
537
+ .qp-rich-text-editor__content code {
538
+ background: var(--muted);
539
+ border-radius: var(--radius-xs);
540
+ padding: 0.1rem 0.3rem;
541
+ font-size: 0.875em;
542
+ font-family: var(--font-mono);
543
+ }
544
+
545
+ .qp-rich-text-editor__content pre {
546
+ background: var(--muted);
547
+ border-radius: var(--control-radius-inner);
548
+ margin: 1rem 0;
549
+ padding: 0.875rem 1rem;
550
+ font-family: var(--font-mono);
551
+ font-size: 0.8125rem;
552
+ line-height: 1.6;
553
+ overflow-x: auto;
554
+ }
555
+
556
+ .qp-rich-text-editor__content pre code {
557
+ background: transparent;
558
+ border-radius: 0;
559
+ padding: 0;
560
+ }
561
+
562
+ .qp-rich-text-editor__content hr {
563
+ border: none;
564
+ border-top: 1px solid var(--border-subtle);
565
+ margin: 1.25rem 0;
566
+ }
567
+
568
+ .qp-rich-text-editor__content img {
569
+ display: block;
570
+ max-width: 100%;
571
+ height: auto;
572
+ margin: 1rem 0;
573
+ border-radius: var(--control-radius-inner);
574
+ outline: 1px solid rgba(255, 255, 255, 0.1);
575
+ outline-offset: -1px;
576
+ }
577
+
578
+ .light .qp-rich-text-editor__content img,
579
+ :root.light .qp-rich-text-editor__content img {
580
+ outline-color: rgba(0, 0, 0, 0.1);
581
+ }
582
+
583
+ .qp-rich-text-editor__content table {
584
+ border-collapse: collapse;
585
+ margin: 1rem 0;
586
+ width: 100%;
587
+ font-size: 0.875rem;
588
+ }
589
+
590
+ .qp-rich-text-editor__content th,
591
+ .qp-rich-text-editor__content td {
592
+ border: 1px solid var(--border-subtle);
593
+ padding: 0.5rem 0.625rem;
594
+ text-align: left;
595
+ vertical-align: top;
596
+ }
597
+
598
+ .qp-rich-text-editor__content th {
599
+ background: var(--surface-mid);
600
+ font-weight: 600;
601
+ }
602
+
603
+ .tippy-box[data-theme~="qp-rich-text-editor"] {
604
+ background: var(--popover);
605
+ color: var(--popover-foreground);
606
+ border: 1px solid var(--border-subtle);
607
+ border-radius: var(--floating-radius);
608
+ box-shadow: var(--floating-shadow);
609
+ }
610
+
611
+ .tippy-box[data-theme~="qp-rich-text-editor"] .tippy-content {
612
+ padding: 0;
613
+ }
614
+
615
+ .qp-rich-text-editor__slash {
616
+ display: flex;
617
+ flex-direction: column;
618
+ gap: 0.25rem;
619
+ min-width: 280px;
620
+ max-width: min(360px, calc(100vw - 2rem));
621
+ padding: 0.35rem;
622
+ }
623
+
624
+ .qp-rich-text-editor__slash-item {
625
+ display: flex;
626
+ width: 100%;
627
+ min-height: 3rem;
628
+ align-items: center;
629
+ gap: 0.625rem;
630
+ border: 1px solid transparent;
631
+ border-radius: var(--control-radius-inner);
632
+ background: transparent;
633
+ padding: 0.45rem 0.55rem;
634
+ color: var(--foreground);
635
+ font-size: 0.8125rem;
636
+ line-height: 1.2;
637
+ text-align: left;
638
+ transition:
639
+ background-color 150ms ease,
640
+ border-color 150ms ease,
641
+ color 150ms ease;
642
+ }
643
+
644
+ .qp-rich-text-editor__slash-item--active,
645
+ .qp-rich-text-editor__slash-item:hover {
646
+ background: var(--surface-high);
647
+ border-color: var(--border-subtle);
648
+ color: var(--accent-foreground);
649
+ }
650
+
651
+ .qp-rich-text-editor__slash-icon {
652
+ display: inline-flex;
653
+ width: 2rem;
654
+ height: 2rem;
655
+ flex: 0 0 auto;
656
+ align-items: center;
657
+ justify-content: center;
658
+ border-radius: var(--radius-xs);
659
+ background: var(--surface-mid);
660
+ color: var(--muted-foreground);
661
+ }
662
+
663
+ .qp-rich-text-editor__slash-copy {
664
+ display: flex;
665
+ min-width: 0;
666
+ flex: 1;
667
+ flex-direction: column;
668
+ gap: 0.125rem;
669
+ }
670
+
671
+ .qp-rich-text-editor__slash-title {
672
+ font-family: var(--font-chrome);
673
+ font-weight: 600;
674
+ }
675
+
676
+ .qp-rich-text-editor__slash-description {
677
+ color: var(--muted-foreground);
678
+ overflow: hidden;
679
+ text-overflow: ellipsis;
680
+ white-space: nowrap;
681
+ }
682
+
683
+ .qp-rich-text-editor__slash-empty {
684
+ padding: 0.5rem;
685
+ font-size: 0.75rem;
686
+ color: var(--muted-foreground);
687
+ }
688
+
689
+ @media (prefers-reduced-motion: reduce) {
690
+ .qp-rich-text-editor,
691
+ .qp-rich-text-editor__bubble,
692
+ .qp-rich-text-editor__slash-item {
693
+ transition: none;
694
+ }
695
+ }
696
+
697
+ @media (max-width: 640px) {
698
+ .qp-rich-text-editor__content {
699
+ min-height: 200px;
700
+ padding: 0.875rem 1rem 1rem;
701
+ }
702
+
703
+ .qp-rich-text-editor__bubble {
704
+ max-width: calc(100vw - 1.5rem);
705
+ flex-wrap: wrap;
706
+ }
707
+
708
+ .qp-rich-text-editor__link-form {
709
+ width: min(24rem, calc(100vw - 2rem));
710
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
711
+ }
712
+
713
+ .qp-rich-text-editor__slash {
714
+ min-width: min(280px, calc(100vw - 2rem));
715
+ }
716
+ }
717
+
718
+ /* =============================================================================
719
+ Base Styles
720
+ ============================================================================= */
721
+
722
+ @layer base {
723
+ * {
724
+ @apply border-border outline-ring/50;
725
+ }
726
+
727
+ html {
728
+ font-family: var(--font-sans);
729
+ -webkit-font-smoothing: antialiased;
730
+ -moz-osx-font-smoothing: grayscale;
731
+ }
732
+
733
+ body {
734
+ @apply bg-background text-foreground;
735
+ font-family: var(--font-sans);
736
+ font-size: 15px;
737
+ line-height: 1.55;
738
+ text-rendering: optimizeLegibility;
739
+ }
740
+
741
+ h1,
742
+ h2,
743
+ h3,
744
+ h4,
745
+ h5,
746
+ h6 {
747
+ letter-spacing: -0.02em;
748
+ text-wrap: balance;
749
+ }
750
+
751
+ p,
752
+ li,
753
+ dd,
754
+ dt {
755
+ text-wrap: pretty;
756
+ }
757
+
758
+ button,
759
+ input,
760
+ textarea,
761
+ select {
762
+ font: inherit;
763
+ }
764
+
765
+ ::selection {
766
+ background-color: var(--selection);
767
+ color: var(--foreground);
768
+ }
769
+ }
770
+
771
+ /* =============================================================================
772
+ Custom Scrollbar Styles
773
+ ============================================================================= */
774
+
775
+ @utility scrollbar-thin {
776
+ scrollbar-width: thin;
777
+ scrollbar-color: color-mix(in oklch, var(--border) 50%, transparent)
778
+ transparent;
779
+
780
+ &::-webkit-scrollbar {
781
+ width: 6px;
782
+ height: 6px;
783
+ }
784
+
785
+ &::-webkit-scrollbar-track {
786
+ background: transparent;
787
+ }
788
+
789
+ &::-webkit-scrollbar-thumb {
790
+ background: color-mix(in oklch, var(--border) 60%, transparent);
791
+ border-radius: 3px;
792
+ }
793
+
794
+ &::-webkit-scrollbar-thumb:hover {
795
+ background: var(--border);
796
+ }
797
+
798
+ &::-webkit-scrollbar-corner {
799
+ background: transparent;
800
+ }
801
+ }
802
+
803
+ /* =============================================================================
804
+ Chrome Meta — compact metadata/label text treatment
805
+ ============================================================================= */
806
+
807
+ @utility chrome-meta {
808
+ text-transform: var(--chrome-text-transform, none);
809
+ letter-spacing: var(--chrome-letter-spacing, normal);
810
+ }
811
+
812
+ /* =============================================================================
813
+ Shared Surface Helpers
814
+ Neutral structural helpers for repeated item/panel patterns.
815
+ Color comes from semantic utilities layered on top.
816
+ ============================================================================= */
817
+
818
+ @utility item-surface {
819
+ border: 1px solid transparent;
820
+ border-radius: var(--radius-sm, var(--radius));
821
+ background-color: transparent;
822
+ transition-property:
823
+ background-color, border-color, color, box-shadow, opacity, transform;
824
+ transition-duration: var(--motion-duration-base);
825
+ transition-timing-function: var(--motion-ease-standard);
826
+ }
827
+
828
+ @utility panel-surface {
829
+ border: 1px solid var(--border);
830
+ border-radius: var(--surface-radius, var(--radius));
831
+ background-color: var(--card);
832
+ box-shadow: var(--surface-shadow);
833
+ transition-property:
834
+ background-color, border-color, color, box-shadow, opacity, transform;
835
+ transition-duration: var(--motion-duration-base);
836
+ transition-timing-function: var(--motion-ease-standard);
837
+ }
838
+
839
+ @utility image-outline {
840
+ outline: 1px solid rgba(255, 255, 255, 0.1);
841
+ outline-offset: -1px;
842
+ }
843
+
844
+ .light .image-outline,
845
+ :root.light .image-outline {
846
+ outline-color: rgba(0, 0, 0, 0.1);
847
+ }
848
+
849
+ /* =============================================================================
850
+ Field Focus Animation
851
+ ============================================================================= */
852
+
853
+ @keyframes field-glow {
854
+ 0%,
855
+ 100% {
856
+ background-color: transparent;
857
+ }
858
+ 50% {
859
+ background-color: color-mix(in srgb, var(--surface-high) 40%, transparent);
860
+ }
861
+ }
862
+
863
+ .animate-field-glow {
864
+ animation: field-glow 2s ease-in-out;
865
+ }
866
+
867
+ /* =============================================================================
868
+ Realtime Highlight Animation
869
+ ============================================================================= */
870
+
871
+ @keyframes realtime-pulse {
872
+ 0% {
873
+ border-left-color: var(--border-strong);
874
+ }
875
+ 100% {
876
+ border-left-color: transparent;
877
+ }
878
+ }
879
+
880
+ .animate-realtime-pulse {
881
+ border-left: 3px solid transparent;
882
+ animation: realtime-pulse 1.5s ease-out;
883
+ }
884
+
885
+ /* Delete animation - neutral pulse + fade out */
886
+ @keyframes realtime-delete {
887
+ 0% {
888
+ background-color: color-mix(
889
+ in srgb,
890
+ var(--surface-highest) 45%,
891
+ transparent
892
+ );
893
+ opacity: 1;
894
+ }
895
+ 70% {
896
+ background-color: color-mix(
897
+ in srgb,
898
+ var(--surface-highest) 28%,
899
+ transparent
900
+ );
901
+ opacity: 0.7;
902
+ }
903
+ 100% {
904
+ background-color: color-mix(
905
+ in srgb,
906
+ var(--surface-highest) 18%,
907
+ transparent
908
+ );
909
+ opacity: 0;
910
+ }
911
+ }
912
+
913
+ .animate-realtime-delete {
914
+ animation: realtime-delete 1.5s ease-out forwards;
915
+ pointer-events: none;
916
+ }
917
+
918
+ /* =============================================================================
919
+ Reduced Motion — Respect user's motion preferences (WCAG 2.1 AA)
920
+ ============================================================================= */
921
+
922
+ @media (prefers-reduced-motion: reduce) {
923
+ *,
924
+ *::before,
925
+ *::after {
926
+ animation-duration: 0.01ms !important;
927
+ animation-iteration-count: 1 !important;
928
+ transition-duration: 0.01ms !important;
929
+ scroll-behavior: auto !important;
930
+ }
931
+
932
+ .animate-field-glow,
933
+ .animate-realtime-pulse,
934
+ .animate-realtime-delete,
935
+ .animate-spin {
936
+ animation: none !important;
937
+ }
938
+ }
939
+
940
+ /* =============================================================================
941
+ High Contrast — Improve visibility for users needing more contrast
942
+ ============================================================================= */
943
+
944
+ @media (prefers-contrast: more) {
945
+ :root {
946
+ --muted-foreground: oklch(0.37 0 0);
947
+ --border: oklch(0.66 0 0);
948
+ }
949
+
950
+ .dark {
951
+ --muted-foreground: oklch(0.73 0 0);
952
+ --border: oklch(0.56 0 0);
953
+ }
954
+ }
955
+
956
+ /* =============================================================================
957
+ Focus Visible — Enhanced focus styles for keyboard navigation
958
+ ============================================================================= */
959
+
960
+ @layer base {
961
+ :focus-visible {
962
+ outline: 2px solid var(--ring);
963
+ outline-offset: 2px;
964
+ }
965
+
966
+ /* Skip link styles */
967
+ [href="#main-content"]:focus {
968
+ clip: auto;
969
+ clip-path: none;
970
+ height: auto;
971
+ width: auto;
972
+ overflow: visible;
973
+ white-space: nowrap;
974
+ }
975
+
976
+ /* Field focus pulse animation (preview click-to-focus) */
977
+ @keyframes field-focus-pulse {
978
+ 0% {
979
+ box-shadow: 0 0 0 0 var(--ring);
980
+ }
981
+ 50% {
982
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--ring) 30%, transparent);
983
+ }
984
+ 100% {
985
+ box-shadow: 0 0 0 0 transparent;
986
+ }
987
+ }
988
+
989
+ .field-focus-pulse {
990
+ animation: field-focus-pulse 0.6s ease-out;
991
+ border-radius: var(--radius);
992
+ }
993
+ }
994
+
995
+ iconify-icon {
996
+ display: inline-block;
997
+ }
998
+
999
+ iconify-icon:not([width]) {
1000
+ width: 1em;
1001
+ height: 1em;
1002
+ }
1003
+
1004
+ .qa-auth-layout {
1005
+ --primary: var(--foreground);
1006
+ --primary-foreground: var(--background);
1007
+ }
1008
+
1009
+ /* =============================================================================
1010
+ Input Group Control — Layout Fix
1011
+
1012
+ SelectSingle / InputGroupInput rendered inside InputGroup as
1013
+ [data-slot="input-group-control"] must grow to fill available flex space.
1014
+ The Button primitive carries `shrink-0` in its base CVA which prevents it
1015
+ from yielding space to sibling InputGroupAddon buttons.
1016
+ Unlayered CSS wins over Tailwind @layer utilities — this is intentional.
1017
+ ============================================================================= */
1018
+
1019
+ [data-slot="input-group-control"] {
1020
+ flex: 1 1 0%;
1021
+ min-width: 0;
1022
+ }