@stacksjs/defaults 0.75.329 → 0.75.334

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 (70) hide show
  1. package/ai/skills/stacks-native/CATALOG.md +6 -6
  2. package/ide/vscode/package.json +1 -1
  3. package/package.json +4 -4
  4. package/resources/components/Dashboard/Auth/ForgotPassword.stx +1 -1
  5. package/resources/components/Dashboard/Ci/CiDashboard.stx +7 -7
  6. package/resources/components/Dashboard/Ci/CiRunHistoryDrawer.stx +3 -3
  7. package/resources/components/Dashboard/Commerce/CommerceCategoriesTable.stx +1 -1
  8. package/resources/components/Dashboard/Commerce/CommerceCategoryDetailsDialog.stx +5 -5
  9. package/resources/components/Dashboard/Commerce/CommerceCategoryDialog.stx +2 -2
  10. package/resources/components/Dashboard/Commerce/CommerceCategoryHierarchy.stx +2 -2
  11. package/resources/components/Dashboard/Commerce/CommerceCouponDetailsDialog.stx +9 -9
  12. package/resources/components/Dashboard/Commerce/CommerceCouponDialog.stx +1 -1
  13. package/resources/components/Dashboard/Commerce/CommerceCustomerDetailsDialog.stx +5 -5
  14. package/resources/components/Dashboard/Commerce/CommerceCustomerDialog.stx +2 -2
  15. package/resources/components/Dashboard/Commerce/CommerceCustomersTable.stx +1 -1
  16. package/resources/components/Dashboard/Commerce/CommerceGiftCardBreakdown.stx +1 -1
  17. package/resources/components/Dashboard/Commerce/CommerceGiftCardDetailsDialog.stx +11 -11
  18. package/resources/components/Dashboard/Commerce/CommerceOrderDetailsDialog.stx +13 -13
  19. package/resources/components/Dashboard/Commerce/CommercePaymentsBreakdown.stx +2 -2
  20. package/resources/components/Dashboard/Commerce/CommercePosCart.stx +1 -1
  21. package/resources/components/Dashboard/Commerce/CommercePosCatalog.stx +1 -1
  22. package/resources/components/Dashboard/Commerce/CommercePosReceiptDialog.stx +1 -1
  23. package/resources/components/Dashboard/Commerce/CommerceProductDetailDashboard.stx +8 -8
  24. package/resources/components/Dashboard/Commerce/CommerceProductDialog.stx +1 -1
  25. package/resources/components/Dashboard/Commerce/CommerceProductsTable.stx +2 -2
  26. package/resources/components/Dashboard/Commerce/CommerceReviewsTable.stx +1 -1
  27. package/resources/components/Dashboard/Commerce/CommerceVariantsTable.stx +1 -1
  28. package/resources/components/Dashboard/Commerce/Delivery/DeliveryOverviewDashboard.stx +1 -1
  29. package/resources/components/Dashboard/Commerce/Delivery/DigitalDeliveryDialog.stx +2 -2
  30. package/resources/components/Dashboard/Commerce/PaymentDetailsDialog.stx +3 -3
  31. package/resources/components/Dashboard/Commerce/PrintDeviceDetailsDialog.stx +6 -6
  32. package/resources/components/Dashboard/Commerce/PrintLogBreakdown.stx +1 -1
  33. package/resources/components/Dashboard/Commerce/PrintLogDetailsDialog.stx +2 -2
  34. package/resources/components/Dashboard/Commerce/PrintLogsTable.stx +3 -3
  35. package/resources/components/Dashboard/Content/CommentsDashboard.stx +1 -1
  36. package/resources/components/Dashboard/Content/FileStoragePanel.stx +6 -6
  37. package/resources/components/Dashboard/Content/FileUploadDialog.stx +1 -1
  38. package/resources/components/Dashboard/Content/PostEditorDialog.stx +2 -2
  39. package/resources/components/Dashboard/Content/PostsDashboard.stx +1 -1
  40. package/resources/components/Dashboard/Content/SeoEditorDialog.stx +1 -1
  41. package/resources/components/Dashboard/Deployments/DeploymentPreviewDialog.stx +1 -1
  42. package/resources/components/Dashboard/Feedback/FeedbackForm.stx +4 -4
  43. package/resources/components/Dashboard/FileViewer/MediaCard.stx +1 -1
  44. package/resources/components/Dashboard/FileViewer/MediaInfoPanel.stx +4 -4
  45. package/resources/components/Dashboard/GlobalSearch.stx +4 -4
  46. package/resources/components/Dashboard/Infrastructure/CloudDashboard.stx +1 -1
  47. package/resources/components/Dashboard/Infrastructure/DnsDashboard.stx +2 -2
  48. package/resources/components/Dashboard/Infrastructure/LogsDashboard.stx +2 -2
  49. package/resources/components/Dashboard/Infrastructure/MailboxesDashboard.stx +3 -3
  50. package/resources/components/Dashboard/Infrastructure/ServerlessDashboard.stx +1 -1
  51. package/resources/components/Dashboard/Infrastructure/ServersDashboard.stx +5 -5
  52. package/resources/components/Dashboard/Kanban/KanbanBoardDashboard.stx +1 -1
  53. package/resources/components/Dashboard/Kanban/KanbanBoardsDashboard.stx +2 -2
  54. package/resources/components/Dashboard/Kanban/KanbanCardDialog.stx +8 -8
  55. package/resources/components/Dashboard/Marketing/AbandonedCartsDashboard.stx +5 -5
  56. package/resources/components/Dashboard/Marketing/CampaignsDashboard.stx +5 -5
  57. package/resources/components/Dashboard/Marketing/MarketingListsDashboard.stx +4 -4
  58. package/resources/components/Dashboard/Marketing/SocialPostsDashboard.stx +4 -4
  59. package/resources/components/Dashboard/Models/ModelsOverview.stx +1 -1
  60. package/resources/components/Dashboard/Navbar.stx +2 -2
  61. package/resources/components/Dashboard/Operations/AuditDashboard.stx +1 -1
  62. package/resources/components/Dashboard/Operations/OperationHistory.stx +1 -1
  63. package/resources/components/Dashboard/Operations/RecoveryJobList.stx +1 -1
  64. package/resources/components/Dashboard/Remote/RemoteConsole.stx +1 -1
  65. package/resources/components/Dashboard/Settings/SettingsDashboard.stx +1 -1
  66. package/resources/components/Dashboard/UI/Checkbox.stx +1 -1
  67. package/resources/components/Dashboard/UI/MetricCards.stx +1 -1
  68. package/resources/components/Dashboard/UI/Pagination.stx +1 -1
  69. package/resources/components/Dashboard/UI/Textarea.stx +2 -2
  70. package/resources/components/Dashboard/UI/Toggle.stx +1 -1
