@mundogamernetwork/shared-ui 1.1.67 → 1.1.69

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.
@@ -403,7 +403,7 @@ function statusColor(slug: string): string {
403
403
  &__login-btn {
404
404
  padding: 10px 24px;
405
405
  background: var(--accent, #00d4ff);
406
- color: #000;
406
+ color: var(--key-accent-ink, var(--accent-ink, #13161C));
407
407
  border: none;
408
408
  font-weight: 600;
409
409
  font-size: 0.9rem;
@@ -528,7 +528,7 @@ function statusColor(slug: string): string {
528
528
  &__request-btn {
529
529
  padding: 8px 16px;
530
530
  background: var(--accent, #00d4ff);
531
- color: #000;
531
+ color: var(--key-accent-ink, var(--accent-ink, #13161C));
532
532
  border: none;
533
533
  font-weight: 600;
534
534
  font-size: 0.85rem;
@@ -262,8 +262,8 @@ const detailRoute = computed(() =>
262
262
  position: absolute;
263
263
  bottom: 6px;
264
264
  left: 6px;
265
- background: rgba(0, 0, 0, 0.75);
266
- color: #D297FF;
265
+ background: var(--overlay-dark-strong, rgba(0, 0, 0, 0.75));
266
+ color: var(--key-accent, var(--primary, #D297FF));
267
267
  font-size: 10px;
268
268
  font-weight: 700;
269
269
  padding: 3px 7px;
@@ -272,7 +272,7 @@ const detailRoute = computed(() =>
272
272
  gap: 4px;
273
273
  text-transform: uppercase;
274
274
 
275
- &.kc-card__exclusive-lock { color: #fff; }
275
+ &.kc-card__exclusive-lock { color: var(--card-article-title, #fff); }
276
276
  }
277
277
 
278
278
  &__early-access-badge {
@@ -300,7 +300,7 @@ const detailRoute = computed(() =>
300
300
  &__lock-overlay {
301
301
  position: absolute;
302
302
  inset: 0;
303
- background: rgba(0, 0, 0, 0.65);
303
+ background: var(--overlay-dark, rgba(0, 0, 0, 0.65));
304
304
  display: flex;
305
305
  flex-direction: column;
306
306
  align-items: center;
@@ -310,10 +310,10 @@ const detailRoute = computed(() =>
310
310
  text-align: center;
311
311
 
312
312
  i { font-size: 1.5rem; color: var(--primary); }
313
- .lock-label { font-size: 11px; font-weight: 700; color: #fff; text-transform: uppercase; }
314
- .lock-countdown { font-size: 10px; color: rgba(255,255,255,0.7); }
313
+ .lock-label { font-size: 11px; font-weight: 700; color: var(--card-article-title, #fff); text-transform: uppercase; }
314
+ .lock-countdown { font-size: 10px; color: var(--secondary-info-fg, rgba(255,255,255,0.7)); }
315
315
 
316
- &--exclusive i { color: #D297FF; }
316
+ &--exclusive i { color: var(--key-accent, var(--primary, #D297FF)); }
317
317
  }
318
318
 
319
319
  &__meta-bar {
@@ -0,0 +1,190 @@
1
+ <script lang="ts" setup>
2
+ import { ref, onMounted, inject } from "vue"
3
+ import { fetchCampaigns } from "../../services/campaignService"
4
+
5
+ const props = defineProps<{
6
+ excludeId?: number | null
7
+ mgPlatform?: string
8
+ }>()
9
+
10
+ const mgPlatform = props.mgPlatform || (inject<string>("mgPlatform", "MGTV"))
11
+
12
+ const items = ref<any[]>([])
13
+ const loading = ref(true)
14
+
15
+ onMounted(async () => {
16
+ try {
17
+ const res = await fetchCampaigns(
18
+ {
19
+ filter: { is_open: 1 },
20
+ per_page: 10,
21
+ sort: "id",
22
+ order: "desc",
23
+ },
24
+ mgPlatform,
25
+ )
26
+ const data: any[] = res?.data?.data || res?.data || []
27
+ items.value = props.excludeId
28
+ ? data.filter((c: any) => c.id !== props.excludeId)
29
+ : data
30
+ } catch {
31
+ // silently ignore — carousel is non-critical
32
+ } finally {
33
+ loading.value = false
34
+ }
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <div v-if="loading || items.length > 0" class="kc-carousel">
40
+ <div class="kc-carousel__header">
41
+ <span class="kc-carousel__title">{{ $t("keys.campaigns.other_campaigns") }}</span>
42
+ </div>
43
+
44
+ <div v-if="loading" class="kc-carousel__track">
45
+ <div v-for="i in 4" :key="i" class="kc-carousel__skeleton" />
46
+ </div>
47
+
48
+ <div v-else class="kc-carousel__track">
49
+ <NuxtLink
50
+ v-for="item in items"
51
+ :key="item.id"
52
+ :to="`/key-campaigns/${item.slug}`"
53
+ class="kc-carousel__card"
54
+ >
55
+ <div class="kc-carousel__thumb">
56
+ <img
57
+ v-if="item.cover_src || item.cover"
58
+ :src="item.cover_src || item.cover"
59
+ :alt="item.name"
60
+ />
61
+ <div v-else class="kc-carousel__thumb-placeholder">
62
+ <i class="mg-icon mg-icon-game-key" />
63
+ </div>
64
+ <span v-if="!item.is_open" class="kc-carousel__closed">{{ $t("keys.campaigns.closed") }}</span>
65
+ </div>
66
+ <div class="kc-carousel__info">
67
+ <div class="kc-carousel__name">{{ item.name }}</div>
68
+ <div class="kc-carousel__avail">
69
+ {{ item.available_count ?? 0 }}/{{ item.total_count ?? item.quantity ?? "?" }}
70
+ {{ $t("keys.campaigns.available") }}
71
+ </div>
72
+ </div>
73
+ </NuxtLink>
74
+ </div>
75
+ </div>
76
+ </template>
77
+
78
+ <style scoped lang="scss">
79
+ .kc-carousel {
80
+ margin-top: 40px;
81
+ padding-top: 24px;
82
+ border-top: 1px solid var(--button-secondary-default-bg);
83
+
84
+ &__header {
85
+ margin-bottom: 16px;
86
+ }
87
+
88
+ &__title {
89
+ font-size: 16px;
90
+ font-weight: 700;
91
+ color: var(--card-article-title);
92
+ }
93
+
94
+ &__track {
95
+ display: flex;
96
+ gap: 12px;
97
+ overflow-x: auto;
98
+ padding-bottom: 8px;
99
+ scrollbar-width: thin;
100
+ scrollbar-color: var(--button-secondary-default-bg) transparent;
101
+
102
+ &::-webkit-scrollbar { height: 4px; }
103
+ &::-webkit-scrollbar-track { background: transparent; }
104
+ &::-webkit-scrollbar-thumb { background: var(--button-secondary-default-bg); }
105
+ }
106
+
107
+ &__skeleton {
108
+ flex: 0 0 180px;
109
+ height: 140px;
110
+ background: var(--bg-app-badge);
111
+ animation: pulse 1.4s ease-in-out infinite;
112
+ }
113
+
114
+ &__card {
115
+ flex: 0 0 180px;
116
+ display: flex;
117
+ flex-direction: column;
118
+ text-decoration: none;
119
+ color: inherit;
120
+ border: 1px solid var(--button-secondary-default-bg);
121
+ transition: border-color 0.15s;
122
+
123
+ &:hover { border-color: var(--key-accent, var(--primary, #D297FF)); }
124
+ }
125
+
126
+ &__thumb {
127
+ position: relative;
128
+ width: 100%;
129
+ height: 101px;
130
+ overflow: hidden;
131
+ background: var(--bg-app-badge);
132
+
133
+ img {
134
+ width: 100%;
135
+ height: 100%;
136
+ object-fit: cover;
137
+ }
138
+ }
139
+
140
+ &__thumb-placeholder {
141
+ width: 100%;
142
+ height: 100%;
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ color: var(--secondary-info-fg);
147
+ font-size: 24px;
148
+ }
149
+
150
+ &__closed {
151
+ position: absolute;
152
+ inset: 0;
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ background: var(--overlay-dark, rgba(0, 0, 0, 0.55));
157
+ font-size: 11px;
158
+ font-weight: 700;
159
+ color: var(--card-article-title, #fff);
160
+ letter-spacing: 0.5px;
161
+ text-transform: uppercase;
162
+ }
163
+
164
+ &__info {
165
+ padding: 8px 10px;
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: 4px;
169
+ }
170
+
171
+ &__name {
172
+ font-size: 12px;
173
+ font-weight: 600;
174
+ color: var(--card-article-title);
175
+ overflow: hidden;
176
+ text-overflow: ellipsis;
177
+ white-space: nowrap;
178
+ }
179
+
180
+ &__avail {
181
+ font-size: 11px;
182
+ color: var(--secondary-info-fg);
183
+ }
184
+ }
185
+
186
+ @keyframes pulse {
187
+ 0%, 100% { opacity: 1; }
188
+ 50% { opacity: 0.4; }
189
+ }
190
+ </style>
package/locales/de.json CHANGED
@@ -133,7 +133,27 @@
133
133
  "who_redeem": "Who redeemed",
134
134
  "created_by": "Published by",
135
135
  "no_data": "Campaign not found"
136
- }
136
+ },
137
+ "other_campaigns": "Andere Kampagnen",
138
+ "available": "verfügbar",
139
+ "closed": "Beendet",
140
+ "platform": "Plattform",
141
+ "region": "Region",
142
+ "description_optional": "Beschreibung (optional)",
143
+ "description_placeholder": "Erzähl uns etwas über deinen Kanal...",
144
+ "sending": "Wird gesendet...",
145
+ "request_sent": "Anfrage gesendet! Weiterleitung...",
146
+ "error_loading": "Kampagnendaten konnten nicht geladen werden.",
147
+ "error_request": "Anfrage konnte nicht gesendet werden. Bitte erneut versuchen.",
148
+ "error_reveal": "Schlüssel konnte nicht enthüllt werden.",
149
+ "redeem_title": "Schlüssel anfordern",
150
+ "reveal_hint": "Klicke unten, um deinen Schlüsselcode zu enthüllen.",
151
+ "your_key": "Dein Schlüssel",
152
+ "copy": "Kopieren",
153
+ "copied": "Kopiert!",
154
+ "redeem_on_platform": "Löse diesen Schlüssel auf der entsprechenden Plattform ein.",
155
+ "revealing": "Enthülle...",
156
+ "status": "Status"
137
157
  },
138
158
  "materials": {
139
159
  "title": "Submit material",
@@ -158,4 +178,4 @@
158
178
  "success_close": "Close"
159
179
  }
160
180
  }
161
- }
181
+ }
package/locales/en.json CHANGED
@@ -133,7 +133,27 @@
133
133
  "who_redeem": "Who redeemed",
134
134
  "created_by": "Published by",
135
135
  "no_data": "Campaign not found"
136
- }
136
+ },
137
+ "other_campaigns": "Other campaigns",
138
+ "available": "available",
139
+ "closed": "Closed",
140
+ "platform": "Platform",
141
+ "region": "Region",
142
+ "description_optional": "Description (optional)",
143
+ "description_placeholder": "Tell us a bit about your channel or content plans...",
144
+ "sending": "Sending...",
145
+ "request_sent": "Request sent! Redirecting...",
146
+ "error_loading": "Failed to load campaign data.",
147
+ "error_request": "Could not submit request. Please try again.",
148
+ "error_reveal": "Could not reveal key. Please try again.",
149
+ "redeem_title": "Request a Key",
150
+ "reveal_hint": "Click the button below to reveal your key code.",
151
+ "your_key": "Your Key",
152
+ "copy": "Copy",
153
+ "copied": "Copied!",
154
+ "redeem_on_platform": "Redeem this key on the platform where you received it.",
155
+ "revealing": "Revealing...",
156
+ "status": "Status"
137
157
  },
138
158
  "materials": {
139
159
  "title": "Submit material",
@@ -158,4 +178,4 @@
158
178
  "success_close": "Close"
159
179
  }
160
180
  }
161
- }
181
+ }
@@ -133,7 +133,27 @@
133
133
  "who_redeem": "Who redeemed",
134
134
  "created_by": "Published by",
135
135
  "no_data": "Campaign not found"
136
- }
136
+ },
137
+ "other_campaigns": "Outras campanhas",
138
+ "available": "disponível",
139
+ "closed": "Encerrada",
140
+ "platform": "Plataforma",
141
+ "region": "Região",
142
+ "description_optional": "Descrição (opcional)",
143
+ "description_placeholder": "Conte um pouco sobre seu canal ou planos de conteúdo...",
144
+ "sending": "Enviando...",
145
+ "request_sent": "Solicitação enviada! Redirecionando...",
146
+ "error_loading": "Falha ao carregar dados da campanha.",
147
+ "error_request": "Não foi possível enviar a solicitação. Tente novamente.",
148
+ "error_reveal": "Não foi possível revelar a chave. Tente novamente.",
149
+ "redeem_title": "Solicitar uma Chave",
150
+ "reveal_hint": "Clique no botão abaixo para revelar o código da sua chave.",
151
+ "your_key": "Sua Chave",
152
+ "copy": "Copiar",
153
+ "copied": "Copiado!",
154
+ "redeem_on_platform": "Resgate esta chave na plataforma correspondente.",
155
+ "revealing": "Revelando...",
156
+ "status": "Status"
137
157
  },
138
158
  "materials": {
139
159
  "title": "Submit material",
@@ -158,4 +178,4 @@
158
178
  "success_close": "Close"
159
179
  }
160
180
  }
161
- }
181
+ }
package/locales/ro.json CHANGED
@@ -133,7 +133,27 @@
133
133
  "who_redeem": "Who redeemed",
134
134
  "created_by": "Published by",
135
135
  "no_data": "Campaign not found"
136
- }
136
+ },
137
+ "other_campaigns": "Alte campanii",
138
+ "available": "disponibil",
139
+ "closed": "Închis",
140
+ "platform": "Platformă",
141
+ "region": "Regiune",
142
+ "description_optional": "Descriere (opțional)",
143
+ "description_placeholder": "Spune-ne puțin despre canalul tău...",
144
+ "sending": "Se trimite...",
145
+ "request_sent": "Cerere trimisă! Redirecționare...",
146
+ "error_loading": "Eroare la încărcarea datelor campaniei.",
147
+ "error_request": "Nu s-a putut trimite cererea. Încearcă din nou.",
148
+ "error_reveal": "Nu s-a putut dezvălui cheia.",
149
+ "redeem_title": "Solicită o Cheie",
150
+ "reveal_hint": "Apasă butonul de mai jos pentru a dezvălui codul cheii.",
151
+ "your_key": "Cheia Ta",
152
+ "copy": "Copiază",
153
+ "copied": "Copiat!",
154
+ "redeem_on_platform": "Activează această cheie pe platforma corespunzătoare.",
155
+ "revealing": "Se dezvăluie...",
156
+ "status": "Status"
137
157
  },
138
158
  "materials": {
139
159
  "title": "Submit material",
@@ -158,4 +178,4 @@
158
178
  "success_close": "Close"
159
179
  }
160
180
  }
161
- }
181
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.1.67",
3
+ "version": "1.1.69",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -41,6 +41,19 @@ const key = computed(() => keyData.value?.data || null);
41
41
  const loading = pending;
42
42
  const error = computed(() => !!fetchError.value || (!pending.value && !key.value));
43
43
 
44
+ const { $i18n } = useNuxtApp()
45
+ const t = $i18n.t.bind($i18n)
46
+
47
+ useSeoMeta({
48
+ title: () => key.value?.name ? t('keys.campaigns.seo.title', { game: key.value.name }) : t('keys.campaigns.seo.title_generic'),
49
+ description: () => key.value?.name ? t('keys.campaigns.seo.description', { game: key.value.name }) : t('keys.campaigns.seo.title_generic'),
50
+ ogTitle: () => key.value?.name ? t('keys.campaigns.seo.title', { game: key.value.name }) : t('keys.campaigns.seo.title_generic'),
51
+ ogDescription: () => key.value?.name ? t('keys.campaigns.seo.description', { game: key.value.name }) : t('keys.campaigns.seo.title_generic'),
52
+ ogImage: () => key.value?.cover_src || key.value?.cover || undefined,
53
+ ogType: 'website',
54
+ twitterCard: 'summary_large_image',
55
+ })
56
+
44
57
  const restriction = computed(() => {
45
58
  const k = key.value;
46
59
  if (!k) return '';
@@ -76,6 +89,8 @@ const restriction = computed(() => {
76
89
  :game-id="key.game?.id || key.game_id"
77
90
  />
78
91
  </div>
92
+
93
+ <KeyCampaignsCarousel :exclude-id="key.id ?? null" />
79
94
  </template>
80
95
  </div>
81
96
  </template>
@@ -125,7 +140,7 @@ const restriction = computed(() => {
125
140
  padding: 4px 10px;
126
141
  font-size: 0.8rem;
127
142
  font-weight: 600;
128
- color: #d297ff;
143
+ color: var(--key-accent, var(--primary, #D297FF));
129
144
  border: 1px solid rgba(210, 151, 255, 0.35);
130
145
  background: rgba(210, 151, 255, 0.12);
131
146
  }
@@ -224,9 +224,9 @@ const restrictionBadges = computed(() => {
224
224
  // UserRequestsValidation inline state (ported from TV component)
225
225
  // ------------------------------------------------------------------
226
226
  type StatusConfig = {
227
- titleParts: { text: string; color?: "default" | "yellow" | "red" }[]
227
+ titleParts: { text: string; color?: "default" | "yellow" | "var(--danger, #e53935)" }[]
228
228
  obs: string
229
- obsColor?: "default" | "yellow" | "red"
229
+ obsColor?: "default" | "yellow" | "var(--danger, #e53935)"
230
230
  progress?: { percent: number; step: number; total: number; color?: "default" | "yellow" | "complete" }
231
231
  actions?: Array<{ type: string; disabled?: boolean }>
232
232
  canViewCode?: boolean
@@ -236,18 +236,18 @@ const statusConfigs: Record<string, StatusConfig> = {
236
236
  expired: {
237
237
  titleParts: [
238
238
  { text: "keys.campaigns.status_key.title_0" },
239
- { text: "keys.campaigns.status_key.title_span_0", color: "red" },
239
+ { text: "keys.campaigns.status_key.title_span_0", color: "var(--danger, #e53935)" },
240
240
  ],
241
241
  obs: "keys.campaigns.status_key.obs_0",
242
- obsColor: "red",
242
+ obsColor: "var(--danger, #e53935)",
243
243
  },
244
244
  exhausted: {
245
245
  titleParts: [
246
246
  { text: "keys.campaigns.status_key.title_exhausted" },
247
- { text: "keys.campaigns.status_key.title_span_exhausted", color: "red" },
247
+ { text: "keys.campaigns.status_key.title_span_exhausted", color: "var(--danger, #e53935)" },
248
248
  ],
249
249
  obs: "keys.campaigns.status_key.obs_exhausted",
250
- obsColor: "red",
250
+ obsColor: "var(--danger, #e53935)",
251
251
  },
252
252
  locked_exclusive: {
253
253
  titleParts: [
@@ -343,34 +343,34 @@ const statusConfigs: Record<string, StatusConfig> = {
343
343
  "6": {
344
344
  titleParts: [
345
345
  { text: "keys.campaigns.status_key.title_5" },
346
- { text: "keys.campaigns.status_key.title_span_5", color: "red" },
346
+ { text: "keys.campaigns.status_key.title_span_5", color: "var(--danger, #e53935)" },
347
347
  ],
348
348
  obs: "keys.campaigns.status_key.obs_5",
349
- obsColor: "red",
349
+ obsColor: "var(--danger, #e53935)",
350
350
  },
351
351
  "7": {
352
352
  titleParts: [
353
353
  { text: "keys.campaigns.status_key.title_6" },
354
- { text: "keys.campaigns.status_key.title_span_6", color: "red" },
354
+ { text: "keys.campaigns.status_key.title_span_6", color: "var(--danger, #e53935)" },
355
355
  ],
356
356
  obs: "keys.campaigns.status_key.obs_6",
357
- obsColor: "red",
357
+ obsColor: "var(--danger, #e53935)",
358
358
  },
359
359
  "8": {
360
360
  titleParts: [
361
361
  { text: "keys.campaigns.status_key.title_7" },
362
- { text: "keys.campaigns.status_key.title_span_7", color: "red" },
362
+ { text: "keys.campaigns.status_key.title_span_7", color: "var(--danger, #e53935)" },
363
363
  ],
364
364
  obs: "keys.campaigns.status_key.obs_7",
365
- obsColor: "red",
365
+ obsColor: "var(--danger, #e53935)",
366
366
  },
367
367
  "9": {
368
368
  titleParts: [
369
369
  { text: "keys.campaigns.status_key.title_8" },
370
- { text: "keys.campaigns.status_key.title_span_8", color: "red" },
370
+ { text: "keys.campaigns.status_key.title_span_8", color: "var(--danger, #e53935)" },
371
371
  ],
372
372
  obs: "keys.campaigns.status_key.obs_8",
373
- obsColor: "red",
373
+ obsColor: "var(--danger, #e53935)",
374
374
  },
375
375
  }
376
376
 
@@ -681,8 +681,9 @@ onMounted(async () => {
681
681
  <img
682
682
  v-for="(u, index) in redeemedUsers?.users?.slice(0, 4)"
683
683
  :key="index"
684
- :src="u.avatar_url"
684
+ :src="u.avatar_url || '/imgs/avatar-default.jpg'"
685
685
  :alt="u.nickname"
686
+ @error="(e: Event) => { const t = e.target as HTMLImageElement; if (t && t.src !== '/imgs/avatar-default.jpg') t.src = '/imgs/avatar-default.jpg' }"
686
687
  />
687
688
  </div>
688
689
  <div class="text">
@@ -719,6 +720,11 @@ onMounted(async () => {
719
720
  </div>
720
721
  </div>
721
722
  </div>
723
+ <KeyCampaignsCarousel
724
+ :exclude-id="campaign?.id ?? null"
725
+ :mg-platform="mgPlatform"
726
+ class="container"
727
+ />
722
728
  </div>
723
729
  </template>
724
730
 
@@ -761,7 +767,7 @@ onMounted(async () => {
761
767
  justify-content: space-between;
762
768
 
763
769
  .btn {
764
- background: var(--key-accent, #D297FF);
770
+ background: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
765
771
  display: flex;
766
772
  height: 44px;
767
773
  padding: 0 14px;
@@ -787,7 +793,7 @@ onMounted(async () => {
787
793
  align-items: center;
788
794
  gap: 6px;
789
795
  font-size: 13px;
790
- color: var(--key-accent, #D297FF);
796
+ color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
791
797
  cursor: pointer;
792
798
  text-decoration: none;
793
799
  white-space: nowrap;
@@ -806,9 +812,9 @@ onMounted(async () => {
806
812
  font-size: 14px;
807
813
  font-weight: 600;
808
814
  color: var(--card-article-title);
809
- span { color: var(--key-accent, #d297ff); }
810
- .yellow { color: #FFD600; }
811
- .red { color: #ff4800; }
815
+ span { color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); }
816
+ .yellow { color: var(--status-pending, #FFD600); }
817
+ .var(--danger, #e53935) { color: var(--danger, #e53935); }
812
818
  }
813
819
 
814
820
  .bar {
@@ -819,7 +825,7 @@ onMounted(async () => {
819
825
 
820
826
  .progress {
821
827
  height: 24px;
822
- background-color: var(--key-accent, #d297ff);
828
+ background-color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
823
829
  span {
824
830
  position: absolute;
825
831
  right: 5px;
@@ -829,15 +835,15 @@ onMounted(async () => {
829
835
  }
830
836
  }
831
837
  .complete span { color: #272930; }
832
- .yellow { background-color: #FFD600; }
838
+ .yellow { background-color: var(--status-pending, #FFD600); }
833
839
  }
834
840
 
835
841
  .info {
836
842
  font-size: 12px;
837
843
  color: var(--secondary-info-fg);
838
- i { color: var(--key-accent, #d297ff); }
839
- .yellow { color: #FFD600; }
840
- .red { color: #ff4800; }
844
+ i { color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); }
845
+ .yellow { color: var(--status-pending, #FFD600); }
846
+ .var(--danger, #e53935) { color: var(--danger, #e53935); }
841
847
  }
842
848
  }
843
849
 
@@ -882,9 +888,9 @@ onMounted(async () => {
882
888
  padding: 4px 10px;
883
889
  font-size: 12px;
884
890
  font-weight: 600;
885
- color: var(--key-accent, #D297FF);
886
- background: rgba(210, 151, 255, 0.12);
887
- border: 1px solid rgba(210, 151, 255, 0.35);
891
+ color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
892
+ background: var(--key-accent-subtle-bg, rgba(210, 151, 255, 0.12));
893
+ border: 1px solid var(--key-accent-subtle-border, rgba(210, 151, 255, 0.35));
888
894
  i { font-size: 13px; }
889
895
  }
890
896
  }
@@ -960,9 +966,9 @@ onMounted(async () => {
960
966
  height: 32px;
961
967
  font-size: 12px;
962
968
  font-weight: 400;
963
- span.active { color: #42FF00; }
964
- span.inactive { color: red; }
965
- span.ending { color: #ffa600; }
969
+ span.active { color: var(--success, #22c55e); }
970
+ span.inactive { color: var(--danger, #e53935); }
971
+ span.ending { color: var(--status-ending, #ffa600); }
966
972
  }
967
973
  }
968
974
  }
@@ -981,7 +987,7 @@ onMounted(async () => {
981
987
  gap: 6px;
982
988
  background-color: var(--button-secondary-default-bg);
983
989
  font-size: 28px;
984
- color: var(--key-accent, #D297FF);
990
+ color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
985
991
  font-weight: 700;
986
992
  width: -webkit-fill-available;
987
993
  span { font-size: 10px; color: var(--secondary-info-fg); font-weight: 400; }
@@ -1015,9 +1021,9 @@ onMounted(async () => {
1015
1021
  width: -webkit-fill-available;
1016
1022
  cursor: pointer;
1017
1023
  &:hover, &.active {
1018
- background-color: var(--key-accent, #D297FF);
1019
- color: #1C1C1C;
1020
- i { color: #1C1C1C; }
1024
+ background-color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
1025
+ color: var(--key-accent-ink, #13161C);
1026
+ i { color: var(--key-accent-ink, #13161C); }
1021
1027
  }
1022
1028
  }
1023
1029
  .tag-bg {
@@ -1060,7 +1066,7 @@ onMounted(async () => {
1060
1066
  flex-shrink: 0;
1061
1067
  border-radius: 100%;
1062
1068
  text-align-last: center;
1063
- i { color: var(--key-accent, #D297FF); }
1069
+ i { color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); }
1064
1070
  }
1065
1071
  .texts {
1066
1072
  display: flex;
@@ -1081,7 +1087,7 @@ onMounted(async () => {
1081
1087
  width: 100%;
1082
1088
  }
1083
1089
 
1084
- .reward span { color: var(--key-accent, #D297FF); }
1090
+ .reward span { color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); }
1085
1091
 
1086
1092
  .data {
1087
1093
  display: flex;
@@ -1114,7 +1120,7 @@ onMounted(async () => {
1114
1120
  font-size: 12px;
1115
1121
  color: var(--secondary-info-fg);
1116
1122
  width: -webkit-fill-available;
1117
- span { font-size: 16px; color: var(--key-accent, #D297FF); font-weight: 600; }
1123
+ span { font-size: 16px; color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); font-weight: 600; }
1118
1124
  }
1119
1125
  }
1120
1126