@mundogamernetwork/shared-ui 1.0.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 (87) hide show
  1. package/README.md +283 -0
  2. package/components/PressKit/AssetGallery.vue +349 -0
  3. package/components/PressKit/Awards.vue +100 -0
  4. package/components/PressKit/Credits.vue +78 -0
  5. package/components/PressKit/FactSheet.vue +204 -0
  6. package/components/PressKit/Hero.vue +143 -0
  7. package/components/PressKit/Quotes.vue +80 -0
  8. package/components/PressKit/VideoPlayer.vue +134 -0
  9. package/components/checkout/MgCartItemList.vue +214 -0
  10. package/components/checkout/MgCartSummary.vue +204 -0
  11. package/components/checkout/MgCheckoutSidebar.vue +230 -0
  12. package/components/checkout/MgGuestEmailForm.vue +97 -0
  13. package/components/checkout/MgPaymentMethodSelector.vue +162 -0
  14. package/components/checkout/MgPixQRCode.vue +222 -0
  15. package/components/indie-wall/IndieWallLeaderboard.vue +208 -0
  16. package/components/indie-wall/MuralCanvas.vue +481 -0
  17. package/components/indie-wall/StepBlock.vue +314 -0
  18. package/components/indie-wall/StepCustomize.vue +530 -0
  19. package/components/indie-wall/StepGoal.vue +169 -0
  20. package/components/indie-wall/StepPackage.vue +145 -0
  21. package/components/indie-wall/StepPay.vue +209 -0
  22. package/components/indie-wall/SupportStepper.vue +372 -0
  23. package/components/invoices/MgInvoiceDownload.vue +50 -0
  24. package/components/pricing/MgBillingToggle.vue +74 -0
  25. package/components/pricing/MgPricingCard.vue +245 -0
  26. package/components/ui/Header/MgMessageCard.vue +147 -0
  27. package/components/ui/Header/MgMessageModal.vue +414 -0
  28. package/components/ui/Header/MgNotificationCard.vue +200 -0
  29. package/components/ui/Header/MgNotificationsModal.vue +125 -0
  30. package/components/ui/MgAnnouncementBanner.vue +147 -0
  31. package/components/ui/MgBanners.vue +23 -0
  32. package/components/ui/MgHeaderComponent.vue +283 -0
  33. package/components/ui/MgHeaderUIConfig.vue +225 -0
  34. package/components/ui/MgHeaderUIUser.vue +301 -0
  35. package/components/ui/MgLoginModal.vue +156 -0
  36. package/components/ui/MgPromotionBanner.vue +185 -0
  37. package/composables/useLogout.ts +42 -0
  38. package/composables/useMgCheckout.ts +287 -0
  39. package/composables/useMgUserNotifications.ts +122 -0
  40. package/composables/usePaymentMethods.ts +75 -0
  41. package/composables/useSubscription.ts +163 -0
  42. package/middleware/auth.global.ts +40 -0
  43. package/nuxt.config.ts +31 -0
  44. package/package.json +40 -0
  45. package/pages/[slug]/index.vue +112 -0
  46. package/pages/about.vue +133 -0
  47. package/pages/blog.vue +430 -0
  48. package/pages/careers.vue +329 -0
  49. package/pages/contact.vue +339 -0
  50. package/pages/faq.vue +317 -0
  51. package/pages/health-check.vue +20 -0
  52. package/pages/icons.vue +58 -0
  53. package/pages/magazine/[slug].vue +209 -0
  54. package/pages/magazine/index.vue +267 -0
  55. package/pages/media-kit/[slug].vue +625 -0
  56. package/pages/mural/[slug].vue +1058 -0
  57. package/pages/partners.vue +290 -0
  58. package/pages/press.vue +237 -0
  59. package/pages/presskit/[slug].vue +191 -0
  60. package/pages/roadmap.vue +355 -0
  61. package/pages/status.vue +199 -0
  62. package/pages/team.vue +266 -0
  63. package/pages/wall/[slug].vue +11 -0
  64. package/plugins/auth.client.ts +17 -0
  65. package/plugins/echo.client.ts +132 -0
  66. package/services/authService.ts +95 -0
  67. package/services/chatService.ts +53 -0
  68. package/services/contactService.ts +35 -0
  69. package/services/documentService.ts +16 -0
  70. package/services/httpService.ts +95 -0
  71. package/services/indieWallService.ts +174 -0
  72. package/services/institutionalService.ts +248 -0
  73. package/services/mediaKitService.ts +51 -0
  74. package/services/notificationsService.ts +20 -0
  75. package/services/pressKitService.ts +55 -0
  76. package/stores/announcement.ts +129 -0
  77. package/stores/auth.ts +86 -0
  78. package/stores/chat.ts +150 -0
  79. package/stores/contact.ts +28 -0
  80. package/stores/document.ts +27 -0
  81. package/stores/index.ts +34 -0
  82. package/stores/institutional.ts +231 -0
  83. package/stores/login.ts +27 -0
  84. package/stores/notifications.ts +133 -0
  85. package/stores/promotion.ts +154 -0
  86. package/types/index.ts +135 -0
  87. package/utils/serialize.ts +29 -0
