opacacms 0.1.11 → 0.1.13

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 (246) hide show
  1. package/dist/admin/index.js +9464 -21
  2. package/dist/admin/webcomponent.d.ts +1 -1
  3. package/dist/admin/webcomponent.js +9620 -6
  4. package/dist/admin.css +1 -0
  5. package/dist/{chunk-6dhs73zq.js → chunk-0am1m47g.js} +1 -1
  6. package/dist/{chunk-0nf7fe26.js → chunk-0d9aqz6z.js} +1 -1
  7. package/dist/{chunk-cvdd4eqh.js → chunk-2kyhqvhc.js} +5 -1
  8. package/dist/{chunk-gjjcc4hm.js → chunk-2z8wxx9g.js} +21 -6
  9. package/dist/{chunk-xg35h5a3.js → chunk-7fyepksb.js} +1 -1
  10. package/dist/{chunk-njytmdb4.js → chunk-pxh5encs.js} +34 -24
  11. package/dist/{chunk-n8aekdnr.js → chunk-qkn1ykrj.js} +33 -23
  12. package/dist/{chunk-kwp83w8b.js → chunk-wmvjvn7b.js} +4 -4
  13. package/dist/{chunk-qrt22f6e.js → chunk-wq314kkx.js} +35 -25
  14. package/dist/{chunk-eqtsfyjf.js → chunk-x2ejaftz.js} +52 -28
  15. package/dist/{chunk-6ew02s0c.js → chunk-xtwc125q.js} +18 -18
  16. package/dist/cli/index.js +5 -5
  17. package/dist/db/better-sqlite.d.ts +1 -0
  18. package/dist/db/better-sqlite.js +3 -3
  19. package/dist/db/bun-sqlite.d.ts +1 -0
  20. package/dist/db/bun-sqlite.js +3 -3
  21. package/dist/db/d1.js +3 -3
  22. package/dist/db/index.d.ts +3 -0
  23. package/dist/db/index.js +17 -13
  24. package/dist/db/postgres.js +3 -3
  25. package/dist/db/sqlite.js +3 -3
  26. package/dist/runtimes/bun.js +2 -2
  27. package/dist/runtimes/cloudflare-workers.js +2 -2
  28. package/dist/runtimes/next.js +2 -2
  29. package/dist/runtimes/node.js +2 -2
  30. package/dist/server.js +2 -2
  31. package/package.json +8 -2
  32. package/bun.lock +0 -34
  33. package/dist/admin/index.css +0 -47
  34. package/dist/api.d.ts +0 -6
  35. package/dist/api.js +0 -27
  36. package/dist/chunk-2zm8cy1w.js +0 -9482
  37. package/global.d.ts +0 -11
  38. package/src/admin/api-client.ts +0 -63
  39. package/src/admin/auth-client.ts +0 -40
  40. package/src/admin/custom-field.ts +0 -179
  41. package/src/admin/index.ts +0 -15
  42. package/src/admin/react.tsx +0 -72
  43. package/src/admin/router.ts +0 -9
  44. package/src/admin/stores/admin-queries.ts +0 -121
  45. package/src/admin/stores/auth.ts +0 -61
  46. package/src/admin/stores/column-visibility.ts +0 -67
  47. package/src/admin/stores/config.ts +0 -15
  48. package/src/admin/stores/media.ts +0 -95
  49. package/src/admin/stores/query.ts +0 -13
  50. package/src/admin/stores/ui.ts +0 -29
  51. package/src/admin/ui/admin-client.tsx +0 -283
  52. package/src/admin/ui/admin-layout.tsx +0 -276
  53. package/src/admin/ui/components/ColumnVisibilityToggle.tsx +0 -141
  54. package/src/admin/ui/components/DataDetailSheet.tsx +0 -141
  55. package/src/admin/ui/components/DataDetailView.tsx +0 -175
  56. package/src/admin/ui/components/Table.tsx +0 -67
  57. package/src/admin/ui/components/fields/ArrayField.tsx +0 -166
  58. package/src/admin/ui/components/fields/BlocksField.tsx +0 -202
  59. package/src/admin/ui/components/fields/BooleanField.tsx +0 -50
  60. package/src/admin/ui/components/fields/CollapsibleField.tsx +0 -75
  61. package/src/admin/ui/components/fields/DateField.tsx +0 -45
  62. package/src/admin/ui/components/fields/FileField.tsx +0 -322
  63. package/src/admin/ui/components/fields/GroupField.tsx +0 -50
  64. package/src/admin/ui/components/fields/JoinField.tsx +0 -23
  65. package/src/admin/ui/components/fields/NumberField.tsx +0 -46
  66. package/src/admin/ui/components/fields/RadioField.tsx +0 -62
  67. package/src/admin/ui/components/fields/RelationshipField.tsx +0 -278
  68. package/src/admin/ui/components/fields/RowField.tsx +0 -40
  69. package/src/admin/ui/components/fields/SelectField.tsx +0 -59
  70. package/src/admin/ui/components/fields/TabsField.tsx +0 -101
  71. package/src/admin/ui/components/fields/TextAreaField.tsx +0 -54
  72. package/src/admin/ui/components/fields/TextField.tsx +0 -49
  73. package/src/admin/ui/components/fields/VirtualField.tsx +0 -53
  74. package/src/admin/ui/components/fields/index.tsx +0 -371
  75. package/src/admin/ui/components/fields/richtext-editor/index.tsx +0 -211
  76. package/src/admin/ui/components/fields/richtext-editor/nodes/ImageComponent.tsx +0 -142
  77. package/src/admin/ui/components/fields/richtext-editor/nodes/ImageNode.tsx +0 -95
  78. package/src/admin/ui/components/fields/richtext-editor/plugins/ComponentPickerPlugin.tsx +0 -226
  79. package/src/admin/ui/components/fields/richtext-editor/plugins/EditableSyncPlugin.tsx +0 -16
  80. package/src/admin/ui/components/fields/richtext-editor/plugins/NotionToolbarPlugin.tsx +0 -184
  81. package/src/admin/ui/components/fields/richtext-editor/plugins/SimpleToolbarPlugin.tsx +0 -240
  82. package/src/admin/ui/components/fields/richtext-editor/plugins/ValueSyncPlugin.tsx +0 -40
  83. package/src/admin/ui/components/fields/utils.ts +0 -1
  84. package/src/admin/ui/components/link.tsx +0 -41
  85. package/src/admin/ui/components/media/AssetManagerModal.tsx +0 -334
  86. package/src/admin/ui/components/toast.tsx +0 -72
  87. package/src/admin/ui/components/ui/accordion.tsx +0 -51
  88. package/src/admin/ui/components/ui/alert-dialog.tsx +0 -98
  89. package/src/admin/ui/components/ui/blocks.tsx +0 -32
  90. package/src/admin/ui/components/ui/breadcrumbs.tsx +0 -59
  91. package/src/admin/ui/components/ui/button.tsx +0 -26
  92. package/src/admin/ui/components/ui/collapsible.tsx +0 -124
  93. package/src/admin/ui/components/ui/dialog.tsx +0 -79
  94. package/src/admin/ui/components/ui/group.tsx +0 -20
  95. package/src/admin/ui/components/ui/index.ts +0 -17
  96. package/src/admin/ui/components/ui/input.tsx +0 -12
  97. package/src/admin/ui/components/ui/join.tsx +0 -53
  98. package/src/admin/ui/components/ui/label.tsx +0 -11
  99. package/src/admin/ui/components/ui/radio-group.tsx +0 -75
  100. package/src/admin/ui/components/ui/relationship-detail-sheet.tsx +0 -122
  101. package/src/admin/ui/components/ui/relationship.tsx +0 -58
  102. package/src/admin/ui/components/ui/scroll-area.tsx +0 -19
  103. package/src/admin/ui/components/ui/select.tsx +0 -187
  104. package/src/admin/ui/components/ui/separator.tsx +0 -21
  105. package/src/admin/ui/components/ui/sheet.tsx +0 -106
  106. package/src/admin/ui/components/ui/tabs.tsx +0 -116
  107. package/src/admin/ui/components/ui/utils.ts +0 -3
  108. package/src/admin/ui/hooks/use-debounce.ts +0 -15
  109. package/src/admin/ui/styles/_locale-switcher.scss +0 -33
  110. package/src/admin/ui/styles/accordion.scss +0 -60
  111. package/src/admin/ui/styles/animations.scss +0 -41
  112. package/src/admin/ui/styles/asset-manager.scss +0 -547
  113. package/src/admin/ui/styles/badge.scss +0 -13
  114. package/src/admin/ui/styles/base.scss +0 -22
  115. package/src/admin/ui/styles/button.scss +0 -161
  116. package/src/admin/ui/styles/card.scss +0 -13
  117. package/src/admin/ui/styles/collapsible.scss +0 -75
  118. package/src/admin/ui/styles/data-detail.scss +0 -92
  119. package/src/admin/ui/styles/dialog.scss +0 -102
  120. package/src/admin/ui/styles/empty-state.scss +0 -22
  121. package/src/admin/ui/styles/group.scss +0 -19
  122. package/src/admin/ui/styles/index.scss +0 -33
  123. package/src/admin/ui/styles/input.scss +0 -80
  124. package/src/admin/ui/styles/label.scss +0 -12
  125. package/src/admin/ui/styles/layout.scss +0 -56
  126. package/src/admin/ui/styles/lexical.scss +0 -469
  127. package/src/admin/ui/styles/loading.scss +0 -102
  128. package/src/admin/ui/styles/media-registry.scss +0 -597
  129. package/src/admin/ui/styles/pagination.scss +0 -20
  130. package/src/admin/ui/styles/radio-group.scss +0 -66
  131. package/src/admin/ui/styles/row.scss +0 -17
  132. package/src/admin/ui/styles/scrollbar.scss +0 -36
  133. package/src/admin/ui/styles/select.scss +0 -121
  134. package/src/admin/ui/styles/separator.scss +0 -14
  135. package/src/admin/ui/styles/sheet.scss +0 -152
  136. package/src/admin/ui/styles/sidebar.scss +0 -148
  137. package/src/admin/ui/styles/switch.scss +0 -59
  138. package/src/admin/ui/styles/table.scss +0 -207
  139. package/src/admin/ui/styles/tabs.scss +0 -62
  140. package/src/admin/ui/styles/toast.scss +0 -45
  141. package/src/admin/ui/styles/variables.scss +0 -24
  142. package/src/admin/ui/views/collection-list-view.tsx +0 -720
  143. package/src/admin/ui/views/dashboard-view.tsx +0 -263
  144. package/src/admin/ui/views/document-edit-view.tsx +0 -384
  145. package/src/admin/ui/views/global-edit-view.tsx +0 -226
  146. package/src/admin/ui/views/init-view.tsx +0 -182
  147. package/src/admin/ui/views/login-view.tsx +0 -123
  148. package/src/admin/ui/views/media-registry-view.tsx +0 -1104
  149. package/src/admin/ui/views/settings-view.tsx +0 -729
  150. package/src/admin/webcomponent.tsx +0 -15
  151. package/src/api.ts +0 -9
  152. package/src/auth/index.ts +0 -194
  153. package/src/auth/migrations.ts +0 -87
  154. package/src/auth/premissions.ts +0 -46
  155. package/src/cli/commands/generate-types.ts +0 -116
  156. package/src/cli/commands/init.ts +0 -95
  157. package/src/cli/commands/migrate-commands.ts +0 -160
  158. package/src/cli/commands/seed-command.ts +0 -11
  159. package/src/cli/d1-mock.ts +0 -101
  160. package/src/cli/index.test.ts +0 -84
  161. package/src/cli/index.ts +0 -183
  162. package/src/cli/r2-mock.ts +0 -217
  163. package/src/cli/seeding.ts +0 -409
  164. package/src/client.ts +0 -181
  165. package/src/config-utils.ts +0 -102
  166. package/src/config.ts +0 -49
  167. package/src/db/adapter.ts +0 -53
  168. package/src/db/better-sqlite.ts +0 -632
  169. package/src/db/bun-sqlite.ts +0 -646
  170. package/src/db/d1.ts +0 -711
  171. package/src/db/index.ts +0 -6
  172. package/src/db/kysely/data-mapper.ts +0 -142
  173. package/src/db/kysely/field-mapper.ts +0 -148
  174. package/src/db/kysely/migration-generator.ts +0 -223
  175. package/src/db/kysely/query-builder.ts +0 -92
  176. package/src/db/kysely/schema-builder.ts +0 -439
  177. package/src/db/kysely/sql-utils.ts +0 -13
  178. package/src/db/postgres.ts +0 -621
  179. package/src/db/sqlite.ts +0 -660
  180. package/src/db/system-schema.ts +0 -121
  181. package/src/index.ts +0 -13
  182. package/src/runtimes/README.md +0 -59
  183. package/src/runtimes/bun.ts +0 -49
  184. package/src/runtimes/cloudflare-workers.ts +0 -38
  185. package/src/runtimes/next.ts +0 -26
  186. package/src/runtimes/node.ts +0 -52
  187. package/src/schema/collection.ts +0 -184
  188. package/src/schema/fields/base.ts +0 -164
  189. package/src/schema/fields/index.ts +0 -427
  190. package/src/schema/global.ts +0 -145
  191. package/src/schema/index.ts +0 -4
  192. package/src/schema/infer.ts +0 -72
  193. package/src/server/admin-router.ts +0 -20
  194. package/src/server/admin.ts +0 -142
  195. package/src/server/assets.ts +0 -306
  196. package/src/server/collection-router.ts +0 -55
  197. package/src/server/handlers.ts +0 -722
  198. package/src/server/middlewares/admin.ts +0 -27
  199. package/src/server/middlewares/auth.ts +0 -89
  200. package/src/server/middlewares/context.ts +0 -17
  201. package/src/server/middlewares/cors.ts +0 -24
  202. package/src/server/middlewares/database-init.ts +0 -74
  203. package/src/server/middlewares/rate-limit.ts +0 -77
  204. package/src/server/router.ts +0 -47
  205. package/src/server/setup-middlewares.ts +0 -58
  206. package/src/server/system-router.ts +0 -35
  207. package/src/server.ts +0 -9
  208. package/src/storage/adapters/cloudflare-r2.ts +0 -136
  209. package/src/storage/adapters/local.ts +0 -146
  210. package/src/storage/adapters/s3.ts +0 -186
  211. package/src/storage/errors.ts +0 -46
  212. package/src/storage/index.ts +0 -5
  213. package/src/storage/types.ts +0 -39
  214. package/src/types.ts +0 -577
  215. package/src/utils/lexical.ts +0 -37
  216. package/src/utils/logger.ts +0 -73
  217. package/src/validation.ts +0 -429
  218. package/src/validator.ts +0 -179
  219. package/test/admin-custom-field.test.ts +0 -162
  220. package/test/admin-react-field.test.tsx +0 -134
  221. package/test/api-features.test.ts +0 -78
  222. package/test/api.test.ts +0 -178
  223. package/test/auth.test.ts +0 -62
  224. package/test/cli-integration.test.ts +0 -148
  225. package/test/cli.test.ts +0 -25
  226. package/test/db/postgres.test.ts +0 -95
  227. package/test/db/sqlite-filter.test.ts +0 -53
  228. package/test/db/sqlite.test.ts +0 -82
  229. package/test/engine-features.test.ts +0 -79
  230. package/test/globals.test.ts +0 -74
  231. package/test/integration-tmp/db-app/opacacms.config.ts +0 -15
  232. package/test/integration-tmp/my-sqlite-app/opacacms.config.ts +0 -25
  233. package/test/integration-tmp/my-test-app/index.ts +0 -8
  234. package/test/integration-tmp/my-test-app/opacacms.config.ts +0 -16
  235. package/test/integration-tmp/my-test-app/package.json +0 -12
  236. package/test/populate.test.ts +0 -79
  237. package/test/runtimes.test.ts +0 -43
  238. package/test/schema-builder.test.ts +0 -107
  239. package/test/schema-features.test.ts +0 -63
  240. package/test/seeding.test.ts +0 -68
  241. package/test/storage/local.test.ts +0 -72
  242. package/test/storage/s3.test.ts +0 -60
  243. package/test/structural-data.test.ts +0 -100
  244. package/test/test-setup.ts +0 -11
  245. package/test/validation.test.ts +0 -162
  246. package/tsconfig.json +0 -42