@@ -294,7 +294,7 @@ function formatTimestamp(iso: string | null | undefined): string {
294
294
  </div>
295
295
  <div class="px-2 py-1.5">
296
296
  <p class="text-[10px] text-zinc-500 dark:text-zinc-400" :text="attachment.mimeType"></p>
297
- <p class="text-[10px] text-zinc-400" :text="formatBytes(attachment.sizeBytes)"></p>
297
+ <p class="text-[10px] text-zinc-500 dark:text-zinc-400" :text="formatBytes(attachment.sizeBytes)"></p>
298
298
  </div>
299
299
  </li>
300
300
  </ul>
@@ -317,14 +317,14 @@ function formatTimestamp(iso: string | null | undefined): string {
317
317
  </div>
318
318
  </div>
319
319
 
320
- <div :if="cardComments().length === 0 && !loadingCard()" class="italic text-xs text-zinc-400">No comments yet.</div>
320
+ <div :if="cardComments().length === 0 && !loadingCard()" class="italic text-xs text-zinc-500 dark:text-zinc-400">No comments yet.</div>
321
321
  <ul class="space-y-3">
322
322
  <li :for="comment in cardComments" class="flex gap-3">
323
323
  <span class="inline-flex flex-shrink-0 items-center justify-center h-7 w-7 font-medium text-[10px] text-white bg-violet-500 rounded-full" :text="initialsOf(comment.authorName, comment.authorEmail)"></span>
324
324
  <div class="flex-1 min-w-0">
325
325
  <div class="flex flex-wrap gap-2 items-baseline">
326
326
  <span class="font-medium text-xs text-zinc-700 dark:text-zinc-200" :text="comment.authorName || comment.authorEmail || 'Unknown'"></span>
327
- <span class="text-[10px] text-zinc-400" :text="formatTimestamp(comment.createdAt)"></span>
327
+ <span class="text-[10px] text-zinc-500 dark:text-zinc-400" :text="formatTimestamp(comment.createdAt)"></span>
328
328
  <template :if="editingCommentId() !== comment.id">
329
329
  <Button variant="ghost" size="xs" @click="startCommentEdit(comment.id, comment.body)">Edit</Button>
330
330
  <Button variant="ghost" size="xs" @click="requestDelete('comment', comment.id)"><span class="text-red-500">Delete</span></Button>
@@ -365,7 +365,7 @@ function formatTimestamp(iso: string | null | undefined): string {
365
365
 
366
366
  <div :if="!showLabelPicker()" class="flex flex-wrap gap-1">
367
367
  <span :for="label in cardLabels" :class="`px-2 py-0.5 text-xs font-medium rounded ${labelChipClass(label.color)}`" :text="label.name"></span>
368
- <span :if="cardLabels().length === 0" class="italic text-xs text-zinc-400">None</span>
368
+ <span :if="cardLabels().length === 0" class="italic text-xs text-zinc-500 dark:text-zinc-400">None</span>
369
369
  </div>
370
370
 
371
371
  <div :if="showLabelPicker()" class="space-y-2">
@@ -407,11 +407,11 @@ function formatTimestamp(iso: string | null | undefined): string {
407
407
  <span class="inline-flex items-center justify-center h-6 w-6 font-medium text-[10px] text-white bg-violet-500 rounded-full" :text="initialsOf(assignee.name, assignee.email)"></span>
408
408
  <span :text="assignee.name || assignee.email || 'Unknown'"></span>
409
409
  </div>
410
- <span :if="cardAssignees().length === 0" class="italic text-xs text-zinc-400">Unassigned</span>
410
+ <span :if="cardAssignees().length === 0" class="italic text-xs text-zinc-500 dark:text-zinc-400">Unassigned</span>
411
411
  </div>
412
412
 
413
413
  <div :if="showAssigneePicker()" class="overflow-y-auto space-y-1 max-h-48">
414
- <p :if="kanban.users().length === 0" class="italic text-xs text-zinc-400">No users to assign.</p>
414
+ <p :if="kanban.users().length === 0" class="italic text-xs text-zinc-500 dark:text-zinc-400">No users to assign.</p>
415
415
  <button :for="user in kanban.users" type="button" :aria-pressed="String(cardAssignees().some(assignee => assignee.userId === user.id))" @click="toggleAssignee(user.id)" class="flex gap-2 items-center px-2 py-1.5 w-full text-left text-xs hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded">
416
416
  <span class="inline-flex flex-shrink-0 items-center justify-center h-6 w-6 font-medium text-[10px] text-white bg-violet-500 rounded-full" :text="initialsOf(user.name, user.email)"></span>
417
417
  <span class="flex-1 text-zinc-700 truncate dark:text-zinc-200" :text="user.name || user.email"></span>
@@ -426,8 +426,8 @@ function formatTimestamp(iso: string | null | undefined): string {
426
426
  </section>
427
427
 
428
428
  <section class="pt-3 border-t border-zinc-200 dark:border-zinc-800">
429
- <p class="text-[10px] text-zinc-400">Created <span :text="formatTimestamp(openCard()?.createdAt)"></span></p>
430
- <p :if="openCard()?.updatedAt && openCard()?.updatedAt !== openCard()?.createdAt" class="text-[10px] text-zinc-400">Updated <span :text="formatTimestamp(openCard()?.updatedAt)"></span></p>
429
+ <p class="text-[10px] text-zinc-500 dark:text-zinc-400">Created <span :text="formatTimestamp(openCard()?.createdAt)"></span></p>
430
+ <p :if="openCard()?.updatedAt && openCard()?.updatedAt !== openCard()?.createdAt" class="text-[10px] text-zinc-500 dark:text-zinc-400">Updated <span :text="formatTimestamp(openCard()?.updatedAt)"></span></p>
431
431
  </section>
432
432
  </aside>
433
433
  </div>
@@ -165,11 +165,11 @@ onMount(() => {
165
165
  <div :if="loadError()" role="alert" class="flex gap-4 items-center justify-between p-4 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900"><span>{{ loadError() }}</span><Button variant="secondary" size="sm" @click="loadCarts()">Retry</Button></div>
166
166
 
167
167
  <section aria-label="Cart recovery metrics" class="grid gap-3 grid-cols-2 lg:grid-cols-5">
168
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Sitting there</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().open.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Carts abandoned or expired</p></article>
169
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Worth</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ money(summary().openValue) }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">{{ money(summary().averageValue) }} average</p></article>
170
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Chased</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().contacted.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Written to and still cold</p></article>
171
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recovered</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ money(summary().recoveredValue) }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">{{ summary().recovered.toLocaleString() }} carts checked out after an email</p></article>
172
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recovery rate</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ percentage(summary().recoveryRate) }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Of the carts actually chased</p></article>
168
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Sitting there</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().open.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Carts abandoned or expired</p></article>
169
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Worth</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ money(summary().openValue) }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">{{ money(summary().averageValue) }} average</p></article>
170
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Chased</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().contacted.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Written to and still cold</p></article>
171
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recovered</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ money(summary().recoveredValue) }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">{{ summary().recovered.toLocaleString() }} carts checked out after an email</p></article>
172
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recovery rate</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ percentage(summary().recoveryRate) }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Of the carts actually chased</p></article>
173
173
  </section>
174
174
 
175
175
  <section :if="campaigns().length > 0" aria-label="Recovery campaigns" class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700">
@@ -273,11 +273,11 @@ onMount(() => {
273
273
  <div :if="loadError()" role="alert" class="flex gap-4 items-center justify-between p-4 text-red-700 text-sm dark:text-red-300 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900"><span>{{ loadError() }}</span><Button variant="secondary" size="sm" @click="loadCampaigns()">Retry</Button></div>
274
274
 
275
275
  <section aria-label="Campaign metrics" class="grid gap-3 grid-cols-2 lg:grid-cols-5">
276
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Campaigns</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Persisted records</p></article>
277
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Live</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().live }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Scheduled, sending, or active</p></article>
278
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Completed</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().sent }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Sent or completed</p></article>
279
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recipients</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().recipients.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Persisted successful sends</p></article>
280
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Delivery issues</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().failedDeliveries.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Failed, bounced, or complained</p></article>
276
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Campaigns</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Persisted records</p></article>
277
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Live</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().live }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Scheduled, sending, or active</p></article>
278
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Completed</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().sent }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Sent or completed</p></article>
279
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Recipients</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().recipients.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Persisted successful sends</p></article>
280
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Delivery issues</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().failedDeliveries.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Failed, bounced, or complained</p></article>
281
281
  </section>
