@mundogamernetwork/shared-ui 1.1.15 → 1.1.17

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.
@@ -17,7 +17,10 @@
17
17
  *
18
18
  * Props let a platform override the login base or disable dropdown positioning.
19
19
  */
20
- import { buildLoginUrl, buildRegisterUrl } from "../../utils/authRedirect";
20
+ // buildLoginUrl and buildRegisterUrl are NOT imported explicitly here because
21
+ // this file ships as raw TypeScript inside an npm package. Relative imports of
22
+ // .ts files from node_modules fail in Vite production builds (vendor chunks are
23
+ // not transpiled). Instead, the URL logic is inlined directly.
21
24
 
22
25
  const props = defineProps({
23
26
  // Override the login URL entirely (else derived from apiBaseURL host).
@@ -47,14 +50,26 @@ const systemId =
47
50
  import.meta.env.VITE_SYSTEM_ID ||
48
51
  "";
49
52
 
53
+ // URL builders inlined to avoid relative .ts imports from node_modules.
54
+ function buildUrl(base: string, path: string, params: Record<string, string>) {
55
+ const p = new URLSearchParams(params);
56
+ return `${base}/${path}?${p}`;
57
+ }
58
+
50
59
  // Computed at click time so redirect_to is always the CURRENT url.
51
60
  function goLogin() {
52
61
  if (typeof window === "undefined") return;
53
- window.location.href = props.loginUrl || buildLoginUrl(apiBase, undefined, systemId);
62
+ const redirectTo = window.location.href;
63
+ const params: Record<string, string> = { redirect_to: redirectTo };
64
+ if (systemId) params.system_id = systemId;
65
+ window.location.href = props.loginUrl || buildUrl(apiBase, "login", params);
54
66
  }
55
67
  function goRegister() {
56
68
  if (typeof window === "undefined") return;
57
- window.location.href = buildRegisterUrl(accountsBaseUrl, undefined, systemId);
69
+ const redirectTo = window.location.href;
70
+ const params: Record<string, string> = { redirect_to: redirectTo };
71
+ if (systemId) params.system_id = systemId;
72
+ window.location.href = buildUrl(accountsBaseUrl, "register", params);
58
73
  }
59
74
  </script>
60
75
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -40,4 +40,4 @@
40
40
  "nuxt": "^3.15.4",
41
41
  "typescript": "^5.0.0"
42
42
  }
43
- }
43
+ }
@@ -22,15 +22,16 @@ const styles = computed(() => kit.value?.content_styles ?? []);
22
22
  const brands = computed(() => kit.value?.brands ?? []);
23
23
  const period = computed(() => kit.value?.period ?? null);
24
24
  const tpl = computed(() => kit.value?.theme || null);
25
- // Layout emphasis template (premium): creator (default) / performance / commercial / audience
26
25
  const template = computed(() => kit.value?.template || 'creator');
27
26
  const platforms = computed(() => kit.value?.platforms ?? []);
28
27
  const totalFollowers = computed(() => kit.value?.total_followers ?? 0);
28
+ const isPremium = computed(() => kit.value?.is_premium ?? false);
29
29
  const mediaKitWall = computed(() => walls.value.find((w: any) => w.show_on_media_kit) ?? null);
30
30
 
31
31
  const PLATFORM_LABEL: Record<string, string> = {
32
32
  instagram: 'Instagram', tiktok: 'TikTok', youtube: 'YouTube', twitch: 'Twitch', x: 'X',
33
- facebook: 'Facebook', kick: 'Kick', discord: 'Discord', telegram: 'Telegram', linkedin: 'LinkedIn', bluesky: 'Bluesky',
33
+ facebook: 'Facebook', kick: 'Kick', discord: 'Discord', telegram: 'Telegram',
34
+ linkedin: 'LinkedIn', bluesky: 'Bluesky',
34
35
  };
35
36
 
