@lemoncat7/dsh-theme-xiaohei 0.3.0-alpha.22

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 (164) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/cordis.patch.yml +4 -0
  4. package/lib/appearance.d.ts +12 -0
  5. package/lib/appearance.d.ts.map +1 -0
  6. package/lib/appearance.js +26 -0
  7. package/lib/appearance.js.map +1 -0
  8. package/lib/blink.d.ts +4 -0
  9. package/lib/blink.d.ts.map +1 -0
  10. package/lib/blink.js +110 -0
  11. package/lib/blink.js.map +1 -0
  12. package/lib/boot-appearance.d.ts +10 -0
  13. package/lib/boot-appearance.d.ts.map +1 -0
  14. package/lib/boot-appearance.js +47 -0
  15. package/lib/boot-appearance.js.map +1 -0
  16. package/lib/boot-loader.d.ts +5 -0
  17. package/lib/boot-loader.d.ts.map +1 -0
  18. package/lib/boot-loader.js +158 -0
  19. package/lib/boot-loader.js.map +1 -0
  20. package/lib/chrome/accessibility.d.ts +3 -0
  21. package/lib/chrome/accessibility.d.ts.map +1 -0
  22. package/lib/chrome/accessibility.js +77 -0
  23. package/lib/chrome/accessibility.js.map +1 -0
  24. package/lib/chrome/blink.d.ts +3 -0
  25. package/lib/chrome/blink.d.ts.map +1 -0
  26. package/lib/chrome/blink.js +15 -0
  27. package/lib/chrome/blink.js.map +1 -0
  28. package/lib/chrome/composer.d.ts +3 -0
  29. package/lib/chrome/composer.d.ts.map +1 -0
  30. package/lib/chrome/composer.js +146 -0
  31. package/lib/chrome/composer.js.map +1 -0
  32. package/lib/chrome/conversation-messages.d.ts +3 -0
  33. package/lib/chrome/conversation-messages.d.ts.map +1 -0
  34. package/lib/chrome/conversation-messages.js +96 -0
  35. package/lib/chrome/conversation-messages.js.map +1 -0
  36. package/lib/chrome/conversation.d.ts +3 -0
  37. package/lib/chrome/conversation.d.ts.map +1 -0
  38. package/lib/chrome/conversation.js +61 -0
  39. package/lib/chrome/conversation.js.map +1 -0
  40. package/lib/chrome/frames.d.ts +6 -0
  41. package/lib/chrome/frames.d.ts.map +1 -0
  42. package/lib/chrome/frames.js +120 -0
  43. package/lib/chrome/frames.js.map +1 -0
  44. package/lib/chrome/gaze.d.ts +3 -0
  45. package/lib/chrome/gaze.d.ts.map +1 -0
  46. package/lib/chrome/gaze.js +103 -0
  47. package/lib/chrome/gaze.js.map +1 -0
  48. package/lib/chrome/identity.d.ts +6 -0
  49. package/lib/chrome/identity.d.ts.map +1 -0
  50. package/lib/chrome/identity.js +61 -0
  51. package/lib/chrome/identity.js.map +1 -0
  52. package/lib/chrome/overlays.d.ts +3 -0
  53. package/lib/chrome/overlays.d.ts.map +1 -0
  54. package/lib/chrome/overlays.js +104 -0
  55. package/lib/chrome/overlays.js.map +1 -0
  56. package/lib/chrome/portal.d.ts +6 -0
  57. package/lib/chrome/portal.d.ts.map +1 -0
  58. package/lib/chrome/portal.js +169 -0
  59. package/lib/chrome/portal.js.map +1 -0
  60. package/lib/chrome/reactions.d.ts +3 -0
  61. package/lib/chrome/reactions.d.ts.map +1 -0
  62. package/lib/chrome/reactions.js +85 -0
  63. package/lib/chrome/reactions.js.map +1 -0
  64. package/lib/chrome/sidebar.d.ts +3 -0
  65. package/lib/chrome/sidebar.d.ts.map +1 -0
  66. package/lib/chrome/sidebar.js +305 -0
  67. package/lib/chrome/sidebar.js.map +1 -0
  68. package/lib/chrome/tokens.d.ts +3 -0
  69. package/lib/chrome/tokens.d.ts.map +1 -0
  70. package/lib/chrome/tokens.js +171 -0
  71. package/lib/chrome/tokens.js.map +1 -0
  72. package/lib/chrome/workspace.d.ts +3 -0
  73. package/lib/chrome/workspace.d.ts.map +1 -0
  74. package/lib/chrome/workspace.js +313 -0
  75. package/lib/chrome/workspace.js.map +1 -0
  76. package/lib/chrome.d.ts +10 -0
  77. package/lib/chrome.d.ts.map +1 -0
  78. package/lib/chrome.js +40 -0
  79. package/lib/chrome.js.map +1 -0
  80. package/lib/client.d.ts +17 -0
  81. package/lib/client.d.ts.map +1 -0
  82. package/lib/client.js +5505 -0
  83. package/lib/client.js.map +7 -0
  84. package/lib/gaze.d.ts +4 -0
  85. package/lib/gaze.d.ts.map +1 -0
  86. package/lib/gaze.js +217 -0
  87. package/lib/gaze.js.map +1 -0
  88. package/lib/generated-identity.d.ts +5 -0
  89. package/lib/generated-identity.d.ts.map +1 -0
  90. package/lib/generated-identity.js +5 -0
  91. package/lib/generated-identity.js.map +1 -0
  92. package/lib/generated-keyart.d.ts +19 -0
  93. package/lib/generated-keyart.d.ts.map +1 -0
  94. package/lib/generated-keyart.js +19 -0
  95. package/lib/generated-keyart.js.map +1 -0
  96. package/lib/generated-loading-assets.d.ts +4 -0
  97. package/lib/generated-loading-assets.d.ts.map +1 -0
  98. package/lib/generated-loading-assets.js +4 -0
  99. package/lib/generated-loading-assets.js.map +1 -0
  100. package/lib/generated-sidebar-assets.d.ts +4 -0
  101. package/lib/generated-sidebar-assets.d.ts.map +1 -0
  102. package/lib/generated-sidebar-assets.js +4 -0
  103. package/lib/generated-sidebar-assets.js.map +1 -0
  104. package/lib/heixiu-interactions.d.ts +10 -0
  105. package/lib/heixiu-interactions.d.ts.map +1 -0
  106. package/lib/heixiu-interactions.js +161 -0
  107. package/lib/heixiu-interactions.js.map +1 -0
  108. package/lib/index.d.ts +8 -0
  109. package/lib/index.d.ts.map +1 -0
  110. package/lib/index.js +11 -0
  111. package/lib/index.js.map +1 -0
  112. package/lib/loading-heixiu.d.ts +8 -0
  113. package/lib/loading-heixiu.d.ts.map +1 -0
  114. package/lib/loading-heixiu.js +287 -0
  115. package/lib/loading-heixiu.js.map +1 -0
  116. package/lib/plugin.d.ts +6 -0
  117. package/lib/plugin.d.ts.map +1 -0
  118. package/lib/plugin.js +38 -0
  119. package/lib/plugin.js.map +1 -0
  120. package/lib/portal.d.ts +40 -0
  121. package/lib/portal.d.ts.map +1 -0
  122. package/lib/portal.js +224 -0
  123. package/lib/portal.js.map +1 -0
  124. package/lib/reactions.d.ts +20 -0
  125. package/lib/reactions.d.ts.map +1 -0
  126. package/lib/reactions.js +380 -0
  127. package/lib/reactions.js.map +1 -0
  128. package/lib/scene/heixiu-feedback.d.ts +3 -0
  129. package/lib/scene/heixiu-feedback.d.ts.map +1 -0
  130. package/lib/scene/heixiu-feedback.js +81 -0
  131. package/lib/scene/heixiu-feedback.js.map +1 -0
  132. package/lib/scene/heixiu-interactions.d.ts +3 -0
  133. package/lib/scene/heixiu-interactions.d.ts.map +1 -0
  134. package/lib/scene/heixiu-interactions.js +92 -0
  135. package/lib/scene/heixiu-interactions.js.map +1 -0
  136. package/lib/scene/state-transitions.d.ts +3 -0
  137. package/lib/scene/state-transitions.d.ts.map +1 -0
  138. package/lib/scene/state-transitions.js +37 -0
  139. package/lib/scene/state-transitions.js.map +1 -0
  140. package/lib/scene.d.ts +14 -0
  141. package/lib/scene.d.ts.map +1 -0
  142. package/lib/scene.js +1024 -0
  143. package/lib/scene.js.map +1 -0
  144. package/lib/sidebar-glass.d.ts +16 -0
  145. package/lib/sidebar-glass.d.ts.map +1 -0
  146. package/lib/sidebar-glass.js +105 -0
  147. package/lib/sidebar-glass.js.map +1 -0
  148. package/lib/sidebar-heixiu-escape.d.ts +44 -0
  149. package/lib/sidebar-heixiu-escape.d.ts.map +1 -0
  150. package/lib/sidebar-heixiu-escape.js +340 -0
  151. package/lib/sidebar-heixiu-escape.js.map +1 -0
  152. package/lib/sidebar-heixiu-roaming.d.ts +27 -0
  153. package/lib/sidebar-heixiu-roaming.d.ts.map +1 -0
  154. package/lib/sidebar-heixiu-roaming.js +310 -0
  155. package/lib/sidebar-heixiu-roaming.js.map +1 -0
  156. package/lib/state.d.ts +9 -0
  157. package/lib/state.d.ts.map +1 -0
  158. package/lib/state.js +114 -0
  159. package/lib/state.js.map +1 -0
  160. package/lib/theme.d.ts +19 -0
  161. package/lib/theme.d.ts.map +1 -0
  162. package/lib/theme.js +188 -0
  163. package/lib/theme.js.map +1 -0
  164. package/package.json +74 -0
