@mumulinya167/ccm-pet-assets 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +4 -0
  2. package/assets/calico/calico-collapsing.apng +0 -0
  3. package/assets/calico/calico-dozing.apng +0 -0
  4. package/assets/calico/calico-error.apng +0 -0
  5. package/assets/calico/calico-happy.apng +0 -0
  6. package/assets/calico/calico-idle-follow.svg +324 -0
  7. package/assets/calico/calico-idle.apng +0 -0
  8. package/assets/calico/calico-mini-alert.apng +0 -0
  9. package/assets/calico/calico-mini-crabwalk.apng +0 -0
  10. package/assets/calico/calico-mini-enter.apng +0 -0
  11. package/assets/calico/calico-mini-happy.apng +0 -0
  12. package/assets/calico/calico-mini-idle.apng +0 -0
  13. package/assets/calico/calico-mini-peek.apng +0 -0
  14. package/assets/calico/calico-mini-sleep.apng +0 -0
  15. package/assets/calico/calico-notification.apng +0 -0
  16. package/assets/calico/calico-react-drag.apng +0 -0
  17. package/assets/calico/calico-react-left.apng +0 -0
  18. package/assets/calico/calico-react-poke.apng +0 -0
  19. package/assets/calico/calico-sleeping.apng +0 -0
  20. package/assets/calico/calico-thinking.apng +0 -0
  21. package/assets/calico/calico-waking.apng +0 -0
  22. package/assets/calico/calico-working-building.apng +0 -0
  23. package/assets/calico/calico-working-carrying.apng +0 -0
  24. package/assets/calico/calico-working-conducting.apng +0 -0
  25. package/assets/calico/calico-working-juggling.apng +0 -0
  26. package/assets/calico/calico-working-sweeping.apng +0 -0
  27. package/assets/calico/calico-working-typing.apng +0 -0
  28. package/assets/calico/calico-yawning.apng +0 -0
  29. package/assets/calico.svg +324 -0
  30. package/assets/clawd/LICENSE +22 -0
  31. package/assets/clawd/clawd-about-hero.svg +202 -0
  32. package/assets/clawd/clawd-collapse-sleep.svg +247 -0
  33. package/assets/clawd/clawd-error.svg +94 -0
  34. package/assets/clawd/clawd-happy.svg +161 -0
  35. package/assets/clawd/clawd-headphones-groove.svg +194 -0
  36. package/assets/clawd/clawd-idle-bubble.svg +180 -0
  37. package/assets/clawd/clawd-idle-collapse.svg +101 -0
  38. package/assets/clawd/clawd-idle-doze.svg +72 -0
  39. package/assets/clawd/clawd-idle-follow.svg +64 -0
  40. package/assets/clawd/clawd-idle-living.svg +196 -0
  41. package/assets/clawd/clawd-idle-look.svg +115 -0
  42. package/assets/clawd/clawd-idle-reading.svg +252 -0
  43. package/assets/clawd/clawd-idle-yawn.svg +158 -0
  44. package/assets/clawd/clawd-mini-alert.svg +129 -0
  45. package/assets/clawd/clawd-mini-crabwalk.svg +76 -0
  46. package/assets/clawd/clawd-mini-enter-sleep.svg +64 -0
  47. package/assets/clawd/clawd-mini-enter.svg +114 -0
  48. package/assets/clawd/clawd-mini-happy.svg +124 -0
  49. package/assets/clawd/clawd-mini-idle.svg +83 -0
  50. package/assets/clawd/clawd-mini-peek.svg +82 -0
  51. package/assets/clawd/clawd-mini-sleep.svg +112 -0
  52. package/assets/clawd/clawd-mini-typing.svg +153 -0
  53. package/assets/clawd/clawd-notification.svg +438 -0
  54. package/assets/clawd/clawd-react-annoyed.svg +167 -0
  55. package/assets/clawd/clawd-react-double-jump.svg +229 -0
  56. package/assets/clawd/clawd-react-double.svg +108 -0
  57. package/assets/clawd/clawd-react-drag.svg +102 -0
  58. package/assets/clawd/clawd-react-left.svg +102 -0
  59. package/assets/clawd/clawd-react-right.svg +102 -0
  60. package/assets/clawd/clawd-sleeping.svg +118 -0
  61. package/assets/clawd/clawd-static-base.svg +21 -0
  62. package/assets/clawd/clawd-wake.svg +277 -0
  63. package/assets/clawd/clawd-working-building.svg +329 -0
  64. package/assets/clawd/clawd-working-carrying.svg +178 -0
  65. package/assets/clawd/clawd-working-debugger.svg +245 -0
  66. package/assets/clawd/clawd-working-juggling.svg +183 -0
  67. package/assets/clawd/clawd-working-sweeping.svg +248 -0
  68. package/assets/clawd/clawd-working-thinking.svg +501 -0
  69. package/assets/clawd/clawd-working-typing-boss.svg +307 -0
  70. package/assets/clawd/clawd-working-typing.svg +273 -0
  71. package/assets/clawd/clawd-working-ultrathink.svg +166 -0
  72. package/assets/clawd/clawd-working-wizard.svg +356 -0
  73. package/assets/clawd.svg +64 -0
  74. package/assets/cloudling/cloudling/cloudling-attention.svg +380 -0
  75. package/assets/cloudling/cloudling/cloudling-building.svg +667 -0
  76. package/assets/cloudling/cloudling/cloudling-carrying.svg +604 -0
  77. package/assets/cloudling/cloudling/cloudling-conducting.svg +616 -0
  78. package/assets/cloudling/cloudling/cloudling-dozing-to-sleeping.svg +578 -0
  79. package/assets/cloudling/cloudling/cloudling-dozing.svg +358 -0
  80. package/assets/cloudling/cloudling/cloudling-error.svg +428 -0
  81. package/assets/cloudling/cloudling/cloudling-idle-reading.svg +658 -0
  82. package/assets/cloudling/cloudling/cloudling-idle-to-dozing.svg +568 -0
  83. package/assets/cloudling/cloudling/cloudling-idle-to-sleeping.svg +811 -0
  84. package/assets/cloudling/cloudling/cloudling-idle.svg +255 -0
  85. package/assets/cloudling/cloudling/cloudling-juggling.svg +648 -0
  86. package/assets/cloudling/cloudling/cloudling-mini-alert.svg +390 -0
  87. package/assets/cloudling/cloudling/cloudling-mini-crabwalk.svg +335 -0
  88. package/assets/cloudling/cloudling/cloudling-mini-enter-roll-in.svg +226 -0
  89. package/assets/cloudling/cloudling/cloudling-mini-enter-sleep.svg +232 -0
  90. package/assets/cloudling/cloudling/cloudling-mini-happy.svg +371 -0
  91. package/assets/cloudling/cloudling/cloudling-mini-idle.svg +279 -0
  92. package/assets/cloudling/cloudling/cloudling-mini-peek.svg +328 -0
  93. package/assets/cloudling/cloudling/cloudling-mini-sleep.svg +260 -0
  94. package/assets/cloudling/cloudling/cloudling-mini-typing.svg +692 -0
  95. package/assets/cloudling/cloudling/cloudling-notification.svg +494 -0
  96. package/assets/cloudling/cloudling/cloudling-react-drag.svg +83 -0
  97. package/assets/cloudling/cloudling/cloudling-sleeping-to-idle.svg +555 -0
  98. package/assets/cloudling/cloudling/cloudling-sleeping.svg +500 -0
  99. package/assets/cloudling/cloudling/cloudling-sweeping.svg +292 -0
  100. package/assets/cloudling/cloudling/cloudling-thinking.svg +720 -0
  101. package/assets/cloudling/cloudling/cloudling-typing.svg +354 -0
  102. package/assets/cloudling/cloudling-attention.svg +380 -0
  103. package/assets/cloudling/cloudling-building.svg +667 -0
  104. package/assets/cloudling/cloudling-carrying.svg +604 -0
  105. package/assets/cloudling/cloudling-conducting.svg +616 -0
  106. package/assets/cloudling/cloudling-dozing-to-sleeping.svg +578 -0
  107. package/assets/cloudling/cloudling-dozing.svg +358 -0
  108. package/assets/cloudling/cloudling-error.svg +428 -0
  109. package/assets/cloudling/cloudling-idle-reading.svg +658 -0
  110. package/assets/cloudling/cloudling-idle-to-dozing.svg +568 -0
  111. package/assets/cloudling/cloudling-idle-to-sleeping.svg +811 -0
  112. package/assets/cloudling/cloudling-idle.svg +255 -0
  113. package/assets/cloudling/cloudling-juggling.svg +648 -0
  114. package/assets/cloudling/cloudling-mini-alert.svg +390 -0
  115. package/assets/cloudling/cloudling-mini-crabwalk.svg +335 -0
  116. package/assets/cloudling/cloudling-mini-enter-roll-in.svg +226 -0
  117. package/assets/cloudling/cloudling-mini-enter-sleep.svg +232 -0
  118. package/assets/cloudling/cloudling-mini-happy.svg +371 -0
  119. package/assets/cloudling/cloudling-mini-idle.svg +279 -0
  120. package/assets/cloudling/cloudling-mini-peek.svg +328 -0
  121. package/assets/cloudling/cloudling-mini-sleep.svg +260 -0
  122. package/assets/cloudling/cloudling-mini-typing.svg +692 -0
  123. package/assets/cloudling/cloudling-notification.svg +494 -0
  124. package/assets/cloudling/cloudling-react-drag.svg +83 -0
  125. package/assets/cloudling/cloudling-sleeping-to-idle.svg +555 -0
  126. package/assets/cloudling/cloudling-sleeping.svg +500 -0
  127. package/assets/cloudling/cloudling-sweeping.svg +292 -0
  128. package/assets/cloudling/cloudling-thinking.svg +720 -0
  129. package/assets/cloudling/cloudling-typing.svg +354 -0
  130. package/assets/cloudling.svg +255 -0
  131. package/assets/ghost-attention.svg +19 -0
  132. package/assets/ghost-carrying.svg +19 -0
  133. package/assets/ghost-collapsing.svg +19 -0
  134. package/assets/ghost-dozing.svg +23 -0
  135. package/assets/ghost-error.svg +19 -0
  136. package/assets/ghost-happy.svg +23 -0
  137. package/assets/ghost-idle-action1.svg +19 -0
  138. package/assets/ghost-idle-action2.svg +19 -0
  139. package/assets/ghost-idle-action3.svg +19 -0
  140. package/assets/ghost-idle.svg +11 -0
  141. package/assets/ghost-juggling.svg +19 -0
  142. package/assets/ghost-notification.svg +19 -0
  143. package/assets/ghost-react-double.svg +23 -0
  144. package/assets/ghost-react-drag.svg +23 -0
  145. package/assets/ghost-react-left.svg +19 -0
  146. package/assets/ghost-react-right.svg +19 -0
  147. package/assets/ghost-sleeping.svg +19 -0
  148. package/assets/ghost-sweeping.svg +19 -0
  149. package/assets/ghost-thinking.svg +19 -0
  150. package/assets/ghost-waking.svg +19 -0
  151. package/assets/ghost-working.svg +19 -0
  152. package/assets/ghost-yawning.svg +23 -0
  153. package/assets/ghost.svg +11 -0
  154. package/assets/robot-attention.svg +19 -0
  155. package/assets/robot-carrying.svg +19 -0
  156. package/assets/robot-collapsing.svg +19 -0
  157. package/assets/robot-dozing.svg +23 -0
  158. package/assets/robot-error.svg +19 -0
  159. package/assets/robot-happy.svg +23 -0
  160. package/assets/robot-idle-action1.svg +19 -0
  161. package/assets/robot-idle-action2.svg +19 -0
  162. package/assets/robot-idle-action3.svg +19 -0
  163. package/assets/robot-idle.svg +11 -0
  164. package/assets/robot-juggling.svg +19 -0
  165. package/assets/robot-notification.svg +19 -0
  166. package/assets/robot-react-double.svg +23 -0
  167. package/assets/robot-react-drag.svg +23 -0
  168. package/assets/robot-react-left.svg +19 -0
  169. package/assets/robot-react-right.svg +19 -0
  170. package/assets/robot-sleeping.svg +19 -0
  171. package/assets/robot-sweeping.svg +19 -0
  172. package/assets/robot-thinking.svg +19 -0
  173. package/assets/robot-waking.svg +19 -0
  174. package/assets/robot-working.svg +19 -0
  175. package/assets/robot-yawning.svg +23 -0
  176. package/assets/robot.svg +11 -0
  177. package/manifest.json +889 -0
  178. package/package.json +18 -0
