@saasicat/ui-vue 0.21.0 → 0.22.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 (132) hide show
  1. package/dist/{catalog-BY_t9prv.d.cts → catalog-DJcfm5N2.d.cts} +20 -7
  2. package/dist/{catalog-BY_t9prv.d.ts → catalog-DJcfm5N2.d.ts} +20 -7
  3. package/dist/{chunk-JN6HZGLV.js → chunk-F7NRM6KI.js} +54 -28
  4. package/dist/{chunk-7IFKVGZV.js → chunk-LY52T4N4.js} +21 -2
  5. package/dist/{chunk-OTP3OSSW.js → chunk-XMMFN2WJ.js} +74 -3
  6. package/dist/client/index.cjs +132 -29
  7. package/dist/client/index.d.cts +53 -3
  8. package/dist/client/index.d.ts +53 -3
  9. package/dist/client/index.js +14 -2
  10. package/dist/index.cjs +319 -162
  11. package/dist/index.d.cts +30 -8
  12. package/dist/index.d.ts +30 -8
  13. package/dist/index.js +176 -133
  14. package/dist/quasar/index.cjs +76 -29
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +6 -2
  18. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  19. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  20. package/dist/{use-super-admin-i18n-c_Eqsu9u.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
  21. package/dist/{use-super-admin-i18n-DlJRGIVq.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
  22. package/package.json +18 -8
  23. package/src/client/i18n/messages/bundles.ts +0 -2
  24. package/src/client/i18n/messages/common.ts +22 -0
  25. package/src/client/i18n/messages/discovery.ts +2 -2
  26. package/src/client/i18n/messages/marketing.ts +2 -4
  27. package/src/client/i18n/messages/plan-detail.ts +0 -4
  28. package/src/client/i18n/messages/plans.ts +20 -8
  29. package/src/client/i18n/messages/tenants.ts +0 -2
  30. package/src/client/index.ts +1 -0
  31. package/src/client/manifest-loader.ts +1 -1
  32. package/src/client/resolve-plans.ts +144 -0
  33. package/src/components/BundleVersionPublishDialog.vue +6 -6
  34. package/src/components/KvBlock.vue +4 -4
  35. package/src/components/MarketingPromotionsTab.vue +34 -48
  36. package/src/components/MfaPromptDialog.vue +8 -2
  37. package/src/components/TenantActionConfirmDialog.vue +4 -4
  38. package/src/components/VersionDiffPreview.vue +7 -7
  39. package/src/components/admin-page/AdminFilters.vue +12 -0
  40. package/src/components/admin-page/AdminHero.vue +22 -5
  41. package/src/components/admin-page/AdminKpi.vue +84 -0
  42. package/src/components/admin-page/AdminPaginator.vue +195 -0
  43. package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
  44. package/src/components/admin-page/AdminSection.vue +31 -16
  45. package/src/components/admin-page/AdminStatistics.vue +40 -0
  46. package/src/components/admin-page/AdminTable.vue +175 -0
  47. package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
  48. package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
  49. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
  50. package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
  51. package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
  52. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
  53. package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
  54. package/src/components/dialogs/PilotCreateDialog.vue +12 -12
  55. package/src/components/dialogs/PilotEditDialog.vue +7 -7
  56. package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
  57. package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
  58. package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
  59. package/src/components/plan/PlanGrid.vue +1 -1
  60. package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
  61. package/src/components/plan-detail/PlanDetail.vue +92 -302
  62. package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
  63. package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
  64. package/src/components/plan-list/PlanList.vue +72 -290
  65. package/src/components/plan-matrix/PlanMatrix.vue +66 -183
  66. package/src/components/plan-review/PlanReview.vue +191 -275
  67. package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
  68. package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
  69. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
  70. package/src/index.ts +1 -0
  71. package/src/pages-standard/AdminLayout.vue +34 -10
  72. package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
  73. package/src/pages-standard/AuditPage.vue +53 -72
  74. package/src/pages-standard/BundlesPage.vue +128 -144
  75. package/src/pages-standard/DashboardPage.vue +43 -107
  76. package/src/pages-standard/DiscoveryPage.vue +158 -200
  77. package/src/pages-standard/EmailHistoryPage.vue +98 -88
  78. package/src/pages-standard/MarketingCatalogPage.vue +237 -267
  79. package/src/pages-standard/PilotsPage.vue +44 -60
  80. package/src/pages-standard/PlansPage.vue +230 -105
  81. package/src/pages-standard/PlatformEmailPage.vue +37 -40
  82. package/src/pages-standard/PromoCodeDetailPage.vue +16 -30
  83. package/src/pages-standard/PromoCodesPage.vue +86 -112
  84. package/src/pages-standard/SubscriptionsPage.vue +10 -17
  85. package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
  86. package/src/pages-standard/SuperAdminSetupWizard.vue +20 -17
  87. package/src/pages-standard/TenantDetailPage.vue +45 -41
  88. package/src/pages-standard/TenantsPage.vue +184 -264
  89. package/src/pages-standard/UsersPage.vue +69 -104
  90. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
  91. package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
  92. package/src/pages-standard/bundles-page/BundlesToolbar.vue +6 -10
  93. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
  94. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
  95. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
  96. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
  97. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
  98. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +1 -1
  99. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +2 -13
  100. package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
  101. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
  102. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
  103. package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
  104. package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
  105. package/src/pages-standard/plans-page/PlansPageToast.vue +1 -1
  106. package/src/pages-standard/sa-theme.css +481 -71
  107. package/src/pages-standard/tenant-detail/TenantUsers.vue +2 -8
  108. package/src/pages-standard/tenants/StatusPill.vue +2 -2
  109. package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
  110. package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
  111. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  112. package/src/pages-tenant/TenantPlanSection.vue +12 -20
  113. package/src/quasar/create-super-admin-app.ts +4 -0
  114. package/src/vue/entitlement-provider.ts +0 -1
  115. package/src/vue/feature-router-guard.ts +0 -1
  116. package/src/vue/super-admin-context.ts +106 -1
  117. package/src/vue/use-api-list.ts +2 -1
  118. package/src/vue/use-pagination.ts +63 -0
  119. package/src/vue/use-plans.ts +1 -2
  120. package/src/vue/use-sign-out.ts +90 -0
  121. package/src/vue/use-tenant-billing.ts +1 -1
  122. package/src/vue/use-tenant-manifest.ts +0 -1
  123. package/src/components/KpiCard.vue +0 -53
  124. package/src/components/plan-cockpit/PlanCockpit.vue +0 -1027
  125. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
  126. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -99
  127. package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
  128. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
  129. package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
  130. package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -249
  131. package/src/components/plan-cockpit/types.ts +0 -72
  132. package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
@@ -1,5 +1,5 @@
1
1
  <!--
2
- MarketingCatalogPage — marketing catalog for SuperAdmin (SPEC_V2 §11.1 M3).
2
+ MarketingCatalogPage — marketing catalog for SuperAdmin.
3
3
 
4
4
  Public marketing projection per plan: filtered view for website,
5
5
  pricing page and checkout. Two tabs:
@@ -35,81 +35,95 @@
35
35
  </template>
36
36
  </AdminHero>
37
37
 
38
- <div v-if="pageError" class="sa-marketing-banner sa-marketing-banner--error" role="alert">
39
- <strong>{{ common.error }}:</strong> {{ pageError }}
40
- <button class="sa-marketing-banner-x" type="button" @click="pageError = null">×</button>
41
- </div>
42
-
43
- <MarketingCatalogToolbar
44
- v-model:tab="tab"
45
- :active-promo-count="activePromoCount"
46
- :catalog-version="catalogVersion"
47
- :active-locale="activeLocale"
48
- />
49
-
50
- <div v-if="loading" class="sa-marketing-loading">{{ msg.page.loading }}</div>
51
-
52
- <!-- ─── Tab: Promotions ─── -->
53
- <MarketingPromotionsTab
54
- v-else-if="tab === 'promos'"
55
- :promotions="promotions"
56
- :plans="promoPlanOptions"
57
- :active-locales="activeLocaleSet"
58
- :busy="busy"
59
- :project-key="projectKey"
60
- :create="promotionsApi.create"
61
- :update="promotionsApi.update"
62
- :remove="promotionsApi.remove"
63
- />
64
-
65
- <div v-else-if="rows.length === 0" class="sa-marketing-banner sa-marketing-banner--info">
66
- {{ msg.page.emptyPlansBefore }} <strong>{{ msg.page.emptyPlansLink }}</strong>
67
- {{ msg.page.emptyPlansAfter }}
68
- </div>
69
-
70
- <MarketingCatalogPreview
71
- v-else-if="tab === 'preview'"
72
- :visible-rows="visibleRows"
73
- :preview-url="previewUrl"
74
- :monthly-of="monthlyOf"
75
- :yearly-of="yearlyOf"
76
- :format-euro="formatEuro"
77
- :promo-of="promoOf"
78
- :promo-result-of="promoResultOf"
79
- :promo-badge-of="promoBadgeOf"
80
- :promo-fineprint-of="promoFineprintOf"
81
- :promo-color-of="promoColorOf"
82
- :cta-text="ctaText"
83
- :show-trial-note="showTrialNote"
84
- :top-feature-label="topFeatureLabel"
85
- />
86
-
87
- <MarketingCatalogAdmin
88
- v-else
89
- :admin-rows="adminRows"
90
- :busy="busy"
91
- :expanded-key="expandedKey"
92
- :active-locale="activeLocale"
93
- :default-locale="defaultLocale"
94
- :edit-features="editFeatures"
95
- :format-version-title="formatVersionTitle"
96
- :format-version-tab="formatVersionTab"
97
- :auto-cta-text="autoCtaText"
98
- :cta-value="ctaValue"
99
- :resolve-component-label="resolveComponentLabel"
100
- :suggestions-for="suggestionsFor"
101
- @select-version="selectVersion"
102
- @patch="patch"
103
- @patch-display-label="patchDisplayLabel"
104
- @toggle-expand="toggleExpand"
105
- @update-feature-label="updateFeatureLabel"
106
- @update-feature-strong="updateFeatureStrong"
107
- @persist-features="persistFeatures"
108
- @move-feature="moveFeature"
109
- @remove-feature="removeFeature"
110
- @add-feature="addFeature"
111
- @add-suggestion="addSuggestion"
112
- />
38
+ <AdminBody>
39
+ <AdminSection>
40
+ <div
41
+ v-if="pageError"
42
+ class="sa-marketing-banner sa-marketing-banner--error"
43
+ role="alert"
44
+ >
45
+ <strong>{{ common.error }}:</strong> {{ pageError }}
46
+ <button class="sa-marketing-banner-x" type="button" @click="pageError = null">
47
+ ×
48
+ </button>
49
+ </div>
50
+
51
+ <MarketingCatalogToolbar
52
+ v-model:tab="tab"
53
+ :active-promo-count="activePromoCount"
54
+ :catalog-version="catalogVersion"
55
+ :active-locale="activeLocale"
56
+ />
57
+ </AdminSection>
58
+ <AdminSection>
59
+ <div v-if="loading" class="sa-marketing-loading">{{ msg.page.loading }}</div>
60
+
61
+ <!-- ─── Tab: Promotions ─── -->
62
+ <MarketingPromotionsTab
63
+ v-else-if="tab === 'promos'"
64
+ :promotions="promotions"
65
+ :plans="promoPlanOptions"
66
+ :active-locales="activeLocaleSet"
67
+ :busy="busy"
68
+ :project-key="projectKey"
69
+ :create="promotionsApi.create"
70
+ :update="promotionsApi.update"
71
+ :remove="promotionsApi.remove"
72
+ />
73
+
74
+ <div
75
+ v-else-if="rows.length === 0"
76
+ class="sa-marketing-banner sa-marketing-banner--info"
77
+ >
78
+ {{ msg.page.emptyPlansBefore }} <strong>{{ msg.page.emptyPlansLink }}</strong>
79
+ {{ msg.page.emptyPlansAfter }}
80
+ </div>
81
+
82
+ <MarketingCatalogPreview
83
+ v-else-if="tab === 'preview'"
84
+ :visible-rows="visibleRows"
85
+ :preview-url="previewUrl"
86
+ :monthly-of="monthlyOf"
87
+ :yearly-of="yearlyOf"
88
+ :format-euro="formatEuro"
89
+ :promo-of="promoOf"
90
+ :promo-result-of="promoResultOf"
91
+ :promo-badge-of="promoBadgeOf"
92
+ :promo-fineprint-of="promoFineprintOf"
93
+ :promo-color-of="promoColorOf"
94
+ :cta-text="ctaText"
95
+ :show-trial-note="showTrialNote"
96
+ :top-feature-label="topFeatureLabel"
97
+ />
98
+
99
+ <MarketingCatalogAdmin
100
+ v-else
101
+ :admin-rows="adminRows"
102
+ :busy="busy"
103
+ :expanded-key="expandedKey"
104
+ :active-locale="activeLocale"
105
+ :default-locale="defaultLocale"
106
+ :edit-features="editFeatures"
107
+ :format-version-title="formatVersionTitle"
108
+ :format-version-tab="formatVersionTab"
109
+ :auto-cta-text="autoCtaText"
110
+ :cta-value="ctaValue"
111
+ :resolve-component-label="resolveComponentLabel"
112
+ :suggestions-for="suggestionsFor"
113
+ @select-version="selectVersion"
114
+ @patch="patch"
115
+ @patch-display-label="patchDisplayLabel"
116
+ @toggle-expand="toggleExpand"
117
+ @update-feature-label="updateFeatureLabel"
118
+ @update-feature-strong="updateFeatureStrong"
119
+ @persist-features="persistFeatures"
120
+ @move-feature="moveFeature"
121
+ @remove-feature="removeFeature"
122
+ @add-feature="addFeature"
123
+ @add-suggestion="addSuggestion"
124
+ />
125
+ </AdminSection>
126
+ </AdminBody>
113
127
  </AdminPage>
114
128
  </template>
115
129
 
@@ -117,6 +131,8 @@
117
131
  import { computed, onMounted, ref } from 'vue';
118
132
  import AdminHero from '../components/admin-page/AdminHero.vue';
119
133
  import AdminPage from '../components/admin-page/AdminPage.vue';
134
+ import AdminBody from '../components/admin-page/AdminBody.vue';
135
+ import AdminSection from '../components/admin-page/AdminSection.vue';
120
136
  import {
121
137
  applyPromo,
122
138
  pickActivePromo,
@@ -177,8 +193,8 @@ const tab = ref<MarketingCatalogTab>('preview');
177
193
  const expandedKey = ref<string | null>(null);
178
194
  const activeLocale = ref<string>(availableLocales.value[0]);
179
195
 
180
- // LocaleManager — `availableLocales` is the allowed pool (app config,
181
- // SPEC_V2 §6.5), `activeLocaleSet` the runtime-activated subset.
196
+ // LocaleManager — `availableLocales` is the allowed pool (app config),
197
+ // `activeLocaleSet` the runtime-activated subset.
182
198
  // Persisted via `/admin/catalog/marketing-settings` (MarketingSettings).
183
199
  const defaultLocale = computed(() => availableLocales.value[0]);
184
200
  const activeLocaleSet = ref<string[]>([...availableLocales.value]);
@@ -268,7 +284,7 @@ const promotionsApi = usePromotions({
268
284
  });
269
285
 
270
286
  // Catalog entries (features + quotas with i18n) — provides the translated
271
- // labels for the top-features editor (SPEC_V2 §6.3 + §6.5).
287
+ // labels for the top-features editor.
272
288
  const catalogEntriesApi = useCatalogEntries({
273
289
  adminEndpoint: props.adminEndpoint,
274
290
  projectKey: props.projectKey,
@@ -407,7 +423,7 @@ function publishedVersionsOf(plan: PlanRow): PlanVersionRow[] {
407
423
  }
408
424
 
409
425
  /**
410
- * Version active as of `asOf` (SPEC_V2 §4.2): `validFrom <= asOf` and
426
+ * Version active as of `asOf`: `validFrom <= asOf` and
411
427
  * (`validUntil == null OR validUntil > asOf`). Default is the version
412
428
  * active today. Fallback when no `validFrom` data is maintained:
413
429
  * highest version.
@@ -603,7 +619,7 @@ function formatEuro(value: number): string {
603
619
  return formatCurrency(Math.round(value * 100) / 100, locale.value);
604
620
  }
605
621
 
606
- // ─── Promo application in the preview (SPEC_V2 §9a) ───
622
+ // ─── Promo application in the preview ───
607
623
  const promoToday = new Date();
608
624
  function promoOf(row: MarketingRow): PromotionRow | null {
609
625
  return pickActivePromo(
@@ -822,31 +838,13 @@ async function onLocaleChange(loc: string): Promise<void> {
822
838
 
823
839
  <style>
824
840
  .sa-marketing {
825
- --sa-marketing-bg: #f6f7f9;
826
- --sa-marketing-surface: #ffffff;
827
- --sa-marketing-surface-2: #f8fafc;
828
- --sa-marketing-border: #e5e7eb;
829
- --sa-marketing-border-strong: #d1d5db;
830
- --sa-marketing-text: #0f172a;
831
- --sa-marketing-text-2: #475569;
832
- --sa-marketing-text-3: #94a3b8;
833
- --sa-marketing-primary: #2563eb;
834
- --sa-marketing-primary-700: #1d4ed8;
835
- --sa-marketing-primary-50: #eff6ff;
836
- --sa-marketing-font-sans:
837
- 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
838
- --sa-marketing-font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
839
-
840
841
  padding: 22px 26px;
841
- background: var(--sa-marketing-bg);
842
- color: var(--sa-marketing-text);
843
- font-family: var(--sa-marketing-font-sans);
842
+ background: var(--sa-bg-app);
843
+ color: var(--sa-heading);
844
+ font-family: var(--sa-font-body);
844
845
  min-height: 100%;
845
846
  box-sizing: border-box;
846
847
  }
847
- .sa-marketing * {
848
- box-sizing: border-box;
849
- }
850
848
 
851
849
  .sa-marketing-head-actions {
852
850
  display: flex;
@@ -857,8 +855,8 @@ async function onLocaleChange(loc: string): Promise<void> {
857
855
  .sa-marketing-locale-switch {
858
856
  display: inline-flex;
859
857
  gap: 2px;
860
- background: var(--sa-marketing-surface);
861
- border: 1px solid var(--sa-marketing-border);
858
+ background: var(--sa-bg-surface);
859
+ border: 1px solid var(--sa-border);
862
860
  border-radius: 8px;
863
861
  padding: 3px;
864
862
  }
@@ -867,13 +865,13 @@ async function onLocaleChange(loc: string): Promise<void> {
867
865
  border: 0;
868
866
  background: transparent;
869
867
  border-radius: 6px;
870
- font: 500 12px var(--sa-marketing-font-mono);
871
- color: var(--sa-marketing-text-2);
868
+ font: 500 12px var(--sa-font-mono);
869
+ color: var(--sa-muted-dark);
872
870
  cursor: pointer;
873
871
  }
874
872
  .sa-marketing-locale-btn.active {
875
- background: var(--sa-marketing-primary-50);
876
- color: var(--sa-marketing-primary-700);
873
+ background: var(--sa-primary-50);
874
+ color: var(--sa-primary-strong);
877
875
  font-weight: 600;
878
876
  }
879
877
  .sa-marketing-locale-mgr {
@@ -884,35 +882,35 @@ async function onLocaleChange(loc: string): Promise<void> {
884
882
  }
885
883
  .sa-marketing-locale-mgr-label {
886
884
  font-size: 11px;
887
- color: var(--sa-marketing-text-3);
885
+ color: var(--sa-muted-light);
888
886
  }
889
887
  .sa-marketing-locale-pill {
890
888
  display: inline-flex;
891
889
  align-items: center;
892
- border: 1px solid var(--sa-marketing-border);
890
+ border: 1px solid var(--sa-border);
893
891
  border-radius: 7px;
894
892
  overflow: hidden;
895
893
  }
896
894
  .sa-marketing-locale-pill.active {
897
- border-color: var(--sa-marketing-primary-700);
898
- background: var(--sa-marketing-primary-50);
895
+ border-color: var(--sa-primary-strong);
896
+ background: var(--sa-primary-50);
899
897
  }
900
898
  .sa-marketing-locale-pill-btn {
901
899
  border: 0;
902
900
  background: transparent;
903
901
  padding: 4px 8px;
904
- font: 600 11px var(--sa-marketing-font-mono);
905
- color: var(--sa-marketing-text-2);
902
+ font: 600 11px var(--sa-font-mono);
903
+ color: var(--sa-muted-dark);
906
904
  cursor: pointer;
907
905
  }
908
906
  .sa-marketing-locale-pill.active .sa-marketing-locale-pill-btn {
909
- color: var(--sa-marketing-primary-700);
907
+ color: var(--sa-primary-strong);
910
908
  }
911
909
  .sa-marketing-locale-x {
912
910
  border: 0;
913
911
  background: transparent;
914
912
  padding: 4px 7px;
915
- color: var(--sa-marketing-text-3);
913
+ color: var(--sa-muted-light);
916
914
  cursor: pointer;
917
915
  font-size: 13px;
918
916
  }
@@ -923,12 +921,12 @@ async function onLocaleChange(loc: string): Promise<void> {
923
921
  position: relative;
924
922
  }
925
923
  .sa-marketing-locale-add {
926
- border: 1px dashed var(--sa-marketing-border);
924
+ border: 1px dashed var(--sa-border);
927
925
  background: transparent;
928
926
  border-radius: 7px;
929
927
  padding: 4px 9px;
930
928
  font-size: 11px;
931
- color: var(--sa-marketing-text-2);
929
+ color: var(--sa-muted-dark);
932
930
  cursor: pointer;
933
931
  }
934
932
  .sa-marketing-locale-add:disabled {
@@ -940,8 +938,8 @@ async function onLocaleChange(loc: string): Promise<void> {
940
938
  top: 100%;
941
939
  right: 0;
942
940
  margin-top: 4px;
943
- background: var(--sa-marketing-surface);
944
- border: 1px solid var(--sa-marketing-border);
941
+ background: var(--sa-bg-surface);
942
+ border: 1px solid var(--sa-border);
945
943
  border-radius: 8px;
946
944
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
947
945
  padding: 4px;
@@ -957,39 +955,11 @@ async function onLocaleChange(loc: string): Promise<void> {
957
955
  padding: 6px 10px;
958
956
  text-align: left;
959
957
  border-radius: 6px;
960
- font: 600 11px var(--sa-marketing-font-mono);
958
+ font: 600 11px var(--sa-font-mono);
961
959
  cursor: pointer;
962
960
  }
963
961
  .sa-marketing-locale-picker-row:hover {
964
- background: var(--sa-marketing-primary-50);
965
- }
966
-
967
- .sa-marketing-btn {
968
- display: inline-flex;
969
- align-items: center;
970
- gap: 7px;
971
- padding: 8px 14px;
972
- border-radius: 7px;
973
- font: 500 13px var(--sa-marketing-font-sans);
974
- cursor: pointer;
975
- border: 1px solid var(--sa-marketing-border-strong);
976
- background: var(--sa-marketing-surface);
977
- color: var(--sa-marketing-text);
978
- transition:
979
- background 0.12s,
980
- border-color 0.12s;
981
- }
982
- .sa-marketing-btn:hover:not(:disabled) {
983
- background: #f8fafc;
984
- }
985
- .sa-marketing-btn:disabled {
986
- opacity: 0.5;
987
- cursor: not-allowed;
988
- }
989
- .sa-marketing-btn--sm {
990
- padding: 5px 9px;
991
- font-size: 12px;
992
- gap: 5px;
962
+ background: var(--sa-primary-50);
993
963
  }
994
964
 
995
965
  .sa-marketing-banner {
@@ -1007,7 +977,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1007
977
  border: 1px solid #fca5a5;
1008
978
  }
1009
979
  .sa-marketing-banner--info {
1010
- background: var(--sa-marketing-primary-50);
980
+ background: var(--sa-primary-50);
1011
981
  color: #1e40af;
1012
982
  border: 1px solid #bfdbfe;
1013
983
  }
@@ -1023,7 +993,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1023
993
  .sa-marketing-loading {
1024
994
  padding: 40px;
1025
995
  text-align: center;
1026
- color: var(--sa-marketing-text-3);
996
+ color: var(--sa-muted-light);
1027
997
  font-size: 13px;
1028
998
  }
1029
999
 
@@ -1031,21 +1001,21 @@ async function onLocaleChange(loc: string): Promise<void> {
1031
1001
  display: flex;
1032
1002
  gap: 12px;
1033
1003
  align-items: center;
1034
- margin: 4px 0 16px;
1004
+ margin: 0px;
1035
1005
  }
1036
1006
  .sa-marketing-tabbar {
1037
1007
  display: inline-flex;
1038
1008
  gap: 2px;
1039
- background: var(--sa-marketing-surface);
1040
- border: 1px solid var(--sa-marketing-border);
1009
+ background: var(--sa-bg-surface);
1010
+ border: 1px solid var(--sa-border);
1041
1011
  border-radius: 8px;
1042
1012
  padding: 3px;
1043
1013
  }
1044
1014
  .sa-marketing-tab {
1045
1015
  padding: 6px 14px;
1046
1016
  border-radius: 6px;
1047
- font: 500 13px var(--sa-marketing-font-sans);
1048
- color: var(--sa-marketing-text-2);
1017
+ font: 500 13px var(--sa-font-body);
1018
+ color: var(--sa-muted-dark);
1049
1019
  background: transparent;
1050
1020
  border: 0;
1051
1021
  cursor: pointer;
@@ -1054,11 +1024,11 @@ async function onLocaleChange(loc: string): Promise<void> {
1054
1024
  color 0.12s;
1055
1025
  }
1056
1026
  .sa-marketing-tab:hover {
1057
- color: var(--sa-marketing-text);
1027
+ color: var(--sa-heading);
1058
1028
  }
1059
1029
  .sa-marketing-tab.active {
1060
- background: var(--sa-marketing-primary-50);
1061
- color: var(--sa-marketing-primary-700);
1030
+ background: var(--sa-primary-50);
1031
+ color: var(--sa-primary-strong);
1062
1032
  font-weight: 600;
1063
1033
  }
1064
1034
  .sa-marketing-tab-count {
@@ -1074,30 +1044,30 @@ async function onLocaleChange(loc: string): Promise<void> {
1074
1044
  .sa-marketing-meta {
1075
1045
  margin-left: auto;
1076
1046
  font-size: 12px;
1077
- color: var(--sa-marketing-text-2);
1047
+ color: var(--sa-muted-dark);
1078
1048
  display: flex;
1079
1049
  align-items: center;
1080
1050
  gap: 8px;
1081
1051
  }
1082
1052
  .sa-marketing-meta code {
1083
- font: 500 11px var(--sa-marketing-font-mono);
1084
- background: #f1f5f9;
1085
- color: #475569;
1053
+ font: 500 11px var(--sa-font-mono);
1054
+ background: var(--sa-border-soft);
1055
+ color: var(--sa-muted-dark);
1086
1056
  padding: 2px 7px;
1087
1057
  border-radius: 4px;
1088
1058
  }
1089
1059
 
1090
1060
  /* ── Public catalog preview ── */
1091
1061
  .sa-marketing-window {
1092
- background: var(--sa-marketing-surface);
1093
- border: 1px solid var(--sa-marketing-border);
1062
+ background: var(--sa-bg-surface);
1063
+ border: 1px solid var(--sa-border);
1094
1064
  border-radius: 12px;
1095
1065
  overflow: hidden;
1096
1066
  }
1097
1067
  .sa-marketing-chrome {
1098
1068
  height: 36px;
1099
- background: #f1f5f9;
1100
- border-bottom: 1px solid var(--sa-marketing-border);
1069
+ background: var(--sa-border-soft);
1070
+ border-bottom: 1px solid var(--sa-border);
1101
1071
  display: flex;
1102
1072
  align-items: center;
1103
1073
  padding: 0 14px;
@@ -1111,12 +1081,12 @@ async function onLocaleChange(loc: string): Promise<void> {
1111
1081
  .sa-marketing-chrome-url {
1112
1082
  margin-left: 18px;
1113
1083
  flex: 1;
1114
- background: var(--sa-marketing-surface);
1115
- border: 1px solid #e2e8f0;
1084
+ background: var(--sa-bg-surface);
1085
+ border: 1px solid var(--sa-border);
1116
1086
  border-radius: 6px;
1117
1087
  padding: 4px 10px;
1118
- font: 500 11.5px var(--sa-marketing-font-mono);
1119
- color: #475569;
1088
+ font: 500 11.5px var(--sa-font-mono);
1089
+ color: var(--sa-muted-dark);
1120
1090
  max-width: 380px;
1121
1091
  }
1122
1092
  .sa-marketing-canvas {
@@ -1124,23 +1094,23 @@ async function onLocaleChange(loc: string): Promise<void> {
1124
1094
  padding: 36px 32px 28px;
1125
1095
  }
1126
1096
  .sa-marketing-eyebrow {
1127
- font: 700 11px var(--sa-marketing-font-sans);
1097
+ font: 700 11px var(--sa-font-body);
1128
1098
  letter-spacing: 0.14em;
1129
1099
  text-transform: uppercase;
1130
- color: var(--sa-marketing-primary);
1100
+ color: var(--sa-primary);
1131
1101
  text-align: center;
1132
1102
  }
1133
1103
  .sa-marketing-hero {
1134
1104
  font-size: 32px;
1135
1105
  font-weight: 700;
1136
1106
  letter-spacing: -0.025em;
1137
- color: var(--sa-marketing-text);
1107
+ color: var(--sa-heading);
1138
1108
  text-align: center;
1139
1109
  margin: 10px 0 6px;
1140
1110
  }
1141
1111
  .sa-marketing-sub {
1142
1112
  font-size: 14px;
1143
- color: var(--sa-marketing-text-2);
1113
+ color: var(--sa-muted-dark);
1144
1114
  text-align: center;
1145
1115
  max-width: 540px;
1146
1116
  margin: 0 auto 26px;
@@ -1151,8 +1121,8 @@ async function onLocaleChange(loc: string): Promise<void> {
1151
1121
  gap: 16px;
1152
1122
  }
1153
1123
  .sa-marketing-card {
1154
- background: var(--sa-marketing-surface);
1155
- border: 1px solid var(--sa-marketing-border);
1124
+ background: var(--sa-bg-surface);
1125
+ border: 1px solid var(--sa-border);
1156
1126
  border-radius: 12px;
1157
1127
  padding: 22px 20px 20px;
1158
1128
  display: flex;
@@ -1176,9 +1146,9 @@ async function onLocaleChange(loc: string): Promise<void> {
1176
1146
  top: -10px;
1177
1147
  left: 50%;
1178
1148
  transform: translateX(-50%);
1179
- background: var(--sa-marketing-primary);
1149
+ background: var(--sa-primary);
1180
1150
  color: #fff;
1181
- font: 700 10.5px var(--sa-marketing-font-sans);
1151
+ font: 700 10.5px var(--sa-font-body);
1182
1152
  letter-spacing: 0.1em;
1183
1153
  text-transform: uppercase;
1184
1154
  padding: 4px 12px;
@@ -1186,21 +1156,21 @@ async function onLocaleChange(loc: string): Promise<void> {
1186
1156
  white-space: nowrap;
1187
1157
  }
1188
1158
  .sa-marketing-card-key {
1189
- font: 700 10.5px var(--sa-marketing-font-mono);
1159
+ font: 700 10.5px var(--sa-font-mono);
1190
1160
  letter-spacing: 0.08em;
1191
- color: var(--sa-marketing-text-3);
1161
+ color: var(--sa-muted-light);
1192
1162
  text-transform: uppercase;
1193
1163
  }
1194
1164
  .sa-marketing-card-name {
1195
1165
  font-size: 22px;
1196
1166
  font-weight: 700;
1197
1167
  letter-spacing: -0.02em;
1198
- color: var(--sa-marketing-text);
1168
+ color: var(--sa-heading);
1199
1169
  margin: 2px 0 4px;
1200
1170
  }
1201
1171
  .sa-marketing-card-desc {
1202
1172
  font-size: 12.5px;
1203
- color: var(--sa-marketing-text-2);
1173
+ color: var(--sa-muted-dark);
1204
1174
  line-height: 1.4;
1205
1175
  min-height: 36px;
1206
1176
  }
@@ -1214,15 +1184,15 @@ async function onLocaleChange(loc: string): Promise<void> {
1214
1184
  font-size: 32px;
1215
1185
  font-weight: 700;
1216
1186
  letter-spacing: -0.03em;
1217
- color: var(--sa-marketing-text);
1187
+ color: var(--sa-heading);
1218
1188
  }
1219
1189
  .sa-marketing-card-price-unit {
1220
1190
  font-size: 13px;
1221
- color: var(--sa-marketing-text-3);
1191
+ color: var(--sa-muted-light);
1222
1192
  }
1223
1193
  .sa-marketing-card-price-y {
1224
1194
  font-size: 11.5px;
1225
- color: var(--sa-marketing-text-3);
1195
+ color: var(--sa-muted-light);
1226
1196
  margin-bottom: 12px;
1227
1197
  }
1228
1198
  .sa-marketing-card-cta {
@@ -1230,29 +1200,29 @@ async function onLocaleChange(loc: string): Promise<void> {
1230
1200
  margin-top: 14px;
1231
1201
  padding: 9px 12px;
1232
1202
  border-radius: 8px;
1233
- border: 1px solid var(--sa-marketing-border);
1234
- background: var(--sa-marketing-surface);
1235
- color: var(--sa-marketing-text);
1236
- font: 600 13px var(--sa-marketing-font-sans);
1203
+ border: 1px solid var(--sa-border);
1204
+ background: var(--sa-bg-surface);
1205
+ color: var(--sa-heading);
1206
+ font: 600 13px var(--sa-font-body);
1237
1207
  cursor: pointer;
1238
1208
  transition:
1239
1209
  background 0.12s,
1240
1210
  border-color 0.12s;
1241
1211
  }
1242
1212
  .sa-marketing-card-cta:hover {
1243
- background: #f8fafc;
1213
+ background: var(--sa-bg-surface-2);
1244
1214
  }
1245
1215
  .sa-marketing-card.featured .sa-marketing-card-cta {
1246
- background: var(--sa-marketing-primary);
1247
- border-color: var(--sa-marketing-primary);
1216
+ background: var(--sa-primary);
1217
+ border-color: var(--sa-primary);
1248
1218
  color: #fff;
1249
1219
  }
1250
1220
  .sa-marketing-card.featured .sa-marketing-card-cta:hover {
1251
- background: var(--sa-marketing-primary-700);
1221
+ background: var(--sa-primary-strong);
1252
1222
  }
1253
1223
  .sa-marketing-card-trialnote {
1254
1224
  font-size: 11px;
1255
- color: var(--sa-marketing-text-3);
1225
+ color: var(--sa-muted-light);
1256
1226
  text-align: center;
1257
1227
  margin-top: 6px;
1258
1228
  }
@@ -1276,14 +1246,14 @@ async function onLocaleChange(loc: string): Promise<void> {
1276
1246
  margin-top: 2px;
1277
1247
  }
1278
1248
  .sa-marketing-card-price-strike s {
1279
- color: var(--sa-marketing-text-3);
1249
+ color: var(--sa-muted-light);
1280
1250
  font-size: 14px;
1281
1251
  }
1282
1252
  .sa-marketing-price-regular {
1283
1253
  font-size: 10px;
1284
1254
  text-transform: uppercase;
1285
1255
  letter-spacing: 0.5px;
1286
- color: var(--sa-marketing-text-3);
1256
+ color: var(--sa-muted-light);
1287
1257
  }
1288
1258
  .sa-marketing-card-fineprint {
1289
1259
  font-size: 10px;
@@ -1296,7 +1266,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1296
1266
  font-size: 11px;
1297
1267
  text-transform: uppercase;
1298
1268
  letter-spacing: 0.08em;
1299
- color: var(--sa-marketing-text-3);
1269
+ color: var(--sa-muted-light);
1300
1270
  font-weight: 700;
1301
1271
  }
1302
1272
  .sa-marketing-card-features {
@@ -1321,24 +1291,24 @@ async function onLocaleChange(loc: string): Promise<void> {
1321
1291
  margin-top: 1px;
1322
1292
  }
1323
1293
  .sa-marketing-card-features b {
1324
- color: var(--sa-marketing-text);
1294
+ color: var(--sa-heading);
1325
1295
  font-weight: 700;
1326
1296
  }
1327
1297
  .sa-marketing-card-features-empty {
1328
1298
  margin-top: 8px;
1329
1299
  font-size: 12px;
1330
- color: var(--sa-marketing-text-3);
1300
+ color: var(--sa-muted-light);
1331
1301
  }
1332
1302
 
1333
1303
  /* ── Marketing administration ── */
1334
1304
  .sa-marketing-admin {
1335
- background: var(--sa-marketing-surface);
1336
- border: 1px solid var(--sa-marketing-border);
1305
+ background: var(--sa-bg-surface);
1306
+ border: 1px solid var(--sa-border);
1337
1307
  border-radius: 10px;
1338
1308
  }
1339
1309
  .sa-marketing-admin-head {
1340
1310
  padding: 14px 16px;
1341
- border-bottom: 1px solid #f1f5f9;
1311
+ border-bottom: 1px solid var(--sa-border-soft);
1342
1312
  display: flex;
1343
1313
  align-items: center;
1344
1314
  gap: 12px;
@@ -1347,11 +1317,11 @@ async function onLocaleChange(loc: string): Promise<void> {
1347
1317
  font-size: 14px;
1348
1318
  font-weight: 700;
1349
1319
  letter-spacing: -0.01em;
1350
- color: var(--sa-marketing-text);
1320
+ color: var(--sa-heading);
1351
1321
  }
1352
1322
  .sa-marketing-admin-sub {
1353
1323
  font-size: 11.5px;
1354
- color: var(--sa-marketing-text-2);
1324
+ color: var(--sa-muted-dark);
1355
1325
  }
1356
1326
  .sa-marketing-admin-grid {
1357
1327
  display: grid;
@@ -1367,20 +1337,20 @@ async function onLocaleChange(loc: string): Promise<void> {
1367
1337
  font-size: 10.5px;
1368
1338
  text-transform: uppercase;
1369
1339
  letter-spacing: 0.1em;
1370
- color: var(--sa-marketing-text-2);
1340
+ color: var(--sa-muted-dark);
1371
1341
  font-weight: 700;
1372
- border-bottom: 1px solid var(--sa-marketing-border);
1342
+ border-bottom: 1px solid var(--sa-border);
1373
1343
  }
1374
1344
  .sa-marketing-admin-row {
1375
1345
  display: contents;
1376
1346
  }
1377
1347
  .sa-marketing-admin-row > div {
1378
1348
  padding: 12px 14px;
1379
- border-bottom: 1px solid #f1f5f9;
1349
+ border-bottom: 1px solid var(--sa-border-soft);
1380
1350
  display: flex;
1381
1351
  align-items: center;
1382
1352
  font-size: 12.5px;
1383
- color: var(--sa-marketing-text);
1353
+ color: var(--sa-heading);
1384
1354
  }
1385
1355
  .sa-marketing-admin-row--disabled > div {
1386
1356
  background: #fcfcfd;
@@ -1400,36 +1370,36 @@ async function onLocaleChange(loc: string): Promise<void> {
1400
1370
  border-radius: 8px;
1401
1371
  display: grid;
1402
1372
  place-items: center;
1403
- font: 700 10px var(--sa-marketing-font-mono);
1373
+ font: 700 10px var(--sa-font-mono);
1404
1374
  border: 1px solid;
1405
1375
  }
1406
1376
  .sa-marketing-plan-label {
1407
1377
  font-size: 13px;
1408
1378
  font-weight: 700;
1409
- color: var(--sa-marketing-text);
1379
+ color: var(--sa-heading);
1410
1380
  }
1411
1381
  .sa-marketing-plan-key {
1412
- font: 500 11px var(--sa-marketing-font-mono);
1413
- color: var(--sa-marketing-text-3);
1382
+ font: 500 11px var(--sa-font-mono);
1383
+ color: var(--sa-muted-light);
1414
1384
  }
1415
1385
 
1416
1386
  .sa-marketing-field {
1417
1387
  width: 100%;
1418
1388
  padding: 5px 8px;
1419
- font: 400 12px var(--sa-marketing-font-sans);
1420
- color: var(--sa-marketing-text);
1421
- background: var(--sa-marketing-surface);
1422
- border: 1px solid var(--sa-marketing-border-strong);
1389
+ font: 400 12px var(--sa-font-body);
1390
+ color: var(--sa-heading);
1391
+ background: var(--sa-bg-surface);
1392
+ border: 1px solid var(--sa-border-strong);
1423
1393
  border-radius: 6px;
1424
1394
  }
1425
1395
  .sa-marketing-field:focus {
1426
1396
  outline: none;
1427
- border-color: var(--sa-marketing-primary);
1428
- box-shadow: 0 0 0 3px var(--sa-marketing-primary-50);
1397
+ border-color: var(--sa-primary);
1398
+ box-shadow: 0 0 0 3px var(--sa-primary-50);
1429
1399
  }
1430
1400
  .sa-marketing-field:disabled {
1431
- background: #f1f5f9;
1432
- color: var(--sa-marketing-text-3);
1401
+ background: var(--sa-border-soft);
1402
+ color: var(--sa-muted-light);
1433
1403
  cursor: not-allowed;
1434
1404
  }
1435
1405
  .sa-marketing-field--area {
@@ -1468,7 +1438,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1468
1438
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
1469
1439
  }
1470
1440
  .sa-marketing-toggle input:checked + span {
1471
- background: var(--sa-marketing-primary);
1441
+ background: var(--sa-primary);
1472
1442
  }
1473
1443
  .sa-marketing-toggle input:checked + span::before {
1474
1444
  transform: translateX(16px);
@@ -1489,17 +1459,17 @@ async function onLocaleChange(loc: string): Promise<void> {
1489
1459
  border: 1px solid;
1490
1460
  }
1491
1461
  .sa-marketing-chip--muted {
1492
- background: #f1f5f9;
1493
- color: #475569;
1462
+ background: var(--sa-border-soft);
1463
+ color: var(--sa-muted-dark);
1494
1464
  border-color: #cbd5e1;
1495
1465
  }
1496
1466
  .sa-marketing-chip--featured {
1497
- background: var(--sa-marketing-primary-50);
1498
- color: var(--sa-marketing-primary-700);
1467
+ background: var(--sa-primary-50);
1468
+ color: var(--sa-primary-strong);
1499
1469
  border-color: #bfdbfe;
1500
1470
  }
1501
1471
  .sa-marketing-chip--live {
1502
- background: #ecfdf5;
1472
+ background: var(--sa-positive-bg);
1503
1473
  color: #047857;
1504
1474
  border-color: #a7f3d0;
1505
1475
  }
@@ -1520,16 +1490,16 @@ async function onLocaleChange(loc: string): Promise<void> {
1520
1490
  border: 1px solid transparent;
1521
1491
  border-radius: 6px;
1522
1492
  cursor: pointer;
1523
- color: var(--sa-marketing-text-3);
1493
+ color: var(--sa-muted-light);
1524
1494
  transition:
1525
1495
  background 0.12s,
1526
1496
  color 0.12s,
1527
1497
  border-color 0.12s;
1528
1498
  }
1529
1499
  .sa-marketing-expand-btn:hover {
1530
- background: #f1f5f9;
1531
- color: var(--sa-marketing-primary);
1532
- border-color: #e2e8f0;
1500
+ background: var(--sa-border-soft);
1501
+ color: var(--sa-primary);
1502
+ border-color: var(--sa-border);
1533
1503
  }
1534
1504
  .sa-marketing-chev {
1535
1505
  display: inline-flex;
@@ -1542,7 +1512,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1542
1512
  .sa-marketing-admin-expand {
1543
1513
  grid-column: 1 / -1;
1544
1514
  background: linear-gradient(180deg, #fbfbfd 0%, #fff 100%);
1545
- border-bottom: 1px solid #f1f5f9;
1515
+ border-bottom: 1px solid var(--sa-border-soft);
1546
1516
  padding: 18px 20px 22px;
1547
1517
  }
1548
1518
  .sa-marketing-expand-grid {
@@ -1564,12 +1534,12 @@ async function onLocaleChange(loc: string): Promise<void> {
1564
1534
  font-size: 10.5px;
1565
1535
  text-transform: uppercase;
1566
1536
  letter-spacing: 0.1em;
1567
- color: var(--sa-marketing-text-2);
1537
+ color: var(--sa-muted-dark);
1568
1538
  font-weight: 700;
1569
1539
  }
1570
1540
  .sa-marketing-expand-hint {
1571
1541
  font-size: 11px;
1572
- color: var(--sa-marketing-text-3);
1542
+ color: var(--sa-muted-light);
1573
1543
  }
1574
1544
  .sa-marketing-field-head {
1575
1545
  display: flex;
@@ -1579,10 +1549,10 @@ async function onLocaleChange(loc: string): Promise<void> {
1579
1549
  }
1580
1550
  .sa-marketing-source-hint {
1581
1551
  font-size: 11px;
1582
- color: var(--sa-marketing-text-3);
1552
+ color: var(--sa-muted-light);
1583
1553
  }
1584
1554
  .sa-marketing-source-hint em {
1585
- color: var(--sa-marketing-text-2);
1555
+ color: var(--sa-muted-dark);
1586
1556
  font-style: normal;
1587
1557
  }
1588
1558
  .sa-marketing-locked-value {
@@ -1590,16 +1560,16 @@ async function onLocaleChange(loc: string): Promise<void> {
1590
1560
  align-items: center;
1591
1561
  gap: 8px;
1592
1562
  padding: 8px 10px;
1593
- background: var(--sa-marketing-surface);
1594
- border: 1px solid var(--sa-marketing-border);
1563
+ background: var(--sa-bg-surface);
1564
+ border: 1px solid var(--sa-border);
1595
1565
  border-radius: 6px;
1596
1566
  font-size: 13px;
1597
- color: var(--sa-marketing-text-1);
1567
+ color: var(--sa-heading);
1598
1568
  }
1599
1569
  .sa-marketing-locked-hint {
1600
1570
  font-size: 10px;
1601
1571
  text-transform: uppercase;
1602
- color: var(--sa-marketing-text-3);
1572
+ color: var(--sa-muted-light);
1603
1573
  background: rgba(148, 163, 184, 0.15);
1604
1574
  padding: 1px 6px;
1605
1575
  border-radius: 4px;
@@ -1609,14 +1579,14 @@ async function onLocaleChange(loc: string): Promise<void> {
1609
1579
  display: flex;
1610
1580
  align-items: center;
1611
1581
  gap: 10px;
1612
- background: var(--sa-marketing-surface);
1613
- border: 1px solid var(--sa-marketing-border);
1582
+ background: var(--sa-bg-surface);
1583
+ border: 1px solid var(--sa-border);
1614
1584
  border-radius: 8px;
1615
1585
  padding: 8px 12px;
1616
1586
  }
1617
1587
  .sa-marketing-trial-label {
1618
1588
  font-size: 13px;
1619
- color: var(--sa-marketing-text);
1589
+ color: var(--sa-heading);
1620
1590
  }
1621
1591
  .sa-marketing-trial-days {
1622
1592
  margin-left: auto;
@@ -1626,7 +1596,7 @@ async function onLocaleChange(loc: string): Promise<void> {
1626
1596
  }
1627
1597
  .sa-marketing-trial-unit {
1628
1598
  font-size: 12px;
1629
- color: var(--sa-marketing-text-2);
1599
+ color: var(--sa-muted-dark);
1630
1600
  }
1631
1601
 
1632
1602
  .sa-marketing-tf-head {
@@ -1645,8 +1615,8 @@ async function onLocaleChange(loc: string): Promise<void> {
1645
1615
  align-items: center;
1646
1616
  }
1647
1617
  .sa-marketing-tf-num {
1648
- font: 600 11px var(--sa-marketing-font-mono);
1649
- color: var(--sa-marketing-text-3);
1618
+ font: 600 11px var(--sa-font-mono);
1619
+ color: var(--sa-muted-light);
1650
1620
  text-align: center;
1651
1621
  }
1652
1622
  .sa-marketing-tf-actions {
@@ -1658,19 +1628,19 @@ async function onLocaleChange(loc: string): Promise<void> {
1658
1628
  height: 24px;
1659
1629
  display: grid;
1660
1630
  place-items: center;
1661
- background: var(--sa-marketing-surface);
1662
- border: 1px solid var(--sa-marketing-border);
1631
+ background: var(--sa-bg-surface);
1632
+ border: 1px solid var(--sa-border);
1663
1633
  border-radius: 5px;
1664
1634
  cursor: pointer;
1665
- font: 600 10px var(--sa-marketing-font-sans);
1666
- color: var(--sa-marketing-text-2);
1635
+ font: 600 10px var(--sa-font-body);
1636
+ color: var(--sa-muted-dark);
1667
1637
  padding: 0;
1668
1638
  transition:
1669
1639
  background 0.12s,
1670
1640
  border-color 0.12s;
1671
1641
  }
1672
1642
  .sa-marketing-iconbtn:hover:not(:disabled) {
1673
- background: #f1f5f9;
1643
+ background: var(--sa-border-soft);
1674
1644
  border-color: #cbd5e1;
1675
1645
  }
1676
1646
  .sa-marketing-iconbtn:disabled {
@@ -1688,8 +1658,8 @@ async function onLocaleChange(loc: string): Promise<void> {
1688
1658
  padding: 14px;
1689
1659
  text-align: center;
1690
1660
  font-size: 12px;
1691
- color: var(--sa-marketing-text-3);
1692
- background: var(--sa-marketing-surface);
1661
+ color: var(--sa-muted-light);
1662
+ background: var(--sa-bg-surface);
1693
1663
  border: 1px dashed #cbd5e1;
1694
1664
  border-radius: 8px;
1695
1665
  }
@@ -1711,10 +1681,10 @@ async function onLocaleChange(loc: string): Promise<void> {
1711
1681
  gap: 5px;
1712
1682
  padding: 3px 9px;
1713
1683
  border-radius: 999px;
1714
- background: var(--sa-marketing-surface);
1684
+ background: var(--sa-bg-surface);
1715
1685
  border: 1px dashed #cbd5e1;
1716
1686
  font-size: 11.5px;
1717
- color: #475569;
1687
+ color: var(--sa-muted-dark);
1718
1688
  cursor: pointer;
1719
1689
  transition:
1720
1690
  background 0.12s,
@@ -1723,14 +1693,14 @@ async function onLocaleChange(loc: string): Promise<void> {
1723
1693
  }
1724
1694
  .sa-marketing-tf-chip em {
1725
1695
  font-style: normal;
1726
- color: var(--sa-marketing-text-3);
1727
- font: 500 11px var(--sa-marketing-font-mono);
1696
+ color: var(--sa-muted-light);
1697
+ font: 500 11px var(--sa-font-mono);
1728
1698
  }
1729
1699
  .sa-marketing-tf-chip:hover:not(:disabled) {
1730
- background: var(--sa-marketing-primary-50);
1700
+ background: var(--sa-primary-50);
1731
1701
  border-color: #93c5fd;
1732
1702
  border-style: solid;
1733
- color: var(--sa-marketing-primary-700);
1703
+ color: var(--sa-primary-strong);
1734
1704
  }
1735
1705
  .sa-marketing-tf-chip:disabled {
1736
1706
  opacity: 0.5;
@@ -1753,12 +1723,12 @@ async function onLocaleChange(loc: string): Promise<void> {
1753
1723
  margin-top: 6px;
1754
1724
  }
1755
1725
  .sa-marketing-version-tab {
1756
- border: 1px solid #e2e8f0;
1726
+ border: 1px solid var(--sa-border);
1757
1727
  background: #fff;
1758
1728
  border-radius: 6px;
1759
1729
  padding: 2px 8px;
1760
1730
  font: 600 10.5px var(--sa-font-mono, ui-monospace, monospace);
1761
- color: #64748b;
1731
+ color: var(--sa-muted);
1762
1732
  cursor: pointer;
1763
1733
  letter-spacing: 0.02em;
1764
1734
  transition:
@@ -1768,12 +1738,12 @@ async function onLocaleChange(loc: string): Promise<void> {
1768
1738
  }
1769
1739
  .sa-marketing-version-tab:hover {
1770
1740
  border-color: #cbd5e1;
1771
- background: #f8fafc;
1772
- color: #475569;
1741
+ background: var(--sa-bg-surface-2);
1742
+ color: var(--sa-muted-dark);
1773
1743
  }
1774
1744
  .sa-marketing-version-tab--active {
1775
- border-color: #1d4ed8;
1776
- background: #eff6ff;
1777
- color: #1d4ed8;
1745
+ border-color: var(--sa-primary-strong);
1746
+ background: var(--sa-primary-50);
1747
+ color: var(--sa-primary-strong);
1778
1748
  }
1779
1749
  </style>