@mundogamernetwork/shared-ui 1.8.3 → 1.8.5

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,16 +1,59 @@
1
1
  <script setup lang="ts">
2
2
  import { fetchPublicMediaKit, trackMediaKitEvent } from '../../services/mediaKitService';
3
+ import { sendMediaKitProposal } from '../../services/mediaKitProposalService';
3
4
  import MediaKitWallBlock from '../../components/indie-wall/MediaKitWallBlock.vue';
4
5
  import MgMediaKitStore from '../../components/MediaKit/MgMediaKitStore.vue';
5
6
 
6
7
  const route = useRoute();
7
8
  const slug = computed(() => route.params.slug as string);
9
+ const localePath = useLocalePath();
10
+ const { t } = useI18n();
11
+
12
+ // Same cross-link pattern as shared-ui/pages/presskit/game/[slug].vue — the
13
+ // "made with" footer CTA points here regardless of which service serves this page.
14
+ const runtimeConfig = useRuntimeConfig();
15
+ const cfg = (runtimeConfig.public as any) || {};
16
+ const agencyBase: string = cfg.agencyBaseUrl || '';
17
+ const authStore = useAuthStore();
18
+ const toast = useToast();
19
+
20
+ // ── C2: internal shortlist / Campaign Wizard bar ──
21
+ // Only ever renders on agency-frontend (isAgencyHost) — Campaign Wizard and the
22
+ // shortlist's localStorage only live there; rendering this on tv-frontend/
23
+ // community-frontend would silently lose items on navigation (different origin).
24
+ // `viewer_can_manage_shortlist` is server-computed (brand/agency/studio profile_types,
25
+ // see PublicMediaKitController::viewerCanBypassRateCardGate) — the true security
26
+ // boundary is already there (gated rate cards never leave the API for ineligible
27
+ // viewers); this only controls whether the bar itself renders.
28
+ const shortlist = useShortlistStore();
8
29
 
9
30
  const kit = ref<Record<string, any> | null>(null);
10
31
  const loading = ref(true);
11
32
  const error = ref(false);
12
33
 
13
34
  const userId = computed(() => kit.value?.user_id);
35
+ const hasMural = ref(false);
36
+ const influencerProId = computed<number | null>(() => kit.value?.influencer_professional_info_id ?? null);
37
+ const isOwnKit = computed(() => !!authStore.user?.id && !!userId.value && String(authStore.user.id) === String(userId.value));
38
+ const showShortlistBar = computed(() =>
39
+ !!cfg.isAgencyHost
40
+ && !!kit.value?.viewer_can_manage_shortlist
41
+ && !isOwnKit.value
42
+ && !!influencerProId.value,
43
+ );
44
+ const inShortlist = computed(() => influencerProId.value ? shortlist.has(influencerProId.value) : false);
45
+ const campaignWizardUrl = computed(() => `${agencyBase}/dashboard/campaign-wizard?influencers=${shortlist.ids.join(',')}`);
46
+
47
+ function toggleShortlist() {
48
+ if (!influencerProId.value) return;
49
+ shortlist.toggle({
50
+ id: influencerProId.value,
51
+ name: streamer.value?.name || slug.value,
52
+ slug: streamer.value?.slug || slug.value,
53
+ image: streamer.value?.avatar || null,
54
+ rate_cards: rateCards.value,
55
+ });
56
+ }
14
57
  const streamer = computed(() => kit.value?.streamer ?? {});
15
58
  const stats = computed(() => kit.value?.stats ?? null);
16
59
  const topGames = computed(() => kit.value?.top_games ?? []);
