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