@@ -0,0 +1,380 @@
1
+ <svg aria-label="Cloudling happy burst animation" xmlns="http://www.w3.org/2000/svg" width="880" height="720" viewBox="-32 -24 88 72" preserveAspectRatio="xMidYMid meet">
2
+ <style><![CDATA[
3
+ .phase-tag {
4
+ position: absolute;
5
+ top: 16px;
6
+ left: 50%;
7
+ transform: translateX(-50%);
8
+ z-index: 2;
9
+ padding: 4px 14px;
10
+ border-radius: 6px;
11
+ background: rgba(122, 157, 255, .16);
12
+ color: #8ea6ff;
13
+ font: 700 11px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
14
+ letter-spacing: .06em;
15
+ white-space: nowrap;
16
+ pointer-events: none;
17
+ }
18
+ .timeline {
19
+ position: absolute;
20
+ right: 16px;
21
+ bottom: 12px;
22
+ left: 16px;
23
+ height: 4px;
24
+ overflow: hidden;
25
+ border-radius: 99px;
26
+ background: rgba(255, 255, 255, .06);
27
+ }
28
+ .timeline-fill {
29
+ width: 0;
30
+ height: 100%;
31
+ border-radius: inherit;
32
+ background: linear-gradient(90deg, #9a8cff, #61b8ff, #58e6d4, #ff8fc6, #ffffff);
33
+ }
34
+ .edge-rim-tight { stroke-opacity: .65; }
35
+ .edge-rim-soft { stroke-opacity: .50; }
36
+ .edge-contact { stroke-opacity: .65; }
37
+ @media (prefers-color-scheme: light) {
38
+ .phase-tag {
39
+ background: rgba(57, 65, 255, .1);
40
+ color: #4650ff;
41
+ }
42
+ .timeline { background: rgba(0, 0, 0, .06); }
43
+ .edge-rim-tight { stroke-opacity: .75; }
44
+ .edge-rim-soft { stroke-opacity: .1; }
45
+ .edge-contact { stroke-opacity: .75; }
46
+ .cloud-drop-shadow { flood-opacity: .13; }
47
+ .food-cloud-shadow { flood-opacity: .28; flood-color: #5060FF; }
48
+ .food-cloud > path {
49
+ stroke: #5870E8 !important;
50
+ stroke-width: 1.2 !important;
51
+ stroke-opacity: .9 !important;
52
+ vector-effect: non-scaling-stroke !important;
53
+ }
54
+ }
55
+ ]]></style>
56
+ <defs>
57
+ <linearGradient id="bg-grad" x1="12" y1="2" x2="12" y2="22" gradientUnits="userSpaceOnUse">
58
+ <stop offset="0" stop-color="#fff"/>
59
+ <stop offset=".5" stop-color="#e0f2fe"/>
60
+ <stop offset="1" stop-color="#bae6fd"/>
61
+ </linearGradient>
62
+ <linearGradient id="eye-grad" x1="12" y1="3" x2="12" y2="21" gradientUnits="userSpaceOnUse">
63
+ <stop offset="0" stop-color="#B1A7FF"/>
64
+ <stop offset=".5" stop-color="#7A9DFF"/>
65
+ <stop offset="1" stop-color="#3941FF"/>
66
+ </linearGradient>
67
+ <radialGradient id="hi-grad" cx=".45" cy=".25" r=".55">
68
+ <stop offset="0" stop-color="#fff" stop-opacity=".9"/>
69
+ <stop offset="1" stop-color="#fff" stop-opacity="0"/>
70
+ </radialGradient>
71
+ <path id="cs" d="M9.064 3.344a4.578 4.578 0 012.285-.312c1 .115 1.891.54 2.673 1.275.01.01.024.017.037.021a.09.09 0 00.043 0 4.55 4.55 0 013.046.275l.047.022.116.057a4.581 4.581 0 012.188 2.399c.209.51.313 1.041.315 1.595a4.24 4.24 0 01-.134 1.223.123.123 0 00.03.115c.594.607.988 1.33 1.183 2.17.289 1.425-.007 2.71-.887 3.854l-.136.166a4.548 4.548 0 01-2.201 1.388.123.123 0 00-.081.076c-.191.551-.383 1.023-.74 1.494-.9 1.187-2.222 1.846-3.711 1.838-1.187-.006-2.239-.44-3.157-1.302a.107.107 0 00-.105-.024c-.388.125-.78.143-1.204.138a4.441 4.441 0 01-1.945-.466 4.544 4.544 0 01-1.61-1.335c-.152-.202-.303-.392-.414-.617a5.81 5.81 0 01-.37-.961 4.582 4.582 0 01-.014-2.298.124.124 0 00.006-.056.085.085 0 00-.027-.048 4.467 4.467 0 01-1.034-1.651 3.896 3.896 0 01-.251-1.192 5.189 5.189 0 01.141-1.6c.337-1.112.982-1.985 1.933-2.618.212-.141.413-.251.601-.33.215-.089.43-.164.646-.227a.098.098 0 00.065-.066 4.51 4.51 0 01.829-1.615 4.535 4.535 0 011.837-1.388z"/>
72
+ <clipPath id="cp"><use href="#cs"/></clipPath>
73
+ <filter id="drop" x="-45%" y="-45%" width="190%" height="190%">
74
+ <feDropShadow class="cloud-drop-shadow" dx="0" dy=".65" stdDeviation=".8" flood-color="#3941FF" flood-opacity=".18"/>
75
+ </filter>
76
+ <filter id="edge-blur" x="-45%" y="-45%" width="190%" height="190%">
77
+ <feGaussianBlur stdDeviation=".16"/>
78
+ </filter>
79
+ <filter id="ring-glow" x="-70%" y="-70%" width="240%" height="240%">
80
+ <feGaussianBlur stdDeviation=".68" result="blur"/>
81
+ <feColorMatrix in="blur" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 .52 0" result="soft"/>
82
+ <feMerge>
83
+ <feMergeNode in="soft"/>
84
+ <feMergeNode in="SourceGraphic"/>
85
+ </feMerge>
86
+ </filter>
87
+ </defs>
88
+
89
+ <g id="rainbowRing" filter="url(#ring-glow)">
90
+ <use id="halo" href="#cs" fill="none" stroke="#fff" stroke-width="10.4" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="0 100" stroke-dashoffset="-16" stroke-opacity="0"/>
91
+ <use id="r4" href="#cs" fill="none" stroke="#FF8FC6" stroke-width="8.3" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="0 100" stroke-dashoffset="-16" stroke-opacity="0"/>
92
+ <use id="r3" href="#cs" fill="none" stroke="#58E6D4" stroke-width="6.2" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="0 100" stroke-dashoffset="-16" stroke-opacity="0"/>
93
+ <use id="r2" href="#cs" fill="none" stroke="#61B8FF" stroke-width="4.1" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="0 100" stroke-dashoffset="-16" stroke-opacity="0"/>
94
+ <use id="r1" href="#cs" fill="none" stroke="#9A8CFF" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="0 100" stroke-dashoffset="-16" stroke-opacity="0"/>
95
+ <use id="runnerAura" href="#cs" fill="none" stroke="#fff" stroke-width="5.8" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="4.8 95.2" stroke-dashoffset="-16" stroke-opacity="0"/>
96
+ <use id="runnerTail" href="#cs" fill="none" stroke="#DFF7FF" stroke-width="4.1" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="8.5 91.5" stroke-dashoffset="-16" stroke-opacity="0"/>
97
+ <use id="runnerCore" href="#cs" fill="none" stroke="#fff" stroke-width="1.85" stroke-linecap="round" stroke-linejoin="round" pathLength="100" stroke-dasharray="2.8 97.2" stroke-dashoffset="-16" stroke-opacity="0"/>
98
+ </g>
99
+
100
+ <g id="sparkles">
101
+ <circle class="spark" cx="0" cy="0" r=".3" fill="#F3FBFF"/>
102
+ <path class="spark" d="M0 -0.45 L0.45 0 L0 0.45 L-0.45 0 Z" fill="#58E6D4"/>
103
+ <circle class="spark" cx="0" cy="0" r=".24" fill="#FF8FC6"/>
104
+ <path class="spark" d="M0 -0.38 L0.38 0 L0 0.38 L-0.38 0 Z" fill="#9A8CFF"/>
105
+ <circle class="spark" cx="0" cy="0" r=".22" fill="#FFFFFF"/>
106
+ <circle class="spark" cx="0" cy="0" r=".18" fill="#61B8FF"/>
107
+ </g>
108
+
109
+ <g id="cloudWrap">
110
+ <g id="edge-system">
111
+ <use class="edge-contact" href="#cs" fill="none" stroke="#7d8aa7" stroke-width="1.05" stroke-linejoin="round" transform="translate(0 .18)" filter="url(#edge-blur)"/>
112
+ <use class="edge-rim-soft" href="#cs" fill="none" stroke="#7A9DFF" stroke-width=".9" stroke-linejoin="round" filter="url(#edge-blur)"/>
113
+ <use class="edge-rim-tight" href="#cs" fill="none" stroke="#aab3c6" stroke-width=".42" stroke-linejoin="round"/>
114
+ </g>
115
+ <g filter="url(#drop)">
116
+ <use href="#cs" fill="url(#bg-grad)"/>
117
+ <rect x="1" y="2" width="22" height="11" fill="url(#hi-grad)" clip-path="url(#cp)"/>
118
+ </g>
119
+ <g id="capsuleEye">
120
+ <rect id="capL" x="7.7" y="9.5" width="2.6" height="5" rx="1.3" fill="url(#eye-grad)"/>
121
+ <rect id="capR" x="13.7" y="9.5" width="2.6" height="5" rx="1.3" fill="url(#eye-grad)"/>
122
+ </g>
123
+ <g id="arcEye" opacity="0">
124
+ <path id="arcL" fill="none" stroke="url(#eye-grad)" stroke-width="1.25" stroke-linecap="round"/>
125
+ <path id="arcR" fill="none" stroke="url(#eye-grad)" stroke-width="1.25" stroke-linecap="round"/>
126
+ </g>
127
+ </g>
128
+ <g id="__cloudling-export-shims" opacity="0" pointer-events="none" style="display:none">
129
+ <g id="debug"></g>
130
+ <g id="light"></g>
131
+ <g id="pause"></g>
132
+ <g id="phaseTag"></g>
133
+ <g id="replay"></g>
134
+ <g id="timelineFill"></g>
135
+ </g>
136
+
137
+ <script type="application/ecmascript"><![CDATA[
138
+ const ring = document.getElementById('rainbowRing');
139
+ const cloudWrap = document.getElementById('cloudWrap');
140
+ const halo = document.getElementById('halo');
141
+ const runnerAura = document.getElementById('runnerAura');
142
+ const runnerTail = document.getElementById('runnerTail');
143
+ const runnerCore = document.getElementById('runnerCore');
144
+ const ringLayers = [
145
+ { el: document.getElementById('r1'), opacity: 1 },
146
+ { el: document.getElementById('r2'), opacity: .98 },
147
+ { el: document.getElementById('r3'), opacity: .96 },
148
+ { el: document.getElementById('r4'), opacity: .92 },
149
+ ];
150
+ const capsule = document.getElementById('capsuleEye');
151
+ const arcEye = document.getElementById('arcEye');
152
+ const arcL = document.getElementById('arcL');
153
+ const arcR = document.getElementById('arcR');
154
+ const sparkEls = [...document.querySelectorAll('.spark')];
155
+ const phaseTag = document.getElementById('phaseTag');
156
+ const timelineFill = document.getElementById('timelineFill');
157
+ const pauseBtn = document.getElementById('pause');
158
+ const replayBtn = document.getElementById('replay');
159
+ const light = document.getElementById('light');
160
+ const debug = document.getElementById('debug');
161
+
162
+ const TOTAL = 2.84;
163
+ const GAP = .82;
164
+ const SWEEP_OFFSET = -16;
165
+ const RING_COUNT = 4;
166
+ const SMILE = { h: 1, w: 3.5 };
167
+ const LAUGH = { h: 1.32, w: 3.95 };
168
+ const EYE_CY = 12.7;
169
+ const CX_L = 8.65;
170
+ const CX_R = 15.35;
171
+ const sparks = [
172
+ { x: 4.1, y: 4.1, dx: -2.4, dy: -1.7, d: 0, s: 1.1, rot: -18 },
173
+ { x: 12.1, y: 1.2, dx: .1, dy: -2.4, d: .08, s: .95, rot: 16 },
174
+ { x: 20.6, y: 6.4, dx: 2.2, dy: -1.4, d: .14, s: 1, rot: 24 },
175
+ { x: 22.1, y: 15.4, dx: 2.2, dy: 1.4, d: .2, s: .92, rot: -14 },
176
+ { x: 10.3, y: 22, dx: -.6, dy: 2.1, d: .25, s: .85, rot: 11 },
177
+ { x: 1.8, y: 14.2, dx: -2, dy: .9, d: .18, s: .82, rot: -28 },
178
+ ];
179
+
180
+ let elapsed = 0;
181
+ let prev = 0;
182
+ let paused = false;
183
+
184
+ function clamp(x, lo, hi) { return Math.max(lo, Math.min(hi, x)); }
185
+ function lerp(a, b, t) { return a + (b - a) * t; }
186
+ function easeOutCubic(x) { return 1 - Math.pow(1 - x, 3); }
187
+ function easeInCubic(x) { return x * x * x; }
188
+ function easeInOutCubic(x) {
189
+ return x < .5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
190
+ }
191
+ function arcPath(h, w) {
192
+ const w2 = w / 2;
193
+ const peakY = EYE_CY - 2 * h;
194
+ return {
195
+ l: `M ${(CX_L - w2).toFixed(2)} ${EYE_CY} Q ${CX_L} ${peakY.toFixed(2)} ${(CX_L + w2).toFixed(2)} ${EYE_CY}`,
196
+ r: `M ${(CX_R - w2).toFixed(2)} ${EYE_CY} Q ${CX_R} ${peakY.toFixed(2)} ${(CX_R + w2).toFixed(2)} ${EYE_CY}`,
197
+ };
198
+ }
199
+ function setArc(shape) {
200
+ const d = arcPath(shape.h, shape.w);
201
+ arcL.setAttribute('d', d.l);
202
+ arcR.setAttribute('d', d.r);
203
+ }
204
+ function setCenteredTransform(el, sx, sy = sx, rot = 0, tx = 0, ty = 0) {
205
+ el.setAttribute('transform', `translate(${(12 + tx).toFixed(3)} ${(12 + ty).toFixed(3)}) rotate(${rot.toFixed(3)}) scale(${sx.toFixed(4)} ${sy.toFixed(4)}) translate(-12 -12)`);
206
+ }
207
+ function setRing(layerLevels, haloOpacity, scale, runnerProgress, runnerOpacity) {
208
+ ringLayers.forEach(({ el, opacity: layerOpacity }, i) => {
209
+ el.setAttribute('stroke-dasharray', '100 .01');
210
+ el.setAttribute('stroke-dashoffset', 0);
211
+ el.setAttribute('stroke-opacity', (clamp(layerLevels[i] || 0, 0, 1) * layerOpacity).toFixed(3));
212
+ });
213
+ halo.setAttribute('stroke-dasharray', '100 .01');
214
+ halo.setAttribute('stroke-dashoffset', 0);
215
+ halo.setAttribute('stroke-opacity', clamp(haloOpacity, 0, .1).toFixed(3));
216
+ const runnerOffset = SWEEP_OFFSET - 100 * runnerProgress;
217
+ runnerAura.setAttribute('stroke-dashoffset', runnerOffset.toFixed(2));
218
+ runnerTail.setAttribute('stroke-dashoffset', runnerOffset.toFixed(2));
219
+ runnerCore.setAttribute('stroke-dashoffset', runnerOffset.toFixed(2));
220
+ runnerAura.setAttribute('stroke-opacity', (runnerOpacity * .18).toFixed(3));
221
+ runnerTail.setAttribute('stroke-opacity', (runnerOpacity * .78).toFixed(3));
222
+ runnerCore.setAttribute('stroke-opacity', runnerOpacity.toFixed(3));
223
+ setCenteredTransform(ring, scale);
224
+ }
225
+ function setSparkles(amount) {
226
+ sparkEls.forEach((el, i) => {
227
+ const cfg = sparks[i];
228
+ const p = clamp((amount - cfg.d) / .62, 0, 1);
229
+ const visible = Math.sin(Math.PI * p);
230
+ const move = easeOutCubic(p);
231
+ const x = cfg.x + cfg.dx * move;
232
+ const y = cfg.y + cfg.dy * move;
233
+ const scale = cfg.s * (.45 + .75 * visible);
234
+ el.setAttribute('transform', `translate(${x.toFixed(2)} ${y.toFixed(2)}) rotate(${(cfg.rot + 80 * p).toFixed(1)}) scale(${scale.toFixed(3)})`);
235
+ el.setAttribute('opacity', (visible * .95).toFixed(3));
236
+ });
237
+ }
238
+ function render(t) {
239
+ const T_anti = .16;
240
+ const T_layers = .96;
241
+ const T_confirm = .18;
242
+ const T_hold = .86;
243
+ const T_fade = .42;
244
+ const T_back = .26;
245
+ const a1 = T_anti;
246
+ const a2 = a1 + T_layers;
247
+ const a3 = a2 + T_confirm;
248
+ const a4 = a3 + T_hold;
249
+ const a5 = a4 + T_fade;
250
+ const a6 = a5 + T_back;
251
+
252
+ let phase = 'idle baseline';
253
+ let layerLevels = [0, 0, 0, 0];
254
+ let haloOpacity = 0;
255
+ let ringScale = 1;
256
+ let runnerProgress = 0;
257
+ let runnerOpacity = 0;
258
+ let cloudSx = 1;
259
+ let cloudSy = 1;
260
+ let cloudRot = 0;
261
+ let capsuleOp = 1;
262
+ let arcOp = 0;
263
+ let eye = SMILE;
264
+ let sparkleAmount = 0;
265
+
266
+ if (t < a1) {
267
+ phase = '① squash charge';
268
+ const p = t / T_anti;
269
+ const pulse = Math.sin(Math.PI * p);
270
+ cloudSx = 1 + .055 * pulse;
271
+ cloudSy = 1 - .08 * pulse;
272
+ capsuleOp = 1;
273
+ arcOp = 0;
274
+ eye = SMILE;
275
+ } else if (t < a2) {
276
+ const p = (t - a1) / T_layers;
277
+ const laps = p * RING_COUNT;
278
+ const completed = Math.min(RING_COUNT, Math.floor(laps));
279
+ const lapLocal = laps - completed;
280
+ const lightIn = easeOutCubic(clamp(p * 4, 0, 1));
281
+ const justLit = completed > 0 ? Math.max(0, 1 - (lapLocal * T_layers / RING_COUNT) / .085) : 0;
282
+ phase = `② runner lap ${Math.min(completed + 1, RING_COUNT)}/${RING_COUNT}`;
283
+ layerLevels = ringLayers.map((_, i) => i < completed ? 1 : 0);
284
+ haloOpacity = 0;
285
+ ringScale = 1 + .014 * lightIn + .012 * justLit;
286
+ runnerProgress = laps;
287
+ runnerOpacity = .9 * lightIn;
288
+ cloudSx = cloudSy = 1 + .014 * lightIn + .007 * justLit;
289
+ capsuleOp = 1 - easeOutCubic(clamp(p * 1.7, 0, 1));
290
+ arcOp = easeOutCubic(clamp(p * 1.7, 0, 1));
291
+ eye = {
292
+ h: lerp(SMILE.h, LAUGH.h, easeInOutCubic(clamp((p - .2) / .8, 0, 1))),
293
+ w: lerp(SMILE.w, LAUGH.w, easeInOutCubic(clamp((p - .2) / .8, 0, 1))),
294
+ };
295
+ } else if (t < a3) {
296
+ phase = '③ confirm lap';
297
+ const p = (t - a2) / T_confirm;
298
+ const pop = Math.sin(Math.PI * p);
299
+ layerLevels = [1, 1, 1, 1];
300
+ haloOpacity = .04;
301
+ ringScale = 1.018 + .02 * pop;
302
+ runnerProgress = RING_COUNT + p;
303
+ runnerOpacity = .95 * (1 - .25 * p);
304
+ cloudSx = cloudSy = 1.02 + .018 * pop;
305
+ cloudRot = 2.6 * Math.sin(2 * Math.PI * p);
306
+ capsuleOp = 0;
307
+ arcOp = 1;
308
+ eye = LAUGH;
309
+ sparkleAmount = p * .72;
310
+ } else if (t < a4) {
311
+ phase = '④ happy hold';
312
+ const p = (t - a3) / T_hold;
313
+ layerLevels = [1, 1, 1, 1];
314
+ haloOpacity = .04;
315
+ ringScale = 1.026 + .006 * Math.sin(2 * Math.PI * p);
316
+ runnerProgress = RING_COUNT + 1;
317
+ runnerOpacity = 0;
318
+ cloudSx = cloudSy = 1.025;
319
+ capsuleOp = 0;
320
+ arcOp = 1;
321
+ eye = LAUGH;
322
+ sparkleAmount = .75 + p * .45;
323
+ } else if (t < a5) {
324
+ phase = '⑤ soft fade';
325
+ const p = (t - a4) / T_fade;
326
+ const keep = 1 - easeInCubic(p);
327
+ layerLevels = [1, 1, 1, 1].map(() => .12 + .88 * keep);
328
+ haloOpacity = .04 * keep;
329
+ ringScale = 1.006 + .02 * keep;
330
+ runnerProgress = RING_COUNT + 1;
331
+ runnerOpacity = 0;
332
+ cloudSx = cloudSy = 1 + .025 * keep;
333
+ capsuleOp = 0;
334
+ arcOp = 1;
335
+ eye = {
336
+ h: lerp(LAUGH.h, SMILE.h, easeInOutCubic(p)),
337
+ w: lerp(LAUGH.w, SMILE.w, easeInOutCubic(p)),
338
+ };
339
+ sparkleAmount = 1.2;
340
+ } else if (t < a6) {
341
+ phase = '⑥ smile return';
342
+ const p = (t - a5) / T_back;
343
+ const out = 1 - easeOutCubic(p);
344
+ layerLevels = [1, 1, 1, 1].map(() => .12 * out);
345
+ haloOpacity = .02 * out;
346
+ ringScale = 1 + .02 * out;
347
+ runnerProgress = RING_COUNT + 1;
348
+ runnerOpacity = 0;
349
+ capsuleOp = easeInOutCubic(p);
350
+ arcOp = 1 - easeInOutCubic(p);
351
+ eye = SMILE;
352
+ } else {
353
+ phase = 'idle baseline';
354
+ }
355
+
356
+ setCenteredTransform(cloudWrap, cloudSx, cloudSy, cloudRot);
357
+ setRing(layerLevels, haloOpacity, ringScale, runnerProgress, runnerOpacity);
358
+ setSparkles(sparkleAmount);
359
+ capsule.setAttribute('opacity', capsuleOp.toFixed(3));
360
+ arcEye.setAttribute('opacity', arcOp.toFixed(3));
361
+ setArc(eye);
362
+ phaseTag.textContent = phase;
363
+ timelineFill.style.width = `${clamp((t / TOTAL) * 100, 0, 100).toFixed(1)}%`;
364
+ }
365
+ function loop(now) {
366
+ if (!prev) prev = now;
367
+ const dt = (now - prev) / 1000;
368
+ prev = now;
369
+ if (!paused) elapsed += dt;
370
+ const cycle = TOTAL + GAP;
371
+ const tt = elapsed % cycle;
372
+ render(tt > TOTAL ? 0 : tt);
373
+ requestAnimationFrame(loop);
374
+ }
375
+
376
+ setArc(SMILE);
377
+ setSparkles(0);
378
+ requestAnimationFrame(loop);
379
+ ]]></script>
380
+ </svg>