package/lib/scene.js ADDED
@@ -0,0 +1,1024 @@
1
+ import { XIAOHEI_COMPLETE, XIAOHEI_DAWN_KEY_ART, XIAOHEI_THINKING, XIAOHEI_ERROR, XIAOHEI_HEIXIU_BLINK, XIAOHEI_HEIXIU_OPEN, XIAOHEI_IDLE_BLINK, XIAOHEI_IDLE_SHEET, XIAOHEI_NIGHT_KEY_ART, XIAOHEI_STREAMING, XIAOHEI_TOOL, XIAOHEI_WAITING, } from './generated-keyart.js';
2
+ import { XIAOHEI_HEIXIU_FEEDBACK_CSS } from './scene/heixiu-feedback.js';
3
+ import { XIAOHEI_HEIXIU_INTERACTION_CSS } from './scene/heixiu-interactions.js';
4
+ import { XIAOHEI_STATE_TRANSITION_CSS } from './scene/state-transitions.js';
5
+ /** DOM ids are exported so lifecycle and browser tests can detect leaks. */
6
+ export const XIAOHEI_SCENE_STYLE_ID = 'dsh-theme-xiaohei/scene-style';
7
+ export const XIAOHEI_SCENE_LAYER_ID = 'dsh-theme-xiaohei/scene-layer';
8
+ /**
9
+ * The generated key art is a real raster asset. CSS supplies only atmosphere
10
+ * and motion, never a shape-built substitute for the character.
11
+ */
12
+ const XIAOHEI_SCENE_BASE_CSS = `
13
+ body {
14
+ background: #151C1E;
15
+ }
16
+
17
+ html[data-xiaohei-appearance='light'] body {
18
+ background: #E5EBF1;
19
+ }
20
+
21
+ #root {
22
+ position: relative;
23
+ z-index: 1;
24
+ }
25
+
26
+ #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} {
27
+ position: fixed;
28
+ inset: 0;
29
+ z-index: 0;
30
+ overflow: hidden;
31
+ contain: strict;
32
+ isolation: isolate;
33
+ pointer-events: none;
34
+ user-select: none;
35
+ background: #151C1E;
36
+ }
37
+
38
+ html[data-xiaohei-appearance='light'] #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} {
39
+ background:
40
+ radial-gradient(80% 64% at 16% 8%, rgb(248 250 252 / 82%), transparent 72%),
41
+ radial-gradient(70% 58% at 86% 88%, rgb(207 220 230 / 48%), transparent 76%),
42
+ #E5EBF1;
43
+ }
44
+
45
+ #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} > * {
46
+ position: absolute;
47
+ display: block;
48
+ pointer-events: none;
49
+ }
50
+
51
+ .xiaohei-scene__keyart {
52
+ inset: 0;
53
+ width: 100%;
54
+ height: 100%;
55
+ max-width: none;
56
+ object-fit: cover;
57
+ object-position: center bottom;
58
+ transform: scale(1.002);
59
+ filter: blur(0.55px) saturate(96%) contrast(98%);
60
+ transition: opacity 320ms ease-out;
61
+ }
62
+
63
+ .xiaohei-scene__keyart--night {
64
+ opacity: 0.98;
65
+ }
66
+
67
+ .xiaohei-scene__keyart--dawn {
68
+ opacity: 0;
69
+ }
70
+
71
+ @media (max-aspect-ratio: 4 / 3) {
72
+ .xiaohei-scene__keyart {
73
+ object-position: 66% bottom;
74
+ }
75
+ }
76
+
77
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night {
78
+ opacity: 0;
79
+ }
80
+
81
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn {
82
+ opacity: 0.98;
83
+ }
84
+
85
+ .xiaohei-scene__veil {
86
+ inset: 0;
87
+ background:
88
+ linear-gradient(90deg, rgb(8 13 15 / 4%) 0%, transparent 48%, rgb(8 13 15 / 4%) 100%),
89
+ linear-gradient(180deg, rgb(8 13 15 / 2%) 0%, transparent 58%, rgb(8 13 15 / 4%) 100%);
90
+ }
91
+
92
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__veil {
93
+ background:
94
+ linear-gradient(90deg, rgb(58 74 88 / 3%) 0%, transparent 48%, rgb(58 74 88 / 4%) 100%),
95
+ linear-gradient(180deg, rgb(255 255 255 / 10%) 0%, transparent 54%, rgb(74 91 105 / 5%) 100%);
96
+ }
97
+
98
+ .xiaohei-scene__spirit {
99
+ width: 0.58rem;
100
+ aspect-ratio: 1;
101
+ border-radius: 50%;
102
+ background: #8BE5D5;
103
+ box-shadow: 0 0 0.7rem rgb(117 228 208 / 88%), 0 0 1.8rem rgb(101 209 190 / 56%);
104
+ mix-blend-mode: screen;
105
+ opacity: 0.18;
106
+ will-change: transform, opacity;
107
+ }
108
+
109
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__spirit {
110
+ background: #4D927C;
111
+ box-shadow: 0 0 0.45rem rgb(67 133 111 / 54%), 0 0 1.4rem rgb(106 151 132 / 28%);
112
+ mix-blend-mode: multiply;
113
+ }
114
+
115
+ .xiaohei-scene__spirit--one {
116
+ right: 22%;
117
+ bottom: 20%;
118
+ animation: xiaohei-spirit-one 6.8s cubic-bezier(0.37, 0, 0.63, 1) infinite;
119
+ }
120
+
121
+ .xiaohei-scene__spirit--two {
122
+ right: 34%;
123
+ bottom: 30%;
124
+ animation: xiaohei-spirit-two 8.4s cubic-bezier(0.37, 0, 0.63, 1) -2.2s infinite;
125
+ }
126
+
127
+ .xiaohei-scene__spirit--three {
128
+ right: 13%;
129
+ bottom: 45%;
130
+ animation: xiaohei-spirit-three 7.7s cubic-bezier(0.37, 0, 0.63, 1) -4.1s infinite;
131
+ }
132
+
133
+ .xiaohei-scene__mascot {
134
+ right: clamp(4.5rem, 8vw, 9rem);
135
+ bottom: clamp(5rem, 10vh, 7rem);
136
+ width: clamp(11.5rem, 19vw, 19rem);
137
+ aspect-ratio: 1;
138
+ overflow: visible;
139
+ isolation: isolate;
140
+ filter:
141
+ drop-shadow(0 0.6rem 1.45rem rgb(83 218 193 / 35%))
142
+ drop-shadow(0 1.25rem 2.6rem rgb(1 9 10 / 30%));
143
+ }
144
+
145
+ .xiaohei-scene__mascot-idle-viewport {
146
+ position: absolute;
147
+ inset: 0;
148
+ z-index: 1;
149
+ overflow: hidden;
150
+ pointer-events: none;
151
+ }
152
+
153
+ .xiaohei-scene__mascot::before {
154
+ content: '';
155
+ position: absolute;
156
+ z-index: 0;
157
+ inset: 4%;
158
+ border-radius: 50%;
159
+ background: radial-gradient(
160
+ circle at 50% 55%,
161
+ rgb(190 255 242 / 68%) 0%,
162
+ rgb(90 228 202 / 48%) 38%,
163
+ rgb(34 144 132 / 18%) 58%,
164
+ transparent 74%
165
+ );
166
+ opacity: 0.66;
167
+ }
168
+
169
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot {
170
+ filter:
171
+ drop-shadow(0 0.55rem 0.9rem rgb(40 58 51 / 22%))
172
+ drop-shadow(0 1.15rem 2.2rem rgb(45 64 56 / 14%));
173
+ }
174
+
175
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot::before {
176
+ background: radial-gradient(
177
+ circle at 50% 58%,
178
+ rgb(236 242 230 / 72%) 0%,
179
+ rgb(198 219 202 / 34%) 40%,
180
+ transparent 72%
181
+ );
182
+ opacity: 0.42;
183
+ }
184
+
185
+ .xiaohei-scene__heixiu-field {
186
+ inset: 0;
187
+ overflow: hidden;
188
+ }
189
+
190
+ .xiaohei-scene__heixiu {
191
+ position: absolute;
192
+ display: block;
193
+ aspect-ratio: 1;
194
+ opacity: var(--heixiu-opacity, 0.58);
195
+ filter:
196
+ drop-shadow(0 0.32rem 0.58rem rgb(109 233 211 / 18%))
197
+ drop-shadow(0 0.68rem 1.15rem rgb(1 9 10 / 20%));
198
+ will-change: transform;
199
+ }
200
+
201
+ #root [data-slot='sidebar'] > div,
202
+ #root [data-slot='conversation.composer.bar'] > div {
203
+ position: relative !important;
204
+ }
205
+
206
+ .xiaohei-scene__heixiu-body > img {
207
+ position: absolute;
208
+ display: block;
209
+ inset: 0;
210
+ width: 100%;
211
+ height: 100%;
212
+ max-width: none;
213
+ max-height: none;
214
+ object-fit: contain;
215
+ filter: brightness(1.12) contrast(1.04) saturate(0.82);
216
+ }
217
+
218
+ .xiaohei-scene__heixiu-open {
219
+ opacity: 1;
220
+ will-change: opacity;
221
+ animation: xiaohei-heixiu-open var(--heixiu-blink-duration, 7.6s) step-end var(--heixiu-blink-delay, 0s) infinite;
222
+ }
223
+
224
+ .xiaohei-scene__heixiu-blink {
225
+ opacity: 0;
226
+ will-change: opacity;
227
+ animation: xiaohei-heixiu-blink var(--heixiu-blink-duration, 7.6s) step-end var(--heixiu-blink-delay, 0s) infinite;
228
+ }
229
+
230
+ .xiaohei-scene__heixiu--mascot {
231
+ right: clamp(19rem, 25vw, 30rem);
232
+ bottom: clamp(9.5rem, 16vh, 13rem);
233
+ width: clamp(4.2rem, 5.4vw, 5.5rem);
234
+ --heixiu-opacity: 0.72;
235
+ --heixiu-blink-duration: 7.2s;
236
+ --heixiu-blink-delay: -1.1s;
237
+ animation: xiaohei-heixiu-drift-one 13.6s cubic-bezier(0.37, 0, 0.63, 1) infinite;
238
+ }
239
+
240
+ .xiaohei-scene__heixiu--sidebar {
241
+ z-index: 6;
242
+ left: 7.15rem;
243
+ right: auto;
244
+ top: 8.05rem;
245
+ width: 2.5rem;
246
+ --heixiu-opacity: 0.76;
247
+ --heixiu-blink-duration: 8.9s;
248
+ --heixiu-blink-delay: -4.7s;
249
+ animation: xiaohei-heixiu-drift-two 16.2s cubic-bezier(0.37, 0, 0.63, 1) -5.2s infinite;
250
+ }
251
+
252
+ .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body > img {
253
+ filter: brightness(1.18) contrast(1.09) saturate(0.86);
254
+ }
255
+
256
+ .xiaohei-scene__heixiu--composer {
257
+ z-index: 3;
258
+ left: 54%;
259
+ right: auto;
260
+ top: -1.7rem;
261
+ width: 3.45rem;
262
+ --heixiu-opacity: 0.6;
263
+ --heixiu-blink-duration: 9.4s;
264
+ --heixiu-blink-delay: -6.2s;
265
+ animation: xiaohei-heixiu-drift-three 17.2s cubic-bezier(0.37, 0, 0.63, 1) -8.1s infinite;
266
+ }
267
+
268
+ .xiaohei-scene__heixiu--sidebar::before,
269
+ .xiaohei-scene__heixiu--composer::before {
270
+ content: '';
271
+ position: absolute;
272
+ z-index: -1;
273
+ left: 50%;
274
+ top: -0.72rem;
275
+ width: 1px;
276
+ height: 0.85rem;
277
+ background: linear-gradient(180deg, transparent, var(--xiaohei-frame-line-strong));
278
+ box-shadow: 0 0 0.35rem var(--xiaohei-focus-shadow);
279
+ transform: translateX(-50%);
280
+ }
281
+
282
+ #root [data-slot='sidebar'] > div[class*='_collapsed'] .xiaohei-scene__heixiu--sidebar {
283
+ display: none;
284
+ }
285
+
286
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu {
287
+ filter:
288
+ drop-shadow(0 0.28rem 0.5rem rgb(52 83 71 / 13%))
289
+ drop-shadow(0 0.62rem 1rem rgb(45 64 56 / 10%));
290
+ }
291
+
292
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu-body > img {
293
+ filter: brightness(1.02) contrast(1.05) saturate(0.74);
294
+ }
295
+
296
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body > img {
297
+ filter: brightness(1.03) contrast(1.1) saturate(0.78);
298
+ }
299
+
300
+ .xiaohei-scene__mascot-sheet {
301
+ position: absolute;
302
+ display: block;
303
+ inset: 0 auto auto 0;
304
+ width: 400%;
305
+ height: 200%;
306
+ max-width: none;
307
+ max-height: none;
308
+ object-fit: fill;
309
+ transform: translate3d(0, 0, 0);
310
+ opacity: 0;
311
+ z-index: 1;
312
+ filter: brightness(1.32) contrast(1.02) saturate(1.04);
313
+ }
314
+
315
+ .xiaohei-scene__mascot-sheet--open {
316
+ opacity: 1;
317
+ transition: opacity 120ms ease-out;
318
+ }
319
+
320
+ .xiaohei-scene__mascot-blink {
321
+ position: absolute;
322
+ display: block;
323
+ inset: 0;
324
+ width: 100%;
325
+ height: 100%;
326
+ max-width: none;
327
+ max-height: none;
328
+ object-fit: contain;
329
+ opacity: 0;
330
+ z-index: 3;
331
+ filter: brightness(1.32) contrast(1.02) saturate(1.04);
332
+ will-change: opacity;
333
+ }
334
+
335
+ .xiaohei-scene__mascot-state {
336
+ position: absolute;
337
+ display: block;
338
+ left: 50%;
339
+ bottom: 0;
340
+ width: 100%;
341
+ height: auto;
342
+ max-width: none;
343
+ max-height: none;
344
+ object-fit: contain;
345
+ opacity: 0;
346
+ z-index: 1;
347
+ filter: brightness(1.32) contrast(1.02) saturate(1.04);
348
+ transform: translateX(-50%);
349
+ transform-origin: 50% 100%;
350
+ transition: opacity 120ms ease-out;
351
+ }
352
+
353
+ .xiaohei-scene__mascot-state--thinking {
354
+ filter: brightness(1.34) contrast(1.02) saturate(1.03);
355
+ }
356
+
357
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-sheet,
358
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-blink,
359
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-state {
360
+ filter: brightness(1.02) contrast(1.07) saturate(0.9);
361
+ }
362
+
363
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-state--thinking {
364
+ filter: brightness(1.04) contrast(1.06) saturate(0.91);
365
+ }
366
+
367
+ html:not([data-xiaohei-state='idle']) .xiaohei-scene__mascot-sheet--open {
368
+ opacity: 0;
369
+ }
370
+
371
+ html:not([data-xiaohei-state='idle']) .xiaohei-scene__mascot-blink {
372
+ opacity: 0;
373
+ animation: none;
374
+ }
375
+
376
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__mascot-state--thinking,
377
+ html[data-xiaohei-state='streaming'] .xiaohei-scene__mascot-state--streaming,
378
+ html[data-xiaohei-state='tool'] .xiaohei-scene__mascot-state--tool,
379
+ html[data-xiaohei-state='waiting'] .xiaohei-scene__mascot-state--waiting,
380
+ html[data-xiaohei-state='complete'] .xiaohei-scene__mascot-state--complete,
381
+ html[data-xiaohei-state='error'] .xiaohei-scene__mascot-state--error {
382
+ opacity: 1;
383
+ }
384
+
385
+ .xiaohei-scene__thinking-fx,
386
+ .xiaohei-scene__thinking-bubble,
387
+ .xiaohei-scene__thinking-dot {
388
+ position: absolute;
389
+ display: block;
390
+ pointer-events: none;
391
+ }
392
+
393
+ .xiaohei-scene__thinking-fx {
394
+ inset: 0;
395
+ z-index: 3;
396
+ opacity: 0;
397
+ transition: opacity 160ms ease-out;
398
+ }
399
+
400
+ .xiaohei-scene__thinking-bubble {
401
+ left: 56%;
402
+ top: -4%;
403
+ width: 36%;
404
+ height: 18%;
405
+ border: 1px solid rgb(210 242 235 / 44%);
406
+ border-radius: 999px;
407
+ background: rgb(226 242 238 / 88%);
408
+ box-shadow:
409
+ 0 0.45rem 1.15rem rgb(1 9 10 / 18%),
410
+ inset 0 1px rgb(255 255 255 / 68%);
411
+ }
412
+
413
+ .xiaohei-scene__thinking-bubble::before,
414
+ .xiaohei-scene__thinking-bubble::after {
415
+ position: absolute;
416
+ display: block;
417
+ content: '';
418
+ aspect-ratio: 1;
419
+ border-radius: 50%;
420
+ background: inherit;
421
+ box-shadow: inherit;
422
+ }
423
+
424
+ .xiaohei-scene__thinking-bubble::before {
425
+ left: 12%;
426
+ bottom: -31%;
427
+ width: 15%;
428
+ }
429
+
430
+ .xiaohei-scene__thinking-bubble::after {
431
+ left: 2%;
432
+ bottom: -51%;
433
+ width: 8%;
434
+ }
435
+
436
+ .xiaohei-scene__thinking-dot {
437
+ top: 50%;
438
+ width: 9%;
439
+ aspect-ratio: 1;
440
+ border-radius: 50%;
441
+ background: #526B66;
442
+ opacity: 0.28;
443
+ transform: translateY(-50%);
444
+ }
445
+
446
+ .xiaohei-scene__thinking-dot--one { left: 25%; }
447
+ .xiaohei-scene__thinking-dot--two { left: 46%; }
448
+ .xiaohei-scene__thinking-dot--three { left: 67%; }
449
+
450
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-fx {
451
+ opacity: 1;
452
+ }
453
+
454
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--one {
455
+ animation: xiaohei-thinking-dot 1.8s ease-in-out infinite;
456
+ }
457
+
458
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--two {
459
+ animation: xiaohei-thinking-dot 1.8s ease-in-out 0.3s infinite;
460
+ }
461
+
462
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--three {
463
+ animation: xiaohei-thinking-dot 1.8s ease-in-out 0.6s infinite;
464
+ }
465
+
466
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__thinking-bubble {
467
+ border-color: rgb(46 94 83 / 20%);
468
+ background: rgb(247 250 247 / 92%);
469
+ box-shadow:
470
+ 0 0.45rem 1.1rem rgb(44 73 60 / 12%),
471
+ inset 0 1px rgb(255 255 255 / 86%);
472
+ }
473
+
474
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__thinking-dot {
475
+ background: #45635C;
476
+ }
477
+
478
+ .xiaohei-scene__state-fx,
479
+ .xiaohei-scene__state-fx > span {
480
+ position: absolute;
481
+ display: block;
482
+ pointer-events: none;
483
+ }
484
+
485
+ .xiaohei-scene__state-fx {
486
+ inset: 0;
487
+ z-index: 2;
488
+ opacity: 0;
489
+ transition: opacity 120ms ease-out;
490
+ }
491
+
492
+ .xiaohei-scene__state-fx > span {
493
+ border-radius: 50%;
494
+ opacity: 0;
495
+ will-change: transform, opacity;
496
+ }
497
+
498
+ html[data-xiaohei-state='streaming'] .xiaohei-scene__state-fx--streaming,
499
+ html[data-xiaohei-state='tool'] .xiaohei-scene__state-fx--tool,
500
+ html[data-xiaohei-state='waiting'] .xiaohei-scene__state-fx--waiting,
501
+ html[data-xiaohei-state='complete'] .xiaohei-scene__state-fx--complete,
502
+ html[data-xiaohei-state='error'] .xiaohei-scene__state-fx--error {
503
+ opacity: 1;
504
+ }
505
+
506
+ .xiaohei-scene__tail-write {
507
+ left: var(--tail-write-left);
508
+ top: var(--tail-write-top);
509
+ width: var(--tail-write-width);
510
+ height: 7%;
511
+ border-top: 2px solid #A8FFEB;
512
+ border-radius: 50%;
513
+ filter: drop-shadow(0 0 0.34rem rgb(91 255 219 / 78%));
514
+ transform: rotate(var(--tail-write-angle)) scaleX(0.08);
515
+ transform-origin: 100% 50%;
516
+ }
517
+
518
+ .xiaohei-scene__tail-write--one {
519
+ --tail-write-left: 67%;
520
+ --tail-write-top: 34%;
521
+ --tail-write-width: 16%;
522
+ --tail-write-angle: -18deg;
523
+ }
524
+
525
+ .xiaohei-scene__tail-write--two {
526
+ --tail-write-left: 59%;
527
+ --tail-write-top: 27%;
528
+ --tail-write-width: 19%;
529
+ --tail-write-angle: -12deg;
530
+ }
531
+
532
+ .xiaohei-scene__tail-write--three {
533
+ --tail-write-left: 50%;
534
+ --tail-write-top: 21%;
535
+ --tail-write-width: 21%;
536
+ --tail-write-angle: -6deg;
537
+ }
538
+
539
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__tail-write {
540
+ border-top-color: #2F8576;
541
+ filter: drop-shadow(0 0 0.28rem rgb(47 133 118 / 34%));
542
+ }
543
+
544
+ html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--one {
545
+ animation: xiaohei-tail-write 1.9s ease-in-out infinite;
546
+ }
547
+
548
+ html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--two {
549
+ animation: xiaohei-tail-write 1.9s ease-in-out 0.3s infinite;
550
+ }
551
+
552
+ html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--three {
553
+ animation: xiaohei-tail-write 1.9s ease-in-out 0.6s infinite;
554
+ }
555
+
556
+ .xiaohei-scene__tool-key {
557
+ top: 84%;
558
+ width: 0.3rem;
559
+ aspect-ratio: 0.7;
560
+ background: #70F2D9;
561
+ box-shadow: 0 0 0.7rem rgb(72 238 208 / 90%);
562
+ }
563
+
564
+ .xiaohei-scene__tool-key--one { left: 29%; }
565
+ .xiaohei-scene__tool-key--two { left: 38%; }
566
+ .xiaohei-scene__tool-key--three { left: 47%; }
567
+
568
+ html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--one {
569
+ animation: xiaohei-tool-key 0.9s ease-in-out infinite;
570
+ }
571
+
572
+ html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--two {
573
+ animation: xiaohei-tool-key 0.9s ease-in-out -0.3s infinite;
574
+ }
575
+
576
+ html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--three {
577
+ animation: xiaohei-tool-key 0.9s ease-in-out -0.6s infinite;
578
+ }
579
+
580
+ .xiaohei-scene__waiting-ring {
581
+ left: 61%;
582
+ top: 34%;
583
+ width: 13%;
584
+ aspect-ratio: 1;
585
+ border: 1px solid rgb(255 207 126 / 88%);
586
+ box-shadow: 0 0 0.8rem rgb(255 188 93 / 42%);
587
+ }
588
+
589
+ html[data-xiaohei-state='waiting'] .xiaohei-scene__waiting-ring {
590
+ animation: xiaohei-waiting-ring 1.8s ease-out infinite;
591
+ }
592
+
593
+ .xiaohei-scene__complete-spark {
594
+ width: 0.35rem;
595
+ aspect-ratio: 1;
596
+ background: #B6FFED;
597
+ box-shadow: 0 0 0.8rem rgb(91 255 219 / 92%);
598
+ }
599
+
600
+ .xiaohei-scene__complete-spark--one { left: 36%; top: 70%; }
601
+ .xiaohei-scene__complete-spark--two { left: 62%; top: 67%; }
602
+
603
+ html[data-xiaohei-state='complete'] .xiaohei-scene__complete-spark--one {
604
+ animation: xiaohei-complete-spark-one 0.8s ease-out infinite;
605
+ }
606
+
607
+ html[data-xiaohei-state='complete'] .xiaohei-scene__complete-spark--two {
608
+ animation: xiaohei-complete-spark-two 0.8s ease-out -0.4s infinite;
609
+ }
610
+
611
+ .xiaohei-scene__error-glow {
612
+ left: 41%;
613
+ top: 82%;
614
+ width: 7%;
615
+ aspect-ratio: 1;
616
+ background: radial-gradient(circle, rgb(255 112 82 / 90%) 0%, rgb(224 58 46 / 28%) 48%, transparent 72%);
617
+ mix-blend-mode: screen;
618
+ }
619
+
620
+ html[data-xiaohei-state='error'] .xiaohei-scene__error-glow {
621
+ animation: xiaohei-error-glow 2.2s ease-in-out infinite;
622
+ }
623
+
624
+ @keyframes xiaohei-heixiu-blink {
625
+ 0%, 87.9% { opacity: 0; }
626
+ 88%, 90.4% { opacity: 1; }
627
+ 90.5%, 100% { opacity: 0; }
628
+ }
629
+
630
+ @keyframes xiaohei-heixiu-open {
631
+ 0%, 87.9% { opacity: 1; }
632
+ 88%, 90.4% { opacity: 0; }
633
+ 90.5%, 100% { opacity: 1; }
634
+ }
635
+
636
+ @keyframes xiaohei-heixiu-drift-one {
637
+ 0%, 100% { transform: translate3d(0, 0.4rem, 0); }
638
+ 28% { transform: translate3d(0.7rem, -0.2rem, 0); }
639
+ 61% { transform: translate3d(-0.45rem, -0.9rem, 0); }
640
+ 82% { transform: translate3d(0.28rem, -0.48rem, 0); }
641
+ }
642
+
643
+ @keyframes xiaohei-heixiu-drift-two {
644
+ 0%, 100% { transform: translate3d(-0.35rem, 0.25rem, 0); }
645
+ 34% { transform: translate3d(0.5rem, -0.72rem, 0); }
646
+ 68% { transform: translate3d(-0.6rem, -1.15rem, 0); }
647
+ }
648
+
649
+ @keyframes xiaohei-heixiu-drift-three {
650
+ 0%, 100% { transform: translate3d(0.25rem, 0.15rem, 0); }
651
+ 37% { transform: translate3d(-0.65rem, 0.72rem, 0); }
652
+ 72% { transform: translate3d(0.48rem, -0.55rem, 0); }
653
+ }
654
+
655
+ @keyframes xiaohei-spirit-one {
656
+ 0%, 100% { transform: translate3d(0, 0.5rem, 0) scale(0.72); opacity: 0.12; }
657
+ 48% { transform: translate3d(-0.7rem, -1.6rem, 0) scale(1); opacity: 0.82; }
658
+ }
659
+
660
+ @keyframes xiaohei-spirit-two {
661
+ 0%, 100% { transform: translate3d(0.6rem, 0.4rem, 0) scale(0.68); opacity: 0.08; }
662
+ 52% { transform: translate3d(-0.35rem, -1.35rem, 0) scale(0.92); opacity: 0.66; }
663
+ }
664
+
665
+ @keyframes xiaohei-spirit-three {
666
+ 0%, 100% { transform: translate3d(-0.4rem, 0.8rem, 0) scale(0.7); opacity: 0.1; }
667
+ 44% { transform: translate3d(0.45rem, -1.2rem, 0) scale(0.96); opacity: 0.7; }
668
+ }
669
+
670
+ @keyframes xiaohei-thinking-dot {
671
+ 0%, 18%, 100% { opacity: 0.28; }
672
+ 42%, 62% { opacity: 0.96; }
673
+ }
674
+
675
+ @keyframes xiaohei-tail-write {
676
+ 0%, 12% { transform: rotate(var(--tail-write-angle)) scaleX(0.08); opacity: 0; }
677
+ 38%, 68% { transform: rotate(var(--tail-write-angle)) scaleX(1); opacity: 0.94; }
678
+ 88%, 100% { transform: rotate(var(--tail-write-angle)) scaleX(1); opacity: 0; }
679
+ }
680
+
681
+ @keyframes xiaohei-tool-key {
682
+ 0%, 100% { transform: translate3d(0, 0, 0) scale(0.7); opacity: 0.18; }
683
+ 45% { transform: translate3d(0, -0.15rem, 0) scale(1); opacity: 1; }
684
+ }
685
+
686
+ @keyframes xiaohei-waiting-ring {
687
+ from { transform: translate3d(-50%, -50%, 0) scale(0.55); opacity: 0.72; }
688
+ to { transform: translate3d(-50%, -50%, 0) scale(1.45); opacity: 0; }
689
+ }
690
+
691
+ @keyframes xiaohei-complete-spark-one {
692
+ from { transform: translate3d(-0.4rem, 0.4rem, 0) scale(0.45); opacity: 0; }
693
+ 35% { opacity: 1; }
694
+ to { transform: translate3d(-2.5rem, -2rem, 0) scale(1.15); opacity: 0; }
695
+ }
696
+
697
+ @keyframes xiaohei-complete-spark-two {
698
+ from { transform: translate3d(0.4rem, 0.3rem, 0) scale(0.45); opacity: 0; }
699
+ 35% { opacity: 0.95; }
700
+ to { transform: translate3d(2.5rem, -1.75rem, 0) scale(1.1); opacity: 0; }
701
+ }
702
+
703
+ @keyframes xiaohei-error-glow {
704
+ 0%, 100% { transform: translate3d(-50%, -50%, 0) scale(0.78); opacity: 0.34; }
705
+ 50% { transform: translate3d(-50%, -50%, 0) scale(1.12); opacity: 0.9; }
706
+ }
707
+
708
+ @media (max-width: 768px) {
709
+ .xiaohei-scene__keyart {
710
+ object-position: 62% bottom;
711
+ }
712
+
713
+ .xiaohei-scene__keyart--night { opacity: 0.9; }
714
+ .xiaohei-scene__keyart--dawn { opacity: 0; }
715
+
716
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night { opacity: 0; }
717
+
718
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn {
719
+ opacity: 0.94;
720
+ }
721
+
722
+ .xiaohei-scene__veil {
723
+ background: linear-gradient(180deg, rgb(8 13 15 / 3%), rgb(8 13 15 / 8%));
724
+ }
725
+
726
+ .xiaohei-scene__mascot {
727
+ right: -1.5rem;
728
+ bottom: 5rem;
729
+ width: clamp(10rem, 42vw, 14rem);
730
+ }
731
+
732
+ .xiaohei-scene__heixiu--mascot {
733
+ right: 8.5rem;
734
+ bottom: 7.5rem;
735
+ width: 3.8rem;
736
+ }
737
+
738
+ .xiaohei-scene__heixiu--sidebar { display: none; }
739
+
740
+ .xiaohei-scene__heixiu--composer {
741
+ left: 52%;
742
+ right: auto;
743
+ top: -1.45rem;
744
+ width: 2.8rem;
745
+ }
746
+
747
+ }
748
+
749
+ @media (prefers-reduced-motion: reduce) {
750
+ .xiaohei-scene__spirit,
751
+ .xiaohei-scene__heixiu,
752
+ .xiaohei-scene__heixiu-open,
753
+ .xiaohei-scene__heixiu-blink,
754
+ .xiaohei-scene__thinking-dot,
755
+ .xiaohei-scene__state-fx > span {
756
+ animation: none;
757
+ will-change: auto;
758
+ }
759
+
760
+ .xiaohei-scene__spirit { display: none; }
761
+ .xiaohei-scene__state-fx { display: none; }
762
+
763
+ html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot {
764
+ animation: none;
765
+ will-change: auto;
766
+ opacity: 0.72;
767
+ }
768
+ }
769
+
770
+ @media (prefers-contrast: more) {
771
+ .xiaohei-scene__keyart--night { opacity: 0.48; }
772
+ .xiaohei-scene__keyart--dawn { opacity: 0; }
773
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night { opacity: 0; }
774
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn { opacity: 0.5; }
775
+ .xiaohei-scene__veil { background: rgb(5 12 15 / 48%); }
776
+ html[data-xiaohei-appearance='light'] .xiaohei-scene__veil { background: rgb(235 240 235 / 58%); }
777
+ .xiaohei-scene__spirit,
778
+ .xiaohei-scene__heixiu-field,
779
+ .xiaohei-scene__heixiu--sidebar,
780
+ .xiaohei-scene__heixiu--composer { display: none; }
781
+ }
782
+
783
+ @media (forced-colors: active), print {
784
+ #${cssEscape(XIAOHEI_SCENE_LAYER_ID)},
785
+ .xiaohei-scene__heixiu--sidebar,
786
+ .xiaohei-scene__heixiu--composer { display: none; }
787
+ }
788
+ `;
789
+ export const XIAOHEI_SCENE_CSS = [
790
+ XIAOHEI_SCENE_BASE_CSS,
791
+ XIAOHEI_STATE_TRANSITION_CSS,
792
+ XIAOHEI_HEIXIU_FEEDBACK_CSS,
793
+ XIAOHEI_HEIXIU_INTERACTION_CSS,
794
+ ].join('\n');
795
+ const PARTS = [
796
+ 'xiaohei-scene__keyart xiaohei-scene__keyart--night',
797
+ 'xiaohei-scene__keyart xiaohei-scene__keyart--dawn',
798
+ 'xiaohei-scene__veil',
799
+ 'xiaohei-scene__spirit xiaohei-scene__spirit--one',
800
+ 'xiaohei-scene__spirit xiaohei-scene__spirit--two',
801
+ 'xiaohei-scene__spirit xiaohei-scene__spirit--three',
802
+ 'xiaohei-scene__mascot',
803
+ 'xiaohei-scene__heixiu-field',
804
+ ];
805
+ /** Number of top-level decorative parts installed into the ambient layer. */
806
+ export const XIAOHEI_SCENE_PART_COUNT = PARTS.length;
807
+ /** Skip host lookups while every companion remains attached to the document. */
808
+ export function shouldRestoreXiaoheiHeixiuCompanions(creatures) {
809
+ return creatures.some(creature => !creature.isConnected);
810
+ }
811
+ /**
812
+ * Install the generated scene after plugin boot becomes idle. The theme tokens
813
+ * apply immediately, while image decoding never extends DSH's loading screen.
814
+ */
815
+ export function installXiaoheiScene(doc = typeof document === 'undefined' ? undefined : document) {
816
+ if (doc === undefined)
817
+ return () => { };
818
+ let disposed = false;
819
+ let removeMountedScene = () => { };
820
+ let removeHeixiuCompanions = () => { };
821
+ const mount = () => {
822
+ if (disposed)
823
+ return;
824
+ doc.getElementById(XIAOHEI_SCENE_STYLE_ID)?.remove();
825
+ doc.getElementById(XIAOHEI_SCENE_LAYER_ID)?.remove();
826
+ const style = doc.createElement('style');
827
+ style.id = XIAOHEI_SCENE_STYLE_ID;
828
+ style.textContent = XIAOHEI_SCENE_CSS;
829
+ doc.head.append(style);
830
+ const layer = doc.createElement('div');
831
+ layer.id = XIAOHEI_SCENE_LAYER_ID;
832
+ layer.setAttribute('aria-hidden', 'true');
833
+ layer.setAttribute('data-xiaohei-scene', '');
834
+ const keyArtSources = [XIAOHEI_NIGHT_KEY_ART, XIAOHEI_DAWN_KEY_ART];
835
+ for (const [index, source] of keyArtSources.entries()) {
836
+ const keyArt = doc.createElement('img');
837
+ keyArt.className = PARTS[index];
838
+ keyArt.alt = '';
839
+ keyArt.decoding = 'async';
840
+ keyArt.fetchPriority = 'low';
841
+ keyArt.src = source;
842
+ layer.append(keyArt);
843
+ }
844
+ for (const className of PARTS.slice(keyArtSources.length)) {
845
+ if (className === 'xiaohei-scene__mascot') {
846
+ const mascot = doc.createElement('div');
847
+ mascot.className = className;
848
+ const idleViewport = doc.createElement('span');
849
+ idleViewport.className = 'xiaohei-scene__mascot-idle-viewport';
850
+ idleViewport.append(createIdleSheet(doc, 7, 'xiaohei-scene__mascot-sheet--open'), createIdleBlink(doc));
851
+ mascot.append(idleViewport, createStateImage(doc, 'thinking', XIAOHEI_THINKING), createStateImage(doc, 'streaming', XIAOHEI_STREAMING), createStateImage(doc, 'tool', XIAOHEI_TOOL), createStateImage(doc, 'waiting', XIAOHEI_WAITING), createStateImage(doc, 'complete', XIAOHEI_COMPLETE), createStateImage(doc, 'error', XIAOHEI_ERROR), createThinkingEffects(doc), createStateEffects(doc, 'streaming', [
852
+ 'xiaohei-scene__tail-write xiaohei-scene__tail-write--one',
853
+ 'xiaohei-scene__tail-write xiaohei-scene__tail-write--two',
854
+ 'xiaohei-scene__tail-write xiaohei-scene__tail-write--three',
855
+ ]), createStateEffects(doc, 'tool', [
856
+ 'xiaohei-scene__tool-key xiaohei-scene__tool-key--one',
857
+ 'xiaohei-scene__tool-key xiaohei-scene__tool-key--two',
858
+ 'xiaohei-scene__tool-key xiaohei-scene__tool-key--three',
859
+ ]), createStateEffects(doc, 'waiting', ['xiaohei-scene__waiting-ring']), createStateEffects(doc, 'complete', [
860
+ 'xiaohei-scene__complete-spark xiaohei-scene__complete-spark--one',
861
+ 'xiaohei-scene__complete-spark xiaohei-scene__complete-spark--two',
862
+ ]), createStateEffects(doc, 'error', ['xiaohei-scene__error-glow']));
863
+ layer.append(mascot);
864
+ continue;
865
+ }
866
+ if (className === 'xiaohei-scene__heixiu-field') {
867
+ layer.append(createHeixiuField(doc));
868
+ continue;
869
+ }
870
+ const part = doc.createElement('span');
871
+ part.className = className;
872
+ layer.append(part);
873
+ }
874
+ doc.body.prepend(layer);
875
+ removeHeixiuCompanions();
876
+ removeHeixiuCompanions = installHeixiuCompanions(doc, layer);
877
+ removeMountedScene = () => {
878
+ removeHeixiuCompanions();
879
+ removeHeixiuCompanions = () => { };
880
+ layer.remove();
881
+ style.remove();
882
+ };
883
+ };
884
+ const win = doc.defaultView;
885
+ let cancelSchedule = () => { };
886
+ if (win !== null && typeof win.requestIdleCallback === 'function') {
887
+ const idleId = win.requestIdleCallback(mount, { timeout: 800 });
888
+ cancelSchedule = () => win.cancelIdleCallback(idleId);
889
+ }
890
+ else if (win !== null) {
891
+ const timeoutId = win.setTimeout(mount, 0);
892
+ cancelSchedule = () => win.clearTimeout(timeoutId);
893
+ }
894
+ else {
895
+ mount();
896
+ }
897
+ return () => {
898
+ disposed = true;
899
+ cancelSchedule();
900
+ removeMountedScene();
901
+ };
902
+ }
903
+ /** CSS id escaping for the slash in stable plugin-owned DOM ids. */
904
+ function cssEscape(value) {
905
+ return value.replaceAll('/', '\\/');
906
+ }
907
+ function createIdleSheet(doc, frame, modifier) {
908
+ const sheet = doc.createElement('img');
909
+ sheet.className = `xiaohei-scene__mascot-sheet ${modifier}`;
910
+ sheet.alt = '';
911
+ sheet.decoding = 'async';
912
+ sheet.fetchPriority = 'low';
913
+ sheet.src = XIAOHEI_IDLE_SHEET;
914
+ setIdleFrame(sheet, frame);
915
+ return sheet;
916
+ }
917
+ function createIdleBlink(doc) {
918
+ const image = doc.createElement('img');
919
+ image.className = 'xiaohei-scene__mascot-blink';
920
+ image.alt = '';
921
+ image.decoding = 'async';
922
+ image.fetchPriority = 'low';
923
+ image.src = XIAOHEI_IDLE_BLINK;
924
+ return image;
925
+ }
926
+ function setIdleFrame(sheet, frame) {
927
+ const column = frame % 4;
928
+ const row = Math.floor(frame / 4);
929
+ sheet.style.transform = `translate3d(${-column * 25}%, ${-row * 50}%, 0)`;
930
+ }
931
+ function createStateImage(doc, state, source) {
932
+ const image = doc.createElement('img');
933
+ image.className = `xiaohei-scene__mascot-state xiaohei-scene__mascot-state--${state}`;
934
+ image.alt = '';
935
+ image.decoding = 'async';
936
+ image.fetchPriority = 'low';
937
+ image.src = source;
938
+ return image;
939
+ }
940
+ function createHeixiuField(doc) {
941
+ const field = doc.createElement('div');
942
+ field.className = 'xiaohei-scene__heixiu-field';
943
+ field.append(createHeixiuCreature(doc, 'mascot'));
944
+ return field;
945
+ }
946
+ function createHeixiuCreature(doc, name) {
947
+ const creature = doc.createElement('span');
948
+ creature.className = `xiaohei-scene__heixiu xiaohei-scene__heixiu--${name}`;
949
+ creature.setAttribute('aria-hidden', 'true');
950
+ const body = doc.createElement('span');
951
+ body.className = 'xiaohei-scene__heixiu-body';
952
+ body.append(createHeixiuImage(doc, XIAOHEI_HEIXIU_OPEN, 'xiaohei-scene__heixiu-open'), createHeixiuImage(doc, XIAOHEI_HEIXIU_BLINK, 'xiaohei-scene__heixiu-blink'));
953
+ creature.append(body);
954
+ return creature;
955
+ }
956
+ function installHeixiuCompanions(doc, layer) {
957
+ const companions = [
958
+ { slot: 'sidebar', creature: createHeixiuCreature(doc, 'sidebar') },
959
+ { slot: 'conversation.composer.bar', creature: createHeixiuCreature(doc, 'composer') },
960
+ ];
961
+ const companionCreatures = companions.map(({ creature }) => creature);
962
+ let attachQueued = false;
963
+ const attach = () => {
964
+ attachQueued = false;
965
+ for (const { slot, creature } of companions) {
966
+ const host = doc.querySelector(`[data-slot='${slot}']`)?.firstElementChild;
967
+ if (host !== null && host !== undefined && creature.parentElement !== host)
968
+ host.append(creature);
969
+ }
970
+ };
971
+ const queueAttach = () => {
972
+ if (attachQueued)
973
+ return;
974
+ attachQueued = true;
975
+ queueMicrotask(attach);
976
+ };
977
+ const restoreDetachedCompanions = () => {
978
+ if (!shouldRestoreXiaoheiHeixiuCompanions(companionCreatures))
979
+ return;
980
+ queueAttach();
981
+ };
982
+ attach();
983
+ const Observer = doc.defaultView?.MutationObserver;
984
+ const observer = Observer === undefined ? undefined : new Observer(restoreDetachedCompanions);
985
+ observer?.observe(doc.body, { childList: true, subtree: true });
986
+ return () => {
987
+ observer?.disconnect();
988
+ for (const { creature } of companions)
989
+ creature.remove();
990
+ };
991
+ }
992
+ function createHeixiuImage(doc, source, className) {
993
+ const image = doc.createElement('img');
994
+ image.className = className;
995
+ image.alt = '';
996
+ image.decoding = 'async';
997
+ image.fetchPriority = 'low';
998
+ image.src = source;
999
+ return image;
1000
+ }
1001
+ function createThinkingEffects(doc) {
1002
+ const effects = doc.createElement('span');
1003
+ effects.className = 'xiaohei-scene__thinking-fx';
1004
+ const bubble = doc.createElement('span');
1005
+ bubble.className = 'xiaohei-scene__thinking-bubble';
1006
+ for (const suffix of ['one', 'two', 'three']) {
1007
+ const dot = doc.createElement('span');
1008
+ dot.className = `xiaohei-scene__thinking-dot xiaohei-scene__thinking-dot--${suffix}`;
1009
+ bubble.append(dot);
1010
+ }
1011
+ effects.append(bubble);
1012
+ return effects;
1013
+ }
1014
+ function createStateEffects(doc, state, classNames) {
1015
+ const effects = doc.createElement('span');
1016
+ effects.className = `xiaohei-scene__state-fx xiaohei-scene__state-fx--${state}`;
1017
+ for (const className of classNames) {
1018
+ const part = doc.createElement('span');
1019
+ part.className = className;
1020
+ effects.append(part);
1021
+ }
1022
+ return effects;
1023
+ }
1024
+ //# sourceMappingURL=scene.js.map