@5even7/dlc-ui 0.2.18 → 0.2.20

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 (87) hide show
  1. package/CHANGELOG.md +158 -144
  2. package/EXTENDING.md +114 -0
  3. package/LICENSE +21 -21
  4. package/README.md +389 -338
  5. package/THIRD_PARTY_NOTICES.md +221 -0
  6. package/dist/avatar-creator/styles/humation.mjs +26 -0
  7. package/dist/avatar-creator/styles.mjs +76 -0
  8. package/dist/avatar-creator.cjs +7831 -0
  9. package/dist/avatar-creator.mjs +74 -0
  10. package/dist/capsule.cjs +185 -66
  11. package/dist/capsule.mjs +364 -1340
  12. package/dist/chunks/avatar-creator-DiAmhpRa.mjs +687 -0
  13. package/dist/chunks/color-DnmNceaf.mjs +350 -0
  14. package/dist/chunks/controls-B5_ctvvA.mjs +160 -0
  15. package/dist/chunks/copy-7J0XIj_0.mjs +13 -0
  16. package/dist/chunks/cosmic-fallback-v8G5_ibh.mjs +408 -0
  17. package/dist/chunks/emitter-CxLYMSbw.mjs +38 -0
  18. package/dist/chunks/emo-Dvahy5Qr.mjs +1140 -0
  19. package/dist/chunks/hash-BiO02UNb.mjs +38 -0
  20. package/dist/chunks/humation-B9OPUGL7.mjs +2987 -0
  21. package/dist/chunks/identicon-BUdMd-yf.mjs +3063 -0
  22. package/dist/chunks/index-BchW1tWE.mjs +478 -0
  23. package/dist/chunks/index-BtH8Lbra.mjs +296 -0
  24. package/dist/chunks/index-C02dvGLD.mjs +263 -0
  25. package/dist/chunks/index-CFybYBA1.mjs +278 -0
  26. package/dist/chunks/index-DgI872-7.mjs +241 -0
  27. package/dist/chunks/index-_sf_14Zu.mjs +455 -0
  28. package/dist/chunks/index-w5Pzdwhv.mjs +305 -0
  29. package/dist/chunks/motion-a8_f8_Ui.mjs +177 -0
  30. package/dist/chunks/number-BqWLX0iQ.mjs +231 -0
  31. package/dist/chunks/progress-KweS4Rx0.mjs +1836 -0
  32. package/dist/chunks/size-Bztk2ryJ.mjs +22 -0
  33. package/dist/chunks/wrapper-DXhy1E7Z.mjs +514 -0
  34. package/dist/color.cjs +186 -67
  35. package/dist/color.mjs +341 -1280
  36. package/dist/emo/miao/angry.mjs +4 -0
  37. package/dist/emo/miao/asleep.mjs +4 -0
  38. package/dist/emo/miao/badminton.mjs +4 -0
  39. package/dist/emo/miao/confident.mjs +4 -0
  40. package/dist/emo/miao/cry.mjs +4 -0
  41. package/dist/emo/miao/investigate.mjs +4 -0
  42. package/dist/emo/miao/laugh.mjs +4 -0
  43. package/dist/emo/miao/leisure.mjs +4 -0
  44. package/dist/emo/miao/mock.mjs +4 -0
  45. package/dist/emo/miao/music.mjs +4 -0
  46. package/dist/emo/miao/mute.mjs +4 -0
  47. package/dist/emo/miao/panic.mjs +4 -0
  48. package/dist/emo/miao/ponder.mjs +4 -0
  49. package/dist/emo/miao/question.mjs +4 -0
  50. package/dist/emo/miao/sad.mjs +4 -0
  51. package/dist/emo/miao/shocked.mjs +4 -0
  52. package/dist/emo/miao/shy.mjs +4 -0
  53. package/dist/emo/miao/sigh.mjs +4 -0
  54. package/dist/emo/miao/smile.mjs +4 -0
  55. package/dist/emo/miao/snigger.mjs +4 -0
  56. package/dist/emo/miao/static.mjs +4 -0
  57. package/dist/emo/miao/yawn.mjs +4 -0
  58. package/dist/emo/miao/yummy.mjs +4 -0
  59. package/dist/emo.cjs +27161 -25964
  60. package/dist/emo.mjs +8 -1421
  61. package/dist/index.cjs +32729 -24466
  62. package/dist/index.mjs +16 -4757
  63. package/dist/index.umd.js +33115 -24852
  64. package/dist/index.umd.min.js +3 -1
  65. package/dist/progress.cjs +195 -76
  66. package/dist/progress.mjs +7 -2448
  67. package/dist/vue2.cjs +33282 -25002
  68. package/dist/vue2.mjs +63 -5131
  69. package/dist/vue3.cjs +33282 -25002
  70. package/dist/vue3.mjs +53 -5122
  71. package/package.json +161 -136
  72. package/styles/avatar-creator.css +38 -0
  73. package/styles/base.css +32 -32
  74. package/styles/color.css +18 -18
  75. package/styles/emo.css +110 -89
  76. package/styles/progress.css +96 -96
  77. package/styles/theme.css +1 -0
  78. package/types/avatar-creator-styles.d.ts +10 -0
  79. package/types/avatar-creator.d.ts +143 -0
  80. package/types/capsule.d.ts +15 -15
  81. package/types/color.d.ts +15 -15
  82. package/types/emo-miao.d.ts +9 -0
  83. package/types/emo.d.ts +38 -37
  84. package/types/index.d.ts +593 -554
  85. package/types/progress.d.ts +16 -16
  86. package/types/vue2.d.ts +11 -10
  87. package/types/vue3.d.ts +169 -146