package/dist/admin.css ADDED
@@ -0,0 +1 @@
1
+ :root{--opaca-bg: #09090b;--opaca-sidebar-bg: #0c0c0f;--opaca-card-bg: #111114;--opaca-surface: #16161a;--opaca-border: #1e1e24;--opaca-border-hover: #2a2a32;--opaca-text: #e4e4e7;--opaca-text-muted: #71717a;--opaca-text-dim: #52525b;--opaca-primary: #7c3aed;--opaca-primary-hover: #6d28d9;--opaca-primary-glow: rgba(124, 58, 237, 0.15);--opaca-accent: #a78bfa;--opaca-error: #f87171;--opaca-error-bg: rgba(248, 113, 113, 0.08);--opaca-success: #34d399;--opaca-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;--opaca-radius: 4px;--opaca-radius-lg: 6px;--opaca-transition: 200ms cubic-bezier(0.4, 0, 0.2, 1);--opaca-sidebar-width: 240px;--opaca-sidebar-collapsed-width: 68px}@keyframes opaca-fade-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes opaca-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes opaca-toast-in{from{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}@keyframes opaca-pulse{0%,100%{transform:scale(1);opacity:.2}50%{transform:scale(1.4);opacity:0}}.opaca-spin{animation:opaca-spin 1s linear infinite}.opaca-admin *,.opaca-admin *::before,.opaca-admin *::after{box-sizing:border-box;margin:0;padding:0}.opaca-admin{background-color:var(--opaca-bg);color:var(--opaca-text);font-family:var(--opaca-font);height:100vh;display:flex;font-size:14px;line-height:1.6;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}.opaca-admin ::-webkit-scrollbar{width:6px;height:6px}.opaca-admin ::-webkit-scrollbar-track{background:rgba(0,0,0,0)}.opaca-admin ::-webkit-scrollbar-thumb{background:var(--opaca-border);border-radius:10px}.opaca-admin ::-webkit-scrollbar-thumb:hover{background:var(--opaca-border-hover)}.opaca-scroll-area::-webkit-scrollbar{width:4px}.opaca-scroll-area::-webkit-scrollbar-thumb{background:var(--opaca-border);border-radius:10px}.opaca-scroll-area::-webkit-scrollbar-thumb:hover{background:var(--opaca-accent)}.opaca-sidebar{width:var(--opaca-sidebar-width);background-color:var(--opaca-sidebar-bg);border-right:1px solid var(--opaca-border);height:100%;display:flex;flex-direction:column;transition:width var(--opaca-transition),padding var(--opaca-transition);z-index:100;overflow:visible;backdrop-filter:blur(10px)}.opaca-sidebar.collapsed{width:var(--opaca-sidebar-collapsed-width)}.opaca-sidebar.collapsed .opaca-sidebar-inner{padding-left:.5rem;padding-right:.5rem}.opaca-sidebar.collapsed .opaca-nav-item{padding-left:0;padding-right:0;justify-content:center;gap:0}.opaca-sidebar.collapsed .opaca-nav-label{opacity:0;width:0}.opaca-sidebar.collapsed .opaca-sidebar-toggle{right:-12px}.opaca-sidebar-inner{display:flex;flex-direction:column;height:100%;overflow:hidden;padding:1.25rem .75rem}.opaca-logo{font-size:.875rem;font-weight:600;letter-spacing:-0.01em;padding:0 .75rem;margin-bottom:2rem;color:var(--opaca-accent);transition:all var(--opaca-transition);white-space:nowrap;display:flex;align-items:center;min-height:32px}.opaca-logo-mini{width:32px;height:32px;background-color:rgba(124,58,237,.1);border:1px solid rgba(124,58,237,.2);color:var(--opaca-accent);display:flex;align-items:center;justify-content:center;border-radius:var(--opaca-radius);font-size:.875rem;font-weight:700}.opaca-nav{flex:1;display:flex;flex-direction:column;min-height:0}.opaca-nav-item{display:flex;align-items:center;gap:.625rem;padding:.5rem .75rem;color:var(--opaca-text-muted);text-decoration:none;border-radius:var(--opaca-radius);transition:all var(--opaca-transition);margin-bottom:1px;font-size:.8125rem;font-weight:400;white-space:nowrap;overflow:hidden;border:1px solid rgba(0,0,0,0)}.opaca-nav-item:hover{background-color:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.05);color:var(--opaca-text)}.opaca-nav-item.active{background-color:var(--opaca-primary-glow);color:var(--opaca-accent);font-weight:600;box-shadow:inset 2px 0 0 0 var(--opaca-primary)}.opaca-nav-label{transition:opacity var(--opaca-transition)}.opaca-nav-footer{border-top:1px solid var(--opaca-border);padding-top:.75rem;margin-top:auto;padding-bottom:.5rem}.opaca-sidebar-toggle{position:absolute;top:25px;right:-12px;width:24px;height:24px;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:50%;color:var(--opaca-text-dim);display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:101;transition:all var(--opaca-transition);box-shadow:0 2px 4px rgba(0,0,0,.1)}.opaca-sidebar-toggle:hover{border-color:var(--opaca-accent);color:var(--opaca-accent);background-color:var(--opaca-surface)}.opaca-content{flex:1;padding:2.5rem;overflow-y:auto;height:100%;scroll-behavior:smooth}.opaca-content-inner{margin:0 auto;width:100%}.opaca-view-container{opacity:1;transform:translateY(0);transition:opacity var(--opaca-transition),transform var(--opaca-transition)}.opaca-view-container.loading{opacity:.5;pointer-events:none;filter:blur(1px)}.opaca-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:2rem}.opaca-title{font-size:1.375rem;font-weight:600;letter-spacing:-0.02em;color:var(--opaca-text)}.opaca-subtitle{color:var(--opaca-text-muted);font-size:.8125rem;margin-top:.25rem}.opaca-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(260px, 1fr));gap:1rem}.opaca-form-group{margin-bottom:1.5rem}.opaca-card{background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);padding:1.25rem;transition:border-color var(--opaca-transition)}.opaca-card:hover{border-color:var(--opaca-border-hover)}.opaca-table-container{background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);overflow:hidden;position:relative}.opaca-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(9,9,11,.6);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:10;animation:opaca-fade-in 200ms ease-out}.opaca-table{width:100%;border-collapse:collapse}.opaca-table th{text-align:left;padding:.625rem 1rem;background-color:var(--opaca-surface);color:var(--opaca-text-dim);font-weight:500;font-size:.6875rem;text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid var(--opaca-border)}.opaca-table td{padding:.625rem 1rem;border-bottom:1px solid var(--opaca-border);font-size:.8125rem;color:var(--opaca-text)}.opaca-table tr:last-child td{border-bottom:none}.opaca-table tr:hover td{background-color:hsla(0,0%,100%,.01)}.opaca-table-wrapper{position:relative;width:100%;overflow:auto;border-radius:var(--opaca-radius-lg);border:1px solid var(--opaca-border);background:var(--opaca-card-bg);box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.opaca-table-wrapper::-webkit-scrollbar{height:8px;width:8px}.opaca-table-wrapper::-webkit-scrollbar-track{background:rgba(0,0,0,0)}.opaca-table-wrapper::-webkit-scrollbar-thumb{background:var(--opaca-border);border-radius:10px}.opaca-table-wrapper::-webkit-scrollbar-thumb:hover{background:var(--opaca-text-dim)}.opaca-new-table{width:100%;caption-side:bottom;font-size:.875rem;border-collapse:collapse}.opaca-new-table .opaca-badge{padding:.2rem .5rem;font-size:.7rem;border-radius:4px;background:var(--opaca-surface);color:var(--opaca-text-muted);border:1px solid var(--opaca-border)}.opaca-new-table .opaca-btn-outline{background:rgba(0,0,0,0);border-color:var(--opaca-border);color:var(--opaca-text-muted)}.opaca-new-table .opaca-btn-outline:hover{border-color:var(--opaca-primary);color:var(--opaca-primary)}.opaca-table-header{background-color:hsla(0,0%,100%,.02);border-bottom:1px solid var(--opaca-border)}.opaca-table-head{position:sticky;top:0;z-index:10;background-color:var(--opaca-card-bg);height:3.5rem;padding:0 1rem;text-align:left;vertical-align:middle;font-weight:600;color:var(--opaca-text-muted);font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;min-width:120px;transition:color .2s ease;box-shadow:inset 0 -1px 0 var(--opaca-border)}.opaca-table-head:hover{color:var(--opaca-text)}.opaca-table-head>div{display:flex;align-items:center;white-space:nowrap;gap:.5rem}.opaca-table-row{border-bottom:1px solid var(--opaca-border);transition:background-color var(--opaca-transition)}.opaca-table-row:last-child{border-bottom:0}.opaca-table-row:hover{background-color:var(--opaca-surface)}.opaca-table-cell{padding:1rem;vertical-align:middle;color:var(--opaca-text);font-size:.875rem;border-bottom:1px solid var(--opaca-border);max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opaca-table-cell.opaca-cell-interactive{cursor:pointer;transition:all .2s ease;border-bottom:2px solid rgba(0,0,0,0)}.opaca-table-cell.opaca-cell-interactive:hover{background-color:hsla(0,0%,100%,.04);color:var(--opaca-primary);border-bottom-color:var(--opaca-primary)}.opaca-table-footer{background-color:hsla(0,0%,100%,.02);font-weight:500}.opaca-table-caption{margin-top:1rem;font-size:.875rem;color:var(--opaca-text-muted)}.opaca-item-button:hover{background-color:hsla(0,0%,100%,.05) !important;border-color:var(--opaca-primary) !important}.opaca-item-button.active{background-color:rgba(var(--opaca-primary-rgb), 0.1) !important;border-color:var(--opaca-primary) !important;color:var(--opaca-primary)}.opaca-ui-btn{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:var(--opaca-radius);font-size:.875rem;font-weight:500;transition:all var(--opaca-transition);cursor:pointer;border:1px solid rgba(0,0,0,0);outline:none}.opaca-ui-btn:focus-visible{box-shadow:0 0 0 2px var(--opaca-bg),0 0 0 4px var(--opaca-primary)}.opaca-ui-btn:disabled{pointer-events:none;opacity:.5}.opaca-ui-btn-size-default{height:2.25rem;padding:.5rem 1rem}.opaca-ui-btn-size-sm{height:2rem;padding:0 .75rem;font-size:.75rem}.opaca-ui-btn-size-lg{height:2.5rem;padding:0 2rem}.opaca-ui-btn-size-icon{height:2.25rem;width:2.25rem;padding:0}.opaca-ui-btn-default{background-color:var(--opaca-primary);color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.opaca-ui-btn-default:hover{background-color:var(--opaca-primary-hover)}.opaca-ui-btn-destructive{background-color:var(--opaca-error);color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.opaca-ui-btn-destructive:hover{background-color:#ef4444}.opaca-ui-btn-outline{border-color:var(--opaca-border);background-color:rgba(0,0,0,0);color:var(--opaca-text);box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.opaca-ui-btn-outline:hover{background-color:hsla(0,0%,100%,.05)}.opaca-ui-btn-secondary{background-color:var(--opaca-surface);color:var(--opaca-text);border-color:var(--opaca-border);box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.opaca-ui-btn-secondary:hover{background-color:hsla(0,0%,100%,.05)}.opaca-ui-btn-ghost{background-color:rgba(0,0,0,0);color:var(--opaca-text)}.opaca-ui-btn-ghost:hover{background-color:hsla(0,0%,100%,.05)}.opaca-ui-btn-link{background-color:rgba(0,0,0,0);color:var(--opaca-primary);text-decoration:underline;text-underline-offset:4px}.opaca-ui-btn-link:hover{text-decoration:none}.opaca-btn{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;padding:.5rem 1rem;border-radius:var(--opaca-radius);font-weight:500;font-size:.8125rem;cursor:pointer;transition:all var(--opaca-transition);border:none;font-family:inherit;line-height:1.4}.opaca-btn-primary{background-color:var(--opaca-primary);color:#fff}.opaca-btn-primary:hover{background-color:var(--opaca-primary-hover)}.opaca-btn-primary:disabled{opacity:.6;cursor:not-allowed}.opaca-btn-outline{background-color:rgba(0,0,0,0);border:1px solid var(--opaca-border);color:var(--opaca-text-muted)}.opaca-btn-outline:hover{border-color:var(--opaca-border-hover);color:var(--opaca-text);background-color:hsla(0,0%,100%,.02)}.opaca-item-button:hover{background-color:var(--opaca-brand-subtle) !important;border-color:var(--opaca-primary) !important;transform:translateY(-1px)}.opaca-item-button:active{transform:translateY(0)}.opaca-item-button.active{background-color:var(--opaca-brand-subtle) !important;border-color:var(--opaca-primary) !important;box-shadow:0 0 0 1px var(--opaca-primary)}.opaca-ui-input{display:flex;height:2.25rem;width:100%;border-radius:var(--opaca-radius);border:1px solid var(--opaca-border);background-color:var(--opaca-surface);padding:.25rem .75rem;font-size:.875rem;color:var(--opaca-text);box-shadow:0 1px 2px 0 rgba(0,0,0,.05);transition:border-color var(--opaca-transition),box-shadow var(--opaca-transition);outline:none}.opaca-ui-input::placeholder{color:var(--opaca-text-dim)}.opaca-ui-input:focus-visible{border-color:var(--opaca-primary);box-shadow:0 0 0 1px var(--opaca-primary)}.opaca-ui-input:disabled{cursor:not-allowed;opacity:.5}.opaca-ui-input[type=file]{border:0;background-color:rgba(0,0,0,0);font-size:.875rem;font-weight:500}.opaca-label{display:block;font-size:.75rem;font-weight:500;margin-bottom:.375rem;color:var(--opaca-text-muted);text-transform:uppercase;letter-spacing:.03em}.opaca-input{width:100%;padding:.5rem .75rem;border-radius:var(--opaca-radius);background-color:var(--opaca-surface);border:1px solid var(--opaca-border);color:var(--opaca-text);font-family:inherit;font-size:.8125rem;transition:border-color var(--opaca-transition),box-shadow var(--opaca-transition);outline:none}.opaca-input::placeholder{color:var(--opaca-text-dim)}.opaca-input:focus{border-color:var(--opaca-primary);box-shadow:0 0 0 1px var(--opaca-primary-glow)}.opaca-input.error{border-color:var(--opaca-error)}.opaca-input.error:focus{box-shadow:0 0 0 1px var(--opaca-error-bg)}.opaca-field-error{display:block;font-size:.75rem;color:var(--opaca-error);margin-top:.25rem}.opaca-badge{display:inline-flex;align-items:center;padding:.125rem .5rem;font-size:.6875rem;font-weight:500;border-radius:var(--opaca-radius);background-color:var(--opaca-primary-glow);color:var(--opaca-accent);letter-spacing:.02em}.opaca-toast-container{position:fixed;top:1.5rem;right:1.5rem;z-index:9999;display:flex;flex-direction:column;gap:.75rem;pointer-events:none}.opaca-toast{pointer-events:auto;min-width:280px;max-width:400px;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);padding:.875rem 1rem;border-radius:var(--opaca-radius-lg);display:flex;align-items:center;gap:.75rem;box-shadow:0 10px 25px -5px rgba(0,0,0,.4);animation:opaca-toast-in 300ms cubic-bezier(0.16, 1, 0.3, 1);transition:all var(--opaca-transition)}.opaca-toast.exit{opacity:0;transform:translateX(20px)}.opaca-toast-success{border-left:3px solid var(--opaca-success)}.opaca-toast-error{border-left:3px solid var(--opaca-error)}.opaca-toast-info{border-left:3px solid var(--opaca-accent)}.opaca-toast-message{font-size:.8125rem;font-weight:500;color:var(--opaca-text);line-height:1.4}.opaca-switch{position:relative;display:inline-flex;align-items:center;cursor:pointer;user-select:none;gap:.75rem}.opaca-switch input{position:absolute;opacity:0;width:0;height:0}.opaca-switch input:checked+.opaca-switch-track{background-color:var(--opaca-accent);border-color:var(--opaca-accent)}.opaca-switch input:checked+.opaca-switch-track .opaca-switch-thumb{left:18px}.opaca-switch input:disabled+.opaca-switch-track{background:var(--opaca-border);cursor:not-allowed;opacity:.6}.opaca-switch-track{width:36px;height:20px;background-color:var(--opaca-surface);border:1px solid var(--opaca-border);border-radius:20px;position:relative;transition:all var(--opaca-transition)}.opaca-switch-thumb{width:14px;height:14px;background-color:#fff;border-radius:50%;position:absolute;top:2px;left:2px;transition:all var(--opaca-transition);box-shadow:0 2px 4px rgba(0,0,0,.2)}.opaca-switch-label{font-size:.8125rem;font-weight:500}.opaca-pagination{display:flex;align-items:center;justify-content:space-between;padding:1rem;border-top:1px solid var(--opaca-border);background-color:var(--opaca-sidebar-bg)}.opaca-pagination-info{font-size:.75rem;color:var(--opaca-text-dim)}.opaca-pagination-actions{display:flex;gap:.5rem}.opaca-empty{padding:5rem 2rem;text-align:center;display:flex;flex-direction:column;align-items:center;gap:1rem}.opaca-empty-icon{width:48px;height:48px;border-radius:50%;background-color:var(--opaca-surface);display:flex;align-items:center;justify-content:center;color:var(--opaca-text-dim);margin-bottom:.5rem}.opaca-loading-screen{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;width:100%;background-color:var(--opaca-bg);color:var(--opaca-text);gap:2rem}.opaca-loading-logo-container{position:relative;display:flex;align-items:center;justify-content:center}.opaca-loading-logo-pulse{position:absolute;width:64px;height:64px;background-color:var(--opaca-primary);border-radius:var(--opaca-radius);opacity:.2;animation:opaca-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite}.opaca-loading-status{display:flex;align-items:center;gap:.75rem;font-size:.875rem;color:var(--opaca-text-muted);animation:opaca-fade-in 1s ease-out}.opaca-login-container{display:flex;align-items:center;justify-content:center;min-height:100vh;width:100%;background-color:var(--opaca-bg);font-family:var(--opaca-font);color:var(--opaca-text);-webkit-font-smoothing:antialiased}.opaca-login-card{width:100%;max-width:380px;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);padding:2rem}.opaca-login-header{text-align:center;margin-bottom:1.5rem}.opaca-login-logo{width:48px;height:48px;display:flex;align-items:center;justify-content:center;background-color:var(--opaca-primary);border-radius:var(--opaca-radius);margin:0 auto 1rem}.opaca-logo-circle{width:48px;height:48px;display:flex;align-items:center;justify-content:center;background-color:var(--opaca-primary);border-radius:var(--opaca-radius);color:#fff}.opaca-login-error{padding:.625rem .75rem;background-color:var(--opaca-error-bg);border:1px solid rgba(248,113,113,.2);color:var(--opaca-error);border-radius:var(--opaca-radius);margin-bottom:1.25rem;display:flex;align-items:center;gap:.5rem;font-size:.8125rem}.opaca-lexical-wrapper{display:flex;flex-direction:column;gap:.75rem}.opaca-lexical-modes{display:inline-flex;gap:2px;background-color:var(--opaca-surface);padding:3px;border-radius:var(--opaca-radius-lg);border:1px solid var(--opaca-border);align-self:flex-start;margin-bottom:.25rem}.opaca-lexical-modes .opaca-btn{padding:.4rem .8rem;font-size:.75rem;border-radius:var(--opaca-radius);border:none;background-color:rgba(0,0,0,0);color:var(--opaca-text-muted);font-weight:500;min-width:80px;transition:all var(--opaca-transition)}.opaca-lexical-modes .opaca-btn:hover{color:var(--opaca-text);background-color:hsla(0,0%,100%,.05)}.opaca-lexical-modes .opaca-btn.opaca-btn-primary{background-color:var(--opaca-primary);color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.2)}.opaca-lexical-container{border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);background-color:var(--opaca-surface);overflow:hidden;transition:all var(--opaca-transition);display:flex;flex-direction:column}.opaca-lexical-container:focus-within{border-color:var(--opaca-accent);box-shadow:0 0 0 2px var(--opaca-primary-glow)}.opaca-lexical-container.mode-notion .opaca-lexical-content{padding:1.5rem 1rem}.opaca-lexical-container.is-readonly{background-color:hsla(0,0%,100%,.02);cursor:not-allowed}.opaca-lexical-container.is-readonly .opaca-lexical-content{padding:0rem}.opaca-lexical-toolbar{display:flex;flex-wrap:wrap;gap:.125rem;padding:.375rem;border-bottom:1px solid var(--opaca-border);background-color:var(--opaca-card-bg);align-items:center}.opaca-lexical-bubble-menu{background:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);padding:4px;display:flex;gap:4px;box-shadow:0 10px 15px -3px rgba(0,0,0,.4);backdrop-filter:blur(8px)}.opaca-lexical-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--opaca-radius);background:rgba(0,0,0,0);border:none;color:var(--opaca-text-muted);cursor:pointer;transition:all var(--opaca-transition)}.opaca-lexical-btn:hover{background-color:hsla(0,0%,100%,.08);color:var(--opaca-text)}.opaca-lexical-btn.is-active{background-color:var(--opaca-primary-glow);color:var(--opaca-accent)}.opaca-lexical-divider{width:1px;height:18px;background-color:var(--opaca-border);margin:0 .25rem}.opaca-lexical-placeholder{color:var(--opaca-text-dim);position:absolute;top:1rem;left:1rem;pointer-events:none;font-style:normal;font-size:.875rem;opacity:.5}.opaca-lexical-editor-inner{position:relative;flex:1}.opaca-lexical-content{min-height:160px;padding:1rem;outline:none;line-height:1.6;color:var(--opaca-text);font-size:.9375rem}.opaca-lexical-content>*:first-child{margin-top:0}.opaca-lexical-content>*:last-child{margin-bottom:0}.opaca-lexical-content p{margin:.75em 0}.opaca-lexical-content .editor-heading-h1{font-size:2.25rem;font-weight:700;margin-top:1.5rem;margin-bottom:.75rem;color:var(--opaca-text)}.opaca-lexical-content .editor-heading-h2{font-size:1.875rem;font-weight:600;margin-top:1.25rem;margin-bottom:.5rem;color:var(--opaca-text)}.opaca-lexical-content .editor-text-bold{font-weight:700}.opaca-lexical-content .editor-text-italic{font-style:italic}.opaca-lexical-content .editor-text-underline{text-decoration:underline}.opaca-lexical-content .editor-text-strikethrough{text-decoration:line-through}.opaca-lexical-content .editor-text-code{background-color:hsla(0,0%,100%,.05);padding:2px 4px;border-radius:4px;font-family:monospace;font-size:.9em}.opaca-lexical-content ul{list-style-type:disc;padding-left:1.5rem;margin:.5rem 0}.opaca-lexical-content ol{list-style-type:decimal;padding-left:1.5rem;margin:.5rem 0}.opaca-lexical-content .editor-listitem{margin:.25rem 0}.opaca-lexical-content ul[data-type=taskList]{list-style:none;padding:0}.opaca-lexical-content ul[data-type=taskList] p{margin:0}.opaca-lexical-content ul[data-type=taskList] li{display:flex;margin-bottom:.25rem}.opaca-lexical-content ul[data-type=taskList] li>label{flex:0 0 auto;margin-right:.5rem;user-select:none}.opaca-lexical-content ul[data-type=taskList] li>div{flex:1 1 auto}.opaca-lexical-content ul[data-type=taskList] li input[type=checkbox]{cursor:pointer;width:1rem;height:1rem;margin-top:.2rem;accent-color:var(--opaca-primary)}.opaca-lexical-content ul[data-type=taskList] li[data-checked=true]>div>p{text-decoration:line-through;color:var(--opaca-text-muted)}.opaca-lexical-content blockquote{border-left:3px solid var(--opaca-border);padding-left:1rem;margin:1em 0;color:var(--opaca-text-dim);font-style:italic}.opaca-lexical-content .editor-image-wrapper{position:relative;display:inline-block;cursor:default;user-select:none;line-height:0}.opaca-lexical-content .editor-image-wrapper.is-selected{outline:3px solid var(--opaca-primary);outline-offset:2px;border-radius:4px;box-shadow:0 0 0 4px var(--opaca-primary-glow)}.opaca-lexical-content .editor-image-wrapper .editor-image-img{max-width:100%;height:auto;border-radius:var(--opaca-radius)}.opaca-lexical-content .editor-image-wrapper .editor-image-resizer{position:absolute;right:-6px;bottom:-6px;width:14px;height:14px;background-color:var(--opaca-primary);border:2px solid #fff;cursor:nwse-resize;z-index:20;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.3)}.opaca-lexical-content .editor-image-wrapper .editor-image-resizer:hover{background-color:var(--opaca-accent);transform:scale(1.2)}.opaca-lexical-content .editor-image-wrapper .editor-image-delete{position:absolute;top:-8px;right:-8px;width:24px;height:24px;background-color:var(--opaca-error);color:#fff;border:1px solid #fff;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;box-shadow:0 2px 4px rgba(0,0,0,.3);padding:0;transition:transform .2s}.opaca-lexical-content .editor-image-wrapper .editor-image-delete:hover{transform:scale(1.1);background-color:#ff4d4d}.opaca-lexical-content a{color:var(--opaca-primary);text-decoration:underline;text-underline-offset:2px}.opaca-lexical-content pre{background-color:var(--opaca-bg);color:var(--opaca-text);padding:1rem;border-radius:var(--opaca-radius);overflow-x:auto;border:1px solid var(--opaca-border);margin:1em 0}.opaca-lexical-content pre code{color:inherit;padding:0;background:none;font-size:.85rem}.opaca-lexical-content [contenteditable=true] p.is-editor-empty:first-child::before,.opaca-lexical-content [contenteditable=true] h1.is-empty::before,.opaca-lexical-content [contenteditable=true] h2.is-empty::before,.opaca-lexical-content [contenteditable=true] h3.is-empty::before,.opaca-lexical-content [contenteditable=true] [data-placeholder]::before{content:attr(data-placeholder);float:left;color:var(--opaca-text-muted);pointer-events:none;height:0;font-style:italic;opacity:.6}.opaca-lexical-bubble-menu{display:flex;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);padding:.25rem;gap:.125rem}.opaca-lexical-floating-menu{display:flex;align-items:center;margin-left:-32px}.opaca-lexical-btn-plus{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:var(--opaca-surface);border:1px solid var(--opaca-border);color:var(--opaca-text-muted);cursor:pointer;transition:all var(--opaca-transition);font-size:1rem;margin-right:.5rem}.opaca-lexical-btn-plus:hover{background-color:var(--opaca-primary-glow);color:var(--opaca-primary);border-color:var(--opaca-primary)}.opaca-lexical-floating-menu-items{display:none;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);padding:.25rem;gap:.125rem;animation:opaca-fade-in 100ms ease-out}.opaca-lexical-floating-menu:hover .opaca-lexical-floating-menu-items{display:flex}.opaca-slash-menu{display:flex;flex-direction:column;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);padding:.5rem;max-height:300px;overflow-y:auto;min-width:250px}.opaca-slash-menu-item{display:flex;align-items:center;gap:.75rem;padding:.3rem;border:none;background:rgba(0,0,0,0);color:var(--opaca-text);border-radius:var(--opaca-radius);cursor:pointer;text-align:left;transition:background-color var(--opaca-transition)}.opaca-slash-menu-item:hover,.opaca-slash-menu-item.is-selected{background-color:var(--opaca-surface)}.opaca-slash-menu-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;background-color:var(--opaca-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);color:var(--opaca-text-muted)}.opaca-slash-menu-text{display:flex;flex-direction:column}.opaca-slash-menu-title{font-size:.8125rem;font-weight:500;color:var(--opaca-text)}.opaca-slash-menu-desc{font-size:.7rem;color:var(--opaca-text-muted)}.opaca-slash-menu-empty{padding:1rem;color:var(--opaca-text-muted);font-size:.8125rem;text-align:center}.opaca-sidebar-accordion{margin-bottom:.25rem;border:none !important;background:rgba(0,0,0,0) !important}.opaca-sidebar-accordion .opaca-sidebar-accordion-trigger{background:rgba(0,0,0,0);padding:1rem .75rem .5rem .75rem;font-size:.625rem;color:var(--opaca-text-dim);text-transform:uppercase;letter-spacing:.06em;font-weight:500;width:100%;display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:color var(--opaca-transition);border:none;outline:none}.opaca-sidebar-accordion .opaca-sidebar-accordion-trigger:hover{color:var(--opaca-text)}.opaca-sidebar-accordion .opaca-sidebar-accordion-trigger .opaca-sidebar-accordion-icon{width:12px;height:12px;stroke:var(--opaca-text-dim);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s cubic-bezier(0.87, 0, 0.13, 1)}.opaca-sidebar-accordion .opaca-sidebar-accordion-trigger[aria-expanded=true] .opaca-sidebar-accordion-icon{transform:rotate(180deg)}.opaca-sidebar-accordion .opaca-sidebar-accordion-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s cubic-bezier(0.87, 0, 0.13, 1)}.opaca-sidebar-accordion .opaca-sidebar-accordion-content[data-state=open]{grid-template-rows:1fr}.opaca-sidebar-accordion .opaca-sidebar-accordion-content .opaca-sidebar-accordion-content-inner{overflow:hidden;display:flex;flex-direction:column}.asset-manager-overlay{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;background-color:rgba(0,0,0,.5);padding:1rem}.asset-manager-container{background-color:var(--opaca-card-bg);border-radius:var(--opaca-radius);box-shadow:0 25px 50px -12px rgba(0,0,0,.5);width:100%;border:1px solid var(--opaca-border);max-width:56rem;height:600px;display:flex;flex-direction:column;color:var(--opaca-text);overflow:hidden}.asset-manager-header{padding:1.25rem 1.75rem;border-bottom:1px solid var(--opaca-border);display:flex;justify-content:space-between;align-items:center;background-color:var(--opaca-card-bg)}.asset-manager-header h2{font-size:1.125rem;font-weight:600;margin:0}.asset-manager-header .asset-manager-breadcrumbs{display:flex;align-items:center;gap:.5rem;margin-top:.25rem;font-size:.8125rem;color:var(--opaca-text-dim)}.asset-manager-header .asset-manager-breadcrumbs button{background:none;border:none;padding:0;color:inherit;cursor:pointer}.asset-manager-header .asset-manager-breadcrumbs button:hover{color:var(--opaca-accent);text-decoration:underline}.asset-manager-header .asset-manager-breadcrumbs .breadcrumb-separator{opacity:.5}.asset-manager-header .header-actions{display:flex;align-items:center;gap:1rem}.asset-manager-header .header-actions .bucket-selector{min-width:140px;height:36px}.asset-manager-header .close-button{color:var(--opaca-text-dim);background:rgba(0,0,0,0);border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all var(--opaca-transition);padding:.25rem;border-radius:6px}.asset-manager-header .close-button:hover{background-color:var(--opaca-surface);color:var(--opaca-text)}.asset-manager-upload-zone{padding:2rem;border-bottom:2px dashed var(--opaca-border);background-color:rgba(0,0,0,.2);cursor:pointer;text-align:center;position:relative;transition:all .2s;display:flex;flex-direction:column;align-items:center;justify-content:center}.asset-manager-upload-zone.uploading{pointer-events:none;opacity:.7}.asset-manager-upload-zone .upload-icon{margin-bottom:.75rem;color:var(--opaca-text-dim)}.asset-manager-upload-zone .upload-prompt{color:var(--opaca-text-dim);margin:0;font-size:.875rem}.asset-manager-upload-zone .upload-prompt span{color:var(--opaca-accent);font-weight:600}.asset-manager-upload-zone .uploading-status{display:flex;flex-direction:column;align-items:center;gap:.75rem}.asset-manager-upload-zone .uploading-status .status-text{color:var(--opaca-accent);font-weight:600;font-size:.875rem}.asset-manager-grid-container{flex:1;overflow-y:auto;padding:1.5rem;background-color:rgba(0,0,0,.1)}.asset-manager-grid-container .loading-assets,.asset-manager-grid-container .no-assets{display:flex;justify-content:center;align-items:center;height:100%;color:#9ca3af}.asset-manager-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(140px, 1fr));gap:1.25rem}.asset-manager-card{position:relative;background-color:var(--opaca-surface);border-radius:12px;border:1px solid var(--opaca-border);overflow:hidden;cursor:pointer;transition:all var(--opaca-transition);display:flex;flex-direction:column}.asset-manager-card:hover{border-color:var(--opaca-accent);transform:translateY(-2px);box-shadow:var(--opaca-shadow-lg)}.asset-manager-card:hover .selection-overlay{opacity:1}.asset-manager-card .asset-thumb{aspect-ratio:16/10;display:flex;align-items:center;justify-content:center;background-color:var(--opaca-bg-alt);overflow:hidden;position:relative}.asset-manager-card .asset-thumb img{width:100%;height:100%;object-fit:cover}.asset-manager-card .asset-thumb .folder-icon{color:#eab308}.asset-manager-card .asset-info{padding:.75rem;display:flex;flex-direction:column;gap:.25rem;background-color:var(--opaca-card-bg);flex:1}.asset-manager-card .asset-info .filename{font-size:.8125rem;font-weight:500;color:var(--opaca-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.asset-manager-card .asset-info .file-meta{font-size:.6875rem;color:var(--opaca-text-dim)}.asset-manager-card .selection-overlay{position:absolute;inset:0;background-color:rgba(var(--opaca-accent-rgb), 0.1);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity var(--opaca-transition);pointer-events:none}.asset-manager-card .selection-overlay .select-badge{background-color:var(--opaca-accent);color:#fff;font-size:.75rem;font-weight:600;padding:.375rem .75rem;border-radius:9999px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1)}.asset-manager-card.folder-card .asset-thumb{background-color:rgba(234,179,8,.05)}.file-field-container{margin-bottom:2rem;background-color:rgba(0,0,0,0);padding:0;border:none;box-shadow:none}.file-field-label-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem}.file-field-label-row label{display:block;font-size:.875rem;font-weight:500;color:var(--opaca-text);text-transform:capitalize}.file-field-label-row .upload-error{font-size:.75rem;color:#ef4444;font-weight:500}.file-field-optimistic-card{display:flex;flex-direction:column;gap:.5rem;padding:1rem;border:1px solid var(--opaca-primary);border-radius:var(--opaca-radius);background-color:rgba(var(--opaca-primary-rgb), 0.1)}.file-field-optimistic-card .optimistic-info{display:flex;align-items:center;gap:1rem;opacity:.7}.file-field-optimistic-card .optimistic-info img{width:4rem;height:4rem;object-fit:cover;border-radius:.25rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.file-field-optimistic-card .optimistic-info .file-icon-placeholder{width:4rem;height:4rem;background-color:#e5e7eb;border-radius:.25rem;display:flex;align-items:center;justify-content:center}.file-field-optimistic-card .optimistic-info .file-icon-placeholder span{font-size:.75rem;font-family:monospace}.file-field-optimistic-card .optimistic-info .optimistic-details{display:flex;flex-direction:column;flex:1;min-width:0}.file-field-optimistic-card .optimistic-info .optimistic-details .filename{font-size:.875rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-field-optimistic-card .optimistic-info .optimistic-details .progress-text{font-size:.75rem;color:#2563eb;margin-bottom:.25rem;font-weight:600}.file-field-optimistic-card .optimistic-info .optimistic-details .progress-bar-bg{width:100%;background-color:#bfdbfe;border-radius:9999px;height:.375rem}.file-field-optimistic-card .optimistic-info .optimistic-details .progress-bar-bg .progress-bar-fill{background-color:#2563eb;height:100%;border-radius:9999px;transition:width .3s}.file-field-asset-card{display:flex;flex-direction:column;gap:1rem}.file-field-asset-info{display:flex;align-items:center;padding:1rem;border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);background-color:var(--opaca-card-bg);justify-content:space-between}.file-field-asset-info .asset-preview{display:flex;align-items:center;gap:1rem}.file-field-asset-info .asset-preview img{width:4rem;height:4rem;object-fit:cover;border-radius:.25rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);border:1px solid #e5e7eb}.file-field-asset-info .asset-preview .file-icon-placeholder{width:4rem;height:4rem;background-color:var(--opaca-border);border-radius:.25rem;display:flex;align-items:center;justify-content:center;border:1px solid var(--opaca-border)}.file-field-asset-info .asset-preview .file-icon-placeholder span{font-size:.75rem;font-family:monospace;color:var(--opaca-subtitle)}.file-field-asset-info .asset-preview .asset-details{display:flex;flex-direction:column}.file-field-asset-info .asset-preview .asset-details .filename{font-size:.875rem;font-weight:500;color:var(--opaca-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}.file-field-asset-info .asset-preview .asset-details .filesize{font-size:.75rem;color:var(--opaca-subtitle);font-family:monospace;margin-top:.125rem}.file-field-asset-info .asset-actions{display:flex;gap:.75rem}.file-field-asset-info .asset-actions button{font-size:.875rem;font-weight:500;background:rgba(0,0,0,0);border:none;cursor:pointer;transition:color .2s}.file-field-asset-info .asset-actions button.replace-button{color:var(--opaca-primary)}.file-field-asset-info .asset-actions button.replace-button:hover{opacity:.8}.file-field-asset-info .asset-actions button.remove-button{color:var(--opaca-error)}.file-field-asset-info .asset-actions button.remove-button:hover{opacity:.8}.file-field-metadata{padding-left:1rem;border-left:2px solid #bfdbfe;display:flex;flex-direction:column;gap:.75rem;padding-top:.5rem}.file-field-metadata h4{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:#6b7280;font-weight:600;margin-bottom:.5rem}.file-field-metadata .metadata-field label{display:block;font-size:.75rem;font-weight:500;color:var(--opaca-subtitle);margin-bottom:.25rem;text-transform:capitalize}.file-field-metadata .metadata-field label .required{color:#ef4444}.file-field-metadata .metadata-field input,.file-field-metadata .metadata-field textarea{width:100%;font-size:.875rem;border:1px solid #d1d5db;border-radius:.375rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);padding:.5rem .75rem;outline:none;transition:all .2s}.file-field-metadata .metadata-field input:focus,.file-field-metadata .metadata-field textarea:focus{border-color:#3b82f6;outline:1px solid #3b82f6}.file-field-empty-button{width:100%;padding:3.5rem 0;border:2px dashed var(--opaca-border);border-radius:var(--opaca-radius);color:var(--opaca-text-dim);background-color:var(--opaca-surface);cursor:pointer;transition:all var(--opaca-transition);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem}.file-field-empty-button:hover{border-color:var(--opaca-primary);color:var(--opaca-accent);background-color:rgba(124,58,237,.05)}.file-field-empty-button svg{width:2rem;height:2rem;color:#9ca3af}.file-field-empty-button span{font-weight:500;font-size:.875rem}.opaca-ui-collapsible{display:flex;flex-direction:column;border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);background-color:rgba(0,0,0,0);overflow:hidden;margin-bottom:2rem;transition:border-color var(--opaca-transition)}.opaca-ui-collapsible-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:1rem 1.25rem;font-size:.875rem;font-weight:500;text-align:left;background-color:var(--opaca-surface);color:var(--opaca-text);border:none;border-bottom:1px solid rgba(0,0,0,0);cursor:pointer;transition:all var(--opaca-transition)}.opaca-ui-collapsible-trigger:hover{background-color:var(--opaca-border)}.opaca-ui-collapsible-trigger[aria-expanded=true]{border-bottom-color:var(--opaca-border)}.opaca-ui-collapsible-trigger[aria-expanded=true] .opaca-ui-collapsible-icon{transform:rotate(180deg)}.opaca-ui-collapsible-icon{width:.875rem;height:.875rem;transition:transform var(--opaca-transition);fill:none;stroke:var(--opaca-text-muted);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.opaca-ui-collapsible-content{padding:1.25rem;background-color:rgba(0,0,0,0);color:var(--opaca-text)}.opaca-ui-collapsible-content[data-state=closed]{display:none}.opaca-ui-collapsible-content[data-state=open]{animation:collapsible-slide-down 200ms ease-out}@keyframes collapsible-slide-down{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.opaca-ui-dialog-portal{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center}.opaca-ui-dialog-overlay{position:fixed;inset:0;background-color:rgba(0,0,0,.8);backdrop-filter:blur(4px);transition:opacity .2s;border:none;padding:0;margin:0;cursor:default;width:100%;height:100%}.opaca-ui-dialog-wrapper{position:relative;z-index:10000;width:100%;height:100%;padding:1rem;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.opaca-ui-dialog-content{pointer-events:auto;position:relative;width:100%;max-height:calc(100vh - 2rem);overflow-y:auto;border-radius:var(--opaca-radius-lg);border:1px solid var(--opaca-border);background-color:var(--opaca-card-bg);padding:1.5rem;box-shadow:0 20px 25px -5px rgba(0,0,0,.3),0 8px 10px -6px rgba(0,0,0,.2);color:var(--opaca-text);animation:opacaDialogIn .2s cubic-bezier(0.16, 1, 0.3, 1)}.opaca-ui-dialog-content.opaca-dialog-max-w{max-width:425px}@keyframes opacaDialogIn{from{opacity:0;transform:scale(0.95)}to{opacity:1;transform:scale(1)}}.opaca-ui-dialog-header{display:flex;flex-direction:column;gap:.375rem;text-align:center}@media(min-width: 640px){.opaca-ui-dialog-header{text-align:left}}.opaca-ui-dialog-title{font-size:1.125rem;font-weight:600;line-height:1;letter-spacing:-0.025em;color:var(--opaca-text)}.opaca-ui-dialog-description{font-size:.875rem;color:var(--opaca-text-muted)}.opaca-ui-dialog-footer{display:flex;flex-direction:column-reverse;margin-top:1rem;gap:.5rem}@media(min-width: 640px){.opaca-ui-dialog-footer{flex-direction:row;justify-content:flex-end;gap:.5rem}}.opaca-ui-group{display:flex;flex-direction:column;gap:1.25rem;padding:1.5rem;border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);background-color:rgba(0,0,0,0);margin-bottom:2rem}.opaca-ui-group-header{font-size:.75rem;font-weight:500;margin-bottom:.5rem;color:var(--opaca-text-muted);text-transform:uppercase;letter-spacing:.03em}.media-registry-view{display:flex;flex-direction:column;height:100%}.media-registry-header{margin-bottom:2rem;flex-shrink:0}.media-registry-header .opaca-title{font-size:1.5rem;font-weight:600;letter-spacing:-0.025em}.media-registry-header .opaca-subtitle{font-size:.875rem;color:var(--opaca-text-muted);margin-top:.25rem}.media-registry-header-actions{display:flex;gap:.75rem}.media-registry-icon-mr{margin-right:.5rem}.media-registry-body{flex:1;display:flex;flex-direction:column;padding:0;overflow:visible;border:none;background:rgba(0,0,0,0)}.media-registry-toolbar{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg, 0.5rem);margin-bottom:1.5rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.media-registry-filters{display:flex;gap:.75rem;align-items:center;width:100%;max-width:600px}.media-registry-search{position:relative;flex:1;min-width:320px}.media-registry-search .search-icon{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--opaca-text-dim)}.media-registry-search .opaca-ui-input{padding-left:2.5rem}.media-registry-select-trigger{width:140px;flex-shrink:0}.media-registry-view-toggles{display:flex;gap:.25rem;background:var(--opaca-surface);padding:.25rem;border-radius:var(--opaca-radius-lg, 0.5rem);border:1px solid var(--opaca-border)}.media-registry-toggle-btn{padding:.4rem;border-radius:var(--opaca-radius, 0.375rem);border:none;cursor:pointer;transition:all .2s;background:rgba(0,0,0,0);color:var(--opaca-text-dim);display:flex;align-items:center;justify-content:center}.media-registry-toggle-btn:hover{color:#fff}.media-registry-toggle-btn.active{background-color:var(--opaca-primary);color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.media-registry-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(220px, 1fr));gap:1.5rem;margin-top:.5rem}.media-registry-card{position:relative;background:var(--opaca-card-bg);border-radius:.75rem;border:1px solid var(--opaca-border);overflow:hidden;cursor:pointer;transition:all .2s;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.media-registry-card:hover{border-color:var(--opaca-border-hover)}.media-registry-card.active{border-color:var(--opaca-primary);box-shadow:0 0 0 1px var(--opaca-primary)}.media-registry-card-thumb{height:160px;background:var(--opaca-surface);display:flex;align-items:center;justify-content:center;border-bottom:1px solid var(--opaca-border);position:relative;overflow:hidden}.media-registry-card-thumb img{width:100%;height:100%;object-fit:cover;transition:transform .5s}.media-registry-card-thumb svg.folder-icon{color:#eab308;transition:transform .3s}.media-registry-card-thumb .media-registry-overlay{position:absolute;inset:0;background:rgba(0,0,0,.4);opacity:0;transition:opacity .2s;display:flex;align-items:center;justify-content:center}.media-registry-card:hover .media-registry-card-thumb img,.media-registry-card:hover .media-registry-card-thumb svg.folder-icon{transform:scale(1.05)}.media-registry-card:hover .media-registry-overlay{opacity:1}.media-registry-overlay-btn{border-radius:9999px;background-color:hsla(0,0%,100%,.1);backdrop-filter:blur(12px);color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;transition:all .2s}.media-registry-overlay-btn:hover{background-color:#fff;color:#000}.media-registry-card-body{padding:1rem}.media-registry-card-title{font-size:.875rem;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--opaca-text)}.media-registry-card-meta{font-size:.75rem;color:var(--opaca-text-dim);display:flex;justify-content:space-between;margin-top:.375rem}.media-registry-card-meta .meta-type{text-transform:uppercase;letter-spacing:.05em;font-size:.65rem;font-weight:600}.media-registry-pagination{display:flex;align-items:center;justify-content:space-between;padding:1rem;background:var(--opaca-surface);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg, 0.5rem);margin-top:2rem}.media-registry-pagination .info{font-size:.875rem;color:var(--opaca-text-muted)}.media-registry-pagination .actions{display:flex;gap:.5rem}.media-sheet-flex{flex:1;display:flex;flex-direction:column}.media-sheet-body{flex:1;overflow-y:auto;padding-right:.5rem;margin-right:-0.5rem}.media-sheet-preview{height:12rem;border-radius:var(--opaca-radius-lg, 0.5rem);background:var(--opaca-surface);border:1px solid var(--opaca-border);display:flex;align-items:center;justify-content:center;overflow:hidden;margin-bottom:1rem;position:relative}.media-sheet-preview img{width:100%;height:100%;object-fit:contain}.media-sheet-preview .overlay{position:absolute;inset:0;background:rgba(0,0,0,.4);opacity:0;transition:opacity .2s;display:flex;align-items:center;justify-content:center}.media-sheet-preview:hover .overlay{opacity:1}.media-sheet-form{display:flex;flex-direction:column;gap:1rem}.media-sheet-group{display:flex;flex-direction:column;gap:.5rem}.media-sheet-textarea{display:flex;min-height:80px;width:100%;border-radius:var(--opaca-radius, 0.375rem);border:1px solid var(--opaca-border);background-color:var(--opaca-surface);padding:.5rem .75rem;font-size:.875rem;color:var(--opaca-text);outline:none;font-family:inherit}.media-sheet-textarea::placeholder{color:var(--opaca-text-dim)}.media-sheet-textarea:focus-visible{border-color:var(--opaca-primary);box-shadow:0 0 0 1px var(--opaca-primary)}.media-sheet-meta-box{background:hsla(0,0%,100%,.02);padding:1rem;border-radius:var(--opaca-radius-lg, 0.5rem);border:1px solid var(--opaca-border);display:flex;flex-direction:column;gap:.75rem;margin-top:1.5rem}.media-sheet-meta-row{display:flex;justify-content:space-between;align-items:center;font-size:.875rem}.media-sheet-meta-row .label{color:var(--opaca-text-dim)}.media-sheet-meta-row .value{color:#fff;font-weight:500}.media-sheet-meta-row .value-mono{font-family:monospace;font-size:.75rem;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.media-sheet-actions{display:flex;gap:.75rem;padding-top:1.5rem;margin-top:1.5rem}.media-sheet-actions button{flex:1}.media-preview-container{flex:1;display:flex;flex-direction:column;padding:1.5rem;background:rgba(15,15,15,.7);backdrop-filter:blur(24px) saturate(180%);border-radius:.5rem;overflow:hidden;border:1px solid hsla(0,0%,100%,.1);box-shadow:0 25px 50px -12px rgba(0,0,0,.5);max-width:90vw;max-height:90vh;animation:opaca-zoom-in .3s cubic-bezier(0.16, 1, 0.3, 1)}@media(min-width: 640px){.media-preview-container{padding:1rem}}@keyframes opaca-zoom-in{from{opacity:0;transform:scale(0.95)}to{opacity:1;transform:scale(1)}}.media-preview-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.5rem;flex-shrink:0;z-index:10}.media-preview-title-group{display:flex;align-items:center;gap:.75rem}.media-preview-title-group h2{font-size:1.25rem;font-weight:600;color:#fff;margin:0}.media-preview-title-group .badge{padding:.125rem .5rem;border-radius:.25rem;font-size:.75rem;font-family:monospace;background:hsla(0,0%,100%,.1);color:#fff;border:1px solid hsla(0,0%,100%,.2)}.media-preview-close-btn{color:#fff;background:rgba(0,0,0,0);border-radius:9999px;height:2.5rem;width:2.5rem;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;transition:background .2s}.media-preview-close-btn:hover{background:hsla(0,0%,100%,.1)}.media-preview-body{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;position:relative}.media-preview-body img{max-width:100%;max-height:100%;object-fit:contain;filter:drop-shadow(0 25px 25px rgba(0, 0, 0, 0.5))}.media-preview-no-rich{text-align:center;padding:2rem;background:hsla(0,0%,100%,.05);border-radius:1rem;border:1px solid hsla(0,0%,100%,.1);backdrop-filter:blur(4px)}.media-preview-no-rich .icon-wrapper{display:flex;justify-content:center;margin-bottom:1.5rem}.media-preview-no-rich p{color:var(--opaca-text-dim);margin-bottom:1.5rem}.media-preview-footer{margin-top:2rem;display:flex;justify-content:center;gap:1rem;flex-shrink:0}.media-preview-stat{background:hsla(0,0%,100%,.03);backdrop-filter:blur(8px);padding:.75rem 1.5rem;border-radius:1rem;border:1px solid hsla(0,0%,100%,.05);text-align:center;transition:all .2s}.media-preview-stat:hover{background:hsla(0,0%,100%,.06);transform:translateY(-2px)}.media-preview-stat .label{font-size:.75rem;color:var(--opaca-text-dim);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem}.media-preview-stat .value{font-weight:600;color:#fff}.media-dialog-create-body{padding:1rem 0}.media-bucket-settings{display:flex;flex-direction:column;gap:1.5rem;padding:1rem 0}.media-bucket-settings .bucket-setting-row{display:flex;flex-direction:column;gap:.75rem}.media-bucket-settings .bucket-setting-row .bucket-name{font-size:.75rem;font-weight:600;color:var(--opaca-text-dim);text-transform:uppercase;letter-spacing:.05em}.media-bucket-settings .bucket-setting-row .color-presets{display:flex;flex-wrap:wrap;gap:.5rem}.media-bucket-settings .bucket-setting-row .color-presets .color-bubble{width:24px;height:24px;border-radius:50%;border:2px solid rgba(0,0,0,0);cursor:pointer;transition:all var(--opaca-transition);padding:0;display:flex;align-items:center;justify-content:center}.media-bucket-settings .bucket-setting-row .color-presets .color-bubble:hover{transform:scale(1.1)}.media-bucket-settings .bucket-setting-row .color-presets .color-bubble.active{border-color:#fff;box-shadow:0 0 0 2px var(--opaca-primary)}.media-registry-dialog-sm{max-width:400px}.opaca-ui-radio-group{display:grid;gap:.75rem}.opaca-ui-radio-item{display:flex;align-items:center;gap:.75rem}.opaca-ui-radio-item input[type=radio]{appearance:none;margin:0;width:1.125rem;height:1.125rem;border:1px solid var(--opaca-border);border-radius:50%;outline:none;cursor:pointer;position:relative;background-color:var(--opaca-surface);transition:all var(--opaca-transition)}.opaca-ui-radio-item input[type=radio]:hover:not(:disabled){border-color:var(--opaca-accent)}.opaca-ui-radio-item input[type=radio]:checked{border-color:var(--opaca-primary);background-color:var(--opaca-primary)}.opaca-ui-radio-item input[type=radio]:checked::after{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);width:.375rem;height:.375rem;border-radius:50%;background-color:#fff}.opaca-ui-radio-item input[type=radio]:focus-visible{box-shadow:0 0 0 2px var(--opaca-primary-glow)}.opaca-ui-radio-item input[type=radio]:disabled{cursor:not-allowed;opacity:.5}.opaca-ui-radio-item label{cursor:pointer;font-size:.8125rem;font-weight:400;color:var(--opaca-text)}.opaca-ui-radio-item label.disabled{cursor:not-allowed;opacity:.5}.opaca-ui-select{position:relative;width:100%}.opaca-ui-select-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;min-width:160px;padding:.5rem .75rem;font-size:.8125rem;background-color:var(--opaca-surface);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);color:var(--opaca-text);cursor:pointer;transition:all var(--opaca-transition);text-align:left;outline:none}.opaca-ui-select-trigger:hover{border-color:var(--opaca-border-hover);background-color:hsla(0,0%,100%,.02)}.opaca-ui-select-trigger:focus{border-color:var(--opaca-primary);box-shadow:0 0 0 1px var(--opaca-primary-glow)}.opaca-ui-select-trigger:disabled{opacity:.5;cursor:not-allowed}.opaca-ui-select-trigger .trigger-placeholder{color:var(--opaca-text-dim)}.opaca-ui-select-trigger .trigger-icon{color:var(--opaca-text-dim);transition:transform var(--opaca-transition)}.opaca-ui-select-trigger[data-state=open] .trigger-icon{transform:rotate(180deg)}.opaca-ui-select-portal{position:fixed;z-index:1000;pointer-events:none}.opaca-ui-select-content{pointer-events:auto;min-width:8rem;overflow:hidden;background-color:var(--opaca-card-bg);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);box-shadow:0 10px 25px -5px rgba(0,0,0,.4);padding:.25rem;animation:opaca-select-in 150ms cubic-bezier(0.16, 1, 0.3, 1);transform-origin:top}@keyframes opaca-select-in{from{opacity:0;transform:scale(0.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}.opaca-ui-select-item{display:flex;align-items:center;width:100%;padding:.375rem .5rem;font-size:.8125rem;color:var(--opaca-text-muted);border-radius:var(--opaca-radius);cursor:pointer;transition:all var(--opaca-transition);border:none;background:rgba(0,0,0,0);text-align:left}.opaca-ui-select-item:hover{background-color:hsla(0,0%,100%,.05);color:var(--opaca-text)}.opaca-ui-select-item[data-selected=true]{background-color:var(--opaca-primary-glow);color:var(--opaca-accent);font-weight:500}.opaca-ui-select-label{padding:.375rem .5rem;font-size:.75rem;font-weight:600;color:var(--opaca-text-dim);text-transform:uppercase;letter-spacing:.05em}.opaca-ui-select-separator{height:1px;background-color:var(--opaca-border);margin:.25rem -0.25rem}.opaca-ui-sheet-portal{position:fixed;inset:0;z-index:9999;display:flex;justify-content:flex-end}.opaca-ui-sheet-overlay{position:fixed;inset:0;background-color:rgba(0,0,0,.8);backdrop-filter:blur(4px);transition:opacity .2s;border:none;padding:0;margin:0;cursor:default;width:100%;height:100%}.opaca-ui-sheet-wrapper{position:relative;z-index:10000;height:100%;pointer-events:none;display:flex;justify-content:flex-end;width:100%}.opaca-ui-sheet-content{pointer-events:auto;position:relative;z-index:50;display:flex;height:100%;width:100%;flex-direction:column;border-left:1px solid var(--opaca-border);background-color:var(--opaca-card-bg);padding:1.5rem;box-shadow:-10px 0 25px -5px rgba(0,0,0,.2);overflow-y:auto;animation:opacaSlideInRight .3s cubic-bezier(0.16, 1, 0.3, 1);color:var(--opaca-text)}@media(min-width: 640px){.opaca-ui-sheet-content{width:400px;max-width:100vw}}@media(min-width: 1024px){.opaca-ui-sheet-content{width:500px}}.opaca-ui-sheet-close{position:absolute;right:1rem;top:1rem;border-radius:50%;opacity:.7;transition:all .2s ease;background:rgba(0,0,0,0);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:.5rem}.opaca-ui-sheet-close:hover{opacity:1;background-color:hsla(0,0%,100%,.05);color:var(--opaca-text)}.opaca-ui-sheet-close:focus-visible{outline:none;box-shadow:0 0 0 2px var(--opaca-primary)}.opaca-ui-sheet-close-icon{height:1rem;width:1rem;color:var(--opaca-text-muted)}.opaca-ui-sheet-header{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem;text-align:center}@media(min-width: 640px){.opaca-ui-sheet-header{text-align:left}}.opaca-ui-sheet-title{font-size:1.125rem;font-weight:600;color:var(--opaca-text);margin:0}.opaca-ui-sheet-description{font-size:.875rem;color:var(--opaca-text-muted);margin:0}.opaca-ui-sheet-footer{display:flex;flex-direction:column-reverse;margin-top:auto;padding-top:1.5rem;border-top:1px solid var(--opaca-border);gap:.75rem}@media(min-width: 640px){.opaca-ui-sheet-footer{flex-direction:row;justify-content:flex-end;gap:.5rem}}.opaca-ui-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}@keyframes opacaSlideInRight{from{transform:translateX(100%)}to{transform:translateX(0)}}.opaca-ui-tabs{display:flex;flex-direction:column;width:100%}.opaca-ui-tabs-list{display:flex;background-color:var(--opaca-surface);padding:.25rem;border-radius:var(--opaca-radius-lg);overflow-x:auto;gap:.25rem;align-items:center;justify-content:flex-start;border:1px solid var(--opaca-border)}.opaca-ui-tabs-trigger{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:var(--opaca-radius);padding:.5rem 1rem;font-size:.8125rem;font-weight:500;color:var(--opaca-text-muted);background-color:rgba(0,0,0,0);border:none;cursor:pointer;transition:all var(--opaca-transition)}.opaca-ui-tabs-trigger:hover{color:var(--opaca-text);background-color:hsla(0,0%,100%,.05)}.opaca-ui-tabs-trigger[data-state=active]{background-color:var(--opaca-primary);color:#fff;box-shadow:0 4px 12px var(--opaca-primary-glow)}.opaca-ui-tabs-trigger:disabled{opacity:.5;cursor:not-allowed}.opaca-ui-tabs-content{margin-top:1rem;padding:1.25rem;border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);background-color:rgba(0,0,0,0);color:var(--opaca-text)}.opaca-ui-tabs-content[data-state=inactive]{display:none}.opaca-data-detail-sheet{width:100% !important}@media(min-width: 640px){.opaca-data-detail-sheet{width:600px !important;max-width:95vw !important}}.opaca-detail-list{display:flex;flex-direction:column;gap:1rem}.opaca-detail-item-card{background:var(--opaca-surface);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius-lg);overflow:hidden;transition:all var(--opaca-transition);box-shadow:0 1px 3px rgba(0,0,0,.05)}.opaca-detail-item-card:hover{border-color:var(--opaca-border-hover);box-shadow:0 4px 12px rgba(0,0,0,.1)}.opaca-detail-item-header{padding:.75rem 1rem;background:hsla(0,0%,100%,.03);border-bottom:1px solid var(--opaca-border);display:flex;align-items:center}.opaca-detail-item-content{padding:1rem}.opaca-detail-grid{display:flex;flex-direction:column;gap:1.25rem}.opaca-detail-grid.nested{padding:1rem;background:hsla(0,0%,100%,.015);border:1px solid var(--opaca-border);border-radius:var(--opaca-radius);margin-top:.5rem}.opaca-detail-row{display:flex;flex-direction:column;gap:.25rem}.opaca-detail-label{font-size:.75rem;font-weight:600;color:var(--opaca-text-muted);text-transform:uppercase;letter-spacing:.05em}.opaca-detail-value-container{font-size:.9375rem;color:var(--opaca-text)}.opaca-detail-value{white-space:pre-wrap;word-break:break-word}.opaca-badge-interactive{cursor:pointer;transition:all .2s ease}.opaca-badge-interactive:hover{background:var(--opaca-surface) !important;border-color:var(--opaca-primary) !important;color:var(--opaca-primary) !important;transform:translateY(-1px);box-shadow:0 2px 4px rgba(0,0,0,.1)}.opaca-row-field{display:flex;flex-wrap:wrap;gap:1rem;margin-bottom:1.25rem}.opaca-row-field .row-item{flex:1;min-width:0}.opaca-row-field .row-item .opaca-form-group{margin-bottom:0}.opaca-separator{flex-shrink:0;background-color:var(--opaca-border)}.opaca-separator.horizontal{height:1px;width:100%}.opaca-separator.vertical{width:1px;height:100%}.opaca-locale-switcher{display:flex;align-items:center;gap:.5rem;background:var(--opaca-card-bg);padding:.25rem;border-radius:var(--opaca-radius);border:1px solid var(--opaca-border);box-shadow:var(--opaca-shadow-sm)}.opaca-locale-btn{background:none;border:none;padding:.375rem .75rem;border-radius:calc(var(--opaca-radius) - 2px);font-size:.75rem;font-weight:600;color:var(--opaca-text-dim);cursor:pointer;transition:all var(--opaca-transition)}.opaca-locale-btn:hover{color:var(--opaca-text);background:hsla(0,0%,100%,.05)}.opaca-locale-btn.active{background:var(--opaca-accent);color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.2)}
@@ -17,7 +17,7 @@ async function migrateCreateCommand(opaca, migrationName = "migration", outDir)
17
17
  fs.mkdirSync(fullMigrationDir, { recursive: true });
18
18
  }
