@saasicat/ui-vue 0.22.2 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-LY52T4N4.js → chunk-TQQMKWN6.js} +58 -1
  3. package/dist/index.cjs +213 -159
  4. package/dist/index.d.cts +2 -2
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +7 -1
  7. package/dist/quasar/index.cjs +116 -20
  8. package/dist/quasar/index.d.cts +48 -3
  9. package/dist/quasar/index.d.ts +48 -3
  10. package/dist/quasar/index.js +58 -3
  11. package/dist/{use-super-admin-i18n-CgTuNi8h.d.cts → use-sa-theme-B5t7oXph.d.cts} +51 -1
  12. package/dist/{use-super-admin-i18n-CHNdsSlm.d.ts → use-sa-theme-OUBlaqgl.d.ts} +51 -1
  13. package/package.json +5 -2
  14. package/src/components/BundleVersionPublishDialog.vue +17 -17
  15. package/src/components/KvBlock.vue +6 -6
  16. package/src/components/MarketingPromotionsTab.vue +78 -78
  17. package/src/components/MfaPromptDialog.vue +2 -2
  18. package/src/components/TenantActionConfirmDialog.vue +5 -5
  19. package/src/components/VersionDiffPreview.vue +18 -18
  20. package/src/components/bundle-editor/BundleCreatePanel.vue +52 -52
  21. package/src/components/bundle-editor/BundleFeaturesEditor.vue +20 -20
  22. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +33 -33
  23. package/src/components/bundle-editor/BundleQuotasEditor.vue +26 -26
  24. package/src/components/bundle-editor/BundleStatusBanner.vue +21 -21
  25. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +48 -48
  26. package/src/components/bundle-editor/BundleVersionStrip.vue +30 -30
  27. package/src/components/dialogs/PilotCreateDialog.vue +20 -20
  28. package/src/components/dialogs/PilotEditDialog.vue +6 -6
  29. package/src/components/dialogs/PromoCodeCreateDialog.vue +9 -9
  30. package/src/components/dialogs/PromoCodeDialogFields.vue +61 -61
  31. package/src/components/dialogs/PromoCodeEditDialog.vue +11 -11
  32. package/src/components/dialogs/pilot-dialog.css +48 -48
  33. package/src/components/plan/PlanCycleToggle.vue +9 -16
  34. package/src/components/plan/PlanGrid.vue +30 -34
  35. package/src/components/plan/PriceSummary.vue +35 -35
  36. package/src/components/plan/PromoCodeInput.vue +26 -26
  37. package/src/components/plan/PublicBundleGrid.vue +32 -28
  38. package/src/components/plan-create-dialog/PlanCreateDialog.vue +49 -49
  39. package/src/components/plan-detail/PlanDetail.vue +172 -156
  40. package/src/components/plan-detail/PlanTitleEdit.vue +11 -11
  41. package/src/components/plan-list/PlanList.vue +98 -77
  42. package/src/components/plan-matrix/PlanMatrix.vue +89 -89
  43. package/src/components/plan-review/PlanReview.vue +60 -56
  44. package/src/components/plan-version-editor/PlanVersionEditor.vue +224 -200
  45. package/src/components/wizard-stepper/WizardStepper.vue +17 -17
  46. package/src/index.ts +1 -0
  47. package/src/pages-standard/AdminLayout.vue +58 -37
  48. package/src/pages-standard/AdminManifestErrorPage.vue +6 -6
  49. package/src/pages-standard/AuditPage.vue +3 -3
  50. package/src/pages-standard/BundlesPage.vue +36 -36
  51. package/src/pages-standard/DashboardPage.vue +17 -17
  52. package/src/pages-standard/DiscoveryPage.vue +55 -49
  53. package/src/pages-standard/EmailHistoryPage.vue +53 -71
  54. package/src/pages-standard/MarketingCatalogPage.vue +226 -218
  55. package/src/pages-standard/PilotsPage.vue +7 -6
  56. package/src/pages-standard/PlatformEmailPage.vue +18 -18
  57. package/src/pages-standard/PromoCodeDetailPage.vue +3 -3
  58. package/src/pages-standard/PromoCodesPage.vue +7 -6
  59. package/src/pages-standard/SuperAdminLoginPage.vue +39 -25
  60. package/src/pages-standard/SuperAdminSetupWizard.vue +44 -33
  61. package/src/pages-standard/TenantDetailPage.vue +7 -7
  62. package/src/pages-standard/TenantsPage.vue +11 -46
  63. package/src/pages-standard/bundles-page/BundleAccordionList.vue +13 -13
  64. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +24 -24
  65. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +22 -22
  66. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +39 -39
  67. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +26 -26
  68. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +1 -1
  69. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -16
  70. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +21 -15
  71. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +45 -45
  72. package/src/pages-standard/plans-page/PlanBundleOverview.vue +21 -15
  73. package/src/pages-standard/plans-page/PlanPublishDialog.vue +4 -4
  74. package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
  75. package/src/pages-standard/sa-theme.css +9 -687
  76. package/src/pages-standard/tenants/StatusPill.vue +13 -13
  77. package/src/pages-tenant/LimitsRow.vue +4 -4
  78. package/src/pages-tenant/MySubscriptionBundlesPage.vue +61 -61
  79. package/src/pages-tenant/OnboardingConfigurator.vue +24 -24
  80. package/src/pages-tenant/PackageSnapshotPanel.vue +10 -16
  81. package/src/pages-tenant/PendingVersionBanner.vue +12 -12
  82. package/src/pages-tenant/PlanChangeWizard.vue +20 -27
  83. package/src/pages-tenant/TenantPlanSection.vue +13 -21
  84. package/src/pages-tenant/UsageBar.vue +7 -7
  85. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +14 -14
  86. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +10 -10
  87. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +2 -2
  88. package/src/quasar/create-super-admin-app.ts +96 -1
  89. package/src/quasar/dark-bridge.ts +66 -0
  90. package/src/quasar/index.ts +1 -0
  91. package/src/ui/theme/_breakpoints.scss +28 -0
  92. package/src/ui/theme/base.css +50 -0
  93. package/src/ui/theme/components/body.css +23 -0
  94. package/src/ui/theme/components/button.css +158 -0
  95. package/src/ui/theme/components/card.css +48 -0
  96. package/src/ui/theme/components/field.css +38 -0
  97. package/src/ui/theme/components/hero.css +46 -0
  98. package/src/ui/theme/components/paginator.css +63 -0
  99. package/src/ui/theme/components/section.css +67 -0
  100. package/src/ui/theme/components/statistics.css +189 -0
  101. package/src/ui/theme/components/table.css +60 -0
  102. package/src/ui/theme/index.css +42 -0
  103. package/src/ui/theme/tokens.legacy.css +147 -0
  104. package/src/ui/theme/tokens.primitive.css +108 -0
  105. package/src/ui/theme/tokens.scale.css +103 -0
  106. package/src/ui/theme/tokens.semantic.dark.css +173 -0
  107. package/src/ui/theme/tokens.semantic.light.css +212 -0
  108. package/src/vue/use-sa-theme.ts +154 -0