282
282
 
283
283
  <section class="space-y-3">
@@ -206,10 +206,10 @@ onMount(() => {
206
206
  </div>
207
207
 
208
208
  <section aria-label="Email list metrics" class="grid gap-3 grid-cols-2 lg:grid-cols-4">
209
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Email lists</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">{{ summary().active }} active</p></article>
210
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Memberships</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().subscribers.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Subscribed and pending</p></article>
211
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">New this week</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().newThisWeek.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Subscribed membership rows</p></article>
212
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Campaigns</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().campaigns.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Linked campaign records</p></article>
209
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Email lists</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">{{ summary().active }} active</p></article>
210
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Memberships</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().subscribers.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Subscribed and pending</p></article>
211
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">New this week</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().newThisWeek.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Subscribed membership rows</p></article>
212
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Campaigns</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().campaigns.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Linked campaign records</p></article>
213
213
  </section>
214
214
 
215
215
  <section class="space-y-3">
@@ -189,10 +189,10 @@ onMount(() => {
189
189
  <div :if="summary().failed > 0" class="flex gap-3 items-start p-4 text-red-800 text-sm dark:text-red-200 bg-red-50 dark:bg-red-950/30 border border-red-200 rounded-lg dark:border-red-900"><span class="shrink-0 mt-0.5 h-5 w-5 i-hugeicons-alert-02"></span><p>{{ summary().failed }} {{ summary().failed === 1 ? 'post has' : 'posts have' }} a failed status and may need review.</p></div>
190
190
 
191
191
  <section aria-label="Social post metrics" class="grid gap-3 grid-cols-2 lg:grid-cols-4">
192
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Social posts</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">{{ summary().published }} published, {{ summary().drafts }} drafts</p></article>
193
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Scheduled</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().scheduled }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Persisted schedule times</p></article>
194
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Reach</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().reach.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Recorded platform reach</p></article>
195
- <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Engagement</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().engagement.toLocaleString() }}</p><p class="mt-1 text-gray-400 text-xs dark:text-neutral-500">Likes, shares, and comments</p></article>
192
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Social posts</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().total }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">{{ summary().published }} published, {{ summary().drafts }} drafts</p></article>
193
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Scheduled</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().scheduled }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Persisted schedule times</p></article>
194
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Reach</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().reach.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Recorded platform reach</p></article>
195
+ <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700"><p class="text-gray-500 text-xs dark:text-neutral-400">Engagement</p><p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ summary().engagement.toLocaleString() }}</p><p class="mt-1 text-gray-500 text-xs dark:text-neutral-500">Likes, shares, and comments</p></article>
196
196
  </section>
