@mundogamernetwork/shared-ui 1.8.22 → 1.9.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.
- package/components/keys/KeyBrowser.vue +41 -11
- package/components/keys/KeyCampaignCommentItem.vue +303 -0
- package/components/keys/KeyCampaignComments.vue +355 -0
- package/components/keys/KeyCampaignDashboardCard.vue +2 -2
- package/components/keys/KeyCampaignFeedback.vue +250 -0
- package/components/keys/KeyRevealModal.vue +2 -2
- package/locales/de.json +45 -3
- package/locales/en.json +45 -3
- package/locales/es.json +45 -3
- package/locales/pt-BR.json +45 -3
- package/locales/ro.json +45 -3
- package/package.json +1 -1
- package/pages/key-campaigns/[slug].vue +86 -34
- package/pages/key-campaigns/index.vue +72 -1
- package/pages/key-campaigns/key-materials.vue +2 -2
- package/pages/key-campaigns/redeem-key-approved.vue +30 -24
- package/pages/key-campaigns/redeem-key.vue +58 -14
- package/pages/keys/index.vue +1 -1
- package/pages/presskit/game/[slug].vue +33 -3
- package/services/campaignService.ts +149 -2
- package/utils/embargo.ts +47 -18
- package/utils/navigation.ts +26 -0
|
@@ -36,6 +36,10 @@ const platforms = ref<{ id: number; name: string }[]>([])
|
|
|
36
36
|
const loadingPools = ref(true)
|
|
37
37
|
const loadingRequests = ref(true)
|
|
38
38
|
const requesting = ref<number | null>(null)
|
|
39
|
+
// Per-pool refusal message. The catch below only ever handled 401, so every
|
|
40
|
+
// other refusal — quota reached, campaign closed, not eligible — left the
|
|
41
|
+
// button doing nothing at all with no explanation.
|
|
42
|
+
const requestErrors = ref<Record<number, string>>({})
|
|
39
43
|
const activeTab = ref<'available' | 'mine'>('available')
|
|
40
44
|
const isAuthenticated = ref(true) // assume true; set false on 401
|
|
41
45
|
|
|
@@ -114,6 +118,7 @@ function redirectToLogin() {
|
|
|
114
118
|
|
|
115
119
|
async function doRequestKey(pool: KeyPool) {
|
|
116
120
|
requesting.value = pool.id
|
|
121
|
+
delete requestErrors.value[pool.id]
|
|
117
122
|
try {
|
|
118
123
|
const form = requestForms.value[pool.id] ?? { platform_ids: [], description: '' }
|
|
119
124
|
const body: Record<string, any> = {
|
|
@@ -129,8 +134,22 @@ async function doRequestKey(pool: KeyPool) {
|
|
|
129
134
|
_checkNotifPrompt()
|
|
130
135
|
}
|
|
131
136
|
} catch (err: any) {
|
|
132
|
-
|
|
137
|
+
const status = err?.response?.status
|
|
138
|
+
const errorCode = err?.response?.data?.error_code
|
|
139
|
+
|
|
140
|
+
if (status === 401) {
|
|
133
141
|
isAuthenticated.value = false
|
|
142
|
+
} else if (status === 409) {
|
|
143
|
+
requestErrors.value[pool.id] = t('keys.campaigns.error_duplicate')
|
|
144
|
+
} else if (status === 403 && errorCode === 'user_key_blocked') {
|
|
145
|
+
requestErrors.value[pool.id] = t('keys.campaigns.error_user_blocked')
|
|
146
|
+
} else if (status === 403) {
|
|
147
|
+
requestErrors.value[pool.id] = t('keys.campaigns.error_not_eligible')
|
|
148
|
+
} else if (status === 422 && errorCode === 'pending_limit_reached') {
|
|
149
|
+
requestErrors.value[pool.id] = t('keys.campaigns.error_pending_limit')
|
|
150
|
+
} else {
|
|
151
|
+
requestErrors.value[pool.id] =
|
|
152
|
+
err?.response?.data?.message || t('keys.campaigns.error_request')
|
|
134
153
|
}
|
|
135
154
|
} finally {
|
|
136
155
|
requesting.value = null
|
|
@@ -325,6 +344,10 @@ function statusColor(slug: string): string {
|
|
|
325
344
|
{{ requesting === pool.id ? $t('common.sending') : $t('keys.browser.request_btn') }}
|
|
326
345
|
</button>
|
|
327
346
|
</div>
|
|
347
|
+
|
|
348
|
+
<p v-if="requestErrors[pool.id]" class="kb__request-error" role="alert">
|
|
349
|
+
{{ requestErrors[pool.id] }}
|
|
350
|
+
</p>
|
|
328
351
|
</div>
|
|
329
352
|
</div>
|
|
330
353
|
</div>
|
|
@@ -399,7 +422,7 @@ function statusColor(slug: string): string {
|
|
|
399
422
|
&__auth-wall {
|
|
400
423
|
padding: 40px;
|
|
401
424
|
text-align: center;
|
|
402
|
-
color: var(--
|
|
425
|
+
color: var(--secondary-info-fg);
|
|
403
426
|
display: flex;
|
|
404
427
|
flex-direction: column;
|
|
405
428
|
align-items: center;
|
|
@@ -430,7 +453,7 @@ function statusColor(slug: string): string {
|
|
|
430
453
|
background: none;
|
|
431
454
|
border: none;
|
|
432
455
|
border-bottom: 2px solid transparent;
|
|
433
|
-
color: var(--
|
|
456
|
+
color: var(--secondary-info-fg);
|
|
434
457
|
cursor: pointer;
|
|
435
458
|
display: flex;
|
|
436
459
|
align-items: center;
|
|
@@ -455,7 +478,7 @@ function statusColor(slug: string): string {
|
|
|
455
478
|
&__empty {
|
|
456
479
|
padding: 40px;
|
|
457
480
|
text-align: center;
|
|
458
|
-
color: var(--
|
|
481
|
+
color: var(--secondary-info-fg);
|
|
459
482
|
font-size: 0.9rem;
|
|
460
483
|
}
|
|
461
484
|
|
|
@@ -484,13 +507,13 @@ function statusColor(slug: string): string {
|
|
|
484
507
|
|
|
485
508
|
&__pool-availability { font-size: 0.82rem; }
|
|
486
509
|
&__avail-ok { color: var(--success, #22c55e); }
|
|
487
|
-
&__avail-empty { color: var(--
|
|
510
|
+
&__avail-empty { color: var(--secondary-info-fg); }
|
|
488
511
|
|
|
489
512
|
&__platform-sel { display: flex; flex-direction: column; gap: 6px; }
|
|
490
513
|
|
|
491
514
|
&__label {
|
|
492
515
|
font-size: 0.75rem;
|
|
493
|
-
color: var(--
|
|
516
|
+
color: var(--secondary-info-fg);
|
|
494
517
|
}
|
|
495
518
|
|
|
496
519
|
&__platform-chips {
|
|
@@ -503,7 +526,7 @@ function statusColor(slug: string): string {
|
|
|
503
526
|
padding: 4px 10px;
|
|
504
527
|
font-size: 0.78rem;
|
|
505
528
|
border: 1px solid var(--border-color, #2a2a2a);
|
|
506
|
-
color: var(--
|
|
529
|
+
color: var(--secondary-info-fg);
|
|
507
530
|
cursor: pointer;
|
|
508
531
|
transition: border-color 0.15s, color 0.15s;
|
|
509
532
|
|
|
@@ -551,6 +574,13 @@ function statusColor(slug: string): string {
|
|
|
551
574
|
color: var(--success, #22c55e);
|
|
552
575
|
}
|
|
553
576
|
|
|
577
|
+
&__request-error {
|
|
578
|
+
margin: 8px 0 0;
|
|
579
|
+
font-size: 0.8rem;
|
|
580
|
+
line-height: 1.45;
|
|
581
|
+
color: var(--danger, #ef4444);
|
|
582
|
+
}
|
|
583
|
+
|
|
554
584
|
&__request-list {
|
|
555
585
|
display: flex;
|
|
556
586
|
flex-direction: column;
|
|
@@ -577,7 +607,7 @@ function statusColor(slug: string): string {
|
|
|
577
607
|
|
|
578
608
|
&__request-platform {
|
|
579
609
|
font-size: 0.78rem;
|
|
580
|
-
color: var(--
|
|
610
|
+
color: var(--secondary-info-fg);
|
|
581
611
|
}
|
|
582
612
|
|
|
583
613
|
&__status-chip {
|
|
@@ -613,7 +643,7 @@ function statusColor(slug: string): string {
|
|
|
613
643
|
|
|
614
644
|
&__pending-label {
|
|
615
645
|
font-size: 0.8rem;
|
|
616
|
-
color: var(--
|
|
646
|
+
color: var(--secondary-info-fg);
|
|
617
647
|
font-style: italic;
|
|
618
648
|
}
|
|
619
649
|
|
|
@@ -647,7 +677,7 @@ function statusColor(slug: string): string {
|
|
|
647
677
|
p {
|
|
648
678
|
margin: 0;
|
|
649
679
|
font-size: 0.82rem;
|
|
650
|
-
color: var(--
|
|
680
|
+
color: var(--secondary-info-fg);
|
|
651
681
|
line-height: 1.4;
|
|
652
682
|
}
|
|
653
683
|
}
|
|
@@ -664,7 +694,7 @@ function statusColor(slug: string): string {
|
|
|
664
694
|
font-weight: 600;
|
|
665
695
|
border: 1px solid var(--border-color, #2a2a2a);
|
|
666
696
|
background: none;
|
|
667
|
-
color: var(--
|
|
697
|
+
color: var(--secondary-info-fg);
|
|
668
698
|
cursor: pointer;
|
|
669
699
|
transition: opacity 0.15s, border-color 0.15s, color 0.15s;
|
|
670
700
|
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<article class="campaign-comment" :class="{ 'campaign-comment--hidden': comment.is_hidden }">
|
|
3
|
+
<div class="campaign-comment__head">
|
|
4
|
+
<img
|
|
5
|
+
v-if="comment.author?.avatar"
|
|
6
|
+
:src="comment.author.avatar"
|
|
7
|
+
:alt="comment.author?.name || ''"
|
|
8
|
+
class="campaign-comment__avatar"
|
|
9
|
+
loading="lazy"
|
|
10
|
+
>
|
|
11
|
+
<div class="campaign-comment__meta">
|
|
12
|
+
<strong class="campaign-comment__author">
|
|
13
|
+
{{ comment.author?.name || comment.author?.nickname || $t("keys.campaigns.comments.unknown_author") }}
|
|
14
|
+
</strong>
|
|
15
|
+
<span class="campaign-comment__date">
|
|
16
|
+
{{ formattedDate }}
|
|
17
|
+
<em v-if="comment.edited">· {{ $t("keys.campaigns.comments.edited") }}</em>
|
|
18
|
+
</span>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<!-- Only shown to studio/admin: the public never learns a comment
|
|
22
|
+
was hidden, which is the point of hiding rather than deleting. -->
|
|
23
|
+
<span v-if="comment.is_hidden" class="campaign-comment__hidden-badge">
|
|
24
|
+
{{ $t("keys.campaigns.comments.hidden_badge") }}
|
|
25
|
+
</span>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<p v-if="!editing" class="campaign-comment__body">{{ comment.body }}</p>
|
|
29
|
+
|
|
30
|
+
<form v-else class="campaign-comment__edit" @submit.prevent="saveEdit">
|
|
31
|
+
<textarea v-model="editDraft" class="campaign-comment__edit-input" rows="3" :maxlength="2200" />
|
|
32
|
+
<div class="campaign-comment__actions">
|
|
33
|
+
<button type="submit" class="campaign-comment__action">{{ $t("keys.campaigns.comments.save") }}</button>
|
|
34
|
+
<button type="button" class="campaign-comment__action" @click="cancelEdit">{{ $t("keys.campaigns.comments.cancel") }}</button>
|
|
35
|
+
</div>
|
|
36
|
+
</form>
|
|
37
|
+
|
|
38
|
+
<div class="campaign-comment__actions">
|
|
39
|
+
<button v-if="canReply" type="button" class="campaign-comment__action" @click="replying = !replying">
|
|
40
|
+
{{ $t("keys.campaigns.comments.reply") }}
|
|
41
|
+
</button>
|
|
42
|
+
<button v-if="comment.can_edit && !editing" type="button" class="campaign-comment__action" @click="startEdit">
|
|
43
|
+
{{ $t("keys.campaigns.comments.edit") }}
|
|
44
|
+
</button>
|
|
45
|
+
<button v-if="comment.can_delete" type="button" class="campaign-comment__action" @click="confirmDelete">
|
|
46
|
+
{{ $t("keys.campaigns.comments.delete") }}
|
|
47
|
+
</button>
|
|
48
|
+
<button
|
|
49
|
+
v-if="canModerate && !comment.is_hidden"
|
|
50
|
+
type="button"
|
|
51
|
+
class="campaign-comment__action"
|
|
52
|
+
@click="emit('hide', { uuid: comment.uuid })"
|
|
53
|
+
>
|
|
54
|
+
{{ $t("keys.campaigns.comments.hide") }}
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
v-if="canModerate && comment.is_hidden"
|
|
58
|
+
type="button"
|
|
59
|
+
class="campaign-comment__action"
|
|
60
|
+
@click="emit('unhide', comment.uuid)"
|
|
61
|
+
>
|
|
62
|
+
{{ $t("keys.campaigns.comments.unhide") }}
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<form v-if="replying" class="campaign-comment__reply" @submit.prevent="sendReply">
|
|
67
|
+
<textarea
|
|
68
|
+
v-model="replyDraft"
|
|
69
|
+
class="campaign-comment__edit-input"
|
|
70
|
+
rows="2"
|
|
71
|
+
:maxlength="2200"
|
|
72
|
+
:placeholder="$t('keys.campaigns.comments.reply_placeholder')"
|
|
73
|
+
/>
|
|
74
|
+
<button type="submit" class="campaign-comment__action" :disabled="replyDraft.trim().length < 2">
|
|
75
|
+
{{ $t("keys.campaigns.comments.send") }}
|
|
76
|
+
</button>
|
|
77
|
+
</form>
|
|
78
|
+
|
|
79
|
+
<ul v-if="comment.replies?.length" class="campaign-comment__replies">
|
|
80
|
+
<li v-for="reply in comment.replies" :key="reply.uuid" class="campaign-comment__reply-item">
|
|
81
|
+
<div class="campaign-comment__head">
|
|
82
|
+
<img
|
|
83
|
+
v-if="reply.author?.avatar"
|
|
84
|
+
:src="reply.author.avatar"
|
|
85
|
+
:alt="reply.author?.name || ''"
|
|
86
|
+
class="campaign-comment__avatar campaign-comment__avatar--small"
|
|
87
|
+
loading="lazy"
|
|
88
|
+
>
|
|
89
|
+
<div class="campaign-comment__meta">
|
|
90
|
+
<strong class="campaign-comment__author">
|
|
91
|
+
{{ reply.author?.name || reply.author?.nickname }}
|
|
92
|
+
</strong>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
<p class="campaign-comment__body">{{ reply.body }}</p>
|
|
96
|
+
</li>
|
|
97
|
+
</ul>
|
|
98
|
+
</article>
|
|
99
|
+
</template>
|
|
100
|
+
|
|
101
|
+
<script setup lang="ts">
|
|
102
|
+
import { ref, computed } from "vue"
|
|
103
|
+
import type { CampaignComment } from "../../services/campaignService"
|
|
104
|
+
|
|
105
|
+
const props = defineProps<{
|
|
106
|
+
comment: CampaignComment
|
|
107
|
+
canModerate?: boolean
|
|
108
|
+
canReply?: boolean
|
|
109
|
+
}>()
|
|
110
|
+
|
|
111
|
+
const emit = defineEmits<{
|
|
112
|
+
(e: "edit", payload: { uuid: string; body: string }): void
|
|
113
|
+
(e: "delete", uuid: string): void
|
|
114
|
+
(e: "reply", payload: { uuid: string; body: string }): void
|
|
115
|
+
(e: "hide", payload: { uuid: string; reason?: string }): void
|
|
116
|
+
(e: "unhide", uuid: string): void
|
|
117
|
+
}>()
|
|
118
|
+
|
|
119
|
+
const editing = ref(false)
|
|
120
|
+
const replying = ref(false)
|
|
121
|
+
const editDraft = ref("")
|
|
122
|
+
const replyDraft = ref("")
|
|
123
|
+
|
|
124
|
+
const formattedDate = computed(() => {
|
|
125
|
+
if (!props.comment.created_at) return ""
|
|
126
|
+
try {
|
|
127
|
+
return new Date(props.comment.created_at).toLocaleDateString(undefined, {
|
|
128
|
+
day: "2-digit",
|
|
129
|
+
month: "short",
|
|
130
|
+
year: "numeric",
|
|
131
|
+
})
|
|
132
|
+
} catch (_) {
|
|
133
|
+
return ""
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
function startEdit() {
|
|
138
|
+
editDraft.value = props.comment.body
|
|
139
|
+
editing.value = true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function cancelEdit() {
|
|
143
|
+
editing.value = false
|
|
144
|
+
editDraft.value = ""
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function saveEdit() {
|
|
148
|
+
if (editDraft.value.trim().length < 2) return
|
|
149
|
+
emit("edit", { uuid: props.comment.uuid, body: editDraft.value.trim() })
|
|
150
|
+
editing.value = false
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function confirmDelete() {
|
|
154
|
+
emit("delete", props.comment.uuid)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function sendReply() {
|
|
158
|
+
if (replyDraft.value.trim().length < 2) return
|
|
159
|
+
emit("reply", { uuid: props.comment.uuid, body: replyDraft.value.trim() })
|
|
160
|
+
replyDraft.value = ""
|
|
161
|
+
replying.value = false
|
|
162
|
+
}
|
|
163
|
+
</script>
|
|
164
|
+
|
|
165
|
+
<style lang="scss" scoped>
|
|
166
|
+
/* Theme tokens only — see KeyCampaignComments.vue for why no literal colours. */
|
|
167
|
+
.campaign-comment {
|
|
168
|
+
padding: 1rem;
|
|
169
|
+
background: var(--card-article-bg);
|
|
170
|
+
border: 1px solid var(--card-article-border);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.campaign-comment--hidden {
|
|
174
|
+
opacity: 0.55;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.campaign-comment__head {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 0.625rem;
|
|
181
|
+
margin-bottom: 0.5rem;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.campaign-comment__avatar {
|
|
185
|
+
width: 2.25rem;
|
|
186
|
+
height: 2.25rem;
|
|
187
|
+
flex-shrink: 0;
|
|
188
|
+
object-fit: cover;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.campaign-comment__avatar--small {
|
|
192
|
+
width: 1.75rem;
|
|
193
|
+
height: 1.75rem;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.campaign-comment__meta {
|
|
197
|
+
display: flex;
|
|
198
|
+
flex-direction: column;
|
|
199
|
+
min-width: 0;
|
|
200
|
+
line-height: 1.3;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.campaign-comment__author {
|
|
204
|
+
font-size: 0.9375rem;
|
|
205
|
+
color: var(--card-article-title);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.campaign-comment__date {
|
|
209
|
+
font-size: 0.75rem;
|
|
210
|
+
color: var(--secondary-info-fg);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.campaign-comment__hidden-badge {
|
|
214
|
+
margin-left: auto;
|
|
215
|
+
font-size: 0.6875rem;
|
|
216
|
+
text-transform: uppercase;
|
|
217
|
+
letter-spacing: 0.04em;
|
|
218
|
+
padding: 0.125rem 0.5rem;
|
|
219
|
+
font-weight: 600;
|
|
220
|
+
color: var(--title-fg);
|
|
221
|
+
border: 1px solid var(--warning);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.campaign-comment__body {
|
|
225
|
+
margin: 0;
|
|
226
|
+
white-space: pre-wrap;
|
|
227
|
+
overflow-wrap: anywhere;
|
|
228
|
+
font-size: 0.9375rem;
|
|
229
|
+
color: var(--card-article-title);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.campaign-comment__edit-input {
|
|
233
|
+
width: 100%;
|
|
234
|
+
padding: 0.5rem;
|
|
235
|
+
/* See KeyCampaignComments.vue: --input-bg/--input-fg is 1.61:1 in dark. */
|
|
236
|
+
background: var(--card-article-bg);
|
|
237
|
+
border: 1px solid var(--input-border-color);
|
|
238
|
+
color: var(--title-fg);
|
|
239
|
+
font: inherit;
|
|
240
|
+
|
|
241
|
+
&::placeholder {
|
|
242
|
+
color: var(--secondary-info-fg);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
&:focus {
|
|
246
|
+
outline: none;
|
|
247
|
+
border-color: var(--key-accent, var(--primary));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.campaign-comment__actions {
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-wrap: wrap;
|
|
254
|
+
gap: 0.75rem;
|
|
255
|
+
margin-top: 0.625rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.campaign-comment__action {
|
|
259
|
+
background: none;
|
|
260
|
+
border: 0;
|
|
261
|
+
padding: 0;
|
|
262
|
+
color: var(--secondary-info-fg);
|
|
263
|
+
font-size: 0.8125rem;
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
|
|
266
|
+
&:hover {
|
|
267
|
+
color: var(--title-fg);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.campaign-comment__reply {
|
|
272
|
+
margin-top: 0.75rem;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.campaign-comment__replies {
|
|
276
|
+
list-style: none;
|
|
277
|
+
margin: 0.875rem 0 0;
|
|
278
|
+
padding: 0 0 0 1rem;
|
|
279
|
+
border-left: 2px solid var(--card-article-border);
|
|
280
|
+
display: grid;
|
|
281
|
+
gap: 0.75rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@media (max-width: 768px) {
|
|
285
|
+
.campaign-comment {
|
|
286
|
+
padding: 0.875rem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Tap targets: the inline actions are too tight to hit reliably at 13px. */
|
|
290
|
+
.campaign-comment__actions {
|
|
291
|
+
gap: 1rem;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.campaign-comment__action {
|
|
295
|
+
padding: 0.25rem 0;
|
|
296
|
+
font-size: 0.875rem;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.campaign-comment__replies {
|
|
300
|
+
padding-left: 0.625rem;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
</style>
|