@dopaminefx/effect-heartburst 0.1.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,1827 @@
1
+ {
2
+ "fmt": "dopamine-effect",
3
+ "v": "1.0.0",
4
+ "id": "dopamine.love.heartburst",
5
+ "meta": {
6
+ "name": "Heartburst",
7
+ "description": "A love / like / favorite moment: a heart swells with a double-beat (lub-dub) then bursts into a flurry of small hearts that fly outward, arc, and fade — warm OKLCH reds/pinks/corals.",
8
+ "tags": [
9
+ "love",
10
+ "like",
11
+ "favorite",
12
+ "heart",
13
+ "burst"
14
+ ]
15
+ },
16
+ "controls": {
17
+ "mood": {
18
+ "type": "enum",
19
+ "label": "Mood",
20
+ "default": "celebratory",
21
+ "options": [
22
+ "serene",
23
+ "celebratory",
24
+ "electric"
25
+ ],
26
+ "ui": "segmented"
27
+ },
28
+ "intensity": {
29
+ "type": "scalar",
30
+ "label": "Intensity",
31
+ "default": 0.7,
32
+ "min": 0,
33
+ "max": 1,
34
+ "step": 0.01,
35
+ "ui": "slider",
36
+ "help": "Beat strength + number of burst hearts + glow."
37
+ },
38
+ "whimsy": {
39
+ "type": "scalar",
40
+ "label": "Whimsy",
41
+ "default": 0.5,
42
+ "min": 0,
43
+ "max": 1,
44
+ "step": 0.01,
45
+ "ui": "slider",
46
+ "help": "Soft photoreal gloss heart (0) to flat cel sticker heart (1)."
47
+ },
48
+ "seed": {
49
+ "type": "int",
50
+ "label": "Seed",
51
+ "default": null,
52
+ "nullable": true,
53
+ "help": "Null = unique warm palette + burst per fire; pin to reproduce."
54
+ },
55
+ "target": {
56
+ "type": "selector",
57
+ "label": "Target",
58
+ "default": "document.body"
59
+ }
60
+ },
61
+ "baselines": {
62
+ "serene": {
63
+ "durationMs": 2400,
64
+ "lightness": 0.82,
65
+ "chroma": 0.11,
66
+ "hueCenter": 5,
67
+ "hueRange": 40,
68
+ "heartScale": 0.26,
69
+ "burstCount": 10,
70
+ "burstSpread": 0.32,
71
+ "beatStrength": 0.6,
72
+ "doubleBeat": 0
73
+ },
74
+ "celebratory": {
75
+ "durationMs": 2000,
76
+ "lightness": 0.78,
77
+ "chroma": 0.17,
78
+ "hueCenter": 12,
79
+ "hueRange": 60,
80
+ "heartScale": 0.3,
81
+ "burstCount": 18,
82
+ "burstSpread": 0.46,
83
+ "beatStrength": 1,
84
+ "doubleBeat": 1
85
+ },
86
+ "electric": {
87
+ "durationMs": 1600,
88
+ "lightness": 0.74,
89
+ "chroma": 0.24,
90
+ "hueCenter": 350,
91
+ "hueRange": 50,
92
+ "heartScale": 0.32,
93
+ "burstCount": 26,
94
+ "burstSpread": 0.58,
95
+ "beatStrength": 1.35,
96
+ "doubleBeat": 1
97
+ }
98
+ },
99
+ "palette": {
100
+ "model": "oklch",
101
+ "space": "linear-srgb",
102
+ "generator": "golden-angle",
103
+ "goldenAngleDeg": 137.50776405003785,
104
+ "stops": 3,
105
+ "hueSpread": 0.18,
106
+ "lightness": {
107
+ "baseline": "lightness",
108
+ "perStop": [
109
+ 0,
110
+ 0.07,
111
+ -0.06
112
+ ]
113
+ },
114
+ "chroma": {
115
+ "from": {
116
+ "mul": [
117
+ {
118
+ "baseline": "chroma"
119
+ },
120
+ {
121
+ "lerp": [
122
+ "intensity",
123
+ 0.75,
124
+ 1.4
125
+ ]
126
+ }
127
+ ]
128
+ },
129
+ "perStop": [
130
+ 0,
131
+ 0.02,
132
+ -0.01
133
+ ]
134
+ },
135
+ "seed": {
136
+ "deterministic": true,
137
+ "source": "controls.seed",
138
+ "prng": "mulberry32"
139
+ },
140
+ "perMood": {
141
+ "serene": {
142
+ "hueCenter": 5,
143
+ "hueRange": 40,
144
+ "lightness": 0.82,
145
+ "chroma": 0.11
146
+ },
147
+ "celebratory": {
148
+ "hueCenter": 12,
149
+ "hueRange": 60,
150
+ "lightness": 0.78,
151
+ "chroma": 0.17
152
+ },
153
+ "electric": {
154
+ "hueCenter": 350,
155
+ "hueRange": 50,
156
+ "lightness": 0.74,
157
+ "chroma": 0.24
158
+ }
159
+ }
160
+ },
161
+ "tempo": {
162
+ "durationMs": {
163
+ "from": {
164
+ "round": {
165
+ "mul": [
166
+ {
167
+ "baseline": "durationMs"
168
+ },
169
+ {
170
+ "lerp": [
171
+ "intensity",
172
+ 1.1,
173
+ 0.9
174
+ ]
175
+ }
176
+ ]
177
+ }
178
+ }
179
+ },
180
+ "frame": {
181
+ "amp": {
182
+ "lt": [
183
+ 0,
184
+ {
185
+ "clamp01": {
186
+ "input": "life"
187
+ }
188
+ },
189
+ {
190
+ "lt": [
191
+ {
192
+ "clamp01": {
193
+ "input": "life"
194
+ }
195
+ },
196
+ 1,
197
+ {
198
+ "clamp01": {
199
+ "max": [
200
+ {
201
+ "mul": [
202
+ {
203
+ "max": [
204
+ {
205
+ "lt": [
206
+ -1,
207
+ {
208
+ "div": [
209
+ {
210
+ "sub": [
211
+ {
212
+ "clamp01": {
213
+ "input": "life"
214
+ }
215
+ },
216
+ 0.1
217
+ ]
218
+ },
219
+ 0.1
220
+ ]
221
+ },
222
+ {
223
+ "lt": [
224
+ {
225
+ "div": [
226
+ {
227
+ "sub": [
228
+ {
229
+ "clamp01": {
230
+ "input": "life"
231
+ }
232
+ },
233
+ 0.1
234
+ ]
235
+ },
236
+ 0.1
237
+ ]
238
+ },
239
+ 1,
240
+ {
241
+ "lt": [
242
+ {
243
+ "div": [
244
+ {
245
+ "sub": [
246
+ {
247
+ "clamp01": {
248
+ "input": "life"
249
+ }
250
+ },
251
+ 0.1
252
+ ]
253
+ },
254
+ 0.1
255
+ ]
256
+ },
257
+ 0,
258
+ {
259
+ "pow": [
260
+ {
261
+ "add": [
262
+ 0.5,
263
+ {
264
+ "mul": [
265
+ 0.5,
266
+ {
267
+ "cos": {
268
+ "mul": [
269
+ {
270
+ "div": [
271
+ {
272
+ "sub": [
273
+ {
274
+ "clamp01": {
275
+ "input": "life"
276
+ }
277
+ },
278
+ 0.1
279
+ ]
280
+ },
281
+ 0.1
282
+ ]
283
+ },
284
+ 3.141592653589793
285
+ ]
286
+ }
287
+ }
288
+ ]
289
+ }
290
+ ]
291
+ },
292
+ 0.7
293
+ ]
294
+ },
295
+ {
296
+ "pow": [
297
+ {
298
+ "add": [
299
+ 0.5,
300
+ {
301
+ "mul": [
302
+ 0.5,
303
+ {
304
+ "cos": {
305
+ "mul": [
306
+ {
307
+ "div": [
308
+ {
309
+ "sub": [
310
+ {
311
+ "clamp01": {
312
+ "input": "life"
313
+ }
314
+ },
315
+ 0.1
316
+ ]
317
+ },
318
+ 0.1
319
+ ]
320
+ },
321
+ 3.141592653589793
322
+ ]
323
+ }
324
+ }
325
+ ]
326
+ }
327
+ ]
328
+ },
329
+ 1.4
330
+ ]
331
+ }
332
+ ]
333
+ },
334
+ 0
335
+ ]
336
+ },
337
+ 0
338
+ ]
339
+ },
340
+ {
341
+ "mul": [
342
+ {
343
+ "lt": [
344
+ -1,
345
+ {
346
+ "div": [
347
+ {
348
+ "sub": [
349
+ {
350
+ "clamp01": {
351
+ "input": "life"
352
+ }
353
+ },
354
+ 0.21
355
+ ]
356
+ },
357
+ 0.075
358
+ ]
359
+ },
360
+ {
361
+ "lt": [
362
+ {
363
+ "div": [
364
+ {
365
+ "sub": [
366
+ {
367
+ "clamp01": {
368
+ "input": "life"
369
+ }
370
+ },
371
+ 0.21
372
+ ]
373
+ },
374
+ 0.075
375
+ ]
376
+ },
377
+ 1,
378
+ {
379
+ "lt": [
380
+ {
381
+ "div": [
382
+ {
383
+ "sub": [
384
+ {
385
+ "clamp01": {
386
+ "input": "life"
387
+ }
388
+ },
389
+ 0.21
390
+ ]
391
+ },
392
+ 0.075
393
+ ]
394
+ },
395
+ 0,
396
+ {
397
+ "pow": [
398
+ {
399
+ "add": [
400
+ 0.5,
401
+ {
402
+ "mul": [
403
+ 0.5,
404
+ {
405
+ "cos": {
406
+ "mul": [
407
+ {
408
+ "div": [
409
+ {
410
+ "sub": [
411
+ {
412
+ "clamp01": {
413
+ "input": "life"
414
+ }
415
+ },
416
+ 0.21
417
+ ]
418
+ },
419
+ 0.075
420
+ ]
421
+ },
422
+ 3.141592653589793
423
+ ]
424
+ }
425
+ }
426
+ ]
427
+ }
428
+ ]
429
+ },
430
+ 0.7
431
+ ]
432
+ },
433
+ {
434
+ "pow": [
435
+ {
436
+ "add": [
437
+ 0.5,
438
+ {
439
+ "mul": [
440
+ 0.5,
441
+ {
442
+ "cos": {
443
+ "mul": [
444
+ {
445
+ "div": [
446
+ {
447
+ "sub": [
448
+ {
449
+ "clamp01": {
450
+ "input": "life"
451
+ }
452
+ },
453
+ 0.21
454
+ ]
455
+ },
456
+ 0.075
457
+ ]
458
+ },
459
+ 3.141592653589793
460
+ ]
461
+ }
462
+ }
463
+ ]
464
+ }
465
+ ]
466
+ },
467
+ 1.4
468
+ ]
469
+ }
470
+ ]
471
+ },
472
+ 0
473
+ ]
474
+ },
475
+ 0
476
+ ]
477
+ },
478
+ 0.62,
479
+ {
480
+ "clamp01": {
481
+ "param": "doubleBeat"
482
+ }
483
+ }
484
+ ]
485
+ }
486
+ ]
487
+ },
488
+ 0.9,
489
+ {
490
+ "param": "beatStrength"
491
+ }
492
+ ]
493
+ },
494
+ {
495
+ "mul": [
496
+ {
497
+ "mul": [
498
+ {
499
+ "lt": [
500
+ 0.3,
501
+ {
502
+ "clamp01": {
503
+ "input": "life"
504
+ }
505
+ },
506
+ {
507
+ "easeOutCubic": {
508
+ "div": [
509
+ {
510
+ "sub": [
511
+ {
512
+ "clamp01": {
513
+ "input": "life"
514
+ }
515
+ },
516
+ 0.3
517
+ ]
518
+ },
519
+ {
520
+ "sub": [
521
+ 1,
522
+ 0.3
523
+ ]
524
+ }
525
+ ]
526
+ }
527
+ },
528
+ 0
529
+ ]
530
+ },
531
+ {
532
+ "pow": [
533
+ {
534
+ "sub": [
535
+ 1,
536
+ {
537
+ "lt": [
538
+ 0.3,
539
+ {
540
+ "clamp01": {
541
+ "input": "life"
542
+ }
543
+ },
544
+ {
545
+ "easeOutCubic": {
546
+ "div": [
547
+ {
548
+ "sub": [
549
+ {
550
+ "clamp01": {
551
+ "input": "life"
552
+ }
553
+ },
554
+ 0.3
555
+ ]
556
+ },
557
+ {
558
+ "sub": [
559
+ 1,
560
+ 0.3
561
+ ]
562
+ }
563
+ ]
564
+ }
565
+ },
566
+ 0
567
+ ]
568
+ }
569
+ ]
570
+ },
571
+ 1.1
572
+ ]
573
+ },
574
+ 2.4
575
+ ]
576
+ },
577
+ {
578
+ "add": [
579
+ 0.7,
580
+ {
581
+ "mul": [
582
+ 0.3,
583
+ {
584
+ "param": "beatStrength"
585
+ }
586
+ ]
587
+ }
588
+ ]
589
+ }
590
+ ]
591
+ }
592
+ ]
593
+ }
594
+ },
595
+ 0
596
+ ]
597
+ },
598
+ 0
599
+ ]
600
+ },
601
+ "extras": {
602
+ "presence": {
603
+ "lt": [
604
+ {
605
+ "clamp01": {
606
+ "input": "life"
607
+ }
608
+ },
609
+ 0.04,
610
+ {
611
+ "div": [
612
+ {
613
+ "clamp01": {
614
+ "input": "life"
615
+ }
616
+ },
617
+ 0.04
618
+ ]
619
+ },
620
+ {
621
+ "lt": [
622
+ {
623
+ "clamp01": {
624
+ "input": "life"
625
+ }
626
+ },
627
+ 0.8,
628
+ 1,
629
+ {
630
+ "pow": [
631
+ {
632
+ "max": [
633
+ 0,
634
+ {
635
+ "sub": [
636
+ 1,
637
+ {
638
+ "div": [
639
+ {
640
+ "sub": [
641
+ {
642
+ "clamp01": {
643
+ "input": "life"
644
+ }
645
+ },
646
+ 0.8
647
+ ]
648
+ },
649
+ 0.2
650
+ ]
651
+ }
652
+ ]
653
+ }
654
+ ]
655
+ },
656
+ 1.4
657
+ ]
658
+ }
659
+ ]
660
+ }
661
+ ]
662
+ },
663
+ "beat": {
664
+ "min": [
665
+ 1,
666
+ {
667
+ "mul": [
668
+ {
669
+ "max": [
670
+ 0,
671
+ {
672
+ "sub": [
673
+ {
674
+ "sub": [
675
+ {
676
+ "add": [
677
+ 1,
678
+ {
679
+ "mul": [
680
+ {
681
+ "max": [
682
+ {
683
+ "lt": [
684
+ -1,
685
+ {
686
+ "div": [
687
+ {
688
+ "sub": [
689
+ {
690
+ "clamp01": {
691
+ "input": "life"
692
+ }
693
+ },
694
+ 0.1
695
+ ]
696
+ },
697
+ 0.1
698
+ ]
699
+ },
700
+ {
701
+ "lt": [
702
+ {
703
+ "div": [
704
+ {
705
+ "sub": [
706
+ {
707
+ "clamp01": {
708
+ "input": "life"
709
+ }
710
+ },
711
+ 0.1
712
+ ]
713
+ },
714
+ 0.1
715
+ ]
716
+ },
717
+ 1,
718
+ {
719
+ "lt": [
720
+ {
721
+ "div": [
722
+ {
723
+ "sub": [
724
+ {
725
+ "clamp01": {
726
+ "input": "life"
727
+ }
728
+ },
729
+ 0.1
730
+ ]
731
+ },
732
+ 0.1
733
+ ]
734
+ },
735
+ 0,
736
+ {
737
+ "pow": [
738
+ {
739
+ "add": [
740
+ 0.5,
741
+ {
742
+ "mul": [
743
+ 0.5,
744
+ {
745
+ "cos": {
746
+ "mul": [
747
+ {
748
+ "div": [
749
+ {
750
+ "sub": [
751
+ {
752
+ "clamp01": {
753
+ "input": "life"
754
+ }
755
+ },
756
+ 0.1
757
+ ]
758
+ },
759
+ 0.1
760
+ ]
761
+ },
762
+ 3.141592653589793
763
+ ]
764
+ }
765
+ }
766
+ ]
767
+ }
768
+ ]
769
+ },
770
+ 0.7
771
+ ]
772
+ },
773
+ {
774
+ "pow": [
775
+ {
776
+ "add": [
777
+ 0.5,
778
+ {
779
+ "mul": [
780
+ 0.5,
781
+ {
782
+ "cos": {
783
+ "mul": [
784
+ {
785
+ "div": [
786
+ {
787
+ "sub": [
788
+ {
789
+ "clamp01": {
790
+ "input": "life"
791
+ }
792
+ },
793
+ 0.1
794
+ ]
795
+ },
796
+ 0.1
797
+ ]
798
+ },
799
+ 3.141592653589793
800
+ ]
801
+ }
802
+ }
803
+ ]
804
+ }
805
+ ]
806
+ },
807
+ 1.4
808
+ ]
809
+ }
810
+ ]
811
+ },
812
+ 0
813
+ ]
814
+ },
815
+ 0
816
+ ]
817
+ },
818
+ {
819
+ "mul": [
820
+ {
821
+ "lt": [
822
+ -1,
823
+ {
824
+ "div": [
825
+ {
826
+ "sub": [
827
+ {
828
+ "clamp01": {
829
+ "input": "life"
830
+ }
831
+ },
832
+ 0.21
833
+ ]
834
+ },
835
+ 0.075
836
+ ]
837
+ },
838
+ {
839
+ "lt": [
840
+ {
841
+ "div": [
842
+ {
843
+ "sub": [
844
+ {
845
+ "clamp01": {
846
+ "input": "life"
847
+ }
848
+ },
849
+ 0.21
850
+ ]
851
+ },
852
+ 0.075
853
+ ]
854
+ },
855
+ 1,
856
+ {
857
+ "lt": [
858
+ {
859
+ "div": [
860
+ {
861
+ "sub": [
862
+ {
863
+ "clamp01": {
864
+ "input": "life"
865
+ }
866
+ },
867
+ 0.21
868
+ ]
869
+ },
870
+ 0.075
871
+ ]
872
+ },
873
+ 0,
874
+ {
875
+ "pow": [
876
+ {
877
+ "add": [
878
+ 0.5,
879
+ {
880
+ "mul": [
881
+ 0.5,
882
+ {
883
+ "cos": {
884
+ "mul": [
885
+ {
886
+ "div": [
887
+ {
888
+ "sub": [
889
+ {
890
+ "clamp01": {
891
+ "input": "life"
892
+ }
893
+ },
894
+ 0.21
895
+ ]
896
+ },
897
+ 0.075
898
+ ]
899
+ },
900
+ 3.141592653589793
901
+ ]
902
+ }
903
+ }
904
+ ]
905
+ }
906
+ ]
907
+ },
908
+ 0.7
909
+ ]
910
+ },
911
+ {
912
+ "pow": [
913
+ {
914
+ "add": [
915
+ 0.5,
916
+ {
917
+ "mul": [
918
+ 0.5,
919
+ {
920
+ "cos": {
921
+ "mul": [
922
+ {
923
+ "div": [
924
+ {
925
+ "sub": [
926
+ {
927
+ "clamp01": {
928
+ "input": "life"
929
+ }
930
+ },
931
+ 0.21
932
+ ]
933
+ },
934
+ 0.075
935
+ ]
936
+ },
937
+ 3.141592653589793
938
+ ]
939
+ }
940
+ }
941
+ ]
942
+ }
943
+ ]
944
+ },
945
+ 1.4
946
+ ]
947
+ }
948
+ ]
949
+ },
950
+ 0
951
+ ]
952
+ },
953
+ 0
954
+ ]
955
+ },
956
+ 0.62,
957
+ {
958
+ "clamp01": {
959
+ "param": "doubleBeat"
960
+ }
961
+ }
962
+ ]
963
+ }
964
+ ]
965
+ },
966
+ 0.42,
967
+ {
968
+ "param": "beatStrength"
969
+ }
970
+ ]
971
+ }
972
+ ]
973
+ },
974
+ {
975
+ "lt": [
976
+ 0.3,
977
+ {
978
+ "clamp01": {
979
+ "input": "life"
980
+ }
981
+ },
982
+ {
983
+ "mul": [
984
+ 0.06,
985
+ {
986
+ "easeOutCubic": {
987
+ "div": [
988
+ {
989
+ "sub": [
990
+ {
991
+ "clamp01": {
992
+ "input": "life"
993
+ }
994
+ },
995
+ 0.3
996
+ ]
997
+ },
998
+ {
999
+ "sub": [
1000
+ 1,
1001
+ 0.3
1002
+ ]
1003
+ }
1004
+ ]
1005
+ }
1006
+ }
1007
+ ]
1008
+ },
1009
+ 0
1010
+ ]
1011
+ }
1012
+ ]
1013
+ },
1014
+ 1
1015
+ ]
1016
+ }
1017
+ ]
1018
+ },
1019
+ 2.2
1020
+ ]
1021
+ }
1022
+ ]
1023
+ },
1024
+ "burst": {
1025
+ "lt": [
1026
+ 0.3,
1027
+ {
1028
+ "clamp01": {
1029
+ "input": "life"
1030
+ }
1031
+ },
1032
+ {
1033
+ "easeOutCubic": {
1034
+ "div": [
1035
+ {
1036
+ "sub": [
1037
+ {
1038
+ "clamp01": {
1039
+ "input": "life"
1040
+ }
1041
+ },
1042
+ 0.3
1043
+ ]
1044
+ },
1045
+ {
1046
+ "sub": [
1047
+ 1,
1048
+ 0.3
1049
+ ]
1050
+ }
1051
+ ]
1052
+ }
1053
+ },
1054
+ 0
1055
+ ]
1056
+ },
1057
+ "flash": {
1058
+ "min": [
1059
+ 1.2,
1060
+ {
1061
+ "add": [
1062
+ {
1063
+ "mul": [
1064
+ {
1065
+ "max": [
1066
+ 0,
1067
+ {
1068
+ "sub": [
1069
+ {
1070
+ "sub": [
1071
+ {
1072
+ "add": [
1073
+ 1,
1074
+ {
1075
+ "mul": [
1076
+ {
1077
+ "max": [
1078
+ {
1079
+ "lt": [
1080
+ -1,
1081
+ {
1082
+ "div": [
1083
+ {
1084
+ "sub": [
1085
+ {
1086
+ "clamp01": {
1087
+ "input": "life"
1088
+ }
1089
+ },
1090
+ 0.1
1091
+ ]
1092
+ },
1093
+ 0.1
1094
+ ]
1095
+ },
1096
+ {
1097
+ "lt": [
1098
+ {
1099
+ "div": [
1100
+ {
1101
+ "sub": [
1102
+ {
1103
+ "clamp01": {
1104
+ "input": "life"
1105
+ }
1106
+ },
1107
+ 0.1
1108
+ ]
1109
+ },
1110
+ 0.1
1111
+ ]
1112
+ },
1113
+ 1,
1114
+ {
1115
+ "lt": [
1116
+ {
1117
+ "div": [
1118
+ {
1119
+ "sub": [
1120
+ {
1121
+ "clamp01": {
1122
+ "input": "life"
1123
+ }
1124
+ },
1125
+ 0.1
1126
+ ]
1127
+ },
1128
+ 0.1
1129
+ ]
1130
+ },
1131
+ 0,
1132
+ {
1133
+ "pow": [
1134
+ {
1135
+ "add": [
1136
+ 0.5,
1137
+ {
1138
+ "mul": [
1139
+ 0.5,
1140
+ {
1141
+ "cos": {
1142
+ "mul": [
1143
+ {
1144
+ "div": [
1145
+ {
1146
+ "sub": [
1147
+ {
1148
+ "clamp01": {
1149
+ "input": "life"
1150
+ }
1151
+ },
1152
+ 0.1
1153
+ ]
1154
+ },
1155
+ 0.1
1156
+ ]
1157
+ },
1158
+ 3.141592653589793
1159
+ ]
1160
+ }
1161
+ }
1162
+ ]
1163
+ }
1164
+ ]
1165
+ },
1166
+ 0.7
1167
+ ]
1168
+ },
1169
+ {
1170
+ "pow": [
1171
+ {
1172
+ "add": [
1173
+ 0.5,
1174
+ {
1175
+ "mul": [
1176
+ 0.5,
1177
+ {
1178
+ "cos": {
1179
+ "mul": [
1180
+ {
1181
+ "div": [
1182
+ {
1183
+ "sub": [
1184
+ {
1185
+ "clamp01": {
1186
+ "input": "life"
1187
+ }
1188
+ },
1189
+ 0.1
1190
+ ]
1191
+ },
1192
+ 0.1
1193
+ ]
1194
+ },
1195
+ 3.141592653589793
1196
+ ]
1197
+ }
1198
+ }
1199
+ ]
1200
+ }
1201
+ ]
1202
+ },
1203
+ 1.4
1204
+ ]
1205
+ }
1206
+ ]
1207
+ },
1208
+ 0
1209
+ ]
1210
+ },
1211
+ 0
1212
+ ]
1213
+ },
1214
+ {
1215
+ "mul": [
1216
+ {
1217
+ "lt": [
1218
+ -1,
1219
+ {
1220
+ "div": [
1221
+ {
1222
+ "sub": [
1223
+ {
1224
+ "clamp01": {
1225
+ "input": "life"
1226
+ }
1227
+ },
1228
+ 0.21
1229
+ ]
1230
+ },
1231
+ 0.075
1232
+ ]
1233
+ },
1234
+ {
1235
+ "lt": [
1236
+ {
1237
+ "div": [
1238
+ {
1239
+ "sub": [
1240
+ {
1241
+ "clamp01": {
1242
+ "input": "life"
1243
+ }
1244
+ },
1245
+ 0.21
1246
+ ]
1247
+ },
1248
+ 0.075
1249
+ ]
1250
+ },
1251
+ 1,
1252
+ {
1253
+ "lt": [
1254
+ {
1255
+ "div": [
1256
+ {
1257
+ "sub": [
1258
+ {
1259
+ "clamp01": {
1260
+ "input": "life"
1261
+ }
1262
+ },
1263
+ 0.21
1264
+ ]
1265
+ },
1266
+ 0.075
1267
+ ]
1268
+ },
1269
+ 0,
1270
+ {
1271
+ "pow": [
1272
+ {
1273
+ "add": [
1274
+ 0.5,
1275
+ {
1276
+ "mul": [
1277
+ 0.5,
1278
+ {
1279
+ "cos": {
1280
+ "mul": [
1281
+ {
1282
+ "div": [
1283
+ {
1284
+ "sub": [
1285
+ {
1286
+ "clamp01": {
1287
+ "input": "life"
1288
+ }
1289
+ },
1290
+ 0.21
1291
+ ]
1292
+ },
1293
+ 0.075
1294
+ ]
1295
+ },
1296
+ 3.141592653589793
1297
+ ]
1298
+ }
1299
+ }
1300
+ ]
1301
+ }
1302
+ ]
1303
+ },
1304
+ 0.7
1305
+ ]
1306
+ },
1307
+ {
1308
+ "pow": [
1309
+ {
1310
+ "add": [
1311
+ 0.5,
1312
+ {
1313
+ "mul": [
1314
+ 0.5,
1315
+ {
1316
+ "cos": {
1317
+ "mul": [
1318
+ {
1319
+ "div": [
1320
+ {
1321
+ "sub": [
1322
+ {
1323
+ "clamp01": {
1324
+ "input": "life"
1325
+ }
1326
+ },
1327
+ 0.21
1328
+ ]
1329
+ },
1330
+ 0.075
1331
+ ]
1332
+ },
1333
+ 3.141592653589793
1334
+ ]
1335
+ }
1336
+ }
1337
+ ]
1338
+ }
1339
+ ]
1340
+ },
1341
+ 1.4
1342
+ ]
1343
+ }
1344
+ ]
1345
+ },
1346
+ 0
1347
+ ]
1348
+ },
1349
+ 0
1350
+ ]
1351
+ },
1352
+ 0.62,
1353
+ {
1354
+ "clamp01": {
1355
+ "param": "doubleBeat"
1356
+ }
1357
+ }
1358
+ ]
1359
+ }
1360
+ ]
1361
+ },
1362
+ 0.42,
1363
+ {
1364
+ "param": "beatStrength"
1365
+ }
1366
+ ]
1367
+ }
1368
+ ]
1369
+ },
1370
+ {
1371
+ "lt": [
1372
+ 0.3,
1373
+ {
1374
+ "clamp01": {
1375
+ "input": "life"
1376
+ }
1377
+ },
1378
+ {
1379
+ "mul": [
1380
+ 0.06,
1381
+ {
1382
+ "easeOutCubic": {
1383
+ "div": [
1384
+ {
1385
+ "sub": [
1386
+ {
1387
+ "clamp01": {
1388
+ "input": "life"
1389
+ }
1390
+ },
1391
+ 0.3
1392
+ ]
1393
+ },
1394
+ {
1395
+ "sub": [
1396
+ 1,
1397
+ 0.3
1398
+ ]
1399
+ }
1400
+ ]
1401
+ }
1402
+ }
1403
+ ]
1404
+ },
1405
+ 0
1406
+ ]
1407
+ }
1408
+ ]
1409
+ },
1410
+ 1
1411
+ ]
1412
+ }
1413
+ ]
1414
+ },
1415
+ 1.6
1416
+ ]
1417
+ },
1418
+ {
1419
+ "mul": [
1420
+ {
1421
+ "lt": [
1422
+ 0,
1423
+ {
1424
+ "lt": [
1425
+ 0.3,
1426
+ {
1427
+ "clamp01": {
1428
+ "input": "life"
1429
+ }
1430
+ },
1431
+ {
1432
+ "easeOutCubic": {
1433
+ "div": [
1434
+ {
1435
+ "sub": [
1436
+ {
1437
+ "clamp01": {
1438
+ "input": "life"
1439
+ }
1440
+ },
1441
+ 0.3
1442
+ ]
1443
+ },
1444
+ {
1445
+ "sub": [
1446
+ 1,
1447
+ 0.3
1448
+ ]
1449
+ }
1450
+ ]
1451
+ }
1452
+ },
1453
+ 0
1454
+ ]
1455
+ },
1456
+ {
1457
+ "exp": {
1458
+ "sub": [
1459
+ 0,
1460
+ {
1461
+ "pow": [
1462
+ {
1463
+ "div": [
1464
+ {
1465
+ "sub": [
1466
+ {
1467
+ "lt": [
1468
+ 0.3,
1469
+ {
1470
+ "clamp01": {
1471
+ "input": "life"
1472
+ }
1473
+ },
1474
+ {
1475
+ "easeOutCubic": {
1476
+ "div": [
1477
+ {
1478
+ "sub": [
1479
+ {
1480
+ "clamp01": {
1481
+ "input": "life"
1482
+ }
1483
+ },
1484
+ 0.3
1485
+ ]
1486
+ },
1487
+ {
1488
+ "sub": [
1489
+ 1,
1490
+ 0.3
1491
+ ]
1492
+ }
1493
+ ]
1494
+ }
1495
+ },
1496
+ 0
1497
+ ]
1498
+ },
1499
+ 0.06
1500
+ ]
1501
+ },
1502
+ 0.12
1503
+ ]
1504
+ },
1505
+ 2
1506
+ ]
1507
+ }
1508
+ ]
1509
+ }
1510
+ },
1511
+ 0
1512
+ ]
1513
+ },
1514
+ 0.8
1515
+ ]
1516
+ }
1517
+ ]
1518
+ }
1519
+ ]
1520
+ }
1521
+ }
1522
+ },
1523
+ "reducedMotion": {
1524
+ "peakMs": 180,
1525
+ "holdMs": 360
1526
+ },
1527
+ "note": "Datafied per-frame logic (the web/Swift/Kotlin heartburst tempo code, delta-0): a lub-dub double beat (two cos^k pulse lobes at life 0.10 / 0.21, the second scaled by doubleBeat), then the burst easing out over the rest of life. amp tracks the beats and the burst flare; presence snaps in / holds / fades the panel; beat is the thump amplitude; burst the flight progress; flash the warm light spike on each thump + the release."
1528
+ },
1529
+ "geometry": {
1530
+ "kind": "radial",
1531
+ "viewBox": [
1532
+ 0,
1533
+ 0,
1534
+ 100,
1535
+ 100
1536
+ ],
1537
+ "outlines": {
1538
+ "heart": {
1539
+ "role": "love-glyph",
1540
+ "note": "Parametric heart curve drawn in heartburst-renderer drawHeartburstPanel (hero + flurry)."
1541
+ }
1542
+ }
1543
+ },
1544
+ "render": {
1545
+ "params": {
1546
+ "exposure": {
1547
+ "type": "float",
1548
+ "from": {
1549
+ "lerp": [
1550
+ "intensity",
1551
+ 0.85,
1552
+ 1.45
1553
+ ]
1554
+ }
1555
+ },
1556
+ "heartScale": {
1557
+ "type": "float",
1558
+ "from": {
1559
+ "mul": [
1560
+ {
1561
+ "baseline": "heartScale"
1562
+ },
1563
+ {
1564
+ "lerp": [
1565
+ "intensity",
1566
+ 0.9,
1567
+ 1.1
1568
+ ]
1569
+ }
1570
+ ]
1571
+ }
1572
+ },
1573
+ "burstCount": {
1574
+ "type": "int",
1575
+ "from": {
1576
+ "round": {
1577
+ "mul": [
1578
+ {
1579
+ "baseline": "burstCount"
1580
+ },
1581
+ {
1582
+ "lerp": [
1583
+ "intensity",
1584
+ 0.5,
1585
+ 1.3
1586
+ ]
1587
+ }
1588
+ ]
1589
+ }
1590
+ }
1591
+ },
1592
+ "burstSpread": {
1593
+ "type": "float",
1594
+ "from": {
1595
+ "mul": [
1596
+ {
1597
+ "baseline": "burstSpread"
1598
+ },
1599
+ {
1600
+ "lerp": [
1601
+ "intensity",
1602
+ 0.85,
1603
+ 1.2
1604
+ ]
1605
+ }
1606
+ ]
1607
+ }
1608
+ },
1609
+ "beatStrength": {
1610
+ "type": "float",
1611
+ "from": {
1612
+ "mul": [
1613
+ {
1614
+ "baseline": "beatStrength"
1615
+ },
1616
+ {
1617
+ "lerp": [
1618
+ "intensity",
1619
+ 0.7,
1620
+ 1.25
1621
+ ]
1622
+ }
1623
+ ]
1624
+ }
1625
+ },
1626
+ "doubleBeat": {
1627
+ "type": "float",
1628
+ "clamp01": true,
1629
+ "from": {
1630
+ "baseline": "doubleBeat"
1631
+ }
1632
+ },
1633
+ "glow": {
1634
+ "type": "float",
1635
+ "clamp01": true,
1636
+ "from": {
1637
+ "lerp": [
1638
+ "intensity",
1639
+ 0.45,
1640
+ 1
1641
+ ]
1642
+ }
1643
+ },
1644
+ "gloss": {
1645
+ "type": "float",
1646
+ "clamp01": true,
1647
+ "from": {
1648
+ "lerp": [
1649
+ "whimsy",
1650
+ 1,
1651
+ 0
1652
+ ]
1653
+ }
1654
+ },
1655
+ "halftone": {
1656
+ "type": "float",
1657
+ "clamp01": true,
1658
+ "from": {
1659
+ "lerp": [
1660
+ "whimsy",
1661
+ 0.15,
1662
+ 1
1663
+ ]
1664
+ }
1665
+ },
1666
+ "dotSize": {
1667
+ "type": "float",
1668
+ "from": {
1669
+ "lerp": [
1670
+ "whimsy",
1671
+ 5,
1672
+ 10
1673
+ ]
1674
+ }
1675
+ },
1676
+ "saturation": {
1677
+ "type": "float",
1678
+ "clamp01": true,
1679
+ "from": {
1680
+ "mul": [
1681
+ {
1682
+ "lerp": [
1683
+ "whimsy",
1684
+ 0.35,
1685
+ 1
1686
+ ]
1687
+ },
1688
+ {
1689
+ "lerp": [
1690
+ "intensity",
1691
+ 0.8,
1692
+ 1.1
1693
+ ]
1694
+ }
1695
+ ]
1696
+ }
1697
+ },
1698
+ "inkWeight": {
1699
+ "type": "float",
1700
+ "from": {
1701
+ "mul": [
1702
+ {
1703
+ "lerp": [
1704
+ "whimsy",
1705
+ 3,
1706
+ 9
1707
+ ]
1708
+ },
1709
+ {
1710
+ "lerp": [
1711
+ "intensity",
1712
+ 0.9,
1713
+ 1.1
1714
+ ]
1715
+ }
1716
+ ]
1717
+ }
1718
+ },
1719
+ "style": {
1720
+ "type": "float",
1721
+ "from": {
1722
+ "control": "whimsy"
1723
+ }
1724
+ }
1725
+ },
1726
+ "shadowHeightFrac": {
1727
+ "mul": [
1728
+ {
1729
+ "param": "heartScale"
1730
+ },
1731
+ 1.1
1732
+ ]
1733
+ },
1734
+ "pass": {
1735
+ "note": "Per-PASS uniforms: the halftone cell is authored in CSS-ish px and scaled to device px on the host (uDotSize = dotSize * dpr).",
1736
+ "dotSize": {
1737
+ "mul": [
1738
+ {
1739
+ "param": "dotSize"
1740
+ },
1741
+ {
1742
+ "input": "dpr"
1743
+ }
1744
+ ]
1745
+ }
1746
+ },
1747
+ "panel": {
1748
+ "sampler": "uPanel",
1749
+ "texture": 0,
1750
+ "note": "The Canvas2D/CoreGraphics/android.graphics panel (hero heart + burst flurry, R=fill G=ink B=burst) the host redraws every frame; the draw itself is the per-platform panel-draw seam (web hooks / Heartburst Panel files)."
1751
+ },
1752
+ "consts": {},
1753
+ "config": {
1754
+ "usesOrigin": true,
1755
+ "stepping": "none"
1756
+ },
1757
+ "backends": {
1758
+ "webgl2": {
1759
+ "stage": "fullscreen-triangle",
1760
+ "blend": "screen",
1761
+ "shader": {
1762
+ "program": "heartburst"
1763
+ },
1764
+ "note": "Hybrid: a Canvas2D panel (hero heart + little hearts, vector heart curves) is uploaded as a texture; the shader adds bloom, gloss, halftone blush, beat flash and casts warm light + shadow."
1765
+ }
1766
+ },
1767
+ "fallbackOrder": [
1768
+ "webgl2"
1769
+ ]
1770
+ },
1771
+ "binding": {
1772
+ "note": "CROSS-PLATFORM uniform-binding contract. Which render.params are NOT shader uniforms, the seed-keyed scatter field, the per-frame/host extras, and the texture samplers — one source of truth for the web u<Name> list, the Swift struct + packer, and the MSL struct. SHIPS in the portable .dope (the runtime derives its uniform bindings from it); the toolchain consumes it too for the Metal struct codegen. Only `x-build`, `slug` and `kind` stay toolchain-only.",
1773
+ "excludeParams": [
1774
+ "style",
1775
+ "heartScale",
1776
+ "burstCount",
1777
+ "burstSpread",
1778
+ "inkWeight",
1779
+ "beatStrength",
1780
+ "doubleBeat",
1781
+ "dotSize",
1782
+ "seed"
1783
+ ],
1784
+ "scatterKey": "heartburstSeed",
1785
+ "scatterWeb": "uSeed",
1786
+ "extras": [
1787
+ {
1788
+ "name": "presence",
1789
+ "type": "float",
1790
+ "web": "uPresence",
1791
+ "note": "panel opacity / presence 0..1"
1792
+ },
1793
+ {
1794
+ "name": "beat",
1795
+ "type": "float",
1796
+ "web": "uBeat",
1797
+ "note": "0..1 current beat amplitude (lub-dub thump)"
1798
+ },
1799
+ {
1800
+ "name": "burst",
1801
+ "type": "float",
1802
+ "web": "uBurst",
1803
+ "note": "0..1 burst progress (little hearts flying out)"
1804
+ },
1805
+ {
1806
+ "name": "flash",
1807
+ "type": "float",
1808
+ "web": "uFlash",
1809
+ "note": "0..1 warm beat/burst flash amount"
1810
+ },
1811
+ {
1812
+ "name": "dotSize",
1813
+ "type": "float",
1814
+ "web": "uDotSize",
1815
+ "note": "halftone cell size in device px (dpr-scaled)"
1816
+ }
1817
+ ],
1818
+ "samplers": [
1819
+ {
1820
+ "web": "uPanel",
1821
+ "name": "panelTex",
1822
+ "texture": 0,
1823
+ "note": "the per-frame panel texture (render.panel)"
1824
+ }
1825
+ ]
1826
+ }
1827
+ }