@saasicat/ui-vue 0.22.2 → 0.23.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 (108) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-LY52T4N4.js → chunk-TQQMKWN6.js} +58 -1
  3. package/dist/index.cjs +213 -159
  4. package/dist/index.d.cts +2 -2
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +7 -1
  7. package/dist/quasar/index.cjs +116 -20
  8. package/dist/quasar/index.d.cts +48 -3
  9. package/dist/quasar/index.d.ts +48 -3
  10. package/dist/quasar/index.js +58 -3
  11. package/dist/{use-super-admin-i18n-CgTuNi8h.d.cts → use-sa-theme-B5t7oXph.d.cts} +51 -1
  12. package/dist/{use-super-admin-i18n-CHNdsSlm.d.ts → use-sa-theme-OUBlaqgl.d.ts} +51 -1
  13. package/package.json +5 -2
  14. package/src/components/BundleVersionPublishDialog.vue +17 -17
  15. package/src/components/KvBlock.vue +6 -6
  16. package/src/components/MarketingPromotionsTab.vue +78 -78
  17. package/src/components/MfaPromptDialog.vue +2 -2
  18. package/src/components/TenantActionConfirmDialog.vue +5 -5
  19. package/src/components/VersionDiffPreview.vue +18 -18
  20. package/src/components/bundle-editor/BundleCreatePanel.vue +52 -52
  21. package/src/components/bundle-editor/BundleFeaturesEditor.vue +20 -20
  22. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +33 -33
  23. package/src/components/bundle-editor/BundleQuotasEditor.vue +26 -26
  24. package/src/components/bundle-editor/BundleStatusBanner.vue +21 -21
  25. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +48 -48
  26. package/src/components/bundle-editor/BundleVersionStrip.vue +30 -30
  27. package/src/components/dialogs/PilotCreateDialog.vue +20 -20
  28. package/src/components/dialogs/PilotEditDialog.vue +6 -6
  29. package/src/components/dialogs/PromoCodeCreateDialog.vue +9 -9
  30. package/src/components/dialogs/PromoCodeDialogFields.vue +61 -61
  31. package/src/components/dialogs/PromoCodeEditDialog.vue +11 -11
  32. package/src/components/dialogs/pilot-dialog.css +48 -48
  33. package/src/components/plan/PlanCycleToggle.vue +9 -16
  34. package/src/components/plan/PlanGrid.vue +30 -34
  35. package/src/components/plan/PriceSummary.vue +35 -35
  36. package/src/components/plan/PromoCodeInput.vue +26 -26
  37. package/src/components/plan/PublicBundleGrid.vue +32 -28
  38. package/src/components/plan-create-dialog/PlanCreateDialog.vue +49 -49
  39. package/src/components/plan-detail/PlanDetail.vue +172 -156
  40. package/src/components/plan-detail/PlanTitleEdit.vue +11 -11
  41. package/src/components/plan-list/PlanList.vue +98 -77
  42. package/src/components/plan-matrix/PlanMatrix.vue +89 -89
  43. package/src/components/plan-review/PlanReview.vue +60 -56
  44. package/src/components/plan-version-editor/PlanVersionEditor.vue +224 -200
  45. package/src/components/wizard-stepper/WizardStepper.vue +17 -17
  46. package/src/index.ts +1 -0
  47. package/src/pages-standard/AdminLayout.vue +58 -37
  48. package/src/pages-standard/AdminManifestErrorPage.vue +6 -6
  49. package/src/pages-standard/AuditPage.vue +3 -3
  50. package/src/pages-standard/BundlesPage.vue +36 -36
  51. package/src/pages-standard/DashboardPage.vue +17 -17
  52. package/src/pages-standard/DiscoveryPage.vue +55 -49
  53. package/src/pages-standard/EmailHistoryPage.vue +53 -71
  54. package/src/pages-standard/MarketingCatalogPage.vue +226 -218
  55. package/src/pages-standard/PilotsPage.vue +7 -6
  56. package/src/pages-standard/PlatformEmailPage.vue +18 -18
  57. package/src/pages-standard/PromoCodeDetailPage.vue +3 -3
  58. package/src/pages-standard/PromoCodesPage.vue +7 -6
  59. package/src/pages-standard/SuperAdminLoginPage.vue +39 -25
  60. package/src/pages-standard/SuperAdminSetupWizard.vue +44 -33
  61. package/src/pages-standard/TenantDetailPage.vue +7 -7
  62. package/src/pages-standard/TenantsPage.vue +11 -46
  63. package/src/pages-standard/bundles-page/BundleAccordionList.vue +13 -13
  64. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +24 -24
  65. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +22 -22
  66. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +39 -39
  67. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +26 -26
  68. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +1 -1
  69. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -16
  70. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +21 -15
  71. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +45 -45
  72. package/src/pages-standard/plans-page/PlanBundleOverview.vue +21 -15
  73. package/src/pages-standard/plans-page/PlanPublishDialog.vue +4 -4
  74. package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
  75. package/src/pages-standard/sa-theme.css +9 -687
  76. package/src/pages-standard/tenants/StatusPill.vue +13 -13
  77. package/src/pages-tenant/LimitsRow.vue +4 -4
  78. package/src/pages-tenant/MySubscriptionBundlesPage.vue +61 -61
  79. package/src/pages-tenant/OnboardingConfigurator.vue +24 -24
  80. package/src/pages-tenant/PackageSnapshotPanel.vue +10 -16
  81. package/src/pages-tenant/PendingVersionBanner.vue +12 -12
  82. package/src/pages-tenant/PlanChangeWizard.vue +20 -27
  83. package/src/pages-tenant/TenantPlanSection.vue +13 -21
  84. package/src/pages-tenant/UsageBar.vue +7 -7
  85. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +14 -14
  86. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +10 -10
  87. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +2 -2
  88. package/src/quasar/create-super-admin-app.ts +96 -1
  89. package/src/quasar/dark-bridge.ts +66 -0
  90. package/src/quasar/index.ts +1 -0
  91. package/src/ui/theme/_breakpoints.scss +28 -0
  92. package/src/ui/theme/base.css +50 -0
  93. package/src/ui/theme/components/body.css +23 -0
  94. package/src/ui/theme/components/button.css +158 -0
  95. package/src/ui/theme/components/card.css +48 -0
  96. package/src/ui/theme/components/field.css +38 -0
  97. package/src/ui/theme/components/hero.css +46 -0
  98. package/src/ui/theme/components/paginator.css +63 -0
  99. package/src/ui/theme/components/section.css +67 -0
  100. package/src/ui/theme/components/statistics.css +189 -0
  101. package/src/ui/theme/components/table.css +60 -0
  102. package/src/ui/theme/index.css +42 -0
  103. package/src/ui/theme/tokens.legacy.css +147 -0
  104. package/src/ui/theme/tokens.primitive.css +108 -0
  105. package/src/ui/theme/tokens.scale.css +103 -0
  106. package/src/ui/theme/tokens.semantic.dark.css +173 -0
  107. package/src/ui/theme/tokens.semantic.light.css +212 -0
  108. package/src/vue/use-sa-theme.ts +154 -0
