skill-tree-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,728 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Skill Tree — AI Fluency Profile</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=Outfit:wght@300;400;500;600&display=swap" rel="stylesheet">
9
+ <style>
10
+ * { margin: 0; padding: 0; box-sizing: border-box; }
11
+
12
+ :root {
13
+ --a-primary: #9e9589;
14
+ --a-accent: #d4cec6;
15
+ --a-glow: rgba(158,149,137,0.06);
16
+ }
17
+
18
+ body {
19
+ font-family: 'Outfit', sans-serif;
20
+ font-weight: 300;
21
+ background: #0f0e0d;
22
+ color: #e8e4df;
23
+ min-height: 100vh;
24
+ position: relative;
25
+ overflow-x: hidden;
26
+ }
27
+
28
+ body::before {
29
+ content: '';
30
+ position: fixed;
31
+ inset: 0;
32
+ background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
33
+ pointer-events: none;
34
+ z-index: 0;
35
+ }
36
+
37
+ .page {
38
+ position: relative;
39
+ z-index: 1;
40
+ max-width: 560px;
41
+ margin: 0 auto;
42
+ padding: 3rem 2rem 4rem;
43
+ }
44
+
45
+ .mark {
46
+ font-family: 'DM Serif Display', Georgia, serif;
47
+ font-size: 0.75rem;
48
+ letter-spacing: 0.25em;
49
+ text-transform: uppercase;
50
+ color: #6b6560;
51
+ text-align: center;
52
+ margin-bottom: 2.5rem;
53
+ }
54
+
55
+ .mark-sub {
56
+ font-family: 'Outfit', sans-serif;
57
+ font-size: 0.6rem;
58
+ letter-spacing: 0.15em;
59
+ font-weight: 300;
60
+ color: #4a4540;
61
+ display: block;
62
+ margin-top: 0.2rem;
63
+ }
64
+
65
+ /* ── Per-archetype color themes ── */
66
+ .card[data-archetype="catalyst"] { --a-primary: #d4584a; --a-accent: #e8a090; --a-glow: rgba(212,88,74,0.10); }
67
+ .card[data-archetype="compass"] { --a-primary: #4a7ba3; --a-accent: #a3c4db; --a-glow: rgba(74,123,163,0.10); }
68
+ .card[data-archetype="forgemaster"] { --a-primary: #b8860b; --a-accent: #e8d4a8; --a-glow: rgba(184,134,11,0.10); }
69
+ .card[data-archetype="illuminator"] { --a-primary: #3d8a5a; --a-accent: #a8d4b8; --a-glow: rgba(61,138,90,0.10); }
70
+ .card[data-archetype="architect"] { --a-primary: #6a8094; --a-accent: #b0c0d0; --a-glow: rgba(106,128,148,0.10); }
71
+ .card[data-archetype="conductor"] { --a-primary: #8b3a62; --a-accent: #d4a0b8; --a-glow: rgba(139,58,98,0.10); }
72
+ .card[data-archetype="polymath"] { --a-primary: #a08040; --a-accent: #e8d8b0; --a-glow: rgba(160,128,64,0.10); }
73
+
74
+ /* ── Character Card ── */
75
+ .card {
76
+ background: #1a1918;
77
+ border: 1px solid #2a2826;
78
+ border-radius: 1rem;
79
+ overflow: hidden;
80
+ margin-bottom: 1.5rem;
81
+ opacity: 0;
82
+ transform: translateY(12px);
83
+ animation: fadeUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards;
84
+ position: relative;
85
+ }
86
+
87
+ @keyframes fadeUp {
88
+ to { opacity: 1; transform: translateY(0); }
89
+ }
90
+
91
+ .card-accent-bar {
92
+ height: 3px;
93
+ background: linear-gradient(90deg, var(--a-primary), transparent);
94
+ }
95
+
96
+ .card-hero {
97
+ padding: 3rem 2rem 2rem;
98
+ text-align: center;
99
+ border-bottom: 1px solid #2a2826;
100
+ position: relative;
101
+ overflow: hidden;
102
+ background: linear-gradient(180deg, var(--a-glow) 0%, transparent 70%);
103
+ }
104
+
105
+ .card-hero .glyph-watermark {
106
+ position: absolute;
107
+ top: 50%;
108
+ left: 50%;
109
+ transform: translate(-50%, -50%);
110
+ width: 200px;
111
+ height: 200px;
112
+ opacity: 0.04;
113
+ color: var(--a-primary);
114
+ }
115
+
116
+ .archetype-label {
117
+ font-size: 0.6rem;
118
+ font-weight: 500;
119
+ letter-spacing: 0.2em;
120
+ text-transform: uppercase;
121
+ color: #6b6560;
122
+ margin-bottom: 0.5rem;
123
+ position: relative;
124
+ }
125
+
126
+ .archetype-name {
127
+ font-family: 'DM Serif Display', Georgia, serif;
128
+ font-size: 2.8rem;
129
+ line-height: 1.1;
130
+ color: var(--a-primary);
131
+ margin-bottom: 0.5rem;
132
+ position: relative;
133
+ }
134
+
135
+ .archetype-tagline {
136
+ font-size: 0.9rem;
137
+ color: #8a8580;
138
+ font-style: italic;
139
+ position: relative;
140
+ max-width: 380px;
141
+ margin: 0 auto;
142
+ line-height: 1.5;
143
+ }
144
+
145
+ .stats-row {
146
+ display: flex;
147
+ justify-content: center;
148
+ gap: 2.5rem;
149
+ margin-top: 1.5rem;
150
+ padding-top: 1.25rem;
151
+ border-top: 1px solid #2a2826;
152
+ position: relative;
153
+ }
154
+
155
+ .stat { text-align: center; }
156
+ .stat-value { font-weight: 500; font-size: 1.4rem; color: #e8e4df; }
157
+ .stat-label { font-size: 0.6rem; letter-spacing: 0.1em; text-transform: uppercase; color: #6b6560; margin-top: 0.1rem; }
158
+
159
+ /* ── Superpower ── */
160
+ .superpower {
161
+ padding: 1.25rem 2rem;
162
+ border-bottom: 1px solid #2a2826;
163
+ display: flex;
164
+ align-items: flex-start;
165
+ gap: 0.75rem;
166
+ }
167
+
168
+ .superpower-icon {
169
+ width: 20px;
170
+ height: 20px;
171
+ color: var(--a-primary);
172
+ flex-shrink: 0;
173
+ margin-top: 0.1rem;
174
+ }
175
+
176
+ .superpower-text {
177
+ font-size: 0.85rem;
178
+ color: #b0aaa4;
179
+ line-height: 1.5;
180
+ }
181
+
182
+ .superpower-text strong {
183
+ color: var(--a-accent);
184
+ font-weight: 500;
185
+ }
186
+
187
+ /* ── Description ── */
188
+ .vibe {
189
+ padding: 1.25rem 2rem;
190
+ border-bottom: 1px solid #2a2826;
191
+ }
192
+
193
+ .vibe-text {
194
+ font-family: 'DM Serif Display', Georgia, serif;
195
+ font-style: italic;
196
+ font-size: 0.85rem;
197
+ color: #6b6560;
198
+ line-height: 1.6;
199
+ }
200
+
201
+ .section-label {
202
+ font-size: 0.6rem;
203
+ font-weight: 500;
204
+ letter-spacing: 0.15em;
205
+ text-transform: uppercase;
206
+ color: #6b6560;
207
+ margin-bottom: 0.75rem;
208
+ }
209
+
210
+ /* ── Skill Tree ── */
211
+ .tree {
212
+ background: #1a1918;
213
+ border: 1px solid #2a2826;
214
+ border-radius: 1rem;
215
+ overflow: hidden;
216
+ margin-bottom: 1.5rem;
217
+ opacity: 0;
218
+ transform: translateY(12px);
219
+ animation: fadeUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
220
+ }
221
+
222
+ .tree-header {
223
+ padding: 1.5rem 2rem 1rem;
224
+ border-bottom: 1px solid #2a2826;
225
+ }
226
+
227
+ .tree-title {
228
+ font-family: 'DM Serif Display', Georgia, serif;
229
+ font-size: 1.3rem;
230
+ color: #e8e4df;
231
+ }
232
+
233
+ .tree-sub {
234
+ font-size: 0.75rem;
235
+ color: #4a4540;
236
+ margin-top: 0.25rem;
237
+ }
238
+
239
+ .gateway {
240
+ padding: 1rem 2rem;
241
+ border-bottom: 1px solid #2a2826;
242
+ display: flex;
243
+ align-items: center;
244
+ gap: 0.75rem;
245
+ }
246
+
247
+ .gateway-label {
248
+ font-size: 0.7rem;
249
+ color: #6b6560;
250
+ font-weight: 500;
251
+ letter-spacing: 0.05em;
252
+ white-space: nowrap;
253
+ }
254
+
255
+ .gateway-bar {
256
+ flex: 1;
257
+ height: 4px;
258
+ background: #2a2826;
259
+ border-radius: 2px;
260
+ overflow: hidden;
261
+ }
262
+
263
+ .gateway-fill {
264
+ height: 100%;
265
+ background: #4a4540;
266
+ border-radius: 2px;
267
+ width: 0%;
268
+ transition: width 1s cubic-bezier(0.22, 1, 0.36, 1);
269
+ }
270
+
271
+ .gateway-pct {
272
+ font-size: 0.7rem;
273
+ color: #4a4540;
274
+ font-variant-numeric: tabular-nums;
275
+ }
276
+
277
+ .branch {
278
+ padding: 1.25rem 2rem;
279
+ border-bottom: 1px solid #2a2826;
280
+ }
281
+
282
+ .branch:last-child { border-bottom: none; }
283
+
284
+ .branch-header {
285
+ display: flex;
286
+ align-items: center;
287
+ gap: 0.5rem;
288
+ margin-bottom: 0.5rem;
289
+ }
290
+
291
+ .branch-dot {
292
+ width: 8px;
293
+ height: 8px;
294
+ border-radius: 50%;
295
+ }
296
+
297
+ .branch-name {
298
+ font-weight: 500;
299
+ font-size: 0.85rem;
300
+ color: #e8e4df;
301
+ }
302
+
303
+ .branch-desc {
304
+ font-size: 0.65rem;
305
+ color: #4a4540;
306
+ margin-left: 0.25rem;
307
+ }
308
+
309
+ .branch-score {
310
+ margin-left: auto;
311
+ font-size: 0.75rem;
312
+ font-weight: 500;
313
+ color: #6b6560;
314
+ }
315
+
316
+ .behavior-row {
317
+ display: flex;
318
+ align-items: center;
319
+ gap: 0.75rem;
320
+ margin-bottom: 0.6rem;
321
+ }
322
+
323
+ .behavior-name {
324
+ width: 140px;
325
+ font-size: 0.75rem;
326
+ color: #6b6560;
327
+ text-align: right;
328
+ flex-shrink: 0;
329
+ }
330
+
331
+ .bar-track {
332
+ flex: 1;
333
+ height: 6px;
334
+ background: #2a2826;
335
+ border-radius: 3px;
336
+ overflow: hidden;
337
+ position: relative;
338
+ }
339
+
340
+ .bar-fill {
341
+ height: 100%;
342
+ border-radius: 3px;
343
+ width: 0%;
344
+ transition: width 1s cubic-bezier(0.22, 1, 0.36, 1);
345
+ }
346
+
347
+ .bar-baseline {
348
+ position: absolute;
349
+ top: -2px;
350
+ height: 10px;
351
+ width: 2px;
352
+ background: #e8e4df;
353
+ opacity: 0.15;
354
+ border-radius: 1px;
355
+ }
356
+
357
+ .behavior-pct {
358
+ width: 45px;
359
+ font-size: 0.7rem;
360
+ color: #6b6560;
361
+ font-variant-numeric: tabular-nums;
362
+ }
363
+
364
+ .behavior-comparison {
365
+ width: 20px;
366
+ font-size: 0.65rem;
367
+ text-align: center;
368
+ }
369
+
370
+ .above { color: #5a9e6f; }
371
+ .below { color: #c4836e; }
372
+ .at { color: #4a4540; }
373
+
374
+ /* ── Growth Quest ── */
375
+ .quest {
376
+ background: #1a1918;
377
+ border: 1px solid #2a2826;
378
+ border-radius: 1rem;
379
+ padding: 2rem;
380
+ margin-bottom: 1.5rem;
381
+ opacity: 0;
382
+ transform: translateY(12px);
383
+ animation: fadeUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.5s forwards;
384
+ position: relative;
385
+ overflow: hidden;
386
+ }
387
+
388
+ .quest::before {
389
+ content: '';
390
+ position: absolute;
391
+ top: 0;
392
+ left: 0;
393
+ right: 0;
394
+ height: 60px;
395
+ background: linear-gradient(180deg, var(--a-glow) 0%, transparent 100%);
396
+ pointer-events: none;
397
+ }
398
+
399
+ .quest-label {
400
+ font-size: 0.6rem;
401
+ font-weight: 500;
402
+ letter-spacing: 0.2em;
403
+ text-transform: uppercase;
404
+ color: var(--a-primary);
405
+ margin-bottom: 0.75rem;
406
+ position: relative;
407
+ }
408
+
409
+ .quest-title {
410
+ font-family: 'DM Serif Display', Georgia, serif;
411
+ font-size: 1.1rem;
412
+ color: #e8e4df;
413
+ margin-bottom: 0.5rem;
414
+ position: relative;
415
+ }
416
+
417
+ .quest-text {
418
+ font-size: 0.85rem;
419
+ color: #8a8580;
420
+ line-height: 1.6;
421
+ position: relative;
422
+ }
423
+
424
+ .quest-path {
425
+ margin-top: 1rem;
426
+ padding-top: 1rem;
427
+ border-top: 1px solid #2a2826;
428
+ font-size: 0.75rem;
429
+ color: #6b6560;
430
+ position: relative;
431
+ }
432
+
433
+ .quest-path strong {
434
+ color: #8a8580;
435
+ font-weight: 500;
436
+ }
437
+
438
+ .quest-arrow {
439
+ display: inline-block;
440
+ margin: 0 0.25rem;
441
+ color: var(--a-primary);
442
+ }
443
+
444
+ /* ── Footer ── */
445
+ .footer {
446
+ text-align: center;
447
+ margin-top: 1rem;
448
+ opacity: 0;
449
+ animation: fadeUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.7s forwards;
450
+ }
451
+
452
+ .footer-text {
453
+ font-size: 0.65rem;
454
+ color: #4a4540;
455
+ letter-spacing: 0.05em;
456
+ }
457
+
458
+ .footer-text a {
459
+ color: #6b6560;
460
+ text-decoration: none;
461
+ }
462
+
463
+ .footer-text a:hover { color: #8a8580; }
464
+
465
+ @media (max-width: 480px) {
466
+ .page { padding: 2rem 1rem 3rem; }
467
+ .card-hero, .superpower, .vibe, .branch, .quest { padding-left: 1.5rem; padding-right: 1.5rem; }
468
+ .archetype-name { font-size: 2.2rem; }
469
+ .behavior-name { width: 100px; font-size: 0.7rem; }
470
+ }
471
+ </style>
472
+ </head>
473
+ <body>
474
+ <!-- Glyph definitions -->
475
+ <svg style="display:none">
476
+ <defs>
477
+ <symbol id="glyph-catalyst" viewBox="0 0 200 200">
478
+ <g stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round">
479
+ <line x1="100" y1="20" x2="100" y2="180"/><line x1="20" y1="100" x2="180" y2="100"/>
480
+ <line x1="40" y1="40" x2="160" y2="160"/><line x1="160" y1="40" x2="40" y2="160"/>
481
+ <line x1="100" y1="40" x2="100" y2="160" opacity="0.4"/>
482
+ <line x1="40" y1="100" x2="160" y2="100" opacity="0.4"/>
483
+ <circle cx="100" cy="100" r="6" fill="currentColor" opacity="0.3"/>
484
+ </g>
485
+ </symbol>
486
+ <symbol id="glyph-compass" viewBox="0 0 200 200">
487
+ <g stroke="currentColor" stroke-width="1.5" fill="none">
488
+ <circle cx="100" cy="100" r="70"/>
489
+ <circle cx="100" cy="100" r="4" fill="currentColor" opacity="0.3"/>
490
+ <polygon points="100,30 108,90 100,80 92,90" fill="currentColor" opacity="0.15"/>
491
+ <polygon points="170,100 110,108 120,100 110,92" fill="currentColor" opacity="0.1"/>
492
+ <polygon points="100,170 92,110 100,120 108,110" fill="currentColor" opacity="0.1"/>
493
+ <polygon points="30,100 90,92 80,100 90,108" fill="currentColor" opacity="0.1"/>
494
+ <line x1="100" y1="28" x2="100" y2="172" opacity="0.2"/>
495
+ <line x1="28" y1="100" x2="172" y2="100" opacity="0.2"/>
496
+ </g>
497
+ </symbol>
498
+ <symbol id="glyph-forgemaster" viewBox="0 0 200 200">
499
+ <g stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round">
500
+ <path d="M60,120 L60,90 Q60,70 80,70 L140,70 Q160,70 160,90 L160,120" fill="currentColor" opacity="0.06"/>
501
+ <line x1="50" y1="120" x2="170" y2="120"/>
502
+ <rect x="80" y="120" width="60" height="20" rx="2" fill="currentColor" opacity="0.06"/>
503
+ <line x1="80" y1="140" x2="140" y2="140"/>
504
+ <rect x="90" y="140" width="40" height="25" rx="2" fill="currentColor" opacity="0.04"/>
505
+ <line x1="115" y1="55" x2="120" y2="40" opacity="0.5"/>
506
+ <line x1="120" y1="40" x2="125" y2="48" opacity="0.5"/>
507
+ <line x1="130" y1="50" x2="138" y2="38" opacity="0.3"/>
508
+ </g>
509
+ </symbol>
510
+ <symbol id="glyph-illuminator" viewBox="0 0 200 200">
511
+ <g stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round">
512
+ <polygon points="100,40 50,150 150,150" fill="currentColor" opacity="0.05"/>
513
+ <line x1="30" y1="100" x2="75" y2="100" opacity="0.4"/>
514
+ <line x1="130" y1="80" x2="175" y2="60" opacity="0.3"/>
515
+ <line x1="130" y1="100" x2="180" y2="100" opacity="0.3"/>
516
+ <line x1="130" y1="120" x2="175" y2="140" opacity="0.3"/>
517
+ </g>
518
+ </symbol>
519
+ <symbol id="glyph-architect" viewBox="0 0 200 200">
520
+ <g stroke="currentColor" stroke-width="1" fill="none" opacity="0.3">
521
+ <rect x="40" y="40" width="120" height="120" rx="2"/>
522
+ <line x1="40" y1="80" x2="160" y2="80"/><line x1="40" y1="120" x2="160" y2="120"/>
523
+ <line x1="80" y1="40" x2="80" y2="160"/><line x1="120" y1="40" x2="120" y2="160"/>
524
+ <circle cx="80" cy="80" r="3" fill="currentColor" opacity="0.5"/>
525
+ <circle cx="120" cy="120" r="3" fill="currentColor" opacity="0.5"/>
526
+ </g>
527
+ </symbol>
528
+ <symbol id="glyph-conductor" viewBox="0 0 200 200">
529
+ <g stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round">
530
+ <path d="M20,100 Q45,40 70,100 Q95,160 120,100 Q145,40 170,100" opacity="0.4"/>
531
+ <path d="M20,100 Q45,60 70,100 Q95,140 120,100 Q145,60 170,100" opacity="0.2"/>
532
+ <circle cx="70" cy="100" r="3" fill="currentColor" opacity="0.3"/>
533
+ <circle cx="120" cy="100" r="3" fill="currentColor" opacity="0.3"/>
534
+ </g>
535
+ </symbol>
536
+ <symbol id="glyph-polymath" viewBox="0 0 200 200">
537
+ <g stroke="currentColor" stroke-width="1.5" fill="none">
538
+ <circle cx="100" cy="72" r="35" fill="currentColor" opacity="0.04"/>
539
+ <circle cx="72" cy="120" r="35" fill="currentColor" opacity="0.04"/>
540
+ <circle cx="128" cy="120" r="35" fill="currentColor" opacity="0.04"/>
541
+ <circle cx="100" cy="100" r="8" fill="currentColor" opacity="0.1"/>
542
+ </g>
543
+ </symbol>
544
+ </defs>
545
+ </svg>
546
+
547
+ <div class="page">
548
+ <div class="mark">
549
+ Skill Tree
550
+ <span class="mark-sub">AI Fluency Profile</span>
551
+ </div>
552
+
553
+ <div class="card" id="character-card"></div>
554
+ <div class="tree" id="skill-tree"></div>
555
+ <div class="quest" id="growth-quest"></div>
556
+
557
+ <div class="footer">
558
+ <div class="footer-text">
559
+ Behaviors from <a href="https://www.anthropic.com/research/AI-fluency-index" target="_blank">Anthropic's AI Fluency Index</a>
560
+ &middot; Framework by <a href="https://aifluencyframework.org/" target="_blank">Dakan &amp; Feller</a>
561
+ &middot; Built by <a href="https://github.com/robertnowell" target="_blank">Robert Nowell</a>
562
+ </div>
563
+ </div>
564
+ </div>
565
+
566
+ <script>
567
+ const PROFILE = __PROFILE_DATA__;
568
+
569
+ const AXIS_COLORS = {
570
+ Specification: '#cca67b',
571
+ Evaluation: '#7bcc96',
572
+ Setup: '#7ba3cc',
573
+ };
574
+
575
+ function renderCharacterCard(profile) {
576
+ const a = profile.archetype || {};
577
+ const el = document.getElementById('character-card');
578
+ const key = a.key || 'catalyst';
579
+
580
+ el.setAttribute('data-archetype', key);
581
+
582
+ const aboveCount = Object.values(profile.behaviors).filter(b => b.above_baseline).length;
583
+ const glyphId = 'glyph-' + (a.glyph || key);
584
+
585
+ el.innerHTML = `
586
+ <div class="card-accent-bar"></div>
587
+ <div class="card-hero">
588
+ <svg class="glyph-watermark"><use href="#${glyphId}"/></svg>
589
+ <div class="archetype-label">Your Archetype</div>
590
+ <div class="archetype-name">${a.name || 'Unknown'}</div>
591
+ <div class="archetype-tagline">${a.tagline || ''}</div>
592
+ <div class="stats-row">
593
+ <div class="stat">
594
+ <div class="stat-value">${profile.total_sessions}</div>
595
+ <div class="stat-label">Sessions</div>
596
+ </div>
597
+ <div class="stat">
598
+ <div class="stat-value">${aboveCount}/11</div>
599
+ <div class="stat-label">Above Avg</div>
600
+ </div>
601
+ <div class="stat">
602
+ <div class="stat-value">${Math.round((a.axis_scores?.specification || 0) * 100)}%</div>
603
+ <div class="stat-label">Specification</div>
604
+ </div>
605
+ <div class="stat">
606
+ <div class="stat-value">${Math.round((a.axis_scores?.evaluation || 0) * 100)}%</div>
607
+ <div class="stat-label">Evaluation</div>
608
+ </div>
609
+ </div>
610
+ </div>
611
+ <div class="superpower">
612
+ <svg class="superpower-icon" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
613
+ <path d="M10 2L12 8L18 10L12 12L10 18L8 12L2 10L8 8Z"/>
614
+ </svg>
615
+ <div class="superpower-text"><strong>Superpower:</strong> ${a.superpower || ''}</div>
616
+ </div>
617
+ ${a.description ? `<div class="vibe"><div class="vibe-text">${a.description}</div></div>` : ''}
618
+ `;
619
+ }
620
+
621
+ function renderSkillTree(profile) {
622
+ const el = document.getElementById('skill-tree');
623
+ const branches = profile.branches || {};
624
+ const iterationRate = profile.behaviors?.iterative_improvement?.rate || 0;
625
+
626
+ let branchesHtml = '';
627
+
628
+ // Iteration gateway
629
+ const iterPct = Math.round(iterationRate * 100);
630
+ branchesHtml += `
631
+ <div class="gateway">
632
+ <div class="gateway-label">Iteration (gateway)</div>
633
+ <div class="gateway-bar">
634
+ <div class="gateway-fill" data-width="${iterPct}"></div>
635
+ </div>
636
+ <div class="gateway-pct">${iterPct}%</div>
637
+ </div>`;
638
+
639
+ for (const [name, branch] of Object.entries(branches)) {
640
+ const color = AXIS_COLORS[name] || '#666';
641
+ const behaviorsHtml = (branch.behaviors || []).map(key => {
642
+ const b = profile.behaviors[key] || {};
643
+ const pct = Math.round((b.rate || 0) * 100);
644
+ const baseline = Math.round((b.baseline || 0) * 100);
645
+ const cmp = pct > baseline ? 'above' : pct < baseline ? 'below' : 'at';
646
+ const arrow = pct > baseline ? '\u2191' : pct < baseline ? '\u2193' : '=';
647
+
648
+ return `<div class="behavior-row">
649
+ <div class="behavior-name">${b.label || key}</div>
650
+ <div class="bar-track">
651
+ <div class="bar-fill" style="background:${color}" data-width="${pct}"></div>
652
+ <div class="bar-baseline" style="left:${baseline}%"></div>
653
+ </div>
654
+ <div class="behavior-pct">${pct}%</div>
655
+ <div class="behavior-comparison ${cmp}">${arrow}</div>
656
+ </div>`;
657
+ }).join('');
658
+
659
+ const desc = branch.description ? `<span class="branch-desc">\u2014 ${branch.description}</span>` : '';
660
+
661
+ branchesHtml += `
662
+ <div class="branch">
663
+ <div class="branch-header">
664
+ <div class="branch-dot" style="background:${color}"></div>
665
+ <div class="branch-name">${name} ${desc}</div>
666
+ <div class="branch-score">${Math.round(branch.score * 100)}%</div>
667
+ </div>
668
+ ${behaviorsHtml}
669
+ </div>`;
670
+ }
671
+
672
+ el.innerHTML = `
673
+ <div class="tree-header">
674
+ <div class="tree-title">Skill Tree</div>
675
+ <div class="tree-sub">11 behaviors &middot; 3 axes &middot; tick marks show population average</div>
676
+ </div>
677
+ ${branchesHtml}
678
+ `;
679
+
680
+ requestAnimationFrame(() => {
681
+ requestAnimationFrame(() => {
682
+ el.querySelectorAll('.bar-fill, .gateway-fill').forEach(bar => {
683
+ bar.style.width = bar.dataset.width + '%';
684
+ });
685
+ });
686
+ });
687
+ }
688
+
689
+ function renderGrowthQuest(profile) {
690
+ const el = document.getElementById('growth-quest');
691
+ const a = profile.archetype || {};
692
+ const ge = profile.growth_edge || {};
693
+
694
+ if (a.key) {
695
+ el.setAttribute('data-archetype', a.key);
696
+ el.style.setProperty('--a-primary', a.color || '#9e9589');
697
+ el.style.setProperty('--a-glow', (a.color || '#9e9589') + '10');
698
+ }
699
+
700
+ const targetKey = a.target_archetype;
701
+ const pathHtml = targetKey
702
+ ? `<div class="quest-path">
703
+ <strong>${a.name}</strong>
704
+ <span class="quest-arrow">\u2192</span>
705
+ <strong>The ${targetKey.charAt(0).toUpperCase() + targetKey.slice(1)}</strong>
706
+ </div>`
707
+ : '';
708
+
709
+ el.innerHTML = `
710
+ <div class="quest-label">\u25C6 Next Unlock</div>
711
+ <div class="quest-title">${a.growth_unlock || 'Keep growing'}</div>
712
+ <div class="quest-text">${a.growth_quest || ''}</div>
713
+ <div class="quest-path">
714
+ <strong>Growth edge:</strong> ${ge.label || ''} \u2014
715
+ you're at ${Math.round((ge.rate || 0) * 100)}%, population average is ${Math.round((ge.baseline || 0) * 100)}%
716
+ </div>
717
+ ${pathHtml}
718
+ `;
719
+ }
720
+
721
+ if (PROFILE && PROFILE.behaviors) {
722
+ renderCharacterCard(PROFILE);
723
+ renderSkillTree(PROFILE);
724
+ renderGrowthQuest(PROFILE);
725
+ }
726
+ </script>
727
+ </body>
728
+ </html>