@@ -92,28 +92,24 @@ function planPrice(plan: CatalogPlan): number | null {
92
92
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
93
93
  gap: 12px;
94
94
  }
95
- /* CSS vars for light + dark mode. Quasar's `body--dark` triggers the dark set. */
95
+ /* This component's knobs, all of them reading a role. The dark set that used to
96
+ * sit below is gone: the roles carry the theme now, so nine values were being
97
+ * maintained twice to say what `--sa-color-*` already says once. */
96
98
  .sp-models {
97
- --sp-card-bg: #fff;
98
- --sp-card-border: rgba(0, 0, 0, 0.1);
99
- --sp-card-border-soft: rgba(0, 0, 0, 0.08);
100
- --sp-card-current-bg: rgba(0, 0, 0, 0.02);
101
- --sp-card-selected-grad: rgba(15, 118, 110, 0.04);
102
- --sp-text-strong: rgba(0, 0, 0, 0.85);
103
- --sp-text-muted: rgba(0, 0, 0, 0.55);
104
- --sp-flag-current-bg: rgba(0, 0, 0, 0.6);
105
- --sp-flag-current-fg: #fff;
106
- }
107
- :global(.body--dark) .sp-models {
108
- --sp-card-bg: rgba(255, 255, 255, 0.06);
109
- --sp-card-border: rgba(255, 255, 255, 0.2);
110
- --sp-card-border-soft: rgba(255, 255, 255, 0.12);
111
- --sp-card-current-bg: rgba(255, 255, 255, 0.1);
112
- --sp-card-selected-grad: rgba(15, 118, 110, 0.25);
113
- --sp-text-strong: rgba(255, 255, 255, 0.92);
114
- --sp-text-muted: rgba(255, 255, 255, 0.65);
115
- --sp-flag-current-bg: rgba(255, 255, 255, 0.85);
116
- --sp-flag-current-fg: var(--sa-heading);
99
+ --sp-card-bg: var(--sa-color-bg-surface);
100
+ --sp-card-border: var(--sa-color-border);
101
+ --sp-card-border-soft: var(--sa-color-border-soft);
102
+ --sp-card-current-bg: var(--sa-color-bg-sunken);
103
+ --sp-card-selected-grad: var(--sa-color-accent-surface-soft);
104
+ --sp-text-strong: var(--sa-color-fg-heading);
105
+ --sp-text-muted: var(--sa-color-fg-muted);
106
+ /* The flag is an inversion of the card: it paints a foreground colour as
107
+ * its surface, so its text has to be the background colour. Pairing it
108
+ * with `--sa-color-fg-on-accent` held only in light mode — that role is
109
+ * white in both themes, while this surface turns light in dark, and white
110
+ * on `--sa-neutral-300` reads 1.48:1. */
111
+ --sp-flag-current-bg: var(--sa-color-fg-secondary);
112
+ --sp-flag-current-fg: var(--sa-color-bg-surface);
117
113
  }
