@mundogamernetwork/shared-ui 1.1.35 → 1.1.37

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.
@@ -1,1450 +1,275 @@
1
1
  <script setup lang="ts">
2
- import { fetchPublicPressKit, trackPressKitEvent } from '~/services/pressKitService'
3
-
4
- definePageMeta({ ssr: false, layout: 'blank' })
5
-
6
- const route = useRoute()
7
- const { t } = useI18n()
8
- const localePath = useLocalePath()
9
-
10
- const slug = route.params.slug as string
11
-
12
- const kit = ref<any>(null)
13
- const loading = ref(true)
14
- const error = ref(false)
15
-
16
- const showTrailer = ref(false)
17
- const assetFilter = ref('all')
18
-
19
- const trailerEmbedUrl = computed(() => {
20
- const url = kit.value?.trailer_url
21
- if (!url) return null
22
- const yt = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/)
23
- if (yt) return `https://www.youtube.com/embed/${yt[1]}?autoplay=1`
24
- return url
25
- })
26
-
27
- const assets = computed(() => {
28
- const all = kit.value?.assets?.data ?? []
29
- if (assetFilter.value === 'all') return all
30
- return all.filter((a: any) => a.type === assetFilter.value)
31
- })
32
-
33
- const assetTypes = computed(() => {
34
- const all = kit.value?.assets?.data ?? []
35
- const types = [...new Set(all.map((a: any) => a.type).filter(Boolean))]
36
- return types
37
- })
38
-
39
- const socialLinks = computed(() => {
40
- const links = kit.value?.social_links ?? {}
41
- return Object.entries(links).filter(([, v]) => !!v).map(([k, v]) => ({ label: k, url: v as string }))
42
- })
43
-
44
- const articles = computed(() => kit.value?.articles ?? [])
45
- const coverage = computed(() => kit.value?.coverage ?? [])
46
- const showcases = computed(() => kit.value?.showcases ?? [])
47
- const hasEcosystem = computed(() =>
48
- showcases.value.length ||
49
- kit.value?.ventures_url ||
50
- kit.value?.magazine_feature ||
51
- kit.value?.community_url
52
- )
53
-
54
- // Sanitize community URL: legacy data may store /games/[slug] (old route).
55
- // The canonical community game route is /game/[slug].
56
- const communityUrl = computed(() =>
57
- kit.value?.community_url
58
- ? kit.value.community_url.replace(/\/games\//, '/game/')
59
- : null
60
- )
61
-
62
- onMounted(async () => {
63
- try {
64
- const { data } = await fetchPublicPressKit(slug)
65
- kit.value = data?.data ?? data
2
+ import { trackPressKitEvent } from '../../services/pressKitService';
3
+
4
+ definePageMeta({ layout: 'blank' });
5
+
6
+ const route = useRoute();
7
+ const slug = route.params.slug as string;
8
+
9
+ const runtimeConfig = useRuntimeConfig();
10
+ const cfg = (runtimeConfig.public?.mgSharedUi || {}) as Record<string, any>;
11
+ // Consuming apps may set apiBaseURL at public root (agency/community/tv pattern)
12
+ // or inside mgSharedUi. pressKitApiUrl overrides both (e.g. community points to agency API).
13
+ const apiBase: string =
14
+ cfg.pressKitApiUrl ||
15
+ (runtimeConfig.public as any)?.pressKitApiUrl ||
16
+ cfg.apiBaseURL ||
17
+ (runtimeConfig.public as any)?.apiBaseURL ||
18
+ '';
19
+
20
+ const agencyBase: string =
21
+ cfg.agencyBaseUrl ||
22
+ (runtimeConfig.public as any)?.agencyBaseUrl ||
23
+ '';
24
+
25
+ const SUPPORTED_LOCALES = ['en', 'pt-BR', 'es', 'de', 'ro', 'ar-AE'];
26
+ const routePath = route.path.split('/');
27
+ const lang = SUPPORTED_LOCALES.find(l => routePath.includes(l)) || 'en';
28
+
29
+ const { data: kitData, error: fetchError, pending } = await useAsyncData(
30
+ `press-kit-${slug}`,
31
+ () => $fetch<any>(`${apiBase}/public/press-kits/${slug}`, {
32
+ params: { include: 'assets,videos,credits,awards,quotes', lang },
33
+ }),
34
+ { lazy: false },
35
+ );
36
+
37
+ const kit = computed(() => kitData.value?.data || kitData.value || null);
38
+ const loading = pending;
39
+ const error = computed(() => !!fetchError.value || (!pending.value && !kit.value));
40
+
41
+ onMounted(() => {
42
+ if (kit.value) {
66
43
  trackPressKitEvent(slug, {
67
44
  event_type: 'view',
68
45
  referrer: document.referrer || undefined,
69
- }).catch(() => {})
70
- } catch {
71
- error.value = true
72
- } finally {
73
- loading.value = false
74
- }
75
- })
76
-
77
- const canonicalUrl = computed(() =>
78
- typeof window !== 'undefined' ? window.location.href : ''
79
- )
80
- const ogDescription = computed(() =>
81
- kit.value?.tagline ?? kit.value?.description?.substring(0, 160) ?? ''
82
- )
83
- const ogImage = computed(() =>
84
- kit.value?.cover_image_url ?? kit.value?.hero_image_url ?? ''
85
- )
86
-
46
+ }).catch(() => {});
47
+ }
48
+ });
49
+
50
+ // Fractal include shape: relation -> { data: [...] }
51
+ const list = (rel: any) => rel?.data || rel || [];
52
+ const assets = computed(() => list(kit.value?.assets));
53
+ const videos = computed(() => list(kit.value?.videos));
54
+ const awards = computed(() => list(kit.value?.awards));
55
+ const quotes = computed(() => list(kit.value?.quotes));
56
+ const team = computed(() => list(kit.value?.credits));
57
+ const features = computed(() => kit.value?.key_features || []);
58
+ // New, optional blocks (rendered only when the API provides them)
59
+ const articles = computed(() => list(kit.value?.articles));
60
+ const coverage = computed(() => list(kit.value?.coverage));
61
+ const showcases = computed(() => list(kit.value?.showcases));
62
+ const hasEcosystem = computed(() => showcases.value.length || kit.value?.ventures_url || kit.value?.magazine_feature || kit.value?.community_url);
63
+
64
+ const screenshots = computed(() => assets.value.filter((a: any) => ['screenshot', 'artwork', 'gif'].includes(a.type)));
65
+ const brandAssets = computed(() => assets.value.filter((a: any) => ['logo', 'document'].includes(a.type)));
66
+
67
+ const tpl = computed(() => kit.value?.theme || null);
68
+ const layout = computed(() => kit.value?.layout || 'classic');
69
+ const allowDownload = computed(() => kit.value?.allow_asset_download !== false);
70
+
71
+ const socials = computed(() => {
72
+ const s = kit.value?.social_links || {};
73
+ return Object.entries(s).filter(([, v]) => v).map(([k, v]) => ({ platform: k, url: v as string }));
74
+ });
75
+
76
+ const facts = computed(() => {
77
+ const k = kit.value || {};
78
+ const out: { label: string; value: string; accent?: boolean; href?: string }[] = [];
79
+ if (k.developer) out.push({ label: 'kit.press.developer', value: k.developer });
80
+ if (k.publisher) out.push({ label: 'kit.press.publisher', value: k.publisher });
81
+ if (k.release_date_tba) out.push({ label: 'kit.press.release', value: 'TBA', accent: true });
82
+ else if (k.release_date) out.push({ label: 'kit.press.release', value: k.release_date, accent: true });
83
+ if (k.release_status) out.push({ label: 'kit.press.status', value: String(k.release_status).replace(/_/g, ' ') });
84
+ if (k.price) out.push({ label: 'kit.press.price', value: `${k.price}${k.currency ? ' ' + k.currency : ''}` });
85
+ if (k.website_url) out.push({ label: 'kit.press.website', value: k.website_url, accent: true, href: k.website_url });
86
+ if (k.steam_url) out.push({ label: 'Steam', value: k.steam_url, href: k.steam_url });
87
+ if (k.press_contact_email) out.push({ label: 'kit.press.contact', value: k.press_contact_email, href: `mailto:${k.press_contact_email}` });
88
+ return out;
89
+ });
90
+
91
+ function track(type: 'click' | 'download' | 'contact') {
92
+ trackPressKitEvent(slug, { event_type: type, referrer: document.referrer || undefined }).catch(() => {});
93
+ }
94
+
95
+ const requestUrl = useRequestURL();
87
96
  useHead(() => ({
88
- title: kit.value?.name
89
- ? `${kit.value.name} — Press Kit`
90
- : t('press_kit.loading'),
97
+ title: kit.value ? `${kit.value.name} — Press Kit` : 'Press Kit',
91
98
  meta: [
92
- // Standard
93
- { name: 'description', content: ogDescription.value },
94
- { name: 'robots', content: 'index, follow' },
95
- // Open Graph
96
- { property: 'og:type', content: 'website' },
97
- { property: 'og:site_name', content: 'Mundo Gamer Agency' },
98
- { property: 'og:title', content: kit.value?.name ?? '' },
99
- { property: 'og:description', content: ogDescription.value },
100
- { property: 'og:image', content: ogImage.value },
101
- { property: 'og:image:width', content: '1200' },
102
- { property: 'og:image:height', content: '630' },
103
- { property: 'og:url', content: canonicalUrl.value },
104
- // Twitter / X Card
105
- { name: 'twitter:card', content: 'summary_large_image' },
106
- { name: 'twitter:title', content: kit.value?.name ?? '' },
107
- { name: 'twitter:description', content: ogDescription.value },
108
- { name: 'twitter:image', content: ogImage.value },
99
+ { name: 'description', content: kit.value?.tagline || '' },
100
+ { property: 'og:title', content: kit.value?.name || 'Press Kit' },
101
+ { property: 'og:description', content: kit.value?.tagline || '' },
102
+ { property: 'og:image', content: kit.value?.hero_image_url || kit.value?.logo_url || '' },
103
+ { property: 'og:type', content: 'article' },
104
+ { property: 'og:url', content: requestUrl.href },
109
105
  ],
110
- link: [
111
- { rel: 'canonical', href: canonicalUrl.value },
112
- ],
113
- script: kit.value ? [
114
- {
115
- type: 'application/ld+json',
116
- innerHTML: JSON.stringify({
117
- '@context': 'https://schema.org',
118
- '@type': 'VideoGame',
119
- name: kit.value.name,
120
- description: ogDescription.value,
121
- image: ogImage.value,
122
- ...(kit.value.developer ? { author: { '@type': 'Organization', name: kit.value.developer } } : {}),
123
- ...(kit.value.publisher ? { publisher: { '@type': 'Organization', name: kit.value.publisher } } : {}),
124
- ...(kit.value.release_date ? { datePublished: kit.value.release_date } : {}),
125
- ...(kit.value.steam_url ? { sameAs: [kit.value.steam_url] } : {}),
126
- ...(kit.value.website_url ? { url: kit.value.website_url } : {}),
127
- }),
128
- },
129
- ] : [],
130
- }))
106
+ }));
131
107
  </script>