@@ -280,4 +280,54 @@ declare function useSuperAdminI18n(): SuperAdminI18n;
280
280
  */
281
281
  declare function useSaMessages<K extends keyof SaMessages>(namespace: K): ComputedRef<SaMessages[K]>;
282
282
 
283
- export { type ActionsMap as A, type ExtensionsMap as E, type InstallPlugin as I, type SuperAdminGuardOptions as S, type UiNotify as U, type SuperAdminBrand as a, type SuperAdminEndpoints as b, type SuperAdminLoginAdapter as c, type SuperAdminI18nOptions as d, type SuperAdminI18n as e, type ExtensionLoader as f, SA_LOCALE_STORAGE_KEY as g, SUPER_ADMIN_ACTIONS_KEY as h, SUPER_ADMIN_BRAND_KEY as i, SUPER_ADMIN_ENDPOINTS_KEY as j, SUPER_ADMIN_EXTENSIONS_KEY as k, SUPER_ADMIN_HTTP_KEY as l, SUPER_ADMIN_I18N_KEY as m, SUPER_ADMIN_LOGIN_ADAPTER_KEY as n, SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY as o, SUPER_ADMIN_MANIFEST_KEY as p, SUPER_ADMIN_NOTIFY_KEY as q, type SuperAdminAuthGuardOptions as r, type SuperAdminLoginResult as s, type SuperAdminManifestGuardOptions as t, type UiNotifyKind as u, type UiNotifyOptions as v, buildNavigationGuard as w, createSuperAdminI18n as x, useSaMessages as y, useSuperAdminI18n as z };
283
+ type SaColorScheme = 'light' | 'dark' | 'system';
284
+ type SaResolvedScheme = 'light' | 'dark';
285
+ interface SaTheme {
286
+ /** What the operator picked. Writable — assigning switches the theme. */
287
+ scheme: Ref<SaColorScheme>;
288
+ /** What that means right now: `'system'` resolved against the OS. */
289
+ resolved: ComputedRef<SaResolvedScheme>;
290
+ /**
291
+ * Releases the `prefers-color-scheme` subscription and the persistence
292
+ * watcher. Idempotent.
293
+ *
294
+ * Needed because this context outlives no component — nothing unmounts it.
295
+ * A second shell in the same document (hot reload, a micro-frontend, a
296
+ * second test file) would otherwise leave the first one subscribed, and the
297
+ * next change of the operating system's theme would drive TWO bridges, both
298
+ * writing `data-sa-theme` and Quasar's `Dark` onto the one document. The
299
+ * stale one can win, and then the new shell's explicit scheme is overruled
300
+ * by a context nobody holds a reference to any more.
301
+ */
302
+ dispose: () => void;
303
+ }
304
+ interface SaThemeOptions {
305
+ /** Starting scheme. Pass a `Ref` to keep the value in your own store. */
306
+ scheme?: SaColorScheme | Ref<SaColorScheme>;
307
+ /**
308
+ * Remember the operator's pick across reloads, default `true`. Ignored when
309
+ * `scheme` is a `Ref`: the app owns that value and persists it where it
310
+ * belongs. Same rule as the locale in `createSuperAdminI18n`.
311
+ */
312
+ persist?: boolean;
313
+ /** Injection seam for tests. */
314
+ storage?: KvStore;
315
+ }
316
+ /**
317
+ * Creates the theme context. `createSuperAdminApp()` makes one and the Quasar
318
+ * bridge mirrors it onto the document; call it directly only when bootstrapping
319
+ * by hand.
320
+ */
321
+ declare function createSaTheme(options?: SaThemeOptions): SaTheme;
322
+ declare const SA_THEME_KEY: InjectionKey<SaTheme>;
323
+ /**
324
+ * The shell's theme context, or a shared unpersisted one outside a shell.
325
+ *
326
+ * Same shape as `useSuperAdminI18n()`, and for the same reason: a component
327
+ * mounted in isolation must render rather than throw, and the fallback must not
328
+ * write to real storage or two tests in one process would decide each other's
329
+ * outcome.
330
+ */
331
+ declare function useSaTheme(): SaTheme;
332
+
333
+ export { type ActionsMap as A, type UiNotifyOptions as B, buildNavigationGuard as C, createSaTheme as D, type ExtensionsMap as E, createSuperAdminI18n as F, useSaMessages as G, useSaTheme as H, type InstallPlugin as I, useSuperAdminI18n as J, type SuperAdminGuardOptions as S, type UiNotify as U, type SuperAdminBrand as a, type SuperAdminEndpoints as b, type SuperAdminLoginAdapter as c, type SuperAdminI18nOptions as d, type SaThemeOptions as e, type SuperAdminI18n as f, type SaTheme as g, type ExtensionLoader as h, SA_LOCALE_STORAGE_KEY as i, SA_THEME_KEY as j, SUPER_ADMIN_ACTIONS_KEY as k, SUPER_ADMIN_BRAND_KEY as l, SUPER_ADMIN_ENDPOINTS_KEY as m, SUPER_ADMIN_EXTENSIONS_KEY as n, SUPER_ADMIN_HTTP_KEY as o, SUPER_ADMIN_I18N_KEY as p, SUPER_ADMIN_LOGIN_ADAPTER_KEY as q, SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY as r, SUPER_ADMIN_MANIFEST_KEY as s, SUPER_ADMIN_NOTIFY_KEY as t, type SaColorScheme as u, type SaResolvedScheme as v, type SuperAdminAuthGuardOptions as w, type SuperAdminLoginResult as x, type SuperAdminManifestGuardOptions as y, type UiNotifyKind as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/ui-vue",
3
- "version": "0.22.2",
3
+ "version": "0.23.0",
4
4
  "description": "Vue 3 components, resource clients and composables for the SuperAdmin UI shell. Provides boot and manifest loaders, navigation, actions and standard pages.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -41,6 +41,9 @@
41
41
  "./pages-standard/*": "./src/pages-standard/*",
42
42
  "./pages-tenant/*": "./src/pages-tenant/*",
43
43
  "./components/*": "./src/components/*",
44
+ "./theme.css": "./src/ui/theme/index.css",
45
+ "./theme/breakpoints": "./src/ui/theme/_breakpoints.scss",
46
+ "./theme/*": "./src/ui/theme/*",
44
47
  "./sa-theme.css": "./src/pages-standard/sa-theme.css",
45
48
  "./testing-e2e/*": {
46
49
  "import": {
@@ -58,7 +61,7 @@
58
61
  "src"
59
62
  ],
60
63
  "dependencies": {
61
- "@saasicat/types": "^0.22.2"
64
+ "@saasicat/types": "^0.23.0"
62
65
  },
63
66
  "peerDependencies": {
64
67
  "pinia": "^2.0.0 || ^3.0.0",
@@ -300,8 +300,8 @@ function formatValue(v: unknown): string {
300
300
  gap: 16px;
301
301
  }
302
302
  .bvpd__label {
303
- font-size: 12px;
304
- color: var(--q-grey-7, #757575);
303
+ font-size: var(--sa-text-sm);
304
+ color: var(--sa-color-fg-muted);
305
305
  text-transform: uppercase;
306
306
  letter-spacing: 0.5px;
307
307
  margin-bottom: 6px;
@@ -313,18 +313,18 @@ function formatValue(v: unknown): string {
313
313
  padding: 32px;
314
314
  }
315
315
  .bvpd__warnings {
316
- border-left: 4px solid var(--q-warning, #f2c037);
316
+ border-left: 4px solid var(--sa-color-warning-strong);
317
317
  }
318
318
  .bvpd__neutral {
319
- border-left: 4px solid var(--q-grey-7, #757575);
319
+ border-left: 4px solid var(--sa-color-border-strong);
320
320
  }
321
321
  .bvpd__regression {
322
- border-left: 4px solid var(--q-negative, #c10015);
322
+ border-left: 4px solid var(--sa-color-negative);
323
323
  }
324
324
  .bvpd__validity {
325
325
  padding: 12px;
326
- background: var(--sa-bg-surface-2);
327
- border: 1px solid var(--sa-border);
326
+ background: var(--sa-color-bg-sunken);
327
+ border: 1px solid var(--sa-color-border);
328
328
  border-radius: 8px;
329
329
  }
330
330
  .bvpd__validity-grid {
@@ -335,36 +335,36 @@ function formatValue(v: unknown): string {
335
335
  .bvpd__field {
336
336
  display: grid;
337
337
  gap: 6px;
338
- font-size: 12px;
338
+ font-size: var(--sa-text-sm);
339
339
  font-weight: 700;
340
- color: var(--sa-muted-dark);
340
+ color: var(--sa-color-fg-secondary);
341
341
  }
342
342
  .bvpd__input {
343
343
  min-height: 36px;
344
- border: 1px solid #cbd5e1;
344
+ border: 1px solid var(--sa-color-border-strong);
345
345
  border-radius: 6px;
346
346
  padding: 0 10px;
347
347
  font: inherit;
348
- color: var(--sa-heading);
349
- background: #fff;
348
+ color: var(--sa-color-fg-heading);
349
+ background: var(--sa-color-bg-surface);
350
350
  }
351
351
  .bvpd__error {
352
352
  margin: 8px 0 0;
353
- color: var(--q-negative, #c10015);
354
- font-size: 12px;
353
+ color: var(--sa-color-negative);
354
+ font-size: var(--sa-text-sm);
355
355
  font-weight: 700;
356
356
  }
357
357
  .bvpd__list {
358
358
  margin: 8px 0 0;
359
359
  padding-left: 20px;
360
- font-size: 13px;
360
+ font-size: var(--sa-text-md);
361
361
  }
362
362
  .bvpd__old {
363
- color: var(--q-negative, #c10015);
363
+ color: var(--sa-color-negative);
364
364
  text-decoration: line-through;
365
365
  }
366
366
  .bvpd__new {
367
- color: var(--q-positive, #21ba45);
367
+ color: var(--sa-color-positive);
368
368
  font-weight: 600;
369
369
  }
370
370
  </style>
@@ -15,22 +15,22 @@ defineProps<{ label: string; value: string }>();
15
15
 
16
16
  <style scoped>
17
17
  .kv {
18
- background: var(--sa-bg-surface-2);
19
- border: 1px solid var(--sa-border);
18
+ background: var(--sa-color-bg-sunken);
19
+ border: 1px solid var(--sa-color-border);
20
20
  border-radius: 10px;
21
21
  padding: 10px 12px;
22
22
  }
23
23
  .kv__label {
24
- color: var(--sa-muted);
25
- font-size: 11px;
24
+ color: var(--sa-color-fg-muted);
25
+ font-size: var(--sa-text-xs);
26
26
  text-transform: uppercase;
27
27
  letter-spacing: 0.05em;
28
28
  font-weight: 700;
29
29
  }
30
30
  .kv__value {
31
- font-size: 14px;
31
+ font-size: var(--sa-text-lg);
32
32
  font-weight: 600;
33
- color: var(--sa-heading);
33
+ color: var(--sa-color-fg-heading);
34
34
  margin-top: 4px;
35
35
  }
36
36
  </style>
@@ -581,65 +581,65 @@ async function onRemove(p: PromotionRow): Promise<void> {
581
581
  flex: 1;
582
582
  }
583
583
  .mc-promo-title {
584
- font-size: 15px;
584
+ font-size: var(--sa-text-lg);
585
585
  font-weight: 700;
586
586
  }
587
587
  .mc-promo-subtitle {
588
- font-size: 12px;
589
- color: var(--sa-muted);
588
+ font-size: var(--sa-text-sm);
589
+ color: var(--sa-color-fg-muted);
590
590
  }
591
591
  .mc-promo-stats {
592
592
  display: flex;
593
593
  gap: 8px;
594
594
  }
595
595
  .mc-promo-stat {
596
- font-size: 11px;
596
+ font-size: var(--sa-text-xs);
597
597
  font-weight: 600;
598
598
  padding: 3px 9px;
599
599
  border-radius: 999px;
600
- background: var(--sa-border-soft);
601
- color: var(--sa-muted-dark);
600
+ background: var(--sa-color-border-soft);
601
+ color: var(--sa-color-fg-secondary);
602
602
  }
603
603
  .mc-promo-stat.active {
604
- background: #dcfce7;
605
- color: #166534;
604
+ background: var(--sa-color-positive-surface-strong);
605
+ color: var(--sa-color-positive-fg);
606
606
  }
607
607
  .mc-promo-stat.scheduled {
608
- background: #dbeafe;
609
- color: var(--sa-primary-strong);
608
+ background: var(--sa-color-scheduled-surface);
609
+ color: var(--sa-color-scheduled-fg);
610
610
  }
611
611
  .mc-promo-stat.expired {
612
- background: var(--sa-border-soft);
613
- color: var(--sa-muted-light);
612
+ background: var(--sa-color-border-soft);
613
+ color: var(--sa-color-fg-subtle);
614
614
  }
615
615
  .mc-promo-timeline {
616
- background: #fff;
617
- border: 1px solid var(--sa-border);
616
+ background: var(--sa-color-bg-surface);
617
+ border: 1px solid var(--sa-color-border);
618
618
  border-radius: 10px;
619
619
  padding: 12px 14px;
620
620
  }
621
621
  .mc-promo-timeline-head {
622
- font-size: 11px;
623
- color: var(--sa-muted);
622
+ font-size: var(--sa-text-xs);
623
+ color: var(--sa-color-fg-muted);
624
624
  margin-bottom: 6px;
625
625
  }
626
626
  .mc-promo-timeline-chart {
627
627
  position: relative;
628
- border-left: 1px solid var(--sa-border);
628
+ border-left: 1px solid var(--sa-color-border);
629
629
  }
630
630
  .mc-promo-tick {
631
631
  position: absolute;
632
632
  top: 0;
633
633
  bottom: 0;
634
634
  width: 1px;
635
- background: var(--sa-border-soft);
635
+ background: var(--sa-color-border-soft);
636
636
  }
637
637
  .mc-promo-tick-label {
638
638
  position: absolute;
639
639
  bottom: 0;
640
640
  left: 3px;
641
- font-size: 9px;
642
- color: var(--sa-muted-light);
641
+ font-size: var(--sa-text-2xs);
642
+ color: var(--sa-color-fg-subtle);
643
643
  white-space: nowrap;
644
644
  }
645
645
  .mc-promo-today {
@@ -647,14 +647,14 @@ async function onRemove(p: PromotionRow): Promise<void> {
647
647
  top: 0;
648
648
  bottom: 18px;
649
649
  width: 0;
650
- border-left: 2px dashed #ef4444;
650
+ border-left: 2px dashed var(--sa-color-negative-strong);
651
651
  }
652
652
  .mc-promo-today span {
653
653
  position: absolute;
654
654
  top: -2px;
655
655
  left: 3px;
656
- font-size: 9px;
657
- color: #ef4444;
656
+ font-size: var(--sa-text-2xs);
657
+ color: var(--sa-color-negative-strong);
658
658
  font-weight: 700;
659
659
  }
660
660
  .mc-promo-bar {
@@ -671,8 +671,8 @@ async function onRemove(p: PromotionRow): Promise<void> {
671
671
  opacity: 0.45;
672
672
  }
673
673
  .mc-promo-bar-label {
674
- font-size: 10px;
675
- color: #fff;
674
+ font-size: var(--sa-text-2xs);
675
+ color: var(--sa-color-fg-on-accent);
676
676
  font-weight: 600;
677
677
  padding: 0 6px;
678
678
  white-space: nowrap;
@@ -680,9 +680,9 @@ async function onRemove(p: PromotionRow): Promise<void> {
680
680
  .mc-promo-empty {
681
681
  padding: 28px;
682
682
  text-align: center;
683
- color: var(--sa-muted-light);
684
- font-size: 13px;
685
- border: 1px dashed #cbd5e1;
683
+ color: var(--sa-color-fg-subtle);
684
+ font-size: var(--sa-text-md);
685
+ border: 1px dashed var(--sa-color-border-strong);
686
686
  border-radius: 10px;
687
687
  }
688
688
  .mc-promo-list {
@@ -694,14 +694,14 @@ async function onRemove(p: PromotionRow): Promise<void> {
694
694
  display: flex;
695
695
  align-items: center;
696
696
  gap: 12px;
697
- background: #fff;
698
- border: 1px solid var(--sa-border);
697
+ background: var(--sa-color-bg-surface);
698
+ border: 1px solid var(--sa-color-border);
699
699
  border-radius: 8px;
700
700
  padding: 10px 12px;
701
701
  cursor: pointer;
702
702
  }
703
703
  .mc-promo-row.expanded {
704
- border-color: #3f6bff;
704
+ border-color: var(--sa-color-accent);
705
705
  border-bottom-left-radius: 0;
706
706
  border-bottom-right-radius: 0;
707
707
  }
@@ -716,7 +716,7 @@ async function onRemove(p: PromotionRow): Promise<void> {
716
716
  min-width: 0;
717
717
  }
718
718
  .mc-promo-row-title {
719
- font-size: 13px;
719
+ font-size: var(--sa-text-md);
720
720
  font-weight: 600;
721
721
  }
722
722
  .mc-promo-row-sub {
@@ -727,57 +727,57 @@ async function onRemove(p: PromotionRow): Promise<void> {
727
727
  margin-top: 2px;
728
728
  }
729
729
  .mc-promo-typechip {
730
- font-size: 10px;
730
+ font-size: var(--sa-text-2xs);
731
731
  font-weight: 700;
732
- background: var(--sa-primary-50);
733
- color: var(--sa-primary-strong);
732
+ background: var(--sa-color-accent-surface-strong);
733
+ color: var(--sa-color-accent-strong);
734
734
  padding: 1px 6px;
735
735
  border-radius: 4px;
736
736
  }
737
737
  .mc-promo-planchip {
738
- font-size: 10px;
739
- background: var(--sa-border-soft);
740
- color: var(--sa-muted-dark);
738
+ font-size: var(--sa-text-2xs);
739
+ background: var(--sa-color-border-soft);
740
+ color: var(--sa-color-fg-secondary);
741
741
  padding: 1px 6px;
742
742
  border-radius: 4px;
743
743
  }
744
744
  .mc-promo-muted {
745
- font-size: 11px;
746
- color: var(--sa-muted-light);
745
+ font-size: var(--sa-text-xs);
746
+ color: var(--sa-color-fg-subtle);
747
747
  }
748
748
  .mc-promo-row-when {
749
- font-size: 11px;
750
- color: var(--sa-muted);
749
+ font-size: var(--sa-text-xs);
750
+ color: var(--sa-color-fg-muted);
751
751
  text-align: right;
752
752
  }
753
753
  .mc-promo-cycle {
754
754
  display: block;
755
- color: var(--sa-muted-light);
755
+ color: var(--sa-color-fg-subtle);
756
756
  }
757
757
  .mc-promo-status {
758
- font-size: 10px;
758
+ font-size: var(--sa-text-2xs);
759
759
  font-weight: 700;
760
760
  text-transform: uppercase;
761
761
  padding: 3px 8px;
762
762
  border-radius: 6px;
763
763
  }
764
764
  .mc-promo-status.active {
765
- background: #dcfce7;
766
- color: #166534;
765
+ background: var(--sa-color-positive-surface-strong);
766
+ color: var(--sa-color-positive-fg);
767
767
  }
768
768
  .mc-promo-status.scheduled {
769
- background: #dbeafe;
770
- color: var(--sa-primary-strong);
769
+ background: var(--sa-color-scheduled-surface);
770
+ color: var(--sa-color-scheduled-fg);
771
771
  }
772
772
  .mc-promo-status.expired {
773
- background: var(--sa-border-soft);
774
- color: var(--sa-muted-light);
773
+ background: var(--sa-color-border-soft);
774
+ color: var(--sa-color-fg-subtle);
775
775
  }
776
776
  .mc-promo-editor {
777
- border: 1px solid #3f6bff;
777
+ border: 1px solid var(--sa-color-accent);
778
778
  border-top: 0;
779
779
  border-radius: 0 0 8px 8px;
780
- background: var(--sa-bg-surface-2);
780
+ background: var(--sa-color-bg-sunken);
781
781
  padding: 14px;
782
782
  }
783
783
  .mc-promo-editor-grid {
@@ -791,18 +791,18 @@ async function onRemove(p: PromotionRow): Promise<void> {
791
791
  gap: 6px;
792
792
  }
793
793
  .mc-promo-label {
794
- font-size: 10px;
794
+ font-size: var(--sa-text-2xs);
795
795
  font-weight: 700;
796
796
  text-transform: uppercase;
797
797
  letter-spacing: 0.5px;
798
- color: var(--sa-muted-dark);
798
+ color: var(--sa-color-fg-secondary);
799
799
  margin-top: 6px;
800
800
  }
801
801
  .mc-promo-input {
802
- border: 1px solid #cbd5e1;
802
+ border: 1px solid var(--sa-color-border-strong);
803
803
  border-radius: 6px;
804
804
  padding: 6px 8px;
805
- font-size: 13px;
805
+ font-size: var(--sa-text-md);
806
806
  }
807
807
  .mc-promo-input--sm {
808
808
  max-width: 90px;
@@ -818,17 +818,17 @@ async function onRemove(p: PromotionRow): Promise<void> {
818
818
  gap: 6px;
819
819
  }
820
820
  .mc-promo-typeopt {
821
- border: 1px solid #cbd5e1;
822
- background: #fff;
821
+ border: 1px solid var(--sa-color-border-strong);
822
+ background: var(--sa-color-bg-surface);
823
823
  border-radius: 6px;
824
824
  padding: 5px 10px;
825
- font-size: 12px;
825
+ font-size: var(--sa-text-sm);
826
826
  cursor: pointer;
827
827
  }
828
828
  .mc-promo-typeopt.active {
829
- border-color: #3f6bff;
830
- background: var(--sa-primary-50);
831
- color: var(--sa-primary-strong);
829
+ border-color: var(--sa-color-accent);
830
+ background: var(--sa-color-accent-surface-strong);
831
+ color: var(--sa-color-accent-strong);
832
832
  font-weight: 600;
833
833
  }
834
834
  .mc-promo-planlist {
@@ -839,34 +839,34 @@ async function onRemove(p: PromotionRow): Promise<void> {
839
839
  .mc-promo-planopt {
840
840
  display: flex;
841
841
  justify-content: space-between;
842
- border: 1px solid #cbd5e1;
843
- background: #fff;
842
+ border: 1px solid var(--sa-color-border-strong);
843
+ background: var(--sa-color-bg-surface);
844
844
  border-radius: 6px;
845
845
  padding: 6px 10px;
846
- font-size: 12px;
846
+ font-size: var(--sa-text-sm);
847
847
  cursor: pointer;
848
848
  }
849
849
  .mc-promo-planopt.active {
850
- border-color: #3f6bff;
851
- background: var(--sa-primary-50);
850
+ border-color: var(--sa-color-accent);
851
+ background: var(--sa-color-accent-surface-strong);
852
852
  }
853
853
  .mc-promo-planopt code {
854
- color: var(--sa-muted-light);
855
- font-size: 10px;
854
+ color: var(--sa-color-fg-subtle);
855
+ font-size: var(--sa-text-2xs);
856
856
  }
857
857
  .mc-promo-i18n-block {
858
858
  display: flex;
859
859
  flex-direction: column;
860
860
  gap: 4px;
861
861
  padding: 8px;
862
- border: 1px solid var(--sa-border);
862
+ border: 1px solid var(--sa-color-border);
863
863
  border-radius: 8px;
864
- background: #fff;
864
+ background: var(--sa-color-bg-surface);
865
865
  }
866
866
  .mc-promo-i18n-code {
867
- font-size: 10px;
867
+ font-size: var(--sa-text-2xs);
868
868
  font-weight: 700;
869
- background: var(--sa-border-soft);
869
+ background: var(--sa-color-border-soft);
870
870
  padding: 2px 7px;
871
871
  border-radius: 5px;
872
872
  align-self: flex-start;
@@ -883,16 +883,16 @@ async function onRemove(p: PromotionRow): Promise<void> {
883
883
  cursor: pointer;
884
884
  }
885
885
  .mc-promo-colorbtn.active {
886
- border-color: var(--sa-heading);
886
+ border-color: var(--sa-color-fg-heading);
887
887
  }
888
888
  .mc-promo-delete {
889
889
  margin-top: 12px;
890
890
  align-self: flex-start;
891
- border: 1px solid #fecaca;
892
- background: #fef2f2;
893
- color: #b91c1c;
891
+ border: 1px solid var(--sa-color-negative-border);
892
+ background: var(--sa-color-negative-surface);
893
+ color: var(--sa-color-negative-fg);
894
894
  font-weight: 600;
895
- font-size: 12px;
895
+ font-size: var(--sa-text-sm);
896
896
  padding: 6px 12px;
897
897
  border-radius: 6px;
898
898
  cursor: pointer;
@@ -102,9 +102,9 @@ function onConfirm() {
102
102
  padding-bottom: 0;
103
103
  }
104
104
  code {
105
- background: rgba(15, 23, 42, 0.06);
105
+ background: var(--sa-color-bg-sunken);
106
106
  padding: 1px 6px;
107
107
  border-radius: 4px;
108
- font-size: 11px;
108
+ font-size: var(--sa-text-xs);
109
109
  }
110
110
  </style>
@@ -236,19 +236,19 @@ function onCancel(): void {
236
236
  }
237
237
  .tenant-action-confirm__lead {
238
238
  margin: 0 0 12px;
239
- color: var(--sa-muted-dark);
239
+ color: var(--sa-color-fg-secondary);
240
240
  line-height: 1.5;
241
241
  }
242
242
  .tenant-action-confirm__hint {
243
243
  margin: 0 0 8px;
244
- color: var(--sa-muted-dark);
245
- font-size: 13px;
244
+ color: var(--sa-color-fg-secondary);
245
+ font-size: var(--sa-text-md);
246
246
  }
247
247
  .tenant-action-confirm__hint code {
248
- background: var(--sa-border-soft);
248
+ background: var(--sa-color-border-soft);
249
249
  padding: 1px 6px;
250
250
  border-radius: 4px;
251
251
  font-family: ui-monospace, SFMono-Regular, monospace;
252
- font-size: 13px;
252
+ font-size: var(--sa-text-md);
253
253
  }
254
254
  </style>
@@ -109,12 +109,12 @@ function formatValue(value: unknown): string {
109
109
 
110
110
  <style scoped>
111
111
  .sa-diff-preview__empty {
112
- color: var(--sa-muted);
112
+ color: var(--sa-color-fg-muted);
113
113
  font-style: italic;
114
114
  padding: 12px;
115
- background: var(--sa-bg-surface-2);
115
+ background: var(--sa-color-bg-sunken);
116
116
  border-radius: 8px;
117
- border: 1px dashed #cbd5e1;
117
+ border: 1px dashed var(--sa-color-border-strong);
118
118
  }
119
119
  .sa-diff-preview__list {
120
120
  display: flex;
@@ -128,35 +128,35 @@ function formatValue(value: unknown): string {
128
128
  padding: 8px 12px;
129
129
  border-radius: 8px;
130
130
  border: 1px solid;
131
- font-size: 13px;
131
+ font-size: var(--sa-text-md);
132
132
  align-items: center;
133
133
  }
134
134
  .sa-diff-preview__row--improvement {
135
- background: #f0fdf4;
136
- border-color: #bbf7d0;
137
- color: #166534;
135
+ background: var(--sa-color-positive-surface);
136
+ border-color: var(--sa-color-positive-border);
137
+ color: var(--sa-color-positive-fg);
138
138
  }
139
139
  .sa-diff-preview__row--regression {
140
- background: #fef2f2;
141
- border-color: #fecaca;
142
- color: #991b1b;
140
+ background: var(--sa-color-negative-surface);
141
+ border-color: var(--sa-color-negative-border);
142
+ color: var(--sa-color-negative-fg);
143
143
  }
144
144
  .sa-diff-preview__row--neutral {
145
- background: var(--sa-bg-surface-2);
146
- border-color: var(--sa-border);
147
- color: var(--sa-muted-dark);
145
+ background: var(--sa-color-bg-sunken);
146
+ border-color: var(--sa-color-border);
147
+ color: var(--sa-color-fg-secondary);
148
148
  }
149
149
  .sa-diff-preview__direction {
150
150
  display: flex;
151
151
  align-items: center;
152
152
  gap: 6px;
153
153
  font-weight: 600;
154
- font-size: 12px;
154
+ font-size: var(--sa-text-sm);
155
155
  text-transform: uppercase;
156
156
  letter-spacing: 0.04em;
157
157
  }
158
158
  .sa-diff-preview__field {
159
- color: var(--sa-heading);
159
+ color: var(--sa-color-fg-heading);
160
160
  font-weight: 500;
161
161
  }
162
162
  .sa-diff-preview__values {
@@ -165,15 +165,15 @@ function formatValue(value: unknown): string {
165
165
  gap: 8px;
166
166
  }
167
167
  .sa-diff-preview__values .old {
168
- color: var(--sa-muted-light);
168
+ color: var(--sa-color-fg-subtle);
169
169
  text-decoration: line-through;
170
170
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
171
- font-size: 12px;
171
+ font-size: var(--sa-text-sm);
172
172
  }
173
173
  .sa-diff-preview__values .new {
174
174
  color: inherit;
175
175
  font-weight: 600;
176
176
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
177
- font-size: 12px;
177
+ font-size: var(--sa-text-sm);
178
178
  }
179
179
  </style>