@@ -0,0 +1,625 @@
1
+ <script setup lang="ts">
2
+ import { fetchPublicMediaKit, trackMediaKitEvent } from '../../services/mediaKitService';
3
+ import { fetchStreamerActiveWalls } from '../../services/indieWallService';
4
+
5
+ const route = useRoute();
6
+ const slug = computed(() => route.params.slug as string);
7
+
8
+ const kit = ref<Record<string, any> | null>(null);
9
+ const loading = ref(true);
10
+ const error = ref(false);
11
+ const walls = ref<any[]>([]);
12
+
13
+ const userId = computed(() => kit.value?.user_id);
14
+ const streamer = computed(() => kit.value?.streamer ?? {});
15
+ const stats = computed(() => kit.value?.stats ?? {});
16
+ const topGames = computed(() => kit.value?.top_games ?? []);
17
+ const period = computed(() => kit.value?.period ?? {});
18
+ const mediaKitWall = computed(() => {
19
+ return walls.value.find((w: any) => w.show_on_media_kit) ?? null;
20
+ });
21
+
22
+ onMounted(async () => {
23
+ try {
24
+ const { data } = await fetchPublicMediaKit(slug.value);
25
+ kit.value = data?.data || data;
26
+
27
+ if (kit.value?.user_id) {
28
+ trackMediaKitEvent(kit.value.user_id, {
29
+ type: 'view',
30
+ referrer: document.referrer || undefined,
31
+ }).catch(() => {});
32
+ }
33
+ } catch {
34
+ error.value = true;
35
+ } finally {
36
+ loading.value = false;
37
+ }
38
+ });
39
+
40
+ watch(userId, async (id) => {
41
+ if (!id) return;
42
+ try {
43
+ const res = await fetchStreamerActiveWalls(id);
44
+ walls.value = res.data?.data ?? res.data ?? [];
45
+ } catch {
46
+ walls.value = [];
47
+ }
48
+ }, { immediate: true });
49
+
50
+ function formatNumber(num: number) {
51
+ if (!num) return '0';
52
+ if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`;
53
+ if (num >= 1000) return `${(num / 1000).toFixed(1)}K`;
54
+ return num.toLocaleString();
55
+ }
56
+
57
+ function handleContact() {
58
+ if (userId.value) {
59
+ trackMediaKitEvent(userId.value, { type: 'contact' });
60
+ }
61
+ }
62
+
63
+ function handleDownload() {
64
+ if (userId.value) {
65
+ trackMediaKitEvent(userId.value, { type: 'download' });
66
+ }
67
+ if (import.meta.client) window.print();
68
+ }
69
+ </script>
70
+
71
+ <template>
72
+ <div id="public-media-kit">
73
+ <div class="mk-inner">
74
+ <div v-if="loading" class="loading-state">
75
+ <i class="fa-solid fa-spinner fa-spin" />
76
+ </div>
77
+
78
+ <div v-else-if="error" class="error-state">
79
+ <i class="fa-solid fa-circle-exclamation" />
80
+ <p>{{ $t("tv.media_kit.not_available") }}</p>
81
+ </div>
82
+
83
+ <template v-else-if="kit">
84
+ <!-- Header -->
85
+ <header class="mk-header">
86
+ <div class="mk-header-content">
87
+ <img
88
+ v-if="streamer.avatar"
89
+ :src="streamer.avatar"
90
+ width="80"
91
+ height="80"
92
+ class="mk-avatar"
93
+ />
94
+ <div class="mk-header-info">
95
+ <h1 class="mk-name">{{ streamer.name }}</h1>
96
+ <div class="mk-meta">
97
+ <span v-if="streamer.platform" class="mk-platform">
98
+ <i :class="streamer.platform === 'twitch' ? 'fa-brands fa-twitch' : 'fa-brands fa-youtube'" />
99
+ {{ streamer.platform }}
100
+ </span>
101
+ <span v-if="streamer.tier && streamer.tier !== 'free'" class="mk-tier">
102
+ {{ streamer.tier.toUpperCase() }}
103
+ </span>
104
+ </div>
105
+ <p v-if="streamer.bio" class="mk-bio">{{ streamer.bio }}</p>
106
+ </div>
107
+ </div>
108
+ <div class="mk-header-actions no-print">
109
+ <button class="btn-mk-download" @click="handleDownload">
110
+ <i class="fa-solid fa-download" />
111
+ {{ $t("tv.media_kit.download_pdf") }}
112
+ </button>
113
+ <button v-if="streamer.social_links?.website" class="btn-mk-contact" @click="handleContact">
114
+ <a :href="streamer.social_links.website" target="_blank" rel="noopener noreferrer">
115
+ <i class="fa-solid fa-envelope" />
116
+ {{ $t("tv.media_kit.contact") }}
117
+ </a>
118
+ </button>
119
+ </div>
120
+ </header>
121
+
122
+ <!-- Key Metrics -->
123
+ <section class="mk-section">
124
+ <h2 class="mk-section-title">{{ $t("tv.media_kit.key_metrics") }}</h2>
125
+ <p class="mk-period">{{ $t("tv.media_kit.last_days", { days: period.days }) }} ({{ period.start }} — {{ period.end }})</p>
126
+ <div class="mk-metrics-grid">
127
+ <div class="mk-metric-card">
128
+ <span class="mk-metric-value">{{ formatNumber(stats.total_followers) }}</span>
129
+ <span class="mk-metric-label">{{ $t("tv.media_kit.followers") }}</span>
130
+ </div>
131
+ <div class="mk-metric-card">
132
+ <span class="mk-metric-value">{{ formatNumber(stats.avg_viewers) }}</span>
133
+ <span class="mk-metric-label">{{ $t("tv.media_kit.avg_viewers") }}</span>
134
+ </div>
135
+ <div class="mk-metric-card">
136
+ <span class="mk-metric-value">{{ formatNumber(stats.peak_viewers) }}</span>
137
+ <span class="mk-metric-label">{{ $t("tv.media_kit.peak_viewers") }}</span>
138
+ </div>
139
+ <div class="mk-metric-card">
140
+ <span class="mk-metric-value">{{ stats.streams_per_week }}</span>
141
+ <span class="mk-metric-label">{{ $t("tv.media_kit.streams_week") }}</span>
142
+ </div>
143
+ <div class="mk-metric-card">
144
+ <span class="mk-metric-value">{{ formatNumber(stats.total_streams_90d) }}</span>
145
+ <span class="mk-metric-label">{{ $t("tv.media_kit.total_streams") }}</span>
146
+ </div>
147
+ <div class="mk-metric-card">
148
+ <span class="mk-metric-value">{{ stats.total_hours_90d }}h</span>
149
+ <span class="mk-metric-label">{{ $t("tv.media_kit.hours_streamed") }}</span>
150
+ </div>
151
+ <div class="mk-metric-card">
152
+ <span class="mk-metric-value">+{{ formatNumber(stats.new_followers_90d) }}</span>
153
+ <span class="mk-metric-label">{{ $t("tv.media_kit.new_followers") }}</span>
154
+ </div>
155
+ <div class="mk-metric-card">
156
+ <span class="mk-metric-value">{{ formatNumber(stats.total_chat_messages) }}</span>
157
+ <span class="mk-metric-label">{{ $t("tv.media_kit.chat_messages") }}</span>
158
+ </div>
159
+ </div>
160
+ </section>
161
+
162
+ <!-- Top Games -->
163
+ <section v-if="topGames.length" class="mk-section">
164
+ <h2 class="mk-section-title">{{ $t("tv.media_kit.top_games") }}</h2>
165
+ <div class="mk-games-list">
166
+ <div v-for="game in topGames" :key="game.game" class="mk-game-item">
167
+ <span class="mk-game-name">{{ game.game }}</span>
168
+ <div class="mk-game-stats">
169
+ <span>{{ game.hours }}h {{ $t("tv.media_kit.played") }}</span>
170
+ <span>{{ game.avg_viewers }} {{ $t("tv.media_kit.avg_viewers_short") }}</span>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </section>
175
+
176
+ <!-- Social Links -->
177
+ <section v-if="streamer.social_links && Object.values(streamer.social_links).some(Boolean)" class="mk-section no-print">
178
+ <h2 class="mk-section-title">{{ $t("tv.media_kit.connect") }}</h2>
179
+ <div class="mk-social-links">
180
+ <a
181
+ v-for="(url, platform) in streamer.social_links"
182
+ v-show="url"
183
+ :key="platform"
184
+ :href="url"
185
+ target="_blank"
186
+ rel="noopener noreferrer"
187
+ class="mk-social-link"
188
+ @click="() => userId && trackMediaKitEvent(userId, { type: 'click' })"
189
+ >
190
+ <i :class="{
191
+ 'fa-brands fa-x-twitter': platform === 'twitter',
192
+ 'fa-brands fa-instagram': platform === 'instagram',
193
+ 'fa-brands fa-discord': platform === 'discord',
194
+ 'fa-brands fa-tiktok': platform === 'tiktok',
195
+ 'fa-solid fa-globe': platform === 'website',
196
+ }" />
197
+ <span>{{ platform }}</span>
198
+ </a>
199
+ </div>
200
+ </section>
201
+
202
+ <!-- IndieWall section (shown only if creator has a media-kit wall) -->
203
+ <section v-if="mediaKitWall" class="mk-section mk-indiewall">
204
+ <h2 class="mk-section-title">{{ $t("tv.media_kit.indiewall_title") }}</h2>
205
+ <div class="mk-indiewall-card">
206
+ <div class="mk-indiewall-info">
207
+ <h3 class="mk-indiewall-name">{{ mediaKitWall.name }}</h3>
208
+ <p v-if="mediaKitWall.description" class="mk-indiewall-desc">{{ mediaKitWall.description }}</p>
209
+ <div class="mk-indiewall-stats">
210
+ <div class="mk-indiewall-stat">
211
+ <span class="mk-indiewall-stat-label">{{ $t("tv.media_kit.indiewall_raised") }}</span>
212
+ <span class="mk-indiewall-stat-value">{{ mediaKitWall.currency }} {{ Number(mediaKitWall.raised_amount || 0).toFixed(2) }}</span>
213
+ </div>
214
+ <div class="mk-indiewall-stat">
215
+ <span class="mk-indiewall-stat-label">{{ $t("tv.media_kit.indiewall_supporters") }}</span>
216
+ <span class="mk-indiewall-stat-value">{{ mediaKitWall.supporters_count ?? 0 }}</span>
217
+ </div>
218
+ <div class="mk-indiewall-stat">
219
+ <span class="mk-indiewall-stat-label">{{ $t("tv.media_kit.indiewall_pixels") }}</span>
220
+ <span class="mk-indiewall-stat-value">{{ mediaKitWall.used_pixels ?? 0 }} / {{ mediaKitWall.total_pixels ?? 0 }}</span>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ <a :href="mediaKitWall.mural_url" target="_blank" rel="noopener" class="mk-indiewall-cta">
225
+ {{ $t("tv.media_kit.indiewall_cta") }}
226
+ </a>
227
+ </div>
228
+ </section>
229
+
230
+ <!-- Footer -->
231
+ <footer class="mk-footer">
232
+ <p>{{ $t("tv.media_kit.powered_by") }} <strong>Mundo Gamer TV</strong></p>
233
+ <p class="mk-generated">{{ $t("tv.media_kit.generated") }} {{ kit.generated_at?.slice(0, 10) }}</p>
234
+ </footer>
235
+ </template>
236
+ </div>
237
+ </div>
238
+ </template>
239
+
240
+ <style lang="scss" scoped>
241
+ #public-media-kit {
242
+ min-height: 100vh;
243
+ background: #0a0a0a;
244
+ color: #fff;
245
+ font-family: "Roboto", sans-serif;
246
+
247
+ .mk-inner {
248
+ max-width: 800px;
249
+ margin: 0 auto;
250
+ padding: 40px 24px;
251
+ }
252
+
253
+ .loading-state,
254
+ .error-state {
255
+ display: flex;
256
+ flex-direction: column;
257
+ align-items: center;
258
+ justify-content: center;
259
+ min-height: 60vh;
260
+ gap: 16px;
261
+ color: #878a99;
262
+ font-size: 16px;
263
+
264
+ i {
265
+ font-size: 32px;
266
+ color: #d297ff;
267
+ }
268
+ }
269
+
270
+ .mk-header {
271
+ display: flex;
272
+ align-items: flex-start;
273
+ justify-content: space-between;
274
+ gap: 24px;
275
+ margin-bottom: 48px;
276
+ padding-bottom: 32px;
277
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
278
+
279
+ .mk-header-content {
280
+ display: flex;
281
+ gap: 20px;
282
+ align-items: flex-start;
283
+ }
284
+
285
+ .mk-avatar {
286
+ border: 2px solid #6b15ac;
287
+ flex-shrink: 0;
288
+ }
289
+
290
+ .mk-header-info {
291
+ display: flex;
292
+ flex-direction: column;
293
+ gap: 6px;
294
+ }
295
+
296
+ .mk-name {
297
+ font: 700 28px/36px "Roboto", sans-serif;
298
+ color: #fff;
299
+ }
300
+
301
+ .mk-meta {
302
+ display: flex;
303
+ align-items: center;
304
+ gap: 12px;
305
+ }
306
+
307
+ .mk-platform {
308
+ color: #878a99;
309
+ font-size: 14px;
310
+ text-transform: capitalize;
311
+
312
+ i {
313
+ margin-right: 4px;
314
+ }
315
+ }
316
+
317
+ .mk-tier {
318
+ background: rgba(107, 21, 172, 0.2);
319
+ color: #a855f7;
320
+ font-size: 10px;
321
+ font-weight: 700;
322
+ padding: 2px 8px;
323
+ letter-spacing: 0.05em;
324
+ }
325
+
326
+ .mk-bio {
327
+ color: #aaa;
328
+ font: 400 14px/20px "Roboto", sans-serif;
329
+ margin-top: 8px;
330
+ max-width: 480px;
331
+ }
332
+
333
+ .mk-header-actions {
334
+ display: flex;
335
+ gap: 8px;
336
+ flex-shrink: 0;
337
+ }
338
+
339
+ .btn-mk-download,
340
+ .btn-mk-contact {
341
+ display: flex;
342
+ align-items: center;
343
+ gap: 6px;
344
+ padding: 8px 16px;
345
+ font: 400 13px/20px "Roboto", sans-serif;
346
+ cursor: pointer;
347
+ transition: all 0.15s ease-in-out;
348
+ }
349
+
350
+ .btn-mk-download {
351
+ background: transparent;
352
+ border: 1px solid #6b15ac;
353
+ color: #d297ff;
354
+
355
+ &:hover {
356
+ background: rgba(107, 21, 172, 0.15);
357
+ }
358
+ }
359
+
360
+ .btn-mk-contact {
361
+ background: #6b15ac;
362
+ border: 1px solid #6b15ac;
363
+ color: #fff;
364
+
365
+ a {
366
+ color: inherit;
367
+ text-decoration: none;
368
+ display: flex;
369
+ align-items: center;
370
+ gap: 6px;
371
+ }
372
+
373
+ &:hover {
374
+ background: #460279;
375
+ }
376
+ }
377
+ }
378
+
379
+ .mk-section {
380
+ margin-bottom: 40px;
381
+
382
+ .mk-section-title {
383
+ font: 600 20px/28px "Roboto", sans-serif;
384
+ color: #fff;
385
+ margin-bottom: 8px;
386
+ }
387
+
388
+ .mk-period {
389
+ color: #878a99;
390
+ font: 400 13px/18px "Roboto", sans-serif;
391
+ margin-bottom: 20px;
392
+ }
393
+ }
394
+
395
+ .mk-metrics-grid {
396
+ display: grid;
397
+ grid-template-columns: repeat(4, 1fr);
398
+ gap: 12px;
399
+
400
+ .mk-metric-card {
401
+ background: rgba(255, 255, 255, 0.04);
402
+ border: 1px solid rgba(255, 255, 255, 0.08);
403
+ padding: 20px 16px;
404
+ text-align: center;
405
+
406
+ .mk-metric-value {
407
+ display: block;
408
+ font: 700 24px/32px "Roboto", sans-serif;
409
+ color: #d297ff;
410
+ margin-bottom: 4px;
411
+ }
412
+
413
+ .mk-metric-label {
414
+ display: block;
415
+ font: 400 12px/16px "Roboto", sans-serif;
416
+ color: #878a99;
417
+ text-transform: uppercase;
418
+ letter-spacing: 0.5px;
419
+ }
420
+ }
421
+ }
422
+
423
+ .mk-games-list {
424
+ display: flex;
425
+ flex-direction: column;
426
+ gap: 8px;
427
+
428
+ .mk-game-item {
429
+ display: flex;
430
+ align-items: center;
431
+ justify-content: space-between;
432
+ padding: 12px 16px;
433
+ background: rgba(255, 255, 255, 0.04);
434
+ border: 1px solid rgba(255, 255, 255, 0.08);
435
+
436
+ .mk-game-name {
437
+ font: 500 14px/20px "Roboto", sans-serif;
438
+ color: #fff;
439
+ }
440
+
441
+ .mk-game-stats {
442
+ display: flex;
443
+ gap: 20px;
444
+ color: #878a99;
445
+ font: 400 13px/18px "Roboto", sans-serif;
446
+ }
447
+ }
448
+ }
449
+
450
+ .mk-social-links {
451
+ display: flex;
452
+ gap: 12px;
453
+ flex-wrap: wrap;
454
+
455
+ .mk-social-link {
456
+ display: flex;
457
+ align-items: center;
458
+ gap: 6px;
459
+ padding: 8px 16px;
460
+ background: rgba(255, 255, 255, 0.04);
461
+ border: 1px solid rgba(255, 255, 255, 0.08);
462
+ color: #d297ff;
463
+ text-decoration: none;
464
+ font: 400 13px/18px "Roboto", sans-serif;
465
+ text-transform: capitalize;
466
+ transition: all 0.15s ease-in-out;
467
+
468
+ &:hover {
469
+ background: rgba(107, 21, 172, 0.15);
470
+ }
471
+ }
472
+ }
473
+
474
+ .mk-indiewall {
475
+ .mk-indiewall-card {
476
+ background: rgba(107, 21, 172, 0.08);
477
+ border: 1px solid rgba(107, 21, 172, 0.3);
478
+ padding: 24px;
479
+ display: flex;
480
+ flex-wrap: wrap;
481
+ align-items: center;
482
+ justify-content: space-between;
483
+ gap: 20px;
484
+ }
485
+
486
+ .mk-indiewall-name {
487
+ font: 700 18px/24px "Roboto", sans-serif;
488
+ color: #fff;
489
+ margin: 0 0 6px;
490
+ }
491
+
492
+ .mk-indiewall-desc {
493
+ font: 400 13px/20px "Roboto", sans-serif;
494
+ color: #aaa;
495
+ margin: 0 0 16px;
496
+ }
497
+
498
+ .mk-indiewall-stats {
499
+ display: flex;
500
+ flex-wrap: wrap;
501
+ gap: 20px;
502
+ }
503
+
504
+ .mk-indiewall-stat {
505
+ display: flex;
506
+ flex-direction: column;
507
+ gap: 2px;
508
+ }
509
+
510
+ .mk-indiewall-stat-label {
511
+ font: 400 10px/14px "Roboto", sans-serif;
512
+ color: #888;
513
+ text-transform: uppercase;
514
+ letter-spacing: 0.04em;
515
+ }
516
+
517
+ .mk-indiewall-stat-value {
518
+ font: 700 15px/20px "Roboto", sans-serif;
519
+ color: #d297ff;
520
+ }
521
+
522
+ .mk-indiewall-cta {
523
+ display: inline-block;
524
+ background: #6b15ac;
525
+ color: #fff;
526
+ padding: 10px 20px;
527
+ font: 600 13px/18px "Roboto", sans-serif;
528
+ text-decoration: none;
529
+ white-space: nowrap;
530
+
531
+ &:hover {
532
+ background: #7d1bc8;
533
+ }
534
+ }
535
+ }
536
+
537
+ .mk-footer {
538
+ margin-top: 60px;
539
+ padding-top: 24px;
540
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
541
+ text-align: center;
542
+ color: #878a99;
543
+ font: 400 13px/18px "Roboto", sans-serif;
544
+
545
+ strong {
546
+ color: #d297ff;
547
+ }
548
+
549
+ .mk-generated {
550
+ margin-top: 4px;
551
+ font-size: 11px;
552
+ }
553
+ }
554
+
555
+ @media screen and (max-width: 767px) {
556
+ .mk-inner {
557
+ padding: 24px 16px;
558
+ }
559
+
560
+ .mk-header {
561
+ flex-direction: column;
562
+
563
+ .mk-header-content {
564
+ flex-direction: column;
565
+ align-items: center;
566
+ text-align: center;
567
+ }
568
+
569
+ .mk-header-info {
570
+ align-items: center;
571
+ }
572
+
573
+ .mk-meta {
574
+ justify-content: center;
575
+ }
576
+
577
+ .mk-header-actions {
578
+ width: 100%;
579
+ justify-content: center;
580
+ }
581
+ }
582
+
583
+ .mk-metrics-grid {
584
+ grid-template-columns: repeat(2, 1fr);
585
+ }
586
+
587
+ .mk-games-list .mk-game-item {
588
+ flex-direction: column;
589
+ align-items: flex-start;
590
+ gap: 4px;
591
+ }
592
+ }
593
+
594
+ @media print {
595
+ background: #fff;
596
+ color: #000;
597
+
598
+ .no-print {
599
+ display: none !important;
600
+ }
601
+
602
+ .mk-name {
603
+ color: #000;
604
+ }
605
+
606
+ .mk-metric-value {
607
+ color: #6b15ac !important;
608
+ }
609
+
610
+ .mk-metric-card,
611
+ .mk-game-item {
612
+ border-color: #ddd !important;
613
+ background: #f9f9f9 !important;
614
+ }
615
+
616
+ .mk-section-title {
617
+ color: #000;
618
+ }
619
+
620
+ .mk-footer strong {
621
+ color: #6b15ac;
622
+ }
623
+ }
624
+ }
625
+ </style>