132
108
 
133
109
  <template>
134
- <div class="pk-page" :data-theme="kit?.theme || 'default'">
135
-
136
- <!-- Loading -->
137
- <div v-if="loading" class="pk-loading">
138
- <div class="pk-spinner" />
139
- </div>
140
-
141
- <!-- Not found -->
142
- <div v-else-if="error || !kit" class="pk-error">
143
- <h1>{{ $t('press_kit.not_found') }}</h1>
144
- <p>{{ $t('press_kit.not_found_message') }}</p>
145
- <NuxtLink :to="localePath('/')" class="pk-btn">{{ $t('press_kit.back_home') }}</NuxtLink>
110
+ <div class="kit-press" :data-tpl="tpl" :data-layout="layout">
111
+ <div v-if="loading" class="kit-state">{{ $t('kit.loading') }}</div>
112
+ <div v-else-if="error || !kit" class="kit-state">
113
+ <h2>{{ $t('kit.press.not_found') }}</h2>
146
114
  </div>
147
115
 
148
116
  <template v-else>
149
-
150
- <!-- ═══ Hero ═══════════════════════════════════════════════════ -->
151
- <div
152
- class="pk-hero"
153
- :style="kit.hero_image_url ? { backgroundImage: `url(${kit.hero_image_url})` } : {}"
154
- >
155
- <div class="pk-hero__overlay">
156
- <div class="pk-hero__inner">
157
- <div v-if="kit.logo_url" class="pk-hero__logo">
158
- <img
159
- :src="kit.logo_url"
160
- :alt="kit.name"
161
- @error="(e: any) => e.target.style.display = 'none'"
162
- />
163
- </div>
164
- <h1 class="pk-hero__title">{{ kit.name }}</h1>
165
- <p v-if="kit.tagline" class="pk-hero__tagline">{{ kit.tagline }}</p>
166
- <div class="pk-hero__actions">
167
- <button
168
- v-if="kit.trailer_url"
169
- class="pk-btn pk-btn--outline"
170
- @click="showTrailer = true"
171
- >
172
- {{ $t('press_kit.watch_trailer') }}
173
- </button>
174
- <a
175
- v-if="kit.steam_url"
176
- :href="kit.steam_url"
177
- target="_blank"
178
- rel="noopener"
179
- class="pk-btn pk-btn--ghost"
180
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'steam_wishlist' } })"
181
- >
182
- {{ $t('press_kit.wishlist_steam') }}
183
- </a>
184
- <a
185
- v-if="kit.epic_url"
186
- :href="kit.epic_url"
187
- target="_blank"
188
- rel="noopener"
189
- class="pk-btn pk-btn--ghost"
190
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'epic_wishlist' } })"
191
- >
192
- {{ $t('press_kit.wishlist_epic') }}
193
- </a>
117
+ <!-- CAPA / COVER -->
118
+ <header class="kit-cover">
119
+ <img v-if="kit.hero_image_url" class="kit-cover-art" :src="kit.hero_image_url" :alt="kit.name" />
120
+ <div class="kit-cover-inner">
121
+ <img v-if="kit.cover_image_url" class="kit-cover-poster" :src="kit.cover_image_url" :alt="kit.name" />
122
+ <div class="kit-cover-text">
123
+ <span v-if="kit.release_status" class="kit-eyebrow">{{ String(kit.release_status).replace(/_/g, ' ') }}</span>
124
+ <img v-if="kit.logo_url" class="kit-cover-logo-img" :src="kit.logo_url" :alt="kit.name" />
125
+ <h1 v-else>{{ kit.name }}</h1>
126
+ <p v-if="kit.tagline" class="kit-tagline">{{ kit.tagline }}</p>
127
+ <p v-if="kit.developer" class="kit-kicker">{{ kit.developer }}</p>
128
+ <div class="kit-actions">
129
+ <a v-if="allowDownload" class="kit-btn kit-btn-primary" @click="track('download')">{{ $t('kit.press.download_assets') }}</a>
130
+ <a v-if="kit.press_contact_email" class="kit-btn kit-btn-ghost" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.request_key') }}</a>
194
131
  </div>
195
132
  </div>
196
133
  </div>