19
19
  const timestamp = new Date().toISOString().replace(/[-:T]/g, "").split(".")[0];
20
- const { generateMigrationCode, generateSQLCode } = await import("./chunk-kwp83w8b.js");
20
+ const { generateMigrationCode, generateSQLCode } = await import("./chunk-wmvjvn7b.js");
21
21
  const { getSystemCollections } = await import("./chunk-v521d72w.js");
22
22
  let dialect = "sqlite";
23
23
  if (db.name === "postgres")
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-62ev8gnc.js";
8
8
  import {
9
9
  toSnakeCase
10
- } from "./chunk-cvdd4eqh.js";
10
+ } from "./chunk-2kyhqvhc.js";
11
11
  import {
12
12
  exports_system_schema,
13
13
  getSystemCollections,
@@ -1,6 +1,10 @@
1
1
  // src/db/kysely/field-mapper.ts
2
2
  function toSnakeCase(str) {
3
- return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
3
+ const res = str.replace(/([A-Z])/g, "_$1").toLowerCase();
4
+ if (res.startsWith("_") && !str.startsWith("_")) {
5
+ return res.slice(1);
6
+ }
7
+ return res;
4
8
  }
5
9
  function mapFieldToPostgresType(field) {
6
10
  switch (field.type) {
@@ -3,7 +3,7 @@ import {
3
3
  flattenPayload,
4
4
  pushSchema,
5
5
  unflattenRow
6
- } from "./chunk-6ew02s0c.js";
6
+ } from "./chunk-xtwc125q.js";
7
7
  import {
8
8
  BaseDatabaseAdapter
9
9
  } from "./chunk-s8mqwnm1.js";
@@ -14,7 +14,7 @@ import {
14
14
  flattenFields,
15
15
  getRelationalFields,
16
16
  toSnakeCase
17
- } from "./chunk-cvdd4eqh.js";
17
+ } from "./chunk-2kyhqvhc.js";
18
18
 
19
19
  // src/db/bun-sqlite.ts
20
20
  import { Database } from "bun:sqlite";
@@ -27,6 +27,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
27
27
  _rawDb;
28
28
  _db;
29
29
  _collections = [];
30
+ _globals = [];
30
31
  push;
31
32
  migrationDir;
32
33
  pushDestructive;
@@ -342,7 +343,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
342
343
  const block = blocks[i];
343
344
  if (!block.blockType)
344
345
  continue;
345
- const blockTableName = `${collection}_${toSnakeCase(key)}_${toSnakeCase(block.blockType)}`.toLowerCase();
346
+ const blockTableName = `${toSnakeCase(collection)}_${toSnakeCase(key)}_${toSnakeCase(block.blockType)}`.toLowerCase();
346
347
  const bId = block.id || crypto.randomUUID();
347
348
  const blockConfig = blockDef?.blocks?.find((b) => b.slug === block.blockType);
348
349
  const blockJsonFields = blockConfig?.fields.filter((f) => ["richtext", "json", "file"].includes(f.type)).map((f) => f.name) || [];
@@ -470,15 +471,28 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
470
471
  return row ? unflattenRow(row) : null;
471
472
  }
