hyperframes 0.5.0-alpha.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/cli.js +7518 -5457
  2. package/dist/commands/contrast-audit.browser.js +2 -0
  3. package/dist/docs/compositions.md +35 -7
  4. package/dist/docs/rendering.md +4 -1
  5. package/dist/hyperframe-runtime.js +82 -32
  6. package/dist/hyperframe.manifest.json +1 -1
  7. package/dist/hyperframe.runtime.iife.js +82 -32
  8. package/dist/skills/gsap/SKILL.md +30 -1
  9. package/dist/skills/hyperframes/SKILL.md +165 -39
  10. package/dist/skills/hyperframes/house-style.md +3 -1
  11. package/dist/skills/hyperframes/patterns.md +73 -0
  12. package/dist/skills/hyperframes/references/beat-direction.md +102 -0
  13. package/dist/skills/hyperframes/references/design-picker.md +117 -0
  14. package/dist/skills/hyperframes/references/motion-principles.md +73 -0
  15. package/dist/skills/hyperframes/references/narration.md +92 -0
  16. package/dist/skills/hyperframes/references/prompt-expansion.md +68 -0
  17. package/dist/skills/hyperframes/references/techniques.md +387 -0
  18. package/dist/skills/hyperframes/references/transcript-guide.md +1 -45
  19. package/dist/skills/hyperframes/references/video-composition.md +62 -0
  20. package/dist/skills/hyperframes/scripts/contrast-report.mjs +10 -0
  21. package/dist/skills/hyperframes/templates/design-picker.html +1432 -0
  22. package/dist/skills/hyperframes/visual-styles.md +339 -107
  23. package/dist/skills/hyperframes-cli/SKILL.md +21 -27
  24. package/dist/studio/assets/hyperframes-player-CoI5h1xv.js +353 -0
  25. package/dist/studio/assets/index-BKjcNNNd.css +1 -0
  26. package/dist/studio/assets/index-CqiisJmo.js +93 -0
  27. package/dist/studio/index.html +2 -2
  28. package/dist/templates/_shared/AGENTS.md +7 -7
  29. package/dist/templates/_shared/CLAUDE.md +15 -7
  30. package/package.json +4 -2
  31. package/dist/skills/hyperframes/references/tts.md +0 -75
  32. package/dist/studio/assets/hyperframes-player-vibA20NC.js +0 -198
  33. package/dist/studio/assets/index-0Zt0t13W.css +0 -1
  34. package/dist/studio/assets/index-C9f5eif8.js +0 -105