197
- </div>
198
-
199
- <!-- ═══ Layout ══════════════════════════════════════════════════ -->
200
- <div class="pk-container">
201
- <div class="pk-layout">
202
-
203
- <!-- Sidebar -->
204
- <aside class="pk-sidebar">
205
- <div class="pk-card">
206
- <h2 class="pk-card__title">{{ $t('press_kit.fact_sheet') }}</h2>
207
- <dl class="pk-dl">
208
- <template v-if="kit.developer">
209
- <dt>{{ $t('press_kit.developer') }}</dt>
210
- <dd>{{ kit.developer }}</dd>
211
- </template>
212
- <template v-if="kit.publisher">
213
- <dt>{{ $t('press_kit.publisher_label') }}</dt>
214
- <dd>{{ kit.publisher }}</dd>
215
- </template>
216
- <template v-if="kit.release_date || kit.release_date_tba">
217
- <dt>{{ $t('press_kit.release_date') }}</dt>
218
- <dd>{{ kit.release_date_tba ? $t('press_kit.date_tba') : kit.release_date }}</dd>
219
- </template>
220
- <template v-if="kit.release_status">
221
- <dt>{{ $t('press_kit.release_status') }}</dt>
222
- <dd>{{ kit.release_status }}</dd>
223
- </template>
224
- <template v-if="kit.price">
225
- <dt>{{ $t('press_kit.price') }}</dt>
226
- <dd>{{ kit.price }} {{ kit.currency }}</dd>
227
- </template>
228
- <template v-if="kit.monetization">
229
- <dt>{{ $t('press_kit.monetization') }}</dt>
230
- <dd>{{ kit.monetization }}</dd>
231
- </template>
232
- <template v-if="kit.press_contact_email">
233
- <dt>{{ $t('press_kit.press_contact') }}</dt>
234
- <dd>
235
- <a
236
- :href="`mailto:${kit.press_contact_email}`"
237
- @click="trackPressKitEvent(slug, { event_type: 'contact' })"
238
- >{{ kit.press_contact_email }}</a>
239
- </dd>
240
- </template>
241
- </dl>
242
- </div>
243
-
244
- <!-- Links -->
245
- <div class="pk-card" v-if="kit.website_url || kit.steam_url || kit.epic_url || kit.ventures_url || communityUrl">
246
- <h2 class="pk-card__title">{{ $t('press_kit.available_on') }}</h2>
247
- <div class="pk-links">
248
- <a v-if="kit.website_url" :href="kit.website_url" target="_blank" rel="noopener" class="pk-link" @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'website' } })">
249
- {{ $t('press_kit.website') }}
250
- </a>
251
- <a v-if="kit.steam_url" :href="kit.steam_url" target="_blank" rel="noopener" class="pk-link" @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'steam' } })">
252
- Steam
253
- </a>
254
- <a v-if="kit.epic_url" :href="kit.epic_url" target="_blank" rel="noopener" class="pk-link" @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'epic' } })">
255
- Epic Games
256
- </a>
257
- <a v-if="kit.ventures_url" :href="kit.ventures_url" target="_blank" rel="noopener" class="pk-link">
258
- Ventures
259
- </a>
260
- <a v-if="communityUrl" :href="communityUrl" target="_blank" rel="noopener" class="pk-link" @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'community' } })">
261
- {{ $t('press_kit.follow_community') }}
262
- </a>
134
+ </header>
135
+
136
+ <div class="kit-wrap">
137
+ <div class="kit-layout">
138
+ <aside class="kit-sidebar">
139
+ <div class="kit-card kit-factsheet">
140
+ <h3 class="kit-fact-title">{{ $t('kit.press.fact_sheet') }}</h3>
141
+ <div v-for="f in facts" :key="f.label" class="kit-fact">
142
+ <span class="k">{{ $te(f.label) ? $t(f.label) : f.label }}</span>
143
+ <a v-if="f.href" class="v accent" :href="f.href" target="_blank" rel="noopener" @click="track('click')">{{ f.value }}</a>
144
+ <span v-else class="v" :class="{ accent: f.accent }">{{ f.value }}</span>
263
145
  </div>
264
- </div>
265
-
266
- <!-- Social media -->
267
- <div class="pk-card" v-if="socialLinks.length">
268
- <h2 class="pk-card__title">{{ $t('press_kit.social_media') }}</h2>
269
- <div class="pk-links">
270
- <a
271
- v-for="link in socialLinks"
272
- :key="link.label"
273
- :href="link.url"
274
- target="_blank"
275
- rel="noopener"
276
- class="pk-link"
277
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: link.label } })"
278
- >
279
- {{ link.label }}
280
- </a>
146
+ <div v-if="socials.length" class="kit-fact">
147
+ <span class="k">{{ $t('kit.press.social') }}</span>
148
+ <div class="kit-socials">
149
+ <a v-for="s in socials" :key="s.platform" :href="s.url" target="_blank" rel="noopener" @click="track('click')">{{ s.platform.charAt(0).toUpperCase() }}</a>
150
+ </div>
281
151
  </div>
282
152
  </div>
283
-
284
- <!-- Press key request -->
285
- <div class="pk-card pk-card--accent" v-if="kit.press_contact_email">
286
- <p class="pk-card__desc">{{ $t('press_kit.key_request_desc') }}</p>
287
- <a
288
- :href="`mailto:${kit.press_contact_email}`"
289
- class="pk-btn pk-btn--full"
290
- @click="trackPressKitEvent(slug, { event_type: 'contact' })"
291
- >
292
- {{ $t('press_kit.request_key') }}
293
- </a>
294
- </div>
295
153
  </aside>
296
154
 
297
- <!-- Main content -->
298
- <main class="pk-main">
155
+ <main class="kit-main">
156
+ <section v-if="kit.description" class="kit-block">
157
+ <h2>{{ $t('kit.press.about') }}</h2>
158
+ <div class="kit-lead" v-html="kit.description" />
159
+ </section>
299
160
 
300
- <!-- Description -->
301
- <section v-if="kit.description" class="pk-section">
302
- <h2 class="pk-section__title">{{ $t('press_kit.description') }}</h2>
303
- <div class="pk-prose" v-html="kit.description" />
161
+ <section v-if="features.length" class="kit-block">
162
+ <h2>{{ $t('kit.press.features') }}</h2>
163
+ <div class="kit-features">
164
+ <div v-for="(f, i) in features" :key="i" class="kit-feature"><span class="m">▸</span>{{ f }}</div>
165
+ </div>
304
166
  </section>
305
167
 
306
- <!-- Key features -->
307
- <section v-if="kit.key_features?.length" class="pk-section">
308
- <h2 class="pk-section__title">{{ $t('press_kit.key_features') }}</h2>
309
- <ul class="pk-features">
310
- <li v-for="(feat, i) in kit.key_features" :key="i">{{ feat }}</li>
311
- </ul>
168
+ <section v-if="videos.length" class="kit-block">
169
+ <h2>{{ $t('kit.press.videos') }}</h2>
170
+ <PressKitVideoPlayer :videos="videos" />
312
171
  </section>
313
172
 
314
- <!-- Videos -->
315
- <section v-if="kit.videos?.data?.length" class="pk-section">
316
- <h2 class="pk-section__title">{{ $t('press_kit.videos') }}</h2>
317
- <div class="pk-videos">
318
- <div
319
- v-for="video in kit.videos.data"
320
- :key="video.id"
321
- class="pk-video-card"
322
- @click="() => { kit.trailer_url = video.url; showTrailer = true; }"
323
- >
324
- <div class="pk-video-card__thumb">▶</div>
325
- <span class="pk-video-card__title">{{ video.title }}</span>
326
- <span class="pk-video-card__type">{{ video.type }}</span>
327
- </div>
173
+ <section v-if="screenshots.length" class="kit-block">
174
+ <div class="kit-shead"><h2>{{ $t('kit.press.screenshots') }}</h2><a v-if="allowDownload" class="kit-dl" @click="track('download')">{{ $t('kit.press.download_all') }}</a></div>
175
+ <div class="kit-gallery">
176
+ <a v-for="(s, i) in screenshots" :key="i" class="kit-shot" :href="s.url" target="_blank" rel="noopener"><img :src="s.thumbnail_url || s.url" :alt="s.title || ''" /></a>
328
177
  </div>
329
178
  </section>
330
179
 
331
- <!-- Assets -->
332
- <section v-if="kit.assets?.data?.length" class="pk-section">
333
- <div class="pk-section__head">
334
- <h2 class="pk-section__title" style="margin-bottom:0;border-bottom:none;">{{ $t('press_kit.assets') }}</h2>
335
- <div v-if="assetTypes.length > 1" class="pk-asset-filters">
336
- <button :class="['pk-filter', { active: assetFilter === 'all' }]" @click="assetFilter = 'all'">
337
- {{ $t('press_kit.all') }}
338
- </button>
339
- <button
340
- v-for="type in assetTypes"
341
- :key="type"
342
- :class="['pk-filter', { active: assetFilter === type }]"
343
- @click="assetFilter = type"
344
- >{{ type }}</button>
345
- </div>
346
- </div>
347
- <div v-if="!assets.length" class="pk-empty">{{ $t('press_kit.no_assets') }}</div>
348
- <div v-else class="pk-assets">
349
- <a
350
- v-for="asset in assets"
351
- :key="asset.id"
352
- :href="asset.url"
353
- target="_blank"
354
- rel="noopener"
355
- class="pk-asset"
356
- @click="trackPressKitEvent(slug, { event_type: 'download', metadata: { asset_id: asset.id } })"
357
- >
358
- <div class="pk-asset__thumb">
359
- <img
360
- v-if="asset.thumbnail_url"
361
- :src="asset.thumbnail_url"
362
- :alt="asset.title"
363
- loading="lazy"
364
- @error="(e: any) => e.target.style.display = 'none'"
365
- />
366
- <span v-else class="pk-asset__dl-icon">↓</span>
367
- </div>
368
- <div class="pk-asset__body">
369
- <span class="pk-asset__title">{{ asset.title }}</span>
370
- <span v-if="asset.file_size" class="pk-asset__size">{{ asset.file_size }}</span>
371
- </div>
180
+ <section v-if="brandAssets.length" class="kit-block">
181
+ <div class="kit-shead"><h2>{{ $t('kit.press.logo_icons') }}</h2></div>
182
+ <div class="kit-logos">
183
+ <a v-for="(b, i) in brandAssets" :key="i" class="kit-logo-tile" :href="b.url" target="_blank" rel="noopener" @click="track('download')">
184
+ <span class="ic">◆</span>{{ b.title || b.type }}
372
185
  </a>