472
473
  async updateGlobal(slug, data) {
474
+ const tableName = toSnakeCase(slug);
473
475
  const existing = await this.findGlobal(slug);
474
476
  const flatData = flattenPayload(data);
475
- flatData.updated_at = new Date().toISOString();
477
+ const globalDef = this._globals.find((g) => g.slug === slug);
478
+ const ts = globalDef?.timestamps !== false;
479
+ if (ts) {
480
+ const config = typeof globalDef?.timestamps === "object" ? globalDef.timestamps : {};
481
+ const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
482
+ flatData[updatedField] = new Date().toISOString();
483
+ }
476
484
  if (!existing) {
477
485
  if (!flatData.id)
478
486
  flatData.id = "global";
479
- await this._db.insertInto(toSnakeCase(slug)).values(flatData).execute();
487
+ if (ts) {
488
+ const config = typeof globalDef?.timestamps === "object" ? globalDef.timestamps : {};
489
+ const createdField = toSnakeCase(config.createdAt || "createdAt");
490
+ if (!flatData[createdField])
491
+ flatData[createdField] = flatData[toSnakeCase(config.updatedAt || "updatedAt")];
492
+ }
493
+ await this._db.insertInto(tableName).values(flatData).execute();
480
494
  } else {
481
- await this._db.updateTable(toSnakeCase(slug)).set(flatData).where("id", "=", existing.id).execute();
495
+ await this._db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
482
496
  }
483
497
  return this.findGlobal(slug);
484
498
  }
