@actuate-media/cms-admin 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +8 -5
  3. package/dist/AdminRoot.js.map +1 -1
  4. package/dist/__tests__/layout/primitives.test.d.ts +2 -0
  5. package/dist/__tests__/layout/primitives.test.d.ts.map +1 -0
  6. package/dist/__tests__/layout/primitives.test.js +34 -0
  7. package/dist/__tests__/layout/primitives.test.js.map +1 -0
  8. package/dist/__tests__/lib/cv.test.d.ts +2 -0
  9. package/dist/__tests__/lib/cv.test.d.ts.map +1 -0
  10. package/dist/__tests__/lib/cv.test.js +66 -0
  11. package/dist/__tests__/lib/cv.test.js.map +1 -0
  12. package/dist/actuate-admin.css +1 -1
  13. package/dist/assets/actuate-logo.d.ts +36 -0
  14. package/dist/assets/actuate-logo.d.ts.map +1 -0
  15. package/dist/assets/actuate-logo.js +15 -0
  16. package/dist/assets/actuate-logo.js.map +1 -0
  17. package/dist/components/Breadcrumbs.js +2 -2
  18. package/dist/components/CommandPalette.js +10 -10
  19. package/dist/components/ContentOverviewChart.js +3 -3
  20. package/dist/components/ErrorBoundary.js +1 -1
  21. package/dist/components/FocalPointPicker.js +2 -2
  22. package/dist/components/FolderTree.js +20 -20
  23. package/dist/components/LivePreview.js +3 -3
  24. package/dist/components/LocaleSwitcher.js +1 -1
  25. package/dist/components/MediaPickerModal.js +4 -4
  26. package/dist/components/PresenceIndicator.js +1 -1
  27. package/dist/components/SEOConfigPanel.d.ts +2 -0
  28. package/dist/components/SEOConfigPanel.d.ts.map +1 -0
  29. package/dist/components/SEOConfigPanel.js +174 -0
  30. package/dist/components/SEOConfigPanel.js.map +1 -0
  31. package/dist/components/SEOPanel.js +9 -9
  32. package/dist/components/SEOPerformance.js +2 -2
  33. package/dist/components/SchedulePublishDialog.d.ts +18 -0
  34. package/dist/components/SchedulePublishDialog.d.ts.map +1 -0
  35. package/dist/components/SchedulePublishDialog.js +106 -0
  36. package/dist/components/SchedulePublishDialog.js.map +1 -0
  37. package/dist/components/SharePreviewLinkDialog.d.ts +17 -0
  38. package/dist/components/SharePreviewLinkDialog.d.ts.map +1 -0
  39. package/dist/components/SharePreviewLinkDialog.js +83 -0
  40. package/dist/components/SharePreviewLinkDialog.js.map +1 -0
  41. package/dist/components/TipTapEditor.js +5 -5
  42. package/dist/components/VersionHistory.js +2 -2
  43. package/dist/components/ui/Badge.d.ts +33 -3
  44. package/dist/components/ui/Badge.d.ts.map +1 -1
  45. package/dist/components/ui/Badge.js +42 -8
  46. package/dist/components/ui/Badge.js.map +1 -1
  47. package/dist/components/ui/Button.d.ts +19 -8
  48. package/dist/components/ui/Button.d.ts.map +1 -1
  49. package/dist/components/ui/Button.js +35 -14
  50. package/dist/components/ui/Button.js.map +1 -1
  51. package/dist/components/ui/Card.d.ts +26 -0
  52. package/dist/components/ui/Card.d.ts.map +1 -0
  53. package/dist/components/ui/Card.js +45 -0
  54. package/dist/components/ui/Card.js.map +1 -0
  55. package/dist/components/ui/DataTable.js +1 -1
  56. package/dist/components/ui/Input.d.ts +15 -0
  57. package/dist/components/ui/Input.d.ts.map +1 -0
  58. package/dist/components/ui/Input.js +23 -0
  59. package/dist/components/ui/Input.js.map +1 -0
  60. package/dist/components/ui/SearchInput.js +1 -1
  61. package/dist/components/ui/Select.d.ts +16 -0
  62. package/dist/components/ui/Select.d.ts.map +1 -0
  63. package/dist/components/ui/Select.js +25 -0
  64. package/dist/components/ui/Select.js.map +1 -0
  65. package/dist/components/ui/Toast.js +1 -1
  66. package/dist/components/ui/index.d.ts +10 -4
  67. package/dist/components/ui/index.d.ts.map +1 -1
  68. package/dist/components/ui/index.js +5 -2
  69. package/dist/components/ui/index.js.map +1 -1
  70. package/dist/fields/BlockBuilderField.js +3 -3
  71. package/dist/fields/DateField.js +1 -1
  72. package/dist/fields/RelationshipField.js +3 -3
  73. package/dist/fields/TextField.js +1 -1
  74. package/dist/index.d.ts +6 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/layout/Header.js +1 -1
  79. package/dist/layout/Layout.d.ts +14 -0
  80. package/dist/layout/Layout.d.ts.map +1 -1
  81. package/dist/layout/Layout.js +17 -11
  82. package/dist/layout/Layout.js.map +1 -1
  83. package/dist/layout/Sidebar.d.ts.map +1 -1
  84. package/dist/layout/Sidebar.js +21 -11
  85. package/dist/layout/Sidebar.js.map +1 -1
  86. package/dist/layout/primitives/AdminShell.d.ts +43 -0
  87. package/dist/layout/primitives/AdminShell.d.ts.map +1 -0
  88. package/dist/layout/primitives/AdminShell.js +51 -0
  89. package/dist/layout/primitives/AdminShell.js.map +1 -0
  90. package/dist/layout/primitives/Box.d.ts +19 -0
  91. package/dist/layout/primitives/Box.d.ts.map +1 -0
  92. package/dist/layout/primitives/Box.js +12 -0
  93. package/dist/layout/primitives/Box.js.map +1 -0
  94. package/dist/layout/primitives/Cluster.d.ts +27 -0
  95. package/dist/layout/primitives/Cluster.d.ts.map +1 -0
  96. package/dist/layout/primitives/Cluster.js +37 -0
  97. package/dist/layout/primitives/Cluster.js.map +1 -0
  98. package/dist/layout/primitives/Grid.d.ts +45 -0
  99. package/dist/layout/primitives/Grid.d.ts.map +1 -0
  100. package/dist/layout/primitives/Grid.js +59 -0
  101. package/dist/layout/primitives/Grid.js.map +1 -0
  102. package/dist/layout/primitives/PageContainer.d.ts +36 -0
  103. package/dist/layout/primitives/PageContainer.d.ts.map +1 -0
  104. package/dist/layout/primitives/PageContainer.js +41 -0
  105. package/dist/layout/primitives/PageContainer.js.map +1 -0
  106. package/dist/layout/primitives/Split.d.ts +34 -0
  107. package/dist/layout/primitives/Split.d.ts.map +1 -0
  108. package/dist/layout/primitives/Split.js +27 -0
  109. package/dist/layout/primitives/Split.js.map +1 -0
  110. package/dist/layout/primitives/Stack.d.ts +23 -0
  111. package/dist/layout/primitives/Stack.d.ts.map +1 -0
  112. package/dist/layout/primitives/Stack.js +34 -0
  113. package/dist/layout/primitives/Stack.js.map +1 -0
  114. package/dist/layout/primitives/index.d.ts +30 -0
  115. package/dist/layout/primitives/index.d.ts.map +1 -0
  116. package/dist/layout/primitives/index.js +22 -0
  117. package/dist/layout/primitives/index.js.map +1 -0
  118. package/dist/layout/primitives/tokens.d.ts +48 -0
  119. package/dist/layout/primitives/tokens.d.ts.map +1 -0
  120. package/dist/layout/primitives/tokens.js +54 -0
  121. package/dist/layout/primitives/tokens.js.map +1 -0
  122. package/dist/lib/cv.d.ts +53 -0
  123. package/dist/lib/cv.d.ts.map +1 -0
  124. package/dist/lib/cv.js +39 -0
  125. package/dist/lib/cv.js.map +1 -0
  126. package/dist/views/ApiKeys.d.ts.map +1 -1
  127. package/dist/views/ApiKeys.js +13 -11
  128. package/dist/views/ApiKeys.js.map +1 -1
  129. package/dist/views/CollectionList.js +8 -8
  130. package/dist/views/Dashboard.d.ts.map +1 -1
  131. package/dist/views/Dashboard.js +333 -78
  132. package/dist/views/Dashboard.js.map +1 -1
  133. package/dist/views/DocumentEdit.d.ts.map +1 -1
  134. package/dist/views/DocumentEdit.js +17 -5
  135. package/dist/views/DocumentEdit.js.map +1 -1
  136. package/dist/views/ForgotPassword.js +2 -2
  137. package/dist/views/FormEditor.js +5 -5
  138. package/dist/views/FormSubmissions.js +6 -6
  139. package/dist/views/Forms.js +2 -2
  140. package/dist/views/Login.d.ts +16 -1
  141. package/dist/views/Login.d.ts.map +1 -1
  142. package/dist/views/Login.js +17 -7
  143. package/dist/views/Login.js.map +1 -1
  144. package/dist/views/MediaBrowser.js +16 -16
  145. package/dist/views/PageEditor.js +2 -2
  146. package/dist/views/Pages.js +10 -10
  147. package/dist/views/PostEditor.js +2 -2
  148. package/dist/views/Posts.js +4 -4
  149. package/dist/views/Redirects.js +4 -4
  150. package/dist/views/ResetPassword.js +2 -2
  151. package/dist/views/SEO.js +6 -6
  152. package/dist/views/ScriptTagEditor.js +4 -4
  153. package/dist/views/ScriptTags.js +2 -2
  154. package/dist/views/Settings.d.ts.map +1 -1
  155. package/dist/views/Settings.js +9 -8
  156. package/dist/views/Settings.js.map +1 -1
  157. package/dist/views/SetupWizard.js +2 -2
  158. package/dist/views/Users.js +4 -4
  159. package/dist/views/page-builder/AIBlockAssist.js +1 -1
  160. package/dist/views/page-builder/AIGenerateDialog.js +10 -10
  161. package/dist/views/page-builder/BlockEditor.js +10 -10
  162. package/dist/views/page-builder/BlockPicker.js +4 -4
  163. package/dist/views/page-builder/BottomBar.js +1 -1
  164. package/dist/views/page-builder/BuilderToolbar.js +2 -2
  165. package/dist/views/page-builder/ContextPanel.js +2 -2
  166. package/dist/views/page-builder/DesignScore.js +9 -9
  167. package/dist/views/page-builder/NodeSettings.js +8 -8
  168. package/dist/views/page-builder/PageBuilder.js +3 -3
  169. package/dist/views/page-builder/PageSettings.js +1 -1
  170. package/dist/views/page-builder/PageTemplates.js +2 -2
  171. package/dist/views/page-builder/SEOPanel.js +13 -13
  172. package/dist/views/page-builder/SavedSections.js +5 -5
  173. package/dist/views/page-builder/TemplatePicker.js +2 -2
  174. package/dist/views/page-builder/block-renderers/CTAPreview.js +5 -5
  175. package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
  176. package/dist/views/page-builder/block-renderers/CodePreview.js +1 -1
  177. package/dist/views/page-builder/block-renderers/FAQPreview.js +3 -3
  178. package/dist/views/page-builder/block-renderers/FallbackPreview.js +1 -1
  179. package/dist/views/page-builder/block-renderers/FormPreview.js +3 -3
  180. package/dist/views/page-builder/block-renderers/GalleryPreview.js +5 -5
  181. package/dist/views/page-builder/block-renderers/HeroPreview.js +3 -3
  182. package/dist/views/page-builder/block-renderers/ImagePreview.js +3 -3
  183. package/dist/views/page-builder/block-renderers/TextPreview.js +3 -3
  184. package/dist/views/page-builder/block-renderers/VideoPreview.js +4 -4
  185. package/dist/views/page-builder/canvas/BlockRenderer.js +1 -1
  186. package/dist/views/page-builder/canvas/BuilderCanvas.js +3 -3
  187. package/dist/views/page-builder/canvas/ColumnRenderer.js +2 -2
  188. package/dist/views/page-builder/canvas/ContainerRenderer.js +2 -2
  189. package/dist/views/page-builder/canvas/RowRenderer.js +2 -2
  190. package/dist/views/page-builder/canvas/SectionRenderer.js +2 -2
  191. package/package.json +6 -2
  192. package/src/AdminRoot.tsx +21 -11
  193. package/src/__tests__/layout/primitives.test.ts +37 -0
  194. package/src/__tests__/lib/cv.test.ts +74 -0
  195. package/src/assets/actuate-logo.tsx +72 -0
  196. package/src/components/Breadcrumbs.tsx +6 -6
  197. package/src/components/CommandPalette.tsx +34 -34
  198. package/src/components/ContentOverviewChart.tsx +3 -3
  199. package/src/components/ErrorBoundary.tsx +3 -3
  200. package/src/components/FocalPointPicker.tsx +4 -4
  201. package/src/components/FolderTree.tsx +38 -38
  202. package/src/components/LivePreview.tsx +16 -16
  203. package/src/components/LocaleSwitcher.tsx +7 -7
  204. package/src/components/MediaPickerModal.tsx +21 -21
  205. package/src/components/PresenceIndicator.tsx +2 -2
  206. package/src/components/SEOConfigPanel.tsx +582 -0
  207. package/src/components/SEOPanel.tsx +46 -46
  208. package/src/components/SEOPerformance.tsx +21 -21
  209. package/src/components/SchedulePublishDialog.tsx +241 -0
  210. package/src/components/SharePreviewLinkDialog.tsx +227 -0
  211. package/src/components/TipTapEditor.tsx +33 -33
  212. package/src/components/VersionHistory.tsx +16 -16
  213. package/src/components/ui/Badge.tsx +66 -14
  214. package/src/components/ui/Button.tsx +70 -33
  215. package/src/components/ui/Card.tsx +101 -0
  216. package/src/components/ui/DataTable.tsx +1 -1
  217. package/src/components/ui/Input.tsx +35 -0
  218. package/src/components/ui/SearchInput.tsx +4 -4
  219. package/src/components/ui/Select.tsx +56 -0
  220. package/src/components/ui/Toast.tsx +1 -1
  221. package/src/components/ui/index.ts +18 -4
  222. package/src/fields/BlockBuilderField.tsx +3 -3
  223. package/src/fields/DateField.tsx +1 -1
  224. package/src/fields/RelationshipField.tsx +10 -10
  225. package/src/fields/TextField.tsx +1 -1
  226. package/src/index.ts +32 -0
  227. package/src/layout/Header.tsx +28 -28
  228. package/src/layout/Layout.tsx +39 -46
  229. package/src/layout/Sidebar.tsx +37 -64
  230. package/src/layout/primitives/AdminShell.tsx +118 -0
  231. package/src/layout/primitives/Box.tsx +30 -0
  232. package/src/layout/primitives/Cluster.tsx +74 -0
  233. package/src/layout/primitives/Grid.tsx +120 -0
  234. package/src/layout/primitives/PageContainer.tsx +96 -0
  235. package/src/layout/primitives/Split.tsx +73 -0
  236. package/src/layout/primitives/Stack.tsx +67 -0
  237. package/src/layout/primitives/index.ts +36 -0
  238. package/src/layout/primitives/tokens.ts +76 -0
  239. package/src/lib/cv.ts +96 -0
  240. package/src/styles/build-input.css +1 -1
  241. package/src/views/ApiKeys.tsx +57 -57
  242. package/src/views/CollectionList.tsx +30 -30
  243. package/src/views/Dashboard.tsx +737 -186
  244. package/src/views/DocumentEdit.tsx +90 -10
  245. package/src/views/ForgotPassword.tsx +18 -18
  246. package/src/views/FormEditor.tsx +75 -75
  247. package/src/views/FormSubmissions.tsx +76 -76
  248. package/src/views/Forms.tsx +27 -27
  249. package/src/views/Login.tsx +65 -25
  250. package/src/views/MediaBrowser.tsx +127 -127
  251. package/src/views/PageEditor.tsx +25 -25
  252. package/src/views/Pages.tsx +59 -59
  253. package/src/views/PostEditor.tsx +37 -37
  254. package/src/views/Posts.tsx +48 -48
  255. package/src/views/Redirects.tsx +21 -21
  256. package/src/views/ResetPassword.tsx +28 -28
  257. package/src/views/SEO.tsx +144 -144
  258. package/src/views/ScriptTagEditor.tsx +24 -24
  259. package/src/views/ScriptTags.tsx +10 -10
  260. package/src/views/Settings.tsx +88 -80
  261. package/src/views/SetupWizard.tsx +28 -28
  262. package/src/views/Users.tsx +20 -20
  263. package/src/views/page-builder/AIBlockAssist.tsx +1 -1
  264. package/src/views/page-builder/AIGenerateDialog.tsx +63 -63
  265. package/src/views/page-builder/BlockEditor.tsx +26 -26
  266. package/src/views/page-builder/BlockPicker.tsx +22 -22
  267. package/src/views/page-builder/BottomBar.tsx +8 -8
  268. package/src/views/page-builder/BuilderToolbar.tsx +17 -17
  269. package/src/views/page-builder/ContextPanel.tsx +3 -3
  270. package/src/views/page-builder/DesignScore.tsx +21 -21
  271. package/src/views/page-builder/NodeSettings.tsx +27 -27
  272. package/src/views/page-builder/PageBuilder.tsx +11 -11
  273. package/src/views/page-builder/PageSettings.tsx +4 -4
  274. package/src/views/page-builder/PageTemplates.tsx +18 -18
  275. package/src/views/page-builder/SEOPanel.tsx +53 -53
  276. package/src/views/page-builder/SavedSections.tsx +37 -37
  277. package/src/views/page-builder/TemplatePicker.tsx +17 -17
  278. package/src/views/page-builder/block-renderers/CTAPreview.tsx +13 -13
  279. package/src/views/page-builder/block-renderers/CardsPreview.tsx +5 -5
  280. package/src/views/page-builder/block-renderers/CodePreview.tsx +6 -6
  281. package/src/views/page-builder/block-renderers/FAQPreview.tsx +13 -13
  282. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +3 -3
  283. package/src/views/page-builder/block-renderers/FormPreview.tsx +20 -20
  284. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +8 -8
  285. package/src/views/page-builder/block-renderers/HeroPreview.tsx +16 -16
  286. package/src/views/page-builder/block-renderers/ImagePreview.tsx +4 -4
  287. package/src/views/page-builder/block-renderers/TextPreview.tsx +14 -14
  288. package/src/views/page-builder/block-renderers/VideoPreview.tsx +12 -12
  289. package/src/views/page-builder/canvas/BlockRenderer.tsx +4 -4
  290. package/src/views/page-builder/canvas/BuilderCanvas.tsx +6 -6
  291. package/src/views/page-builder/canvas/ColumnRenderer.tsx +3 -3
  292. package/src/views/page-builder/canvas/ContainerRenderer.tsx +2 -2
  293. package/src/views/page-builder/canvas/RowRenderer.tsx +2 -2
  294. package/src/views/page-builder/canvas/SectionRenderer.tsx +2 -2