@@ -0,0 +1,1432 @@
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" />
6
+ <title>Design your visual direction</title>
7
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+ body {
15
+ font-family:
16
+ system-ui,
17
+ -apple-system,
18
+ sans-serif;
19
+ background: #0e0e0e;
20
+ color: #eee;
21
+ height: 100vh;
22
+ overflow: hidden;
23
+ display: flex;
24
+ flex-direction: column;
25
+ font-size: 13px;
26
+ line-height: 1.4;
27
+ -webkit-font-smoothing: antialiased;
28
+ }
29
+
30
+ /* ── Phase bar ── */
31
+ .phase-bar {
32
+ display: flex;
33
+ border-bottom: 1px solid #1a1a1a;
34
+ padding: 0 20px;
35
+ flex-shrink: 0;
36
+ background: #111;
37
+ }
38
+ .phase-tab {
39
+ padding: 12px 16px;
40
+ font-size: 12px;
41
+ font-weight: 600;
42
+ color: #555;
43
+ cursor: pointer;
44
+ border-bottom: 2px solid transparent;
45
+ transition: all 0.15s;
46
+ letter-spacing: 0.02em;
47
+ }
48
+ .phase-tab.active {
49
+ color: #fff;
50
+ border-bottom-color: #fff;
51
+ }
52
+ .phase-tab.disabled {
53
+ opacity: 0.25;
54
+ pointer-events: none;
55
+ }
56
+
57
+ /* ── Phases ── */
58
+ .phase {
59
+ display: none;
60
+ flex: 1;
61
+ overflow: hidden;
62
+ }
63
+ .phase.active {
64
+ display: flex;
65
+ }
66
+
67
+ /* ── Phase 1: Mood boards ── */
68
+ .mood-grid {
69
+ display: grid;
70
+ grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
71
+ gap: 16px;
72
+ padding: 20px;
73
+ overflow-y: auto;
74
+ flex: 1;
75
+ align-content: start;
76
+ }
77
+ .mood-card {
78
+ border: 1px solid #1e1e1e;
79
+ border-radius: 12px;
80
+ overflow: hidden;
81
+ cursor: pointer;
82
+ transition:
83
+ border-color 0.15s,
84
+ transform 0.15s,
85
+ box-shadow 0.15s;
86
+ background: #141414;
87
+ display: flex;
88
+ flex-direction: column;
89
+ }
90
+ .mood-card:hover {
91
+ border-color: #333;
92
+ transform: translateY(-1px);
93
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
94
+ }
95
+ .mood-card.selected {
96
+ border-color: #fff;
97
+ }
98
+ .mood-preview {
99
+ height: 500px;
100
+ overflow: hidden;
101
+ position: relative;
102
+ background: #0a0a0a;
103
+ }
104
+ .mood-preview > div {
105
+ transform-origin: top left;
106
+ }
107
+ .mood-info {
108
+ padding: 14px 16px;
109
+ }
110
+ .mood-name {
111
+ font-size: 14px;
112
+ font-weight: 600;
113
+ margin-bottom: 3px;
114
+ }
115
+ .mood-desc {
116
+ font-size: 11px;
117
+ color: #666;
118
+ line-height: 1.4;
119
+ display: -webkit-box;
120
+ -webkit-line-clamp: 2;
121
+ -webkit-box-orient: vertical;
122
+ overflow: hidden;
123
+ }
124
+ .mood-tokens {
125
+ display: flex;
126
+ gap: 4px;
127
+ margin-top: 8px;
128
+ flex-wrap: wrap;
129
+ }
130
+ .mood-token {
131
+ font-size: 9px;
132
+ color: #555;
133
+ background: #1a1a1a;
134
+ padding: 2px 7px;
135
+ border-radius: 3px;
136
+ letter-spacing: 0.02em;
137
+ }
138
+
139
+ .mood-header {
140
+ padding: 20px 20px 0;
141
+ flex-shrink: 0;
142
+ }
143
+ .mood-header h2 {
144
+ font-size: 16px;
145
+ font-weight: 600;
146
+ margin-bottom: 2px;
147
+ }
148
+ .mood-header p {
149
+ font-size: 12px;
150
+ color: #555;
151
+ }
152
+ .mood-next {
153
+ padding: 12px 20px;
154
+ flex-shrink: 0;
155
+ display: flex;
156
+ justify-content: flex-end;
157
+ }
158
+ .mood-next-btn {
159
+ background: #fff;
160
+ color: #000;
161
+ border: none;
162
+ padding: 10px 24px;
163
+ border-radius: 8px;
164
+ font-size: 13px;
165
+ font-weight: 600;
166
+ cursor: pointer;
167
+ opacity: 0;
168
+ transform: translateY(8px);
169
+ transition: all 0.2s;
170
+ }
171
+ .mood-next-btn.visible {
172
+ opacity: 1;
173
+ transform: translateY(0);
174
+ }
175
+ .mood-next-btn:hover {
176
+ background: #ddd;
177
+ }
178
+
179
+ /* ── Phase 2: Fine-tune ── */
180
+ .panel-left {
181
+ width: 400px;
182
+ min-width: 400px;
183
+ height: 100%;
184
+ overflow-y: auto;
185
+ border-right: 1px solid #1a1a1a;
186
+ padding: 0 0 100px;
187
+ background: #111;
188
+ }
189
+ .panel-right {
190
+ flex: 1;
191
+ height: 100%;
192
+ overflow-y: auto;
193
+ overflow-x: hidden;
194
+ background: #0e0e0e;
195
+ }
196
+ .panel-right * {
197
+ max-width: 100%;
198
+ box-sizing: border-box;
199
+ }
200
+
201
+ /* ── Section cards (Neuform-inspired) ── */
202
+ .section-card {
203
+ border-bottom: 1px solid #1a1a1a;
204
+ }
205
+ .section-header {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 8px;
209
+ padding: 14px 16px 6px;
210
+ }
211
+ .section-icon {
212
+ width: 22px;
213
+ height: 22px;
214
+ border-radius: 5px;
215
+ background: rgba(255, 255, 255, 0.04);
216
+ display: flex;
217
+ align-items: center;
218
+ justify-content: center;
219
+ color: #555;
220
+ font-size: 11px;
221
+ flex-shrink: 0;
222
+ }
223
+ .section-title {
224
+ font-size: 11px;
225
+ font-weight: 600;
226
+ color: #fff;
227
+ letter-spacing: 0.01em;
228
+ }
229
+ .section-meta {
230
+ font-size: 10px;
231
+ color: #444;
232
+ margin-left: auto;
233
+ }
234
+ .section-body {
235
+ padding: 6px 16px 16px;
236
+ }
237
+
238
+ /* ── Option cards ── */
239
+ .opt {
240
+ border: 1px solid #1e1e1e;
241
+ border-radius: 10px;
242
+ margin-bottom: 6px;
243
+ cursor: pointer;
244
+ transition: border-color 0.12s;
245
+ overflow: hidden;
246
+ background: #141414;
247
+ position: relative;
248
+ }
249
+ .opt:hover {
250
+ border-color: #333;
251
+ }
252
+ .opt.selected {
253
+ border-color: #fff;
254
+ }
255
+ .opt-inner {
256
+ padding: 12px 14px;
257
+ }
258
+ .opt-name {
259
+ font-size: 12px;
260
+ font-weight: 600;
261
+ margin-bottom: 2px;
262
+ }
263
+ .opt-desc {
264
+ font-size: 10px;
265
+ color: #666;
266
+ line-height: 1.4;
267
+ }
268
+ .opt-tag {
269
+ font-size: 9px;
270
+ color: #444;
271
+ margin-top: 4px;
272
+ text-transform: uppercase;
273
+ letter-spacing: 0.04em;
274
+ }
275
+ .opt-rec {
276
+ position: absolute;
277
+ top: 8px;
278
+ right: 10px;
279
+ font-size: 8px;
280
+ font-weight: 700;
281
+ color: #4ade80;
282
+ background: rgba(74, 222, 128, 0.08);
283
+ padding: 2px 6px;
284
+ border-radius: 3px;
285
+ text-transform: uppercase;
286
+ letter-spacing: 0.04em;
287
+ }
288
+
289
+ /* ── Palette option ── */
290
+ .pal-strip {
291
+ display: flex;
292
+ height: 28px;
293
+ border-radius: 6px;
294
+ overflow: hidden;
295
+ margin-bottom: 8px;
296
+ }
297
+ .pal-strip > div {
298
+ flex: 1;
299
+ }
300
+ .pal-ramp {
301
+ display: flex;
302
+ gap: 2px;
303
+ margin-top: 4px;
304
+ }
305
+ .pal-ramp-swatch {
306
+ width: 100%;
307
+ height: 6px;
308
+ border-radius: 2px;
309
+ }
310
+
311
+ /* ── Type option (specimen) ── */
312
+ .type-specimen {
313
+ padding: 14px;
314
+ border-bottom: 1px solid #1a1a1a;
315
+ }
316
+ .type-headline {
317
+ line-height: 1.1;
318
+ letter-spacing: -0.02em;
319
+ margin-bottom: 6px;
320
+ }
321
+ .type-body {
322
+ line-height: 1.5;
323
+ color: #666;
324
+ font-size: 11px;
325
+ }
326
+ .type-meta {
327
+ padding: 10px 14px;
328
+ display: flex;
329
+ justify-content: space-between;
330
+ align-items: center;
331
+ }
332
+ .type-families {
333
+ font-size: 9px;
334
+ color: #444;
335
+ letter-spacing: 0.02em;
336
+ }
337
+ .type-letters {
338
+ font-size: 9px;
339
+ color: #333;
340
+ letter-spacing: 0.08em;
341
+ overflow: hidden;
342
+ white-space: nowrap;
343
+ text-overflow: ellipsis;
344
+ max-width: 200px;
345
+ }
346
+
347
+ /* ── Chip options ── */
348
+ .chips {
349
+ display: flex;
350
+ gap: 6px;
351
+ flex-wrap: wrap;
352
+ }
353
+ .chip {
354
+ border: 1px solid #1e1e1e;
355
+ border-radius: 8px;
356
+ padding: 8px 12px;
357
+ cursor: pointer;
358
+ transition: border-color 0.12s;
359
+ display: flex;
360
+ align-items: center;
361
+ gap: 8px;
362
+ background: #141414;
363
+ }
364
+ .chip:hover {
365
+ border-color: #333;
366
+ }
367
+ .chip.selected {
368
+ border-color: #fff;
369
+ }
370
+ .chip-label {
371
+ font-size: 11px;
372
+ font-weight: 500;
373
+ }
374
+ .chip-sub {
375
+ font-size: 9px;
376
+ color: #555;
377
+ }
378
+ .chip-preview {
379
+ flex-shrink: 0;
380
+ }
381
+
382
+ .theme-chip {
383
+ flex: 1;
384
+ min-width: 90px;
385
+ flex-direction: column;
386
+ align-items: center;
387
+ padding: 10px 12px;
388
+ text-align: center;
389
+ }
390
+ .theme-swatch {
391
+ width: 100%;
392
+ height: 28px;
393
+ border-radius: 4px;
394
+ margin-bottom: 4px;
395
+ border: 1px solid rgba(255, 255, 255, 0.06);
396
+ }
397
+ .corner-box {
398
+ width: 22px;
399
+ height: 22px;
400
+ border: 2px solid #666;
401
+ }
402
+ .density-bars {
403
+ display: flex;
404
+ flex-direction: column;
405
+ width: 24px;
406
+ }
407
+ .density-bar {
408
+ background: #666;
409
+ height: 3px;
410
+ border-radius: 1px;
411
+ }
412
+ .depth-square {
413
+ width: 22px;
414
+ height: 22px;
415
+ background: #2a2a2a;
416
+ border-radius: 3px;
417
+ }
418
+
419
+ /* ── Easing option ── */
420
+ .ease-opt {
421
+ border: 1px solid #1e1e1e;
422
+ border-radius: 10px;
423
+ margin-bottom: 6px;
424
+ cursor: pointer;
425
+ transition: border-color 0.12s;
426
+ overflow: hidden;
427
+ background: #141414;
428
+ padding: 10px 14px;
429
+ }
430
+ .ease-opt:hover {
431
+ border-color: #333;
432
+ }
433
+ .ease-opt.selected {
434
+ border-color: #fff;
435
+ }
436
+ .ease-track {
437
+ position: relative;
438
+ height: 8px;
439
+ background: #1a1a1a;
440
+ border-radius: 4px;
441
+ margin-bottom: 8px;
442
+ overflow: visible;
443
+ }
444
+ .ease-dot {
445
+ position: absolute;
446
+ top: 50%;
447
+ transform: translateY(-50%);
448
+ left: 0;
449
+ width: 12px;
450
+ height: 12px;
451
+ border-radius: 50%;
452
+ background: #fff;
453
+ }
454
+ .ease-label {
455
+ display: flex;
456
+ justify-content: space-between;
457
+ align-items: center;
458
+ }
459
+ .ease-name {
460
+ font-size: 11px;
461
+ font-weight: 600;
462
+ }
463
+ .ease-value {
464
+ font-size: 9px;
465
+ color: #444;
466
+ font-family: "SF Mono", Consolas, monospace;
467
+ letter-spacing: 0.02em;
468
+ }
469
+
470
+ .preview-empty {
471
+ display: flex;
472
+ align-items: center;
473
+ justify-content: center;
474
+ height: 100%;
475
+ color: #2a2a2a;
476
+ font-size: 13px;
477
+ }
478
+
479
+ /* ── FAB + Overlay ── */
480
+ .fab {
481
+ position: fixed;
482
+ bottom: 20px;
483
+ right: 32px;
484
+ transform: translateY(60px);
485
+ opacity: 0;
486
+ background: #fff;
487
+ color: #000;
488
+ border: none;
489
+ padding: 12px 24px;
490
+ border-radius: 10px;
491
+ font-size: 13px;
492
+ font-weight: 600;
493
+ cursor: pointer;
494
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
495
+ transition:
496
+ transform 0.25s ease,
497
+ opacity 0.25s ease;
498
+ z-index: 100;
499
+ }
500
+ .fab.visible {
501
+ transform: translateY(0);
502
+ opacity: 1;
503
+ }
504
+ .fab:hover {
505
+ background: #ddd;
506
+ }
507
+
508
+ .md-overlay {
509
+ position: fixed;
510
+ inset: 0;
511
+ background: rgba(0, 0, 0, 0.85);
512
+ backdrop-filter: blur(8px);
513
+ z-index: 200;
514
+ display: none;
515
+ align-items: center;
516
+ justify-content: center;
517
+ }
518
+ .md-overlay.visible {
519
+ display: flex;
520
+ }
521
+ .md-card {
522
+ background: #161616;
523
+ border: 1px solid #2a2a2a;
524
+ border-radius: 14px;
525
+ max-width: 600px;
526
+ width: 90%;
527
+ max-height: 80vh;
528
+ display: flex;
529
+ flex-direction: column;
530
+ }
531
+ .md-header {
532
+ padding: 16px 20px;
533
+ border-bottom: 1px solid #1e1e1e;
534
+ display: flex;
535
+ justify-content: space-between;
536
+ align-items: center;
537
+ }
538
+ .md-title {
539
+ font-size: 14px;
540
+ font-weight: 600;
541
+ }
542
+ .md-actions {
543
+ display: flex;
544
+ gap: 6px;
545
+ }
546
+ .copy-btn {
547
+ background: #fff;
548
+ color: #000;
549
+ border: none;
550
+ padding: 7px 16px;
551
+ border-radius: 6px;
552
+ font-size: 12px;
553
+ font-weight: 600;
554
+ cursor: pointer;
555
+ }
556
+ .copy-btn:hover {
557
+ background: #ddd;
558
+ }
559
+ .close-btn {
560
+ background: transparent;
561
+ color: #666;
562
+ border: 1px solid #2a2a2a;
563
+ padding: 7px 14px;
564
+ border-radius: 6px;
565
+ font-size: 12px;
566
+ cursor: pointer;
567
+ }
568
+ .close-btn:hover {
569
+ color: #fff;
570
+ border-color: #444;
571
+ }
572
+ .md-body {
573
+ padding: 20px;
574
+ overflow-y: auto;
575
+ flex: 1;
576
+ }
577
+ .md-editor {
578
+ font-family: "SF Mono", Consolas, monospace;
579
+ font-size: 12px;
580
+ line-height: 1.6;
581
+ color: #aaa;
582
+ background: transparent;
583
+ border: none;
584
+ width: 100%;
585
+ min-height: 360px;
586
+ resize: vertical;
587
+ outline: none;
588
+ white-space: pre-wrap;
589
+ }
590
+
591
+ /* ── Phase 1 palette bar ── */
592
+ .pal-bar {
593
+ display: flex;
594
+ gap: 8px;
595
+ padding: 12px 20px 0;
596
+ flex-shrink: 0;
597
+ flex-wrap: wrap;
598
+ align-items: center;
599
+ }
600
+ .pal-bar-label {
601
+ font-size: 10px;
602
+ color: #444;
603
+ letter-spacing: 0.03em;
604
+ text-transform: uppercase;
605
+ margin-right: 4px;
606
+ }
607
+ .pal-bar-chip {
608
+ display: flex;
609
+ align-items: center;
610
+ gap: 6px;
611
+ padding: 5px 10px;
612
+ border: 1px solid #1e1e1e;
613
+ border-radius: 6px;
614
+ cursor: pointer;
615
+ transition: border-color 0.12s;
616
+ background: #141414;
617
+ }
618
+ .pal-bar-chip:hover {
619
+ border-color: #333;
620
+ }
621
+ .pal-bar-chip.active {
622
+ border-color: #fff;
623
+ }
624
+ .pal-bar-chip-swatches {
625
+ display: flex;
626
+ gap: 2px;
627
+ }
628
+ .pal-bar-chip-swatch {
629
+ width: 14px;
630
+ height: 14px;
631
+ border-radius: 3px;
632
+ }
633
+ .pal-bar-chip-name {
634
+ font-size: 10px;
635
+ font-weight: 500;
636
+ color: #888;
637
+ }
638
+ </style>
639
+ </head>
640
+ <body>
641
+ <div class="phase-bar">
642
+ <div class="phase-tab active" id="tab-mood" onclick="showPhase('mood')">1. Direction</div>
643
+ <div class="phase-tab disabled" id="tab-tune" onclick="showPhase('tune')">2. Fine-tune</div>
644
+ </div>
645
+
646
+ <!-- Phase 1: Mood boards -->
647
+ <div class="phase active" id="phase-mood" style="flex-direction: column">
648
+ <div class="mood-header">
649
+ <h2 id="mood-title">Pick a direction</h2>
650
+ <p id="mood-subtitle">
651
+ Each option is a complete visual identity. Pick one, then fine-tune.
652
+ </p>
653
+ </div>
654
+ <div class="pal-bar" id="pal-bar"><span class="pal-bar-label">Palette</span></div>
655
+ <div class="mood-grid" id="mood-grid"></div>
656
+ <div class="mood-next">
657
+ <button class="mood-next-btn" id="mood-next-btn" onclick="goToTune()">
658
+ Customize this direction →
659
+ </button>
660
+ </div>
661
+ </div>
662
+
663
+ <!-- Phase 2: Fine-tune -->
664
+ <div class="phase" id="phase-tune" style="flex-direction: row">
665
+ <div class="panel-left">
666
+ <!-- Theme -->
667
+ <div class="section-card">
668
+ <div class="section-header">
669
+ <div class="section-icon">◐</div>
670
+ <div class="section-title">Theme</div>
671
+ </div>
672
+ <div class="section-body"><div class="chips" id="theme-options"></div></div>
673
+ </div>
674
+ <!-- Structure -->
675
+ <div class="section-card">
676
+ <div class="section-header">
677
+ <div class="section-icon">▦</div>
678
+ <div class="section-title">Structure</div>
679
+ <div class="section-meta" id="arch-meta"></div>
680
+ </div>
681
+ <div class="section-body" id="arch-options"></div>
682
+ </div>
683
+ <!-- Palette -->
684
+ <div class="section-card">
685
+ <div class="section-header">
686
+ <div class="section-icon">◉</div>
687
+ <div class="section-title">Color</div>
688
+ </div>
689
+ <div class="section-body" id="pal-options"></div>
690
+ </div>
691
+ <!-- Typography -->
692
+ <div class="section-card">
693
+ <div class="section-header">
694
+ <div class="section-icon">Aa</div>
695
+ <div class="section-title">Typography</div>
696
+ </div>
697
+ <div class="section-body" id="type-options"></div>
698
+ </div>
699
+ <!-- Corners -->
700
+ <div class="section-card">
701
+ <div class="section-header">
702
+ <div class="section-icon">⬔</div>
703
+ <div class="section-title">Corners</div>
704
+ </div>
705
+ <div class="section-body"><div class="chips" id="corner-options"></div></div>
706
+ </div>
707
+ <!-- Density -->
708
+ <div class="section-card">
709
+ <div class="section-header">
710
+ <div class="section-icon">≡</div>
711
+ <div class="section-title">Density</div>
712
+ </div>
713
+ <div class="section-body"><div class="chips" id="density-options"></div></div>
714
+ </div>
715
+ <!-- Depth -->
716
+ <div class="section-card">
717
+ <div class="section-header">
718
+ <div class="section-icon">◧</div>
719
+ <div class="section-title">Depth</div>
720
+ </div>
721
+ <div class="section-body"><div class="chips" id="depth-options"></div></div>
722
+ </div>
723
+ <!-- Motion / Easing -->
724
+ <div class="section-card">
725
+ <div class="section-header">
726
+ <div class="section-icon">⟿</div>
727
+ <div class="section-title">Motion</div>
728
+ <div class="section-meta">entry easing</div>
729
+ </div>
730
+ <div class="section-body" id="ease-options"></div>
731
+ </div>
732
+ </div>
733
+ <div class="panel-right" id="preview">
734
+ <div class="preview-empty">Pick a structure to preview</div>
735
+ </div>
736
+ </div>
737
+
738
+ <button class="fab" id="fab" onclick="showOutput()">Create design.md</button>
739
+
740
+ <div class="md-overlay" id="md-overlay">
741
+ <div class="md-card">
742
+ <div class="md-header">
743
+ <div class="md-title">
744
+ design.md
745
+ <span style="font-size: 11px; font-weight: 400; color: #555">— edit, then copy</span>
746
+ </div>
747
+ <div class="md-actions">
748
+ <button class="copy-btn" id="copy-btn">Copy</button>
749
+ <button
750
+ class="close-btn"
751
+ onclick="document.getElementById('md-overlay').classList.remove('visible')"
752
+ >
753
+ Close
754
+ </button>
755
+ </div>
756
+ </div>
757
+ <div class="md-body">
758
+ <textarea class="md-editor" id="md-output" spellcheck="false"></textarea>
759
+ </div>
760
+ </div>
761
+ </div>
762
+
763
+ <script>
764
+ var ARCHITECTURES = __ARCHITECTURES_JSON__;
765
+ var PALETTES = __PALETTES_JSON__;
766
+ var TYPEPAIRS = __TYPEPAIRS_JSON__;
767
+ var MOODBOARDS = __MOODBOARDS_JSON__;
768
+ var PROMPT = __PROMPT_JSON__;
769
+ var picks = {
770
+ theme: null,
771
+ arch: null,
772
+ palette: null,
773
+ type: null,
774
+ corners: null,
775
+ density: null,
776
+ depth: null,
777
+ easing: null,
778
+ };
779
+
780
+ var EASINGS = [
781
+ { name: "Confident", value: "power3.out", desc: "Fast start, smooth deceleration" },
782
+ { name: "Snappy", value: "expo.out", desc: "Very fast start, crisp stop" },
783
+ { name: "Gentle", value: "sine.inOut", desc: "Soft acceleration and deceleration" },
784
+ { name: "Bouncy", value: "back.out(1.4)", desc: "Overshoots then settles" },
785
+ { name: "Elastic", value: "elastic.out(1, 0.5)", desc: "Springs past target and wobbles" },
786
+ { name: "Sharp", value: "power4.out", desc: "Aggressive start, hard stop" },
787
+ ];
788
+
789
+ var THEMES = [
790
+ { name: "Dark", id: "dark", bg: "#0e0e0e", fg: "#eee", desc: "Light on dark" },
791
+ { name: "Light", id: "light", bg: "#f5f3ef", fg: "#1a1a1a", desc: "Dark on light" },
792
+ { name: "Palette", id: "palette", bg: null, fg: null, desc: "Use palette colors" },
793
+ ];
794
+ var CORNERS = [
795
+ { name: "Sharp", value: "0px" },
796
+ { name: "Slight", value: "4px" },
797
+ { name: "Rounded", value: "12px" },
798
+ ];
799
+ var DENSITIES = [
800
+ { name: "Tight", padding: "8-12px", gap: "8-12px", desc: "Compact" },
801
+ { name: "Normal", padding: "16-24px", gap: "16-20px", desc: "Balanced" },
802
+ { name: "Generous", padding: "32-48px", gap: "28-40px", desc: "Spacious" },
803
+ ];
804
+ var DEPTHS = [
805
+ { name: "Flat", desc: "No shadows" },
806
+ { name: "Subtle", desc: "Faint shadows" },
807
+ { name: "Layered", desc: "Glows + depth" },
808
+ ];
809
+
810
+ // Load fonts
811
+ var fams = [];
812
+ TYPEPAIRS.forEach(function (tp) {
813
+ fams.push(tp.headline.family.replace(/ /g, "+") + ":wght@" + tp.headline.weight);
814
+ fams.push(tp.body.family.replace(/ /g, "+") + ":wght@" + tp.body.weight);
815
+ });
816
+ var lnk = document.createElement("link");
817
+ lnk.rel = "stylesheet";
818
+ lnk.href =
819
+ "https://fonts.googleapis.com/css2?family=" + fams.join("&family=") + "&display=swap";
820
+ document.head.appendChild(lnk);
821
+
822
+ function al(hex, o) {
823
+ if (!hex || typeof hex !== "string" || hex[0] !== "#") return "rgba(128,128,128," + o + ")";
824
+ if (hex.length === 4) hex = "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
825
+ var r = parseInt(hex.slice(1, 3), 16),
826
+ g = parseInt(hex.slice(3, 5), 16),
827
+ b = parseInt(hex.slice(5, 7), 16);
828
+ if (isNaN(r)) r = 128;
829
+ if (isNaN(g)) g = 128;
830
+ if (isNaN(b)) b = 128;
831
+ return "rgba(" + r + "," + g + "," + b + "," + o + ")";
832
+ }
833
+
834
+ // Prompt-aware UI
835
+ if (PROMPT && PROMPT.title)
836
+ document.getElementById("mood-title").textContent = "Pick a direction for: " + PROMPT.title;
837
+
838
+ // ── Phase 1: Mood boards + Palette bar ──
839
+ var moodGrid = document.getElementById("mood-grid");
840
+ var selectedMood = null;
841
+ var overridePalette = null;
842
+
843
+ // Build palette bar
844
+ var palBar = document.getElementById("pal-bar");
845
+ PALETTES.forEach(function (p, i) {
846
+ var chip = document.createElement("div");
847
+ chip.className = "pal-bar-chip" + (i === 0 ? "" : "");
848
+ chip.innerHTML =
849
+ '<div class="pal-bar-chip-swatches"><div class="pal-bar-chip-swatch" style="background:' +
850
+ p.background +
851
+ ';border:1px solid rgba(255,255,255,0.08);"></div><div class="pal-bar-chip-swatch" style="background:' +
852
+ p.accent +
853
+ ';"></div><div class="pal-bar-chip-swatch" style="background:' +
854
+ p.foreground +
855
+ ';border:1px solid rgba(255,255,255,0.08);"></div></div><span class="pal-bar-chip-name">' +
856
+ p.name +
857
+ "</span>";
858
+ chip.onclick = function () {
859
+ palBar.querySelectorAll(".pal-bar-chip").forEach(function (c) {
860
+ c.classList.remove("active");
861
+ });
862
+ if (overridePalette === i) {
863
+ overridePalette = null;
864
+ } else {
865
+ chip.classList.add("active");
866
+ overridePalette = i;
867
+ }
868
+ renderMoodBoards();
869
+ };
870
+ palBar.appendChild(chip);
871
+ });
872
+
873
+ function renderMoodBoards() {
874
+ var prevSelected = selectedMood;
875
+ moodGrid.innerHTML = "";
876
+ MOODBOARDS.forEach(function (mb, i) {
877
+ var card = document.createElement("div");
878
+ card.className = "mood-card" + (i === prevSelected ? " selected" : "");
879
+ var tp = TYPEPAIRS[mb.type_index || 0],
880
+ arch = ARCHITECTURES[mb.arch_index || 0];
881
+ var pal =
882
+ overridePalette !== null ? PALETTES[overridePalette] : PALETTES[mb.palette_index || 0];
883
+ var thId = mb.theme || "dark",
884
+ th =
885
+ THEMES.find(function (t) {
886
+ return t.id === thId;
887
+ }) || THEMES[0];
888
+ var bg = thId === "palette" ? pal.background : th.bg,
889
+ fg = thId === "palette" ? pal.foreground : th.fg;
890
+ var tokens = {
891
+ "{{bg}}": bg,
892
+ "{{fg}}": fg,
893
+ "{{ac}}": pal.accent,
894
+ "{{mt}}": pal.muted || pal.mid || al(fg, 0.4),
895
+ "{{hf}}": tp.headline.family,
896
+ "{{hw}}": tp.headline.weight,
897
+ "{{bf}}": tp.body.family,
898
+ "{{bw}}": tp.body.weight,
899
+ "{{cr}}": mb.corners || "4px",
900
+ "{{pad}}": mb.padding || "20px",
901
+ "{{gap}}": mb.gap || "16px",
902
+ "{{shadow}}": mb.shadow || "none",
903
+ "{{sf}}": al(fg, 0.06),
904
+ "{{g}}": al(fg, 0.06),
905
+ "{{fg3}}": al(fg, 0.03),
906
+ "{{fg6}}": al(fg, 0.06),
907
+ "{{fg8}}": al(fg, 0.08),
908
+ "{{fg15}}": al(fg, 0.15),
909
+ "{{ac3}}": al(pal.accent, 0.03),
910
+ "{{ac5}}": al(pal.accent, 0.05),
911
+ "{{ac25}}": al(pal.accent, 0.25),
912
+ "{{prompt_headline}}": (PROMPT && PROMPT.headline) || "Your Headline",
913
+ "{{prompt_sub}}": (PROMPT && PROMPT.subline) || "A subline for your product.",
914
+ };
915
+ var preview = arch.preview_html || "";
916
+ Object.keys(tokens).forEach(function (k) {
917
+ preview = preview.split(k).join(tokens[k]);
918
+ });
919
+ var tagHtml = [tp.headline.family, pal.name, CORNERS[mb.corners_index || 1].name]
920
+ .map(function (t) {
921
+ return '<span class="mood-token">' + t + "</span>";
922
+ })
923
+ .join("");
924
+ card.innerHTML =
925
+ '<div class="mood-preview"><div style="transform:scale(0.38);transform-origin:top left;width:263.16%;min-height:263.16%;">' +
926
+ preview +
927
+ '</div></div><div class="mood-info"><div class="mood-name">' +
928
+ mb.name +
929
+ '</div><div class="mood-desc">' +
930
+ mb.description +
931
+ '</div><div class="mood-tokens">' +
932
+ tagHtml +
933
+ "</div></div>";
934
+ card.onclick = function () {
935
+ moodGrid.querySelectorAll(".mood-card").forEach(function (c) {
936
+ c.classList.remove("selected");
937
+ });
938
+ card.classList.add("selected");
939
+ selectedMood = i;
940
+ document.getElementById("mood-next-btn").classList.add("visible");
941
+ };
942
+ moodGrid.appendChild(card);
943
+ });
944
+ }
945
+ renderMoodBoards();
946
+
947
+ var currentPhase = "mood";
948
+ function showPhase(name) {
949
+ currentPhase = name;
950
+ document.querySelectorAll(".phase").forEach(function (p) {
951
+ p.classList.remove("active");
952
+ });
953
+ document.querySelectorAll(".phase-tab").forEach(function (t) {
954
+ t.classList.remove("active");
955
+ });
956
+ document.getElementById("phase-" + name).classList.add("active");
957
+ document.getElementById("tab-" + name).classList.add("active");
958
+ if (name === "mood") document.getElementById("fab").classList.remove("visible");
959
+ else checkReady();
960
+ }
961
+
962
+ function goToTune() {
963
+ if (selectedMood === null) return;
964
+ var mb = MOODBOARDS[selectedMood];
965
+ var thIdx = THEMES.findIndex(function (t) {
966
+ return t.id === (mb.theme || "dark");
967
+ });
968
+ if (thIdx >= 0) chipSel("theme", thIdx, document.getElementById("theme-options"));
969
+ if (mb.arch_index != null)
970
+ sel("arch", mb.arch_index, document.getElementById("arch-options"));
971
+ var palIdx = overridePalette !== null ? overridePalette : mb.palette_index;
972
+ if (palIdx != null) sel("palette", palIdx, document.getElementById("pal-options"));
973
+ if (mb.type_index != null)
974
+ sel("type", mb.type_index, document.getElementById("type-options"));
975
+ if (mb.corners_index != null)
976
+ chipSel("corners", mb.corners_index, document.getElementById("corner-options"));
977
+ if (mb.density_index != null)
978
+ chipSel("density", mb.density_index, document.getElementById("density-options"));
979
+ if (mb.depth_index != null)
980
+ chipSel("depth", mb.depth_index, document.getElementById("depth-options"));
981
+ var eIdx = mb.easing_index != null ? mb.easing_index : 0;
982
+ var eOpts = document.getElementById("ease-options");
983
+ eOpts.querySelectorAll(".ease-opt").forEach(function (c) {
984
+ c.classList.remove("selected");
985
+ });
986
+ eOpts.children[eIdx].classList.add("selected");
987
+ picks.easing = eIdx;
988
+ document.getElementById("tab-tune").classList.remove("disabled");
989
+ showPhase("tune");
990
+ }
991
+
992
+ // ── Phase 2: Build options ──
993
+
994
+ // Architecture cards
995
+ var archOpts = document.getElementById("arch-options");
996
+ ARCHITECTURES.forEach(function (a, i) {
997
+ var el = document.createElement("div");
998
+ el.className = "opt";
999
+ el.innerHTML =
1000
+ '<div class="opt-inner"><div class="opt-name">' +
1001
+ a.name +
1002
+ '</div><div class="opt-desc">' +
1003
+ a.description +
1004
+ '</div><div class="opt-tag">' +
1005
+ a.tag +
1006
+ "</div></div>";
1007
+ el.onclick = function () {
1008
+ sel("arch", i, archOpts);
1009
+ };
1010
+ archOpts.appendChild(el);
1011
+ });
1012
+
1013
+ // Palette cards with ramp
1014
+ var palOpts = document.getElementById("pal-options");
1015
+ PALETTES.forEach(function (p, i) {
1016
+ var el = document.createElement("div");
1017
+ el.className = "opt";
1018
+ el.innerHTML =
1019
+ '<div class="opt-inner"><div class="pal-strip"><div style="background:' +
1020
+ p.background +
1021
+ ';"></div><div style="background:' +
1022
+ (p.muted || p.mid || "#888") +
1023
+ ';"></div><div style="background:' +
1024
+ p.accent +
1025
+ ';"></div><div style="background:' +
1026
+ p.foreground +
1027
+ ';"></div></div><div class="opt-name">' +
1028
+ p.name +
1029
+ '</div><div class="opt-desc">' +
1030
+ p.description +
1031
+ "</div></div>";
1032
+ el.onclick = function () {
1033
+ sel("palette", i, palOpts);
1034
+ };
1035
+ palOpts.appendChild(el);
1036
+ });
1037
+
1038
+ // Typography cards with specimen
1039
+ var typeOpts = document.getElementById("type-options");
1040
+ TYPEPAIRS.forEach(function (tp, i) {
1041
+ var letters = "AaBbCcDdEeFfGgHh";
1042
+ var el = document.createElement("div");
1043
+ el.className = "opt";
1044
+ el.innerHTML =
1045
+ '<div class="type-specimen"><div class="type-headline" style="font-family:\'' +
1046
+ tp.headline.family +
1047
+ "',sans-serif;font-weight:" +
1048
+ tp.headline.weight +
1049
+ ';font-size:24px;">' +
1050
+ tp.preview +
1051
+ '</div><div class="type-body" style="font-family:\'' +
1052
+ tp.body.family +
1053
+ "',monospace;font-weight:" +
1054
+ tp.body.weight +
1055
+ ';">' +
1056
+ tp.body_preview +
1057
+ '</div></div><div class="type-meta"><div class="type-families">' +
1058
+ tp.headline.family +
1059
+ " " +
1060
+ tp.headline.weight +
1061
+ " · " +
1062
+ tp.body.family +
1063
+ " " +
1064
+ tp.body.weight +
1065
+ '</div><div class="type-letters" style="font-family:\'' +
1066
+ tp.headline.family +
1067
+ "',sans-serif;font-weight:" +
1068
+ tp.headline.weight +
1069
+ ';">' +
1070
+ letters +
1071
+ "</div></div>";
1072
+ el.onclick = function () {
1073
+ sel("type", i, typeOpts);
1074
+ };
1075
+ typeOpts.appendChild(el);
1076
+ });
1077
+
1078
+ // Theme chips
1079
+ var themeOpts = document.getElementById("theme-options");
1080
+ THEMES.forEach(function (th, i) {
1081
+ var el = document.createElement("div");
1082
+ el.className = "chip theme-chip";
1083
+ el.innerHTML =
1084
+ '<div class="theme-swatch" style="background:' +
1085
+ th.bg +
1086
+ ';"></div><div class="chip-label">' +
1087
+ th.name +
1088
+ '</div><div class="chip-sub">' +
1089
+ th.desc +
1090
+ "</div>";
1091
+ el.onclick = function () {
1092
+ chipSel("theme", i, themeOpts);
1093
+ };
1094
+ themeOpts.appendChild(el);
1095
+ });
1096
+
1097
+ // Corner chips
1098
+ var cornerOpts = document.getElementById("corner-options");
1099
+ CORNERS.forEach(function (c, i) {
1100
+ var el = document.createElement("div");
1101
+ el.className = "chip";
1102
+ el.innerHTML =
1103
+ '<div class="chip-preview"><div class="corner-box" style="border-radius:' +
1104
+ c.value +
1105
+ ';"></div></div><div><div class="chip-label">' +
1106
+ c.name +
1107
+ '</div><div class="chip-sub">' +
1108
+ c.value +
1109
+ "</div></div>";
1110
+ el.onclick = function () {
1111
+ chipSel("corners", i, cornerOpts);
1112
+ };
1113
+ cornerOpts.appendChild(el);
1114
+ });
1115
+
1116
+ // Density chips
1117
+ var densityOpts = document.getElementById("density-options");
1118
+ DENSITIES.forEach(function (d, i) {
1119
+ var gaps = [2, 4, 7][i];
1120
+ var el = document.createElement("div");
1121
+ el.className = "chip";
1122
+ el.innerHTML =
1123
+ '<div class="chip-preview"><div class="density-bars" style="gap:' +
1124
+ gaps +
1125
+ 'px;"><div class="density-bar"></div><div class="density-bar"></div><div class="density-bar"></div></div></div><div><div class="chip-label">' +
1126
+ d.name +
1127
+ '</div><div class="chip-sub">' +
1128
+ d.desc +
1129
+ "</div></div>";
1130
+ el.onclick = function () {
1131
+ chipSel("density", i, densityOpts);
1132
+ };
1133
+ densityOpts.appendChild(el);
1134
+ });
1135
+
1136
+ // Depth chips
1137
+ var depthOpts = document.getElementById("depth-options");
1138
+ DEPTHS.forEach(function (d, i) {
1139
+ var shadow = [
1140
+ "none",
1141
+ "0 2px 8px rgba(255,255,255,0.04)",
1142
+ "0 0 16px rgba(255,255,255,0.06)",
1143
+ ][i];
1144
+ var el = document.createElement("div");
1145
+ el.className = "chip";
1146
+ el.innerHTML =
1147
+ '<div class="chip-preview"><div class="depth-square" style="box-shadow:' +
1148
+ shadow +
1149
+ ';"></div></div><div><div class="chip-label">' +
1150
+ d.name +
1151
+ '</div><div class="chip-sub">' +
1152
+ d.desc +
1153
+ "</div></div>";
1154
+ el.onclick = function () {
1155
+ chipSel("depth", i, depthOpts);
1156
+ };
1157
+ depthOpts.appendChild(el);
1158
+ });
1159
+
1160
+ // Easing options with GSAP animation
1161
+ var easeOpts = document.getElementById("ease-options");
1162
+ EASINGS.forEach(function (e, i) {
1163
+ var el = document.createElement("div");
1164
+ el.className = "ease-opt";
1165
+ var dotId = "ease-dot-" + i;
1166
+ el.innerHTML =
1167
+ '<div class="ease-track"><div class="ease-dot" id="' +
1168
+ dotId +
1169
+ '"></div></div>' +
1170
+ '<div class="ease-label"><div class="ease-name">' +
1171
+ e.name +
1172
+ '</div><div class="ease-value">' +
1173
+ e.value +
1174
+ "</div></div>";
1175
+ el.onclick = function () {
1176
+ easeOpts.querySelectorAll(".ease-opt").forEach(function (c) {
1177
+ c.classList.remove("selected");
1178
+ });
1179
+ el.classList.add("selected");
1180
+ picks.easing = i;
1181
+ checkReady();
1182
+ };
1183
+ easeOpts.appendChild(el);
1184
+ // Animate the dot with GSAP
1185
+ gsap.to("#" + dotId, {
1186
+ left: "calc(100% - 12px)",
1187
+ duration: 1.2,
1188
+ ease: e.value,
1189
+ repeat: -1,
1190
+ repeatDelay: 0.8,
1191
+ yoyo: true,
1192
+ });
1193
+ });
1194
+
1195
+ function chipSel(key, idx, container) {
1196
+ container.querySelectorAll(".chip").forEach(function (c) {
1197
+ c.classList.remove("selected");
1198
+ });
1199
+ container.children[idx].classList.add("selected");
1200
+ picks[key] = idx;
1201
+ checkReady();
1202
+ renderPreview();
1203
+ }
1204
+ function sel(key, idx, container) {
1205
+ container.querySelectorAll(".opt").forEach(function (c) {
1206
+ c.classList.remove("selected");
1207
+ });
1208
+ container.children[idx].classList.add("selected");
1209
+ picks[key] = idx;
1210
+ checkReady();
1211
+ renderPreview();
1212
+ }
1213
+
1214
+ function checkReady() {
1215
+ var ready =
1216
+ picks.theme !== null &&
1217
+ picks.arch !== null &&
1218
+ picks.palette !== null &&
1219
+ picks.type !== null &&
1220
+ picks.corners !== null &&
1221
+ picks.density !== null &&
1222
+ picks.depth !== null &&
1223
+ picks.easing !== null;
1224
+ document
1225
+ .getElementById("fab")
1226
+ .classList.toggle("visible", ready && currentPhase === "tune");
1227
+ document.getElementById("md-overlay").classList.remove("visible");
1228
+ }
1229
+
1230
+ function renderPreview() {
1231
+ var pv = document.getElementById("preview");
1232
+ if (picks.arch === null) {
1233
+ pv.innerHTML = '<div class="preview-empty">Pick a structure to preview</div>';
1234
+ return;
1235
+ }
1236
+ var a = ARCHITECTURES[picks.arch];
1237
+ var th = picks.theme !== null ? THEMES[picks.theme] : THEMES[0];
1238
+ var p =
1239
+ picks.palette !== null ? PALETTES[picks.palette] : { accent: "#888", muted: "#555" };
1240
+ var t =
1241
+ picks.type !== null
1242
+ ? TYPEPAIRS[picks.type]
1243
+ : {
1244
+ headline: { family: "system-ui", weight: 600 },
1245
+ body: { family: "system-ui", weight: 400 },
1246
+ };
1247
+ var cr = picks.corners !== null ? CORNERS[picks.corners].value : "0px";
1248
+ var dn = picks.density !== null ? picks.density : 1;
1249
+ var dp = picks.depth !== null ? picks.depth : 0;
1250
+ var bg, fg;
1251
+ if (th.id === "palette" && p.background) {
1252
+ bg = p.background;
1253
+ fg = p.foreground;
1254
+ } else {
1255
+ bg = th.bg;
1256
+ fg = th.fg;
1257
+ }
1258
+ var ac = p.accent,
1259
+ mt = p.muted || al(fg, 0.4);
1260
+ var pad = [12, 20, 36][dn] + "px",
1261
+ gap = [8, 16, 28][dn] + "px";
1262
+ var isDark = bg && bg[0] === "#" ? parseInt(bg.slice(1, 3), 16) < 80 : true;
1263
+ var shCol = isDark ? ac : fg;
1264
+ var shadow = [
1265
+ "none",
1266
+ "0 2px 16px " + al(shCol, isDark ? 0.15 : 0.1),
1267
+ "0 4px 32px " + al(shCol, isDark ? 0.3 : 0.18),
1268
+ ][dp];
1269
+ var tokens = {
1270
+ "{{bg}}": bg,
1271
+ "{{fg}}": fg,
1272
+ "{{ac}}": ac,
1273
+ "{{mt}}": mt,
1274
+ "{{sf}}": al(fg, 0.06),
1275
+ "{{hf}}": t.headline.family,
1276
+ "{{hw}}": t.headline.weight,
1277
+ "{{bf}}": t.body.family,
1278
+ "{{bw}}": t.body.weight,
1279
+ "{{cr}}": cr,
1280
+ "{{pad}}": pad,
1281
+ "{{gap}}": gap,
1282
+ "{{shadow}}": shadow,
1283
+ "{{g}}": al(fg, 0.06),
1284
+ "{{fg3}}": al(fg, 0.03),
1285
+ "{{fg6}}": al(fg, 0.06),
1286
+ "{{fg8}}": al(fg, 0.08),
1287
+ "{{fg15}}": al(fg, 0.15),
1288
+ "{{ac3}}": al(ac, 0.03),
1289
+ "{{ac5}}": al(ac, 0.05),
1290
+ "{{ac25}}": al(ac, 0.25),
1291
+ "{{prompt_headline}}": (PROMPT && PROMPT.headline) || "Your Headline",
1292
+ "{{prompt_sub}}": (PROMPT && PROMPT.subline) || "Subline.",
1293
+ };
1294
+ var h =
1295
+ a.preview_html ||
1296
+ '<div style="background:' +
1297
+ bg +
1298
+ ";padding:40px;min-height:100%;display:flex;align-items:center;justify-content:center;color:" +
1299
+ mt +
1300
+ ';font-size:14px;">No preview</div>';
1301
+ Object.keys(tokens).forEach(function (k) {
1302
+ h = h.split(k).join(tokens[k]);
1303
+ });
1304
+ pv.innerHTML = h;
1305
+ }
1306
+
1307
+ // ── Output ──
1308
+ function showOutput() {
1309
+ if (
1310
+ picks.theme === null ||
1311
+ picks.arch === null ||
1312
+ picks.palette === null ||
1313
+ picks.type === null ||
1314
+ picks.corners === null ||
1315
+ picks.density === null ||
1316
+ picks.depth === null
1317
+ )
1318
+ return;
1319
+ var a = ARCHITECTURES[picks.arch],
1320
+ p = PALETTES[picks.palette],
1321
+ t = TYPEPAIRS[picks.type];
1322
+ var th = THEMES[picks.theme],
1323
+ cr = CORNERS[picks.corners],
1324
+ dn = DENSITIES[picks.density],
1325
+ dp = DEPTHS[picks.depth];
1326
+ var bg = th.id === "palette" && p.background ? p.background : th.bg;
1327
+ var fg = th.id === "palette" && p.foreground ? p.foreground : th.fg;
1328
+ var ac = p.accent,
1329
+ mt = p.muted || p.mid || "#888";
1330
+ var padVal = { Tight: "8px", Normal: "16px", Generous: "32px" }[dn.name] || "16px";
1331
+ var gapVal = { Tight: "8px", Normal: "16px", Generous: "28px" }[dn.name] || "16px";
1332
+
1333
+ var md = "---\n";
1334
+ md += "name: " + ((PROMPT && PROMPT.title) || "Untitled") + "\n";
1335
+ md +=
1336
+ 'colors:\n primary: "' +
1337
+ bg +
1338
+ '"\n on-primary: "' +
1339
+ fg +
1340
+ '"\n accent: "' +
1341
+ ac +
1342
+ '"\n muted: "' +
1343
+ mt +
1344
+ '"\n';
1345
+ md +=
1346
+ "typography:\n headline:\n fontFamily: " +
1347
+ t.headline.family +
1348
+ "\n fontSize: 3.5rem\n fontWeight: " +
1349
+ t.headline.weight +
1350
+ "\n letterSpacing: -0.03em\n";
1351
+ md +=
1352
+ " body:\n fontFamily: " +
1353
+ t.body.family +
1354
+ "\n fontSize: 1rem\n fontWeight: " +
1355
+ t.body.weight +
1356
+ "\n lineHeight: 1.5\n";
1357
+ md += "rounded:\n md: " + cr.value + "\n";
1358
+ md += "spacing:\n md: " + padVal + "\n lg: " + gapVal + "\n";
1359
+ md += "---\n\n";
1360
+ md += "## Overview\n\n" + a.mood + ". " + a.description + ". " + p.description + ".\n\n";
1361
+ md +=
1362
+ "## Colors\n\n- **Primary** (`" +
1363
+ bg +
1364
+ "`) — Canvas background\n- **On-Primary** (`" +
1365
+ fg +
1366
+ "`) — Text and content\n- **Accent** (`" +
1367
+ ac +
1368
+ "`) — CTAs, highlights\n- **Muted** (`" +
1369
+ mt +
1370
+ "`) — Secondary text\n\n";
1371
+ md +=
1372
+ "## Typography\n\n- **Headline** — " +
1373
+ t.headline.family +
1374
+ " at weight " +
1375
+ t.headline.weight +
1376
+ "\n- **Body** — " +
1377
+ t.body.family +
1378
+ " at weight " +
1379
+ t.body.weight +
1380
+ "\n\n";
1381
+ md +=
1382
+ "## Layout\n\n- Structure: " +
1383
+ a.name +
1384
+ " — " +
1385
+ a.tag +
1386
+ "\n- Density: " +
1387
+ dn.name +
1388
+ " (" +
1389
+ dn.desc +
1390
+ ")\n- Corners: " +
1391
+ cr.name +
1392
+ " (" +
1393
+ cr.value +
1394
+ ")\n\n";
1395
+ md += "## Elevation\n\n" + dp.name + " — " + dp.desc + ".\n\n";
1396
+ var easeObj = picks.easing !== null ? EASINGS[picks.easing] : null;
1397
+ if (easeObj) {
1398
+ md +=
1399
+ "## Motion\n\n- **Entry easing:** `" +
1400
+ easeObj.value +
1401
+ "` — " +
1402
+ easeObj.desc +
1403
+ "\n- **Energy:** " +
1404
+ easeObj.name +
1405
+ "\n\n";
1406
+ }
1407
+ if (a.components) md += "## Components\n\n" + a.components + "\n\n";
1408
+ md += "## Do's and Don'ts\n\n";
1409
+ if (a.dos) {
1410
+ md += a.dos + "\n";
1411
+ } else {
1412
+ md +=
1413
+ "### Do's\n- Use accent color sparingly for maximum impact\n- Maintain consistent " +
1414
+ cr.name.toLowerCase() +
1415
+ " corners\n\n### Don'ts\n- Do not mix multiple accent colors\n- Do not use weights outside the headline/body pair\n";
1416
+ }
1417
+
1418
+ document.getElementById("md-output").value = md;
1419
+ document.getElementById("md-overlay").classList.add("visible");
1420
+ }
1421
+
1422
+ document.getElementById("copy-btn").addEventListener("click", function () {
1423
+ navigator.clipboard.writeText(document.getElementById("md-output").value).then(function () {
1424
+ document.getElementById("copy-btn").textContent = "Copied!";
1425
+ setTimeout(function () {
1426
+ document.getElementById("copy-btn").textContent = "Copy";
1427
+ }, 2000);
1428
+ });
1429
+ });
1430
+ </script>
1431
+ </body>
1432
+ </html>