36
37
  const socials = computed(() => {
@@ -89,24 +90,29 @@ function onDownload() {
89
90
 
90
91
  <template v-else>
91
92
  <div class="mk-cover" />
93
+
92
94
  <div class="kit-wrap mk-sections">
93
95
  <header class="mk-header">
94
96
  <img v-if="streamer.avatar" class="mk-avatar" :src="streamer.avatar" :alt="streamer.name" />
95
97
  <div v-else class="mk-avatar mk-avatar-ph" />
98
+
96
99
  <div class="mk-hid">
97
100
  <h1>{{ streamer.name }}</h1>
98
101
  <div class="mk-badges">
99
102
  <span v-if="streamer.platform" class="mk-badge plat">{{ streamer.platform }}</span>
100
103
  <span v-if="streamer.tier && streamer.tier !== 'free'" class="mk-badge tier">{{ String(streamer.tier).toUpperCase() }}</span>
104
+ <span v-if="streamer.slug" class="mk-badge loc">@{{ streamer.slug }}</span>
101
105
  </div>
102
106
  <p v-if="streamer.bio" class="mk-bio">{{ streamer.bio }}</p>
103
107
  </div>
108
+
104
109
  <div class="mk-actions no-print">
105
110
  <a class="kit-btn kit-btn-primary" @click="onDownload">{{ $t('kit.media.download_pdf') }}</a>
106
111
  <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>
107
112
  </div>
108
113
  </header>
109
114
 
115
+ <!-- Reach / multi-platform followers -->
110
116
  <section v-if="platforms.length" class="kit-block" data-sec="reach">
111
117
  <h2>{{ $t('kit.media.reach') }}</h2>
112
118
  <p v-if="totalFollowers" class="mk-total-reach">{{ fmt(totalFollowers) }} <span>{{ $t('kit.media.total_reach') }}</span></p>
@@ -125,6 +131,7 @@ function onDownload() {
125
131
  </div>
126
132
  </section>
127
133
 
134
+ <!-- TV streaming metrics -->
128
135
  <section v-if="stats" class="kit-block" data-sec="metrics">
129
136
  <h2>{{ $t('kit.media.key_metrics') }}</h2>
130
137
  <p v-if="period" class="mk-period">{{ $t('kit.media.last_days', { days: period.days }) }} · {{ period.start }} — {{ period.end }}</p>
@@ -140,41 +147,59 @@ function onDownload() {
140
147
  </div>
141
148
  </section>
142
149
 
143
- <section v-if="demographics" data-sec="audience" class="kit-block">
150
+ <!-- Audience demographics -->
151
+ <section v-if="demographics" class="kit-block" data-sec="audience">
144
152
  <h2>{{ $t('kit.media.audience') }}</h2>
145
153
  <div class="mk-cols2">
146
- <div class="kit-card mk-pad" v-if="demographics.age_ranges?.length">
154
+ <div v-if="demographics.age_ranges?.length" class="kit-card mk-pad">
147
155
  <h3>{{ $t('kit.media.age') }}</h3>
148
156
  <div v-for="a in demographics.age_ranges" :key="a.label" class="mk-bar">
149
157
  <div class="top"><span>{{ a.label }}</span><b>{{ a.percent }}%</b></div>
150
- <div class="track"><div class="fill" :style="{ width: a.percent + '%' }" /></div>
158
+ <div class="mk-track"><div class="mk-fill" :style="{ width: a.percent + '%' }" /></div>
151
159
  </div>
152
160
  </div>
153
- <div class="kit-card mk-pad" v-if="demographics.gender">
161
+ <div v-if="demographics.gender" class="kit-card mk-pad">
154
162
  <h3>{{ $t('kit.media.gender_regions') }}</h3>
155
163
  <div class="mk-gender">
156
- <div v-for="(v, k) in demographics.gender" :key="k" class="g"><div class="pct">{{ v }}%</div><div class="lb">{{ k }}</div></div>
164
+ <div v-for="(v, k) in demographics.gender" :key="k" class="g">
165
+ <div class="pct">{{ v }}%</div>
166
+ <div class="lb">{{ k }}</div>
167
+ </div>
168
+ </div>
169
+ <div v-if="demographics.top_countries?.length" class="mk-countries">
170
+ <div v-for="c in demographics.top_countries" :key="c.code" class="mk-bar">
171
+ <div class="top"><span>{{ c.label }}</span><b>{{ c.percent }}%</b></div>
172
+ <div class="mk-track"><div class="mk-fill" :style="{ width: c.percent + '%' }" /></div>
173
+ </div>
157
174
  </div>
158
175
  </div>
159
176
  </div>
160
177
  </section>
161
178
 
162
- <section v-if="styles.length" data-sec="styles" class="kit-block">
179
+ <!-- Content styles / niches -->
180
+ <section v-if="styles.length" class="kit-block" data-sec="styles">
163
181
  <h2>{{ $t('kit.media.styles') }}</h2>
164
- <div class="mk-tags"><span v-for="(s, i) in styles" :key="i" class="mk-tag">{{ s }}</span></div>
182
+ <div class="mk-tags">
183
+ <span v-for="(s, i) in styles" :key="i" class="mk-tag" :class="{ on: i < 4 }">{{ s }}</span>
184
+ </div>
165
185
  </section>
166
186
 
167
- <section v-if="topGames.length" data-sec="games" class="kit-block">
187
+ <!-- Top games (TV streamers) -->
188
+ <section v-if="topGames.length" class="kit-block" data-sec="games">
168
189
  <h2>{{ $t('kit.media.top_games') }}</h2>
169
190
  <div class="mk-games">
170
191
  <div v-for="g in topGames" :key="g.game" class="mk-game">
171
192
  <span class="nm">{{ g.game }}</span>
172
- <span class="st"><span>{{ g.hours }}h</span><span>{{ g.avg_viewers }} {{ $t('kit.media.avg_short') }}</span></span>
193
+ <span class="st">
194
+ <span>{{ g.hours }}h</span>
195
+ <span>{{ g.avg_viewers }} {{ $t('kit.media.avg_short') }}</span>
196
+ </span>
173
197
  </div>
174
198
  </div>
175
199
  </section>
176
200
 
177
- <section v-if="rateCards.length || bundles.length" data-sec="rates" class="kit-block">
201
+ <!-- Rate cards & bundles (premium) -->
202
+ <section v-if="rateCards.length || bundles.length" class="kit-block" data-sec="rates">
178
203
  <h2>{{ $t('kit.media.rates') }}</h2>
179
204
  <div v-if="rateCards.length" class="mk-rates">
180
205
  <div v-for="(r, i) in rateCards" :key="i" class="mk-rate">
@@ -197,12 +222,16 @@ function onDownload() {
197
222
  </div>
198
223
  </section>
199
224
 
200
- <section v-if="brands.length" data-sec="brands" class="kit-block">
225
+ <!-- Partner brands -->
226
+ <section v-if="brands.length" class="kit-block" data-sec="brands">
201
227
  <h2>{{ $t('kit.media.brands') }}</h2>
202
- <div class="mk-brands"><div v-for="(b, i) in brands" :key="i" class="mk-brand">{{ b.name || b }}</div></div>
228
+ <div class="mk-brands">
229
+ <div v-for="(b, i) in brands" :key="i" class="mk-brand">{{ b.name || b }}</div>
230
+ </div>
203
231
  </section>
204
232
 
205
- <section v-if="schedule.length" data-sec="schedule" class="kit-block">
233
+ <!-- Weekly schedule -->
234
+ <section v-if="schedule.length" class="kit-block" data-sec="schedule">
206
235
  <h2>{{ $t('kit.media.schedule') }}</h2>
207
236
  <div class="mk-schedule">
208
237
  <div v-for="d in scheduleByDay" :key="d.d" class="mk-day" :class="{ on: d.slot }">
@@ -213,14 +242,18 @@ function onDownload() {
213
242
  </div>
214
243
  </section>
215
244
 
216
- <section v-if="socials.length" data-sec="connect" class="kit-block no-print">
245
+ <!-- Social links -->
246
+ <section v-if="socials.length" class="kit-block no-print" data-sec="connect">
217
247
  <h2>{{ $t('kit.media.connect') }}</h2>
218
248
  <div class="mk-socials">
219
- <a v-for="s in socials" :key="s.platform" class="mk-soc" :href="s.url" target="_blank" rel="noopener" @click="track('click')">{{ s.platform }}</a>
249
+ <a v-for="s in socials" :key="s.platform" class="mk-soc" :href="s.url" target="_blank" rel="noopener" @click="track('click')">
250
+ {{ s.platform }}
251
+ </a>
220
252
  </div>
221
253
  </section>
222
254
 
223
- <section v-if="mediaKitWall" data-sec="support" class="kit-block">
255
+ <!-- IndieWall / mural -->
256
+ <section v-if="mediaKitWall" class="kit-block" data-sec="support">
224
257
  <h2>{{ $t('kit.media.support') }}</h2>
225
258
  <div class="mk-indiewall">
226
259
  <div>
@@ -231,112 +264,549 @@ function onDownload() {
231
264
  <div class="s"><div class="v">{{ mediaKitWall.supporters_count ?? 0 }}</div><div class="l">{{ $t('kit.media.supporters') }}</div></div>
232
265
  </div>
233
266
  </div>
234
- <a :href="mediaKitWall.mural_url" target="_blank" rel="noopener" class="kit-btn kit-btn-primary">{{ $t('kit.media.view_wall') }}</a>
267
+ <a :href="mediaKitWall.mural_url" target="_blank" rel="noopener" class="kit-btn kit-btn-primary" @click="track('click')">{{ $t('kit.media.view_wall') }}</a>
235
268
  </div>
236
269
  </section>
237
270
 
238
- <footer class="mk-footer">{{ $t('kit.media.generated') }} {{ kit.generated_at?.slice(0, 10) }}</footer>
271
+ <footer class="mk-footer">
272
+ {{ $t('kit.media.generated') }} <strong>Mundo Gamer</strong> · {{ kit.generated_at?.slice(0, 10) }}
273
+ </footer>
239
274
  </div>
240
275
  </template>
241
276
  </div>
242
277
  </template>
243
278
 
244
279
  <style lang="scss" scoped>
245
- .kit-media { background: var(--kit-bg); color: var(--kit-text); min-height: 100vh; font-family: 'Inter', system-ui, sans-serif; }
246
- .kit-state { display: flex; align-items: center; justify-content: center; min-height: 60vh; color: var(--kit-muted); }
247
- .kit-wrap { max-width: 1100px; margin: 0 auto; padding: 0 24px 60px; }
248
- .mk-cover { height: 200px; background: linear-gradient(120deg, var(--kit-accent), #2a0e4e 60%, var(--kit-bg)); }
249
-
250
- .mk-header { margin-top: -70px; position: relative; z-index: 2; display: flex; gap: 24px; align-items: flex-end; flex-wrap: wrap; }
251
- .mk-avatar { width: 140px; height: 140px; border: 3px solid var(--kit-accent); object-fit: cover; flex-shrink: 0; background: var(--kit-surface-2); }
252
- .mk-avatar-ph { background: linear-gradient(135deg, var(--kit-surface-2), var(--kit-accent)); }
253
- .mk-hid { flex: 1; min-width: 260px; padding-bottom: 6px; }
254
- .mk-hid h1 { font-family: 'Rajdhani'; font-size: 40px; line-height: 1.05; }
255
- .mk-badges { display: flex; gap: 8px; margin: 8px 0; flex-wrap: wrap; }
256
- .mk-badge { font-family: 'Rajdhani'; font-weight: 700; font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; padding: 4px 10px; }
257
- .mk-badge.plat { background: var(--kit-surface-2); border: 1px solid var(--kit-line); }
258
- .mk-badge.tier { background: var(--kit-accent); color: var(--kit-accent-ink); }
259
- .mk-bio { color: #c4c4d2; font-size: 15px; max-width: 60ch; margin-top: 6px; }
260
- .mk-actions { display: flex; gap: 10px; padding-bottom: 8px; }
261
-
262
- .kit-btn { display: inline-flex; align-items: center; gap: 8px; font-family: 'Rajdhani'; font-weight: 700; font-size: 14px; padding: 11px 20px; cursor: pointer; border: 1px solid transparent; text-transform: uppercase; text-decoration: none; }
263
- .kit-btn-primary { background: var(--kit-accent); color: var(--kit-accent-ink); }
264
- .kit-btn-ghost { background: rgba(255,255,255,.04); border-color: var(--kit-line); color: var(--kit-text); }
265
-
266
- .kit-block { margin-top: 44px; }
267
- .kit-block > h2 { font-size: 13px; letter-spacing: 3px; text-transform: uppercase; color: var(--kit-muted); font-weight: 700; margin-bottom: 16px; display: flex; align-items: center; gap: 12px; }
268
- .kit-block > h2::after { content: ""; flex: 1; height: 1px; background: var(--kit-line); }
269
- .mk-period { color: var(--kit-muted); font-size: 13px; margin: -8px 0 16px; }
270
-
271
- .mk-metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
272
- .mk-metric { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 20px 16px; text-align: center; position: relative; }
273
- .mk-metric::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: var(--kit-accent); }
274
- .mk-metric .val { font-family: 'Rajdhani'; font-weight: 700; font-size: 30px; line-height: 1; }
275
- .mk-metric .val.accent { color: var(--kit-accent); }
276
- .mk-metric .lab { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); margin-top: 8px; }
277
-
278
- .mk-cols2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
279
- .kit-card { background: var(--kit-surface); border: 1px solid var(--kit-line); }
280
- .mk-pad { padding: 20px; }
281
- .mk-pad h3 { font-size: 14px; font-weight: 700; margin-bottom: 14px; }
282
- .mk-bar { margin-bottom: 12px; }
283
- .mk-bar .top { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 5px; }
284
- .mk-bar .top b { color: var(--kit-accent); }
285
- .mk-bar .track { height: 8px; background: var(--kit-surface-2); }
286
- .mk-bar .fill { height: 100%; background: var(--kit-accent); }
287
- .mk-gender { display: flex; gap: 16px; }
288
- .mk-gender .g { flex: 1; text-align: center; background: var(--kit-surface-2); border: 1px solid var(--kit-line); padding: 14px; }
289
- .mk-gender .pct { font-family: 'Rajdhani'; font-weight: 700; font-size: 26px; color: var(--kit-accent); }
290
- .mk-gender .lb { font-size: 12px; color: var(--kit-muted); text-transform: uppercase; }
291
-
292
- .mk-tags { display: flex; flex-wrap: wrap; gap: 8px; }
293
- .mk-tag { background: var(--kit-surface-2); border: 1px solid var(--kit-line); padding: 6px 13px; font-size: 13px; }
294
-
295
- .mk-games { display: flex; flex-direction: column; gap: 8px; }
296
- .mk-game { display: flex; align-items: center; justify-content: space-between; background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 12px 16px; }
297
- .mk-game .nm { font-weight: 600; }
298
- .mk-game .st { display: flex; gap: 18px; color: var(--kit-muted); font-size: 13px; }
299
-
300
- .mk-rates { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
301
- .mk-rate { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 18px; }
302
- .mk-rate .fmt { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-accent); font-weight: 700; }
303
- .mk-rate .lb { font-weight: 600; font-size: 16px; margin: 6px 0 10px; font-family: 'Rajdhani'; }
304
- .mk-rate .price { font-family: 'Rajdhani'; font-weight: 700; font-size: 22px; }
305
- .mk-rate .dl { font-size: 12px; color: var(--kit-muted); margin-top: 6px; }
306
- .mk-bundles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
307
- .mk-bundle { background: linear-gradient(135deg, var(--kit-surface), var(--kit-surface-2)); border: 1px solid var(--kit-accent); padding: 18px; position: relative; }
308
- .mk-bundle .off { position: absolute; top: 14px; right: 14px; background: var(--kit-accent); color: var(--kit-accent-ink); font-size: 11px; font-weight: 700; padding: 3px 9px; font-family: 'Rajdhani'; }
309
- .mk-bundle .bn { font-weight: 700; font-size: 17px; font-family: 'Rajdhani'; }
310
- .mk-bundle .bd { font-size: 13px; color: var(--kit-muted); margin: 4px 0 10px; }
311
- .mk-bundle .bp { font-family: 'Rajdhani'; font-weight: 700; font-size: 24px; color: var(--kit-accent); }
312
- .mk-bundle .bp s { color: var(--kit-muted); font-size: 15px; font-weight: 500; margin-left: 8px; }
313
- .mk-bundle .bundle-items { list-style: none; padding: 0; margin: 0 0 12px; display: flex; flex-direction: column; gap: 4px; }
314
- .mk-bundle .bundle-items li { font-size: 13px; color: #c4c4d2; }
315
- .mk-bundle .bundle-items li b { color: var(--kit-accent); font-family: 'Rajdhani'; }
316
-
317
- .mk-brands { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
318
- .mk-brand { aspect-ratio: 5/2; background: var(--kit-surface-2); border: 1px solid var(--kit-line); display: flex; align-items: center; justify-content: center; color: var(--kit-muted); font-family: 'Rajdhani'; font-weight: 700; font-size: 14px; }
319
-
320
- .mk-schedule { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; }
321
- .mk-day { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 12px 8px; text-align: center; }
322
- .mk-day.on { border-color: var(--kit-accent); }
323
- .mk-day .dn { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
324
- .mk-day.on .dn { color: var(--kit-accent); }
325
- .mk-day .hr { font-family: 'Rajdhani'; font-weight: 700; margin-top: 6px; font-size: 14px; }
326
- .mk-day .off { color: var(--kit-muted); opacity: .4; margin-top: 6px; }
327
-
328
- .mk-socials { display: flex; flex-wrap: wrap; gap: 10px; }
329
- .mk-soc { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 9px 16px; font-size: 14px; text-transform: capitalize; }
330
-
331
- .mk-indiewall { background: var(--kit-surface); border: 1px solid var(--kit-accent); padding: 24px; display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; }
332
- .mk-indiewall .iw-name { font-family: 'Rajdhani'; font-weight: 700; font-size: 19px; }
333
- .mk-indiewall .iw-desc { color: #b4b4c2; font-size: 13px; margin-top: 4px; }
334
- .mk-indiewall .iw-stats { display: flex; gap: 26px; margin-top: 10px; }
335
- .mk-indiewall .iw-stats .v { font-family: 'Rajdhani'; font-weight: 700; font-size: 20px; color: var(--kit-accent); }
336
- .mk-indiewall .iw-stats .l { font-size: 11px; text-transform: uppercase; color: var(--kit-muted); }
337
-
338
- .mk-footer { border-top: 1px solid var(--kit-line); margin-top: 48px; padding: 24px 0; text-align: center; color: var(--kit-muted); font-size: 13px; }
280
+ .kit-media {
281
+ background: var(--kit-bg);
282
+ color: var(--kit-text);
283
+ min-height: 100vh;
284
+ font-family: 'Inter', system-ui, sans-serif;
285
+ -webkit-font-smoothing: antialiased;
286
+ }
287
+ .kit-state {
288
+ display: flex;
289
+ align-items: center;
290
+ justify-content: center;
291
+ min-height: 60vh;
292
+ color: var(--kit-muted);
293
+ }
294
+ .kit-wrap {
295
+ max-width: 1100px;
296
+ margin: 0 auto;
297
+ padding: 0 24px 60px;
298
+ }
299
+
300
+ /* Cover */
301
+ .mk-cover {
302
+ height: 200px;
303
+ background: linear-gradient(120deg, var(--kit-accent-2, #6b15ac) 0%, #2a0e4e 50%, var(--kit-bg) 100%);
304
+ position: relative;
305
+ border-bottom: 1px solid var(--kit-line);
306
+
307
+ &::after {
308
+ content: "";
309
+ position: absolute;
310
+ inset: 0;
311
+ background: radial-gradient(circle at 80% 20%, rgba(168, 85, 247, .35), transparent 60%);
312
+ }
313
+ }
314
+
315
+ /* Header */
316
+ .mk-header {
317
+ margin-top: -70px;
318
+ position: relative;
319
+ z-index: 2;
320
+ display: flex;
321
+ gap: 24px;
322
+ align-items: flex-end;
323
+ flex-wrap: wrap;
324
+ }
325
+ .mk-avatar {
326
+ width: 140px;
327
+ height: 140px;
328
+ border: 3px solid var(--kit-accent);
329
+ object-fit: cover;
330
+ flex-shrink: 0;
331
+ background: var(--kit-surface-2);
332
+ }
333
+ .mk-avatar-ph {
334
+ background: linear-gradient(135deg, var(--kit-accent-2, #6b15ac), var(--kit-accent));
335
+ }
336
+ .mk-hid {
337
+ flex: 1;
338
+ min-width: 260px;
339
+ padding-bottom: 6px;
340
+
341
+ h1 {
342
+ font-family: 'Rajdhani', sans-serif;
343
+ font-size: 40px;
344
+ line-height: 1.05;
345
+ }
346
+ }
347
+ .mk-badges {
348
+ display: flex;
349
+ gap: 8px;
350
+ margin: 8px 0;
351
+ flex-wrap: wrap;
352
+ }
353
+ .mk-badge {
354
+ font-family: 'Rajdhani', sans-serif;
355
+ font-weight: 700;
356
+ font-size: 11px;
357
+ letter-spacing: 1.5px;
358
+ text-transform: uppercase;
359
+ padding: 4px 10px;
360
+
361
+ &.plat { background: var(--kit-surface-2); border: 1px solid var(--kit-line); }
362
+ &.tier { background: var(--kit-accent); color: var(--kit-accent-ink); }
363
+ &.loc { color: var(--kit-muted); border: 1px solid var(--kit-line); }
364
+ }
365
+ .mk-bio {
366
+ color: #c4c4d2;
367
+ font-size: 15px;
368
+ max-width: 60ch;
369
+ margin-top: 6px;
370
+ }
371
+ .mk-actions {
372
+ display: flex;
373
+ gap: 10px;
374
+ padding-bottom: 8px;
375
+ }
376
+
377
+ /* Buttons */
378
+ .kit-btn {
379
+ display: inline-flex;
380
+ align-items: center;
381
+ gap: 8px;
382
+ font-family: 'Rajdhani', sans-serif;
383
+ font-weight: 700;
384
+ font-size: 14px;
385
+ padding: 11px 20px;
386
+ cursor: pointer;
387
+ border: 1px solid transparent;
388
+ text-transform: uppercase;
389
+ text-decoration: none;
390
+ transition: filter .15s, border-color .15s, color .15s;
391
+
392
+ &.kit-btn-primary {
393
+ background: var(--kit-accent);
394
+ color: var(--kit-accent-ink);
395
+ &:hover { filter: brightness(1.1); }
396
+ }
397
+ &.kit-btn-ghost {
398
+ background: rgba(255, 255, 255, .04);
399
+ border-color: var(--kit-line);
400
+ color: var(--kit-text);
401
+ &:hover { border-color: var(--kit-accent); color: var(--kit-accent); }
402
+ }
403
+ }
404
+
405
+ /* Sections */
406
+ .kit-block {
407
+ margin-top: 44px;
408
+
409
+ > h2 {
410
+ font-size: 13px;
411
+ letter-spacing: 3px;
412
+ text-transform: uppercase;
413
+ color: var(--kit-muted);
414
+ font-weight: 700;
415
+ margin-bottom: 16px;
416
+ display: flex;
417
+ align-items: center;
418
+ gap: 12px;
419
+
420
+ &::after {
421
+ content: "";
422
+ flex: 1;
423
+ height: 1px;
424
+ background: var(--kit-line);
425
+ }
426
+ }
427
+ }
428
+ .mk-period {
429
+ color: var(--kit-muted);
430
+ font-size: 13px;
431
+ margin: -8px 0 16px;
432
+ }
433
+
434
+ /* Metrics grid */
435
+ .mk-metrics {
436
+ display: grid;
437
+ grid-template-columns: repeat(4, 1fr);
438
+ gap: 12px;
439
+ }
440
+ .mk-metric {
441
+ background: var(--kit-surface);
442
+ border: 1px solid var(--kit-line);
443
+ padding: 20px 16px;
444
+ text-align: center;
445
+ position: relative;
446
+ overflow: hidden;
447
+
448
+ &::before {
449
+ content: "";
450
+ position: absolute;
451
+ top: 0; left: 0;
452
+ width: 100%;
453
+ height: 2px;
454
+ background: var(--kit-accent);
455
+ }
456
+
457
+ .val {
458
+ font-family: 'Rajdhani', sans-serif;
459
+ font-weight: 700;
460
+ font-size: 30px;
461
+ line-height: 1;
462
+ &.accent { color: var(--kit-accent); }
463
+ }
464
+ .lab {
465
+ font-size: 11px;
466
+ text-transform: uppercase;
467
+ letter-spacing: 1px;
468
+ color: var(--kit-muted);
469
+ margin-top: 8px;
470
+ }
471
+ }
472
+
473
+ /* Demographics */
474
+ .mk-cols2 {
475
+ display: grid;
476
+ grid-template-columns: 1fr 1fr;
477
+ gap: 24px;
478
+ }
479
+ .kit-card {
480
+ background: var(--kit-surface);
481
+ border: 1px solid var(--kit-line);
482
+ }
483
+ .mk-pad {
484
+ padding: 20px;
485
+
486
+ h3 {
487
+ font-size: 14px;
488
+ font-weight: 700;
489
+ margin-bottom: 14px;
490
+ letter-spacing: .5px;
491
+ }
492
+ }
493
+ .mk-bar {
494
+ margin-bottom: 12px;
495
+
496
+ .top {
497
+ display: flex;
498
+ justify-content: space-between;
499
+ font-size: 13px;
500
+ margin-bottom: 5px;
501
+
502
+ b { color: var(--kit-accent); font-weight: 600; }
503
+ }
504
+ }
505
+ .mk-track {
506
+ height: 8px;
507
+ background: var(--kit-surface-2);
508
+ }
509
+ .mk-fill {
510
+ height: 100%;
511
+ background: linear-gradient(90deg, var(--kit-accent-2, #6b15ac), var(--kit-accent));
512
+ }
513
+ .mk-gender {
514
+ display: flex;
515
+ gap: 16px;
516
+ margin-top: 4px;
517
+
518
+ .g {
519
+ flex: 1;
520
+ text-align: center;
521
+ background: var(--kit-surface-2);
522
+ border: 1px solid var(--kit-line);
523
+ padding: 14px;
524
+
525
+ .pct {
526
+ font-family: 'Rajdhani', sans-serif;
527
+ font-weight: 700;
528
+ font-size: 26px;
529
+ color: var(--kit-accent);
530
+ }
531
+ .lb {
532
+ font-size: 12px;
533
+ color: var(--kit-muted);
534
+ text-transform: uppercase;
535
+ letter-spacing: 1px;
536
+ }
537
+ }
538
+ }
539
+ .mk-countries { margin-top: 14px; }
540
+
541
+ /* Tags */
542
+ .mk-tags {
543
+ display: flex;
544
+ flex-wrap: wrap;
545
+ gap: 8px;
546
+ }
547
+ .mk-tag {
548
+ background: var(--kit-surface-2);
549
+ border: 1px solid var(--kit-line);
550
+ padding: 6px 13px;
551
+ font-size: 13px;
552
+ color: #d4d4e0;
553
+
554
+ &.on {
555
+ border-color: var(--kit-accent);
556
+ color: var(--kit-accent);
557
+ }
558
+ }
559
+
560
+ /* Top games */
561
+ .mk-games {
562
+ display: flex;
563
+ flex-direction: column;
564
+ gap: 8px;
565
+ }
566
+ .mk-game {
567
+ display: flex;
568
+ align-items: center;
569
+ justify-content: space-between;
570
+ background: var(--kit-surface);
571
+ border: 1px solid var(--kit-line);
572
+ padding: 12px 16px;
573
+
574
+ .nm { font-weight: 600; }
575
+ .st { display: flex; gap: 18px; color: var(--kit-muted); font-size: 13px; }
576
+ }
577
+
578
+ /* Rate cards */
579
+ .mk-rates {
580
+ display: grid;
581
+ grid-template-columns: repeat(3, 1fr);
582
+ gap: 12px;
583
+ }
584
+ .mk-rate {
585
+ background: var(--kit-surface);
586
+ border: 1px solid var(--kit-line);
587
+ padding: 18px;
588
+
589
+ .fmt { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-accent); font-weight: 700; }
590
+ .lb { font-family: 'Rajdhani', sans-serif; font-weight: 600; font-size: 16px; margin: 6px 0 10px; }
591
+ .price{ font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 22px; }
592
+ .dl { font-size: 12px; color: var(--kit-muted); margin-top: 6px; }
593
+ }
339
594
 
595
+ /* Bundles */
596
+ .mk-bundles {
597
+ display: grid;
598
+ grid-template-columns: 1fr 1fr;
599
+ gap: 12px;
600
+ margin-top: 12px;
601
+ }
602
+ .mk-bundle {
603
+ background: linear-gradient(135deg, var(--kit-surface), var(--kit-surface-2));
604
+ border: 1px solid var(--kit-accent);
605
+ padding: 18px;
606
+ position: relative;
607
+
608
+ .off {
609
+ position: absolute;
610
+ top: 14px; right: 14px;
611
+ background: var(--kit-accent);
612
+ color: var(--kit-accent-ink);
613
+ font-size: 11px;
614
+ font-weight: 700;
615
+ padding: 3px 9px;
616
+ font-family: 'Rajdhani', sans-serif;
617
+ letter-spacing: 1px;
618
+ }
619
+ .bn { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 17px; }
620
+ .bd { font-size: 13px; color: var(--kit-muted); margin: 4px 0 10px; }
621
+ .bp {
622
+ font-family: 'Rajdhani', sans-serif;
623
+ font-weight: 700;
624
+ font-size: 24px;
625
+ color: var(--kit-accent);
626
+
627
+ s { color: var(--kit-muted); font-size: 15px; font-weight: 500; margin-left: 8px; }
628
+ }
629
+ .bundle-items {
630
+ list-style: none;
631
+ padding: 0;
632
+ margin: 0 0 12px;
633
+ display: flex;
634
+ flex-direction: column;
635
+ gap: 4px;
636
+
637
+ li { font-size: 13px; color: #c4c4d2; }
638
+ li b { color: var(--kit-accent); font-family: 'Rajdhani', sans-serif; }
639
+ }
640
+ }
641
+
642
+ /* Brands */
643
+ .mk-brands {
644
+ display: grid;
645
+ grid-template-columns: repeat(5, 1fr);
646
+ gap: 10px;
647
+ }
648
+ .mk-brand {
649
+ aspect-ratio: 5 / 2;
650
+ background: var(--kit-surface-2);
651
+ border: 1px solid var(--kit-line);
652
+ display: flex;
653
+ align-items: center;
654
+ justify-content: center;
655
+ color: var(--kit-muted);
656
+ font-family: 'Rajdhani', sans-serif;
657
+ font-weight: 700;
658
+ font-size: 14px;
659
+ letter-spacing: 1px;
660
+ }
661
+
662
+ /* Schedule */
663
+ .mk-schedule {
664
+ display: grid;
665
+ grid-template-columns: repeat(7, 1fr);
666
+ gap: 8px;
667
+ }
668
+ .mk-day {
669
+ background: var(--kit-surface);
670
+ border: 1px solid var(--kit-line);
671
+ padding: 12px 8px;
672
+ text-align: center;
673
+
674
+ &.on { border-color: var(--kit-accent); }
675
+ &.on .dn { color: var(--kit-accent); }
676
+
677
+ .dn { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
678
+ .hr { font-family: 'Rajdhani', sans-serif; font-weight: 700; margin-top: 6px; font-size: 14px; }
679
+ .off { color: var(--kit-muted); opacity: .4; margin-top: 6px; }
680
+ }
681
+
682
+ /* Socials */
683
+ .mk-socials {
684
+ display: flex;
685
+ flex-wrap: wrap;
686
+ gap: 10px;
687
+ }
688
+ .mk-soc {
689
+ display: flex;
690
+ align-items: center;
691
+ gap: 8px;
692
+ background: var(--kit-surface);
693
+ border: 1px solid var(--kit-line);
694
+ padding: 9px 16px;
695
+ font-size: 14px;
696
+ text-transform: capitalize;
697
+ color: #d4d4e0;
698
+ text-decoration: none;
699
+ transition: border-color .15s, color .15s;
700
+
701
+ &:hover { border-color: var(--kit-accent); color: var(--kit-accent); }
702
+ }
703
+
704
+ /* IndieWall */
705
+ .mk-indiewall {
706
+ background: linear-gradient(120deg, rgba(168, 85, 247, .1), rgba(107, 21, 172, .05));
707
+ border: 1px solid var(--kit-accent);
708
+ padding: 24px;
709
+ display: flex;
710
+ justify-content: space-between;
711
+ align-items: center;
712
+ gap: 20px;
713
+ flex-wrap: wrap;
714
+
715
+ .iw-name { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 19px; }
716
+ .iw-desc { color: #b4b4c2; font-size: 13px; margin-top: 4px; }
717
+ .iw-stats { display: flex; gap: 26px; margin-top: 10px; }
718
+ .iw-stats .v { font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 20px; color: var(--kit-accent); }
719
+ .iw-stats .l { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
720
+ }
721
+
722
+ /* Reach / platform breakdown */
723
+ .mk-total-reach {
724
+ font-family: 'Rajdhani', sans-serif;
725
+ font-weight: 700;
726
+ font-size: 28px;
727
+ color: var(--kit-accent);
728
+ margin: -8px 0 16px;
729
+
730
+ span {
731
+ font-family: 'Inter', sans-serif;
732
+ font-size: 13px;
733
+ color: var(--kit-muted);
734
+ font-weight: 500;
735
+ text-transform: uppercase;
736
+ letter-spacing: 1px;
737
+ }
738
+ }
739
+ .mk-platforms {
740
+ display: grid;
741
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
742
+ gap: 12px;
743
+ }
744
+ .mk-platform {
745
+ background: var(--kit-surface);
746
+ border: 1px solid var(--kit-line);
747
+ padding: 16px;
748
+ text-decoration: none;
749
+ color: inherit;
750
+ display: flex;
751
+ flex-direction: column;
752
+ gap: 6px;
753
+ transition: border-color .15s;
754
+
755
+ &:hover { border-color: var(--kit-accent); }
756
+
757
+ .pl-head { display: flex; align-items: center; justify-content: space-between; }
758
+ .pl-name { font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
759
+ .pl-verified { color: #27ae60; font-weight: 700; }
760
+ .pl-followers{ font-family: 'Rajdhani', sans-serif; font-weight: 700; font-size: 24px; }
761
+ .pl-meta { display: flex; gap: 12px; font-size: 12px; color: var(--kit-muted); flex-wrap: wrap; }
762
+ }
763
+
764
+ /* Footer */
765
+ .mk-footer {
766
+ border-top: 1px solid var(--kit-line);
767
+ margin-top: 48px;
768
+ padding: 24px 0;
769
+ text-align: center;
770
+ color: var(--kit-muted);
771
+ font-size: 13px;
772
+
773
+ strong { color: var(--kit-accent); font-weight: 700; }
774
+ }
775
+
776
+ /* Template ordering (layout emphasis) */
777
+ .mk-sections { display: flex; flex-direction: column; }
778
+ .mk-sections > .mk-header { order: 0; }
779
+ .mk-sections > .mk-footer { order: 100; }
780
+ .mk-sections > [data-sec="reach"] { order: 1; }
781
+ .mk-sections > [data-sec="metrics"] { order: 2; }
782
+ .mk-sections > [data-sec="audience"] { order: 3; }
783
+ .mk-sections > [data-sec="styles"] { order: 4; }
784
+ .mk-sections > [data-sec="games"] { order: 5; }
785
+ .mk-sections > [data-sec="rates"] { order: 6; }
786
+ .mk-sections > [data-sec="brands"] { order: 7; }
787
+ .mk-sections > [data-sec="schedule"] { order: 8; }
788
+ .mk-sections > [data-sec="connect"] { order: 9; }
789
+ .mk-sections > [data-sec="support"] { order: 10; }
790
+
791
+ [data-template="performance"] {
792
+ .mk-sections > [data-sec="metrics"] { order: 1; }
793
+ .mk-sections > [data-sec="reach"] { order: 2; }
794
+ .mk-sections > [data-sec="games"] { order: 3; }
795
+ }
796
+ [data-template="commercial"] {
797
+ .mk-sections > [data-sec="reach"] { order: 1; }
798
+ .mk-sections > [data-sec="rates"] { order: 2; }
799
+ .mk-sections > [data-sec="brands"] { order: 3; }
800
+ .mk-sections > [data-sec="metrics"] { order: 4; }
801
+ }
802
+ [data-template="audience"] {
803
+ .mk-sections > [data-sec="reach"] { order: 1; }
804
+ .mk-sections > [data-sec="audience"] { order: 2; }
805
+ .mk-sections > [data-sec="styles"] { order: 3; }
806
+ .mk-sections > [data-sec="metrics"] { order: 4; }
807
+ }
808
+
809
+ /* Responsive */
340
810
  @media (max-width: 840px) {
341
811
  .mk-metrics { grid-template-columns: repeat(2, 1fr); }
342
812
  .mk-cols2, .mk-rates, .mk-bundles { grid-template-columns: 1fr; }
@@ -344,41 +814,8 @@ function onDownload() {
344
814
  .mk-schedule { grid-template-columns: repeat(4, 1fr); }
345
815
  .mk-header { flex-direction: column; align-items: flex-start; }
346
816
  }
347
- @media print { .no-print { display: none !important; } }
348
817
 
349
- /* Reach / platform breakdown */
350
- .mk-total-reach { font-family: 'Rajdhani'; font-weight: 700; font-size: 28px; color: var(--kit-accent); margin: -8px 0 16px; }
351
- .mk-total-reach span { font-family: 'Inter'; font-size: 13px; color: var(--kit-muted); font-weight: 500; text-transform: uppercase; letter-spacing: 1px; }
352
- .mk-platforms { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
353
- .mk-platform { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 16px; text-decoration: none; color: inherit; display: flex; flex-direction: column; gap: 6px; }
354
- .mk-platform:hover { border-color: var(--kit-accent); }
355
- .mk-platform .pl-head { display: flex; align-items: center; justify-content: space-between; }
356
- .mk-platform .pl-name { font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
357
- .mk-platform .pl-verified { color: #27ae60; font-weight: 700; }
358
- .mk-platform .pl-followers { font-family: 'Rajdhani'; font-weight: 700; font-size: 24px; }
359
- .mk-platform .pl-meta { display: flex; gap: 12px; font-size: 12px; color: var(--kit-muted); flex-wrap: wrap; }
360
-
361
- /* Template = layout emphasis (section order). Default DOM order = Creator. */
362
- .mk-sections { display: flex; flex-direction: column; }
363
- .mk-sections > .mk-header { order: 0; }
364
- .mk-sections > .mk-footer { order: 100; }
365
- .mk-sections > [data-sec="reach"]{order:1} .mk-sections > [data-sec="metrics"]{order:2}
366
- .mk-sections > [data-sec="audience"]{order:3} .mk-sections > [data-sec="styles"]{order:4}
367
- .mk-sections > [data-sec="games"]{order:5} .mk-sections > [data-sec="rates"]{order:6}
368
- .mk-sections > [data-sec="brands"]{order:7} .mk-sections > [data-sec="schedule"]{order:8}
369
- .mk-sections > [data-sec="connect"]{order:9} .mk-sections > [data-sec="support"]{order:10}
370
-
371
- [data-template="performance"] .mk-sections > [data-sec="metrics"]{order:1}
372
- [data-template="performance"] .mk-sections > [data-sec="reach"]{order:2}
373
- [data-template="performance"] .mk-sections > [data-sec="games"]{order:3}
374
-
375
- [data-template="commercial"] .mk-sections > [data-sec="reach"]{order:1}
376
- [data-template="commercial"] .mk-sections > [data-sec="rates"]{order:2}
377
- [data-template="commercial"] .mk-sections > [data-sec="brands"]{order:3}
378
- [data-template="commercial"] .mk-sections > [data-sec="metrics"]{order:4}
379
-
380
- [data-template="audience"] .mk-sections > [data-sec="reach"]{order:1}
381
- [data-template="audience"] .mk-sections > [data-sec="audience"]{order:2}
382
- [data-template="audience"] .mk-sections > [data-sec="styles"]{order:3}
383
- [data-template="audience"] .mk-sections > [data-sec="metrics"]{order:4}
818
+ @media print {
819
+ .no-print { display: none !important; }
820
+ }
384
821
  </style>