@actuate-media/cms-admin 0.56.0 → 0.56.2

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 (216) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/__tests__/components/posts-badges.test.js +3 -3
  3. package/dist/__tests__/components/posts-badges.test.js.map +1 -1
  4. package/dist/actuate-admin.css +1 -1
  5. package/dist/components/AICoauthorBubbleMenu.js +2 -2
  6. package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
  7. package/dist/components/Breadcrumbs.js +2 -2
  8. package/dist/components/Breadcrumbs.js.map +1 -1
  9. package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
  10. package/dist/components/CoauthorResultPopover.js +1 -1
  11. package/dist/components/CoauthorResultPopover.js.map +1 -1
  12. package/dist/components/CommandPalette.d.ts.map +1 -1
  13. package/dist/components/CommandPalette.js +11 -11
  14. package/dist/components/CommandPalette.js.map +1 -1
  15. package/dist/components/CommentSidePanel.js +11 -11
  16. package/dist/components/CommentSidePanel.js.map +1 -1
  17. package/dist/components/ContentOverviewChart.js +2 -2
  18. package/dist/components/ContentOverviewChart.js.map +1 -1
  19. package/dist/components/FocalPointPicker.js +1 -1
  20. package/dist/components/FocalPointPicker.js.map +1 -1
  21. package/dist/components/LivePreview.d.ts.map +1 -1
  22. package/dist/components/LivePreview.js +5 -5
  23. package/dist/components/LivePreview.js.map +1 -1
  24. package/dist/components/LogoPlaceholder.js +1 -1
  25. package/dist/components/LogoPlaceholder.js.map +1 -1
  26. package/dist/components/MentionableTextarea.js +3 -3
  27. package/dist/components/MentionableTextarea.js.map +1 -1
  28. package/dist/components/NotificationBell.js +1 -1
  29. package/dist/components/NotificationBell.js.map +1 -1
  30. package/dist/components/OfflineStatus.js +8 -8
  31. package/dist/components/OfflineStatus.js.map +1 -1
  32. package/dist/components/PresenceChips.d.ts.map +1 -1
  33. package/dist/components/PresenceChips.js +10 -6
  34. package/dist/components/PresenceChips.js.map +1 -1
  35. package/dist/components/SEOConfigPanel.d.ts.map +1 -1
  36. package/dist/components/SEOConfigPanel.js +10 -10
  37. package/dist/components/SEOConfigPanel.js.map +1 -1
  38. package/dist/components/SEOPanel.js +12 -12
  39. package/dist/components/SEOPanel.js.map +1 -1
  40. package/dist/components/SEOPerformance.d.ts.map +1 -1
  41. package/dist/components/SEOPerformance.js +3 -3
  42. package/dist/components/SEOPerformance.js.map +1 -1
  43. package/dist/components/TipTapEditor.js +6 -6
  44. package/dist/components/TipTapEditor.js.map +1 -1
  45. package/dist/components/pages/tag-badges.js +6 -6
  46. package/dist/components/pages/tag-badges.js.map +1 -1
  47. package/dist/components/posts/badges.d.ts +0 -4
  48. package/dist/components/posts/badges.d.ts.map +1 -1
  49. package/dist/components/posts/badges.js +28 -42
  50. package/dist/components/posts/badges.js.map +1 -1
  51. package/dist/components/ui/Badge.js +5 -5
  52. package/dist/components/ui/Badge.js.map +1 -1
  53. package/dist/components/ui/Toast.d.ts.map +1 -1
  54. package/dist/components/ui/Toast.js +4 -4
  55. package/dist/components/ui/Toast.js.map +1 -1
  56. package/dist/fields/ComponentBlockField.js +2 -2
  57. package/dist/fields/ComponentBlockField.js.map +1 -1
  58. package/dist/fields/FieldRenderer.js +1 -1
  59. package/dist/fields/FieldRenderer.js.map +1 -1
  60. package/dist/fields/PropInput.js +1 -1
  61. package/dist/fields/PropInput.js.map +1 -1
  62. package/dist/fields/RelationshipField.js +5 -5
  63. package/dist/fields/RelationshipField.js.map +1 -1
  64. package/dist/fields/ToggleField.js +1 -1
  65. package/dist/fields/ToggleField.js.map +1 -1
  66. package/dist/views/Dashboard.js +5 -5
  67. package/dist/views/Dashboard.js.map +1 -1
  68. package/dist/views/DocumentEdit.d.ts.map +1 -1
  69. package/dist/views/DocumentEdit.js +5 -5
  70. package/dist/views/DocumentEdit.js.map +1 -1
  71. package/dist/views/ForgotPassword.d.ts.map +1 -1
  72. package/dist/views/ForgotPassword.js +3 -2
  73. package/dist/views/ForgotPassword.js.map +1 -1
  74. package/dist/views/FormEditor.d.ts.map +1 -1
  75. package/dist/views/FormEditor.js +5 -5
  76. package/dist/views/FormEditor.js.map +1 -1
  77. package/dist/views/Login.d.ts.map +1 -1
  78. package/dist/views/Login.js +17 -17
  79. package/dist/views/Login.js.map +1 -1
  80. package/dist/views/PageEditor.d.ts.map +1 -1
  81. package/dist/views/PageEditor.js +2 -2
  82. package/dist/views/PageEditor.js.map +1 -1
  83. package/dist/views/Pages/PagesListView.js +6 -6
  84. package/dist/views/Pages/PagesListView.js.map +1 -1
  85. package/dist/views/Pages.d.ts.map +1 -1
  86. package/dist/views/Pages.js +16 -19
  87. package/dist/views/Pages.js.map +1 -1
  88. package/dist/views/ResetPassword.d.ts.map +1 -1
  89. package/dist/views/ResetPassword.js +3 -2
  90. package/dist/views/ResetPassword.js.map +1 -1
  91. package/dist/views/Settings.js +2 -2
  92. package/dist/views/Settings.js.map +1 -1
  93. package/dist/views/SetupWizard.d.ts.map +1 -1
  94. package/dist/views/SetupWizard.js +6 -5
  95. package/dist/views/SetupWizard.js.map +1 -1
  96. package/dist/views/page-builder/DesignScore.js +12 -12
  97. package/dist/views/page-builder/DesignScore.js.map +1 -1
  98. package/dist/views/page-builder/SEOPanel.js +9 -9
  99. package/dist/views/page-builder/SEOPanel.js.map +1 -1
  100. package/dist/views/page-editor/EditorCanvas.js +1 -1
  101. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  102. package/dist/views/page-editor/EditorTopBar.js +2 -2
  103. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  104. package/dist/views/page-editor/PagePreview.js +1 -1
  105. package/dist/views/page-editor/PagePreview.js.map +1 -1
  106. package/dist/views/page-editor/SectionInspector.js +1 -1
  107. package/dist/views/page-editor/SectionInspector.js.map +1 -1
  108. package/dist/views/page-editor/SitePreviewFrame.js +1 -1
  109. package/dist/views/page-editor/SitePreviewFrame.js.map +1 -1
  110. package/dist/views/page-editor/sections/ArticleBodySection.js +1 -1
  111. package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
  112. package/dist/views/page-editor/sections/AuthorBioSection.js +2 -2
  113. package/dist/views/page-editor/sections/AuthorBioSection.js.map +1 -1
  114. package/dist/views/page-editor/sections/ByTheNumbersSection.js +1 -1
  115. package/dist/views/page-editor/sections/ByTheNumbersSection.js.map +1 -1
  116. package/dist/views/page-editor/sections/CtaBannerSection.js +1 -1
  117. package/dist/views/page-editor/sections/CtaBannerSection.js.map +1 -1
  118. package/dist/views/page-editor/sections/EmbedSection.d.ts.map +1 -1
  119. package/dist/views/page-editor/sections/EmbedSection.js +1 -1
  120. package/dist/views/page-editor/sections/EmbedSection.js.map +1 -1
  121. package/dist/views/page-editor/sections/FeatureHighlightSection.d.ts.map +1 -1
  122. package/dist/views/page-editor/sections/FeatureHighlightSection.js +2 -2
  123. package/dist/views/page-editor/sections/FeatureHighlightSection.js.map +1 -1
  124. package/dist/views/page-editor/sections/GallerySection.d.ts.map +1 -1
  125. package/dist/views/page-editor/sections/GallerySection.js +1 -1
  126. package/dist/views/page-editor/sections/GallerySection.js.map +1 -1
  127. package/dist/views/page-editor/sections/HeroBannerSection.js +1 -1
  128. package/dist/views/page-editor/sections/HeroBannerSection.js.map +1 -1
  129. package/dist/views/page-editor/sections/MissionSection.d.ts.map +1 -1
  130. package/dist/views/page-editor/sections/MissionSection.js +1 -1
  131. package/dist/views/page-editor/sections/MissionSection.js.map +1 -1
  132. package/dist/views/page-editor/sections/PullQuoteSection.js +1 -1
  133. package/dist/views/page-editor/sections/PullQuoteSection.js.map +1 -1
  134. package/dist/views/page-editor/sections/RelatedPostsSection.js +1 -1
  135. package/dist/views/page-editor/sections/RelatedPostsSection.js.map +1 -1
  136. package/dist/views/page-editor/sections/SectionRenderer.js +1 -1
  137. package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
  138. package/dist/views/page-editor/sections/parts.js +6 -6
  139. package/dist/views/page-editor/sections/parts.js.map +1 -1
  140. package/dist/views/post-editor/PostEditorCanvas.js +2 -2
  141. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  142. package/dist/views/post-editor/PostHeader.js +2 -2
  143. package/dist/views/post-editor/PostHeader.js.map +1 -1
  144. package/dist/views/post-editor/PostHeaderPanel.js +1 -1
  145. package/dist/views/post-editor/PostHeaderPanel.js.map +1 -1
  146. package/dist/views/post-editor/PostPreview.js +1 -1
  147. package/dist/views/post-editor/PostPreview.js.map +1 -1
  148. package/dist/views/profile/AccountSecurity.js +1 -1
  149. package/dist/views/profile/AccountSecurity.js.map +1 -1
  150. package/dist/views/settings/components.js +1 -1
  151. package/dist/views/settings/components.js.map +1 -1
  152. package/package.json +2 -2
  153. package/src/__tests__/components/posts-badges.test.tsx +3 -3
  154. package/src/components/AICoauthorBubbleMenu.tsx +4 -4
  155. package/src/components/Breadcrumbs.tsx +5 -5
  156. package/src/components/CoauthorResultPopover.tsx +26 -23
  157. package/src/components/CommandPalette.tsx +41 -39
  158. package/src/components/CommentSidePanel.tsx +20 -20
  159. package/src/components/ContentOverviewChart.tsx +4 -4
  160. package/src/components/FocalPointPicker.tsx +2 -2
  161. package/src/components/LivePreview.tsx +20 -17
  162. package/src/components/LogoPlaceholder.tsx +1 -1
  163. package/src/components/MentionableTextarea.tsx +5 -5
  164. package/src/components/NotificationBell.tsx +10 -10
  165. package/src/components/OfflineStatus.tsx +8 -8
  166. package/src/components/PresenceChips.tsx +12 -8
  167. package/src/components/SEOConfigPanel.tsx +40 -38
  168. package/src/components/SEOPanel.tsx +15 -15
  169. package/src/components/SEOPerformance.tsx +25 -23
  170. package/src/components/TipTapEditor.tsx +7 -7
  171. package/src/components/pages/tag-badges.tsx +6 -6
  172. package/src/components/posts/badges.tsx +28 -46
  173. package/src/components/ui/Badge.tsx +5 -5
  174. package/src/components/ui/Toast.tsx +4 -5
  175. package/src/fields/ComponentBlockField.tsx +2 -2
  176. package/src/fields/FieldRenderer.tsx +1 -1
  177. package/src/fields/PropInput.tsx +1 -1
  178. package/src/fields/RelationshipField.tsx +5 -5
  179. package/src/fields/ToggleField.tsx +1 -1
  180. package/src/views/Dashboard.tsx +5 -5
  181. package/src/views/DocumentEdit.tsx +13 -11
  182. package/src/views/ForgotPassword.tsx +21 -18
  183. package/src/views/FormEditor.tsx +74 -69
  184. package/src/views/Login.tsx +45 -39
  185. package/src/views/PageEditor.tsx +26 -22
  186. package/src/views/Pages/PagesListView.tsx +6 -6
  187. package/src/views/Pages.tsx +64 -65
  188. package/src/views/ResetPassword.tsx +32 -29
  189. package/src/views/Settings.tsx +2 -2
  190. package/src/views/SetupWizard.tsx +42 -33
  191. package/src/views/page-builder/DesignScore.tsx +12 -12
  192. package/src/views/page-builder/SEOPanel.tsx +12 -12
  193. package/src/views/page-editor/EditorCanvas.tsx +1 -1
  194. package/src/views/page-editor/EditorTopBar.tsx +2 -2
  195. package/src/views/page-editor/PagePreview.tsx +1 -1
  196. package/src/views/page-editor/SectionInspector.tsx +1 -1
  197. package/src/views/page-editor/SitePreviewFrame.tsx +1 -1
  198. package/src/views/page-editor/sections/ArticleBodySection.tsx +5 -5
  199. package/src/views/page-editor/sections/AuthorBioSection.tsx +6 -6
  200. package/src/views/page-editor/sections/ByTheNumbersSection.tsx +5 -5
  201. package/src/views/page-editor/sections/CtaBannerSection.tsx +1 -1
  202. package/src/views/page-editor/sections/EmbedSection.tsx +6 -4
  203. package/src/views/page-editor/sections/FeatureHighlightSection.tsx +7 -5
  204. package/src/views/page-editor/sections/GallerySection.tsx +6 -4
  205. package/src/views/page-editor/sections/HeroBannerSection.tsx +2 -2
  206. package/src/views/page-editor/sections/MissionSection.tsx +4 -2
  207. package/src/views/page-editor/sections/PullQuoteSection.tsx +4 -4
  208. package/src/views/page-editor/sections/RelatedPostsSection.tsx +5 -5
  209. package/src/views/page-editor/sections/SectionRenderer.tsx +2 -2
  210. package/src/views/page-editor/sections/parts.tsx +6 -6
  211. package/src/views/post-editor/PostEditorCanvas.tsx +4 -4
  212. package/src/views/post-editor/PostHeader.tsx +5 -5
  213. package/src/views/post-editor/PostHeaderPanel.tsx +1 -1
  214. package/src/views/post-editor/PostPreview.tsx +1 -1
  215. package/src/views/profile/AccountSecurity.tsx +1 -1
  216. package/src/views/settings/components.tsx +1 -1