@@ -86,9 +86,9 @@ export function NodeSettings({
86
86
  : 'Column'
87
87
 
88
88
  return (
89
- <div className="flex flex-col h-full">
90
- <div className="p-4 border-b border-border">
91
- <p className="text-sm font-medium text-foreground">{nodeLabel} Settings</p>
89
+ <div className="flex h-full flex-col">
90
+ <div className="border-border border-b p-4">
91
+ <p className="text-foreground text-sm font-medium">{nodeLabel} Settings</p>
92
92
  </div>
93
93
 
94
94
  <div className="flex-1 overflow-y-auto">
@@ -104,14 +104,14 @@ export function NodeSettings({
104
104
  </div>
105
105
  </div>
106
106
 
107
- <div className="p-4 border-t border-border space-y-2">
107
+ <div className="border-border space-y-2 border-t p-4">
108
108
  <p className={SECTION_HEADING_CLASS}>Actions</p>
109
109
  <div className="flex gap-2">
110
110
  <button
111
111
  type="button"
112
112
  onClick={() => onMoveNodeUp(node.id)}
113
113
  aria-label="Move up"
114
- className="flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm bg-background border border-input rounded-md hover:bg-accent transition-colors"
114
+ className="bg-background border-input hover:bg-accent flex flex-1 items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-sm transition-colors"
115
115
  >
116
116
  <ArrowUp size={14} />
117
117
  Up
@@ -120,7 +120,7 @@ export function NodeSettings({
120
120
  type="button"
121
121
  onClick={() => onMoveNodeDown(node.id)}
122
122
  aria-label="Move down"
123
- className="flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm bg-background border border-input rounded-md hover:bg-accent transition-colors"
123
+ className="bg-background border-input hover:bg-accent flex flex-1 items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-sm transition-colors"
124
124
  >
125
125
  <ArrowDown size={14} />
126
126
  Down
@@ -129,7 +129,7 @@ export function NodeSettings({
129
129
  <button
130
130
  type="button"
131
131
  onClick={() => onDuplicateNode(node.id)}
132
- className="w-full flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium bg-background border border-input rounded-md hover:bg-accent transition-colors"
132
+ className="bg-background border-input hover:bg-accent flex w-full items-center justify-center gap-2 rounded-md border px-3 py-2 text-sm font-medium transition-colors"
133
133
  >
134
134
  <Copy size={14} />
135
135
  Duplicate
@@ -138,10 +138,10 @@ export function NodeSettings({
138
138
  type="button"
139
139
  onClick={handleDelete}
140
140
  onBlur={() => setConfirmDelete(false)}
141
- className={`w-full flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-md transition-colors ${
141
+ className={`flex w-full items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors ${
142
142
  confirmDelete
143
143
  ? 'bg-destructive text-destructive-foreground'
144
- : 'bg-background border border-destructive text-destructive hover:bg-destructive/10'
144
+ : 'bg-background border-destructive text-destructive hover:bg-destructive/10 border'
145
145
  }`}
146
146
  >
147
147
  <Trash2 size={14} />
@@ -172,7 +172,7 @@ function SectionFields({
172
172
  type="color"
173
173
  value={s.background ?? '#ffffff'}
174
174
  onChange={(e) => updateSetting('background', e.target.value)}
175
- className="h-9 w-9 rounded-md border border-input cursor-pointer"
175
+ className="border-input h-9 w-9 cursor-pointer rounded-md border"
176
176
  />
177
177
  <input
178
178
  type="text"
@@ -230,14 +230,14 @@ function SectionFields({
230
230
 
231
231
  <p className={SECTION_HEADING_CLASS}>Attributes</p>
232
232
  <div className="flex items-center justify-between">
233
- <label className="text-sm font-medium text-foreground">Visibility</label>
233
+ <label className="text-foreground text-sm font-medium">Visibility</label>
234
234
  <SwitchPrimitive.Root
235
235
  checked={s.visibility !== 'hidden'}
236
236
  onCheckedChange={(checked) => updateSetting('visibility', checked ? 'visible' : 'hidden')}
237
- className="w-9 h-5 bg-input rounded-full relative data-[state=checked]:bg-primary transition-colors"
237
+ className="bg-input data-[state=checked]:bg-primary relative h-5 w-9 rounded-full transition-colors"
238
238
  aria-label="Section visibility"
239
239
  >
240
- <SwitchPrimitive.Thumb className="block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" />
240
+ <SwitchPrimitive.Thumb className="bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[18px]" />
241
241
  </SwitchPrimitive.Root>
242
242
  </div>
243
243
  <div>
@@ -265,7 +265,7 @@ function SectionFields({
265
265
  <button
266
266
  type="button"
267
267
  onClick={() => onAddRow(node.id)}
268
- className="w-full flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
268
+ className="bg-primary text-primary-foreground hover:bg-primary/90 flex w-full items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors"
269
269
  >
270
270
  <Plus size={14} />
271
271
  Add Row
@@ -308,7 +308,7 @@ function ContainerFields({
308
308
  type="button"
309
309
  onClick={() => updateSetting('alignment', align)}
310
310
  aria-label={`Align ${align}`}
311
- className={`flex-1 flex items-center justify-center py-2 rounded-md border transition-colors ${
311
+ className={`flex flex-1 items-center justify-center rounded-md border py-2 transition-colors ${
312
312
  s.alignment === align
313
313
  ? 'bg-primary text-primary-foreground border-primary'
314
314
  : 'bg-background border-input hover:bg-accent'
@@ -373,7 +373,7 @@ function RowFields({
373
373
  type="button"
374
374
  onClick={() => updateSetting('verticalAlign', align)}
375
375
  aria-label={`Align ${align}`}
376
- className={`flex-1 flex items-center justify-center py-2 rounded-md border text-xs transition-colors ${
376
+ className={`flex flex-1 items-center justify-center rounded-md border py-2 text-xs transition-colors ${
377
377
  s.verticalAlign === align
378
378
  ? 'bg-primary text-primary-foreground border-primary'
379
379
  : 'bg-background border-input hover:bg-accent'
@@ -388,25 +388,25 @@ function RowFields({
388
388
 
389
389
  <p className={SECTION_HEADING_CLASS}>Mobile</p>
390
390
  <div className="flex items-center justify-between">
391
- <label className="text-sm font-medium text-foreground">Reverse on Mobile</label>
391
+ <label className="text-foreground text-sm font-medium">Reverse on Mobile</label>
392
392
  <SwitchPrimitive.Root
393
393
  checked={!!s.reverseOnMobile}
394
394
  onCheckedChange={(checked) => updateSetting('reverseOnMobile', checked)}
395
- className="w-9 h-5 bg-input rounded-full relative data-[state=checked]:bg-primary transition-colors"
395
+ className="bg-input data-[state=checked]:bg-primary relative h-5 w-9 rounded-full transition-colors"
396
396
  aria-label="Reverse column order on mobile"
397
397
  >
398
- <SwitchPrimitive.Thumb className="block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" />
398
+ <SwitchPrimitive.Thumb className="bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[18px]" />
399
399
  </SwitchPrimitive.Root>
400
400
  </div>
401
401
  <div className="flex items-center justify-between">
402
- <label className="text-sm font-medium text-foreground">Wrap on Mobile</label>
402
+ <label className="text-foreground text-sm font-medium">Wrap on Mobile</label>
403
403
  <SwitchPrimitive.Root
404
404
  checked={!!s.wrapOnMobile}
405
405
  onCheckedChange={(checked) => updateSetting('wrapOnMobile', checked)}
406
- className="w-9 h-5 bg-input rounded-full relative data-[state=checked]:bg-primary transition-colors"
406
+ className="bg-input data-[state=checked]:bg-primary relative h-5 w-9 rounded-full transition-colors"
407
407
  aria-label="Wrap columns on mobile"
408
408
  >
409
- <SwitchPrimitive.Thumb className="block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" />
409
+ <SwitchPrimitive.Thumb className="bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[18px]" />
410
410
  </SwitchPrimitive.Root>
411
411
  </div>
412
412
 
@@ -417,14 +417,14 @@ function RowFields({
417
417
  key={preset.label}
418
418
  type="button"
419
419
  onClick={() => updateSetting('__columnPreset', preset.widths)}
420
- className="px-2 py-2 rounded-md border border-input bg-background hover:bg-accent transition-colors"
420
+ className="border-input bg-background hover:bg-accent rounded-md border px-2 py-2 transition-colors"
421
421
  >
422
- <div className="flex gap-0.5 h-4">
422
+ <div className="flex h-4 gap-0.5">
423
423
  {preset.widths.map((w, i) => (
424
424
  <div key={i} className="bg-muted-foreground/30 rounded-sm" style={{ flex: w }} />
425
425
  ))}
426
426
  </div>
427
- <p className="text-xs text-muted-foreground mt-1 text-center">
427
+ <p className="text-muted-foreground mt-1 text-center text-xs">
428
428
  {preset.widths.join(' | ')}
429
429
  </p>
430
430
  </button>
@@ -470,7 +470,7 @@ function ColumnFields({
470
470
  type="button"
471
471
  onClick={() => updateSetting('verticalAlign', align)}
472
472
  aria-label={`Align ${align}`}
473
- className={`flex-1 flex items-center justify-center py-2 rounded-md border transition-colors ${
473
+ className={`flex flex-1 items-center justify-center rounded-md border py-2 transition-colors ${
474
474
  s.verticalAlign === align
475
475
  ? 'bg-primary text-primary-foreground border-primary'
476
476
  : 'bg-background border-input hover:bg-accent'
@@ -499,7 +499,7 @@ function ColumnFields({
499
499
  type="color"
500
500
  value={s.background ?? '#ffffff'}
501
501
  onChange={(e) => updateSetting('background', e.target.value)}
502
- className="h-9 w-9 rounded-md border border-input cursor-pointer"
502
+ className="border-input h-9 w-9 cursor-pointer rounded-md border"
503
503
  />
504
504
  <input
505
505
  type="text"
@@ -184,20 +184,20 @@ export function PageBuilder({ documentId, collectionSlug, config, onNavigate }:
184
184
 
185
185
  if (loading) {
186
186
  return (
187
- <div className="h-full flex items-center justify-center bg-background">
188
- <Loader2 className="animate-spin text-muted-foreground" size={24} />
187
+ <div className="bg-background flex h-full items-center justify-center">
188
+ <Loader2 className="text-muted-foreground animate-spin" size={24} />
189
189
  </div>
190
190
  )
191
191
  }
192
192
 
193
193
  if (loadError) {
194
194
  return (
195
- <div className="h-full flex items-center justify-center bg-background">
196
- <div className="flex items-center gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-4 max-w-md">
195
+ <div className="bg-background flex h-full items-center justify-center">
196
+ <div className="border-destructive/30 bg-destructive/5 flex max-w-md items-center gap-3 rounded-lg border p-4">
197
197
  <AlertTriangle className="text-destructive shrink-0" size={20} />
198
198
  <div>
199
- <p className="text-sm font-medium text-foreground">Failed to load page</p>
200
- <p className="text-sm text-muted-foreground mt-1">{loadError}</p>
199
+ <p className="text-foreground text-sm font-medium">Failed to load page</p>
200
+ <p className="text-muted-foreground mt-1 text-sm">{loadError}</p>
201
201
  </div>
202
202
  </div>
203
203
  </div>
@@ -226,7 +226,7 @@ export function PageBuilder({ documentId, collectionSlug, config, onNavigate }:
226
226
 
227
227
  return (
228
228
  <ErrorBoundary>
229
- <div className="h-full flex flex-col bg-background overflow-hidden">
229
+ <div className="bg-background flex h-full flex-col overflow-hidden">
230
230
  <BuilderToolbar
231
231
  collectionSlug={collectionSlug}
232
232
  pageSettings={pageSettings}
@@ -246,15 +246,15 @@ export function PageBuilder({ documentId, collectionSlug, config, onNavigate }:
246
246
  onOpenAI={() => setAiDialogOpen(true)}
247
247
  />
248
248
 
249
- <div className="flex-1 flex overflow-hidden">
249
+ <div className="flex flex-1 overflow-hidden">
250
250
  {/* Canvas area */}
251
- <div className="flex-1 overflow-auto bg-muted">
251
+ <div className="bg-muted flex-1 overflow-auto">
252
252
  <div
253
253
  className="mx-auto h-full max-w-full transition-all duration-200"
254
254
  style={{ width: canvasWidth }}
255
255
  >
256
256
  <div
257
- className={`h-full bg-background page-builder-canvas-shell ${isConstrained ? 'shadow-lg border-x border-border' : ''}`}
257
+ className={`bg-background page-builder-canvas-shell h-full ${isConstrained ? 'border-border border-x shadow-lg' : ''}`}
258
258
  style={canvasShellStyle}
259
259
  >
260
260
  <BuilderCanvas
@@ -269,7 +269,7 @@ export function PageBuilder({ documentId, collectionSlug, config, onNavigate }:
269
269
  </div>
270
270
 
271
271
  {/* Context panel */}
272
- <div className="w-[35%] min-w-[280px] max-w-[420px] border-l border-border bg-card overflow-y-auto">
272
+ <div className="border-border bg-card w-[35%] max-w-[420px] min-w-[280px] overflow-y-auto border-l">
273
273
  <ContextPanel
274
274
  activeTab={activeTab}
275
275
  onTabChange={setActiveTab}
@@ -79,8 +79,8 @@ export function PageSettingsEditor({ settings, onChange }: PageSettingsProps) {
79
79
  <p className={SECTION_HEADING_CLASS}>SEO</p>
80
80
 
81
81
  <div>
82
- <div className="flex items-center justify-between mb-1">
83
- <label className="text-sm font-medium text-foreground">Meta Title</label>
82
+ <div className="mb-1 flex items-center justify-between">
83
+ <label className="text-foreground text-sm font-medium">Meta Title</label>
84
84
  <span
85
85
  className={`text-xs ${
86
86
  metaTitleLength > 60 ? 'text-destructive' : 'text-muted-foreground'
@@ -100,8 +100,8 @@ export function PageSettingsEditor({ settings, onChange }: PageSettingsProps) {
100
100
  </div>
101
101
 
102
102
  <div>
103
- <div className="flex items-center justify-between mb-1">
104
- <label className="text-sm font-medium text-foreground">Meta Description</label>
103
+ <div className="mb-1 flex items-center justify-between">
104
+ <label className="text-foreground text-sm font-medium">Meta Description</label>
105
105
  <span
106
106
  className={`text-xs ${
107
107
  metaDescLength > 160 ? 'text-destructive' : 'text-muted-foreground'
@@ -23,7 +23,7 @@ export function PageTemplates({ onNavigate }: PageTemplatesProps) {
23
23
  if (loading) {
24
24
  return (
25
25
  <div className="flex h-64 items-center justify-center p-4" role="status" aria-live="polite">
26
- <Loader2 className="h-6 w-6 animate-spin text-primary" />
26
+ <Loader2 className="text-primary h-6 w-6 animate-spin" />
27
27
  <span className="sr-only">Loading page templates</span>
28
28
  </div>
29
29
  )
@@ -32,13 +32,13 @@ export function PageTemplates({ onNavigate }: PageTemplatesProps) {
32
32
  return (
33
33
  <div className="p-4 pr-8">
34
34
  {error && (
35
- <div className="mb-4 flex items-center gap-3 rounded-lg border border-border bg-card p-3">
36
- <AlertTriangle className="h-5 w-5 shrink-0 text-muted-foreground" />
37
- <span className="flex-1 text-sm text-foreground">{error}</span>
35
+ <div className="border-border bg-card mb-4 flex items-center gap-3 rounded-lg border p-3">
36
+ <AlertTriangle className="text-muted-foreground h-5 w-5 shrink-0" />
37
+ <span className="text-foreground flex-1 text-sm">{error}</span>
38
38
  <button
39
39
  type="button"
40
40
  onClick={refetch}
41
- className="rounded-md border border-border px-3 py-1 text-sm text-foreground hover:bg-accent"
41
+ className="border-border text-foreground hover:bg-accent rounded-md border px-3 py-1 text-sm"
42
42
  >
43
43
  Retry
44
44
  </button>
@@ -47,15 +47,15 @@ export function PageTemplates({ onNavigate }: PageTemplatesProps) {
47
47
 
48
48
  <div className="mb-4 flex items-center justify-between">
49
49
  <div>
50
- <h1 className="mb-1 text-2xl font-medium text-foreground">Page Templates</h1>
51
- <p className="text-sm text-muted-foreground">
50
+ <h1 className="text-foreground mb-1 text-2xl font-medium">Page Templates</h1>
51
+ <p className="text-muted-foreground text-sm">
52
52
  {templates.length} saved template{templates.length === 1 ? '' : 's'}
53
53
  </p>
54
54
  </div>
55
55
  <button
56
56
  type="button"
57
57
  onClick={refetch}
58
- className="inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-foreground hover:bg-accent"
58
+ className="border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium"
59
59
  >
60
60
  <RefreshCw className="h-4 w-4" />
61
61
  Refresh
@@ -63,16 +63,16 @@ export function PageTemplates({ onNavigate }: PageTemplatesProps) {
63
63
  </div>
64
64
 
65
65
  {templates.length === 0 ? (
66
- <div className="rounded-lg border border-border bg-card p-8 text-center">
67
- <Layers className="mx-auto mb-3 h-8 w-8 text-muted-foreground" />
68
- <h2 className="mb-1 text-lg font-medium text-foreground">No page templates yet</h2>
69
- <p className="mb-4 text-sm text-muted-foreground">
66
+ <div className="border-border bg-card rounded-lg border p-8 text-center">
67
+ <Layers className="text-muted-foreground mx-auto mb-3 h-8 w-8" />
68
+ <h2 className="text-foreground mb-1 text-lg font-medium">No page templates yet</h2>
69
+ <p className="text-muted-foreground mb-4 text-sm">
70
70
  Built-in templates are seeded by the CMS when the templates API is available.
71
71
  </p>
72
72
  <button
73
73
  type="button"
74
74
  onClick={() => onNavigate?.('/saved-sections')}
75
- className="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90"
75
+ className="bg-primary text-primary-foreground rounded-md px-4 py-2 text-sm font-medium hover:opacity-90"
76
76
  >
77
77
  View Saved Sections
78
78
  </button>
@@ -80,23 +80,23 @@ export function PageTemplates({ onNavigate }: PageTemplatesProps) {
80
80
  ) : (
81
81
  <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
82
82
  {templates.map((template) => (
83
- <div key={template.id} className="rounded-lg border border-border bg-card p-4">
83
+ <div key={template.id} className="border-border bg-card rounded-lg border p-4">
84
84
  <div className="mb-3 flex items-start justify-between gap-3">
85
85
  <div>
86
- <h2 className="text-base font-medium text-foreground">
86
+ <h2 className="text-foreground text-base font-medium">
87
87
  {template.name ?? 'Untitled template'}
88
88
  </h2>
89
- <p className="mt-1 text-sm text-muted-foreground">
89
+ <p className="text-muted-foreground mt-1 text-sm">
90
90
  {template.description ?? 'No description provided.'}
91
91
  </p>
92
92
  </div>
93
93
  {template.builtIn && (
94
- <span className="rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground">
94
+ <span className="bg-muted text-muted-foreground rounded-full px-2 py-0.5 text-xs">
95
95
  Built-in
96
96
  </span>
97
97
  )}
98
98
  </div>
99
- <div className="flex items-center justify-between text-sm text-muted-foreground">
99
+ <div className="text-muted-foreground flex items-center justify-between text-sm">
100
100
  <span>{template.category ?? 'content'}</span>
101
101
  <span>
102
102
  {template.updatedAt ? new Date(template.updatedAt).toLocaleDateString() : ''}
@@ -54,11 +54,11 @@ function getScoreLabel(score: number): string {
54
54
  function StatusIcon({ status }: { status: BuilderSEOCheck['status'] }) {
55
55
  switch (status) {
56
56
  case 'good':
57
- return <CheckCircle2 size={14} className="text-green-500 shrink-0" />
57
+ return <CheckCircle2 size={14} className="shrink-0 text-green-500" />
58
58
  case 'warning':
59
- return <AlertCircle size={14} className="text-amber-500 shrink-0" />
59
+ return <AlertCircle size={14} className="shrink-0 text-amber-500" />
60
60
  case 'error':
61
- return <XCircle size={14} className="text-red-500 shrink-0" />
61
+ return <XCircle size={14} className="shrink-0 text-red-500" />
62
62
  }
63
63
  }
64
64
 
@@ -110,15 +110,15 @@ function ScoreSummary({ checks }: { checks: BuilderSEOCheck[] }) {
110
110
  <div className="flex flex-col gap-1">
111
111
  <div className="flex items-center gap-1.5">
112
112
  <CheckCircle2 size={12} className="text-green-500" />
113
- <span className="text-xs text-muted-foreground">{passed} passed</span>
113
+ <span className="text-muted-foreground text-xs">{passed} passed</span>
114
114
  </div>
115
115
  <div className="flex items-center gap-1.5">
116
116
  <AlertCircle size={12} className="text-amber-500" />
117
- <span className="text-xs text-muted-foreground">{warnings} warnings</span>
117
+ <span className="text-muted-foreground text-xs">{warnings} warnings</span>
118
118
  </div>
119
119
  <div className="flex items-center gap-1.5">
120
120
  <XCircle size={12} className="text-red-500" />
121
- <span className="text-xs text-muted-foreground">{errors} issues</span>
121
+ <span className="text-muted-foreground text-xs">{errors} issues</span>
122
122
  </div>
123
123
  </div>
124
124
  )
@@ -138,16 +138,16 @@ function CollapsibleSection({
138
138
  children: React.ReactNode
139
139
  }) {
140
140
  return (
141
- <div className="border-b border-border last:border-b-0">
141
+ <div className="border-border border-b last:border-b-0">
142
142
  <button
143
143
  type="button"
144
- className="w-full text-left px-4 py-3 flex items-center justify-between hover:bg-muted/50 transition-colors"
144
+ className="hover:bg-muted/50 flex w-full items-center justify-between px-4 py-3 text-left transition-colors"
145
145
  onClick={onToggle}
146
146
  aria-expanded={expanded}
147
147
  >
148
148
  <div className="flex items-center gap-2">
149
149
  <Icon size={14} className="text-muted-foreground" />
150
- <span className="text-xs font-medium text-foreground">{title}</span>
150
+ <span className="text-foreground text-xs font-medium">{title}</span>
151
151
  </div>
152
152
  {expanded ? (
153
153
  <ChevronUp size={14} className="text-muted-foreground" />
@@ -167,8 +167,8 @@ function SEOChecksList({ checks }: { checks: BuilderSEOCheck[] }) {
167
167
  <div key={check.id} className="flex items-start gap-2">
168
168
  <StatusIcon status={check.status} />
169
169
  <div className="flex flex-col">
170
- <span className="text-xs font-medium text-foreground">{check.label}</span>
171
- <span className="text-xs text-muted-foreground">{check.detail}</span>
170
+ <span className="text-foreground text-xs font-medium">{check.label}</span>
171
+ <span className="text-muted-foreground text-xs">{check.detail}</span>
172
172
  </div>
173
173
  </div>
174
174
  ))}
@@ -186,48 +186,48 @@ function ReadabilityGrid({ readability }: { readability: BuilderReadabilityResul
186
186
 
187
187
  return (
188
188
  <div className="grid grid-cols-2 gap-3">
189
- <div className="bg-muted/50 rounded-md p-3 flex flex-col gap-1">
189
+ <div className="bg-muted/50 flex flex-col gap-1 rounded-md p-3">
190
190
  <div className="flex items-center gap-1.5">
191
191
  <BarChart3 size={12} className="text-muted-foreground" />
192
- <span className="text-xs text-muted-foreground">Flesch Score</span>
192
+ <span className="text-muted-foreground text-xs">Flesch Score</span>
193
193
  </div>
194
194
  <span className={`text-sm font-medium ${getScoreColor(readability.fleschScore)}`}>
195
195
  {readability.fleschScore}
196
196
  </span>
197
- <span className="text-xs text-muted-foreground">{fleschLabel}</span>
197
+ <span className="text-muted-foreground text-xs">{fleschLabel}</span>
198
198
  </div>
199
199
 
200
- <div className="bg-muted/50 rounded-md p-3 flex flex-col gap-1">
200
+ <div className="bg-muted/50 flex flex-col gap-1 rounded-md p-3">
201
201
  <div className="flex items-center gap-1.5">
202
202
  <Type size={12} className="text-muted-foreground" />
203
- <span className="text-xs text-muted-foreground">Word Count</span>
203
+ <span className="text-muted-foreground text-xs">Word Count</span>
204
204
  </div>
205
- <span className="text-sm font-medium text-foreground">{readability.wordCount}</span>
206
- <span className="text-xs text-muted-foreground">
205
+ <span className="text-foreground text-sm font-medium">{readability.wordCount}</span>
206
+ <span className="text-muted-foreground text-xs">
207
207
  {readability.wordCount >= 300 ? 'Good length' : 'Short'}
208
208
  </span>
209
209
  </div>
210
210
 
211
- <div className="bg-muted/50 rounded-md p-3 flex flex-col gap-1">
211
+ <div className="bg-muted/50 flex flex-col gap-1 rounded-md p-3">
212
212
  <div className="flex items-center gap-1.5">
213
213
  <FileText size={12} className="text-muted-foreground" />
214
- <span className="text-xs text-muted-foreground">Avg Sentence</span>
214
+ <span className="text-muted-foreground text-xs">Avg Sentence</span>
215
215
  </div>
216
- <span className="text-sm font-medium text-foreground">
216
+ <span className="text-foreground text-sm font-medium">
217
217
  {readability.avgSentenceLength} words
218
218
  </span>
219
- <span className="text-xs text-muted-foreground">
219
+ <span className="text-muted-foreground text-xs">
220
220
  {readability.avgSentenceLength <= 20 ? 'Good' : 'Long'}
221
221
  </span>
222
222
  </div>
223
223
 
224
- <div className="bg-muted/50 rounded-md p-3 flex flex-col gap-1">
224
+ <div className="bg-muted/50 flex flex-col gap-1 rounded-md p-3">
225
225
  <div className="flex items-center gap-1.5">
226
226
  <Clock size={12} className="text-muted-foreground" />
227
- <span className="text-xs text-muted-foreground">Reading Time</span>
227
+ <span className="text-muted-foreground text-xs">Reading Time</span>
228
228
  </div>
229
- <span className="text-sm font-medium text-foreground">{readability.readingTime} min</span>
230
- <span className="text-xs text-muted-foreground">~{readability.wordCount} words</span>
229
+ <span className="text-foreground text-sm font-medium">{readability.readingTime} min</span>
230
+ <span className="text-muted-foreground text-xs">~{readability.wordCount} words</span>
231
231
  </div>
232
232
  </div>
233
233
  )
@@ -240,8 +240,8 @@ function PerBlockHints({ hints }: { hints: BuilderSEOCheck[] }) {
240
240
  <div key={`${hint.id}-${index}`} className="flex items-start gap-2">
241
241
  <StatusIcon status={hint.status} />
242
242
  <div className="flex flex-col">
243
- <span className="text-xs font-medium text-foreground">{hint.label}</span>
244
- <span className="text-xs text-muted-foreground">{hint.detail}</span>
243
+ <span className="text-foreground text-xs font-medium">{hint.label}</span>
244
+ <span className="text-muted-foreground text-xs">{hint.detail}</span>
245
245
  </div>
246
246
  </div>
247
247
  ))}
@@ -263,7 +263,7 @@ function BasicSEOFields({
263
263
  <div className="flex flex-col gap-4">
264
264
  <div className="flex flex-col gap-1.5">
265
265
  <div className="flex items-center justify-between">
266
- <label className="text-xs font-medium text-foreground">Meta Title</label>
266
+ <label className="text-foreground text-xs font-medium">Meta Title</label>
267
267
  <span
268
268
  className={`text-xs ${metaTitleLength > 60 ? 'text-red-500' : metaTitleLength > 0 ? 'text-muted-foreground' : 'text-muted-foreground'}`}
269
269
  >
@@ -275,13 +275,13 @@ function BasicSEOFields({
275
275
  value={pageSettings.metaTitle || ''}
276
276
  onChange={(e) => onPageSettingsChange({ metaTitle: e.target.value })}
277
277
  placeholder="Page title for search engines"
278
- className="w-full px-3 py-2 text-sm bg-input-background border border-border rounded-md text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary"
278
+ className="bg-input-background border-border text-foreground placeholder:text-muted-foreground focus:ring-primary w-full rounded-md border px-3 py-2 text-sm focus:ring-1 focus:outline-none"
279
279
  />
280
280
  </div>
281
281
 
282
282
  <div className="flex flex-col gap-1.5">
283
283
  <div className="flex items-center justify-between">
284
- <label className="text-xs font-medium text-foreground">Meta Description</label>
284
+ <label className="text-foreground text-xs font-medium">Meta Description</label>
285
285
  <span
286
286
  className={`text-xs ${metaDescLength > 160 ? 'text-red-500' : metaDescLength > 0 ? 'text-muted-foreground' : 'text-muted-foreground'}`}
287
287
  >
@@ -293,18 +293,18 @@ function BasicSEOFields({
293
293
  onChange={(e) => onPageSettingsChange({ metaDescription: e.target.value })}
294
294
  placeholder="Brief description of the page content"
295
295
  rows={3}
296
- className="w-full px-3 py-2 text-sm bg-input-background border border-border rounded-md text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary resize-none"
296
+ className="bg-input-background border-border text-foreground placeholder:text-muted-foreground focus:ring-primary w-full resize-none rounded-md border px-3 py-2 text-sm focus:ring-1 focus:outline-none"
297
297
  />
298
298
  </div>
299
299
 
300
300
  <div className="flex flex-col gap-1.5">
301
- <label className="text-xs font-medium text-foreground">Focus Keyphrase</label>
301
+ <label className="text-foreground text-xs font-medium">Focus Keyphrase</label>
302
302
  <input
303
303
  type="text"
304
304
  value={pageSettings.focusKeyphrase || ''}
305
305
  onChange={(e) => onPageSettingsChange({ focusKeyphrase: e.target.value })}
306
306
  placeholder="Primary keyword or phrase"
307
- className="w-full px-3 py-2 text-sm bg-input-background border border-border rounded-md text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary"
307
+ className="bg-input-background border-border text-foreground placeholder:text-muted-foreground focus:ring-primary w-full rounded-md border px-3 py-2 text-sm focus:ring-1 focus:outline-none"
308
308
  />
309
309
  </div>
310
310
  </div>
@@ -317,12 +317,12 @@ function SearchPreview({ pageSettings }: { pageSettings: PageSettings }) {
317
317
  const slug = pageSettings.slug || 'page'
318
318
 
319
319
  return (
320
- <div className="bg-background rounded-md border border-border p-4">
321
- <p className="text-xs text-muted-foreground mb-2">Google Search Preview</p>
320
+ <div className="bg-background border-border rounded-md border p-4">
321
+ <p className="text-muted-foreground mb-2 text-xs">Google Search Preview</p>
322
322
  <div className="flex flex-col gap-1">
323
- <p className="text-sm text-primary truncate">{title}</p>
324
- <p className="text-xs text-green-600 truncate">example.com/{slug}</p>
325
- <p className="text-xs text-muted-foreground line-clamp-2">{description}</p>
323
+ <p className="text-primary truncate text-sm">{title}</p>
324
+ <p className="truncate text-xs text-green-600">example.com/{slug}</p>
325
+ <p className="text-muted-foreground line-clamp-2 text-xs">{description}</p>
326
326
  </div>
327
327
  </div>
328
328
  )
@@ -333,22 +333,22 @@ function SocialPreview({ pageSettings }: { pageSettings: PageSettings }) {
333
333
  const description = pageSettings.metaDescription || 'No description set'
334
334
 
335
335
  return (
336
- <div className="bg-background rounded-md border border-border overflow-hidden">
337
- <p className="text-xs text-muted-foreground px-4 pt-3 pb-2">Open Graph Preview</p>
336
+ <div className="bg-background border-border overflow-hidden rounded-md border">
337
+ <p className="text-muted-foreground px-4 pt-3 pb-2 text-xs">Open Graph Preview</p>
338
338
  {pageSettings.ogImage && (
339
- <div className="w-full h-32 bg-muted flex items-center justify-center overflow-hidden">
340
- <img src={pageSettings.ogImage} alt="OG preview" className="w-full h-full object-cover" />
339
+ <div className="bg-muted flex h-32 w-full items-center justify-center overflow-hidden">
340
+ <img src={pageSettings.ogImage} alt="OG preview" className="h-full w-full object-cover" />
341
341
  </div>
342
342
  )}
343
343
  {!pageSettings.ogImage && (
344
- <div className="w-full h-32 bg-muted flex items-center justify-center">
344
+ <div className="bg-muted flex h-32 w-full items-center justify-center">
345
345
  <Globe size={24} className="text-muted-foreground" />
346
346
  </div>
347
347
  )}
348
- <div className="p-3 flex flex-col gap-1">
349
- <p className="text-xs text-muted-foreground uppercase">example.com</p>
350
- <p className="text-sm font-medium text-foreground truncate">{title}</p>
351
- <p className="text-xs text-muted-foreground line-clamp-2">{description}</p>
348
+ <div className="flex flex-col gap-1 p-3">
349
+ <p className="text-muted-foreground text-xs uppercase">example.com</p>
350
+ <p className="text-foreground truncate text-sm font-medium">{title}</p>
351
+ <p className="text-muted-foreground line-clamp-2 text-xs">{description}</p>
352
352
  </div>
353
353
  </div>
354
354
  )
@@ -380,10 +380,10 @@ export function BuilderSEOPanel({
380
380
 
381
381
  if (!tree.children || tree.children.length === 0) {
382
382
  return (
383
- <div className="p-6 flex flex-col items-center justify-center text-center min-h-[200px]">
383
+ <div className="flex min-h-[200px] flex-col items-center justify-center p-6 text-center">
384
384
  <Search size={32} className="text-muted-foreground mb-3" />
385
- <p className="text-sm font-medium text-foreground mb-1">SEO Analysis</p>
386
- <p className="text-xs text-muted-foreground">
385
+ <p className="text-foreground mb-1 text-sm font-medium">SEO Analysis</p>
386
+ <p className="text-muted-foreground text-xs">
387
387
  Add content to your page to see SEO analysis
388
388
  </p>
389
389
  </div>
@@ -392,10 +392,10 @@ export function BuilderSEOPanel({
392
392
 
393
393
  return (
394
394
  <div className="flex flex-col">
395
- <div className="flex items-center gap-4 px-4 py-5 border-b border-border">
395
+ <div className="border-border flex items-center gap-4 border-b px-4 py-5">
396
396
  <ScoreRing score={analysis.score} />
397
397
  <div className="flex flex-col gap-1">
398
- <span className="text-xs font-medium text-foreground">
398
+ <span className="text-foreground text-xs font-medium">
399
399
  {getScoreLabel(analysis.score)}
400
400
  </span>
401
401
  <ScoreSummary checks={analysis.checks} />