@@ -0,0 +1,1140 @@
1
+ import { c as createEmitter } from './emitter-CxLYMSbw.mjs';
2
+ import { p as parseSize } from './size-Bztk2ryJ.mjs';
3
+ import { w as wakeScheduler, a as createVisibilityGuard, s as subscribeScheduler, b as createReducedMotionPreference } from './motion-a8_f8_Ui.mjs';
4
+ import smileData from '../emo/miao/smile.mjs';
5
+ import { n as normalizeColor, h as hexToRgb01 } from './color-DnmNceaf.mjs';
6
+
7
+ // Generated by scripts/generate-emo-assets.mjs. Do not edit by hand.
8
+ const MIAO_ANIMATION_META = {"angry":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"asleep":{"w":720,"h":720,"ip":0,"op":2200,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"sleepBreath":{"paint":"paint.sleepBreath","default":"#ffffff"}}}},"badminton":{"w":720,"h":720,"ip":0,"op":200,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"shuttlecock":{"paint":"paint.shuttlecock","default":"#ffffff"}}}},"confident":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"cry":{"w":720,"h":720,"ip":0,"op":320,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"investigate":{"w":720,"h":720,"ip":0,"op":400,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"laugh":{"w":720,"h":720,"ip":0,"op":200,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"leisure":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"meditationFigure":{"paint":"paint.meditationFigure","default":"#000000"},"meditationBubble":{"paint":"paint.meditationBubble","default":"#ffffff"}}}},"mock":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"music":{"w":720,"h":720,"ip":0,"op":200,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"musicNotes":{"paint":"paint.musicNotes","default":"#ffffff"}}}},"mute":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"mouthFill":{"paint":"paint.mouthFill","default":"#000000"}}}},"panic":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"ponder":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"leftEyeOverlay":{"paint":"paint.leftEyeOverlay","default":"#e6f6ff"}}}},"question":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"questionMark":{"paint":"paint.questionMark","default":"#000000"}}}},"sad":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"shocked":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"shy":{"w":720,"h":720,"ip":0,"op":1000,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"leftBlush":{"paint":"paint.leftBlush","default":"#ffa2a2"},"rightBlush":{"paint":"paint.rightBlush","default":"#ffa2a2"}}}},"sigh":{"w":720,"h":720,"ip":0,"op":400,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"sighBreath":{"paint":"paint.sighBreath","default":"#ffffff"}}}},"smile":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"snigger":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"static":{"w":720,"h":720,"ip":0,"op":150,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"}}}},"yawn":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"}}}},"yummy":{"w":720,"h":720,"ip":0,"op":300,"fr":100,"miao":{"schema":2,"partColors":{"leftEye":{"paint":"paint.leftEye","default":"#ffffff"},"rightEye":{"paint":"paint.rightEye","default":"#ffffff"},"mouth":{"paint":"paint.mouth","default":"#ffffff"},"particles":{"paint":"paint.particles","default":"#ffcc00"}}}}};
9
+
10
+ // Generated by scripts/generate-emo-assets.mjs. Do not edit by hand.
11
+ // smile 是默认表情:静态打进主包,其余动画按需动态加载。
12
+
13
+ const MIAO_ANIMATION_LOADERS = {
14
+ "angry": () => import('../emo/miao/angry.mjs'),
15
+ "asleep": () => import('../emo/miao/asleep.mjs'),
16
+ "badminton": () => import('../emo/miao/badminton.mjs'),
17
+ "confident": () => import('../emo/miao/confident.mjs'),
18
+ "cry": () => import('../emo/miao/cry.mjs'),
19
+ "investigate": () => import('../emo/miao/investigate.mjs'),
20
+ "laugh": () => import('../emo/miao/laugh.mjs'),
21
+ "leisure": () => import('../emo/miao/leisure.mjs'),
22
+ "mock": () => import('../emo/miao/mock.mjs'),
23
+ "music": () => import('../emo/miao/music.mjs'),
24
+ "mute": () => import('../emo/miao/mute.mjs'),
25
+ "panic": () => import('../emo/miao/panic.mjs'),
26
+ "ponder": () => import('../emo/miao/ponder.mjs'),
27
+ "question": () => import('../emo/miao/question.mjs'),
28
+ "sad": () => import('../emo/miao/sad.mjs'),
29
+ "shocked": () => import('../emo/miao/shocked.mjs'),
30
+ "shy": () => import('../emo/miao/shy.mjs'),
31
+ "sigh": () => import('../emo/miao/sigh.mjs'),
32
+ "smile": () => import('../emo/miao/smile.mjs'),
33
+ "snigger": () => import('../emo/miao/snigger.mjs'),
34
+ "static": () => import('../emo/miao/static.mjs'),
35
+ "yawn": () => import('../emo/miao/yawn.mjs'),
36
+ "yummy": () => import('../emo/miao/yummy.mjs')
37
+ };
38
+
39
+ const cache = {};
40
+
41
+ cache["smile"] = Promise.resolve(smileData);
42
+
43
+ /**
44
+ * Load one miao animation's Lottie data (cached on demand). Concurrent
45
+ * calls for the same name share a single import; different names stay
46
+ * independent. Rejects for unknown names.
47
+ */
48
+ function loadMiaoAnimation(name) {
49
+ const loader = MIAO_ANIMATION_LOADERS[name];
50
+ if (!loader) return Promise.reject(new Error(`Unknown miao animation: ${name}`));
51
+ if (!cache[name]) cache[name] = loader().then((module) => module.default);
52
+ return cache[name];
53
+ }
54
+
55
+ /**
56
+ * Grok state presentation metadata.
57
+ *
58
+ * Grok's `name` describes a dynamic state module (expression pool + cadence +
59
+ * blink + body motion), not a single still face. These fields only organize
60
+ * how states are displayed in Docs / Playground; they never affect the
61
+ * renderer animation algorithm or the public API (all 13 names stay valid).
62
+ *
63
+ * `source: 'upstream'` marks states ported from zhulin025/LaoA-GrokBot;
64
+ * `source: 'dlc'` is reserved for future DLC-original states.
65
+ */
66
+
67
+ /** Upstream state groups (display-only; see file header). */
68
+ const GROK_GROUPS = [
69
+ { key: 'lifecycle', label: '生命周期', states: ['sleeping', 'idle', 'listening', 'thinking', 'searching', 'working'] },
70
+ { key: 'emotion', label: '情绪反应', states: ['surprised', 'angry', 'happy', 'confused', 'sad'] },
71
+ { key: 'product', label: '产品流程', states: ['loading', 'receiving'] }
72
+ ];
73
+
74
+ /** Chinese display labels for the 13 grok states. */
75
+ const GROK_STATE_LABELS = {
76
+ sleeping: '睡觉', idle: '平静', listening: '聆听', thinking: '思考', searching: '寻找',
77
+ working: '专注', surprised: '惊讶', angry: '生气', happy: '开心', confused: '疑惑',
78
+ sad: '难过', loading: '缓冲中', receiving: '接收'
79
+ };
80
+
81
+ const GROK_CATEGORIES = [
82
+ { key: 'emotion', label: '情绪' },
83
+ { key: 'agent', label: 'Agent 状态' },
84
+ { key: 'lifecycle', label: '生命周期' }
85
+ ];
86
+
87
+ /** All 13 public grok state names, in upstream group order. */
88
+ const GROK_NAMES = GROK_GROUPS.flatMap((group) => group.states);
89
+
90
+ const GROK_STATE_META = {
91
+ // emotion
92
+ idle: { category: 'emotion', description: '中性平和的眼神,自然眨眼,不抢戏的默认姿态', source: 'upstream' },
93
+ surprised: { category: 'emotion', description: '眼睛瞪得又大又圆,猝不及防', source: 'upstream' },
94
+ angry: { category: 'emotion', description: '眉头下压、眼神凌厉,一脸不爽', source: 'upstream' },
95
+ happy: { category: 'emotion', description: '眼睛弯成月牙,眉开眼笑', source: 'upstream' },
96
+ confused: { category: 'emotion', description: '一眯眼一瞪眼、眼神歪斜,满脸问号', source: 'upstream' },
97
+ sad: { category: 'emotion', description: '双眼低垂闭合,垂头丧气', source: 'upstream' },
98
+ // agent
99
+ listening: { category: 'agent', description: '温和注视、微微凝神,认真听对方说话', source: 'upstream' },
100
+ thinking: { category: 'agent', description: '眼神左顾右盼、时眯时睁,像在琢磨问题', source: 'upstream' },
101
+ searching: { category: 'agent', description: '目光快速扫动、不时瞪圆,像在搜寻目标', source: 'upstream' },
102
+ working: { category: 'agent', description: '时绷紧眼神、时睁大,全神贯注在做事', source: 'upstream' },
103
+ loading: { category: 'agent', description: '平静眼神配缓慢起伏的节奏,等待加载完成', source: 'upstream' },
104
+ receiving: { category: 'agent', description: '平和注视、安静等待,像在接收新内容', source: 'upstream' },
105
+ // lifecycle
106
+ sleeping: { category: 'lifecycle', description: '双眼紧闭、呼吸般一起一伏,睡得正香', source: 'upstream' }
107
+ };
108
+
109
+ for (const name of GROK_NAMES) {
110
+ GROK_STATE_META[name].label = GROK_STATE_LABELS[name] || name;
111
+ }
112
+
113
+ /**
114
+ * Resolve the display name list for a docs tab: category key | 'all'.
115
+ * Unknown tabs fall back to the full list.
116
+ */
117
+ function getGrokNamesFor(tab) {
118
+ if (tab === 'all') return [...GROK_NAMES];
119
+ if (GROK_CATEGORIES.some((category) => category.key === tab)) {
120
+ return GROK_NAMES.filter((name) => GROK_STATE_META[name].category === tab);
121
+ }
122
+ return [...GROK_NAMES];
123
+ }
124
+
125
+ /** Get a single state's metadata (label included). Throws on unknown names. */
126
+ function getGrokStateMeta(name) {
127
+ const normalized = String(name || '').trim().toLowerCase();
128
+ const meta = GROK_STATE_META[normalized];
129
+ if (!meta) throw new Error(`Unknown grok state: ${normalized}`);
130
+ return { ...meta };
131
+ }
132
+
133
+ const MIAO_META = [
134
+ ['angry', '生气', 'negative'],
135
+ ['cry', '哭泣', 'negative'],
136
+ ['sad', '难过', 'negative'],
137
+ ['sigh', '叹气', 'negative'],
138
+ ['investigate', '观察', 'thinking'],
139
+ ['mute', '安静', 'thinking'],
140
+ ['ponder', '沉思', 'thinking'],
141
+ ['question', '疑问', 'thinking'],
142
+ ['static', '平静', 'thinking'],
143
+ ['asleep', '睡着', 'physical'],
144
+ ['yawn', '哈欠', 'physical'],
145
+ ['badminton', '羽毛球', 'positive'],
146
+ ['confident', '自信', 'positive'],
147
+ ['laugh', '大笑', 'positive'],
148
+ ['leisure', '悠闲', 'positive'],
149
+ ['music', '音乐', 'positive'],
150
+ ['smile', '微笑', 'positive'],
151
+ ['yummy', '好吃', 'positive'],
152
+ ['mock', '调侃', 'social'],
153
+ ['shy', '害羞', 'social'],
154
+ ['snigger', '偷笑', 'social'],
155
+ ['panic', '慌张', 'reaction'],
156
+ ['shocked', '震惊', 'reaction']
157
+ ];
158
+
159
+ const EMO_CATEGORIES = {
160
+ negative: '负面情绪',
161
+ thinking: '中性与思考',
162
+ physical: '身体与特殊状态',
163
+ positive: '正面情绪',
164
+ social: '社交情境',
165
+ reaction: '惊讶与反应',
166
+ lifecycle: '生命周期',
167
+ emotion: '情绪反应',
168
+ agent: '代理形态',
169
+ product: '产品流程'
170
+ };
171
+
172
+ const GROK_META = GROK_NAMES.map((name) => ({
173
+ name,
174
+ label: GROK_STATE_META[name].label,
175
+ category: GROK_STATE_META[name].category
176
+ }));
177
+
178
+ const EMO_PRESETS = [
179
+ ...MIAO_META.map(([name, label, category]) => {
180
+ const meta = MIAO_ANIMATION_META[name];
181
+ return {
182
+ type: 'miao',
183
+ name,
184
+ label,
185
+ category,
186
+ width: meta.w,
187
+ height: meta.h,
188
+ engine: 'lottie',
189
+ frames: meta.op - meta.ip,
190
+ fps: meta.fr
191
+ };
192
+ }),
193
+ ...GROK_META.map(({ name, label, category }) => ({
194
+ type: 'grok',
195
+ name,
196
+ label,
197
+ category,
198
+ width: 229,
199
+ height: 229,
200
+ engine: 'grok'
201
+ }))
202
+ ];
203
+
204
+ const MIAO_PART_KEYS = Object.values(MIAO_ANIMATION_META)
205
+ .reduce((acc, meta) => {
206
+ const metadata = meta.miao && meta.miao.partColors;
207
+ if (metadata) for (const key of Object.keys(metadata)) acc.add(key);
208
+ return acc;
209
+ }, new Set());
210
+
211
+ const GROK_SHAPE_KEYS = ['blob', 'pebble', 'squircle', 'capsule', 'triangle', 'hex', 'cloud', 'drop'];
212
+
213
+ const EMO_TYPES = [
214
+ {
215
+ type: 'miao',
216
+ label: '喵',
217
+ defaultName: 'smile',
218
+ engine: 'lottie',
219
+ names: EMO_PRESETS.filter((item) => item.type === 'miao').map((item) => item.name),
220
+ partColors: [...MIAO_PART_KEYS].sort()
221
+ },
222
+ {
223
+ type: 'grok',
224
+ label: 'Grok',
225
+ defaultName: 'idle',
226
+ engine: 'grok',
227
+ names: GROK_NAMES,
228
+ partColors: ['body', 'eyes'],
229
+ shapes: GROK_SHAPE_KEYS
230
+ }
231
+ ];
232
+
233
+ function getEmoType(type) {
234
+ const normalizedType = String(type || '').trim().toLowerCase();
235
+ const definition = EMO_TYPES.find((item) => item.type === normalizedType);
236
+ if (!definition) throw new Error(`Unknown emo type: ${normalizedType}`);
237
+ return definition;
238
+ }
239
+
240
+ function getEmoPreset(type = 'miao', name = 'smile') {
241
+ const normalizedType = String(type || '').trim().toLowerCase();
242
+ const normalizedName = String(name || '').trim().toLowerCase();
243
+ const preset = EMO_PRESETS.find((item) => item.type === normalizedType && item.name === normalizedName);
244
+ if (!preset) throw new Error(`Unknown emo: ${normalizedType}/${normalizedName}`);
245
+ return preset;
246
+ }
247
+
248
+ /**
249
+ * Load the full Lottie data for a miao animation (cached, loads on demand).
250
+ * Rejects for unknown presets or non-miao types. Returns the shared cached
251
+ * promise directly, so concurrent calls for the same animation are one load.
252
+ */
253
+ function getEmoAnimation(type = 'miao', name = 'smile') {
254
+ try {
255
+ const preset = getEmoPreset(type, name);
256
+ if (preset.type !== 'miao') return Promise.reject(new Error(`Unsupported emo type: ${preset.type}`));
257
+ return loadMiaoAnimation(preset.name);
258
+ } catch (error) {
259
+ return Promise.reject(error);
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Synchronous lightweight metadata (w/h/frames/fps/miao partColors) for a
265
+ * miao animation — safe to call from computed properties before data loads.
266
+ */
267
+ function getEmoAnimationMeta(type = 'miao', name = 'smile') {
268
+ const preset = getEmoPreset(type, name);
269
+ if (preset.type !== 'miao') throw new Error(`Unsupported emo type: ${preset.type}`);
270
+ return MIAO_ANIMATION_META[preset.name];
271
+ }
272
+
273
+ /**
274
+ * Miao renderer: Lottie JSON + lottie-web. Extracted from the former emo.js
275
+ * so the emo facade stays engine-agnostic. Miao-only concerns live here:
276
+ * renderer (svg/canvas), direction, segment, paint.* partColors, lottie events.
277
+ */
278
+
279
+
280
+ const defaultPlayerPromises = {};
281
+
282
+ const POSTER_HTML = '<div class="dlc-emo-poster" aria-hidden="true"></div>';
283
+
284
+ function loadDefaultPlayer(renderer) {
285
+ const key = renderer === 'canvas' ? 'canvas' : 'svg';
286
+ if (!defaultPlayerPromises[key]) {
287
+ const loader = key === 'canvas'
288
+ ? import('lottie-web/build/player/lottie_light_canvas.js')
289
+ : import('lottie-web/build/player/lottie_light.js');
290
+ defaultPlayerPromises[key] = loader.then((module) => module.default || module);
291
+ }
292
+ return defaultPlayerPromises[key];
293
+ }
294
+
295
+ function cloneAnimationData(data) {
296
+ return JSON.parse(JSON.stringify(data));
297
+ }
298
+
299
+ function normalizeSegment(value, preset) {
300
+ if (!Array.isArray(value) || value.length !== 2) return null;
301
+ const start = Number(value[0]);
302
+ const end = Number(value[1]);
303
+ if (!Number.isFinite(start) || !Number.isFinite(end) || start === end) return null;
304
+ const min = 0;
305
+ const max = Math.max(1, preset.frames);
306
+ return [Math.max(min, Math.min(max, start)), Math.max(min, Math.min(max, end))].sort((a, b) => a - b);
307
+ }
308
+
309
+ /**
310
+ * Build a map of `paint.*` layer names → replacement rgb(0..1) tuples from the
311
+ * partColors option and the animation's embedded `miao.partColors` metadata.
312
+ * Keys not supported by the current animation are ignored.
313
+ */
314
+ function buildPaintReplacements(animationData, partColors) {
315
+ const replacements = {};
316
+ const metadata = animationData && animationData.miao && animationData.miao.partColors;
317
+ if (!metadata || !partColors || typeof partColors !== 'object') return replacements;
318
+ for (const key of Object.keys(partColors)) {
319
+ const value = partColors[key];
320
+ if (value == null || value === '') continue;
321
+ const entry = metadata[key];
322
+ if (!entry || typeof entry.paint !== 'string' || !entry.paint) continue;
323
+ const hex = normalizeColor(value);
324
+ if (!hex) continue;
325
+ replacements[entry.paint] = hexToRgb01(hex);
326
+ }
327
+ return replacements;
328
+ }
329
+
330
+ function replacePaintProperty(property, rgb) {
331
+ if (!property || !Array.isArray(property.k)) return;
332
+ if (typeof property.k[0] === 'number') {
333
+ property.k = [...rgb, ...property.k.slice(3)];
334
+ return;
335
+ }
336
+ for (const keyframe of property.k) {
337
+ for (const key of ['s', 'e']) {
338
+ if (!Array.isArray(keyframe[key])) continue;
339
+ keyframe[key] = [...rgb, ...keyframe[key].slice(3)];
340
+ }
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Recursively replace every fill/stroke named `paint.<part>` (top-level layers
346
+ * and precomp assets alike). Nodes without a matching paint name are untouched.
347
+ */
348
+ function applyPartColors(node, replacements) {
349
+ if (!node || typeof node !== 'object') return;
350
+ if ((node.ty === 'fl' || node.ty === 'st') && node.nm && node.c && replacements[node.nm]) {
351
+ replacePaintProperty(node.c, replacements[node.nm]);
352
+ }
353
+ for (const key of Object.keys(node)) {
354
+ const value = node[key];
355
+ if (Array.isArray(value)) value.forEach((item) => applyPartColors(item, replacements));
356
+ else if (value && typeof value === 'object') applyPartColors(value, replacements);
357
+ }
358
+ }
359
+
360
+ /**
361
+ * @param {object} env
362
+ * @param {HTMLElement} env.stage lottie container
363
+ * @param {object} env.s live facade state (preset/speed/loop/autoplay/...)
364
+ * @param {object} env.emitter event bus
365
+ */
366
+ function createMiaoRenderer({ stage, s, emitter }) {
367
+ let animation = null;
368
+ let disposed = false;
369
+
370
+ const removeAnimationEvents = () => {
371
+ if (!animation || !animation.__dlcHandlers) return;
372
+ for (const [event, handler] of animation.__dlcHandlers) animation.removeEventListener(event, handler);
373
+ animation.__dlcHandlers = null;
374
+ };
375
+
376
+ const destroy = () => {
377
+ if (!animation) return;
378
+ removeAnimationEvents();
379
+ animation.destroy();
380
+ animation = null;
381
+ };
382
+
383
+ const attachAnimation = (player, animationData) => {
384
+ if (disposed) return;
385
+ if (!player || typeof player.loadAnimation !== 'function') {
386
+ emitter.emit('error', { message: 'createEmo: lottie-web player is unavailable' });
387
+ return;
388
+ }
389
+ try {
390
+ stage.innerHTML = ''; // 去掉加载占位,交给 lottie 挂载真实画面
391
+ animation = player.loadAnimation({
392
+ container: stage,
393
+ renderer: s.renderer,
394
+ loop: s.loop,
395
+ autoplay: false,
396
+ name: s.instanceName || `dlc-emo-${s.preset.type}-${s.preset.name}`,
397
+ animationData,
398
+ rendererSettings: {
399
+ preserveAspectRatio: s.fit === 'cover' ? 'xMidYMid slice' : s.fit === 'fill' ? 'none' : 'xMidYMid meet',
400
+ progressiveLoad: false,
401
+ runExpressions: false,
402
+ title: s.label || `${s.preset.label}表情动画`,
403
+ description: `${s.preset.type}/${s.preset.name}`
404
+ }
405
+ });
406
+ const handlers = [
407
+ ['DOMLoaded', () => {
408
+ if (disposed) return;
409
+ applyPlayback();
410
+ emitter.emit('ready', { preset: { ...s.preset }, duration: animation.getDuration(false), frames: s.preset.frames });
411
+ }],
412
+ ['complete', () => emitter.emit('complete', { preset: { ...s.preset } })],
413
+ ['loopComplete', () => emitter.emit('loopComplete', { preset: { ...s.preset } })],
414
+ ['segmentStart', () => emitter.emit('segmentStart', { segment: s.segment ? [...s.segment] : null })],
415
+ ['data_failed', () => emitter.emit('error', { message: `Failed to load emo: ${s.preset.type}/${s.preset.name}` })]
416
+ ];
417
+ animation.__dlcHandlers = handlers;
418
+ handlers.forEach(([event, handler]) => animation.addEventListener(event, handler));
419
+ } catch (error) {
420
+ emitter.emit('error', { message: String(error && error.message ? error.message : error) });
421
+ }
422
+ };
423
+
424
+ const applyPlayback = () => {
425
+ if (!animation) return;
426
+ animation.setSpeed(s.speed);
427
+ animation.setDirection(s.direction);
428
+ if (s.segment) {
429
+ animation.playSegments(s.segment, true);
430
+ if (s.direction < 0) animation.goToAndStop(s.segment[1], true);
431
+ else animation.goToAndStop(s.segment[0], true);
432
+ } else if (s.direction < 0) {
433
+ animation.goToAndStop(Math.max(0, s.preset.frames - 1), true);
434
+ }
435
+ if (s.paused || s.reducedMotion || !s.autoplay) animation.pause();
436
+ else animation.play();
437
+ };
438
+
439
+ return {
440
+ get animation() { return animation; },
441
+ /**
442
+ * Load the animation data (cached on demand) and the player in parallel.
443
+ * Never rejects — failures are reported through the emitter.
444
+ */
445
+ async mount() {
446
+ // 先放一个占位(数据/播放器按需加载期间避免白屏),到位后替换
447
+ stage.innerHTML = POSTER_HTML;
448
+ const animationDataPromise = s.animationData
449
+ ? Promise.resolve(cloneAnimationData(s.animationData)).then((cloned) => {
450
+ applyPartColors(cloned, buildPaintReplacements(cloned, s.partColors));
451
+ return cloned;
452
+ })
453
+ : loadMiaoAnimation(s.preset.name).then((data) => {
454
+ const cloned = cloneAnimationData(data);
455
+ applyPartColors(cloned, buildPaintReplacements(cloned, s.partColors));
456
+ return cloned;
457
+ });
458
+ try {
459
+ const [animationData, player] = await Promise.all([
460
+ animationDataPromise,
461
+ s.player ? Promise.resolve(s.player) : loadDefaultPlayer(s.renderer)
462
+ ]);
463
+ attachAnimation(player, animationData);
464
+ } catch (error) {
465
+ if (disposed) return;
466
+ emitter.emit('error', { message: String(error && error.message ? error.message : error) });
467
+ }
468
+ },
469
+ play() { if (animation && !s.reducedMotion) animation.play(); },
470
+ pause() { if (animation) animation.pause(); },
471
+ stop() { if (animation) animation.stop(); },
472
+ setPaused(value) { return value ? this.pause() : this.play(); },
473
+ setSpeed(value) { if (animation) animation.setSpeed(value); },
474
+ setDirection(value) {
475
+ if (!animation) return;
476
+ animation.setDirection(value);
477
+ if (value < 0 && animation.currentFrame <= 0) {
478
+ animation.goToAndStop(s.segment ? s.segment[1] : s.preset.frames - 1, true);
479
+ }
480
+ },
481
+ setSegment(value) { applyPlayback(); },
482
+ setShape() {},
483
+ setInteractive() {},
484
+ dispose() {
485
+ if (disposed) return;
486
+ disposed = true;
487
+ destroy();
488
+ stage.innerHTML = '';
489
+ }
490
+ };
491
+ }
492
+
493
+ // Generated from zhulin025/LaoA-GrokBot (https://github.com/zhulin025/LaoA-GrokBot), MIT License.
494
+ // See THIRD_PARTY_NOTICES.md. Do not edit by hand.
495
+ // 数据体积很小(约 39 KB / gzip 15 KB),静态打进 emo 主包,grok 同步渲染。
496
+ // State groups / labels live in ./meta.js so presets and docs stay synchronous.
497
+
498
+ const GROK_EXPRESSIONS = [
499
+ [[[130.36,45.98],[132.71,46.19],[134.98,46.81],[137.11,47.83],[138.97,49.28],[140.47,51.09],[141.68,53.12],[142.73,55.23],[143.76,57.36],[144.78,59.49],[145.79,61.62],[146.79,63.76],[147.76,65.91],[148.71,68.07],[149.63,70.25],[150.52,72.43],[151.37,74.63],[151.99,76.91],[152.1,79.26],[151.64,81.57],[150.59,83.68],[149.04,85.45],[147.1,86.78],[144.9,87.62],[142.56,87.93],[140.22,87.71],[137.98,86.99],[135.93,85.82],[134.17,84.24],[132.78,82.34],[131.69,80.25],[130.77,78.08],[129.87,75.89],[128.94,73.72],[128,71.56],[127.03,69.4],[126.05,67.26],[125.05,65.12],[124.03,62.99],[122.93,60.9],[121.87,58.79],[121.03,56.59],[120.72,54.26],[121.1,51.93],[122.15,49.83],[123.75,48.1],[125.76,46.89],[128.01,46.19]],
500
+ [[176.61,37.08],[178.72,37.59],[180.7,38.48],[182.52,39.65],[184.2,41.03],[185.71,42.59],[187.03,44.31],[188.2,46.14],[189.26,48.03],[190.27,49.96],[191.26,51.89],[192.23,53.84],[193.16,55.8],[194.05,57.78],[194.92,59.77],[195.74,61.78],[196.53,63.8],[197.27,65.84],[197.97,67.9],[198.47,70.01],[198.63,72.18],[198.4,74.33],[197.58,76.33],[195.95,77.72],[193.83,78.08],[191.71,77.65],[189.76,76.69],[188.03,75.38],[186.53,73.82],[185.28,72.05],[184.25,70.13],[183.4,68.14],[182.63,66.11],[181.87,64.07],[181.07,62.05],[180.25,60.04],[179.39,58.05],[178.49,56.07],[177.57,54.1],[176.61,52.15],[175.62,50.22],[174.59,48.31],[173.53,46.41],[172.54,44.48],[171.86,42.42],[171.76,40.26],[172.62,38.3],[174.45,37.19]]]
501
+ ,[[[86.14,124.79],[89.16,124.92],[92.06,125.76],[94.68,127.27],[96.86,129.36],[98.48,131.92],[99.51,134.76],[100.12,137.73],[100.56,140.72],[101.01,143.72],[101.52,146.71],[102.06,149.69],[102.62,152.67],[103.2,155.64],[103.81,158.61],[104.44,161.57],[105.11,164.52],[105.81,167.47],[106.49,170.42],[106.72,173.44],[106.01,176.37],[104.37,178.9],[102.03,180.81],[99.26,181.99],[96.27,182.46],[93.25,182.25],[90.34,181.43],[87.65,180.04],[85.32,178.11],[83.51,175.7],[82.37,172.9],[81.66,169.96],[80.98,167],[80.32,164.05],[79.69,161.08],[79.08,158.12],[78.5,155.14],[77.94,152.16],[77.4,149.18],[76.89,146.2],[76.4,143.21],[75.93,140.21],[75.56,137.21],[75.7,134.19],[76.6,131.3],[78.22,128.76],[80.47,126.74],[83.18,125.4]],
502
+ [[147.23,112.87],[150.24,113.13],[153.07,114.19],[155.53,115.94],[157.46,118.26],[158.73,121.01],[159.53,123.93],[160.21,126.88],[160.88,129.84],[161.52,132.8],[162.15,135.76],[162.74,138.73],[163.32,141.71],[163.87,144.69],[164.39,147.67],[164.9,150.66],[165.39,153.65],[165.8,156.65],[165.76,159.67],[164.98,162.59],[163.56,165.26],[161.61,167.58],[159.23,169.45],[156.52,170.77],[153.57,171.46],[150.55,171.4],[147.67,170.52],[145.19,168.79],[143.45,166.33],[142.57,163.44],[142.08,160.45],[141.61,157.46],[141.11,154.47],[140.59,151.48],[140.04,148.5],[139.47,145.53],[138.87,142.56],[138.25,139.59],[137.6,136.63],[136.94,133.68],[136.25,130.72],[135.59,127.77],[135.47,124.75],[136.07,121.78],[137.34,119.04],[139.19,116.65],[141.53,114.74],[144.26,113.44]]]
503
+ ,[[[104.84,104.08],[109.39,104.89],[113.63,106.73],[117.32,109.5],[120.25,113.08],[122.22,117.25],[123.15,121.77],[122.92,126.39],[121.86,130.89],[120.61,135.35],[119.37,139.81],[118.15,144.27],[116.94,148.74],[115.74,153.21],[114.56,157.69],[113.39,162.17],[112.24,166.65],[111.13,171.15],[110.04,175.65],[108.89,180.13],[106.98,184.33],[103.8,187.67],[99.75,189.87],[95.25,190.93],[90.63,190.93],[86.11,189.97],[81.86,188.16],[78.05,185.54],[74.89,182.18],[72.62,178.16],[71.54,173.67],[71.94,169.08],[73.01,164.57],[74.13,160.08],[75.26,155.59],[76.42,151.11],[77.59,146.63],[78.77,142.15],[79.97,137.68],[81.18,133.22],[82.41,128.75],[83.65,124.29],[84.87,119.83],[86.33,115.43],[88.67,111.46],[91.9,108.15],[95.83,105.72],[100.23,104.35]],
504
+ [[174.26,115.55],[178.59,116.54],[182.37,118.86],[185.31,122.2],[187.23,126.21],[188.12,130.57],[188.06,135.02],[187.52,139.44],[186.86,143.85],[186.11,148.25],[185.25,152.62],[184.3,156.98],[183.24,161.31],[182.07,165.61],[180.79,169.88],[179.39,174.12],[177.89,178.31],[176.27,182.47],[174.47,186.55],[172.17,190.35],[169.21,193.68],[165.73,196.46],[161.84,198.64],[157.66,200.16],[153.27,200.91],[148.83,200.69],[144.65,199.19],[141.47,196.14],[140.18,191.91],[140.82,187.53],[142.46,183.38],[144.16,179.26],[145.73,175.09],[147.18,170.87],[148.51,166.62],[149.73,162.33],[150.84,158.01],[151.84,153.67],[152.74,149.3],[153.54,144.91],[154.24,140.51],[154.85,136.1],[155.58,131.7],[156.93,127.46],[159.15,123.6],[162.12,120.29],[165.73,117.68],[169.84,116]]]
505
+ ,[[[44.72,103.35],[47.95,103.93],[51.04,105.05],[53.93,106.62],[56.58,108.57],[58.97,110.83],[61.09,113.35],[62.93,116.07],[64.5,118.97],[65.79,121.99],[66.8,125.13],[67.52,128.34],[67.94,131.6],[68.08,134.89],[67.9,138.17],[67.4,141.42],[66.56,144.6],[65.33,147.66],[63.71,150.52],[61.69,153.11],[59.3,155.36],[56.54,157.16],[53.51,158.42],[50.29,159.07],[47,159.09],[43.76,158.5],[40.67,157.39],[37.78,155.82],[35.13,153.87],[32.75,151.6],[30.63,149.09],[28.78,146.36],[27.21,143.47],[25.92,140.44],[24.92,137.31],[24.2,134.1],[23.77,130.84],[23.64,127.55],[23.81,124.27],[24.31,121.01],[25.16,117.84],[26.38,114.78],[28,111.92],[30.02,109.33],[32.42,107.08],[35.17,105.28],[38.21,104.02],[41.43,103.37]],
506
+ [[114.62,83.64],[118.31,83.88],[121.94,84.6],[125.44,85.77],[128.77,87.38],[131.86,89.4],[134.67,91.81],[137.13,94.56],[139.2,97.62],[140.85,100.93],[142.05,104.42],[142.79,108.05],[143.05,111.73],[142.83,115.42],[142.13,119.05],[140.95,122.55],[139.34,125.88],[137.3,128.96],[134.88,131.75],[132.11,134.2],[129.05,136.27],[125.75,137.93],[122.25,139.13],[118.63,139.86],[114.94,140.1],[111.25,139.86],[107.63,139.14],[104.12,137.97],[100.8,136.36],[97.7,134.34],[94.9,131.93],[92.44,129.18],[90.36,126.12],[88.72,122.81],[87.51,119.31],[86.78,115.69],[86.52,112.01],[86.74,108.32],[87.44,104.69],[88.61,101.18],[90.23,97.86],[92.27,94.78],[94.69,91.99],[97.45,89.54],[100.51,87.47],[103.82,85.81],[107.31,84.61],[110.94,83.88]]]
507
+ ,[[[90.44,99.25],[93.11,99.26],[95.74,99.79],[98.37,100.3],[101,100.82],[103.64,101.33],[106.27,101.85],[108.9,102.37],[111.53,102.89],[114.16,103.41],[116.79,103.94],[119.42,104.47],[122.06,105],[124.69,105.53],[127.32,106.06],[129.94,106.6],[132.57,107.14],[135.2,107.68],[137.65,108.73],[139.5,110.65],[140.44,113.14],[140.36,115.81],[139.35,118.28],[137.48,120.18],[135,121.14],[132.32,121.11],[129.7,120.56],[127.08,120],[124.45,119.46],[121.82,118.93],[119.19,118.4],[116.56,117.87],[113.93,117.35],[111.29,116.83],[108.66,116.32],[106.02,115.82],[103.39,115.31],[100.76,114.79],[98.12,114.28],[95.49,113.75],[92.86,113.22],[90.23,112.68],[87.77,111.66],[85.93,109.74],[85.01,107.24],[85.06,104.57],[86.07,102.1],[87.96,100.22]],
508
+ [[156.6,112.56],[158.91,112.66],[161.18,113.15],[163.45,113.64],[165.72,114.13],[167.99,114.62],[170.26,115.12],[172.53,115.62],[174.8,116.12],[177.07,116.62],[179.34,117.13],[181.6,117.64],[183.87,118.15],[186.14,118.67],[188.4,119.18],[190.67,119.7],[192.94,120.2],[195.12,120.96],[196.7,122.63],[197.45,124.82],[197.53,127.14],[197.07,129.41],[196.08,131.51],[194.49,133.18],[192.33,133.97],[190.04,133.68],[187.79,133.09],[185.52,132.57],[183.26,132.05],[180.99,131.54],[178.72,131.03],[176.45,130.53],[174.18,130.03],[171.91,129.54],[169.64,129.05],[167.37,128.56],[165.1,128.07],[162.83,127.58],[160.56,127.08],[158.29,126.57],[156.02,126.05],[153.9,125.14],[152.26,123.51],[151.32,121.4],[151.08,119.1],[151.53,116.82],[152.65,114.8],[154.41,113.31]]]
509
+ ,[[[79.94,130.44],[83.08,130.57],[86.11,131.41],[88.89,132.89],[91.27,134.94],[93.15,137.46],[94.39,140.35],[95.11,143.42],[95.65,146.52],[96.2,149.62],[96.78,152.72],[97.39,155.81],[98.04,158.89],[98.72,161.97],[99.43,165.04],[100.18,168.1],[100.97,171.15],[101.81,174.18],[102.64,177.22],[103.01,180.34],[102.35,183.4],[100.66,186.04],[98.19,187.98],[95.28,189.16],[92.17,189.6],[89.03,189.37],[85.99,188.56],[83.16,187.2],[80.63,185.33],[78.55,182.97],[77.05,180.21],[76.1,177.21],[75.28,174.17],[74.5,171.11],[73.74,168.06],[73.02,164.99],[72.33,161.92],[71.68,158.83],[71.06,155.75],[70.47,152.65],[69.91,149.55],[69.37,146.45],[68.97,143.32],[69.12,140.18],[70.04,137.18],[71.7,134.51],[74.03,132.41],[76.86,131.04]],
510
+ [[168.95,136.28],[171.31,136.97],[172.99,138.76],[173.66,141.13],[173.36,143.58],[172.24,145.79],[170.45,147.49],[168.22,148.58],[165.89,149.43],[163.57,150.31],[161.24,151.18],[158.9,152.02],[156.56,152.85],[154.21,153.65],[151.85,154.44],[149.48,155.2],[147.11,155.94],[144.73,156.65],[142.34,157.34],[139.95,158.01],[137.55,158.66],[135.14,159.27],[132.73,159.86],[130.31,160.43],[127.84,160.54],[125.53,159.69],[123.77,157.96],[122.89,155.66],[123.09,153.21],[124.36,151.09],[126.34,149.61],[128.69,148.83],[131.1,148.24],[133.51,147.62],[135.91,146.98],[138.31,146.32],[140.7,145.65],[143.08,144.95],[145.46,144.23],[147.83,143.49],[150.2,142.73],[152.56,141.95],[154.91,141.15],[157.25,140.32],[159.59,139.48],[161.92,138.61],[164.24,137.72],[166.54,136.78]]]
511
+ ,[[[119.79,105.35],[121.94,105.42],[124.03,105.87],[126,106.72],[127.77,107.93],[129.27,109.47],[130.45,111.26],[131.29,113.23],[131.73,115.33],[131.79,117.47],[131.53,119.6],[131.11,121.71],[130.66,123.81],[130.27,125.92],[129.88,128.03],[129.49,130.14],[129.07,132.25],[128.62,134.35],[127.96,136.39],[126.96,138.29],[125.62,139.96],[123.99,141.36],[122.13,142.43],[120.11,143.15],[118,143.5],[115.85,143.45],[113.75,143],[111.79,142.15],[110.03,140.93],[108.54,139.38],[107.36,137.59],[106.53,135.61],[106.1,133.51],[106.07,131.37],[106.35,129.24],[106.77,127.14],[107.22,125.04],[107.64,122.93],[108.05,120.82],[108.45,118.71],[108.84,116.6],[109.25,114.49],[109.86,112.44],[110.83,110.52],[112.16,108.84],[113.78,107.44],[115.65,106.38],[117.67,105.68]],
512
+ [[174.73,114.1],[176.71,114.59],[178.5,115.55],[180.04,116.88],[181.27,118.5],[182.17,120.33],[182.71,122.29],[182.9,124.32],[182.82,126.36],[182.56,128.38],[182.23,130.39],[181.89,132.4],[181.53,134.41],[181.16,136.41],[180.75,138.41],[180.3,140.4],[179.82,142.38],[179.18,144.31],[178.28,146.15],[177.14,147.83],[175.74,149.31],[174.11,150.53],[172.29,151.44],[170.32,151.97],[168.29,152.07],[166.29,151.69],[164.45,150.83],[162.87,149.54],[161.66,147.91],[160.83,146.06],[160.38,144.07],[160.29,142.04],[160.53,140.01],[160.98,138.02],[161.43,136.03],[161.84,134.04],[162.24,132.04],[162.62,130.03],[162.93,128.02],[163.24,126],[163.6,124],[164.11,122.03],[164.91,120.15],[165.99,118.43],[167.35,116.91],[168.94,115.64],[170.74,114.69],[172.7,114.15]]]
513
+ ,[[[105.72,72.58],[108.82,72.78],[111.75,73.82],[114.27,75.64],[116.39,77.92],[118.42,80.29],[120.45,82.66],[122.47,85.03],[124.48,87.41],[126.49,89.8],[128.48,92.2],[130.47,94.6],[132.45,97.01],[134.43,99.42],[136.4,101.83],[138.37,104.25],[140.3,106.7],[141.85,109.39],[142.65,112.4],[142.63,115.51],[141.8,118.5],[140.21,121.17],[137.95,123.31],[135.17,124.7],[132.11,125.26],[129.02,124.98],[126.12,123.86],[123.67,121.94],[121.61,119.6],[119.66,117.17],[117.69,114.75],[115.73,112.33],[113.75,109.92],[111.77,107.52],[109.77,105.12],[107.77,102.73],[105.76,100.34],[103.75,97.96],[101.72,95.59],[99.68,93.23],[97.63,90.89],[95.91,88.3],[94.95,85.34],[94.92,82.24],[95.84,79.27],[97.56,76.68],[99.9,74.63],[102.67,73.22]],
514
+ [[176.73,63.75],[179.52,64.43],[182.02,65.85],[184.15,67.78],[185.85,70.1],[187.08,72.7],[187.76,75.5],[187.76,78.37],[187.23,81.2],[186.58,84.01],[185.89,86.8],[185.16,89.59],[184.39,92.36],[183.59,95.13],[182.76,97.89],[181.88,100.64],[180.98,103.37],[180.02,106.09],[179.03,108.79],[177.99,111.48],[176.9,114.15],[175.5,116.66],[173.51,118.72],[171,120.11],[168.18,120.66],[165.34,120.29],[162.75,119.04],[160.62,117.12],[159.02,114.73],[158,112.04],[157.63,109.19],[157.98,106.34],[158.83,103.59],[159.86,100.9],[160.87,98.2],[161.85,95.49],[162.79,92.76],[163.7,90.03],[164.57,87.29],[165.41,84.53],[166.21,81.76],[166.98,78.99],[167.7,76.2],[168.38,73.4],[169,70.58],[169.79,67.82],[171.41,65.46],[173.88,64.03]]]
515
+ ,[[[64.12,83.43],[66.69,84.08],[68.9,85.53],[70.57,87.6],[71.56,90.05],[71.86,92.69],[71.53,95.32],[70.55,97.78],[69.06,99.99],[67.36,102.03],[65.64,104.06],[63.95,106.11],[62.28,108.18],[60.63,110.27],[59,112.38],[57.41,114.5],[55.84,116.65],[54.29,118.82],[52.78,121],[51.31,123.22],[49.86,125.45],[48.42,127.69],[46.67,129.68],[44.36,130.96],[41.73,131.22],[39.22,130.38],[37.16,128.72],[35.64,126.55],[34.65,124.08],[34.2,121.46],[34.29,118.81],[34.94,116.24],[36.12,113.86],[37.54,111.61],[39.04,109.41],[40.54,107.21],[42.06,105.03],[43.61,102.87],[45.18,100.73],[46.79,98.6],[48.41,96.5],[50.07,94.42],[51.74,92.35],[53.45,90.31],[55.17,88.28],[56.94,86.3],[59.04,84.67],[61.48,83.65]],
516
+ [[104.23,93.09],[106.97,93.77],[109.4,95.24],[111.32,97.31],[112.59,99.85],[113.4,102.57],[114.13,105.32],[114.87,108.06],[115.62,110.8],[116.37,113.54],[117.14,116.28],[117.9,119.02],[118.67,121.75],[119.45,124.49],[120.23,127.22],[121.03,129.95],[121.83,132.68],[122.6,135.41],[122.98,138.22],[122.57,141.02],[121.34,143.57],[119.44,145.67],[117.05,147.19],[114.34,148.04],[111.51,148.14],[108.77,147.45],[106.33,146.01],[104.38,143.96],[103.07,141.44],[102.21,138.73],[101.43,136],[100.65,133.27],[99.87,130.53],[99.09,127.8],[98.32,125.06],[97.55,122.33],[96.79,119.59],[96.04,116.85],[95.28,114.11],[94.53,111.37],[93.79,108.62],[93.05,105.88],[92.73,103.07],[93.18,100.27],[94.42,97.72],[96.32,95.62],[98.7,94.08],[101.4,93.21]]]
517
+ ,[[[108.14,135.9],[111.13,136.06],[114.08,136.56],[116.95,137.39],[119.71,138.55],[122.31,140.03],[124.71,141.81],[126.86,143.89],[128.73,146.23],[130.27,148.8],[131.44,151.55],[132.22,154.44],[132.56,157.41],[132.47,160.4],[131.93,163.34],[130.96,166.17],[129.6,168.83],[127.87,171.28],[125.83,173.46],[123.51,175.35],[120.96,176.91],[118.23,178.13],[115.36,179],[112.42,179.52],[109.43,179.7],[106.44,179.54],[103.49,179.04],[100.62,178.21],[97.86,177.06],[95.26,175.58],[92.86,173.79],[90.71,171.71],[88.84,169.37],[87.3,166.81],[86.13,164.06],[85.35,161.17],[85.01,158.2],[85.11,155.21],[85.64,152.26],[86.61,149.43],[87.97,146.77],[89.7,144.33],[91.74,142.14],[94.06,140.25],[96.61,138.69],[99.34,137.47],[102.21,136.6],[105.15,136.08]],
518
+ [[175.67,128.81],[177.16,128.85],[178.62,129.14],[180.01,129.67],[181.28,130.44],[182.41,131.42],[183.36,132.57],[184.12,133.85],[184.68,135.23],[185.05,136.68],[185.24,138.15],[185.27,139.64],[185.13,141.13],[184.85,142.59],[184.42,144.02],[183.85,145.4],[183.15,146.72],[182.33,147.96],[181.38,149.11],[180.32,150.16],[179.15,151.08],[177.88,151.87],[176.53,152.49],[175.1,152.91],[173.62,153.11],[172.13,153.07],[170.67,152.78],[169.28,152.24],[168.01,151.47],[166.88,150.49],[165.93,149.35],[165.18,148.06],[164.61,146.68],[164.24,145.24],[164.05,143.76],[164.02,142.27],[164.16,140.78],[164.44,139.32],[164.87,137.89],[165.44,136.51],[166.14,135.2],[166.96,133.95],[167.91,132.8],[168.97,131.75],[170.14,130.83],[171.4,130.04],[172.76,129.43],[174.19,129.01]]]
519
+ ,[[[103.39,78.25],[106.56,78.38],[109.59,79.28],[112.29,80.94],[114.43,83.28],[115.86,86.1],[116.52,89.2],[116.32,92.37],[115.62,95.46],[114.86,98.55],[114.1,101.63],[113.36,104.72],[112.63,107.81],[111.91,110.91],[111.2,114.01],[110.51,117.1],[109.82,120.21],[109.16,123.31],[108.52,126.42],[107.84,129.53],[106.8,132.52],[105.04,135.16],[102.66,137.25],[99.81,138.63],[96.7,139.2],[93.54,138.96],[90.53,137.95],[87.87,136.24],[85.71,133.92],[84.21,131.13],[83.48,128.05],[83.5,124.88],[84,121.74],[84.7,118.64],[85.4,115.54],[86.08,112.44],[86.77,109.34],[87.48,106.24],[88.19,103.15],[88.92,100.05],[89.66,96.96],[90.41,93.88],[91.18,90.8],[91.95,87.71],[93.1,84.76],[94.95,82.19],[97.4,80.19],[100.28,78.86]],
520
+ [[161.99,91.57],[165.07,92],[167.9,93.28],[170.32,95.23],[172.22,97.69],[173.49,100.53],[174.05,103.59],[173.93,106.7],[173.45,109.78],[172.9,112.85],[172.33,115.91],[171.71,118.97],[171.06,122.02],[170.38,125.06],[169.66,128.09],[168.91,131.12],[168.13,134.14],[167.33,137.15],[166.5,140.16],[165.58,143.14],[164.33,145.98],[162.5,148.5],[160.15,150.53],[157.38,151.95],[154.34,152.61],[151.24,152.43],[148.32,151.38],[145.83,149.52],[143.99,147.01],[142.95,144.08],[142.73,140.98],[143.25,137.91],[144.09,134.91],[144.94,131.91],[145.76,128.9],[146.54,125.89],[147.29,122.86],[148.01,119.83],[148.69,116.79],[149.34,113.74],[149.95,110.68],[150.54,107.62],[151.09,104.55],[151.6,101.47],[152.44,98.48],[154,95.79],[156.21,93.6],[158.94,92.12]]]
521
+ ,[[[47.23,91.05],[51.61,92.47],[55.26,95.29],[57.96,99.03],[59.7,103.31],[60.56,107.85],[61.28,112.42],[62.11,116.97],[63.06,121.51],[64.11,126.01],[65.28,130.49],[66.56,134.94],[67.95,139.35],[69.44,143.73],[71.05,148.07],[72.77,152.37],[74.62,156.61],[76.52,160.83],[78.06,165.19],[78.52,169.78],[77.62,174.3],[75.2,178.22],[71.44,180.86],[66.96,181.91],[62.36,181.55],[57.99,180.06],[54.03,177.68],[50.59,174.58],[47.77,170.92],[45.62,166.83],[43.74,162.6],[41.96,158.33],[40.29,154.01],[38.72,149.66],[37.27,145.26],[35.93,140.83],[34.69,136.37],[33.56,131.88],[32.55,127.37],[31.65,122.83],[30.85,118.27],[30.2,113.69],[30.08,109.07],[30.85,104.51],[32.49,100.19],[35.01,96.32],[38.44,93.24],[42.64,91.35]],
522
+ [[108.93,73.38],[113.76,73.6],[118.38,75.01],[122.49,77.56],[125.82,81.07],[128.1,85.34],[129.65,89.93],[131.04,94.58],[132.43,99.22],[133.82,103.87],[135.22,108.51],[136.6,113.16],[137.99,117.81],[139.36,122.46],[140.73,127.11],[142.13,131.76],[143.51,136.41],[144.82,141.08],[145.51,145.86],[144.91,150.66],[143.09,155.14],[140.17,158.99],[136.38,162.01],[132,164.05],[127.26,165.03],[122.42,164.86],[117.79,163.48],[113.67,160.95],[110.36,157.43],[108.17,153.11],[106.72,148.49],[105.36,143.83],[103.99,139.18],[102.62,134.53],[101.24,129.88],[99.87,125.23],[98.48,120.58],[97.09,115.93],[95.7,111.29],[94.29,106.64],[92.89,102],[91.49,97.36],[90.81,92.57],[91.38,87.77],[93.14,83.26],[96.02,79.37],[99.79,76.34],[104.18,74.32]]]
523
+ ,[[[102.86,129.56],[106.39,129.96],[109.85,130.76],[113.21,131.94],[116.4,133.5],[119.39,135.42],[122.13,137.69],[124.56,140.28],[126.64,143.16],[128.33,146.29],[129.59,149.61],[130.37,153.08],[130.66,156.62],[130.43,160.16],[129.68,163.63],[128.42,166.96],[126.7,170.07],[124.54,172.89],[122.02,175.39],[119.18,177.52],[116.07,179.25],[112.76,180.54],[109.31,181.4],[105.78,181.82],[102.23,181.83],[98.7,181.42],[95.24,180.62],[91.88,179.44],[88.69,177.88],[85.7,175.96],[82.96,173.69],[80.53,171.1],[78.45,168.22],[76.76,165.1],[75.5,161.77],[74.72,158.31],[74.44,154.77],[74.67,151.22],[75.41,147.75],[76.67,144.42],[78.39,141.32],[80.55,138.49],[83.07,135.99],[85.91,133.86],[89.02,132.14],[92.33,130.84],[95.78,129.99],[99.31,129.56]],
524
+ [[180.44,141.06],[183.61,141.1],[186.72,141.68],[189.66,142.86],[192.28,144.63],[194.43,146.96],[196,149.71],[197,152.72],[197.48,155.86],[197.51,159.03],[197.15,162.18],[196.43,165.27],[195.38,168.26],[194.07,171.15],[192.52,173.92],[190.74,176.55],[188.77,179.03],[186.6,181.35],[184.25,183.48],[181.74,185.41],[179.06,187.12],[176.23,188.56],[173.28,189.71],[170.21,190.52],[167.07,190.95],[163.9,190.91],[160.78,190.33],[157.84,189.15],[155.22,187.37],[153.08,185.04],[151.51,182.29],[150.51,179.28],[150.03,176.15],[150,172.98],[150.36,169.83],[151.07,166.74],[152.12,163.74],[153.43,160.85],[154.99,158.09],[156.76,155.46],[158.74,152.98],[160.91,150.66],[163.25,148.53],[165.77,146.59],[168.45,144.89],[171.27,143.45],[174.23,142.3],[177.29,141.48]]]
525
+ ,[[[86.02,131.33],[88.42,131.69],[90.54,132.87],[92.12,134.71],[93.03,136.97],[93.17,139.39],[92.41,141.69],[90.78,143.48],[88.59,144.52],[86.19,144.97],[83.78,145.34],[81.37,145.72],[78.96,146.09],[76.54,146.45],[74.13,146.81],[71.72,147.16],[69.3,147.5],[66.88,147.84],[64.47,148.16],[62.05,148.47],[59.62,148.76],[57.2,149.03],[54.77,149.27],[52.34,149.49],[49.91,149.68],[47.53,149.28],[45.52,147.92],[44.04,145.99],[43.12,143.74],[42.85,141.32],[43.44,138.97],[45.04,137.17],[47.33,136.4],[49.76,136.2],[52.19,135.96],[54.62,135.7],[57.04,135.43],[59.46,135.15],[61.89,134.85],[64.31,134.54],[66.72,134.22],[69.14,133.89],[71.56,133.54],[73.97,133.19],[76.38,132.83],[78.79,132.45],[81.2,132.06],[83.61,131.67]],
526
+ [[153.42,116.84],[155.92,117.69],[157.78,119.56],[158.72,122.03],[158.73,124.68],[157.84,127.18],[156.08,129.15],[153.71,130.33],[151.13,131],[148.55,131.65],[145.98,132.32],[143.4,132.98],[140.82,133.63],[138.23,134.27],[135.65,134.9],[133.06,135.53],[130.47,136.15],[127.88,136.76],[125.29,137.36],[122.69,137.94],[120.09,138.51],[117.49,139.06],[114.88,139.59],[112.27,140.1],[109.62,140.12],[107.17,139.14],[105.28,137.29],[104.18,134.88],[104.06,132.23],[105.03,129.78],[106.92,127.93],[109.35,126.87],[111.96,126.34],[114.57,125.8],[117.17,125.24],[119.77,124.67],[122.37,124.09],[124.96,123.5],[127.56,122.9],[130.15,122.29],[132.74,121.68],[135.32,121.05],[137.91,120.41],[140.49,119.76],[143.07,119.11],[145.65,118.44],[148.22,117.76],[150.78,117.03]]]
527
+ ,[[[83.36,65.84],[86.61,66.42],[89.57,67.88],[92,70.12],[93.67,72.97],[94.46,76.17],[94.31,79.47],[93.61,82.71],[92.8,85.92],[92.02,89.14],[91.27,92.36],[90.56,95.6],[89.88,98.84],[89.23,102.09],[88.62,105.34],[88.03,108.61],[87.51,111.88],[87.01,115.15],[86.5,118.42],[85.65,121.62],[84.11,124.54],[81.9,126.99],[79.13,128.79],[75.98,129.8],[72.68,129.91],[69.47,129.13],[66.6,127.49],[64.24,125.18],[62.49,122.38],[61.42,119.25],[61.08,115.97],[61.36,112.67],[61.87,109.4],[62.45,106.13],[63.01,102.87],[63.61,99.61],[64.24,96.36],[64.9,93.11],[65.6,89.87],[66.33,86.64],[67.09,83.42],[67.89,80.2],[68.73,77],[69.89,73.9],[71.7,71.14],[74.1,68.86],[76.93,67.16],[80.07,66.12]],
528
+ [[119.49,99.16],[121.99,99.28],[124.44,99.82],[126.9,100.34],[129.36,100.86],[131.81,101.38],[134.27,101.91],[136.72,102.44],[139.17,102.98],[141.62,103.52],[144.08,104.07],[146.52,104.62],[148.97,105.18],[151.42,105.74],[153.86,106.31],[156.31,106.89],[158.75,107.47],[161.2,108.02],[163.49,109.03],[165.16,110.87],[165.95,113.24],[165.87,115.74],[164.94,118.05],[163.17,119.8],[160.79,120.55],[158.31,120.29],[155.88,119.65],[153.44,119.06],[150.99,118.49],[148.55,117.92],[146.1,117.36],[143.65,116.81],[141.2,116.26],[138.75,115.73],[136.29,115.2],[133.84,114.67],[131.38,114.15],[128.93,113.62],[126.47,113.1],[124.02,112.57],[121.56,112.04],[119.11,111.5],[116.81,110.53],[115.08,108.73],[114.22,106.39],[114.29,103.9],[115.28,101.61],[117.12,99.93]]]
529
+ ,[[[168.71,85.67],[170.73,86],[172.64,86.75],[174.37,87.85],[175.88,89.24],[177.11,90.88],[178.04,92.71],[178.71,94.65],[179.21,96.64],[179.64,98.65],[180.05,100.66],[180.45,102.67],[180.83,104.69],[181.18,106.71],[181.5,108.74],[181.77,110.78],[181.88,112.82],[181.71,114.87],[181.22,116.86],[180.41,118.74],[179.27,120.45],[177.83,121.91],[176.12,123.03],[174.2,123.74],[172.16,123.99],[170.13,123.75],[168.21,123.04],[166.49,121.93],[165.03,120.48],[163.88,118.79],[163.02,116.93],[162.49,114.95],[162.17,112.92],[161.85,110.89],[161.51,108.87],[161.14,106.84],[160.77,104.83],[160.37,102.81],[159.96,100.8],[159.52,98.79],[159.24,96.76],[159.3,94.71],[159.71,92.7],[160.48,90.8],[161.58,89.08],[163.01,87.61],[164.73,86.49],[166.67,85.83]],
530
+ [[206.57,78.24],[208.3,78.8],[209.77,79.87],[210.99,81.22],[212.01,82.73],[212.85,84.34],[213.53,86.03],[214.08,87.77],[214.54,89.54],[214.95,91.31],[215.34,93.09],[215.7,94.88],[216.04,96.67],[216.36,98.46],[216.64,100.26],[216.89,102.07],[217.11,103.88],[217.25,105.7],[217.26,107.52],[217.1,109.33],[216.75,111.12],[216.16,112.84],[215.3,114.44],[214.04,115.75],[212.34,116.35],[210.58,115.96],[209.11,114.89],[207.97,113.48],[207.1,111.88],[206.44,110.18],[205.97,108.42],[205.62,106.63],[205.35,104.83],[205.11,103.02],[204.85,101.22],[204.55,99.42],[204.22,97.63],[203.87,95.84],[203.49,94.05],[203.09,92.28],[202.67,90.5],[202.32,88.71],[202.1,86.91],[202.1,85.08],[202.32,83.28],[202.77,81.51],[203.54,79.86],[204.82,78.59]]]
531
+ ,[[[39.78,104.3],[42.64,105.01],[45.03,106.74],[46.73,109.15],[47.75,111.93],[48.35,114.83],[48.81,117.76],[49.31,120.68],[49.87,123.6],[50.48,126.5],[51.15,129.39],[51.86,132.27],[52.63,135.13],[53.44,137.98],[54.3,140.82],[55.19,143.65],[56.13,146.46],[57.1,149.26],[58.1,152.05],[58.86,154.92],[58.96,157.87],[58.18,160.72],[56.43,163.09],[53.84,164.48],[50.9,164.62],[48.08,163.75],[45.58,162.16],[43.51,160.05],[41.89,157.57],[40.67,154.87],[39.67,152.08],[38.73,149.26],[37.81,146.44],[36.94,143.61],[36.11,140.76],[35.34,137.9],[34.61,135.03],[33.92,132.14],[33.28,129.24],[32.7,126.34],[32.16,123.42],[31.67,120.5],[31.23,117.57],[31.14,114.61],[31.65,111.69],[32.74,108.94],[34.47,106.54],[36.89,104.86]],
532
+ [[108.97,125.73],[111.9,126.2],[114.63,127.37],[117,129.16],[118.84,131.49],[119.99,134.23],[120.32,137.18],[119.85,140.11],[118.59,142.8],[116.78,145.16],[114.84,147.42],[112.89,149.67],[110.93,151.92],[108.97,154.16],[107.01,156.39],[105.03,158.62],[103.05,160.85],[101.07,163.06],[99.07,165.28],[97.09,167.5],[95.09,169.71],[93.05,171.88],[90.69,173.67],[87.89,174.66],[84.93,174.81],[82.02,174.22],[79.31,173],[76.92,171.24],[74.99,168.98],[73.7,166.3],[73.26,163.37],[73.74,160.45],[75.2,157.86],[77.17,155.63],[79.18,153.43],[81.18,151.23],[83.17,149.02],[85.16,146.8],[87.14,144.58],[89.11,142.35],[91.08,140.11],[93.04,137.87],[95,135.63],[96.95,133.38],[98.89,131.12],[100.87,128.89],[103.25,127.12],[106.02,126.04]]]
533
+ ,[[[115.43,87.59],[118.19,88.24],[120.69,89.59],[122.69,91.59],[124.03,94.09],[124.63,96.87],[124.41,99.7],[123.7,102.45],[122.9,105.18],[122.12,107.92],[121.34,110.65],[120.57,113.39],[119.79,116.13],[119.02,118.87],[118.25,121.61],[117.48,124.35],[116.72,127.09],[115.97,129.83],[115.23,132.58],[114.45,135.32],[113.3,137.91],[111.49,140.09],[109.13,141.65],[106.41,142.48],[103.58,142.56],[100.82,141.91],[98.33,140.54],[96.33,138.53],[94.99,136.03],[94.38,133.26],[94.57,130.43],[95.25,127.67],[96.02,124.93],[96.79,122.19],[97.55,119.45],[98.31,116.7],[99.08,113.96],[99.85,111.22],[100.62,108.49],[101.4,105.75],[102.18,103.01],[102.95,100.27],[103.74,97.54],[104.51,94.8],[105.68,92.21],[107.5,90.04],[109.88,88.5],[112.59,87.67]],
534
+ [[155.37,78.64],[158.04,79.15],[160.48,80.37],[162.53,82.16],[164.33,84.22],[166.1,86.3],[167.85,88.4],[169.58,90.51],[171.29,92.64],[172.98,94.78],[174.65,96.94],[176.3,99.12],[177.92,101.32],[179.51,103.54],[181.06,105.79],[182.57,108.07],[184.03,110.37],[185.2,112.83],[185.77,115.5],[185.73,118.23],[185.07,120.87],[183.8,123.28],[181.94,125.26],[179.57,126.6],[176.89,127.03],[174.24,126.43],[171.99,124.92],[170.26,122.8],[168.75,120.53],[167.22,118.27],[165.66,116.03],[164.07,113.81],[162.45,111.6],[160.82,109.41],[159.16,107.25],[157.47,105.1],[155.76,102.97],[154.03,100.85],[152.28,98.76],[150.51,96.68],[148.74,94.6],[147.29,92.29],[146.49,89.69],[146.36,86.97],[146.94,84.31],[148.23,81.91],[150.19,80.02],[152.66,78.89]]]
535
+ ,[[[92.71,76.24],[95.76,76.59],[98.73,77.35],[101.56,78.53],[104.21,80.08],[106.63,81.96],[108.78,84.16],[110.61,86.62],[112.09,89.31],[113.19,92.17],[113.91,95.15],[114.24,98.2],[114.18,101.27],[113.73,104.31],[112.9,107.26],[111.7,110.09],[110.15,112.73],[108.28,115.17],[106.12,117.35],[103.71,119.24],[101.08,120.83],[98.27,122.07],[95.33,122.95],[92.3,123.44],[89.23,123.51],[86.18,123.17],[83.21,122.41],[80.38,121.23],[77.73,119.69],[75.31,117.8],[73.16,115.61],[71.33,113.14],[69.86,110.45],[68.75,107.59],[68.02,104.61],[67.7,101.56],[67.76,98.49],[68.22,95.46],[69.05,92.5],[70.25,89.68],[71.8,87.03],[73.67,84.59],[75.83,82.41],[78.24,80.52],[80.87,78.93],[83.67,77.69],[86.61,76.81],[89.64,76.32]],
536
+ [[157.73,102.08],[159.31,102.13],[160.86,102.42],[162.35,102.95],[163.74,103.69],[165.01,104.62],[166.15,105.72],[167.13,106.95],[167.96,108.29],[168.63,109.72],[169.13,111.22],[169.45,112.76],[169.59,114.34],[169.55,115.91],[169.31,117.47],[168.88,118.99],[168.28,120.45],[167.52,121.83],[166.58,123.1],[165.48,124.23],[164.25,125.22],[162.89,126.02],[161.43,126.63],[159.91,127.02],[158.34,127.2],[156.76,127.14],[155.21,126.85],[153.73,126.33],[152.33,125.59],[151.06,124.65],[149.93,123.56],[148.94,122.33],[148.11,120.99],[147.44,119.56],[146.95,118.06],[146.62,116.51],[146.48,114.94],[146.52,113.37],[146.76,111.8],[147.18,110.28],[147.78,108.83],[148.56,107.45],[149.5,106.18],[150.59,105.05],[151.83,104.07],[153.18,103.26],[154.64,102.65],[156.17,102.26]]]
537
+ ,[[[57.98,112.03],[61.01,112.26],[63.82,113.41],[66.22,115.27],[68.09,117.67],[69.36,120.44],[70.14,123.39],[70.64,126.39],[71.07,129.41],[71.58,132.42],[72.15,135.41],[72.76,138.4],[73.4,141.38],[74.09,144.35],[74.82,147.31],[75.59,150.26],[76.42,153.2],[77.3,156.12],[78.16,159.04],[78.68,162.04],[78.42,165.07],[77.28,167.88],[75.25,170.13],[72.54,171.49],[69.52,171.87],[66.51,171.44],[63.69,170.32],[61.16,168.61],[59.03,166.44],[57.38,163.89],[56.23,161.06],[55.34,158.15],[54.53,155.21],[53.73,152.27],[52.97,149.31],[52.25,146.35],[51.57,143.38],[50.93,140.4],[50.34,137.41],[49.78,134.41],[49.26,131.4],[48.78,128.39],[48.37,125.37],[48.37,122.33],[49.06,119.36],[50.44,116.65],[52.47,114.39],[55.04,112.78]],
538
+ [[117.45,101.46],[120.57,101.84],[123.48,103.02],[125.99,104.91],[127.97,107.35],[129.25,110.23],[130.05,113.27],[130.76,116.34],[131.46,119.41],[132.15,122.49],[132.85,125.56],[133.55,128.63],[134.24,131.71],[134.93,134.78],[135.61,137.86],[136.32,140.93],[137.01,144],[137.66,147.09],[137.87,150.22],[137.25,153.3],[135.83,156.1],[133.73,158.45],[131.15,160.23],[128.22,161.38],[125.11,161.83],[121.98,161.5],[119.05,160.37],[116.52,158.51],[114.57,156.05],[113.37,153.14],[112.64,150.08],[111.95,147],[111.27,143.93],[110.58,140.85],[109.89,137.78],[109.2,134.7],[108.51,131.63],[107.81,128.56],[107.12,125.48],[106.42,122.41],[105.71,119.34],[105.02,116.27],[104.83,113.13],[105.42,110.04],[106.79,107.22],[108.84,104.83],[111.41,103.02],[114.33,101.87]]]
539
+ ,[[[113.75,120.08],[118.16,120.78],[122.31,122.43],[125.98,124.96],[128.94,128.29],[131.02,132.23],[132.12,136.56],[132.1,141.02],[131.16,145.38],[129.94,149.68],[128.69,153.98],[127.44,158.27],[126.19,162.56],[124.92,166.85],[123.64,171.14],[122.35,175.42],[121.05,179.69],[119.76,183.97],[118.46,188.25],[117.05,192.49],[114.84,196.36],[111.47,199.27],[107.42,201.12],[103.04,201.99],[98.58,201.97],[94.18,201.19],[89.97,199.7],[86.1,197.48],[82.8,194.48],[80.41,190.72],[79.31,186.41],[79.87,182],[81.24,177.74],[82.57,173.47],[83.88,169.2],[85.19,164.92],[86.48,160.64],[87.75,156.36],[89.02,152.07],[90.28,147.78],[91.53,143.49],[92.77,139.19],[93.97,134.88],[95.5,130.69],[97.93,126.95],[101.16,123.87],[105.02,121.64],[109.3,120.36]],
540
+ [[181.19,127.71],[185.4,128.03],[189.23,129.79],[192.19,132.8],[194.06,136.59],[194.87,140.74],[194.76,144.98],[194.21,149.18],[193.55,153.37],[192.79,157.55],[191.91,161.69],[190.91,165.82],[189.8,169.91],[188.57,173.97],[187.22,177.99],[185.72,181.96],[184.07,185.87],[182.26,189.7],[180.26,193.44],[177.85,196.92],[174.93,199.99],[171.62,202.64],[168,204.85],[164.13,206.59],[160.07,207.78],[155.86,208.24],[151.69,207.6],[148.31,205.16],[147.33,201.11],[148.48,197.06],[150.4,193.28],[152.24,189.46],[153.93,185.56],[155.48,181.61],[156.89,177.62],[158.17,173.57],[159.32,169.49],[160.35,165.38],[161.26,161.23],[162.06,157.07],[162.7,152.87],[163.29,148.67],[164.12,144.52],[165.46,140.5],[167.49,136.78],[170.16,133.49],[173.37,130.73],[177.08,128.7]]]
541
+ ,[[[52.43,111.88],[55.76,112.3],[59,113.21],[62.08,114.57],[64.96,116.3],[67.61,118.36],[70.01,120.71],[72.16,123.3],[74.02,126.1],[75.61,129.06],[76.9,132.17],[77.89,135.38],[78.56,138.68],[78.89,142.02],[78.86,145.39],[78.45,148.72],[77.63,151.98],[76.39,155.11],[74.74,158.03],[72.67,160.68],[70.2,162.96],[67.38,164.79],[64.28,166.08],[61,166.78],[57.64,166.91],[54.3,166.49],[51.07,165.57],[47.99,164.22],[45.11,162.49],[42.46,160.42],[40.05,158.07],[37.91,155.48],[36.04,152.68],[34.46,149.72],[33.16,146.62],[32.17,143.4],[31.51,140.11],[31.18,136.76],[31.21,133.4],[31.62,130.06],[32.44,126.8],[33.67,123.68],[35.33,120.75],[37.4,118.1],[39.86,115.82],[42.68,114],[45.79,112.71],[49.07,112.01]],
542
+ [[126.89,95.19],[130.56,95.44],[134.16,96.17],[137.64,97.36],[140.94,98.99],[143.98,101.06],[146.73,103.5],[149.13,106.29],[151.14,109.37],[152.72,112.69],[153.86,116.19],[154.54,119.8],[154.74,123.47],[154.45,127.14],[153.67,130.74],[152.43,134.2],[150.76,137.48],[148.69,140.51],[146.25,143.27],[143.48,145.69],[140.43,147.75],[137.14,149.39],[133.66,150.59],[130.06,151.32],[126.39,151.56],[122.72,151.31],[119.11,150.59],[115.63,149.4],[112.34,147.76],[109.29,145.7],[106.54,143.26],[104.14,140.47],[102.13,137.39],[100.55,134.07],[99.41,130.57],[98.73,126.96],[98.53,123.28],[98.83,119.62],[99.6,116.02],[100.84,112.56],[102.51,109.28],[104.59,106.25],[107.03,103.49],[109.79,101.07],[112.84,99.01],[116.13,97.36],[119.61,96.16],[123.22,95.43]]]
543
+ ,[[[72.34,79.33],[74.93,79.64],[77.52,79.94],[80.12,80.25],[82.71,80.57],[85.3,80.91],[87.88,81.26],[90.47,81.63],[93.05,82],[95.63,82.39],[98.21,82.79],[100.79,83.21],[103.37,83.63],[105.94,84.07],[108.51,84.52],[111.09,84.92],[113.65,85.44],[115.99,86.56],[117.75,88.47],[118.68,90.89],[118.57,93.48],[117.47,95.83],[115.57,97.6],[113.16,98.56],[110.56,98.58],[108,98.1],[105.43,97.64],[102.85,97.19],[100.28,96.76],[97.7,96.33],[95.12,95.93],[92.54,95.53],[89.96,95.14],[87.38,94.77],[84.79,94.4],[82.2,94.06],[79.62,93.72],[77.02,93.41],[74.43,93.11],[71.84,92.81],[69.24,92.5],[66.78,91.69],[64.99,89.83],[64.25,87.35],[64.5,84.76],[65.58,82.39],[67.38,80.53],[69.74,79.45]],
544
+ [[136.83,90.25],[139.33,90.71],[141.8,91.34],[144.28,91.93],[146.75,92.53],[149.22,93.14],[151.69,93.77],[154.15,94.4],[156.62,95.05],[159.08,95.71],[161.53,96.38],[163.98,97.07],[166.43,97.76],[168.88,98.47],[171.32,99.2],[173.75,99.94],[176.19,100.67],[178.49,101.74],[180.18,103.62],[181.12,105.98],[181.31,108.51],[180.69,110.96],[179.21,113.01],[176.98,114.19],[174.46,114.13],[172.02,113.41],[169.58,112.66],[167.14,111.93],[164.7,111.22],[162.25,110.52],[159.8,109.84],[157.34,109.17],[154.88,108.52],[152.42,107.88],[149.95,107.26],[147.48,106.64],[145.01,106.03],[142.54,105.42],[140.06,104.81],[137.59,104.21],[135.12,103.61],[132.78,102.62],[130.96,100.86],[129.93,98.55],[129.77,96.02],[130.49,93.59],[132.06,91.61],[134.31,90.46]]]
545
+ ,[[[107.05,116.19],[110.26,116.71],[113.26,118],[115.85,119.97],[117.92,122.49],[119.29,125.45],[120.04,128.63],[120.54,131.86],[121.04,135.09],[121.54,138.31],[122.06,141.54],[122.59,144.77],[123.12,147.99],[123.67,151.21],[124.22,154.43],[124.8,157.65],[125.4,160.86],[125.95,164.08],[126.04,167.34],[125.2,170.49],[123.53,173.28],[121.14,175.49],[118.26,177.02],[115.11,177.87],[111.85,178.04],[108.63,177.56],[105.58,176.41],[102.87,174.58],[100.72,172.14],[99.35,169.18],[98.61,166],[98.04,162.78],[97.47,159.57],[96.91,156.35],[96.36,153.13],[95.83,149.9],[95.3,146.68],[94.78,143.45],[94.27,140.22],[93.76,137],[93.26,133.77],[92.82,130.53],[92.96,127.27],[93.87,124.15],[95.55,121.35],[97.88,119.07],[100.68,117.41],[103.79,116.44]],
546
+ [[189.21,121.96],[191.36,122.71],[192.8,124.5],[193.41,126.73],[193.32,129.04],[192.59,131.23],[191.22,133.09],[189.28,134.34],[187.12,135.19],[184.95,136],[182.78,136.83],[180.61,137.63],[178.43,138.43],[176.24,139.2],[174.05,139.95],[171.85,140.69],[169.64,141.4],[167.43,142.09],[165.21,142.76],[162.98,143.42],[160.75,144.05],[158.51,144.66],[156.27,145.25],[154.02,145.81],[151.72,145.98],[149.57,145.18],[148.01,143.49],[147.25,141.31],[147.31,139],[148.16,136.86],[149.7,135.14],[151.74,134.05],[153.97,133.43],[156.21,132.84],[158.45,132.22],[160.68,131.59],[162.91,130.93],[165.13,130.26],[167.34,129.58],[169.55,128.87],[171.76,128.15],[173.95,127.41],[176.15,126.65],[178.33,125.87],[180.51,125.08],[182.68,124.26],[184.84,123.41],[186.98,122.53]]]
547
+ ,[[[98.62,121.53],[100.72,121.6],[102.78,122.03],[104.72,122.83],[106.49,123.97],[108.01,125.42],[109.24,127.12],[110.15,129.02],[110.66,131.05],[110.78,133.15],[110.62,135.25],[110.34,137.33],[110.04,139.42],[109.76,141.5],[109.49,143.59],[109.21,145.68],[108.92,147.76],[108.6,149.84],[108.08,151.88],[107.18,153.78],[105.92,155.45],[104.34,156.83],[102.51,157.86],[100.51,158.52],[98.43,158.81],[96.33,158.72],[94.28,158.27],[92.33,157.47],[90.57,156.33],[89.03,154.89],[87.78,153.21],[86.85,151.32],[86.29,149.3],[86.13,147.2],[86.28,145.11],[86.57,143.02],[86.9,140.94],[87.2,138.86],[87.49,136.78],[87.79,134.69],[88.08,132.61],[88.4,130.53],[88.96,128.5],[89.88,126.61],[91.15,124.94],[92.73,123.56],[94.56,122.52],[96.54,121.84]],
548
+ [[155.31,127.29],[157.36,127.43],[159.33,127.99],[161.14,128.96],[162.7,130.29],[163.95,131.92],[164.84,133.77],[165.35,135.75],[165.49,137.8],[165.35,139.85],[165.07,141.89],[164.79,143.92],[164.53,145.96],[164.26,148],[163.97,150.04],[163.65,152.06],[163.27,154.09],[162.7,156.06],[161.83,157.92],[160.68,159.62],[159.29,161.13],[157.69,162.41],[155.9,163.42],[153.97,164.1],[151.94,164.41],[149.89,164.32],[147.9,163.82],[146.06,162.92],[144.47,161.62],[143.24,159.98],[142.41,158.1],[142,156.09],[142.01,154.04],[142.32,152.01],[142.64,149.98],[142.96,147.95],[143.25,145.92],[143.51,143.88],[143.73,141.83],[143.97,139.79],[144.27,137.76],[144.74,135.76],[145.53,133.87],[146.62,132.13],[147.98,130.59],[149.57,129.28],[151.35,128.27],[153.28,127.58]]]
549
+ ];
550
+
551
+ const GROK_POOLS = {"sleeping":[13,22,4],"idle":[0,8],"listening":[10,1,19],"thinking":[8,16,14,17,5],"searching":[15,9,3,20,12,18],"working":[7,16,11,10],"surprised":[3,21],"angry":[7,16],"happy":[2,11,17,19],"confused":[14,5,8],"sad":[4,13,22],"loading":[0,8],"receiving":[19,0,8]};
552
+
553
+ const GROK_EXPR_CADENCE = {"sleeping":[6000,10000],"idle":[9000,16000],"listening":[2800,5000],"thinking":[2000,3600],"searching":[1000,1800],"working":[1800,3200],"surprised":[2500,4000],"angry":[2200,3800],"happy":[2500,4500],"confused":[2200,3800],"sad":[4000,7000],"loading":[6000,10000],"receiving":[4000,8000]};
554
+
555
+ const GROK_BLINK = {"sleeping":null,"idle":[6000,14000],"listening":[3000,7000],"thinking":[3500,7000],"searching":[1600,4000],"working":[2800,5500],"surprised":[1800,3500],"angry":[3500,7000],"happy":[2500,5000],"confused":[2800,5500],"sad":[4000,8000],"loading":null,"receiving":null};
556
+
557
+ const GROK_SHAPES = {
558
+ "blob": { label: "原始形态", d: "M228.541 114.228C228.541 130.133 225.184 145.994 218.738 160.534C212.674 174.217 203.904 186.669 193.065 196.988C155.933 232.34 99.497 238.596 55.5255 212.24C45.097 205.99 35.6851 198.072 27.7451 188.866C19.1926 178.953 12.3686 167.569 7.65781 155.351C2.60712 142.264 0 128.257 0 114.228C0 98.3219 3.35751 82.4611 9.80315 67.9215C15.8672 54.2382 24.6377 41.7862 35.4767 31.4668C72.6081 -3.88483 129.044 -10.1413 173.016 16.2153C183.444 22.4653 192.856 30.3829 200.796 39.5896C209.349 49.5018 216.173 60.8859 220.883 73.1037C225.934 86.1906 228.541 100.198 228.541 114.228Z" }
559
+ ,"pebble": { label: "鹅卵石", d: "M114 8C177 8 217 45 217 109C217 178 181 219 112 219C43 219 12 181 12 113C12 48 51 8 114 8Z" }
560
+ ,"squircle": { label: "圆角方", d: "M55 10H174Q219 10 219 55V174Q219 219 174 219H55Q10 219 10 174V55Q10 10 55 10Z" }
561
+ ,"capsule": { label: "胶囊", d: "M61 31H168C202 31 220 65 220 114C220 163 202 197 168 197H61C27 197 9 163 9 114C9 65 27 31 61 31Z" }
562
+ ,"triangle": { label: "三角体", d: "M114 9Q122 9 128 21L220 194Q227 210 207 210H21Q1 210 9 194L101 21Q106 9 114 9Z" }
563
+ ,"hex": { label: "六边体", d: "M114 5L207 58Q218 64 218 78V153Q218 167 207 173L128 218Q114 226 100 218L21 173Q10 167 10 153V78Q10 64 21 58L100 12Q114 5 114 5Z" }
564
+ ,"cloud": { label: "云朵", d: "M55 188C21 188 6 169 12 142C-1 113 20 86 51 84C61 48 96 35 124 55C151 28 195 46 195 82C226 91 235 128 213 149C214 174 193 190 165 188Z" }
565
+ ,"drop": { label: "水滴", d: "M114 5C137 42 202 103 202 151C202 196 165 222 114 222C63 222 26 196 26 151C26 103 91 42 114 5Z" }
566
+ };
567
+
568
+ /**
569
+ * Grok renderer: SVG Path Morph engine, powered by LaoA-GrokBot data
570
+ * (25 expression geometries / 39 semantic states / 8 body shapes).
571
+ *
572
+ * Renders with two <path> eyes + one body path. Every frame the eyes morph
573
+ * through a critically-damped spring toward the target expression, while
574
+ * per-state expression pools / cadences and blink cadences drive the living
575
+ * feel. Runs on the shared document-level rAF scheduler and honors a
576
+ * visibility guard, so hidden / paused / reduced-motion instances do no work.
577
+ */
578
+
579
+
580
+ const SVG_NS = 'http://www.w3.org/2000/svg';
581
+ const EYE_CX = 114.2705;
582
+ const EYE_R = 105;
583
+ const BLINK_MS = 320;
584
+ const MOTION_MS = 1100;
585
+ const SPRING_STIFFNESS = 49;
586
+ const DEFAULT_BODY = '#2f86ed';
587
+ const DEFAULT_EYES = '#fffdf7';
588
+
589
+ let clipCounter = 0;
590
+
591
+ const MOTION_GROUPS = {
592
+ bounce: ['happy'],
593
+ tilt: ['listening', 'thinking', 'confused'],
594
+ scan: ['searching', 'working'],
595
+ turn: ['receiving'],
596
+ pulse: ['sleeping', 'loading']
597
+ };
598
+ const MOTION_DURATIONS = { bounce: 0.85, tilt: 0.8, scan: 0.8, turn: 0.9, pulse: 0.9, glitch: 0.55 };
599
+ const MOTION_CLASSES = [...Object.keys(MOTION_GROUPS), 'glitch'].map((name) => `act-${name}`);
600
+
601
+ function clamp(value, min, max) {
602
+ return Math.max(min, Math.min(max, value));
603
+ }
604
+
605
+ function pathFromRing(ring) {
606
+ return 'M' + ring.map((point) => `${point[0].toFixed(2)} ${point[1].toFixed(2)}`).join('L') + 'Z';
607
+ }
608
+
609
+ function ringCentroid(ring) {
610
+ return ring.reduce((acc, point) => [acc[0] + point[0] / ring.length, acc[1] + point[1] / ring.length], [0, 0]);
611
+ }
612
+
613
+ function randomBetween(range) {
614
+ return range[0] + Math.random() * (range[1] - range[0]);
615
+ }
616
+
617
+ /**
618
+ * @param {object} env
619
+ * @param {HTMLElement} env.stage SVG container
620
+ * @param {object} env.s live facade state (preset/name/shape/interactive/speed/...)
621
+ * @param {object} env.emitter event bus
622
+ * @returns {object} renderer controller
623
+ */
624
+ function createGrokRenderer({ stage, s, emitter }) {
625
+ let disposed = false;
626
+ let unsubscribe = null;
627
+ let visibility = null;
628
+ let detachPointer = null;
629
+
630
+ const svg = document.createElementNS(SVG_NS, 'svg');
631
+ svg.setAttribute('class', 'dlc-grok');
632
+ svg.setAttribute('viewBox', '-28 -28 285 285');
633
+ svg.setAttribute('role', 'img');
634
+ svg.setAttribute('preserveAspectRatio', s.fit === 'cover' ? 'xMidYMid slice' : s.fit === 'fill' ? 'none' : 'xMidYMid meet');
635
+ const body = document.createElementNS(SVG_NS, 'path');
636
+ body.setAttribute('class', 'dlc-grok__body');
637
+ const defs = document.createElementNS(SVG_NS, 'defs');
638
+ const clipPath = document.createElementNS(SVG_NS, 'clipPath');
639
+ const clipId = `dlc-grok-clip-${clipCounter++}`;
640
+ clipPath.setAttribute('id', clipId);
641
+ const clipShape = document.createElementNS(SVG_NS, 'path');
642
+ clipPath.appendChild(clipShape);
643
+ defs.appendChild(clipPath);
644
+ const eyesGroup = document.createElementNS(SVG_NS, 'g');
645
+ eyesGroup.setAttribute('class', 'dlc-grok__eyes');
646
+ eyesGroup.setAttribute('clip-path', `url(#${clipId})`);
647
+ const eyes = [0, 1].map(() => {
648
+ const path = document.createElementNS(SVG_NS, 'path');
649
+ path.setAttribute('class', 'dlc-grok__eye');
650
+ eyesGroup.appendChild(path);
651
+ return path;
652
+ });
653
+ svg.appendChild(defs);
654
+ svg.appendChild(body);
655
+ svg.appendChild(eyesGroup);
656
+ stage.appendChild(svg);
657
+
658
+ let current = GROK_EXPRESSIONS[0].map((ring) => ring.map((point) => [...point]));
659
+ let target = GROK_EXPRESSIONS[0];
660
+ let expression = 0;
661
+ let morph = 1;
662
+ let velocity = 0;
663
+ let blinkStart = 0;
664
+ let blinkTimer = 0;
665
+ let exprTimer = 0;
666
+ let gazeX = 0;
667
+ let gazeY = 0;
668
+ let motionUntil = 0;
669
+ let motionClass = null;
670
+
671
+ const applyBodyShape = () => {
672
+ const shape = GROK_SHAPES[s.shape] || GROK_SHAPES.blob;
673
+ body.setAttribute('d', shape.d);
674
+ clipShape.setAttribute('d', shape.d);
675
+ };
676
+
677
+ const applyColors = () => {
678
+ const resolve = (value, fallback) => {
679
+ const hex = normalizeColor(value);
680
+ return hex || fallback;
681
+ };
682
+ // 用 inline style 而不是 presentation attribute:emo.css 里
683
+ // .dlc-grok__body / .dlc-grok__eye 的 fill 规则优先级更高,attribute 会被覆盖。
684
+ body.style.fill = resolve(s.partColors.body, DEFAULT_BODY);
685
+ eyes.forEach((path) => { path.style.fill = resolve(s.partColors.eyes, DEFAULT_EYES); });
686
+ };
687
+
688
+ const rings = () => current.map((ring, eye) => ring.map((point, i) => [
689
+ point[0] + (target[eye][i][0] - point[0]) * clamp(morph, 0, 1),
690
+ point[1] + (target[eye][i][1] - point[1]) * clamp(morph, 0, 1)
691
+ ]));
692
+
693
+ const chooseExpression = (index) => {
694
+ current = rings();
695
+ target = GROK_EXPRESSIONS[index];
696
+ expression = index;
697
+ morph = 0;
698
+ velocity = 0;
699
+ };
700
+
701
+ const setExpression = (index) => {
702
+ current = GROK_EXPRESSIONS[index].map((ring) => ring.map((point) => [...point]));
703
+ target = GROK_EXPRESSIONS[index];
704
+ expression = index;
705
+ morph = 1;
706
+ velocity = 0;
707
+ };
708
+
709
+ const blinkScale = (now) => {
710
+ if (!blinkStart) return 1;
711
+ const t = (now - blinkStart) / (BLINK_MS / s.speed);
712
+ if (t >= 1) { blinkStart = 0; return 1; }
713
+ return Math.max(t < 0.42 ? 1 - t / 0.42 : (t - 0.42) / 0.58, 0.04);
714
+ };
715
+
716
+ const renderEyes = (now) => {
717
+ const shown = rings();
718
+ const blink = blinkScale(now);
719
+ shown.forEach((ring, i) => {
720
+ const center = ringCentroid(ring);
721
+ const base = Math.asin(clamp((center[0] - EYE_CX) / EYE_R, -1, 1));
722
+ const depth = Math.cos(base);
723
+ const perspective = Math.max(depth, 0.02) / Math.max(Math.cos(base), 0.02);
724
+ const x = EYE_CX + EYE_R * Math.sin(base) + gazeX;
725
+ const y = center[1] + gazeY;
726
+ eyes[i].setAttribute('d', pathFromRing(ring));
727
+ eyes[i].setAttribute('transform', `translate(${x} ${y}) scale(${clamp(perspective, 0.02, 2.4)} ${blink}) translate(${-center[0]} ${-center[1]})`);
728
+ eyes[i].style.opacity = depth > 0.02 ? '1' : '0';
729
+ });
730
+ };
731
+
732
+ const motionClassFor = (name) => {
733
+ for (const [className, states] of Object.entries(MOTION_GROUPS)) {
734
+ if (states.includes(name)) return className;
735
+ }
736
+ return 'glitch';
737
+ };
738
+
739
+ const applyBodyMotion = () => {
740
+ const className = motionClassFor(s.preset.name);
741
+ svg.classList.remove(...MOTION_CLASSES);
742
+ svg.classList.add(`act-${className}`);
743
+ svg.style.animationDuration = `${MOTION_DURATIONS[className] / s.speed}s`;
744
+ svg.style.animationPlayState = s.paused || s.reducedMotion || !s.autoplay ? 'paused' : 'running';
745
+ motionClass = className;
746
+ motionUntil = 0;
747
+ };
748
+
749
+ const scheduleExpression = () => {
750
+ const cadence = GROK_EXPR_CADENCE[s.preset.name];
751
+ exprTimer = cadence && s.loop ? randomBetween(cadence) : 0;
752
+ };
753
+
754
+ const scheduleBlink = () => {
755
+ const cadence = GROK_BLINK[s.preset.name];
756
+ blinkTimer = cadence ? randomBetween(cadence) : 0;
757
+ };
758
+
759
+ const onFrame = (delta, now) => {
760
+ if (disposed || s.paused || s.reducedMotion || !s.autoplay) return;
761
+
762
+ if (exprTimer > 0) {
763
+ exprTimer -= delta * 1000 * s.speed;
764
+ if (exprTimer <= 0) {
765
+ const pool = GROK_POOLS[s.preset.name] || [expression];
766
+ chooseExpression(pool[Math.floor(Math.random() * pool.length)]);
767
+ scheduleExpression();
768
+ }
769
+ }
770
+ if (blinkTimer > 0) {
771
+ blinkTimer -= delta * 1000 * s.speed;
772
+ if (blinkTimer <= 0) {
773
+ blinkStart = now;
774
+ scheduleBlink();
775
+ }
776
+ }
777
+ if (motionClass) {
778
+ if (motionUntil === 0) motionUntil = now + MOTION_MS / s.speed;
779
+ else if (now >= motionUntil) {
780
+ svg.classList.remove(`act-${motionClass}`);
781
+ motionClass = null;
782
+ }
783
+ }
784
+
785
+ const step = Math.min(delta * s.speed, 0.1);
786
+ velocity += (-14 * velocity - SPRING_STIFFNESS * (morph - 1)) * step;
787
+ morph += velocity * step;
788
+ if (!Number.isFinite(morph)) { morph = 1; velocity = 0; }
789
+ renderEyes(now);
790
+ };
791
+
792
+ const renderInitial = () => {
793
+ const pool = GROK_POOLS[s.preset.name] || [0];
794
+ setExpression(pool[0]);
795
+ renderEyes(0);
796
+ };
797
+
798
+ const onPointerMove = (event) => {
799
+ const rect = stage.getBoundingClientRect();
800
+ gazeX = clamp((event.clientX - rect.left) / rect.width * 2 - 1, -0.6, 0.6) * 22;
801
+ gazeY = clamp((event.clientY - rect.top) / rect.height * 2 - 1, -0.6, 0.6) * 14;
802
+ };
803
+ const onPointerLeave = () => { gazeX = 0; gazeY = 0; };
804
+ const onPointerDown = () => { blinkStart = performance.now(); };
805
+
806
+ const attachPointer = () => {
807
+ if (!s.interactive || disposed) return;
808
+ stage.addEventListener('pointermove', onPointerMove);
809
+ stage.addEventListener('pointerleave', onPointerLeave);
810
+ stage.addEventListener('pointerdown', onPointerDown);
811
+ detachPointer = () => {
812
+ stage.removeEventListener('pointermove', onPointerMove);
813
+ stage.removeEventListener('pointerleave', onPointerLeave);
814
+ stage.removeEventListener('pointerdown', onPointerDown);
815
+ detachPointer = null;
816
+ };
817
+ };
818
+
819
+ const setPointerAttached = (enabled) => {
820
+ if (enabled && !detachPointer) attachPointer();
821
+ else if (!enabled && detachPointer) detachPointer();
822
+ if (!enabled) { gazeX = 0; gazeY = 0; }
823
+ };
824
+
825
+ return {
826
+ get animation() { return svg; },
827
+ mount() {
828
+ applyBodyShape();
829
+ applyColors();
830
+ renderInitial();
831
+ applyBodyMotion();
832
+ scheduleExpression();
833
+ scheduleBlink();
834
+ visibility = createVisibilityGuard(stage, wakeScheduler);
835
+ unsubscribe = subscribeScheduler(onFrame, () => (
836
+ s.paused || s.reducedMotion || !s.autoplay || !visibility.isVisible()
837
+ ));
838
+ setPointerAttached(s.interactive);
839
+ emitter.emit('ready', { preset: { ...s.preset }, duration: null });
840
+ },
841
+ play() {
842
+ svg.style.animationPlayState = s.reducedMotion ? 'paused' : 'running';
843
+ wakeScheduler();
844
+ },
845
+ pause() {
846
+ svg.style.animationPlayState = 'paused';
847
+ },
848
+ stop() {
849
+ renderInitial();
850
+ this.pause();
851
+ },
852
+ setPaused(value) { return value ? this.pause() : this.play(); },
853
+ setSpeed() {
854
+ const className = motionClassFor(s.preset.name);
855
+ svg.style.animationDuration = `${MOTION_DURATIONS[className] / s.speed}s`;
856
+ motionUntil = 0;
857
+ },
858
+ setDirection() {},
859
+ setSegment() {},
860
+ setShape() { applyBodyShape(); },
861
+ setInteractive(value) { setPointerAttached(value === true); },
862
+ dispose() {
863
+ if (disposed) return;
864
+ disposed = true;
865
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
866
+ if (visibility) { visibility.dispose(); visibility = null; }
867
+ if (detachPointer) detachPointer();
868
+ svg.classList.remove(...MOTION_CLASSES);
869
+ svg.remove();
870
+ }
871
+ };
872
+ }
873
+
874
+ /**
875
+ * DLC-EMO public controller / facade.
876
+ *
877
+ * Owns the shared concerns (root/stage DOM, size, opacity, background, fit,
878
+ * type, name, lifecycle, emitter, reduced-motion, renderer creation and
879
+ * switching) and delegates the actual animation to a per-type renderer:
880
+ *
881
+ * miao → renderers/miao.js (Lottie + lottie-web)
882
+ * grok → renderers/grok.js (SVG Path Morph state machine)
883
+ *
884
+ * Structural changes (type/name/partColors/fit/renderer/loop) rebuild the
885
+ * current renderer; behavioral changes (speed/direction/segment/paused) are
886
+ * forwarded live. Grok-only concerns (shape/interactive) are no-ops for miao
887
+ * and vice versa (renderer/direction/segment are ignored by grok).
888
+ */
889
+
890
+
891
+ const SPEED_MIN = 0.1;
892
+ const SPEED_MAX = 4;
893
+
894
+ const RENDERER_FACTORIES = {
895
+ miao: createMiaoRenderer,
896
+ grok: createGrokRenderer
897
+ };
898
+
899
+ function normalizeSpeed(value) {
900
+ const number = Number(value);
901
+ if (!Number.isFinite(number)) return 1;
902
+ return Math.min(SPEED_MAX, Math.max(SPEED_MIN, number));
903
+ }
904
+
905
+ function normalizeOpacity(value) {
906
+ const number = Number(value);
907
+ if (!Number.isFinite(number)) return 1;
908
+ return Math.min(1, Math.max(0, number));
909
+ }
910
+
911
+ function normalizeDirection(value) {
912
+ return value === -1 || value === 'reverse' ? -1 : 1;
913
+ }
914
+
915
+ function normalizeRenderer(value) {
916
+ return value === 'canvas' ? 'canvas' : 'svg';
917
+ }
918
+
919
+ function normalizeFit(value) {
920
+ if (value === 'cover') return 'cover';
921
+ if (value === 'fill' || value === 'stretch' || value === 'none') return 'fill';
922
+ return 'contain';
923
+ }
924
+
925
+ function normalizeShape(value) {
926
+ const shapes = getEmoType('grok').shapes;
927
+ return shapes.includes(value) ? value : 'blob';
928
+ }
929
+
930
+ /** Mount an emo of the given type (miao | grok) into a container. */
931
+ function createEmo(container, options = {}) {
932
+ if (!container || typeof container.appendChild !== 'function') {
933
+ throw new Error('createEmo: container element is required');
934
+ }
935
+
936
+ let type = getEmoType(options.type || 'miao').type;
937
+ let name = options.name || getEmoType(type).defaultName;
938
+
939
+ const s = {
940
+ type,
941
+ name,
942
+ preset: getEmoPreset(type, name),
943
+ width: options.width === undefined ? 160 : options.width,
944
+ height: options.height === undefined ? 160 : options.height,
945
+ speed: normalizeSpeed(options.speed),
946
+ loop: options.loop !== false,
947
+ autoplay: options.autoplay !== false,
948
+ direction: normalizeDirection(options.direction),
949
+ opacity: normalizeOpacity(options.opacity),
950
+ fit: normalizeFit(options.fit),
951
+ renderer: normalizeRenderer(options.renderer),
952
+ paused: options.paused === true,
953
+ segment: null,
954
+ partColors: options.partColors && typeof options.partColors === 'object' ? { ...options.partColors } : {},
955
+ shape: normalizeShape(options.shape),
956
+ interactive: options.interactive === true,
957
+ background: options.background == null ? 'transparent' : String(options.background),
958
+ label: typeof options.label === 'string' && options.label ? options.label : null,
959
+ reducedMotion: false,
960
+ player: options.player,
961
+ instanceName: options.instanceName,
962
+ // 模块路径(Element 式):import { smile } from '@5even7/dlc-ui/emo/miao/smile'
963
+ // 后直接传入,数据同步可用;字符串路径(模板)不传,走内部按需加载。
964
+ animationData: options.animation && typeof options.animation === 'object' ? options.animation : null,
965
+ disposed: false
966
+ };
967
+ if (type === 'miao') s.segment = normalizeSegment(options.segment, s.preset);
968
+
969
+ let rendererImpl = null;
970
+ let mountToken = 0;
971
+ const emitter = createEmitter();
972
+
973
+ const root = document.createElement('div');
974
+ root.className = 'dlc-emo-root';
975
+ root.setAttribute('role', 'img');
976
+ const stage = document.createElement('div');
977
+ stage.className = 'dlc-emo-stage';
978
+ root.appendChild(stage);
979
+ container.appendChild(root);
980
+
981
+ const updateRoot = () => {
982
+ const effectiveRenderer = s.type === 'grok' ? 'svg' : s.renderer;
983
+ root.style.width = parseSize(s.width);
984
+ root.style.height = parseSize(s.height);
985
+ root.style.setProperty('--dlc-emo-opacity', String(s.opacity));
986
+ root.style.setProperty('--dlc-emo-background', s.background);
987
+ root.dataset.type = s.preset.type;
988
+ root.dataset.name = s.preset.name;
989
+ root.dataset.fit = s.fit;
990
+ root.dataset.renderer = effectiveRenderer;
991
+ root.dataset.paused = String(s.paused || s.reducedMotion);
992
+ root.setAttribute('aria-label', s.label || `${s.preset.label}表情动画`);
993
+ };
994
+
995
+ const destroyCurrent = () => {
996
+ if (rendererImpl) {
997
+ rendererImpl.dispose();
998
+ rendererImpl = null;
999
+ }
1000
+ };
1001
+
1002
+ /**
1003
+ * Rebuild the current renderer. Renderer factories may resolve asynchronously
1004
+ * (data loads on demand), so a mount token guards against stale renders:
1005
+ * a slower older mount can never replace a newer one, and its half-built
1006
+ * renderer is disposed instead.
1007
+ */
1008
+ const mount = async () => {
1009
+ destroyCurrent();
1010
+ if (s.disposed) return;
1011
+ s.preset = getEmoPreset(s.type, s.name);
1012
+ if (s.type === 'miao' && s.segment) s.segment = normalizeSegment(s.segment, s.preset);
1013
+ updateRoot();
1014
+ const token = ++mountToken;
1015
+ try {
1016
+ const impl = await RENDERER_FACTORIES[s.type]({ stage, s, emitter });
1017
+ if (s.disposed || token !== mountToken) {
1018
+ if (impl && typeof impl.dispose === 'function') impl.dispose();
1019
+ return;
1020
+ }
1021
+ rendererImpl = impl;
1022
+ impl.mount();
1023
+ } catch (error) {
1024
+ if (s.disposed || token !== mountToken) return;
1025
+ emitter.emit('error', { message: String(error && error.message ? error.message : error) });
1026
+ }
1027
+ };
1028
+
1029
+ const motionPreference = createReducedMotionPreference(options.respectReducedMotion !== false, (matches) => {
1030
+ s.reducedMotion = matches;
1031
+ if (s.disposed) return;
1032
+ updateRoot();
1033
+ if (!rendererImpl) return;
1034
+ if (s.paused || s.reducedMotion || !s.autoplay) rendererImpl.pause();
1035
+ else rendererImpl.play();
1036
+ });
1037
+ s.reducedMotion = motionPreference.matches();
1038
+
1039
+ updateRoot();
1040
+ mount();
1041
+
1042
+ return {
1043
+ element: root,
1044
+ get animation() { return rendererImpl ? rendererImpl.animation : null; },
1045
+ get preset() { return { ...s.preset }; },
1046
+ on: emitter.on,
1047
+ off: emitter.off,
1048
+ play() { s.paused = false; updateRoot(); if (rendererImpl && !s.reducedMotion) rendererImpl.play(); return this; },
1049
+ pause() { s.paused = true; root.dataset.paused = 'true'; if (rendererImpl) rendererImpl.pause(); return this; },
1050
+ stop() { s.paused = true; root.dataset.paused = 'true'; if (rendererImpl) rendererImpl.stop(); return this; },
1051
+ setPaused(value) { return value ? this.pause() : this.play(); },
1052
+ setSpeed(value) { s.speed = normalizeSpeed(value); if (rendererImpl) rendererImpl.setSpeed(s.speed); return this; },
1053
+ setDirection(value) {
1054
+ s.direction = normalizeDirection(value);
1055
+ if (rendererImpl) rendererImpl.setDirection(s.direction);
1056
+ return this;
1057
+ },
1058
+ setSegment(value) {
1059
+ if (s.type !== 'miao') return this;
1060
+ s.segment = normalizeSegment(value, s.preset);
1061
+ if (rendererImpl) rendererImpl.setSegment(s.segment);
1062
+ return this;
1063
+ },
1064
+ setName(value) {
1065
+ const nextName = String(value || '').trim().toLowerCase();
1066
+ getEmoPreset(s.type, nextName);
1067
+ s.name = nextName;
1068
+ mount();
1069
+ emitter.emit('namechange', { preset: { ...s.preset } });
1070
+ return this;
1071
+ },
1072
+ setType(value) {
1073
+ const nextType = getEmoType(value).type;
1074
+ s.type = nextType;
1075
+ if (!getEmoType(s.type).names.includes(s.name)) s.name = getEmoType(s.type).defaultName;
1076
+ mount();
1077
+ emitter.emit('typechange', { preset: { ...s.preset } });
1078
+ return this;
1079
+ },
1080
+ setPartColors(next) {
1081
+ s.partColors = next && typeof next === 'object' ? { ...next } : {};
1082
+ mount();
1083
+ return this;
1084
+ },
1085
+ setOpacity(value) { s.opacity = normalizeOpacity(value); updateRoot(); return this; },
1086
+ setBackground(value) { s.background = value == null ? 'transparent' : String(value); updateRoot(); return this; },
1087
+ setSize(nextWidth, nextHeight) {
1088
+ if (nextWidth !== undefined) { parseSize(nextWidth); s.width = nextWidth; }
1089
+ if (nextHeight !== undefined) { parseSize(nextHeight); s.height = nextHeight; }
1090
+ updateRoot();
1091
+ return this;
1092
+ },
1093
+ setFit(value) { s.fit = normalizeFit(value); mount(); return this; },
1094
+ setRenderer(value) {
1095
+ s.renderer = normalizeRenderer(value);
1096
+ if (s.type === 'miao') mount();
1097
+ else updateRoot();
1098
+ return this;
1099
+ },
1100
+ setLoop(value) { s.loop = value !== false; mount(); return this; },
1101
+ setAutoplay(value) {
1102
+ s.autoplay = value !== false;
1103
+ if (s.autoplay && !s.paused && !s.reducedMotion) this.play();
1104
+ else if (rendererImpl) rendererImpl.pause();
1105
+ return this;
1106
+ },
1107
+ setShape(value) {
1108
+ s.shape = normalizeShape(value);
1109
+ if (rendererImpl) rendererImpl.setShape(s.shape);
1110
+ return this;
1111
+ },
1112
+ setInteractive(value) {
1113
+ s.interactive = value === true;
1114
+ if (rendererImpl) rendererImpl.setInteractive(s.interactive);
1115
+ return this;
1116
+ },
1117
+ setLabel(value) { s.label = typeof value === 'string' && value ? value : null; updateRoot(); return this; },
1118
+ dispose() {
1119
+ s.disposed = true;
1120
+ motionPreference.dispose();
1121
+ destroyCurrent();
1122
+ root.remove();
1123
+ },
1124
+ get speed() { return s.speed; },
1125
+ get loop() { return s.loop; },
1126
+ get autoplay() { return s.autoplay; },
1127
+ get direction() { return s.direction; },
1128
+ get opacity() { return s.opacity; },
1129
+ get fit() { return s.fit; },
1130
+ get renderer() { return s.type === 'grok' ? 'svg' : s.renderer; },
1131
+ get paused() { return s.paused; },
1132
+ get segment() { return s.segment ? [...s.segment] : null; },
1133
+ get partColors() { return { ...s.partColors }; },
1134
+ get shape() { return s.shape; },
1135
+ get interactive() { return s.interactive; },
1136
+ get background() { return s.background; }
1137
+ };
1138
+ }
1139
+
1140
+ export { EMO_CATEGORIES as E, GROK_CATEGORIES as G, EMO_PRESETS as a, EMO_TYPES as b, GROK_NAMES as c, GROK_STATE_META as d, createEmo as e, getEmoAnimationMeta as f, getEmoAnimation as g, getEmoPreset as h, getEmoType as i, getGrokNamesFor as j, getGrokStateMeta as k };