197
197
 
198
198
  <section class="space-y-3">
@@ -204,7 +204,7 @@ onMount(() => {
204
204
  <div :if="model.apiUri" class="flex gap-2 items-center mt-4">
205
205
  <span class="inline-flex px-2 py-0.5 font-medium text-green-700 text-xs dark:text-green-300 bg-green-50 dark:bg-green-950/40 rounded">API</span>
206
206
  <code class="text-neutral-500 text-xs truncate dark:text-neutral-400">{{ model.apiUri }}</code>
207
- <span class="ml-auto text-neutral-400 text-xs">{{ model.apiRoutes.length }} routes</span>
207
+ <span class="ml-auto text-neutral-500 text-xs dark:text-neutral-400">{{ model.apiRoutes.length }} routes</span>
208
208
  </div>
209
209
  </StxLink>
210
210
  </div>
@@ -58,12 +58,12 @@ useClickOutside(userMenu, () => setDropdownOpen(false))
58
58
  <div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
59
59
  <StxLink
60
60
  to="/models"
61
- class="flex relative flex-1 items-center pl-8 text-gray-400 sm:text-sm hover:text-gray-600 dark:hover:text-neutral-200 transition-colors"
61
+ class="flex relative flex-1 items-center pl-8 text-gray-500 sm:text-sm dark:text-gray-400 hover:text-gray-600 dark:hover:text-neutral-200 transition-colors"
62
62
  aria-label="Search model records"
63
63
  >
64
64
  <span aria-hidden="true" class="absolute left-0 h-5 w-5 i-hugeicons-search-01"></span>
65
65
  <span>Search model records</span>
66
- <kbd class="ml-auto px-1.5 py-0.5 font-medium text-[10px] text-neutral-400 bg-neutral-100 dark:bg-neutral-700 border border-neutral-200 rounded dark:border-neutral-600">
66
+ <kbd class="ml-auto px-1.5 py-0.5 font-medium text-[10px] text-neutral-500 dark:text-neutral-400 bg-neutral-100 dark:bg-neutral-700 border border-neutral-200 rounded dark:border-neutral-600">
67
67
  ⌘K
68
68
  </kbd>
69
69
  </StxLink>
@@ -12,5 +12,5 @@ onMount(() => void load())
12
12
  <PageHeader title="Operations" description="Inspect the append-only operator event stream with actor and operation correlation."><template #actions><Button variant="secondary" :loading="loading()" @click="load"><span :if="!loading()" class="h-4 w-4 i-hugeicons-refresh"></span>Refresh</Button></template></PageHeader>
13
13
  <OperationsNavigation active="audit" />
14
14
  <section class="grid gap-3 sm:grid-cols-2 lg:grid-cols-4"><StatsCard title="Events" :value="String(data()?.summary.events || 0)" icon="i-hugeicons-activity-03" iconBg="primary" :loading="loading()" /><StatsCard title="Operators" :value="String(data()?.summary.operators || 0)" icon="i-hugeicons-user-group" iconBg="neutral" :loading="loading()" /><StatsCard title="Failures" :value="String(data()?.summary.failures || 0)" icon="i-hugeicons-alert-02" iconBg="warning" :loading="loading()" /><StatsCard title="Latest sequence" :value="String(data()?.summary.latestSequence || 0)" icon="i-hugeicons-list-view" iconBg="success" :loading="loading()" /></section>
15
- <section class="overflow-hidden bg-white dark:bg-neutral-900 border border-gray-200 rounded-lg dark:border-neutral-800"><div class="px-4 py-4 border-b border-gray-200 dark:border-neutral-800"><h2 class="font-semibold text-gray-900 dark:text-white">Operator events</h2><p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Events are sequence ordered and retained in the ts-cloud control plane.</p></div><div :if="!loading() && !data()?.events.length" class="px-6 py-12 text-center text-gray-500 text-sm dark:text-neutral-400">No operator events have been recorded.</div><div class="overflow-auto max-h-[42rem] divide-gray-100 divide-y dark:divide-neutral-800"><div :for="event in data()?.events || []" class="grid gap-2 md:grid-cols-[5rem_1fr_10rem_12rem] px-4 py-3"><span class="font-mono text-gray-400 text-xs">#{{ event.sequence }}</span><div><p class="font-medium text-gray-900 text-sm dark:text-white">{{ event.type }}</p><p class="mt-1 font-mono text-gray-500 text-xs dark:text-neutral-400">{{ event.operationId || event.id }}</p></div><span class="text-gray-600 text-sm dark:text-neutral-300">{{ event.actorName }}</span><time class="text-gray-500 text-xs dark:text-neutral-400">{{ date(event.createdAt) }}</time></div></div></section>
15
+ <section class="overflow-hidden bg-white dark:bg-neutral-900 border border-gray-200 rounded-lg dark:border-neutral-800"><div class="px-4 py-4 border-b border-gray-200 dark:border-neutral-800"><h2 class="font-semibold text-gray-900 dark:text-white">Operator events</h2><p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Events are sequence ordered and retained in the ts-cloud control plane.</p></div><div :if="!loading() && !data()?.events.length" class="px-6 py-12 text-center text-gray-500 text-sm dark:text-neutral-400">No operator events have been recorded.</div><div class="overflow-auto max-h-[42rem] divide-gray-100 divide-y dark:divide-neutral-800"><div :for="event in data()?.events || []" class="grid gap-2 md:grid-cols-[5rem_1fr_10rem_12rem] px-4 py-3"><span class="font-mono text-gray-500 text-xs dark:text-gray-400">#{{ event.sequence }}</span><div><p class="font-medium text-gray-900 text-sm dark:text-white">{{ event.type }}</p><p class="mt-1 font-mono text-gray-500 text-xs dark:text-neutral-400">{{ event.operationId || event.id }}</p></div><span class="text-gray-600 text-sm dark:text-neutral-300">{{ event.actorName }}</span><time class="text-gray-500 text-xs dark:text-neutral-400">{{ date(event.createdAt) }}</time></div></div></section>
16
16
  </div>
@@ -55,7 +55,7 @@ function statusVariant(state: OperatorOperation['state']): 'default' | 'primary'
55
55
  <p class="mt-1 text-gray-500 text-xs dark:text-neutral-400">{{ operation.actorName }} at {{ formatDate(operation.finishedAt || operation.createdAt) }}</p>
56
56
  <p :if="operation.error" class="mt-1 text-red-600 text-xs dark:text-red-400">{{ operation.error }}</p>
57
57
  </div>
58
- <code class="font-mono text-[11px] text-gray-400 dark:text-neutral-500">{{ operation.id }}</code>
58
+ <code class="font-mono text-[11px] text-gray-500 dark:text-neutral-500">{{ operation.id }}</code>
59
59
  </li>
60
60
  </ul>
61
61
  </Card>
@@ -26,7 +26,7 @@ function variant(status: RecoveryJob['status']): 'default' | 'primary' | 'succes
26
26
  <p class="mt-1 text-gray-500 text-xs dark:text-neutral-400">{{ job.progress.phase || 'queued' }} · {{ formatDate(job.finishedAt || job.startedAt || job.createdAt) }}</p>
27
27
  <p :if="job.error" class="mt-1 text-red-600 text-xs dark:text-red-400">{{ job.error }}</p>
28
28
  </div>
29
- <code class="font-mono text-[11px] text-gray-400 dark:text-neutral-500">{{ job.id }}</code>
29
+ <code class="font-mono text-[11px] text-gray-500 dark:text-neutral-500">{{ job.id }}</code>
30
30
  </li>
31
31
  </ul>
32
32
  </Card>
@@ -109,7 +109,7 @@ onMount(() => {
109
109
  <span class="h-4 w-4 i-hugeicons-command-line"></span>
110
110
  Open terminal
111
111
  </Button>
112
- <span :if="!entry.terminal" class="text-gray-400 text-xs dark:text-neutral-500">Named commands only</span>
112
+ <span :if="!entry.terminal" class="text-gray-500 text-xs dark:text-neutral-500">Named commands only</span>
113
113
  </li>
114
114
  </template>
115
115
  </ul>
@@ -220,7 +220,7 @@ void loadFiles()
220
220
  >
221
221
  <span class="flex-none h-4 w-4 i-hugeicons-settings-02"></span>
222
222
  <span class="flex-1 font-medium text-sm truncate">{{ file.title }}</span>
223
- <span class="text-[10px] text-neutral-400">{{ file.size < 1024 ? file.size + ' B' : Math.round(file.size / 1024) + ' KB' }}</span>
223
+ <span class="text-[10px] text-neutral-500 dark:text-neutral-400">{{ file.size < 1024 ? file.size + ' B' : Math.round(file.size / 1024) + ' KB' }}</span>
224
224
  </button>
225
225
  </template>
226
226
  </nav>
@@ -44,7 +44,7 @@ const iconClass = derived(() => [
44
44
  const labelClass = derived(() => [
45
45
  sizeClasses[liveSize()]?.label || sizeClasses.md.label,
46
46
  'font-medium',
47
- liveDisabled() ? 'text-neutral-400 dark:text-neutral-500' : 'text-neutral-700 dark:text-neutral-200',
47
+ liveDisabled() ? 'text-neutral-500 dark:text-neutral-500' : 'text-neutral-700 dark:text-neutral-200',
48
48
  ].join(' '))
49
49
  const descriptionClass = derived(() => [
50
50
  sizeClasses[liveSize()]?.description || sizeClasses.md.description,
@@ -26,7 +26,7 @@ const columns = useReactiveProp('columns', 'grid-cols-2 lg:grid-cols-4')
26
26
  <article class="p-4 bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700">
27
27
  <p class="text-gray-500 text-xs dark:text-neutral-400">{{ item.label }}</p>
28
28
  <p class="mt-2 font-semibold text-2xl text-gray-900 dark:text-white">{{ item.value }}</p>
29
- <p :if="item.detail" class="mt-1 text-gray-400 text-xs dark:text-neutral-500">{{ item.detail }}</p>
29
+ <p :if="item.detail" class="mt-1 text-gray-500 text-xs dark:text-neutral-500">{{ item.detail }}</p>
30
30
  </article>
31
31
  </template>
32
32
  </section>
@@ -100,7 +100,7 @@ function emitItemsPerPage(event: Event): void {
100
100
  </Button>
101
101
 
102
102
  <template :for="page in visiblePages()">
103
- <span :if="typeof page !== 'number'" class="px-2 text-neutral-400 dark:text-neutral-500">...</span>
103
+ <span :if="typeof page !== 'number'" class="px-2 text-neutral-500 dark:text-neutral-500">...</span>
104
104
  <Button :if="typeof page === 'number' && page === currentPage()" @click="goToPage(page)">
105
105
  <span aria-current="page">{{ page }}</span>
106
106
  </Button>
@@ -77,7 +77,7 @@ function handleBlur(event: Event): void {
77
77
  </label>
78
78
  <span
79
79
  :if="liveShowCount() && liveMaxLength()"
80
- class="text-neutral-400 text-xs dark:text-neutral-500"
80
+ class="text-neutral-500 text-xs dark:text-neutral-500"
81
81
  :text="limitedCountLabel()"
82
82
  ></span>
83
83
  </div>
@@ -103,7 +103,7 @@ function handleBlur(event: Event): void {
103
103
 
104
104
  <span
105
105
  :if="liveShowCount() && !liveMaxLength()"
106
- class="absolute bottom-2 right-2 px-1 text-neutral-400 text-xs dark:text-neutral-500 bg-white dark:bg-neutral-900"
106
+ class="absolute bottom-2 right-2 px-1 text-neutral-500 text-xs dark:text-neutral-500 bg-white dark:bg-neutral-900"
107
107
  :text="openCountLabel()"
108
108
  ></span>
109
109
  </div>
@@ -51,7 +51,7 @@ const thumbClass = derived(() => [
51
51
  ].join(' '))
52
52
  const labelClass = derived(() => [
53
53
  'text-[13px] font-medium tracking-tight',
54
- liveDisabled() ? 'text-neutral-400 dark:text-neutral-600' : 'text-neutral-700 dark:text-neutral-200',
54
+ liveDisabled() ? 'text-neutral-500 dark:text-neutral-600' : 'text-neutral-700 dark:text-neutral-200',
55
55
  ].join(' '))
56
56
  const descriptionClass = derived(() => [
57
57
  'mt-0.5 text-[12px]',