373
186
  </div>
374
187
  </section>
375
188
 
376
- <!-- Quotes -->
377
- <section v-if="kit.quotes?.data?.length" class="pk-section">
378
- <h2 class="pk-section__title">{{ $t('press_kit.quotes') }}</h2>
379
- <div class="pk-quotes">
380
- <blockquote v-for="q in kit.quotes.data" :key="q.id" class="pk-quote">
381
- <p>"{{ q.quote }}"</p>
382
- <footer>
383
- <a v-if="q.source_url" :href="q.source_url" target="_blank" rel="noopener">{{ q.source }}</a>
384
- <span v-else>{{ q.source }}</span>
385
- </footer>
386
- </blockquote>
189
+ <!-- NEW: Conteúdos & Artigos (community + external) -->
190
+ <section v-if="articles.length" class="kit-block">
191
+ <div class="kit-shead"><h2>{{ $t('kit.press.articles') }}</h2></div>
192
+ <div class="kit-articles">
193
+ <a v-for="(a, i) in articles" :key="i" class="kit-article" :href="a.url" target="_blank" rel="noopener" @click="track('click')">
194
+ <div class="thumb" :style="a.image ? { backgroundImage: `url(${a.image})` } : {}"><span class="src" :class="{ ext: a.external }">{{ a.external ? $t('kit.press.external') : 'Mundo Gamer' }}</span></div>
195
+ <div class="a-body"><h4>{{ a.title }}</h4><div class="meta">{{ a.source }}<span v-if="a.date"> · {{ a.date }}</span></div></div>
196
+ </a>
387
197
  </div>
388
198
  </section>
389
199
 
390
- <!-- Articles -->
391
- <section v-if="articles.length" class="pk-section">
392
- <h2 class="pk-section__title">{{ $t('press_kit.articles') }}</h2>
393
- <div class="pk-articles">
394
- <a
395
- v-for="(a, i) in articles"
396
- :key="i"
397
- :href="a.url"
398
- target="_blank"
399
- rel="noopener"
400
- class="pk-article"
401
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'article' } })"
402
- >
403
- <div
404
- class="pk-article__thumb"
405
- :style="a.image ? { backgroundImage: `url(${a.image})` } : {}"
406
- >
407
- <span class="pk-article__src" :class="{ external: a.external }">{{ a.source }}</span>
408
- </div>
409
- <div class="pk-article__body">
410
- <p class="pk-article__title">{{ a.title }}</p>
411
- <span class="pk-article__date">{{ a.date }}</span>
412
- </div>
200
+ <!-- NEW: Cobertura de Criadores -->
201
+ <section v-if="coverage.length" class="kit-block">
202
+ <h2>{{ $t('kit.press.coverage') }}</h2>
203
+ <div class="kit-creators">
204
+ <a v-for="(c, i) in coverage" :key="i" class="kit-creator" :href="c.url || undefined" target="_blank" rel="noopener">
205
+ <div class="av" :style="c.avatar ? { backgroundImage: `url(${c.avatar})` } : {}" />
206
+ <div class="cn">{{ c.name }}</div>
207
+ <div class="cp">{{ c.platform }}<span v-if="c.followers"> · {{ c.followers }}</span></div>
208
+ <div v-if="c.label" class="cv">{{ c.label }}</div>
413
209
  </a>
414
210
  </div>
415
211
  </section>
416
212
 
417
- <!-- Coverage -->
418
- <section v-if="coverage.length" class="pk-section">
419
- <h2 class="pk-section__title">{{ $t('press_kit.coverage') }}</h2>
420
- <div class="pk-coverage">
421
- <a
422
- v-for="(c, i) in coverage"
423
- :key="i"
424
- :href="c.url || undefined"
425
- target="_blank"
426
- rel="noopener"
427
- class="pk-creator"
428
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'coverage' } })"
429
- >
430
- <div
431
- class="pk-creator__avatar"
432
- :style="c.avatar ? { backgroundImage: `url(${c.avatar})` } : {}"
433
- />
434
- <div class="pk-creator__info">
435
- <strong>{{ c.name }}</strong>
436
- <span>{{ c.platform }}</span>
437
- <span v-if="c.followers" class="pk-creator__followers">
438
- {{ Intl.NumberFormat('pt-BR', { notation: 'compact' }).format(c.followers) }} {{ $t('press_kit.followers') }}
439
- </span>
440
- </div>
441
- <span v-if="c.label" class="pk-creator__label">{{ c.label }}</span>
442
- </a>
443
- </div>
213
+ <section v-if="awards.length" class="kit-block">
214
+ <h2>{{ $t('kit.press.awards') }}</h2>
215
+ <PressKitAwards :awards="awards" />
444
216
  </section>
445
217
 
446
- <!-- Awards -->
447
- <section v-if="kit.awards?.data?.length" class="pk-section">
448
- <h2 class="pk-section__title">{{ $t('press_kit.awards') }}</h2>
449
- <div class="pk-awards">
450
- <div v-for="aw in kit.awards.data" :key="aw.id" class="pk-award">
451
- <span class="pk-award__star">★</span>
452
- <div class="pk-award__body">
453
- <strong>{{ aw.title }}</strong>
454
- <span v-if="aw.event || aw.year">{{ aw.event }}{{ aw.event && aw.year ? ' · ' : '' }}{{ aw.year }}</span>
455
- </div>
456
- <a v-if="aw.url" :href="aw.url" target="_blank" rel="noopener" class="pk-award__link">↗</a>
457
- </div>
458
- </div>
218
+ <section v-if="quotes.length" class="kit-block">
219
+ <h2>{{ $t('kit.press.press') }}</h2>
220
+ <PressKitQuotes :quotes="quotes" />
459
221
  </section>
460
222
 
461
- <!-- Team / Credits -->
462
- <section v-if="kit.credits?.data?.length" class="pk-section">
463
- <h2 class="pk-section__title">{{ $t('press_kit.team') }}</h2>
464
- <div class="pk-credits">
465
- <div v-for="cr in kit.credits.data" :key="cr.id" class="pk-credit">
466
- <strong>{{ cr.name }}</strong>
467
- <span>{{ cr.role }}</span>
468
- <a v-if="cr.url" :href="cr.url" target="_blank" rel="noopener">↗</a>
469
- </div>
223
+ <!-- Créditos -> Equipe -->
224
+ <section v-if="team.length" class="kit-block">
225
+ <h2>{{ $t('kit.press.team') }}</h2>
226
+ <div class="kit-team">
227
+ <div v-for="(m, i) in team" :key="i" class="kit-member"><span>{{ m.name }}</span><span class="role">{{ m.role }}</span></div>
470
228
  </div>
471
229
  </section>
472
230
 
473
- <!-- Ecosystem -->
474
- <section v-if="hasEcosystem" class="pk-section">
475
- <h2 class="pk-section__title">{{ $t('press_kit.ecosystem') }}</h2>
476
- <div class="pk-ecosystem">
477
-
478
- <!-- Showcases -->
479
- <div v-if="showcases.length" class="pk-eco-card pk-eco-card--full">
480
- <h3 class="pk-eco-card__title">{{ $t('press_kit.showcases') }}</h3>
481
- <div class="pk-showcases">
482
- <span
483
- v-for="(s, i) in showcases"
484
- :key="i"
485
- class="pk-showcase"
486
- :class="{ featured: s.featured }"
487
- >
488
- {{ s.featured ? '🏵️' : '🎮' }} {{ s.name }}<em v-if="s.year"> {{ s.year }}</em>
489
- </span>
231
+ <!-- NEW: Ecossistema Mundo Gamer -->
232
+ <section v-if="hasEcosystem" class="kit-block">
233
+ <h2>{{ $t('kit.press.ecosystem') }}</h2>
234
+ <div class="kit-eco">
235
+ <div v-if="showcases.length" class="kit-eco-card full">
236
+ <div class="kit-eco-h"><span class="ic">★</span>{{ $t('kit.press.showcases') }}</div>
237
+ <div class="kit-sbadges">
238
+ <span v-for="(s, i) in showcases" :key="i" class="kit-sbadge" :class="{ feat: s.featured }"><span class="medal">{{ s.featured ? '🏵️' : '🎮' }}</span>{{ s.name }}<span v-if="s.year"> {{ s.year }}</span></span>
490
239
  </div>