@@ -505,6 +519,7 @@ class BunSQLiteAdapter extends BaseDatabaseAdapter {
505
519
  }
506
520
  async migrate(collections, globals = []) {
507
521
  this._collections = collections;
522
+ this._globals = globals;
508
523
  if (this.push) {
509
524
  await pushSchema(this._db, "sqlite", collections, globals, {
510
525
  pushDestructive: this.pushDestructive
@@ -4,7 +4,7 @@ import {
4
4
  mapFieldToPostgresType,
5
5
  mapFieldToSQLiteType,
6
6
  toSnakeCase
7
- } from "./chunk-cvdd4eqh.js";
7
+ } from "./chunk-2kyhqvhc.js";
8
8
  import"./chunk-8sqjbsgt.js";
9
9
  export {
10
10
  toSnakeCase,
@@ -3,7 +3,7 @@ import {
3
3
  flattenPayload,
4
4
  pushSchema,
5
5
  unflattenRow
6
- } from "./chunk-6ew02s0c.js";
6
+ } from "./chunk-xtwc125q.js";
7
7
  import {
8
8
  BaseDatabaseAdapter
9
9
  } from "./chunk-s8mqwnm1.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-62ev8gnc.js";
13
13
  import {
14
14
  toSnakeCase
15
- } from "./chunk-cvdd4eqh.js";
15
+ } from "./chunk-2kyhqvhc.js";
16
16
  import {
17
17
  __require
18
18
  } from "./chunk-8sqjbsgt.js";
@@ -100,7 +100,8 @@ class PostgresAdapter extends BaseDatabaseAdapter {
100
100
  async count(collection, query) {
101
101
  if (!this._db)
102
102
  throw new Error("DB not connected");
103
- let qb = this._db.selectFrom(collection).select((eb) => eb.fn.count("id").as("count"));
103
+ const tableName = toSnakeCase(collection);
104
+ let qb = this._db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count"));
104
105
  if (query && Object.keys(query).length > 0) {
105
106
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
106
107
  }
@@ -110,6 +111,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
110
111
  async create(collection, data) {
111
112
  if (!this._db)
112
113
  throw new Error("DB not connected");
114
+ const tableName = toSnakeCase(collection);
113
115
  return this._db.transaction().execute(async (tx) => {
114
116
  const colDef = this._collections.find((c) => c.slug === collection);
115
117
  const jsonFields = colDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
@@ -139,9 +141,9 @@ class PostgresAdapter extends BaseDatabaseAdapter {
139
141
  if (!flatData[updatedField])
140
142
  flatData[updatedField] = new Date().toISOString();
141
143
  }
142
- await tx.insertInto(collection).values(flatData).execute();
144
+ await tx.insertInto(tableName).values(flatData).execute();
143
145
  for (const [key, values] of Object.entries(hasManyData)) {
144
- const joinTableName = `${collection}_${toSnakeCase(key)}_relations`.toLowerCase();
146
+ const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
145
147
  if (values.length > 0) {
146
148
  const joinData = values.map((val, idx) => {
147
149
  const tId = typeof val === "object" ? val.id : val;
@@ -155,7 +157,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
155
157
  const block = blocks[i];
156
158
  if (!block.blockType)
157
159
  continue;
158
- const blockTableName = `${collection}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
160
+ const blockTableName = `${tableName}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
159
161
  const bId = block.id || crypto.randomUUID();
160
162
  const blockFlatData = flattenPayload({ ...block, id: bId });
161
163
  delete blockFlatData.blockType;
@@ -171,10 +173,11 @@ class PostgresAdapter extends BaseDatabaseAdapter {
171
173
  });
172
174
  }
173
175
  async findOne(collection, query, tx) {
176
+ const tableName = toSnakeCase(collection);
174
177
  const executor = tx || this._db;
175
178
  if (!executor)
176
179
  throw new Error("DB not connected");
177
- let qb = executor.selectFrom(collection).selectAll();
180
+ let qb = executor.selectFrom(tableName).selectAll();
178
181
  if (query && Object.keys(query).length > 0) {
179
182
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
180
183
  }
@@ -184,7 +187,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
184
187
  const unflattened = unflattenRow(row);
185
188
  const colDef = this._collections.find((c) => c.slug === collection);
186
189
  if (colDef) {
187
- const { getRelationalFields, toSnakeCase: toSnakeCase2 } = await import("./chunk-xg35h5a3.js");
190
+ const { getRelationalFields, toSnakeCase: toSnakeCase2 } = await import("./chunk-7fyepksb.js");
188
191
  const relationalFields = getRelationalFields(colDef.fields);
189
192
  for (const field of relationalFields) {
190
193
  if (!field.name)
@@ -241,7 +244,8 @@ class PostgresAdapter extends BaseDatabaseAdapter {
241
244
  const limit = options?.limit || 10;
242
245
  const offset = (page - 1) * limit;
243
246
  const total = await this.count(collection, query);
244
- let qb = this._db.selectFrom(collection).selectAll().limit(limit).offset(offset);
247
+ const tableName = toSnakeCase(collection);
248
+ let qb = this._db.selectFrom(tableName).selectAll().limit(limit).offset(offset);
245
249
  if (query && Object.keys(query).length > 0) {
246
250
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
247
251
  }
@@ -302,11 +306,12 @@ class PostgresAdapter extends BaseDatabaseAdapter {
302
306
  const updatedField = toSnakeCase(config.updatedAt || "updatedAt");
303
307
  flatData[updatedField] = new Date().toISOString();
304
308
  }
309
+ const tableName = toSnakeCase(collection);
305
310
  if (Object.keys(flatData).length > 0) {
306
- await tx.updateTable(collection).set(flatData).where("id", "=", current.id).execute();
311
+ await tx.updateTable(tableName).set(flatData).where("id", "=", current.id).execute();
307
312
  }
308
313
  for (const [key, values] of Object.entries(hasManyData)) {
309
- const joinTableName = `${collection}_${toSnakeCase(key)}_relations`.toLowerCase();
314
+ const joinTableName = `${tableName}_${toSnakeCase(key)}_relations`.toLowerCase();
310
315
  await tx.deleteFrom(joinTableName).where("source_id", "=", current.id).execute();
311
316
  if (values.length > 0) {
312
317
  const joinData = values.map((val, idx) => {
@@ -320,7 +325,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
320
325
  const fieldDef = colDef?.fields.find((f) => f.name === key);
321
326
  if (fieldDef && "blocks" in fieldDef && fieldDef.blocks) {
322
327
  for (const b of fieldDef.blocks) {
323
- const blockTableName = `${collection}_${toSnakeCase(key)}_${b.slug}`.toLowerCase();
328
+ const blockTableName = `${tableName}_${toSnakeCase(key)}_${b.slug}`.toLowerCase();
324
329
  try {
325
330
  await tx.deleteFrom(blockTableName).where("_parent_id", "=", current.id).execute();
326
331
  } catch (e) {}
@@ -330,7 +335,7 @@ class PostgresAdapter extends BaseDatabaseAdapter {
330
335
  const block = blocks[i];
331
336
  if (!block.blockType)
332
337
  continue;
333
- const blockTableName = `${collection}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
338
+ const blockTableName = `${tableName}_${toSnakeCase(key)}_${block.blockType}`.toLowerCase();
334
339
  const bId = block.id || crypto.randomUUID();
335
340
  const blockFlatData = flattenPayload({ ...block, id: bId });
336
341
  delete blockFlatData.blockType;
@@ -348,8 +353,9 @@ class PostgresAdapter extends BaseDatabaseAdapter {
348
353
  async updateMany(collection, query, data) {
349
354
  if (!this._db)
350
355
  throw new Error("DB not connected");
356
+ const tableName = toSnakeCase(collection);
351
357
  return this._db.transaction().execute(async (tx) => {
352
- let qb = tx.updateTable(collection);
358
+ let qb = tx.updateTable(tableName);
353
359
  if (query && Object.keys(query).length > 0) {
354
360
  qb = qb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
355
361
  }
@@ -383,19 +389,20 @@ class PostgresAdapter extends BaseDatabaseAdapter {
383
389
  const current = await this.findOne(collection, normalizedQuery);
384
390
  if (!current)
385
391
  return false;
392
+ const tableName = toSnakeCase(collection);
386
393
  await this._db.transaction().execute(async (tx) => {
387
394
  const colDef = this._collections.find((c) => c.slug === collection);
388
395
  if (colDef) {
389
396
  for (const field of colDef.fields) {
390
397
  const snakeName = toSnakeCase(field.name);
391
398
  if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
392
- const joinTableName = `${collection}_${snakeName}_relations`.toLowerCase();
399
+ const joinTableName = `${tableName}_${snakeName}_relations`.toLowerCase();
393
400
  try {
394
401
  await tx.deleteFrom(joinTableName).where("source_id", "=", current.id).execute();
395
402
  } catch (e) {}
396
403
  } else if (field.type === "blocks" && "blocks" in field && field.blocks) {
397
404
  for (const b of field.blocks) {
398
- const blockTableName = `${collection}_${snakeName}_${b.slug}`.toLowerCase();
405
+ const blockTableName = `${tableName}_${snakeName}_${b.slug}`.toLowerCase();
399
406
  try {
400
407
  await tx.deleteFrom(blockTableName).where("_parent_id", "=", current.id).execute();
401
408
  } catch (e) {}
@@ -403,15 +410,16 @@ class PostgresAdapter extends BaseDatabaseAdapter {
403
410
  }
404
411
  }
405
412
  }
406
- await tx.deleteFrom(collection).where("id", "=", current.id).execute();
413
+ await tx.deleteFrom(tableName).where("id", "=", current.id).execute();
407
414
  });
408
415
  return true;
409
416
  }
410
417
  async deleteMany(collection, query) {
411
418
  if (!this._db)
412
419
  throw new Error("DB not connected");
420
+ const tableName = toSnakeCase(collection);
413
421
  return this._db.transaction().execute(async (tx) => {
414
- let selectQb = tx.selectFrom(collection).select("id");
422
+ let selectQb = tx.selectFrom(tableName).select("id");
415
423
  if (query && Object.keys(query).length > 0) {
416
424
  selectQb = selectQb.where((eb) => buildKyselyWhere(eb, query) || eb.val(true));
417
425
  }
@@ -424,13 +432,13 @@ class PostgresAdapter extends BaseDatabaseAdapter {
424
432
  for (const field of colDef.fields) {
425
433
  const snakeName = toSnakeCase(field.name);
426
434
  if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
427
- const joinTableName = `${collection}_${snakeName}_relations`.toLowerCase();
435
+ const joinTableName = `${tableName}_${snakeName}_relations`.toLowerCase();
428
436
  try {
429
437
  await tx.deleteFrom(joinTableName).where("source_id", "in", ids).execute();
430
438
  } catch (e) {}
431
439
  } else if (field.type === "blocks" && "blocks" in field && field.blocks) {
432
440
  for (const b of field.blocks) {
433
- const blockTableName = `${collection}_${snakeName}_${b.slug}`.toLowerCase();
441
+ const blockTableName = `${tableName}_${snakeName}_${b.slug}`.toLowerCase();
434
442
  try {
435
443
  await tx.deleteFrom(blockTableName).where("_parent_id", "in", ids).execute();
436
444
  } catch (e) {}
@@ -438,19 +446,21 @@ class PostgresAdapter extends BaseDatabaseAdapter {
438
446
  }
439
447
  }
440
448
  }
441
- const result = await tx.deleteFrom(collection).where("id", "in", ids).executeTakeFirst();
449
+ const result = await tx.deleteFrom(tableName).where("id", "in", ids).executeTakeFirst();
442
450
  return Number(result.numDeletedRows || 0);
443
451
  });
444
452
  }
445
453
  async findGlobal(slug) {
446
454
  if (!this._db)
447
455
  throw new Error("DB not connected");
448
- const row = await this._db.selectFrom(slug).selectAll().limit(1).executeTakeFirst();
456
+ const tableName = toSnakeCase(slug);
457
+ const row = await this._db.selectFrom(tableName).selectAll().limit(1).executeTakeFirst();
449
458
  return row ? unflattenRow(row) : null;
450
459
  }
451
460
  async updateGlobal(slug, data) {
452
461
  if (!this._db)
453
462
  throw new Error("DB not connected");
463
+ const tableName = toSnakeCase(slug);
454
464
  const existing = await this.findGlobal(slug);
455
465
  const globalDef = this._globals.find((g) => g.slug === slug);
456
466
  const jsonFields = globalDef?.fields.filter((f) => f.name && (["richtext", "json", "file"].includes(f.type) || f.localized)).map((f) => f.name) || [];
@@ -470,9 +480,9 @@ class PostgresAdapter extends BaseDatabaseAdapter {
470
480
  if (!flatData[createdField])
471
481
  flatData[createdField] = new Date().toISOString();
472
482
  }
473
- await this._db.insertInto(slug).values(flatData).execute();
483
+ await this._db.insertInto(tableName).values(flatData).execute();
474
484
  } else {
475
- await this._db.updateTable(slug).set(flatData).where("id", "=", existing.id).execute();
485
+ await this._db.updateTable(tableName).set(flatData).where("id", "=", existing.id).execute();
476
486
  }
477
487
  return this.findGlobal(slug);
478
488
  }