@@ -31,9 +74,22 @@ const portfolioImages = computed(() => kit.value?.portfolio_images ?? streamer.v
31
74
  const brandLogos = computed(() => kit.value?.brand_logos ?? streamer.value?.brand_logos ?? []);
32
75
  const creatorStore = computed(() => kit.value?.creator_store ?? null);
33
76
  const customLinks = computed(() => kit.value?.custom_links ?? streamer.value?.custom_links ?? []);
77
+ const websiteUrl = computed<string | null>(() => streamer.value?.website ?? null);
78
+
79
+ // ── D2 ecosystem data ──
80
+ const selectedGames = computed<string[]>(() => kit.value?.selected_games ?? []);
81
+ const audienceGeo = computed<any[]>(() => kit.value?.audience_geo ?? []);
82
+ const platformsPlayed = computed<any[]>(() => kit.value?.platforms_played ?? []);
83
+ const academyMentor = computed(() => kit.value?.academy_mentor ?? null);
84
+ const communityStats = computed(() => kit.value?.community ?? null);
85
+ const tvChannelLogin = computed<string | null>(() => streamer.value?.tv_channel_login ?? null);
86
+ const tvSiteUrl = import.meta.env.VITE_TV_SITE_URL || 'https://mundogamer.tv';
87
+ const tvChannelUrl = computed(() => tvChannelLogin.value
88
+ ? `${tvSiteUrl}/${route.params.locale || 'en'}/stream/${tvChannelLogin.value}`
89
+ : null);
34
90
 
35
91
  const coverStyle = computed(() => coverUrl.value
36
- ? { backgroundImage: `linear-gradient(180deg, rgba(5,6,10,.14), rgba(5,6,10,.92)), url("${String(coverUrl.value).replace(/"/g, '\\"')}")` }
92
+ ? { backgroundImage: `linear-gradient(180deg, rgba(10,10,12,.15), rgba(10,10,12,.85)), url("${String(coverUrl.value).replace(/"/g, '\\"')}")` }
37
93
  : undefined);
38
94
 
39
95
  const PLATFORM_LABEL: Record<string, string> = {
@@ -54,20 +110,100 @@ const scheduleByDay = computed(() => {
54
110
  return [0, 1, 2, 3, 4, 5, 6].map((d) => ({ d, key: DOW[d], slot: map[d] || null }));
55
111
  });
56
112
 
113
+ // ── Tabs: template picks which one opens first, casting-details-style ──
114
+ const TAB_KEYS = ['profile', 'rates', 'performance'] as const;
115
+ const TEMPLATE_DEFAULT_TAB: Record<string, number> = {
116
+ creator: 0, audience: 0, commercial: 1, performance: 2,
117
+ };
118
+ const activeTab = ref(TEMPLATE_DEFAULT_TAB[template.value] ?? 0);
119
+ const hasRatesTab = computed(() => rateCards.value.length > 0 || bundles.value.length > 0);
120
+ const hasPerformanceTab = computed(() => !!stats.value || !!academyMentor.value || !!communityStats.value || schedule.value.length > 0);
121
+
122
+ // ── Rate card / bundle proposal builder ──
123
+ const cartMode = ref<'packages' | 'individual'>(hasRatesTab.value && rateCards.value.length ? 'individual' : 'packages');
124
+ const selectedCardIndexes = ref<Set<number>>(new Set());
125
+
126
+ function toggleCardSelection(i: number) {
127
+ const next = new Set(selectedCardIndexes.value);
128
+ next.has(i) ? next.delete(i) : next.add(i);
129
+ selectedCardIndexes.value = next;
130
+ }
131
+
132
+ const cartItems = computed(() => rateCards.value.filter((_: any, i: number) => selectedCardIndexes.value.has(i)));
133
+ const cartTotal = computed(() => cartItems.value.reduce((sum: number, c: any) => sum + Number(c.price_min || 0), 0));
134
+ const cartCurrency = computed(() => cartItems.value[0]?.currency || 'BRL');
135
+
136
+ const sendingProposal = ref(false);
137
+
138
+ async function submitBundleProposal(bundle: any) {
139
+ await submitProposal({
140
+ title: `${t('kit.media.rates_bundle_proposal_title')}: ${bundle.name}`,
141
+ amount: Number(bundle.bundle_price || 0),
142
+ currency: bundle.currency || 'BRL',
143
+ deliverables: (bundle.rate_cards || []).map((i: any) => ({ title: i.label, description: `${i.quantity || 1}x` })),
144
+ });
145
+ }
146
+
147
+ async function submitCartProposal() {
148
+ if (!cartItems.value.length) return;
149
+ await submitProposal({
150
+ title: t('kit.media.rates_custom_proposal_title'),
151
+ amount: cartTotal.value,
152
+ currency: cartCurrency.value,
153
+ deliverables: cartItems.value.map((c: any) => ({ title: c.label, description: c.content_format || c.ad_channel })),
154
+ });
155
+ }
156
+
157
+ async function submitProposal(opts: { title: string; amount: number; currency: string; deliverables: { title: string; description?: string }[] }) {
158
+ if (!influencerProId.value) return;
159
+
160
+ if (!authStore.user?.id) {
161
+ const returnTo = useRequestURL().href;
162
+ navigateTo(localePath(`/login?redirect=${encodeURIComponent(returnTo)}`));
163
+ return;
164
+ }
165
+
166
+ sendingProposal.value = true;
167
+ try {
168
+ await sendMediaKitProposal({
169
+ receiverInfluencerProId: influencerProId.value,
170
+ senderUserId: authStore.user.id,
171
+ title: opts.title,
172
+ proposedAmount: opts.amount,
173
+ currency: opts.currency,
174
+ deliverables: opts.deliverables,
175
+ });
176
+ toast.success(t('kit.media.proposal_sent'));
177
+ selectedCardIndexes.value = new Set();
178
+ track('contact');
179
+ } catch (err) {
180
+ toast.error(t('kit.media.proposal_error'));
181
+ } finally {
182
+ sendingProposal.value = false;
183
+ }
184
+ }
185
+
57
186
  // SSR-safe fetch so bots/link-preview scrapers (which don't run JS) get the
58
187
  // real creator data for the SEO tags below, instead of the site-wide default.
59
188
  const { data: ssrKitData } = await useAsyncData(
60
189
  `media-kit-${slug.value}`,
61
190
  () => fetchPublicMediaKit(slug.value).then(r => r.data?.data || r.data).catch(() => null),
62
191
  );
63
- if (ssrKitData.value) kit.value = ssrKitData.value;
64
- else error.value = true;
192
+ if (ssrKitData.value) {
193
+ kit.value = ssrKitData.value;
194
+ activeTab.value = TEMPLATE_DEFAULT_TAB[kit.value?.template || 'creator'] ?? 0;
195
+ } else {
196
+ error.value = true;
197
+ }
65
198
  loading.value = false;
66
199
 
67
200
  onMounted(() => {
68
201
  if (kit.value?.user_id) {
69
202
  trackMediaKitEvent(kit.value.user_id, { type: 'view', referrer: document.referrer || undefined }).catch(() => {});
70
203
  }
204
+ if (cfg.isAgencyHost) {
205
+ shortlist.hydrate();
206
+ }
71
207
  });
72
208
 
73
209
  const requestUrl = useRequestURL();
@@ -119,204 +255,303 @@ function onDownload() {
119
255
  <div v-else-if="error || !kit" class="kit-state"><p>{{ $t('kit.media.not_available') }}</p></div>
120
256
 
121
257
  <template v-else>
122
- <div class="mk-cover" :class="{ 'has-image': coverUrl }" :style="coverStyle" />
258
+ <div class="mk-cover" :class="{ 'has-image': coverUrl }" :style="coverStyle">
259
+ <span v-if="!coverUrl" class="mk-cover-brand">MUNDO GAMER AGENCY</span>
260
+ </div>
123
261
 
124
- <div class="kit-wrap mk-sections">
125
- <header class="mk-header">
262
+ <div class="kit-wrap mk-layout">
263
+ <!-- ══════════════ SIDEBAR ══════════════ -->
264
+ <aside class="mk-sidebar">
126
265
  <img v-if="streamer.avatar" class="mk-avatar" :src="streamer.avatar" :alt="streamer.name" />
127
266
  <div v-else class="mk-avatar mk-avatar-ph" />
128
267
 
129
- <div class="mk-hid">
130
- <h1>{{ streamer.name }}</h1>
131
- <p v-if="streamer.custom_headline" class="mk-headline">{{ streamer.custom_headline }}</p>
132
- <div class="mk-badges">
133
- <span v-if="streamer.platform" class="mk-badge plat">{{ streamer.platform }}</span>
134
- <span v-if="streamer.tier && streamer.tier !== 'free'" class="mk-badge tier">{{ String(streamer.tier).toUpperCase() }}</span>
135
- <span v-if="streamer.slug" class="mk-badge loc">@{{ streamer.slug }}</span>
136
- </div>
137
- <p v-if="streamer.bio" class="mk-bio">{{ streamer.bio }}</p>
268
+ <h1 class="mk-name">{{ streamer.name }}</h1>
269
+ <p v-if="streamer.custom_headline" class="mk-headline">{{ streamer.custom_headline }}</p>
270
+ <p v-if="streamer.slug" class="mk-handle">@{{ streamer.slug }}</p>
271
+
272
+ <div class="mk-badges">
273
+ <span v-if="streamer.platform" class="mk-badge plat">{{ streamer.platform }}</span>
274
+ <span v-if="streamer.tier && streamer.tier !== 'free'" class="mk-badge tier">{{ String(streamer.tier).toUpperCase() }}</span>
275
+ </div>
276
+
277
+ <div v-if="showShortlistBar" class="mk-internal-bar no-print">
278
+ <button class="kit-btn" :class="inShortlist ? 'kit-btn-primary' : 'kit-btn-ghost'" @click="toggleShortlist">
279
+ {{ inShortlist ? $t('kit.media.shortlist_remove') : $t('kit.media.shortlist_add') }}
280
+ </button>
281
+ <a v-if="shortlist.count" class="kit-btn kit-btn-ghost" :href="campaignWizardUrl" target="_blank" rel="noopener">
282
+ {{ $t('kit.media.go_to_campaign') }} ({{ shortlist.count }})
283
+ </a>
138
284
  </div>
139
285
 
140
286
  <div class="mk-actions no-print">
141
287
  <a class="kit-btn kit-btn-primary" @click="onDownload">{{ $t('kit.media.download_pdf') }}</a>
142
288
  <a v-if="streamer.contact_email" class="kit-btn kit-btn-ghost" :href="`mailto:${streamer.contact_email}`" @click="track('contact')">{{ $t('kit.media.contact') }}</a>
143
289
  </div>
144
- </header>
145
-
146
- <!-- Personal link hub: replaces a separate link-in-bio service. -->
147
- <nav class="mk-link-hub no-print" data-sec="links" :aria-label="$t('kit.media.quick_links')">
148
- <a v-for="(link, index) in customLinks" :key="`${link.url}-${index}`" class="mk-link" :class="{ 'mk-link--primary': index === 0 }" :href="link.url" target="_blank" rel="noopener" @click="track('click')">
149
- <span>{{ link.label }}</span><b>↗</b>
150
- </a>
151
- <a v-if="streamer.contact_email" class="mk-link mk-link--primary" :href="`mailto:${streamer.contact_email}`" @click="track('contact')">
152
- <span>{{ $t('kit.media.work_with_me') }}</span><b>↗</b>
153
- </a>
154
- <a v-if="creatorStore" class="mk-link" href="#store" @click="track('click')">
155
- <span>{{ $t('kit.media.visit_store') }}</span><b>↓</b>
156
- </a>
157
- <a v-if="userId" class="mk-link" href="#support" @click="track('click')">
158
- <span>{{ $t('kit.media.visit_mural') }}</span><b>↓</b>
159
- </a>
160
- <a v-for="s in socials" :key="s.platform" class="mk-link mk-link--social" :href="s.url" target="_blank" rel="noopener" @click="track('click')">
161
- <span>{{ PLATFORM_LABEL[s.platform] || s.platform }}</span><b>↗</b>
162
- </a>
163
- </nav>
164
-
165
- <!-- Reach / multi-platform followers -->
166
- <section v-if="platforms.length" class="kit-block" data-sec="reach">
167
- <h2>{{ $t('kit.media.reach') }}</h2>
168
- <p v-if="totalFollowers" class="mk-total-reach">{{ fmt(totalFollowers) }} <span>{{ $t('kit.media.total_reach') }}</span></p>
169
- <div class="mk-platforms">
170
- <a v-for="p in platforms" :key="p.platform" class="mk-platform" :href="p.url || undefined" target="_blank" rel="noopener" @click="track('click')">
171
- <div class="pl-head">
172
- <span class="pl-name">{{ PLATFORM_LABEL[p.platform] || p.platform }}</span>
173
- <span v-if="p.verified" class="pl-verified" :title="$t('kit.media.verified')">✓</span>
174
- </div>
175
- <div class="pl-followers">{{ fmt(p.followers) }}</div>
176
- <div class="pl-meta">
177
- <span v-if="p.engagement_rate != null">{{ p.engagement_rate }}% {{ $t('kit.media.eng_short') }}</span>
178
- <span v-if="p.avg_views != null">{{ fmt(p.avg_views) }} {{ $t('kit.media.views_short') }}</span>
179
- </div>
180
- </a>
290
+
291
+ <div v-if="totalFollowers" class="mk-sb-stat">
292
+ <span class="n">{{ fmt(totalFollowers) }}</span>
293
+ <span class="l">{{ $t('kit.media.total_reach') }}</span>
181
294
  </div>
182
- </section>
183
295
 
184
- <!-- Mundo Gamer creator store -->
185
- <section v-if="creatorStore" id="store" class="kit-block kit-card mk-store-block" data-sec="store">
186
- <MgMediaKitStore :store="creatorStore" :contact-email="streamer.contact_email" @click="track('click')" />
187
- </section>
296
+ <!-- Personal link hub: replaces a separate link-in-bio service. -->
297
+ <nav v-if="customLinks.length || tvChannelUrl || websiteUrl || creatorStore || hasMural" class="mk-link-hub no-print" data-sec="links" :aria-label="$t('kit.media.quick_links')">
298
+ <a v-if="tvChannelUrl" class="mk-link mk-link--tv" :href="tvChannelUrl" target="_blank" rel="noopener" @click="track('click')">
299
+ <span>{{ $t('kit.media.tv_channel') }}</span><b>↗</b>
300
+ </a>
301
+ <a v-if="websiteUrl" class="mk-link" :href="websiteUrl" target="_blank" rel="noopener" @click="track('click')">
302
+ <span>{{ $t('kit.media.official_site') }}</span><b>↗</b>
303
+ </a>
304
+ <a v-for="(link, index) in customLinks" :key="`${link.url}-${index}`" class="mk-link" :href="link.url" target="_blank" rel="noopener" @click="track('click')">
305
+ <span>{{ link.label }}</span><b>↗</b>
306
+ </a>
307
+ <a v-if="creatorStore" class="mk-link" href="#store" @click="track('click')">
308
+ <span>{{ $t('kit.media.visit_store') }}</span><b>↓</b>
309
+ </a>
310
+ <a v-if="hasMural" class="mk-link" href="#support" @click="track('click')">
311
+ <span>{{ $t('kit.media.visit_mural') }}</span><b>↓</b>
312
+ </a>
313
+ </nav>
188
314
 
189
- <!-- Creator-selected portfolio and brand imagery -->
190
- <section v-if="portfolioImages.length || brandLogos.length" class="kit-block" data-sec="portfolio">
191
- <h2>{{ $t('kit.media.portfolio') }}</h2>
192
- <div v-if="portfolioImages.length" class="mk-portfolio">
193
- <a v-for="(image, index) in portfolioImages" :key="image" :href="image" target="_blank" rel="noopener" @click="track('click')">
194
- <img :src="image" :alt="`${streamer.name} — ${index + 1}`" />
315
+ <div v-if="socials.length" class="mk-socials no-print">
316
+ <a v-for="s in socials" :key="s.platform" class="mk-soc" :href="s.url" target="_blank" rel="noopener" :title="PLATFORM_LABEL[s.platform] || s.platform" @click="track('click')">
317
+ {{ (PLATFORM_LABEL[s.platform] || s.platform).slice(0, 2).toUpperCase() }}
195
318
  </a>
196
319
  </div>
197
- <div v-if="brandLogos.length" class="mk-brand-logos">
198
- <img v-for="logo in brandLogos" :key="logo" :src="logo" :alt="$t('kit.media.partner_brand')" />
320
+ </aside>
321
+
322
+ <!-- ══════════════ MAIN: TABS ══════════════ -->
323
+ <main class="mk-main">
324
+ <div class="mk-tabs no-print">
325
+ <button class="mk-tab" :class="{ active: activeTab === 0 }" @click="activeTab = 0">{{ $t('kit.media.tab_profile') }}</button>
326
+ <button v-if="hasRatesTab" class="mk-tab" :class="{ active: activeTab === 1 }" @click="activeTab = 1">{{ $t('kit.media.tab_rates') }}</button>
327
+ <button v-if="hasPerformanceTab" class="mk-tab" :class="{ active: activeTab === 2 }" @click="activeTab = 2">{{ $t('kit.media.tab_performance') }}</button>
199
328
  </div>
200
- </section>
201
329
 
202
- <!-- TV streaming metrics -->
203
- <section v-if="stats" class="kit-block" data-sec="metrics">
204
- <h2>{{ $t('kit.media.key_metrics') }}</h2>
205
- <p v-if="period" class="mk-period">{{ $t('kit.media.last_days', { days: period.days }) }} · {{ period.start }} — {{ period.end }}</p>
206
- <div class="mk-metrics">
207
- <div class="mk-metric"><div class="val accent">{{ fmt(stats.total_followers) }}</div><div class="lab">{{ $t('kit.media.followers') }}</div></div>
208
- <div class="mk-metric"><div class="val">{{ fmt(stats.avg_viewers) }}</div><div class="lab">{{ $t('kit.media.avg_viewers') }}</div></div>
209
- <div class="mk-metric"><div class="val">{{ fmt(stats.peak_viewers) }}</div><div class="lab">{{ $t('kit.media.peak_viewers') }}</div></div>
210
- <div class="mk-metric"><div class="val">{{ stats.streams_per_week }}</div><div class="lab">{{ $t('kit.media.streams_week') }}</div></div>
211
- <div class="mk-metric"><div class="val">{{ fmt(stats.total_streams_90d) }}</div><div class="lab">{{ $t('kit.media.total_streams') }}</div></div>
212
- <div class="mk-metric"><div class="val">{{ stats.total_hours_90d }}h</div><div class="lab">{{ $t('kit.media.hours') }}</div></div>
213
- <div class="mk-metric"><div class="val accent">+{{ fmt(stats.new_followers_90d) }}</div><div class="lab">{{ $t('kit.media.new_followers') }}</div></div>
214
- <div class="mk-metric"><div class="val">{{ fmt(stats.total_chat_messages) }}</div><div class="lab">{{ $t('kit.media.chat') }}</div></div>
215
- </div>
216
- </section>
330
+ <!-- ── TAB: PERFIL ── -->
331
+ <div class="mk-tabpanel" :class="{ active: activeTab === 0 }" data-print-tab="profile">
332
+ <p v-if="streamer.bio" class="mk-bio">{{ streamer.bio }}</p>
217
333
 
218
- <!-- Audience demographics -->
219
- <section v-if="demographics" class="kit-block" data-sec="audience">
220
- <h2>{{ $t('kit.media.audience') }}</h2>
221
- <div class="mk-cols2">
222
- <div v-if="demographics.age_ranges?.length" class="kit-card mk-pad">
223
- <h3>{{ $t('kit.media.age') }}</h3>
224
- <div v-for="a in demographics.age_ranges" :key="a.label" class="mk-bar">
225
- <div class="top"><span>{{ a.label }}</span><b>{{ a.percent }}%</b></div>
226
- <div class="mk-track"><div class="mk-fill" :style="{ width: a.percent + '%' }" /></div>
334
+ <section v-if="academyMentor" class="kit-block" data-sec="academy">
335
+ <h2>{{ $t('kit.media.academy_mentor_title') }}</h2>
336
+ <div class="mk-mentor-badge">
337
+ 🎓 {{ $t('kit.media.academy_mentor_label') }} · <b>{{ academyMentor.creator_title }}</b>
338
+ <span v-if="academyMentor.game">— {{ academyMentor.game }}</span>
339
+ <span class="mk-mentor-stats">
340
+ {{ academyMentor.total_students }} {{ $t('kit.media.academy_students') }} · {{ academyMentor.avg_rating.toFixed(1) }}★
341
+ </span>
227
342
  </div>
228
- </div>
229
- <div v-if="demographics.gender" class="kit-card mk-pad">
230
- <h3>{{ $t('kit.media.gender_regions') }}</h3>
231
- <div class="mk-gender">
232
- <div v-for="(v, k) in demographics.gender" :key="k" class="g">
233
- <div class="pct">{{ v }}%</div>
234
- <div class="lb">{{ k }}</div>
235
- </div>
343
+ </section>
344
+
345
+ <section v-if="platforms.length" class="kit-block" data-sec="reach">
346
+ <h2>{{ $t('kit.media.reach') }}</h2>
347
+ <div class="mk-platforms">
348
+ <a v-for="p in platforms" :key="p.platform" class="mk-platform" :href="p.url || undefined" target="_blank" rel="noopener" @click="track('click')">
349
+ <div class="pl-head">
350
+ <span class="pl-name">{{ PLATFORM_LABEL[p.platform] || p.platform }}</span>
351
+ <span v-if="p.verified" class="pl-verified" :title="$t('kit.media.verified')">✓</span>
352
+ </div>
353
+ <div class="pl-followers">{{ fmt(p.followers) }}</div>
354
+ <div class="pl-meta">
355
+ <span v-if="p.engagement_rate != null">{{ p.engagement_rate }}% {{ $t('kit.media.eng_short') }}</span>
356
+ <span v-if="p.avg_views != null">{{ fmt(p.avg_views) }} {{ $t('kit.media.views_short') }}</span>
357
+ </div>
358
+ </a>
236
359
  </div>
237
- <div v-if="demographics.top_countries?.length" class="mk-countries">
238
- <div v-for="c in demographics.top_countries" :key="c.code" class="mk-bar">
239
- <div class="top"><span>{{ c.label }}</span><b>{{ c.percent }}%</b></div>
360
+ </section>
361
+
362
+ <section v-if="audienceGeo.length" class="kit-block" data-sec="geo">
363
+ <h2>{{ $t('kit.media.audience_geo') }}</h2>
364
+ <div class="mk-geo">
365
+ <div v-for="c in audienceGeo" :key="c.isocode" class="mk-bar">
366
+ <div class="top">
367
+ <span><img v-if="c.flag_url" :src="c.flag_url" class="mk-flag" :alt="c.name">{{ c.name }}</span>
368
+ <b>{{ c.percent }}%</b>
369
+ </div>
240
370
  <div class="mk-track"><div class="mk-fill" :style="{ width: c.percent + '%' }" /></div>
241
371
  </div>
242
372
  </div>
243
- </div>
244
- </div>
245
- </section>
373
+ </section>
374
+
375
+ <section v-if="demographics" class="kit-block" data-sec="audience">
376
+ <h2>{{ $t('kit.media.audience') }}</h2>
377
+ <div class="mk-cols2">
378
+ <div v-if="demographics.age_ranges?.length" class="kit-card mk-pad">
379
+ <h3>{{ $t('kit.media.age') }}</h3>
380
+ <div v-for="a in demographics.age_ranges" :key="a.label" class="mk-bar">
381
+ <div class="top"><span>{{ a.label }}</span><b>{{ a.percent }}%</b></div>
382
+ <div class="mk-track"><div class="mk-fill" :style="{ width: a.percent + '%' }" /></div>
383
+ </div>
384
+ </div>
385
+ <div v-if="demographics.gender" class="kit-card mk-pad">
386
+ <h3>{{ $t('kit.media.gender_regions') }}</h3>
387
+ <div class="mk-gender">
388
+ <div v-for="(v, k) in demographics.gender" :key="k" class="g">
389
+ <div class="pct">{{ v }}%</div>
390
+ <div class="lb">{{ k }}</div>
391
+ </div>
392
+ </div>
393
+ </div>
394
+ </div>
395
+ </section>
246
396
 
247
- <!-- Content styles / niches -->
248
- <section v-if="styles.length" class="kit-block" data-sec="styles">
249
- <h2>{{ $t('kit.media.styles') }}</h2>
250
- <div class="mk-tags">
251
- <span v-for="(s, i) in styles" :key="i" class="mk-tag" :class="{ on: i < 4 }">{{ s }}</span>
252
- </div>
253
- </section>
397
+ <section v-if="styles.length" class="kit-block" data-sec="styles">
398
+ <h2>{{ $t('kit.media.styles') }}</h2>
399
+ <div class="mk-tags">
400
+ <span v-for="(s, i) in styles" :key="i" class="mk-tag" :class="{ on: i < 4 }">{{ s }}</span>
401
+ </div>
402
+ </section>
254
403
 
255
- <!-- Top games (TV streamers) -->
256
- <section v-if="topGames.length" class="kit-block" data-sec="games">
257
- <h2>{{ $t('kit.media.top_games') }}</h2>
258
- <div class="mk-games">
259
- <div v-for="g in topGames" :key="g.game" class="mk-game">
260
- <span class="nm">{{ g.game }}</span>
261
- <span class="st">
262
- <span>{{ g.hours }}h</span>
263
- <span>{{ g.avg_viewers }} {{ $t('kit.media.avg_short') }}</span>
264
- </span>
265
- </div>
266
- </div>
267
- </section>
404
+ <section v-if="selectedGames.length" class="kit-block" data-sec="selected-games">
405
+ <h2>{{ $t('kit.media.selected_games') }}</h2>
406
+ <div class="mk-tags">
407
+ <span v-for="(g, i) in selectedGames" :key="i" class="mk-tag">{{ g }}</span>
408
+ </div>
409
+ </section>
410
+
411
+ <section v-if="platformsPlayed.length" class="kit-block" data-sec="platforms-played">
412
+ <h2>{{ $t('kit.media.platforms_played') }}</h2>
413
+ <div class="mk-platforms-played">
414
+ <div v-for="p in platformsPlayed" :key="p.id" class="mk-plat-box">
415
+ <img v-if="p.icon_url" :src="p.icon_url" :alt="p.name">
416
+ <span class="lb">{{ p.name }}</span>
417
+ </div>
418
+ </div>
419
+ </section>
420
+
421
+ <section v-if="topGames.length" class="kit-block" data-sec="games">
422
+ <h2>{{ $t('kit.media.top_games') }}</h2>
423
+ <div class="mk-games">
424
+ <div v-for="g in topGames" :key="g.game" class="mk-game">
425
+ <span class="nm">{{ g.game }}</span>
426
+ <span class="st">
427
+ <span>{{ g.hours }}h</span>
428
+ <span>{{ g.avg_viewers }} {{ $t('kit.media.avg_short') }}</span>
429
+ </span>
430
+ </div>
431
+ </div>
432
+ </section>
268
433
 
269
- <!-- Rate cards & bundles (premium) -->
270
- <section v-if="rateCards.length || bundles.length" class="kit-block" data-sec="rates">
271
- <h2>{{ $t('kit.media.rates') }}</h2>
272
- <div v-if="rateCards.length" class="mk-rates">
273
- <div v-for="(r, i) in rateCards" :key="i" class="mk-rate">
274
- <div class="fmt">{{ r.content_format || r.ad_channel }}</div>
275
- <div class="lb">{{ r.label }}</div>
276
- <div class="price">{{ r.currency }} {{ r.price_min }}<span v-if="r.price_max">–{{ r.price_max }}</span></div>
277
- <div v-if="r.delivery_time_days" class="dl">{{ $t('kit.media.delivery', { d: r.delivery_time_days }) }}</div>
278
- </div>
434
+ <section v-if="brands.length" class="kit-block" data-sec="brands">
435
+ <h2>{{ $t('kit.media.brands') }}</h2>
436
+ <div class="mk-brands">
437
+ <div v-for="(b, i) in brands" :key="i" class="mk-brand">{{ b.name || b }}</div>
438
+ </div>
439
+ </section>
440
+
441
+ <section v-if="portfolioImages.length || brandLogos.length" class="kit-block" data-sec="portfolio">
442
+ <h2>{{ $t('kit.media.portfolio') }}</h2>
443
+ <div v-if="portfolioImages.length" class="mk-portfolio">
444
+ <a v-for="(image, index) in portfolioImages" :key="image" :href="image" target="_blank" rel="noopener" @click="track('click')">
445
+ <img :src="image" :alt="`${streamer.name} — ${index + 1}`" />
446
+ </a>
447
+ </div>
448
+ <div v-if="brandLogos.length" class="mk-brand-logos">
449
+ <img v-for="logo in brandLogos" :key="logo" :src="logo" :alt="$t('kit.media.partner_brand')" />
450
+ </div>
451
+ </section>
279
452
  </div>
280
- <div v-if="bundles.length" class="mk-bundles">
281
- <div v-for="(b, i) in bundles" :key="i" class="mk-bundle">
282
- <span v-if="b.discount_percent" class="off">-{{ b.discount_percent }}%</span>
283
- <div class="bn">{{ b.name }}</div>
284
- <div v-if="b.description" class="bd">{{ b.description }}</div>
285
- <ul v-if="b.rate_cards?.length" class="bundle-items">
286
- <li v-for="(it, j) in b.rate_cards" :key="j"><b>{{ it.quantity || 1 }}×</b> {{ it.label }}</li>
287
- </ul>
288
- <div class="bp">{{ b.currency }} {{ b.bundle_price }} <s v-if="b.original_price">{{ b.original_price }}</s></div>
453
+
454
+ <!-- ── TAB: RATE CARDS ── -->
455
+ <div v-if="hasRatesTab" class="mk-tabpanel" :class="{ active: activeTab === 1 }" data-print-tab="rates">
456
+ <div class="mk-rc-layout">
457
+ <div class="mk-rc-main">
458
+ <div v-if="bundles.length" class="mk-rc-group">
459
+ <h2>{{ $t('kit.media.rates_bundles') }}</h2>
460
+ <div v-for="(b, i) in bundles" :key="i" class="mk-rc-item">
461
+ <div class="mk-rc-info">
462
+ <span v-if="b.discount_percent" class="off">-{{ b.discount_percent }}%</span>
463
+ <div class="mk-rc-title">{{ b.name }}</div>
464
+ <p v-if="b.description" class="mk-rc-desc">{{ b.description }}</p>
465
+ </div>
466
+ <div class="mk-rc-side">
467
+ <div class="mk-rc-price">{{ b.currency }} {{ b.bundle_price }}</div>
468
+ <button class="mk-rc-add" :disabled="sendingProposal" @click="submitBundleProposal(b)">{{ $t('kit.media.rates_send_proposal') }}</button>
469
+ </div>
470
+ </div>
471
+ </div>
472
+
473
+ <div v-if="rateCards.length" class="mk-rc-group">
474
+ <h2>{{ $t('kit.media.rates_individual') }}</h2>
475
+ <div v-for="(r, i) in rateCards" :key="i" class="mk-rc-item">
476
+ <input type="checkbox" class="mk-rc-check" :checked="selectedCardIndexes.has(i)" @change="toggleCardSelection(i)">
477
+ <div class="mk-rc-info">
478
+ <div class="fmt">{{ r.content_format || r.ad_channel }}</div>
479
+ <div class="mk-rc-title">{{ r.label }}</div>
480
+ </div>
481
+ <div class="mk-rc-side">
482
+ <div class="mk-rc-price">{{ r.currency }} {{ r.price_min }}<span v-if="r.price_max">–{{ r.price_max }}</span></div>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ </div>
487
+
488
+ <aside v-if="rateCards.length" class="mk-rc-summary no-print">
489
+ <h3>{{ $t('kit.media.rates_your_package') }}</h3>
490
+ <template v-if="cartItems.length">
491
+ <div v-for="(c, i) in cartItems" :key="i" class="mk-rc-summary-line"><span>{{ c.label }}</span><span>{{ c.currency }} {{ c.price_min }}</span></div>
492
+ <div class="mk-rc-summary-total"><span>{{ $t('common.total') }}</span><span>{{ cartCurrency }} {{ cartTotal }}</span></div>
493
+ <button class="kit-btn kit-btn-primary" style="width:100%;" :disabled="sendingProposal" @click="submitCartProposal">{{ $t('kit.media.rates_send_proposal') }}</button>
494
+ </template>
495
+ <p v-else class="mk-rc-summary-hint">{{ $t('kit.media.rates_pick_hint') }}</p>
496
+ <p class="mk-rc-summary-hint">{{ $t('kit.media.rates_login_hint') }}</p>
497
+ </aside>
289
498
  </div>
290
499
  </div>
291
- </section>
292
500
 
293
- <!-- Partner brands -->
294
- <section v-if="brands.length" class="kit-block" data-sec="brands">
295
- <h2>{{ $t('kit.media.brands') }}</h2>
296
- <div class="mk-brands">
297
- <div v-for="(b, i) in brands" :key="i" class="mk-brand">{{ b.name || b }}</div>
501
+ <!-- ── TAB: PERFORMANCE ── -->
502
+ <div v-if="hasPerformanceTab" class="mk-tabpanel" :class="{ active: activeTab === 2 }" data-print-tab="performance">
503
+ <section v-if="stats" class="kit-block" data-sec="metrics">
504
+ <h2>{{ $t('kit.media.key_metrics') }}</h2>
505
+ <p v-if="period" class="mk-period">{{ $t('kit.media.last_days', { days: period.days }) }} · {{ period.start }} — {{ period.end }}</p>
506
+ <div class="mk-metrics">
507
+ <div class="mk-metric"><div class="val accent">{{ fmt(stats.total_followers) }}</div><div class="lab">{{ $t('kit.media.followers') }}</div></div>
508
+ <div class="mk-metric"><div class="val">{{ fmt(stats.avg_viewers) }}</div><div class="lab">{{ $t('kit.media.avg_viewers') }}</div></div>
509
+ <div class="mk-metric"><div class="val">{{ fmt(stats.peak_viewers) }}</div><div class="lab">{{ $t('kit.media.peak_viewers') }}</div></div>
510
+ <div class="mk-metric"><div class="val">{{ stats.streams_per_week }}</div><div class="lab">{{ $t('kit.media.streams_week') }}</div></div>
511
+ <div class="mk-metric"><div class="val">{{ fmt(stats.total_streams_90d) }}</div><div class="lab">{{ $t('kit.media.total_streams') }}</div></div>
512
+ <div class="mk-metric"><div class="val">{{ stats.total_hours_90d }}h</div><div class="lab">{{ $t('kit.media.hours') }}</div></div>
513
+ <div class="mk-metric"><div class="val accent">+{{ fmt(stats.new_followers_90d) }}</div><div class="lab">{{ $t('kit.media.new_followers') }}</div></div>
514
+ <div class="mk-metric"><div class="val">{{ fmt(stats.total_chat_messages) }}</div><div class="lab">{{ $t('kit.media.chat') }}</div></div>
515
+ </div>
516
+ </section>
517
+
518
+ <section v-if="communityStats" class="kit-block" data-sec="community">
519
+ <h2>{{ $t('kit.media.community_title') }}</h2>
520
+ <div class="mk-cross-card">
521
+ <span class="mk-cross-badge">Community</span>
522
+ <div class="mk-cross-row"><span>{{ $t('kit.media.community_memberships') }}</span><b>{{ communityStats.communities }}</b></div>
523
+ <div class="mk-cross-row"><span>{{ $t('kit.media.community_posts_30d') }}</span><b>{{ communityStats.posts_30d }}</b></div>
524
+ </div>
525
+ </section>
526
+
527
+ <section v-if="schedule.length" class="kit-block" data-sec="schedule">
528
+ <h2>{{ $t('kit.media.schedule') }}</h2>
529
+ <div class="mk-schedule">
530
+ <div v-for="d in scheduleByDay" :key="d.d" class="mk-day" :class="{ on: d.slot }">
531
+ <div class="dn">{{ $t(d.key) }}</div>
532
+ <div v-if="d.slot" class="hr">{{ d.slot.start_time }}</div>
533
+ <div v-else class="off">—</div>
534
+ </div>
535
+ </div>
536
+ </section>
298
537
  </div>
299
- </section>
538
+ </main>
539
+ </div>
300
540
 
301
- <!-- Weekly schedule -->
302
- <section v-if="schedule.length" class="kit-block" data-sec="schedule">
303
- <h2>{{ $t('kit.media.schedule') }}</h2>
304
- <div class="mk-schedule">
305
- <div v-for="d in scheduleByDay" :key="d.d" class="mk-day" :class="{ on: d.slot }">
306
- <div class="dn">{{ $t(d.key) }}</div>
307
- <div v-if="d.slot" class="hr">{{ d.slot.start_time }}</div>
308
- <div v-else class="off">—</div>
309
- </div>
310
- </div>
541
+ <!-- ══════════════ Full-width: Store + Mural (real embedded widgets, not tabbed) ══════════════ -->
542
+ <div class="kit-wrap mk-below-tabs">
543
+ <section v-if="creatorStore" id="store" class="kit-block kit-card mk-store-block" data-sec="store">
544
+ <MgMediaKitStore :store="creatorStore" :contact-email="streamer.contact_email" @click="track('click')" />
311
545
  </section>
312
546
 
313
- <!-- IndieWall / mural — self-contained widget (own fetch, realtime, stepper) -->
314
547
  <section v-if="userId" id="support" class="kit-block" data-sec="support">
315
- <MediaKitWallBlock :user-id="userId" />
548
+ <MediaKitWallBlock :user-id="userId" @wall-status="hasMural = $event" />
316
549
  </section>
317
550
 
318
551
  <footer class="mk-footer">
319
- {{ $t('kit.media.generated') }} <strong>Mundo Gamer</strong> · {{ kit.generated_at?.slice(0, 10) }}
552
+ <p v-if="!isPremium" class="kit-footer__text">{{ $t('kit.press.made_with') }} <strong>Mundo Gamer Agency</strong></p>
553
+ <a v-if="!isPremium" :href="`${agencyBase}/dashboard/media-kit`" target="_blank" rel="noopener" class="kit-footer__cta">{{ $t('kit.media.create_yours') }}</a>
554
+ <p class="mk-footer-meta">{{ $t('kit.media.generated') }} {{ kit.generated_at?.slice(0, 10) }}</p>
320
555
  </footer>
321
556
  </div>
322
557
  </template>
@@ -339,156 +574,158 @@ function onDownload() {
339
574
  color: var(--kit-muted);
340
575
  }
341
576
  .kit-wrap {
342
- max-width: 1100px;
577
+ max-width: 1180px;
343
578
  margin: 0 auto;
344
579
  padding: 0 24px 60px;
345
580
  }
346
581
 
347
582
  /* Cover */
348
583
  .mk-cover {
349
- height: 280px;
584
+ height: 220px;
350
585
  background: linear-gradient(120deg, var(--kit-accent-2, #6b15ac) 0%, #2a0e4e 50%, var(--kit-bg) 100%);
351
586
  background-position: center;
352
587
  background-size: cover;
353
588
  position: relative;
354
589
  border-bottom: 1px solid var(--kit-line);
355
590
 
356
- &::after {
591
+ &.has-image::after {
357
592
  content: "";
358
593
  position: absolute;
359
594
  inset: 0;
360
- background: radial-gradient(circle at 80% 20%, rgba(168, 85, 247, .35), transparent 60%);
595
+ background: linear-gradient(180deg, rgba(5, 6, 10, .04), rgba(5, 6, 10, .52));
361
596
  }
597
+ }
362
598
 
363
- &.has-image::after {
364
- background: linear-gradient(180deg, rgba(5, 6, 10, .04), rgba(5, 6, 10, .52));
599
+ .mk-cover-brand {
600
+ position: absolute;
601
+ top: 20px;
602
+ right: 24px;
603
+ font-family: 'Rajdhani', sans-serif;
604
+ font-weight: 700;
605
+ font-size: 13px;
606
+ letter-spacing: 3px;
607
+ color: rgba(255, 255, 255, .55);
608
+ pointer-events: none;
609
+
610
+ @media (max-width: 640px) {
611
+ display: none;
365
612
  }
366
613
  }
367
614
 
368
- /* Header */
369
- .mk-header {
370
- margin: -82px auto 0;
615
+ /* ── Layout: sidebar + main ── */
616
+ .mk-layout {
617
+ display: grid;
618
+ grid-template-columns: 320px 1fr;
619
+ gap: 32px;
620
+ margin-top: -80px;
371
621
  position: relative;
372
622
  z-index: 2;
623
+ align-items: start;
624
+ }
625
+ @media (max-width: 900px) {
626
+ .mk-layout { grid-template-columns: 1fr; margin-top: -60px; }
627
+ }
628
+
629
+ /* ── Sidebar ── */
630
+ .mk-sidebar {
631
+ background: var(--kit-surface);
632
+ border: 1px solid var(--kit-line);
633
+ padding: 24px;
373
634
  display: flex;
374
635
  flex-direction: column;
375
- align-items: center;
376
- max-width: 760px;
377
- text-align: center;
636
+ gap: 16px;
637
+ position: sticky;
638
+ top: 24px;
378
639
  }
640
+ @media (max-width: 900px) { .mk-sidebar { position: static; } }
641
+
379
642
  .mk-avatar {
380
- width: 156px;
381
- height: 156px;
643
+ width: 128px;
644
+ height: 128px;
645
+ border-radius: 100%;
382
646
  border: 3px solid var(--kit-accent);
383
647
  object-fit: cover;
384
- flex-shrink: 0;
385
648
  background: var(--kit-surface-2);
386
- box-shadow: 0 20px 52px rgba(0, 0, 0, .42);
387
- }
388
- .mk-avatar-ph {
389
- background: linear-gradient(135deg, var(--kit-accent-2, #6b15ac), var(--kit-accent));
649
+ box-shadow: 0 12px 32px rgba(0, 0, 0, .35);
390
650
  }
391
- .mk-hid {
392
- width: 100%;
393
- padding-top: 18px;
651
+ .mk-avatar-ph { background: linear-gradient(135deg, var(--kit-accent-2, #6b15ac), var(--kit-accent)); }
394
652
 
395
- h1 {
396
- font-family: 'Rajdhani', sans-serif;
397
- font-size: clamp(36px, 7vw, 54px);
398
- line-height: 1.05;
399
- margin: 0;
400
- }
401
- }
402
- .mk-headline {
403
- margin: 8px auto 0;
404
- max-width: 620px;
405
- color: var(--kit-accent);
406
- font-family: 'Rajdhani', sans-serif;
407
- font-size: 20px;
408
- font-weight: 600;
409
- }
410
- .mk-badges {
411
- display: flex;
412
- justify-content: center;
413
- gap: 8px;
414
- margin: 12px 0;
415
- flex-wrap: wrap;
416
- }
653
+ .mk-name { font-family: 'Rajdhani', sans-serif; font-size: 28px; line-height: 1.1; margin: 4px 0 0; }
654
+ .mk-headline { color: var(--kit-accent); font-family: 'Rajdhani', sans-serif; font-size: 15px; font-weight: 600; margin: 0; }
655
+ .mk-handle { color: var(--kit-muted); font-size: 13px; margin: 0; }
656
+
657
+ .mk-badges { display: flex; flex-wrap: wrap; gap: 6px; }
417
658
  .mk-badge {
418
659
  font-family: 'Rajdhani', sans-serif;
419
660
  font-weight: 700;
420
661
  font-size: 11px;
421
- letter-spacing: 1.5px;
662
+ letter-spacing: 1px;
422
663
  text-transform: uppercase;
423
664
  padding: 4px 10px;
424
665
 
425
666
  &.plat { background: var(--kit-surface-2); border: 1px solid var(--kit-line); }
426
667
  &.tier { background: var(--kit-accent); color: var(--kit-accent-ink); }
427
- &.loc { color: var(--kit-muted); border: 1px solid var(--kit-line); }
428
- }
429
- .mk-bio {
430
- color: #c4c4d2;
431
- font-size: 15px;
432
- line-height: 1.65;
433
- max-width: 66ch;
434
- margin: 6px auto 0;
435
668
  }
436
- .mk-actions {
669
+
670
+ .mk-internal-bar {
437
671
  display: flex;
438
- justify-content: center;
439
- flex-wrap: wrap;
440
- gap: 10px;
441
- padding-top: 18px;
672
+ flex-direction: column;
673
+ gap: 8px;
674
+ width: 100%;
675
+ padding: 12px;
676
+ border: 1px dashed var(--kit-accent);
677
+ background: rgba(253, 178, 21, .06);
442
678
  }
679
+ .mk-actions { display: flex; flex-direction: column; gap: 8px; width: 100%; }
443
680
 
444
- /* Link-in-bio hub */
445
- .mk-link-hub {
446
- display: grid;
447
- grid-template-columns: 1fr 1fr;
448
- gap: 10px;
449
- width: min(100%, 720px);
450
- margin: 30px auto 2px;
681
+ .mk-sb-stat {
682
+ display: flex;
683
+ flex-direction: column;
684
+ gap: 2px;
685
+ padding: 10px 0 10px 14px;
686
+ border-left: 4px solid var(--kit-accent);
687
+
688
+ .n { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 24px; color: var(--kit-accent); }
689
+ .l { font-size: 12px; color: var(--kit-muted); text-transform: uppercase; letter-spacing: .5px; }
451
690
  }
691
+
692
+ /* Link hub in sidebar */
693
+ .mk-link-hub { display: flex; flex-direction: column; gap: 1px; background: var(--kit-line); border: 1px solid var(--kit-line); width: 100%; }
452
694
  .mk-link {
453
695
  display: flex;
454
696
  align-items: center;
455
697
  justify-content: space-between;
456
- gap: 16px;
457
- min-height: 54px;
458
- padding: 0 18px;
459
- border: 1px solid var(--kit-line);
460
- background: color-mix(in srgb, var(--kit-surface) 92%, transparent);
698
+ gap: 10px;
699
+ padding: 10px 12px;
700
+ background: var(--kit-surface-2);
461
701
  color: var(--kit-text);
462
- font-size: 14px;
463
- font-weight: 700;
702
+ font-size: 13px;
703
+ font-weight: 600;
464
704
  text-decoration: none;
465
- transition: transform .16s ease, border-color .16s ease, background .16s ease;
466
-
467
- &:hover {
468
- transform: translateY(-2px);
469
- border-color: var(--kit-accent);
470
- background: var(--kit-surface-2);
471
- }
705
+ transition: background .15s;
472
706
 
473
- b { color: var(--kit-accent); font-size: 16px; }
474
-
475
- &--primary {
476
- grid-column: 1 / -1;
477
- background: var(--kit-accent);
478
- border-color: var(--kit-accent);
479
- color: var(--kit-accent-ink);
707
+ &:hover { background: color-mix(in srgb, var(--kit-accent) 8%, var(--kit-surface-2)); }
708
+ b { color: var(--kit-accent); }
709
+ &--tv { background: color-mix(in srgb, var(--kit-accent) 10%, var(--kit-surface-2)); }
710
+ }
480
711
 
481
- b { color: var(--kit-accent-ink); }
482
- &:hover { background: var(--kit-accent); filter: brightness(1.06); }
483
- }
712
+ .mk-socials { display: flex; flex-wrap: wrap; gap: 8px; }
713
+ .mk-soc {
714
+ width: 34px; height: 34px;
715
+ display: flex; align-items: center; justify-content: center;
716
+ border: 1px solid var(--kit-line);
717
+ color: var(--kit-muted);
718
+ font-size: 11px; font-weight: 700;
719
+ text-decoration: none;
484
720
 
485
- &--social { min-height: 46px; color: var(--kit-muted); }
721
+ &:hover { border-color: var(--kit-accent); color: var(--kit-accent); }
486
722
  }
487
723
 
488
- /* Buttons */
724
+ /* Buttons (shared) */
489
725
  .kit-btn {
490
726
  display: inline-flex;
491
727
  align-items: center;
728
+ justify-content: center;
492
729
  gap: 8px;
493
730
  font-family: 'Rajdhani', sans-serif;
494
731
  font-weight: 700;
@@ -504,6 +741,7 @@ function onDownload() {
504
741
  background: var(--kit-accent);
505
742
  color: var(--kit-accent-ink);
506
743
  &:hover { filter: brightness(1.1); }
744
+ &:disabled { opacity: .5; cursor: not-allowed; }
507
745
  }
508
746
  &.kit-btn-ghost {
509
747
  background: rgba(255, 255, 255, .04);
@@ -513,442 +751,260 @@ function onDownload() {
513
751
  }
514
752
  }
515
753
 
516
- /* Sections */
517
- .kit-block {
518
- margin-top: 44px;
519
-
520
- > h2 {
521
- font-size: 13px;
522
- letter-spacing: 3px;
523
- text-transform: uppercase;
524
- color: var(--kit-muted);
525
- font-weight: 700;
526
- margin-bottom: 16px;
527
- display: flex;
528
- align-items: center;
529
- gap: 12px;
530
-
531
- &::after {
532
- content: "";
533
- flex: 1;
534
- height: 1px;
535
- background: var(--kit-line);
536
- }
537
- }
538
- }
539
- .mk-store-block { padding: 24px; scroll-margin-top: 24px; }
540
- .mk-portfolio {
541
- display: grid;
542
- grid-template-columns: repeat(3, minmax(0, 1fr));
543
- gap: 10px;
754
+ /* ── Main / tabs ── */
755
+ .mk-main { min-width: 0; }
756
+ .mk-tabs { display: flex; border-bottom: 1px solid var(--kit-line); margin-bottom: 24px; }
757
+ .mk-tab {
758
+ font: inherit;
759
+ font-family: 'Rajdhani', sans-serif;
760
+ font-weight: 700;
761
+ font-size: 14px;
762
+ letter-spacing: .5px;
763
+ text-transform: uppercase;
764
+ padding: 12px 4px;
765
+ margin-right: 28px;
766
+ color: var(--kit-muted);
767
+ background: none;
768
+ border: none;
769
+ border-bottom: 2px solid transparent;
770
+ cursor: pointer;
771
+ appearance: none;
544
772
 
545
- a { display: block; overflow: hidden; aspect-ratio: 4 / 3; border: 1px solid var(--kit-line); background: var(--kit-surface); }
546
- img { width: 100%; height: 100%; object-fit: cover; transition: transform .2s ease; }
547
- a:hover img { transform: scale(1.03); }
773
+ &.active, &:hover { color: var(--kit-text); border-bottom-color: var(--kit-accent); }
548
774
  }
549
- .mk-brand-logos {
775
+
776
+ .mk-tabpanel { display: none; flex-direction: column; gap: 40px; }
777
+ .mk-tabpanel.active { display: flex; }
778
+
779
+ .mk-bio { font-size: 15px; line-height: 1.65; color: #c4c4d2; max-width: 64ch; margin: 0; }
780
+
781
+ /* Sections */
782
+ .kit-block > h2 {
783
+ font-size: 12px;
784
+ letter-spacing: 2px;
785
+ text-transform: uppercase;
786
+ color: var(--kit-muted);
787
+ font-weight: 700;
788
+ margin-bottom: 16px;
550
789
  display: flex;
551
790
  align-items: center;
552
- justify-content: center;
553
- flex-wrap: wrap;
554
- gap: 16px;
555
- margin-top: 16px;
556
- padding: 18px;
557
- border: 1px solid var(--kit-line);
558
- background: var(--kit-surface);
791
+ gap: 12px;
559
792
 
560
- img { width: 112px; height: 54px; object-fit: contain; filter: grayscale(1); opacity: .8; }
561
- }
562
- .mk-period {
563
- color: var(--kit-muted);
564
- font-size: 13px;
565
- margin: -8px 0 16px;
793
+ &::after { content: ""; flex: 1; height: 1px; background: var(--kit-line); }
566
794
  }
795
+ .mk-store-block { padding: 24px; scroll-margin-top: 24px; }
567
796
 
568
- /* Metrics grid */
569
- .mk-metrics {
570
- display: grid;
571
- grid-template-columns: repeat(4, 1fr);
572
- gap: 12px;
797
+ /* Academy mentor badge */
798
+ .mk-mentor-badge {
799
+ display: flex;
800
+ flex-direction: column;
801
+ gap: 4px;
802
+ padding: 12px 14px;
803
+ background: color-mix(in srgb, var(--kit-accent) 10%, transparent);
804
+ border: 1px solid color-mix(in srgb, var(--kit-accent) 35%, transparent);
805
+ font-size: 14px;
806
+
807
+ b { color: var(--kit-accent); }
808
+ .mk-mentor-stats { font-size: 12px; color: var(--kit-muted); }
573
809
  }
574
- .mk-metric {
810
+
811
+ /* Reach / platforms */
812
+ .mk-platforms { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
813
+ .mk-platform {
575
814
  background: var(--kit-surface);
576
815
  border: 1px solid var(--kit-line);
577
- padding: 20px 16px;
578
- text-align: center;
579
- position: relative;
580
- overflow: hidden;
581
-
582
- &::before {
583
- content: "";
584
- position: absolute;
585
- top: 0; left: 0;
586
- width: 100%;
587
- height: 2px;
588
- background: var(--kit-accent);
589
- }
816
+ padding: 16px;
817
+ text-decoration: none;
818
+ color: inherit;
819
+ display: flex;
820
+ flex-direction: column;
821
+ gap: 6px;
822
+ transition: border-color .15s;
590
823
 
591
- .val {
592
- font-family: 'Rajdhani', sans-serif;
593
- font-weight: 700;
594
- font-size: 30px;
595
- line-height: 1;
596
- &.accent { color: var(--kit-accent); }
597
- }
598
- .lab {
599
- font-size: 11px;
600
- text-transform: uppercase;
601
- letter-spacing: 1px;
602
- color: var(--kit-muted);
603
- margin-top: 8px;
604
- }
824
+ &:hover { border-color: var(--kit-accent); }
825
+ .pl-head { display: flex; align-items: center; justify-content: space-between; }
826
+ .pl-name { font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
827
+ .pl-verified { color: #27ae60; font-weight: 700; }
828
+ .pl-followers { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 24px; }
829
+ .pl-meta { display: flex; gap: 12px; font-size: 12px; color: var(--kit-muted); flex-wrap: wrap; }
605
830
  }
606
831
 
832
+ /* Geo */
833
+ .mk-geo { display: flex; flex-direction: column; gap: 10px; }
834
+ .mk-flag { width: 18px; height: 13px; object-fit: cover; margin-right: 8px; vertical-align: middle; }
835
+
607
836
  /* Demographics */
608
- .mk-cols2 {
609
- display: grid;
610
- grid-template-columns: 1fr 1fr;
611
- gap: 24px;
612
- }
613
- .kit-card {
614
- background: var(--kit-surface);
615
- border: 1px solid var(--kit-line);
616
- }
837
+ .mk-cols2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
838
+ .kit-card { background: var(--kit-surface); border: 1px solid var(--kit-line); }
617
839
  .mk-pad {
618
840
  padding: 20px;
619
-
620
- h3 {
621
- font-size: 14px;
622
- font-weight: 700;
623
- margin-bottom: 14px;
624
- letter-spacing: .5px;
625
- }
841
+ h3 { font-size: 14px; font-weight: 700; margin-bottom: 14px; letter-spacing: .5px; }
626
842
  }
627
843
  .mk-bar {
628
844
  margin-bottom: 12px;
629
-
630
- .top {
631
- display: flex;
632
- justify-content: space-between;
633
- font-size: 13px;
634
- margin-bottom: 5px;
635
-
636
- b { color: var(--kit-accent); font-weight: 600; }
637
- }
638
- }
639
- .mk-track {
640
- height: 8px;
641
- background: var(--kit-surface-2);
642
- }
643
- .mk-fill {
644
- height: 100%;
645
- background: linear-gradient(90deg, var(--kit-accent-2, #6b15ac), var(--kit-accent));
845
+ .top { display: flex; justify-content: space-between; align-items: center; font-size: 13px; margin-bottom: 5px; b { color: var(--kit-accent); font-weight: 600; } }
646
846
  }
847
+ .mk-track { height: 8px; background: var(--kit-surface-2); }
848
+ .mk-fill { height: 100%; background: linear-gradient(90deg, var(--kit-accent-2, #6b15ac), var(--kit-accent)); }
647
849
  .mk-gender {
648
- display: flex;
649
- gap: 16px;
650
- margin-top: 4px;
651
-
850
+ display: flex; gap: 16px; margin-top: 4px;
652
851
  .g {
653
- flex: 1;
654
- text-align: center;
655
- background: var(--kit-surface-2);
656
- border: 1px solid var(--kit-line);
657
- padding: 14px;
658
-
659
- .pct {
660
- font-family: 'Rajdhani', sans-serif;
661
- font-weight: 700;
662
- font-size: 26px;
663
- color: var(--kit-accent);
664
- }
665
- .lb {
666
- font-size: 12px;
667
- color: var(--kit-muted);
668
- text-transform: uppercase;
669
- letter-spacing: 1px;
670
- }
852
+ flex: 1; text-align: center; background: var(--kit-surface-2); border: 1px solid var(--kit-line); padding: 14px;
853
+ .pct { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 26px; color: var(--kit-accent); }
854
+ .lb { font-size: 12px; color: var(--kit-muted); text-transform: uppercase; letter-spacing: 1px; }
671
855
  }
672
856
  }
673
- .mk-countries { margin-top: 14px; }
674
857
 
675
858
  /* Tags */
676
- .mk-tags {
677
- display: flex;
678
- flex-wrap: wrap;
679
- gap: 8px;
680
- }
859
+ .mk-tags { display: flex; flex-wrap: wrap; gap: 8px; }
681
860
  .mk-tag {
682
861
  background: var(--kit-surface-2);
683
862
  border: 1px solid var(--kit-line);
684
863
  padding: 6px 13px;
685
864
  font-size: 13px;
686
865
  color: #d4d4e0;
866
+ &.on { border-color: var(--kit-accent); color: var(--kit-accent); }
867
+ }
687
868
 
688
- &.on {
689
- border-color: var(--kit-accent);
690
- color: var(--kit-accent);
691
- }
869
+ /* Platforms played */
870
+ .mk-platforms-played { display: flex; flex-wrap: wrap; gap: 1px; background: var(--kit-line); }
871
+ .mk-plat-box {
872
+ width: 96px; height: 96px;
873
+ background: var(--kit-surface);
874
+ display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
875
+ img { width: 32px; height: 32px; object-fit: contain; }
876
+ .lb { font-size: 10px; color: var(--kit-muted); text-align: center; }
692
877
  }
693
878
 
694
879
  /* Top games */
695
- .mk-games {
696
- display: flex;
697
- flex-direction: column;
698
- gap: 8px;
699
- }
880
+ .mk-games { display: flex; flex-direction: column; gap: 8px; }
700
881
  .mk-game {
701
- display: flex;
702
- align-items: center;
703
- justify-content: space-between;
704
- background: var(--kit-surface);
705
- border: 1px solid var(--kit-line);
706
- padding: 12px 16px;
707
-
882
+ display: flex; align-items: center; justify-content: space-between;
883
+ background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 12px 16px;
708
884
  .nm { font-weight: 600; }
709
885
  .st { display: flex; gap: 18px; color: var(--kit-muted); font-size: 13px; }
710
886
  }
711
887
 
712
- /* Rate cards */
713
- .mk-rates {
714
- display: grid;
715
- grid-template-columns: repeat(3, 1fr);
716
- gap: 12px;
717
- }
718
- .mk-rate {
719
- background: var(--kit-surface);
720
- border: 1px solid var(--kit-line);
721
- padding: 18px;
722
-
723
- .fmt { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-accent); font-weight: 700; }
724
- .lb { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 16px; margin: 6px 0 10px; }
725
- .price{ font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 22px; }
726
- .dl { font-size: 12px; color: var(--kit-muted); margin-top: 6px; }
727
- }
728
-
729
- /* Bundles */
730
- .mk-bundles {
731
- display: grid;
732
- grid-template-columns: 1fr 1fr;
733
- gap: 12px;
734
- margin-top: 12px;
735
- }
736
- .mk-bundle {
737
- background: linear-gradient(135deg, var(--kit-surface), var(--kit-surface-2));
738
- border: 1px solid var(--kit-accent);
739
- padding: 18px;
740
- position: relative;
741
-
742
- .off {
743
- position: absolute;
744
- top: 14px; right: 14px;
745
- background: var(--kit-accent);
746
- color: var(--kit-accent-ink);
747
- font-size: 11px;
748
- font-weight: 700;
749
- padding: 3px 9px;
750
- font-family: 'Rajdhani', sans-serif;
751
- letter-spacing: 1px;
752
- }
753
- .bn { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 17px; }
754
- .bd { font-size: 13px; color: var(--kit-muted); margin: 4px 0 10px; }
755
- .bp {
756
- font-family: 'Rajdhani', sans-serif;
757
- font-weight: 700;
758
- font-size: 24px;
759
- color: var(--kit-accent);
760
-
761
- s { color: var(--kit-muted); font-size: 15px; font-weight: 500; margin-left: 8px; }
762
- }
763
- .bundle-items {
764
- list-style: none;
765
- padding: 0;
766
- margin: 0 0 12px;
767
- display: flex;
768
- flex-direction: column;
769
- gap: 4px;
770
-
771
- li { font-size: 13px; color: #c4c4d2; }
772
- li b { color: var(--kit-accent); font-family: 'Rajdhani', sans-serif; }
773
- }
774
- }
775
-
776
888
  /* Brands */
777
- .mk-brands {
778
- display: grid;
779
- grid-template-columns: repeat(5, 1fr);
780
- gap: 10px;
781
- }
889
+ .mk-brands { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
782
890
  .mk-brand {
783
891
  aspect-ratio: 5 / 2;
784
892
  background: var(--kit-surface-2);
785
893
  border: 1px solid var(--kit-line);
786
- display: flex;
787
- align-items: center;
788
- justify-content: center;
894
+ display: flex; align-items: center; justify-content: center;
789
895
  color: var(--kit-muted);
790
- font-family: 'Rajdhani', sans-serif;
791
- font-weight: 700;
792
- font-size: 14px;
793
- letter-spacing: 1px;
896
+ font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 13px; letter-spacing: 1px;
794
897
  }
795
898
 
796
- /* Schedule */
797
- .mk-schedule {
798
- display: grid;
799
- grid-template-columns: repeat(7, 1fr);
800
- gap: 8px;
899
+ /* Portfolio */
900
+ .mk-portfolio {
901
+ display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
902
+ a { display: block; overflow: hidden; aspect-ratio: 4 / 3; border: 1px solid var(--kit-line); background: var(--kit-surface); }
903
+ img { width: 100%; height: 100%; object-fit: cover; }
801
904
  }
802
- .mk-day {
803
- background: var(--kit-surface);
804
- border: 1px solid var(--kit-line);
805
- padding: 12px 8px;
806
- text-align: center;
807
-
808
- &.on { border-color: var(--kit-accent); }
809
- &.on .dn { color: var(--kit-accent); }
810
-
811
- .dn { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
812
- .hr { font-family: 'Rajdhani', sans-serif; font-weight: 700; margin-top: 6px; font-size: 14px; }
813
- .off { color: var(--kit-muted); opacity: .4; margin-top: 6px; }
905
+ .mk-brand-logos {
906
+ display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 16px;
907
+ margin-top: 16px; padding: 18px; border: 1px solid var(--kit-line); background: var(--kit-surface);
908
+ img { width: 112px; height: 54px; object-fit: contain; filter: grayscale(1); opacity: .8; }
814
909
  }
815
910
 
816
- /* Socials */
817
- .mk-socials {
818
- display: flex;
819
- flex-wrap: wrap;
820
- gap: 10px;
911
+ /* Rate cards / builder */
912
+ .mk-rc-layout { display: grid; grid-template-columns: 1fr 260px; gap: 20px; align-items: start; }
913
+ @media (max-width: 760px) { .mk-rc-layout { grid-template-columns: 1fr; } }
914
+ .mk-rc-group { display: flex; flex-direction: column; gap: 1px; background: var(--kit-line); margin-bottom: 24px; }
915
+ .mk-rc-group > h2 {
916
+ background: var(--kit-bg);
917
+ font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: var(--kit-muted); font-weight: 700;
918
+ padding: 4px 0 12px;
919
+ }
920
+ .mk-rc-item {
921
+ display: flex; align-items: center; gap: 14px;
922
+ background: var(--kit-surface); padding: 14px 16px;
923
+ border-left: 4px solid var(--kit-muted);
924
+ }
925
+ .mk-rc-check { flex: none; width: 18px; height: 18px; accent-color: var(--kit-accent); }
926
+ .mk-rc-info {
927
+ flex: 1; min-width: 0;
928
+ .fmt { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-accent); font-weight: 700; }
929
+ }
930
+ .mk-rc-title { font-weight: 600; font-size: 15px; margin-top: 2px; }
931
+ .mk-rc-desc { font-size: 12.5px; color: var(--kit-muted); margin: 4px 0 0; }
932
+ .mk-rc-side { flex: none; text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
933
+ .mk-rc-price { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 16px; }
934
+ .mk-rc-add {
935
+ font: inherit; font-size: 11px; font-weight: 700; color: var(--kit-accent);
936
+ border: 1px solid var(--kit-accent); background: none; padding: 5px 10px; cursor: pointer;
937
+ &:hover { background: var(--kit-accent); color: var(--kit-accent-ink); }
938
+ &:disabled { opacity: .5; cursor: not-allowed; }
939
+ }
940
+ .off { background: var(--kit-accent); color: var(--kit-accent-ink); font-size: 10px; font-weight: 800; padding: 2px 6px; display: inline-block; margin-bottom: 6px; }
941
+
942
+ .mk-rc-summary { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 16px; position: sticky; top: 16px; }
943
+ .mk-rc-summary-line { display: flex; justify-content: space-between; font-size: 13px; color: #c4c4d2; padding: 6px 0; border-bottom: 1px solid var(--kit-line); }
944
+ .mk-rc-summary-total { display: flex; justify-content: space-between; font-weight: 700; font-size: 15px; padding: 10px 0; }
945
+ .mk-rc-summary-hint { font-size: 11.5px; color: var(--kit-muted); margin: 10px 0 0; line-height: 1.5; }
946
+
947
+ /* Performance tab */
948
+ .mk-metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
949
+ .mk-metric {
950
+ background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 20px 16px; text-align: center; position: relative; overflow: hidden;
951
+ &::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: var(--kit-accent); }
952
+ .val { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 30px; line-height: 1; &.accent { color: var(--kit-accent); } }
953
+ .lab { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); margin-top: 8px; }
821
954
  }
822
- .mk-soc {
823
- display: flex;
824
- align-items: center;
825
- gap: 8px;
826
- background: var(--kit-surface);
827
- border: 1px solid var(--kit-line);
828
- padding: 9px 16px;
829
- font-size: 14px;
830
- text-transform: capitalize;
831
- color: #d4d4e0;
832
- text-decoration: none;
833
- transition: border-color .15s, color .15s;
955
+ .mk-period { color: var(--kit-muted); font-size: 13px; margin: -8px 0 16px; }
834
956
 
835
- &:hover { border-color: var(--kit-accent); color: var(--kit-accent); }
836
- }
957
+ .mk-cross-card { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 18px; max-width: 340px; }
958
+ .mk-cross-badge { font-size: 10px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; padding: 3px 8px; background: var(--kit-surface-2); border: 1px solid var(--kit-line); color: var(--kit-muted); display: inline-block; margin-bottom: 12px; }
959
+ .mk-cross-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--kit-line); font-size: 13px; &:last-child { border-bottom: none; } b { color: var(--kit-accent); } }
837
960
 
838
- /* Reach / platform breakdown */
839
- .mk-total-reach {
840
- font-family: 'Rajdhani', sans-serif;
841
- font-weight: 700;
842
- font-size: 28px;
843
- color: var(--kit-accent);
844
- margin: -8px 0 16px;
845
-
846
- span {
847
- font-family: 'Inter', sans-serif;
848
- font-size: 13px;
849
- color: var(--kit-muted);
850
- font-weight: 500;
851
- text-transform: uppercase;
852
- letter-spacing: 1px;
853
- }
854
- }
855
- .mk-platforms {
856
- display: grid;
857
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
858
- gap: 12px;
961
+ .mk-schedule { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; }
962
+ .mk-day {
963
+ background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 12px 8px; text-align: center;
964
+ &.on { border-color: var(--kit-accent); .dn { color: var(--kit-accent); } }
965
+ .dn { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
966
+ .hr { font-family: 'Rajdhani', sans-serif; font-weight: 700; margin-top: 6px; font-size: 14px; }
967
+ .off { color: var(--kit-muted); opacity: .4; margin-top: 6px; }
859
968
  }
860
- .mk-platform {
861
- background: var(--kit-surface);
862
- border: 1px solid var(--kit-line);
863
- padding: 16px;
864
- text-decoration: none;
865
- color: inherit;
866
- display: flex;
867
- flex-direction: column;
868
- gap: 6px;
869
- transition: border-color .15s;
870
969
 
871
- &:hover { border-color: var(--kit-accent); }
970
+ /* Below tabs: store + mural */
971
+ .mk-below-tabs { padding-top: 48px; display: flex; flex-direction: column; gap: 48px; }
872
972
 
873
- .pl-head { display: flex; align-items: center; justify-content: space-between; }
874
- .pl-name { font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
875
- .pl-verified { color: #27ae60; font-weight: 700; }
876
- .pl-followers{ font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 24px; }
877
- .pl-meta { display: flex; gap: 12px; font-size: 12px; color: var(--kit-muted); flex-wrap: wrap; }
878
- }
879
-
880
- /* Footer */
881
973
  .mk-footer {
974
+ display: flex;
975
+ flex-direction: column;
976
+ align-items: center;
977
+ gap: 8px;
882
978
  border-top: 1px solid var(--kit-line);
883
- margin-top: 48px;
979
+ margin-top: 24px;
884
980
  padding: 24px 0;
885
981
  text-align: center;
886
- color: var(--kit-muted);
887
- font-size: 13px;
888
-
889
982
  strong { color: var(--kit-accent); font-weight: 700; }
890
983
  }
891
-
892
- /* Template ordering (layout emphasis) */
893
- .mk-sections { display: flex; flex-direction: column; }
894
- .mk-sections > .mk-header { order: 0; }
895
- .mk-sections > .mk-footer { order: 100; }
896
- .mk-sections > [data-sec="links"] { order: 1; }
897
- .mk-sections > [data-sec="reach"] { order: 2; }
898
- .mk-sections > [data-sec="store"] { order: 3; }
899
- .mk-sections > [data-sec="portfolio"] { order: 4; }
900
- .mk-sections > [data-sec="metrics"] { order: 5; }
901
- .mk-sections > [data-sec="audience"] { order: 6; }
902
- .mk-sections > [data-sec="styles"] { order: 7; }
903
- .mk-sections > [data-sec="games"] { order: 8; }
904
- .mk-sections > [data-sec="rates"] { order: 9; }
905
- .mk-sections > [data-sec="brands"] { order: 10; }
906
- .mk-sections > [data-sec="schedule"] { order: 11; }
907
- .mk-sections > [data-sec="connect"] { order: 12; }
908
- .mk-sections > [data-sec="support"] { order: 13; scroll-margin-top: 24px; }
909
-
910
- [data-template="performance"] {
911
- .mk-sections > [data-sec="metrics"] { order: 1; }
912
- .mk-sections > [data-sec="reach"] { order: 2; }
913
- .mk-sections > [data-sec="games"] { order: 3; }
914
- }
915
- [data-template="commercial"] {
916
- .mk-sections > [data-sec="reach"] { order: 1; }
917
- .mk-sections > [data-sec="rates"] { order: 2; }
918
- .mk-sections > [data-sec="brands"] { order: 3; }
919
- .mk-sections > [data-sec="metrics"] { order: 4; }
920
- }
921
- [data-template="audience"] {
922
- .mk-sections > [data-sec="reach"] { order: 1; }
923
- .mk-sections > [data-sec="audience"] { order: 2; }
924
- .mk-sections > [data-sec="styles"] { order: 3; }
925
- .mk-sections > [data-sec="metrics"] { order: 4; }
984
+ .mk-footer-meta {
985
+ color: var(--kit-muted);
986
+ font-size: 13px;
987
+ margin: 0;
926
988
  }
927
989
 
928
990
  /* Responsive */
929
991
  @media (max-width: 840px) {
930
992
  .mk-metrics { grid-template-columns: repeat(2, 1fr); }
931
- .mk-cols2, .mk-rates, .mk-bundles { grid-template-columns: 1fr; }
993
+ .mk-cols2 { grid-template-columns: 1fr; }
932
994
  .mk-brands { grid-template-columns: repeat(3, 1fr); }
933
995
  .mk-schedule { grid-template-columns: repeat(4, 1fr); }
934
996
  .mk-portfolio { grid-template-columns: 1fr 1fr; }
935
997
  }
936
-
937
998
  @media (max-width: 560px) {
938
999
  .kit-wrap { padding-inline: 14px; }
939
- .mk-cover { height: 230px; }
940
- .mk-avatar { width: 132px; height: 132px; }
941
- .mk-header { margin-top: -68px; }
942
- .mk-link-hub { grid-template-columns: 1fr; }
943
- .mk-link--primary { grid-column: auto; }
944
- .mk-actions { width: 100%; }
945
- .kit-btn { flex: 1; justify-content: center; }
946
- .mk-portfolio { grid-template-columns: 1fr; }
947
- .mk-store-block { padding: 16px; }
1000
+ .mk-cover { height: 180px; }
948
1001
  }
949
1002
 
950
1003
  @media print {
951
1004
  .no-print { display: none !important; }
1005
+ /* Tabs don't apply to print/PDF export — every panel renders so nothing
1006
+ the creator built gets silently dropped from the exported PDF. */
1007
+ .mk-tabpanel { display: flex !important; }
952
1008
  }
953
1009
 
954
1010
  // ── Scroll unlock (body has overflow-y: hidden globally in some frontends) ───