hyperframes 0.6.97 → 0.6.98

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 (77) hide show
  1. package/dist/beat-analyzer.global.js +326 -0
  2. package/dist/cli.js +2479 -1961
  3. package/dist/commands/layout-audit.browser.js +86 -0
  4. package/dist/hyperframe-runtime.js +22 -22
  5. package/dist/hyperframe.manifest.json +1 -1
  6. package/dist/hyperframe.runtime.iife.js +22 -22
  7. package/dist/skills/hyperframes-cli/SKILL.md +67 -103
  8. package/dist/skills/hyperframes-cli/references/doctor-browser.md +45 -0
  9. package/dist/skills/hyperframes-cli/references/init-and-scaffold.md +51 -0
  10. package/dist/skills/hyperframes-cli/references/lambda.md +132 -0
  11. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +93 -0
  12. package/dist/skills/hyperframes-cli/references/preview-render.md +107 -0
  13. package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
  14. package/dist/studio/assets/hyperframes-player-DgsMQSvV.js +418 -0
  15. package/dist/studio/assets/index-B62bDCQv.css +1 -0
  16. package/dist/studio/assets/index-Ce3pBm_I.js +252 -0
  17. package/dist/studio/assets/{index-HveJ0MuV.js → index-D-ET9M0b.js} +1 -1
  18. package/dist/studio/assets/index-D-bS9Dxx.js +1 -0
  19. package/dist/studio/index.html +2 -2
  20. package/dist/templates/_shared/AGENTS.md +46 -21
  21. package/dist/templates/_shared/CLAUDE.md +16 -14
  22. package/package.json +3 -2
  23. package/dist/pngDecodeBlitWorker.js +0 -239
  24. package/dist/skills/gsap/SKILL.md +0 -240
  25. package/dist/skills/gsap/references/effects.md +0 -297
  26. package/dist/skills/gsap/scripts/extract-audio-data.py +0 -188
  27. package/dist/skills/hyperframes/SKILL.md +0 -491
  28. package/dist/skills/hyperframes/data-in-motion.md +0 -19
  29. package/dist/skills/hyperframes/house-style.md +0 -73
  30. package/dist/skills/hyperframes/palettes/bold-energetic.md +0 -14
  31. package/dist/skills/hyperframes/palettes/clean-corporate.md +0 -14
  32. package/dist/skills/hyperframes/palettes/dark-premium.md +0 -14
  33. package/dist/skills/hyperframes/palettes/jewel-rich.md +0 -14
  34. package/dist/skills/hyperframes/palettes/monochrome.md +0 -14
  35. package/dist/skills/hyperframes/palettes/nature-earth.md +0 -14
  36. package/dist/skills/hyperframes/palettes/neon-electric.md +0 -14
  37. package/dist/skills/hyperframes/palettes/pastel-soft.md +0 -14
  38. package/dist/skills/hyperframes/palettes/warm-editorial.md +0 -14
  39. package/dist/skills/hyperframes/patterns.md +0 -191
  40. package/dist/skills/hyperframes/references/audio-reactive.md +0 -76
  41. package/dist/skills/hyperframes/references/beat-direction.md +0 -171
  42. package/dist/skills/hyperframes/references/captions.md +0 -163
  43. package/dist/skills/hyperframes/references/css-patterns.md +0 -373
  44. package/dist/skills/hyperframes/references/design-picker.md +0 -117
  45. package/dist/skills/hyperframes/references/dynamic-techniques.md +0 -102
  46. package/dist/skills/hyperframes/references/html-in-canvas-patterns.md +0 -507
  47. package/dist/skills/hyperframes/references/motion-principles.md +0 -150
  48. package/dist/skills/hyperframes/references/narration.md +0 -92
  49. package/dist/skills/hyperframes/references/prompt-expansion.md +0 -68
  50. package/dist/skills/hyperframes/references/techniques.md +0 -525
  51. package/dist/skills/hyperframes/references/text-effects.md +0 -64
  52. package/dist/skills/hyperframes/references/transcript-guide.md +0 -107
  53. package/dist/skills/hyperframes/references/transitions/catalog.md +0 -117
  54. package/dist/skills/hyperframes/references/transitions/css-3d.md +0 -12
  55. package/dist/skills/hyperframes/references/transitions/css-blur.md +0 -51
  56. package/dist/skills/hyperframes/references/transitions/css-cover.md +0 -43
  57. package/dist/skills/hyperframes/references/transitions/css-destruction.md +0 -95
  58. package/dist/skills/hyperframes/references/transitions/css-dissolve.md +0 -66
  59. package/dist/skills/hyperframes/references/transitions/css-distortion.md +0 -45
  60. package/dist/skills/hyperframes/references/transitions/css-grid.md +0 -10
  61. package/dist/skills/hyperframes/references/transitions/css-light.md +0 -49
  62. package/dist/skills/hyperframes/references/transitions/css-mechanical.md +0 -30
  63. package/dist/skills/hyperframes/references/transitions/css-other.md +0 -25
  64. package/dist/skills/hyperframes/references/transitions/css-push.md +0 -41
  65. package/dist/skills/hyperframes/references/transitions/css-radial.md +0 -37
  66. package/dist/skills/hyperframes/references/transitions/css-scale.md +0 -24
  67. package/dist/skills/hyperframes/references/transitions.md +0 -138
  68. package/dist/skills/hyperframes/references/typography.md +0 -175
  69. package/dist/skills/hyperframes/references/video-composition.md +0 -62
  70. package/dist/skills/hyperframes/scripts/animation-map.mjs +0 -601
  71. package/dist/skills/hyperframes/scripts/contrast-report.mjs +0 -348
  72. package/dist/skills/hyperframes/scripts/package-loader.mjs +0 -269
  73. package/dist/skills/hyperframes/templates/design-picker.html +0 -1432
  74. package/dist/skills/hyperframes/visual-styles.md +0 -443
  75. package/dist/studio/assets/hyperframes-player-Daj5djxa.js +0 -418
  76. package/dist/studio/assets/index-B0twsRu0.css +0 -1
  77. package/dist/studio/assets/index-Cfye9xzo.js +0 -251
@@ -1,1432 +0,0 @@
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>