@@ -155,13 +155,16 @@ export function LivePreview({
155
155
 
156
156
  if (!previewSrc) {
157
157
  return (
158
- <div className="flex h-full flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 bg-gray-50 p-8">
159
- <p className="text-center text-sm text-gray-500">
158
+ <div className="border-border bg-muted flex h-full flex-col items-center justify-center rounded-lg border border-dashed p-8">
159
+ <p className="text-muted-foreground text-center text-sm">
160
160
  {!documentId
161
161
  ? 'Save the document first to enable preview'
162
162
  : 'Configure a preview URL in the collection settings to enable live preview'}
163
163
  </p>
164
- <button onClick={onClose} className="mt-4 text-xs text-gray-400 hover:text-gray-600">
164
+ <button
165
+ onClick={onClose}
166
+ className="text-muted-foreground hover:text-muted-foreground mt-4 text-xs"
167
+ >
165
168
  Close Preview
166
169
  </button>
167
170
  </div>
@@ -169,8 +172,8 @@ export function LivePreview({
169
172
  }
170
173
 
171
174
  return (
172
- <div className="flex h-full flex-col border-l border-gray-200 bg-white">
173
- <div className="flex items-center justify-between border-b border-gray-200 bg-gray-50 px-3 py-2">
175
+ <div className="border-border bg-card flex h-full flex-col border-l">
176
+ <div className="border-border bg-muted flex items-center justify-between border-b px-3 py-2">
174
177
  <div className="flex items-center gap-1">
175
178
  {(
176
179
  [
@@ -182,14 +185,14 @@ export function LivePreview({
182
185
  <button
183
186
  key={vp}
184
187
  onClick={() => setViewport(vp)}
185
- className={`rounded p-1.5 ${viewport === vp ? 'bg-white text-blue-600 shadow-sm' : 'text-gray-400 hover:text-gray-600'}`}
188
+ className={`rounded p-1.5 ${viewport === vp ? 'bg-card text-primary shadow-sm' : 'text-muted-foreground hover:text-muted-foreground'}`}
186
189
  title={vp}
187
190
  >
188
191
  <Icon className="h-4 w-4" />
189
192
  </button>
190
193
  ))}
191
194
  <span
192
- className="ml-2 inline-flex items-center gap-1 rounded-full bg-white px-2 py-0.5 text-[10px] font-medium text-gray-600"
195
+ className="bg-card text-muted-foreground ml-2 inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium"
193
196
  title={
194
197
  streamStatus === 'connected'
195
198
  ? 'Live preview is streaming updates from the server.'
@@ -202,19 +205,19 @@ export function LivePreview({
202
205
  >
203
206
  {streamStatus === 'connected' ? (
204
207
  <>
205
- <Wifi className="h-3 w-3 text-green-600" aria-hidden /> Live
208
+ <Wifi className="text-success h-3 w-3" aria-hidden /> Live
206
209
  </>
207
210
  ) : streamStatus === 'connecting' ? (
208
211
  <>
209
- <Wifi className="h-3 w-3 animate-pulse text-blue-500" aria-hidden /> Connecting
212
+ <Wifi className="text-info h-3 w-3 animate-pulse" aria-hidden /> Connecting
210
213
  </>
211
214
  ) : streamStatus === 'offline' ? (
212
215
  <>
213
- <WifiOff className="h-3 w-3 text-amber-500" aria-hidden /> Reconnecting
216
+ <WifiOff className="text-warning h-3 w-3" aria-hidden /> Reconnecting
214
217
  </>
215
218
  ) : (
216
219
  <>
217
- <WifiOff className="h-3 w-3 text-gray-400" aria-hidden /> Idle
220
+ <WifiOff className="text-muted-foreground h-3 w-3" aria-hidden /> Idle
218
221
  </>
219
222
  )}
220
223
  </span>
@@ -222,21 +225,21 @@ export function LivePreview({
222
225
  <div className="flex items-center gap-1">
223
226
  <button
224
227
  onClick={handleRefresh}
225
- className="rounded p-1.5 text-gray-400 hover:text-gray-600"
228
+ className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
226
229
  title="Refresh"
227
230
  >
228
231
  <RefreshCw className="h-4 w-4" />
229
232
  </button>
230
233
  <button
231
234
  onClick={handleOpenExternal}
232
- className="rounded p-1.5 text-gray-400 hover:text-gray-600"
235
+ className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
233
236
  title="Open in new tab"
234
237
  >
235
238
  <ExternalLink className="h-4 w-4" />
236
239
  </button>
237
240
  <button
238
241
  onClick={onClose}
239
- className="rounded p-1.5 text-gray-400 hover:text-gray-600"
242
+ className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
240
243
  title="Close"
241
244
  >
242
245
  <X className="h-4 w-4" />
@@ -244,20 +247,20 @@ export function LivePreview({
244
247
  </div>
245
248
  </div>
246
249
 
247
- <div className="flex flex-1 justify-center overflow-auto bg-gray-100 p-4">
250
+ <div className="bg-muted flex flex-1 justify-center overflow-auto p-4">
248
251
  <div
249
252
  style={{ width: VIEWPORT_WIDTHS[viewport], maxWidth: '100%', transition: 'width 0.3s' }}
250
253
  className="relative"
251
254
  >
252
255
  {loading && (
253
- <div className="absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-white/80">
256
+ <div className="bg-card/80 absolute inset-0 z-10 flex items-center justify-center rounded-lg">
254
257
  <div className="h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600" />
255
258
  </div>
256
259
  )}
257
260
  <iframe
258
261
  ref={iframeRef}
259
262
  src={previewSrc}
260
- className="h-full w-full rounded-lg border border-gray-200 bg-white shadow-lg"
263
+ className="border-border bg-card h-full w-full rounded-lg border shadow-lg"
261
264
  style={{ minHeight: '600px' }}
262
265
  onLoad={() => setLoading(false)}
263
266
  title="Page Preview"
@@ -25,7 +25,7 @@ export function LogoPlaceholder({ tone, label }: LogoPlaceholderProps) {
25
25
  role="img"
26
26
  aria-label="Logo placeholder"
27
27
  title="Add a logo in Settings → Appearance"
28
- className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-lg border border-dashed border-gray-300 text-gray-400"
28
+ className="border-border text-muted-foreground mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-lg border border-dashed"
29
29
  >
30
30
  <ImagePlus className="h-6 w-6" aria-hidden="true" />
31
31
  </span>
@@ -283,11 +283,11 @@ export function MentionableTextarea({
283
283
  id={pickerId}
284
284
  role="listbox"
285
285
  aria-label="Mention a teammate"
286
- className="absolute top-full left-0 z-30 mt-1 max-h-56 w-64 overflow-y-auto rounded border border-gray-200 bg-white shadow-lg"
286
+ className="border-border bg-card absolute top-full left-0 z-30 mt-1 max-h-56 w-64 overflow-y-auto rounded border shadow-lg"
287
287
  data-testid={testId ? `${testId}-picker` : 'mention-picker'}
288
288
  >
289
289
  {picker.users.length === 0 ? (
290
- <p className="px-3 py-2 text-xs text-gray-500">
290
+ <p className="text-muted-foreground px-3 py-2 text-xs">
291
291
  {picker.query ? 'No matches' : 'Type a name…'}
292
292
  </p>
293
293
  ) : (
@@ -309,13 +309,13 @@ export function MentionableTextarea({
309
309
  onMouseEnter={() => setPicker((s) => ({ ...s, highlight: idx }))}
310
310
  className={`block w-full px-3 py-1.5 text-left text-xs ${
311
311
  idx === picker.highlight
312
- ? 'bg-blue-50 text-blue-900'
313
- : 'text-gray-800 hover:bg-gray-50'
312
+ ? 'bg-info/10 text-foreground'
313
+ : 'text-foreground hover:bg-accent'
314
314
  }`}
315
315
  data-testid={testId ? `${testId}-picker-row-${u.id}` : `mention-row-${u.id}`}
316
316
  >
317
317
  <div className="font-medium">{formatLabel(u)}</div>
318
- <div className="text-[10px] text-gray-500">{u.email}</div>
318
+ <div className="text-muted-foreground text-[10px]">{u.email}</div>
319
319
  </button>
320
320
  </li>
321
321
  ))}
@@ -246,7 +246,7 @@ export function NotificationBell({
246
246
  <div className={`relative ${className ?? ''}`} data-testid="notification-bell">
247
247
  <button
248
248
  type="button"
249
- className="relative rounded p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900"
249
+ className="text-muted-foreground hover:bg-accent hover:text-foreground relative rounded p-1.5"
250
250
  aria-label="Notifications"
251
251
  aria-haspopup="menu"
252
252
  aria-expanded={open}
@@ -256,7 +256,7 @@ export function NotificationBell({
256
256
  <BellIcon />
257
257
  {unread > 0 && (
258
258
  <span
259
- className="absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-600 px-1 text-[10px] font-medium text-white"
259
+ className="bg-destructive absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] font-medium text-white"
260
260
  data-testid="bell-badge"
261
261
  >
262
262
  {unread > 99 ? '99+' : unread}
@@ -266,14 +266,14 @@ export function NotificationBell({
266
266
  {open && (
267
267
  <div
268
268
  role="menu"
269
- className="absolute right-0 z-50 mt-1 w-80 rounded border border-gray-200 bg-white shadow-lg"
269
+ className="border-border bg-card absolute right-0 z-50 mt-1 w-80 rounded border shadow-lg"
270
270
  data-testid="bell-dropdown"
271
271
  >
272
272
  <header className="flex items-center justify-between border-b border-gray-100 px-3 py-2">
273
- <span className="text-sm font-medium text-gray-900">Notifications</span>
273
+ <span className="text-foreground text-sm font-medium">Notifications</span>
274
274
  <button
275
275
  type="button"
276
- className="text-xs text-gray-600 hover:text-gray-900 disabled:opacity-50"
276
+ className="text-muted-foreground hover:text-foreground text-xs disabled:opacity-50"
277
277
  onClick={handleMarkAll}
278
278
  disabled={unread === 0}
279
279
  data-testid="bell-mark-all"
@@ -283,9 +283,9 @@ export function NotificationBell({
283
283
  </header>
284
284
  <div className="max-h-80 overflow-y-auto" aria-busy={loading} data-testid="bell-list">
285
285
  {loading ? (
286
- <p className="px-3 py-2 text-xs text-gray-500">Loading…</p>
286
+ <p className="text-muted-foreground px-3 py-2 text-xs">Loading…</p>
287
287
  ) : items.length === 0 ? (
288
- <p className="px-3 py-2 text-xs text-gray-500">All caught up.</p>
288
+ <p className="text-muted-foreground px-3 py-2 text-xs">All caught up.</p>
289
289
  ) : (
290
290
  <ul>
291
291
  {items.map((n) => (
@@ -293,15 +293,15 @@ export function NotificationBell({
293
293
  <button
294
294
  type="button"
295
295
  role="menuitem"
296
- className={`block w-full px-3 py-2 text-left text-xs hover:bg-gray-50 ${
297
- n.readAt ? 'text-gray-500' : 'font-medium text-gray-900'
296
+ className={`hover:bg-accent block w-full px-3 py-2 text-left text-xs ${
297
+ n.readAt ? 'text-muted-foreground' : 'text-foreground font-medium'
298
298
  }`}
299
299
  onClick={() => handleClickRow(n)}
300
300
  data-testid={`bell-row-${n.id}`}
301
301
  data-read={n.readAt ? 'true' : 'false'}
302
302
  >
303
303
  <div>{notificationSummary(n)}</div>
304
- <div className="mt-0.5 text-[10px] text-gray-400">{n.createdAt}</div>
304
+ <div className="text-muted-foreground mt-0.5 text-[10px]">{n.createdAt}</div>
305
305
  </button>
306
306
  </li>
307
307
  ))}
@@ -51,17 +51,17 @@ export function OfflineStatus({ connection, offline }: OfflineStatusProps): Reac
51
51
  export type OfflineTone = 'good' | 'warn' | 'info' | 'bad'
52
52
 
53
53
  const TONE_CLASSES: Record<OfflineTone, string> = {
54
- good: 'bg-emerald-50 text-emerald-700',
55
- warn: 'bg-amber-50 text-amber-800',
56
- info: 'bg-blue-50 text-blue-700',
57
- bad: 'bg-red-50 text-red-700',
54
+ good: 'bg-success/10 text-emerald-700',
55
+ warn: 'bg-warning/10 text-warning',
56
+ info: 'bg-info/10 text-info',
57
+ bad: 'bg-destructive/10 text-destructive',
58
58
  }
59
59
 
60
60
  const DOT_CLASSES: Record<OfflineTone, string> = {
61
- good: 'bg-emerald-500',
62
- warn: 'bg-amber-500',
63
- info: 'bg-blue-500',
64
- bad: 'bg-red-500',
61
+ good: 'bg-success',
62
+ warn: 'bg-warning',
63
+ info: 'bg-info',
64
+ bad: 'bg-destructive',
65
65
  }
66
66
 
67
67
  /**
@@ -70,7 +70,7 @@ export function PresenceChips({
70
70
  >
71
71
  {status && <StatusPill status={status} />}
72
72
  {shown.length === 0 && status !== 'connecting' && (
73
- <span className="text-gray-500" data-testid="presence-empty">
73
+ <span className="text-muted-foreground" data-testid="presence-empty">
74
74
  You're the only one here
75
75
  </span>
76
76
  )}
@@ -79,7 +79,7 @@ export function PresenceChips({
79
79
  ))}
80
80
  {overflow > 0 && (
81
81
  <span
82
- className="rounded-full bg-gray-100 px-2 py-0.5 text-gray-700"
82
+ className="bg-muted text-foreground rounded-full px-2 py-0.5"
83
83
  data-testid="presence-overflow"
84
84
  >
85
85
  +{overflow}
@@ -91,14 +91,18 @@ export function PresenceChips({
91
91
 
92
92
  function StatusPill({ status }: { status: CollaborationStatus }) {
93
93
  const palette: Record<CollaborationStatus, { dot: string; label: string; text: string }> = {
94
- connected: { dot: 'bg-emerald-500', label: 'Live', text: 'text-emerald-700' },
95
- connecting: { dot: 'bg-amber-400 animate-pulse', label: 'Connecting', text: 'text-amber-700' },
96
- disconnected: { dot: 'bg-gray-300', label: 'Offline', text: 'text-gray-500' },
94
+ connected: { dot: 'bg-success', label: 'Live', text: 'text-emerald-700' },
95
+ connecting: { dot: 'bg-amber-400 animate-pulse', label: 'Connecting', text: 'text-warning' },
96
+ disconnected: {
97
+ dot: 'bg-muted-foreground/30',
98
+ label: 'Offline',
99
+ text: 'text-muted-foreground',
100
+ },
97
101
  }
98
102
  const cfg = palette[status]
99
103
  return (
100
104
  <span
101
- className={`inline-flex items-center gap-1 rounded-full bg-gray-50 px-2 py-0.5 ${cfg.text}`}
105
+ className={`bg-muted inline-flex items-center gap-1 rounded-full px-2 py-0.5 ${cfg.text}`}
102
106
  data-testid={`presence-status-${status}`}
103
107
  >
104
108
  <span className={`h-1.5 w-1.5 rounded-full ${cfg.dot}`} />
@@ -111,7 +115,7 @@ function Chip({ name, color, avatarUrl }: { name: string; color: string; avatarU
111
115
  const initials = nameToInitials(name)
112
116
  return (
113
117
  <span
114
- className="inline-flex items-center gap-1 rounded-full bg-white px-1.5 py-0.5 ring-1 ring-gray-200"
118
+ className="bg-card inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 ring-1 ring-gray-200"
115
119
  title={name}
116
120
  data-testid="presence-chip"
117
121
  >
@@ -131,7 +135,7 @@ function Chip({ name, color, avatarUrl }: { name: string; color: string; avatarU
131
135
  {initials}
132
136
  </span>
133
137
  )}
134
- <span className="max-w-[80px] truncate text-gray-700">{name}</span>
138
+ <span className="text-foreground max-w-[80px] truncate">{name}</span>
135
139
  </span>
136
140
  )
137
141
  }
@@ -192,7 +192,7 @@ export function SEOConfigPanel() {
192
192
 
193
193
  if (loading) {
194
194
  return (
195
- <div className="flex items-center gap-2 py-8 text-sm text-gray-600">
195
+ <div className="text-muted-foreground flex items-center gap-2 py-8 text-sm">
196
196
  <Loader2 className="h-4 w-4 animate-spin" /> Loading SEO defaults…
197
197
  </div>
198
198
  )
@@ -200,12 +200,12 @@ export function SEOConfigPanel() {
200
200
 
201
201
  if (error) {
202
202
  return (
203
- <div className="rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-700">
203
+ <div className="border-destructive/30 bg-destructive/10 text-destructive rounded-lg border p-4 text-sm">
204
204
  <div className="mb-2 font-medium">Failed to load SEO config</div>
205
205
  <div className="font-mono text-xs">{error}</div>
206
206
  <button
207
207
  onClick={() => void load()}
208
- className="mt-3 inline-flex items-center gap-1.5 rounded-md border border-red-300 bg-white px-3 py-1.5 text-xs font-medium text-red-700 hover:bg-red-100"
208
+ className="border-destructive bg-card text-destructive hover:bg-destructive/10 mt-3 inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-medium"
209
209
  >
210
210
  <RefreshCw className="h-3.5 w-3.5" /> Retry
211
211
  </button>
@@ -217,21 +217,23 @@ export function SEOConfigPanel() {
217
217
  <div className="space-y-6">
218
218
  <div className="flex items-start justify-between gap-4">
219
219
  <div>
220
- <p className="text-sm text-gray-600">
220
+ <p className="text-muted-foreground text-sm">
221
221
  Edit the SEO defaults that flow into{' '}
222
- <code className="rounded bg-gray-100 px-1 py-0.5 text-[11px]">/sitemap.xml</code>,{' '}
223
- <code className="rounded bg-gray-100 px-1 py-0.5 text-[11px]">/robots.txt</code>,{' '}
224
- <code className="rounded bg-gray-100 px-1 py-0.5 text-[11px]">/og.png</code>, and the{' '}
225
- <code className="rounded bg-gray-100 px-1 py-0.5 text-[11px]">/resolve</code> meta +
222
+ <code className="bg-muted rounded px-1 py-0.5 text-[11px]">/sitemap.xml</code>,{' '}
223
+ <code className="bg-muted rounded px-1 py-0.5 text-[11px]">/robots.txt</code>,{' '}
224
+ <code className="bg-muted rounded px-1 py-0.5 text-[11px]">/og.png</code>, and the{' '}
225
+ <code className="bg-muted rounded px-1 py-0.5 text-[11px]">/resolve</code> meta +
226
226
  JSON-LD response. Empty fields fall back to{' '}
227
- <code className="rounded bg-gray-100 px-1 py-0.5 text-[11px]">actuate.config.ts</code>.
227
+ <code className="bg-muted rounded px-1 py-0.5 text-[11px]">actuate.config.ts</code>.
228
228
  </p>
229
- {updatedAt && <p className="mt-1 text-xs text-gray-500">Last saved: {updatedAt}</p>}
229
+ {updatedAt && (
230
+ <p className="text-muted-foreground mt-1 text-xs">Last saved: {updatedAt}</p>
231
+ )}
230
232
  </div>
231
233
  <button
232
234
  onClick={handleSave}
233
235
  disabled={saving}
234
- className="inline-flex shrink-0 items-center gap-1.5 rounded-md bg-blue-600 px-3 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-blue-700 disabled:opacity-50"
236
+ className="bg-primary hover:bg-primary/90 inline-flex shrink-0 items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium text-white shadow-sm disabled:opacity-50"
235
237
  >
236
238
  {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
237
239
  Save SEO defaults
@@ -239,10 +241,10 @@ export function SEOConfigPanel() {
239
241
  </div>
240
242
 
241
243
  {/* Site-wide section */}
242
- <section className="rounded-lg border border-gray-200 bg-white">
243
- <header className="flex items-center gap-2 border-b border-gray-200 px-4 py-3">
244
- <Globe className="h-4 w-4 text-blue-600" />
245
- <h3 className="text-sm font-medium text-gray-900">Site-wide defaults</h3>
244
+ <section className="border-border bg-card rounded-lg border">
245
+ <header className="border-border flex items-center gap-2 border-b px-4 py-3">
246
+ <Globe className="text-primary h-4 w-4" />
247
+ <h3 className="text-foreground text-sm font-medium">Site-wide defaults</h3>
246
248
  </header>
247
249
  <div className="grid grid-cols-1 gap-4 p-4 md:grid-cols-2">
248
250
  <Field
@@ -330,11 +332,11 @@ export function SEOConfigPanel() {
330
332
  </section>
331
333
 
332
334
  {/* Per-collection section */}
333
- <section className="rounded-lg border border-gray-200 bg-white">
334
- <header className="flex items-center gap-2 border-b border-gray-200 px-4 py-3">
335
- <FileText className="h-4 w-4 text-blue-600" />
336
- <h3 className="text-sm font-medium text-gray-900">Per-collection defaults</h3>
337
- <span className="text-xs text-gray-500">
335
+ <section className="border-border bg-card rounded-lg border">
336
+ <header className="border-border flex items-center gap-2 border-b px-4 py-3">
337
+ <FileText className="text-primary h-4 w-4" />
338
+ <h3 className="text-foreground text-sm font-medium">Per-collection defaults</h3>
339
+ <span className="text-muted-foreground text-xs">
338
340
  — shown placeholders are the static defaults
339
341
  </span>
340
342
  </header>
@@ -346,14 +348,14 @@ export function SEOConfigPanel() {
346
348
  <div key={col.slug} className="p-4">
347
349
  <div className="mb-3 flex items-baseline justify-between gap-4">
348
350
  <div>
349
- <h4 className="text-sm font-medium text-gray-900">{col.label}</h4>
350
- <p className="text-xs text-gray-500">
351
- <code className="rounded bg-gray-100 px-1 py-0.5">{col.slug}</code>
351
+ <h4 className="text-foreground text-sm font-medium">{col.label}</h4>
352
+ <p className="text-muted-foreground text-xs">
353
+ <code className="bg-muted rounded px-1 py-0.5">{col.slug}</code>
352
354
  {col.urlPrefix !== undefined && (
353
355
  <>
354
356
  {' '}
355
357
  prefix:{' '}
356
- <code className="rounded bg-gray-100 px-1 py-0.5">/{col.urlPrefix}</code>
358
+ <code className="bg-muted rounded px-1 py-0.5">/{col.urlPrefix}</code>
357
359
  </>
358
360
  )}{' '}
359
361
  — {col.type}
@@ -414,7 +416,7 @@ export function SEOConfigPanel() {
414
416
  )
415
417
  })}
416
418
  {data?.collections.length === 0 && (
417
- <div className="p-4 text-sm text-gray-500">
419
+ <div className="text-muted-foreground p-4 text-sm">
418
420
  No collections configured in <code>actuate.config.ts</code>.
419
421
  </div>
420
422
  )}
@@ -425,7 +427,7 @@ export function SEOConfigPanel() {
425
427
  <button
426
428
  onClick={handleSave}
427
429
  disabled={saving}
428
- className="inline-flex items-center gap-1.5 rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 disabled:opacity-50"
430
+ className="bg-primary hover:bg-primary/90 inline-flex items-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium text-white shadow-sm disabled:opacity-50"
429
431
  >
430
432
  {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
431
433
  Save SEO defaults
@@ -465,15 +467,15 @@ function Field({
465
467
  }) {
466
468
  return (
467
469
  <div>
468
- <label className="mb-1 block text-xs font-medium text-gray-700">{label}</label>
470
+ <label className="text-foreground mb-1 block text-xs font-medium">{label}</label>
469
471
  <input
470
472
  type="text"
471
473
  value={value}
472
474
  placeholder={placeholder}
473
475
  onChange={(e) => onChange(e.target.value)}
474
- className="w-full rounded-md border border-gray-300 px-2.5 py-1.5 text-sm text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
476
+ className="border-border text-foreground focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border px-2.5 py-1.5 text-sm placeholder-gray-400 focus:ring-1 focus:outline-none"
475
477
  />
476
- {hint && <p className="mt-1 text-[11px] text-gray-500">{hint}</p>}
478
+ {hint && <p className="text-muted-foreground mt-1 text-[11px]">{hint}</p>}
477
479
  </div>
478
480
  )
479
481
  }
@@ -499,7 +501,7 @@ function NumberField({
499
501
  }) {
500
502
  return (
501
503
  <div>
502
- <label className="mb-1 block text-xs font-medium text-gray-700">{label}</label>
504
+ <label className="text-foreground mb-1 block text-xs font-medium">{label}</label>
503
505
  <input
504
506
  type="number"
505
507
  value={value ?? ''}
@@ -513,9 +515,9 @@ function NumberField({
513
515
  const n = Number(raw)
514
516
  if (Number.isFinite(n)) onChange(n)
515
517
  }}
516
- className="w-full rounded-md border border-gray-300 px-2.5 py-1.5 text-sm text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
518
+ className="border-border text-foreground focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border px-2.5 py-1.5 text-sm placeholder-gray-400 focus:ring-1 focus:outline-none"
517
519
  />
518
- {hint && <p className="mt-1 text-[11px] text-gray-500">{hint}</p>}
520
+ {hint && <p className="text-muted-foreground mt-1 text-[11px]">{hint}</p>}
519
521
  </div>
520
522
  )
521
523
  }
@@ -537,11 +539,11 @@ function Select({
537
539
  }) {
538
540
  return (
539
541
  <div>
540
- <label className="mb-1 block text-xs font-medium text-gray-700">{label}</label>
542
+ <label className="text-foreground mb-1 block text-xs font-medium">{label}</label>
541
543
  <select
542
544
  value={value}
543
545
  onChange={(e) => onChange(e.target.value)}
544
- className="w-full rounded-md border border-gray-300 bg-white px-2.5 py-1.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
546
+ className="border-border bg-card text-foreground focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-1 focus:outline-none"
545
547
  >
546
548
  {options.map((opt) => (
547
549
  <option key={opt} value={opt}>
@@ -549,7 +551,7 @@ function Select({
549
551
  </option>
550
552
  ))}
551
553
  </select>
552
- {hint && <p className="mt-1 text-[11px] text-gray-500">{hint}</p>}
554
+ {hint && <p className="text-muted-foreground mt-1 text-[11px]">{hint}</p>}
553
555
  </div>
554
556
  )
555
557
  }
@@ -566,16 +568,16 @@ function Toggle({
566
568
  hint?: string
567
569
  }) {
568
570
  return (
569
- <label className="flex cursor-pointer items-center gap-2 text-sm text-gray-700">
571
+ <label className="text-foreground flex cursor-pointer items-center gap-2 text-sm">
570
572
  <input
571
573
  type="checkbox"
572
574
  checked={checked}
573
575
  onChange={(e) => onChange(e.target.checked)}
574
- className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
576
+ className="border-border text-primary focus-visible:ring-ring/50 h-4 w-4 rounded"
575
577
  />
576
578
  <span>
577
579
  {label}
578
- {hint && <span className="ml-1 text-[11px] text-gray-500">— {hint}</span>}
580
+ {hint && <span className="text-muted-foreground ml-1 text-[11px]">— {hint}</span>}
579
581
  </span>
580
582
  </label>
581
583
  )
@@ -387,9 +387,9 @@ function computeOverallScore(checks: SEOCheck[]): number {
387
387
  }
388
388
 
389
389
  function StatusDot({ status }: { status: 'good' | 'ok' | 'bad' }) {
390
- if (status === 'good') return <CheckCircle2 className="h-4 w-4 shrink-0 text-green-500" />
391
- if (status === 'ok') return <AlertCircle className="h-4 w-4 shrink-0 text-amber-500" />
392
- return <XCircle className="h-4 w-4 shrink-0 text-red-500" />
390
+ if (status === 'good') return <CheckCircle2 className="text-success h-4 w-4 shrink-0" />
391
+ if (status === 'ok') return <AlertCircle className="text-warning h-4 w-4 shrink-0" />
392
+ return <XCircle className="text-destructive h-4 w-4 shrink-0" />
393
393
  }
394
394
 
395
395
  function ScoreRing({ score }: { score: number }) {
@@ -486,7 +486,7 @@ function ToggleSwitch({
486
486
  className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full transition-colors ${checked ? 'bg-[var(--primary)]' : 'bg-[var(--muted)]'}`}
487
487
  >
488
488
  <span
489
- className={`pointer-events-none mt-0.5 block h-5 w-5 rounded-full bg-white shadow-sm transition-transform ${checked ? 'translate-x-[22px]' : 'translate-x-0.5'}`}
489
+ className={`bg-card pointer-events-none mt-0.5 block h-5 w-5 rounded-full shadow-sm transition-transform ${checked ? 'translate-x-[22px]' : 'translate-x-0.5'}`}
490
490
  />
491
491
  </button>
492
492
  </div>
@@ -616,10 +616,10 @@ export function SEOPanel({
616
616
  : 'Very difficult'
617
617
  const fleschColor =
618
618
  readability.fleschScore >= 60
619
- ? 'text-green-500'
619
+ ? 'text-success'
620
620
  : readability.fleschScore >= 30
621
- ? 'text-amber-500'
622
- : 'text-red-500'
621
+ ? 'text-warning'
622
+ : 'text-destructive'
623
623
 
624
624
  return (
625
625
  <div className="rounded-lg border border-[var(--border)] bg-[var(--card)]">
@@ -643,13 +643,13 @@ export function SEOPanel({
643
643
  <ScoreRing score={score} />
644
644
  <div className="space-y-0.5 text-xs text-[var(--muted-foreground)]">
645
645
  <div className="flex items-center gap-1.5">
646
- <CheckCircle2 className="h-3 w-3 text-green-500" /> {goodCount} passed
646
+ <CheckCircle2 className="text-success h-3 w-3" /> {goodCount} passed
647
647
  </div>
648
648
  <div className="flex items-center gap-1.5">
649
- <AlertCircle className="h-3 w-3 text-amber-500" /> {okCount} improvements
649
+ <AlertCircle className="text-warning h-3 w-3" /> {okCount} improvements
650
650
  </div>
651
651
  <div className="flex items-center gap-1.5">
652
- <XCircle className="h-3 w-3 text-red-500" /> {badCount} issues
652
+ <XCircle className="text-destructive h-3 w-3" /> {badCount} issues
653
653
  </div>
654
654
  </div>
655
655
  </div>
@@ -723,8 +723,8 @@ export function SEOPanel({
723
723
  <span
724
724
  className={
725
725
  readability.passiveEstimate > 15
726
- ? 'font-medium text-amber-500'
727
- : 'font-medium text-green-500'
726
+ ? 'text-warning font-medium'
727
+ : 'text-success font-medium'
728
728
  }
729
729
  >
730
730
  {readability.passiveEstimate}%
@@ -849,10 +849,10 @@ export function SEOPanel({
849
849
  onToggle={toggleSection}
850
850
  >
851
851
  <div className="rounded-lg border border-[var(--border)] bg-[var(--background)] p-3">
852
- <div className="line-clamp-1 cursor-pointer text-sm text-blue-600 hover:underline">
852
+ <div className="text-primary line-clamp-1 cursor-pointer text-sm hover:underline">
853
853
  {metaTitle || title || 'Page Title'}
854
854
  </div>
855
- <div className="mt-1 truncate text-xs text-green-700">
855
+ <div className="text-success mt-1 truncate text-xs">
856
856
  {siteUrl}/{slug}
857
857
  </div>
858
858
  <div className="mt-1 line-clamp-2 text-sm text-[var(--muted-foreground)]">
@@ -971,7 +971,7 @@ export function SEOPanel({
971
971
  onChange={(v) => update({ isCornerstone: v })}
972
972
  />
973
973
  {seoData.isCornerstone && (
974
- <div className="flex items-center gap-1.5 rounded-md bg-amber-50 px-2.5 py-1.5 text-xs text-amber-600">
974
+ <div className="text-warning bg-warning/10 flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-xs">
975
975
  <Star className="h-3.5 w-3.5" />
976
976
  Cornerstone content is held to stricter SEO standards
977
977
  </div>