491
240
  </div>
492
-
493
- <!-- Magazine feature -->
494
- <a
495
- v-if="kit.magazine_feature"
496
- :href="kit.magazine_feature.url"
497
- target="_blank"
498
- rel="noopener"
499
- class="pk-eco-card"
500
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'magazine' } })"
501
- >
502
- <div class="pk-eco-mag">
503
- <div
504
- v-if="kit.magazine_feature.cover"
505
- class="pk-eco-mag__cover"
506
- :style="{ backgroundImage: `url(${kit.magazine_feature.cover})` }"
507
- />
508
- <div>
509
- <p class="pk-eco-mag__title">{{ kit.magazine_feature.title }}</p>
510
- <p class="pk-eco-mag__issue">{{ kit.magazine_feature.issue }}</p>
511
- </div>
512
- </div>
241
+ <div v-if="kit.ventures_url" class="kit-eco-card">
242
+ <div class="kit-eco-h"><span class="ic">◈</span>MGN Ventures</div>
243
+ <a class="kit-vrow" :href="kit.ventures_url" target="_blank" rel="noopener" @click="track('click')"><span class="vlogo">VENTURES</span><span class="vtxt">{{ $t('kit.press.ventures_text') }}</span></a>
244
+ </div>
245
+ <a v-if="kit.magazine_feature" class="kit-eco-card kit-mag" :href="kit.magazine_feature.url" target="_blank" rel="noopener" @click="track('click')">
246
+ <div class="kit-eco-h" style="width:100%"><span class="ic">▤</span>MGN Magazine</div>
247
+ <div class="kit-mag-row"><div class="mcover" :style="kit.magazine_feature.cover ? { backgroundImage: `url(${kit.magazine_feature.cover})` } : {}" /><div><div class="mtitle">{{ kit.magazine_feature.title }}</div><div class="mmeta">{{ kit.magazine_feature.issue }}</div></div></div>
513
248
  </a>
514
-
515
- <!-- Community follow -->
516
- <div v-if="communityUrl" class="pk-eco-card">
517
- <p class="pk-eco-card__text">{{ $t('press_kit.follow_community_desc', { name: kit.name }) }}</p>
518
- <a
519
- :href="communityUrl"
520
- target="_blank"
521
- rel="noopener"
522
- class="pk-btn pk-btn--sm"
523
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'community' } })"
524
- >
525
- {{ $t('press_kit.follow_community') }}
526
- </a>
249
+ <div v-if="kit.community_url" class="kit-eco-card full">
250
+ <div class="kit-ccta">
251
+ <div><div class="ctitle">{{ $t('kit.press.follow_community', { name: kit.name }) }}</div><div v-if="kit.community_followers" class="cmeta">{{ kit.community_followers }} {{ $t('kit.press.followers') }}</div></div>
252
+ <a class="kit-btn kit-btn-primary" :href="kit.community_url" target="_blank" rel="noopener" @click="track('click')">{{ $t('kit.press.follow') }}</a>
253
+ </div>
527
254
  </div>
255
+ </div>
256
+ </section>
528
257
 
529
- <!-- Ventures -->
530
- <a
531
- v-if="kit.ventures_url"
532
- :href="kit.ventures_url"
533
- target="_blank"
534
- rel="noopener"
535
- class="pk-eco-card"
536
- @click="trackPressKitEvent(slug, { event_type: 'click', metadata: { target: 'ventures' } })"
537
- >
538
- <p class="pk-eco-card__label">MGN Ventures</p>
539
- <p class="pk-eco-card__text">{{ $t('press_kit.ventures_text') }}</p>
540
- </a>
258
+ <section v-if="kit.press_contact_email" class="kit-block">
259
+ <div class="kit-cta">
260
+ <h2>{{ $t('kit.press.covering', { name: kit.name }) }}</h2>
261
+ <p>{{ $t('kit.press.cta_text') }}</p>
262
+ <a class="kit-btn kit-btn-primary" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.request_key') }}</a>
541
263
  </div>
542
264
  </section>
543
265
 
266
+ <p class="kit-madewith">
267
+ {{ $t('kit.press.made_with') }} <strong>Mundo Gamer</strong> —
268
+ <a :href="kit.create_kit_url || `${agencyBase}/presskit`" target="_blank" rel="noopener">{{ $t('kit.press.create_yours') }}</a>
269
+ </p>
544
270
  </main>
545
271
  </div>
546
272
  </div>
547
-
548
- <!-- ═══ Brand footer ════════════════════════════════════════════ -->
549
- <p class="pk-brand-footer">
550
- {{ $t('press_kit.made_with') }} {{ $t('press_kit.brand_sub') }} —
551
- <a href="https://agency.mundogamer.network/press" target="_blank" rel="noopener">{{ $t('press_kit.create_yours_cta') }}</a>
552
- </p>
553
-
554
273
  </template>
555
-
556
- <!-- ═══ Trailer Modal ══════════════════════════════════════════════ -->
557
- <div
558
- v-if="showTrailer && trailerEmbedUrl"
559
- class="pk-modal"
560
- role="dialog"
561
- :aria-label="$t('press_kit.watch_trailer')"
562
- @click.self="showTrailer = false"
563
- @keydown.esc="showTrailer = false"
564
- >
565
- <button class="pk-modal__close" :aria-label="$t('common.close')" @click="showTrailer = false">×</button>
566
- <iframe
567
- :src="trailerEmbedUrl"
568
- class="pk-modal__video"
569
- frameborder="0"
570
- allow="autoplay; encrypted-media"
571
- allowfullscreen
572
- />
573
- </div>
574
274
  </div>
575
275
  </template>