118
114
  .sp-model {
119
115
  position: relative;
@@ -132,12 +128,12 @@ function planPrice(plan: CatalogPlan): number | null {
132
128
  }
133
129
  .sp-model:hover {
134
130
  transform: translateY(-3px);
135
- border-color: rgba(15, 118, 110, 0.55);
131
+ border-color: var(--sa-color-accent);
136
132
  }
137
133
  .sp-model--selected {
138
- border-color: var(--q-primary, #0f766e);
134
+ border-color: var(--sa-color-accent);
139
135
  background: linear-gradient(180deg, var(--sp-card-selected-grad), var(--sp-card-bg) 70%);
140
- box-shadow: 0 14px 30px rgba(15, 118, 110, 0.16);
136
+ box-shadow: 0 14px 30px var(--sa-shadow-tint-3);
141
137
  }
142
138
  .sp-model--current {
143
139
  background: var(--sp-card-current-bg);
@@ -146,9 +142,9 @@ function planPrice(plan: CatalogPlan): number | null {
146
142
  position: absolute;
147
143
  top: -10px;
148
144
  right: 14px;
149
- background: var(--q-primary, #0f766e);
150
- color: #fff;
151
- font-size: 10px;
145
+ background: var(--sa-color-accent);
146
+ color: var(--sa-color-fg-on-accent);
147
+ font-size: var(--sa-text-2xs);
152
148
  font-weight: 700;
153
149
  padding: 4px 10px;
154
150
  border-radius: 999px;
@@ -160,12 +156,12 @@ function planPrice(plan: CatalogPlan): number | null {
160
156
  color: var(--sp-flag-current-fg);
161
157
  }
162
158
  .sp-model__name {
163
- font-size: 17px;
159
+ font-size: var(--sa-text-xl);
164
160
  font-weight: 700;
165
161
  color: var(--sp-text-strong);
166
162
  }
167
163
  .sp-model__tagline {
168
- font-size: 12px;
164
+ font-size: var(--sa-text-sm);
169
165
  color: var(--sp-text-muted);
170
166
  line-height: 1.4;
171
167
  }
@@ -176,12 +172,12 @@ function planPrice(plan: CatalogPlan): number | null {
176
172
  margin-top: 4px;
177
173
  }
178
174
  .sp-model__price strong {
179
- font-size: 22px;
175
+ font-size: var(--sa-text-2xl);
180
176
  font-weight: 800;
181
177
  color: var(--sp-text-strong);
182
178
  }
183
179
  .sp-model__price-cycle {
184
- font-size: 11px;
180
+ font-size: var(--sa-text-xs);
185
181
  color: var(--sp-text-muted);
186
182
  }
187
183
  .sp-model__quotas {
@@ -196,15 +192,15 @@ function planPrice(plan: CatalogPlan): number | null {
196
192
  display: flex;
197
193
  flex-direction: column;
198
194
  gap: 1px;
199
- font-size: 11px;
195
+ font-size: var(--sa-text-xs);
200
196
  }
201
197
  .sp-model__quota strong {
202
- font-size: 14px;
198
+ font-size: var(--sa-text-lg);
203
199
  color: var(--sp-text-strong);
204
200
  }
205
201
  .sp-model__quota span {
206
202
  color: var(--sp-text-muted);
207
- font-size: 10px;
203
+ font-size: var(--sa-text-2xs);
208
204
  text-transform: uppercase;
209
205
  letter-spacing: 0.06em;
210
206
  }
@@ -126,33 +126,33 @@ const emit = defineEmits<{
126
126
 
127
127
  <style scoped>
128
128
  .sp-summary {
129
- background: #fff;
130
- border: 1.5px solid rgba(0, 0, 0, 0.85);
129
+ background: var(--sa-color-bg-surface);
130
+ border: 1.5px solid var(--sa-color-inverse-bg);
131
131
  border-radius: 22px;
132
132
  overflow: hidden;
133
- box-shadow: 0 24px 80px rgba(31, 41, 51, 0.1);
133
+ box-shadow: 0 24px 80px var(--sa-shadow-tint-2);
134
134
  position: sticky;
135
135
  top: 24px;
136
136
  }
137
137
  .sp-summary__head {
138
138
  padding: 16px 20px 14px;
139
- background: rgba(0, 0, 0, 0.85);
140
- color: #fff;
139
+ background: var(--sa-color-bg-overlay);
140
+ color: var(--sa-color-fg-on-accent);
141
141
  display: flex;
142
142
  justify-content: space-between;
143
143
  align-items: baseline;
144
144
  gap: 8px;
145
145
  }
146
146
  .sp-summary__title {
147
- font-size: 18px;
147
+ font-size: var(--sa-text-xl);
148
148
  font-weight: 700;
149
149
  }
150
150
  .sp-summary__cycle {
151
151
  font-family: 'SF Mono', Consolas, monospace;
152
- font-size: 10px;
152
+ font-size: var(--sa-text-2xs);
153
153
  letter-spacing: 0.08em;
154
154
  text-transform: uppercase;
155
- background: rgba(255, 255, 255, 0.16);
155
+ background: var(--sa-color-inverse-border-strong);
156
156
  padding: 4px 9px;
157
157
  border-radius: 999px;
158
158
  }
@@ -166,13 +166,13 @@ const emit = defineEmits<{
166
166
  }
167
167
  .sp-summary__group-head {
168
168
  font-family: 'SF Mono', Consolas, monospace;
169
- font-size: 10px;
169
+ font-size: var(--sa-text-2xs);
170
170
  letter-spacing: 0.12em;
171
171
  text-transform: uppercase;
172
- color: rgba(0, 0, 0, 0.5);
172
+ color: var(--sa-color-fg-subtle);
173
173
  font-weight: 700;
174
174
  padding-bottom: 6px;
175
- border-bottom: 1px solid rgba(0, 0, 0, 0.08);
175
+ border-bottom: 1px solid var(--sa-color-border);
176
176
  margin-bottom: 6px;
177
177
  }
178
178
  .sp-summary__line {
@@ -181,7 +181,7 @@ const emit = defineEmits<{
181
181
  gap: 10px;
182
182
  align-items: baseline;
183
183
  padding: 4px 0;
184
- font-size: 13px;
184
+ font-size: var(--sa-text-md);
185
185
  }
186
186
  .sp-summary__line strong {
187
187
  font-weight: 600;
@@ -189,40 +189,40 @@ const emit = defineEmits<{
189
189
  .sp-summary__line small {
190
190
  display: block;
191
191
  font-family: 'SF Mono', Consolas, monospace;
192
- font-size: 9.5px;
192
+ font-size: var(--sa-text-2xs);
193
193
  letter-spacing: 0.06em;
194
194
  text-transform: uppercase;
195
- color: rgba(0, 0, 0, 0.5);
195
+ color: var(--sa-color-fg-subtle);
196
196
  margin-top: 2px;
197
197
  }
198
198
  .sp-summary__price {
199
199
  white-space: nowrap;
200
200
  font-weight: 600;
201
- font-size: 14px;
201
+ font-size: var(--sa-text-lg);
202
202
  }
203
203
  .sp-summary__empty {
204
204
  padding: 20px 8px;
205
205
  text-align: center;
206
- font-size: 12px;
207
- color: rgba(0, 0, 0, 0.5);
206
+ font-size: var(--sa-text-sm);
207
+ color: var(--sa-color-fg-subtle);
208
208
  line-height: 1.5;
209
209
  font-style: italic;
210
210
  }
211
211
  .sp-summary__foot {
212
- border-top: 1px solid rgba(0, 0, 0, 0.08);
212
+ border-top: 1px solid var(--sa-color-border);
213
213
  padding: 16px 20px 18px;
214
- background: rgba(15, 118, 110, 0.04);
214
+ background: var(--sa-color-accent-surface-soft);
215
215
  }
216
216
  .sp-summary__row {
217
217
  display: flex;
218
218
  justify-content: space-between;
219
219
  align-items: baseline;
220
- font-size: 12px;
221
- color: rgba(0, 0, 0, 0.55);
220
+ font-size: var(--sa-text-sm);
221
+ color: var(--sa-color-fg-muted);
222
222
  margin-bottom: 4px;
223
223
  }
224
224
  .sp-summary__row--discount {
225
- color: #166534;
225
+ color: var(--sa-color-positive-fg);
226
226
  }
227
227
  .sp-summary__total {
228
228
  display: flex;
@@ -231,33 +231,33 @@ const emit = defineEmits<{
231
231
  margin-top: 6px;
232
232
  }
233
233
  .sp-summary__total-l {
234
- font-size: 14px;
234
+ font-size: var(--sa-text-lg);
235
235
  font-weight: 700;
236
236
  }
237
237
  .sp-summary__total-l small {
238
238
  display: block;
239
239
  font-family: 'SF Mono', Consolas, monospace;
240
- font-size: 10px;
240
+ font-size: var(--sa-text-2xs);
241
241
  letter-spacing: 0.06em;
242
242
  text-transform: uppercase;
243
- color: rgba(0, 0, 0, 0.5);
243
+ color: var(--sa-color-fg-subtle);
244
244
  font-weight: 500;
245
245
  margin-top: 2px;
246
246
  }
247
247
  .sp-summary__total-r {
248
- font-size: 32px;
248
+ font-size: var(--sa-text-4xl);
249
249
  font-weight: 800;
250
- color: var(--q-primary, #0f766e);
250
+ color: var(--sa-color-accent);
251
251
  letter-spacing: -0.02em;
252
252
  line-height: 1;
253
253
  }
254
254
  .sp-summary__savings {
255
255
  margin-top: 10px;
256
256
  padding: 8px 10px;
257
- background: rgba(22, 163, 74, 0.12);
258
- color: #166534;
257
+ background: var(--sa-color-positive-surface-strong);
258
+ color: var(--sa-color-positive-fg);
259
259
  border-radius: 8px;
260
- font-size: 12px;
260
+ font-size: var(--sa-text-sm);
261
261
  font-weight: 600;
262
262
  }
263
263
  .sp-summary__cta {
@@ -265,12 +265,12 @@ const emit = defineEmits<{
265
265
  width: 100%;
266
266
  margin-top: 14px;
267
267
  padding: 14px 18px;
268
- background: var(--q-primary, #0f766e);
269
- color: #fff;
268
+ background: var(--sa-color-accent);
269
+ color: var(--sa-color-fg-on-accent);
270
270
  border: none;
271
271
  border-radius: 14px;
272
272
  font-family: inherit;
273
- font-size: 14px;
273
+ font-size: var(--sa-text-lg);
274
274
  font-weight: 700;
275
275
  letter-spacing: 0.01em;
276
276
  cursor: pointer;
@@ -285,8 +285,8 @@ const emit = defineEmits<{
285
285
  }
286
286
  .sp-summary__disclaimer {
287
287
  margin-top: 12px;
288
- font-size: 11px;
289
- color: rgba(0, 0, 0, 0.5);
288
+ font-size: var(--sa-text-xs);
289
+ color: var(--sa-color-fg-subtle);
290
290
  line-height: 1.5;
291
291
  text-align: center;
292
292
  }
@@ -104,37 +104,37 @@ function remove(): void {
104
104
  width: 100%;
105
105
  padding: 10px 12px;
106
106
  margin: 10px 0 6px;
107
- border: 1px dashed rgba(15, 118, 110, 0.3);
108
- background: rgba(15, 118, 110, 0.04);
107
+ border: 1px dashed var(--sa-color-accent-border);
108
+ background: var(--sa-color-accent-surface-soft);
109
109
  border-radius: 10px;
110
- color: var(--q-primary, #0f766e);
110
+ color: var(--sa-color-accent);
111
111
  font-weight: 700;
112
- font-size: 12px;
112
+ font-size: var(--sa-text-sm);
113
113
  cursor: pointer;
114
114
  font-family: inherit;
115
115
  letter-spacing: 0.01em;
116
116
  }
117
117
  .sp-promo__toggle:hover {
118
- background: rgba(15, 118, 110, 0.1);
118
+ background: var(--sa-color-accent-surface);
119
119
  }
120
120
  .sp-promo {
121
121
  margin: 10px 0 6px;
122
122
  padding: 10px;
123
- background: rgba(15, 118, 110, 0.04);
124
- border: 1px solid rgba(0, 0, 0, 0.1);
123
+ background: var(--sa-color-accent-surface-soft);
124
+ border: 1px solid var(--sa-color-border);
125
125
  border-radius: 10px;
126
126
  }
127
127
  .sp-promo--valid {
128
- border-color: rgba(22, 163, 74, 0.5);
129
- background: rgba(22, 163, 74, 0.06);
128
+ border-color: var(--sa-color-positive-border);
129
+ background: var(--sa-color-positive-surface);
130
130
  }
131
131
  .sp-promo--invalid {
132
- border-color: rgba(220, 38, 38, 0.4);
133
- background: rgba(220, 38, 38, 0.04);
132
+ border-color: var(--sa-color-negative-border);
133
+ background: var(--sa-color-negative-surface);
134
134
  }
135
135
  .sp-promo--restricted {
136
- border-color: rgba(245, 158, 11, 0.4);
137
- background: rgba(245, 158, 11, 0.06);
136
+ border-color: var(--sa-color-warning-border);
137
+ background: var(--sa-color-warning-surface);
138
138
  }
139
139
  .sp-promo__field {
140
140
  display: flex;
@@ -143,26 +143,26 @@ function remove(): void {
143
143
  .sp-promo__field input {
144
144
  flex: 1;
145
145
  padding: 8px 10px;
146
- border: 1px solid rgba(0, 0, 0, 0.1);
146
+ border: 1px solid var(--sa-color-border);
147
147
  border-radius: 8px;
148
148
  font-family: 'SF Mono', Consolas, monospace;
149
- font-size: 12px;
149
+ font-size: var(--sa-text-sm);
150
150
  letter-spacing: 0.04em;
151
- background: #fff;
151
+ background: var(--sa-color-bg-surface);
152
152
  outline: none;
153
153
  text-transform: uppercase;
154
154
  }
155
155
  .sp-promo__field input:focus {
156
- border-color: var(--q-primary, #0f766e);
156
+ border-color: var(--sa-color-accent);
157
157
  }
158
158
  .sp-promo__btn {
159
159
  padding: 8px 12px;
160
- background: var(--q-primary, #0f766e);
161
- color: #fff;
160
+ background: var(--sa-color-accent);
161
+ color: var(--sa-color-fg-on-accent);
162
162
  border: none;
163
163
  border-radius: 8px;
164
164
  font-family: inherit;
165
- font-size: 11px;
165
+ font-size: var(--sa-text-xs);
166
166
  font-weight: 700;
167
167
  cursor: pointer;
168
168
  min-width: 70px;
@@ -172,21 +172,21 @@ function remove(): void {
172
172
  cursor: not-allowed;
173
173
  }
174
174
  .sp-promo__btn--remove {
175
- background: rgba(220, 38, 38, 0.1);
176
- color: #b91c1c;
175
+ background: var(--sa-color-negative-surface);
176
+ color: var(--sa-color-negative-fg);
177
177
  }
178
178
  .sp-promo__msg {
179
179
  margin-top: 6px;
180
- font-size: 11px;
180
+ font-size: var(--sa-text-xs);
181
181
  font-weight: 600;
182
182
  }
183
183
  .sp-promo__msg--valid {
184
- color: #166534;
184
+ color: var(--sa-color-positive-fg);
185
185
  }
186
186
  .sp-promo__msg--invalid {
187
- color: #b91c1c;
187
+ color: var(--sa-color-negative-fg);
188
188
  }
189
189
  .sp-promo__msg--restricted {
190
- color: #92400e;
190
+ color: var(--sa-color-warning-fg);
191
191
  }
192
192
  </style>
@@ -172,8 +172,8 @@ function priceLabel(bundle: PublicMarketingBundle): string {
172
172
  cursor: pointer;
173
173
  font-family: inherit;
174
174
  text-align: left;
175
- background: #fff;
176
- border: 1.5px solid rgba(0, 0, 0, 0.1);
175
+ background: var(--sa-color-bg-surface);
176
+ border: 1.5px solid var(--sa-color-border);
177
177
  border-radius: 14px;
178
178
  padding: 14px 16px 12px;
179
179
  display: flex;
@@ -183,11 +183,15 @@ function priceLabel(bundle: PublicMarketingBundle): string {
183
183
  }
184
184
  .sp-public-bundle:hover {
185
185
  transform: translateY(-2px);
186
- border-color: rgba(15, 118, 110, 0.3);
186
+ border-color: var(--sa-color-accent-border);
187
187
  }
188
188
  .sp-public-bundle--on {
189
- border-color: var(--q-primary, #0f766e);
190
- background: linear-gradient(180deg, rgba(15, 118, 110, 0.06), #fff 80%);
189
+ border-color: var(--sa-color-accent);
190
+ background: linear-gradient(
191
+ 180deg,
192
+ var(--sa-color-accent-surface-soft),
193
+ var(--sa-color-bg-surface) 80%
194
+ );
191
195
  }
192
196
  .sp-public-bundle--off {
193
197
  cursor: not-allowed;
@@ -195,7 +199,7 @@ function priceLabel(bundle: PublicMarketingBundle): string {
195
199
  }
196
200
  .sp-public-bundle--off:hover {
197
201
  transform: none;
198
- border-color: rgba(0, 0, 0, 0.1);
202
+ border-color: var(--sa-color-border);
199
203
  }
200
204
  .sp-public-bundle__head {
201
205
  display: flex;
@@ -203,24 +207,24 @@ function priceLabel(bundle: PublicMarketingBundle): string {
203
207
  gap: 10px;
204
208
  }
205
209
  .sp-public-bundle__name {
206
- font-size: 14px;
210
+ font-size: var(--sa-text-lg);
207
211
  font-weight: 700;
208
- color: rgba(0, 0, 0, 0.85);
212
+ color: var(--sa-color-fg-heading);
209
213
  }
210
214
  .sp-public-bundle__desc {
211
215
  margin: 4px 0 0;
212
- color: rgba(0, 0, 0, 0.55);
213
- font-size: 12px;
216
+ color: var(--sa-color-fg-muted);
217
+ font-size: var(--sa-text-sm);
214
218
  line-height: 1.4;
215
219
  }
216
220
  .sp-public-bundle__tag {
217
221
  align-self: flex-start;
218
222
  white-space: nowrap;
219
223
  font-family: 'SF Mono', Consolas, monospace;
220
- font-size: 9.5px;
224
+ font-size: var(--sa-text-2xs);
221
225
  letter-spacing: 0.06em;
222
- color: #166534;
223
- background: rgba(22, 163, 74, 0.16);
226
+ color: var(--sa-color-positive-fg);
227
+ background: var(--sa-color-positive-surface-strong);
224
228
  padding: 3px 7px;
225
229
  border-radius: 999px;
226
230
  font-weight: 700;
@@ -228,33 +232,33 @@ function priceLabel(bundle: PublicMarketingBundle): string {
228
232
  }
229
233
  .sp-public-bundle__state {
230
234
  align-self: flex-start;
231
- font-size: 11px;
235
+ font-size: var(--sa-text-xs);
232
236
  font-weight: 700;
233
237
  padding: 3px 8px;
234
238
  border-radius: 999px;
235
239
  line-height: 1.3;
236
240
  }
237
241
  .sp-public-bundle__state--covered {
238
- color: #166534;
239
- background: rgba(22, 163, 74, 0.16);
242
+ color: var(--sa-color-positive-fg);
243
+ background: var(--sa-color-positive-surface-strong);
240
244
  }
241
245
  .sp-public-bundle__state--blocked {
242
- color: rgba(0, 0, 0, 0.6);
243
- background: rgba(0, 0, 0, 0.08);
246
+ color: var(--sa-color-fg-secondary);
247
+ background: var(--sa-color-bg-sunken);
244
248
  }
245
249
  .sp-public-bundle__features,
246
250
  .sp-public-bundle__quotas {
247
251
  display: flex;
248
252
  flex-direction: column;
249
253
  gap: 3px;
250
- font-size: 12px;
251
- color: rgba(0, 0, 0, 0.55);
254
+ font-size: var(--sa-text-sm);
255
+ color: var(--sa-color-fg-muted);
252
256
  line-height: 1.4;
253
257
  }
254
258
  .sp-public-bundle__features span::before,
255
259
  .sp-public-bundle__quotas span::before {
256
260
  content: '+ ';
257
- color: var(--q-primary, #0f766e);
261
+ color: var(--sa-color-accent);
258
262
  font-weight: 700;
259
263
  }
260
264
  .sp-public-bundle__foot {
@@ -263,24 +267,24 @@ function priceLabel(bundle: PublicMarketingBundle): string {
263
267
  align-items: baseline;
264
268
  padding-top: 8px;
265
269
  margin-top: auto;
266
- border-top: 1px dashed rgba(0, 0, 0, 0.08);
270
+ border-top: 1px dashed var(--sa-color-border);
267
271
  }
268
272
  .sp-public-bundle__foot strong {
269
- font-size: 16px;
273
+ font-size: var(--sa-text-lg);
270
274
  font-weight: 800;
271
- color: rgba(0, 0, 0, 0.85);
275
+ color: var(--sa-color-fg-heading);
272
276
  }
273
277
  .sp-public-bundle__cycle {
274
278
  font-family: 'SF Mono', Consolas, monospace;
275
- font-size: 9.5px;
276
- color: rgba(0, 0, 0, 0.55);
279
+ font-size: var(--sa-text-2xs);
280
+ color: var(--sa-color-fg-muted);
277
281
  letter-spacing: 0.06em;
278
282
  }
279
283
  .sp-public-bundles__empty {
280
284
  grid-column: 1 / -1;
281
- color: rgba(0, 0, 0, 0.5);
285
+ color: var(--sa-color-fg-subtle);
282
286
  font-style: italic;
283
- font-size: 13px;
287
+ font-size: var(--sa-text-md);
284
288
  padding: 20px;
285
289
  text-align: center;
286
290
  }