576
-
577
- <style lang="scss" scoped>
578
- // ── Self-contained theme system ────────────────────────────────────
579
- // All tokens are declared directly on .pk-page so the press kit is
580
- // always correctly styled regardless of the host platform's
581
- // light/dark mode. Studios choose a theme in the editor; the value
582
- // is stored in kit.theme and applied via data-theme attribute.
583
- //
584
- // Available themes:
585
- // default · light · blade · aurora · ember · nova
586
- // ──────────────────────────────────────────────────────────────────
587
- .pk-page {
588
- // ── default (dark gold) ──────────────────────────────────────
589
- --background: #0e1015;
590
- --card-background: #191b20;
591
- --divider: #2a2d35;
592
- --text-primary: #ffffff;
593
- --text-secondary: #8a8f9e;
594
- --primary: #fcb216;
595
- --primary-contrast: #13161c;
596
-
597
- min-height: 100vh;
598
- background: var(--background);
599
- color: var(--text-primary);
600
-
601
- // ── light (white + slate) ────────────────────────────────────
602
- &[data-theme="light"] {
603
- --background: #f5f6f8;
604
- --card-background: #ffffff;
605
- --divider: #e2e5ea;
606
- --text-primary: #111318;
607
- --text-secondary: #5a6070;
608
- --primary: #fcb216;
609
- --primary-contrast: #ffffff;
610
- }
611
-
612
- // ── blade (dark navy + electric blue) ───────────────────────
613
- &[data-theme="blade"] {
614
- --background: #0d1b2a;
615
- --card-background: #112236;
616
- --divider: #1e3a52;
617
- --text-primary: #e0f0ff;
618
- --text-secondary: #7aabce;
619
- --primary: #3a86ff;
620
- --primary-contrast: #ffffff;
621
- }
622
-
623
- // ── aurora (deep purple + neon green) ───────────────────────
624
- &[data-theme="aurora"] {
625
- --background: #0f0c1a;
626
- --card-background: #1a1428;
627
- --divider: #2d2040;
628
- --text-primary: #f0ecff;
629
- --text-secondary: #9d87c4;
630
- --primary: #a855f7;
631
- --primary-contrast: #ffffff;
632
- }
633
-
634
- // ── ember (deep brown + fire orange) ────────────────────────
635
- &[data-theme="ember"] {
636
- --background: #1a0900;
637
- --card-background: #251100;
638
- --divider: #3d1f00;
639
- --text-primary: #ffedd5;
640
- --text-secondary: #c4875a;
641
- --primary: #f97316;
642
- --primary-contrast: #ffffff;
643
- }
644
-
645
- // ── nova (true black + gold) ─────────────────────────────────
646
- &[data-theme="nova"] {
647
- --background: #0d0d0d;
648
- --card-background: #161616;
649
- --divider: #2a2a2a;
650
- --text-primary: #fff8dc;
651
- --text-secondary: #a89060;
652
- --primary: #ffd700;
653
- --primary-contrast: #0d0d0d;
654
- }
655
- }
656
-
657
- // ── Loading ───────────────────────────────────────────────────────
658
- .pk-loading {
659
- display: flex;
660
- justify-content: center;
661
- align-items: center;
662
- min-height: 60vh;
663
- }
664
-
665
- .pk-spinner {
666
- width: 40px;
667
- height: 40px;
668
- border: 3px solid var(--divider, #2a2d35);
669
- border-top-color: var(--primary, #fcb216);
670
- animation: pk-spin 0.8s linear infinite;
671
- }
672
-
673
- @keyframes pk-spin { to { transform: rotate(360deg); } }
674
-
675
- // ── Error ─────────────────────────────────────────────────────────
676
- .pk-error {
677
- text-align: center;
678
- padding: 80px 20px;
679
-
680
- h1 { font-size: 1.8rem; margin-bottom: 8px; }
681
- p { color: var(--text-secondary, #888); margin-bottom: 24px; }
682
- }
683
-
684
- // ── Hero ─────────────────────────────────────────────────────────
685
- .pk-hero {
686
- position: relative;
687
- min-height: 480px;
688
- background-size: cover;
689
- background-position: center;
690
- background-color: var(--card-background, #191b20);
691
- overflow: hidden;
692
-
693
- @media (max-width: 768px) { min-height: 320px; }
694
- }
695
-
696
- .pk-hero__overlay {
697
- position: absolute;
698
- inset: 0;
699
- background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.15) 100%);
700
- display: flex;
701
- align-items: flex-end;
702
- }
703
-
704
- .pk-hero__inner {
705
- max-width: 900px;
706
- margin: 0 auto;
707
- width: 100%;
708
- padding: 48px 24px;
709
-
710
- @media (max-width: 768px) { padding: 24px 16px; }
711
- }
712
-
713
- .pk-hero__logo {
714
- margin-bottom: 16px;
715
-
716
- img {
717
- max-height: 80px;
718
- max-width: 240px;
719
- object-fit: contain;
720
- }
721
- }
722
-
723
- .pk-hero__title {
724
- font-size: 2.8rem;
725
- font-weight: 700;
726
- margin: 0 0 8px;
727
- line-height: 1.1;
728
-
729
- @media (max-width: 768px) { font-size: 1.8rem; }
730
- }
731
-
732
- .pk-hero__tagline {
733
- font-size: 1.1rem;
734
- color: rgba(255,255,255,0.75);
735
- margin: 0 0 20px;
736
- max-width: 600px;
737
- }
738
-
739
- .pk-hero__actions {
740
- display: flex;
741
- gap: 10px;
742
- flex-wrap: wrap;
743
- }
744
-
745
- // ── Buttons ───────────────────────────────────────────────────────
746
- .pk-btn {
747
- display: inline-flex;
748
- align-items: center;
749
- gap: 6px;
750
- background: var(--primary, #fcb216);
751
- color: var(--primary-contrast, #13161c);
752
- border: none;
753
- padding: 10px 22px;
754
- font-weight: 700;
755
- font-size: 0.9rem;
756
- cursor: pointer;
757
- text-decoration: none;
758
- transition: opacity 0.15s;
759
-
760
- &:hover { opacity: 0.85; }
761
-
762
- &--outline {
763
- background: rgba(252, 178, 22, 0.12);
764
- color: var(--primary, #fcb216);
765
- border: 1px solid var(--primary, #fcb216);
766
- }
767
-
768
- &--ghost {
769
- background: rgba(255,255,255,0.08);
770
- color: var(--text-primary, #fff);
771
- border: 1px solid rgba(255,255,255,0.2);
772
- }
773
-
774
- &--sm {
775
- padding: 7px 16px;
776
- font-size: 0.82rem;
777
- }
778
-
779
- &--full {
780
- width: 100%;
781
- justify-content: center;
782
- margin-top: 10px;
783
- }
784
- }
785
-
786
- // ── Container / Layout ────────────────────────────────────────────
787
- .pk-container {
788
- max-width: 1200px;
789
- margin: 0 auto;
790
- padding: 48px 16px;
791
- }
792
-
793
- .pk-layout {
794
- display: grid;
795
- grid-template-columns: 280px 1fr;
796
- gap: 40px;
797
- align-items: start;
798
-
799
- @media (max-width: 900px) {
800
- grid-template-columns: 1fr;
801
- }
802
- }
803
-
804
- .pk-sidebar {
805
- display: flex;
806
- flex-direction: column;
807
- gap: 20px;
808
- position: sticky;
809
- top: 24px;
810
-
811
- @media (max-width: 900px) { position: static; }
812
- }
813
-
814
- .pk-main {
815
- display: flex;
816
- flex-direction: column;
817
- gap: 48px;
818
- }
819
-
820
- // ── Card (sidebar) ────────────────────────────────────────────────
821
- .pk-card {
822
- background: var(--card-background, #191b20);
823
- border: 1px solid var(--divider, #2a2d35);
824
- padding: 20px;
825
-
826
- &--accent {
827
- border-color: var(--primary, #fcb216);
828
- background: rgba(252, 178, 22, 0.05);
829
- }
830
-
831
- &__title {
832
- font-size: 0.75rem;
833
- text-transform: uppercase;
834
- letter-spacing: 0.08em;
835
- font-weight: 700;
836
- color: var(--text-secondary, #888);
837
- margin: 0 0 14px;
838
- }
839
-
840
- &__desc {
841
- font-size: 0.82rem;
842
- color: var(--text-secondary, #aaa);
843
- line-height: 1.5;
844
- margin: 0;
845
- }
846
- }
847
-
848
- .pk-dl {
849
- margin: 0;
850
-
851
- dt {
852
- font-size: 0.7rem;
853
- text-transform: uppercase;
854
- letter-spacing: 0.05em;
855
- color: var(--text-secondary, #888);
856
- margin-top: 10px;
857
- }
858
-
859
- dd {
860
- margin: 3px 0 0;
861
- font-size: 0.88rem;
862
- color: var(--text-primary, #fff);
863
- word-break: break-word;
864
-
865
- a { color: var(--primary, #fcb216); text-decoration: none; }
866
- }
867
- }
868
-
869
- .pk-links {
870
- display: flex;
871
- flex-direction: column;
872
- gap: 8px;
873
- }
874
-
875
- .pk-link {
876
- display: flex;
877
- align-items: center;
878
- gap: 8px;
879
- color: var(--text-secondary, #aaa);
880
- text-decoration: none;
881
- font-size: 0.88rem;
882
- padding: 6px 0;
883
- border-bottom: 1px solid var(--divider, #2a2d35);
884
- transition: color 0.15s;
885
-
886
- &:last-child { border-bottom: none; }
887
- &:hover { color: var(--primary, #fcb216); }
888
- }
889
-
890
- // ── Sections ──────────────────────────────────────────────────────
891
- .pk-section {
892
- &__head {
893
- display: flex;
894
- justify-content: space-between;
895
- align-items: center;
896
- flex-wrap: wrap;
897
- gap: 10px;
898
- margin-bottom: 16px;
899
- padding-bottom: 10px;
900
- border-bottom: 1px solid var(--divider, #2a2d35);
901
- }
902
-
903
- &__title {
904
- font-size: 1.1rem;
905
- font-weight: 700;
906
- margin: 0 0 16px;
907
- padding-bottom: 10px;
908
- border-bottom: 1px solid var(--divider, #2a2d35);
909
- }
910
- }
911
-
912
- .pk-prose {
913
- font-size: 0.95rem;
914
- line-height: 1.7;
915
- color: var(--text-secondary, #ccc);
916
-
917
- :deep(p) { margin-bottom: 12px; }
918
- }
919
-
920
- .pk-features {
921
- list-style: none;
922
- padding: 0;
923
- margin: 0;
924
- display: grid;
925
- grid-template-columns: 1fr 1fr;
926
- gap: 8px 24px;
927
-
928
- @media (max-width: 600px) { grid-template-columns: 1fr; }
929
-
930
- li {
931
- display: flex;
932
- align-items: flex-start;
933
- gap: 8px;
934
- font-size: 0.9rem;
935
- color: var(--text-secondary, #ccc);
936
-
937
- &::before {
938
- content: '▸';
939
- color: var(--primary, #fcb216);
940
- flex-shrink: 0;
941
- margin-top: 1px;
942
- }
943
- }
944
- }
945
-
946
- // ── Videos ────────────────────────────────────────────────────────
947
- .pk-videos {
948
- display: grid;
949
- grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
950
- gap: 12px;
951
- }
952
-
953
- .pk-video-card {
954
- background: var(--card-background, #191b20);
955
- border: 1px solid var(--divider, #2a2d35);
956
- cursor: pointer;
957
- overflow: hidden;
958
- transition: border-color 0.15s;
959
-
960
- &:hover { border-color: var(--primary, #fcb216); }
961
-
962
- &__thumb {
963
- aspect-ratio: 16 / 9;
964
- background: var(--divider, #2a2d35);
965
- display: flex;
966
- align-items: center;
967
- justify-content: center;
968
- font-size: 1.8rem;
969
- color: var(--primary, #fcb216);
970
- }
971
-
972
- &__title {
973
- display: block;
974
- font-size: 0.8rem;
975
- font-weight: 600;
976
- padding: 8px 10px 2px;
977
- color: var(--text-primary, #fff);
978
- }
979
-
980
- &__type {
981
- display: block;
982
- font-size: 0.7rem;
983
- padding: 0 10px 8px;
984
- color: var(--text-secondary, #888);
985
- text-transform: uppercase;
986
- letter-spacing: 0.04em;
987
- }
988
- }
989
-
990
- // ── Asset filters ─────────────────────────────────────────────────
991
- .pk-asset-filters {
992
- display: flex;
993
- gap: 6px;
994
- flex-wrap: wrap;
995
- }
996
-
997
- .pk-filter {
998
- background: var(--card-background, #191b20);
999
- border: 1px solid var(--divider, #2a2d35);
1000
- color: var(--text-secondary, #888);
1001
- padding: 4px 12px;
1002
- font-size: 0.75rem;
1003
- cursor: pointer;
1004
- text-transform: capitalize;
1005
- transition: all 0.15s;
1006
-
1007
- &:hover { color: var(--text-primary, #fff); }
1008
-
1009
- &.active {
1010
- background: var(--primary, #fcb216);
1011
- border-color: var(--primary, #fcb216);
1012
- color: var(--primary-contrast, #13161c);
1013
- font-weight: 700;
1014
- }
1015
- }
1016
-
1017
- // ── Assets grid ───────────────────────────────────────────────────
1018
- .pk-assets {
1019
- display: grid;
1020
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1021
- gap: 12px;
1022
- margin-top: 16px;
1023
- }
1024
-
1025
- .pk-asset {
1026
- display: flex;
1027
- flex-direction: column;
1028
- background: var(--card-background, #191b20);
1029
- border: 1px solid var(--divider, #2a2d35);
1030
- text-decoration: none;
1031
- color: inherit;
1032
- transition: border-color 0.15s;
1033
-
1034
- &:hover { border-color: var(--primary, #fcb216); }
1035
-
1036
- &__thumb {
1037
- aspect-ratio: 16 / 9;
1038
- overflow: hidden;
1039
- background: var(--divider, #2a2d35);
1040
- display: flex;
1041
- align-items: center;
1042
- justify-content: center;
1043
- font-size: 1.5rem;
1044
- color: var(--text-secondary, #555);
1045
-
1046
- img {
1047
- width: 100%;
1048
- height: 100%;
1049
- object-fit: cover;
1050
- display: block;
1051
- }
1052
- }
1053
-
1054
- &__dl-icon { font-size: 1.4rem; color: var(--text-secondary, #555); }
1055
-
1056
- &__body {
1057
- padding: 10px;
1058
- flex: 1;
1059
- display: flex;
1060
- flex-direction: column;
1061
- gap: 4px;
1062
- }
1063
-
1064
- &__title {
1065
- font-size: 0.8rem;
1066
- font-weight: 600;
1067
- color: var(--text-primary, #fff);
1068
- }
1069
-
1070
- &__size {
1071
- font-size: 0.7rem;
1072
- color: var(--text-secondary, #888);
1073
- }
1074
- }
1075
-
1076
- .pk-empty {
1077
- color: var(--text-secondary, #888);
1078
- font-size: 0.9rem;
1079
- padding: 16px 0;
1080
- }
1081
-
1082
- // ── Quotes ────────────────────────────────────────────────────────
1083
- .pk-quotes {
1084
- display: flex;
1085
- flex-direction: column;
1086
- gap: 16px;
1087
- }
1088
-
1089
- .pk-quote {
1090
- border-left: 3px solid var(--primary, #fcb216);
1091
- padding: 12px 20px;
1092
- background: var(--card-background, #191b20);
1093
- margin: 0;
1094
-
1095
- p {
1096
- font-size: 1rem;
1097
- font-style: italic;
1098
- color: var(--text-secondary, #ccc);
1099
- margin: 0 0 8px;
1100
- line-height: 1.6;
1101
- }
1102
-
1103
- footer {
1104
- font-size: 0.8rem;
1105
- color: var(--text-secondary, #888);
1106
-
1107
- a { color: var(--primary, #fcb216); text-decoration: none; }
1108
- }
1109
- }
1110
-
1111
- // ── Articles ──────────────────────────────────────────────────────
1112
- .pk-articles {
1113
- display: grid;
1114
- grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
1115
- gap: 14px;
1116
- }
1117
-
1118
- .pk-article {
1119
- background: var(--card-background, #191b20);
1120
- border: 1px solid var(--divider, #2a2d35);
1121
- text-decoration: none;
1122
- color: inherit;
1123
- overflow: hidden;
1124
- transition: border-color 0.15s;
1125
- display: flex;
1126
- flex-direction: column;
1127
-
1128
- &:hover { border-color: var(--primary, #fcb216); }
1129
-
1130
- &__thumb {
1131
- aspect-ratio: 16 / 9;
1132
- background: var(--divider, #2a2d35) center / cover;
1133
- position: relative;
1134
- }
1135
-
1136
- &__src {
1137
- position: absolute;
1138
- top: 8px;
1139
- left: 8px;
1140
- background: var(--primary, #fcb216);
1141
- color: var(--primary-contrast, #13161c);
1142
- font-size: 0.65rem;
1143
- font-weight: 700;
1144
- letter-spacing: 0.05em;
1145
- text-transform: uppercase;
1146
- padding: 3px 8px;
1147
-
1148
- &.external {
1149
- background: var(--card-background, #191b20);
1150
- color: var(--text-secondary, #888);
1151
- border: 1px solid var(--divider, #2a2d35);
1152
- }
1153
- }
1154
-
1155
- &__body {
1156
- padding: 12px 14px;
1157
- flex: 1;
1158
- display: flex;
1159
- flex-direction: column;
1160
- gap: 6px;
1161
- }
1162
-
1163
- &__title {
1164
- font-size: 0.88rem;
1165
- font-weight: 600;
1166
- line-height: 1.4;
1167
- color: var(--text-primary, #fff);
1168
- margin: 0;
1169
- }
1170
-
1171
- &__date {
1172
- font-size: 0.75rem;
1173
- color: var(--text-secondary, #888);
1174
- }
1175
- }
1176
-
1177
- // ── Coverage ──────────────────────────────────────────────────────
1178
- .pk-coverage {
1179
- display: grid;
1180
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1181
- gap: 12px;
1182
- }
1183
-
1184
- .pk-creator {
1185
- display: flex;
1186
- flex-direction: column;
1187
- align-items: center;
1188
- text-align: center;
1189
- gap: 10px;
1190
- padding: 20px 16px;
1191
- background: var(--card-background, #191b20);
1192
- border: 1px solid var(--divider, #2a2d35);
1193
- text-decoration: none;
1194
- color: inherit;
1195
- transition: border-color 0.15s;
1196
-
1197
- &:hover { border-color: var(--primary, #fcb216); }
1198
-
1199
- &__avatar {
1200
- width: 56px;
1201
- height: 56px;
1202
- background: var(--divider, #2a2d35) center / cover;
1203
- border: 2px solid var(--primary, #fcb216);
1204
- }
1205
-
1206
- &__info {
1207
- display: flex;
1208
- flex-direction: column;
1209
- gap: 2px;
1210
-
1211
- strong { font-size: 0.9rem; color: var(--text-primary, #fff); }
1212
- span { font-size: 0.78rem; color: var(--text-secondary, #888); }
1213
- }
1214
-
1215
- &__followers {
1216
- font-size: 0.72rem !important;
1217
- color: var(--primary, #fcb216) !important;
1218
- font-weight: 600;
1219
- }
1220
-
1221
- &__label {
1222
- font-size: 0.7rem;
1223
- font-weight: 700;
1224
- text-transform: uppercase;
1225
- letter-spacing: 0.05em;
1226
- color: var(--text-secondary, #888);
1227
- border: 1px solid var(--divider, #2a2d35);
1228
- padding: 2px 8px;
1229
- }
1230
- }
1231
-
1232
- // ── Awards ────────────────────────────────────────────────────────
1233
- .pk-awards {
1234
- display: flex;
1235
- flex-direction: column;
1236
- gap: 10px;
1237
- }
1238
-
1239
- .pk-award {
1240
- display: flex;
1241
- align-items: center;
1242
- gap: 12px;
1243
- padding: 12px 16px;
1244
- background: var(--card-background, #191b20);
1245
- border: 1px solid var(--divider, #2a2d35);
1246
-
1247
- &__star { color: var(--primary, #fcb216); font-size: 1.2rem; flex-shrink: 0; }
1248
-
1249
- &__body {
1250
- flex: 1;
1251
- display: flex;
1252
- flex-direction: column;
1253
- gap: 2px;
1254
-
1255
- strong { font-size: 0.9rem; color: var(--text-primary, #fff); }
1256
- span { font-size: 0.8rem; color: var(--text-secondary, #888); }
1257
- }
1258
-
1259
- &__link { color: var(--primary, #fcb216); text-decoration: none; }
1260
- }
1261
-
1262
- // ── Team / Credits ─────────────────────────────────────────────────
1263
- .pk-credits {
1264
- display: grid;
1265
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1266
- gap: 10px;
1267
- }
1268
-
1269
- .pk-credit {
1270
- display: flex;
1271
- flex-direction: column;
1272
- gap: 2px;
1273
- padding: 12px 14px;
1274
- background: var(--card-background, #191b20);
1275
- border: 1px solid var(--divider, #2a2d35);
1276
-
1277
- strong { font-size: 0.9rem; color: var(--text-primary, #fff); }
1278
- span { font-size: 0.78rem; color: var(--text-secondary, #888); }
1279
-
1280
- a {
1281
- color: var(--primary, #fcb216);
1282
- text-decoration: none;
1283
- font-size: 0.78rem;
1284
- margin-top: 4px;
1285
- }
1286
- }
1287
-
1288
- // ── Ecosystem ─────────────────────────────────────────────────────
1289
- .pk-ecosystem {
1290
- display: grid;
1291
- grid-template-columns: 1fr 1fr;
1292
- gap: 14px;
1293
-
1294
- @media (max-width: 640px) { grid-template-columns: 1fr; }
1295
- }
1296
-
1297
- .pk-eco-card {
1298
- background: var(--card-background, #191b20);
1299
- border: 1px solid var(--divider, #2a2d35);
1300
- padding: 20px;
1301
- display: flex;
1302
- flex-direction: column;
1303
- gap: 10px;
1304
- text-decoration: none;
1305
- color: inherit;
1306
- transition: border-color 0.15s;
1307
-
1308
- &:hover { border-color: var(--primary, #fcb216); }
1309
-
1310
- &--full { grid-column: 1 / -1; }
1311
-
1312
- &__title {
1313
- font-size: 0.75rem;
1314
- text-transform: uppercase;
1315
- letter-spacing: 0.07em;
1316
- font-weight: 700;
1317
- color: var(--text-secondary, #888);
1318
- margin: 0 0 8px;
1319
- }
1320
-
1321
- &__label {
1322
- font-size: 0.75rem;
1323
- text-transform: uppercase;
1324
- letter-spacing: 0.07em;
1325
- font-weight: 700;
1326
- color: var(--primary, #fcb216);
1327
- margin: 0;
1328
- }
1329
-
1330
- &__text {
1331
- font-size: 0.88rem;
1332
- color: var(--text-secondary, #ccc);
1333
- line-height: 1.5;
1334
- margin: 0;
1335
- }
1336
- }
1337
-
1338
- .pk-showcases {
1339
- display: flex;
1340
- flex-wrap: wrap;
1341
- gap: 8px;
1342
- }
1343
-
1344
- .pk-showcase {
1345
- display: flex;
1346
- align-items: center;
1347
- gap: 6px;
1348
- background: var(--divider, #2a2d35);
1349
- border: 1px solid var(--divider, #2a2d35);
1350
- padding: 6px 12px;
1351
- font-size: 0.82rem;
1352
- color: var(--text-secondary, #ccc);
1353
-
1354
- &.featured {
1355
- border-color: var(--primary, #fcb216);
1356
- background: rgba(252, 178, 22, 0.06);
1357
- color: var(--text-primary, #fff);
1358
- }
1359
-
1360
- em { font-style: normal; color: var(--text-secondary, #888); margin-left: 4px; }
1361
- }
1362
-
1363
- .pk-eco-mag {
1364
- display: flex;
1365
- gap: 14px;
1366
- align-items: center;
1367
-
1368
- &__cover {
1369
- width: 52px;
1370
- aspect-ratio: 3 / 4;
1371
- background: var(--divider, #2a2d35) center / cover;
1372
- border: 1px solid var(--divider, #2a2d35);
1373
- flex-shrink: 0;
1374
- }
1375
-
1376
- &__title {
1377
- font-size: 0.88rem;
1378
- font-weight: 600;
1379
- color: var(--text-primary, #fff);
1380
- margin: 0 0 4px;
1381
- }
1382
-
1383
- &__issue {
1384
- font-size: 0.75rem;
1385
- color: var(--text-secondary, #888);
1386
- margin: 0;
1387
- }
1388
- }
1389
-
1390
- // ── Brand footer ──────────────────────────────────────────────────
1391
- .pk-brand-footer {
1392
- text-align: center;
1393
- font-size: 0.75rem;
1394
- color: var(--text-secondary, #666);
1395
- padding: 20px 16px;
1396
- border-top: 1px solid var(--divider, #2a2d35);
1397
- margin: 0;
1398
-
1399
- strong { color: var(--text-secondary, #888); font-weight: 600; }
1400
-
1401
- a {
1402
- color: var(--text-secondary, #888);
1403
- text-decoration: none;
1404
- border-bottom: 1px solid var(--divider, #2a2d35);
1405
- transition: color 0.15s, border-color 0.15s;
1406
-
1407
- &:hover {
1408
- color: var(--primary, #fcb216);
1409
- border-color: var(--primary, #fcb216);
1410
- }
1411
- }
1412
- }
1413
-
1414
- // ── Scroll unlock (body has overflow-y: hidden globally in some frontends) ───
1415
- :global(body):has(.pk-page) {
1416
- overflow-y: auto !important;
1417
- max-height: none !important;
1418
- }
1419
-
1420
- // ── Trailer modal ─────────────────────────────────────────────────
1421
- .pk-modal {
1422
- position: fixed;
1423
- inset: 0;
1424
- background: rgba(0,0,0,0.92);
1425
- z-index: 9000;
1426
- display: flex;
1427
- align-items: center;
1428
- justify-content: center;
1429
-
1430
- &__close {
1431
- position: absolute;
1432
- top: 16px;
1433
- right: 20px;
1434
- background: none;
1435
- border: none;
1436
- color: var(--text-primary, #fff);
1437
- font-size: 2rem;
1438
- cursor: pointer;
1439
- z-index: 1;
1440
- }
1441
-
1442
- &__video {
1443
- width: 80vw;
1444
- max-width: 900px;
1445
- aspect-ratio: 16 / 9;
1446
- border: none;
1447
- display: block;
1448
- }
1449
- }
1450
- </style>