ai-control-center 1.15.2

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +584 -0
  3. package/bin/aicc.js +772 -0
  4. package/lib/actions/approve.js +71 -0
  5. package/lib/actions/assign-project.js +132 -0
  6. package/lib/actions/browser-test.js +64 -0
  7. package/lib/actions/cleanup.js +174 -0
  8. package/lib/actions/debug.js +298 -0
  9. package/lib/actions/deploy.js +1229 -0
  10. package/lib/actions/fix-bug.js +134 -0
  11. package/lib/actions/new-feature.js +255 -0
  12. package/lib/actions/reject.js +307 -0
  13. package/lib/actions/review.js +706 -0
  14. package/lib/actions/status.js +47 -0
  15. package/lib/agents/browser-qa-agent.js +611 -0
  16. package/lib/agents/payment-agent.js +116 -0
  17. package/lib/agents/suggestion-agent.js +88 -0
  18. package/lib/cli.js +303 -0
  19. package/lib/config.js +243 -0
  20. package/lib/hub/hub-server.js +440 -0
  21. package/lib/hub/project-poller.js +75 -0
  22. package/lib/hub/skill-registry.js +89 -0
  23. package/lib/hub/state-aggregator.js +204 -0
  24. package/lib/index.js +471 -0
  25. package/lib/init/doctor.js +523 -0
  26. package/lib/init/presets.js +222 -0
  27. package/lib/init/skill-fetcher.js +77 -0
  28. package/lib/init/wizard.js +973 -0
  29. package/lib/integrations/codex-runner.js +128 -0
  30. package/lib/integrations/github-actions.js +248 -0
  31. package/lib/integrations/github-reporter.js +229 -0
  32. package/lib/integrations/screenshot-store.js +102 -0
  33. package/lib/openclaw/bridge.js +650 -0
  34. package/lib/openclaw/generate-skill.js +235 -0
  35. package/lib/openclaw/openclaw.json +64 -0
  36. package/lib/orchestrator/autonomous-loop.js +429 -0
  37. package/lib/orchestrator/thread-triggers.js +63 -0
  38. package/lib/roleplay/agent-messenger.js +75 -0
  39. package/lib/roleplay/discussion-threads.js +303 -0
  40. package/lib/roleplay/health-monitor.js +121 -0
  41. package/lib/roleplay/pm-agent.js +513 -0
  42. package/lib/roleplay/roleplay-config.js +25 -0
  43. package/lib/roleplay/room.js +164 -0
  44. package/lib/shared/action-runner.js +2330 -0
  45. package/lib/shared/event-bus.js +185 -0
  46. package/lib/slack/bot.js +378 -0
  47. package/lib/telegram/bot.js +416 -0
  48. package/lib/telegram/commands.js +1267 -0
  49. package/lib/telegram/keyboards.js +113 -0
  50. package/lib/telegram/notifications.js +247 -0
  51. package/lib/twitch/bot.js +354 -0
  52. package/lib/twitch/commands.js +302 -0
  53. package/lib/twitch/notifications.js +63 -0
  54. package/lib/utils/achievements.js +191 -0
  55. package/lib/utils/activity-log.js +182 -0
  56. package/lib/utils/agent-leaderboard.js +119 -0
  57. package/lib/utils/audit-logger.js +232 -0
  58. package/lib/utils/codebase-context.js +288 -0
  59. package/lib/utils/codebase-indexer.js +381 -0
  60. package/lib/utils/config-schema.js +230 -0
  61. package/lib/utils/context-compressor.js +172 -0
  62. package/lib/utils/correlation.js +63 -0
  63. package/lib/utils/cost-tracker.js +423 -0
  64. package/lib/utils/cron-scheduler.js +53 -0
  65. package/lib/utils/db-adapter.js +293 -0
  66. package/lib/utils/display.js +272 -0
  67. package/lib/utils/errors.js +116 -0
  68. package/lib/utils/format.js +134 -0
  69. package/lib/utils/intent-engine.js +464 -0
  70. package/lib/utils/mcp-client.js +238 -0
  71. package/lib/utils/model-ab-test.js +164 -0
  72. package/lib/utils/notify.js +122 -0
  73. package/lib/utils/persona-loader.js +80 -0
  74. package/lib/utils/pipeline-lock.js +73 -0
  75. package/lib/utils/pipeline.js +214 -0
  76. package/lib/utils/plugin-runner.js +234 -0
  77. package/lib/utils/rate-limiter.js +84 -0
  78. package/lib/utils/rbac.js +74 -0
  79. package/lib/utils/runner.js +1809 -0
  80. package/lib/utils/security.js +191 -0
  81. package/lib/utils/self-healer.js +144 -0
  82. package/lib/utils/skill-loader.js +255 -0
  83. package/lib/utils/spinner.js +132 -0
  84. package/lib/utils/stage-queue.js +50 -0
  85. package/lib/utils/state-machine.js +89 -0
  86. package/lib/utils/status-bar.js +327 -0
  87. package/lib/utils/token-estimator.js +101 -0
  88. package/lib/utils/ux-analyzer.js +101 -0
  89. package/lib/utils/webhook-emitter.js +83 -0
  90. package/lib/web/public/css/styles.css +417 -0
  91. package/lib/web/public/dark-mode.js +44 -0
  92. package/lib/web/public/hub/kanban.html +206 -0
  93. package/lib/web/public/index.html +45 -0
  94. package/lib/web/public/js/app.js +71 -0
  95. package/lib/web/public/js/ask.js +110 -0
  96. package/lib/web/public/js/dashboard.js +165 -0
  97. package/lib/web/public/js/deploy.js +72 -0
  98. package/lib/web/public/js/feature.js +79 -0
  99. package/lib/web/public/js/health.js +65 -0
  100. package/lib/web/public/js/logs.js +93 -0
  101. package/lib/web/public/js/review.js +123 -0
  102. package/lib/web/public/js/ws-client.js +82 -0
  103. package/lib/web/public/office/css/office.css +678 -0
  104. package/lib/web/public/office/index.html +148 -0
  105. package/lib/web/public/office/js/achievements-ui.js +117 -0
  106. package/lib/web/public/office/js/character.js +1056 -0
  107. package/lib/web/public/office/js/chat-bubbles.js +177 -0
  108. package/lib/web/public/office/js/cost-overlay.js +123 -0
  109. package/lib/web/public/office/js/day-night.js +68 -0
  110. package/lib/web/public/office/js/effects.js +632 -0
  111. package/lib/web/public/office/js/engine.js +146 -0
  112. package/lib/web/public/office/js/feature-ticket.js +216 -0
  113. package/lib/web/public/office/js/hub-client.js +60 -0
  114. package/lib/web/public/office/js/main.js +1757 -0
  115. package/lib/web/public/office/js/office-layout.js +1524 -0
  116. package/lib/web/public/office/js/pathfinding.js +144 -0
  117. package/lib/web/public/office/js/pixel-sprites.js +1454 -0
  118. package/lib/web/public/office/js/progress-bars.js +117 -0
  119. package/lib/web/public/office/js/replay.js +191 -0
  120. package/lib/web/public/office/js/sound-effects.js +91 -0
  121. package/lib/web/public/office/js/sprite-renderer.js +211 -0
  122. package/lib/web/public/office/js/stamina-system.js +89 -0
  123. package/lib/web/public/office/js/ui.js +107 -0
  124. package/lib/web/public/onboarding/index.html +243 -0
  125. package/lib/web/public/timeline/index.html +195 -0
  126. package/lib/web/routes/api.js +499 -0
  127. package/lib/web/routes/logs.js +20 -0
  128. package/lib/web/routes/metrics.js +99 -0
  129. package/lib/web/server.js +183 -0
  130. package/lib/web/ws/handler.js +65 -0
  131. package/package.json +67 -0
  132. package/templates/agent-architect.md +69 -0
  133. package/templates/agent-gemini-pm.md +49 -0
  134. package/templates/agent-gemini-reviewer.md +52 -0
  135. package/templates/copilot-instructions.md +36 -0
  136. package/templates/pipelines/mobile.json +27 -0
  137. package/templates/pipelines/nodejs-api.json +27 -0
  138. package/templates/pipelines/python.json +27 -0
  139. package/templates/pipelines/react.json +27 -0
  140. package/templates/pipelines/salesforce.json +27 -0
  141. package/templates/role-gemini.md +97 -0
  142. package/templates/skill-architect.md +114 -0
  143. package/templates/skill-browser-qa.md +50 -0
  144. package/templates/skill-bug-from-qa.md +58 -0
  145. package/templates/skill-chatbot.md +93 -0
  146. package/templates/skill-implement.md +78 -0
  147. package/templates/skill-openclaw.md +174 -0
  148. package/templates/skill-payment.md +110 -0
  149. package/templates/skill-pm-spec.md +77 -0
  150. package/templates/skill-requirement-capture.md +97 -0
  151. package/templates/skill-review.md +108 -0
  152. package/templates/skill-reviewer-qa.md +44 -0
  153. package/templates/skill-suggestion.md +45 -0
  154. package/templates/skill-template.md +142 -0
@@ -0,0 +1,1454 @@
1
+ /**
2
+ * Pixel Sprite Data — 16×24 top-down RPG character sprites
3
+ * Stardew Valley / pixel-agents inspired with diverse characters.
4
+ * Each frame is a 24-row × 16-column array of hex color strings (null = transparent).
5
+ */
6
+
7
+ // ── Compact sprite parser ───────────────────────────────────────────────────
8
+ function p(str, pal) {
9
+ return str.trim().split('\n').map(row =>
10
+ row.trim().split(' ').map(c => pal[c] ?? null)
11
+ );
12
+ }
13
+
14
+ // ── Outline ─────────────────────────────────────────────────────────────────
15
+ const X = '#1a1a2e';
16
+
17
+ // ============================================================
18
+ // PM (Gemini) — Fair skin, dark brown hair, navy suit, red tie
19
+ // ============================================================
20
+ const pmP = {
21
+ '.': null, X,
22
+ H: '#3a2818', h: '#5a3828', // hair
23
+ S: '#f0c8a0', s: '#daa870', P: '#ffe0c0', // skin
24
+ E: '#2a2a40', M: '#c07060', W: '#e8e8f0', w: '#c0c0d0', // eyes/mouth/white
25
+ R: '#c03030', r: '#901818', // tie
26
+ B: '#2a4080', b: '#1a3060', L: '#3a60a0', // suit
27
+ N: '#252545', n: '#1a1a35', // pants
28
+ K: '#2a2a2a', k: '#3a3a3a', // shoes
29
+ };
30
+
31
+ const PM_IDLE_0 = p(`
32
+ . . . . . X X X X X X . . . . .
33
+ . . . . X H h H H h H X . . . .
34
+ . . . X H h H H H H h H X . . .
35
+ . . . X H H H H H H H H X . . .
36
+ . . . X S S S S S S S S X . . .
37
+ . . X S S E P S S E P S S X . .
38
+ . . X S S S S S s S S S S X . .
39
+ . . X S S S M M M S S S S X . .
40
+ . . . X S S S S S S S S X . . .
41
+ . . . . X X S S S S X X . . . .
42
+ . . . . X W W R W W X . . . . .
43
+ . . . X B W W R W W B X . . . .
44
+ . . X B B B W R W B B B X . . .
45
+ . . X s B B B R B B B s X . . .
46
+ . . . X B B B R B B B X . . . .
47
+ . . . X b B B B B B b X . . . .
48
+ . . . . X N N N N N X . . . . .
49
+ . . . . X N N N N N X . . . . .
50
+ . . . . X N N . N N X . . . . .
51
+ . . . . X N N . N N X . . . . .
52
+ . . . . X n n . n n X . . . . .
53
+ . . . . X K K . K K X . . . . .
54
+ . . . . K k k . k k K . . . . .
55
+ . . . . . . . . . . . . . . . .`, pmP);
56
+
57
+ const PM_IDLE_1 = p(`
58
+ . . . . . X X X X X X . . . . .
59
+ . . . . X H h H H h H X . . . .
60
+ . . . X H h H H H H h H X . . .
61
+ . . . X H H H H H H H H X . . .
62
+ . . . X S S S S S S S S X . . .
63
+ . . X S S s s S S s s S S X . .
64
+ . . X S S S S S s S S S S X . .
65
+ . . X S S S M M M S S S S X . .
66
+ . . . X S S S S S S S S X . . .
67
+ . . . . X X S S S S X X . . . .
68
+ . . . . X W W R W W X . . . . .
69
+ . . . X B W W R W W B X . . . .
70
+ . . X B B B W R W B B B X . . .
71
+ . . X s B B B R B B B s X . . .
72
+ . . . X B B B R B B B X . . . .
73
+ . . . X b B B B B B b X . . . .
74
+ . . . . X N N N N N X . . . . .
75
+ . . . . X N N N N N X . . . . .
76
+ . . . . X N N . N N X . . . . .
77
+ . . . . X N N . N N X . . . . .
78
+ . . . . X n n . n n X . . . . .
79
+ . . . . X K K . K K X . . . . .
80
+ . . . . K k k . k k K . . . . .
81
+ . . . . . . . . . . . . . . . .`, pmP);
82
+
83
+ const PM_WALK_D0 = p(`
84
+ . . . . . X X X X X X . . . . .
85
+ . . . . X H h H H h H X . . . .
86
+ . . . X H h H H H H h H X . . .
87
+ . . . X H H H H H H H H X . . .
88
+ . . . X S S S S S S S S X . . .
89
+ . . X S S E P S S E P S S X . .
90
+ . . X S S S S S s S S S S X . .
91
+ . . X S S S M M M S S S S X . .
92
+ . . . X S S S S S S S S X . . .
93
+ . . . . X X S S S S X X . . . .
94
+ . . . . X W W R W W X . . . . .
95
+ . . . X B W W R W W B X . . . .
96
+ . . X B B B W R W B B B X . . .
97
+ . . X s B B B R B B B s X . . .
98
+ . . . X B B B R B B B X . . . .
99
+ . . . X b B B B B B b X . . . .
100
+ . . . . X N N N N N X . . . . .
101
+ . . . X N N N . . N N X . . . .
102
+ . . X N N X . . . . X N N X . .
103
+ . . X N n X . . . . X n N X . .
104
+ . . X K K X . . . . X K K X . .
105
+ . . K k k X . . . . X k k K . .
106
+ . . . . . . . . . . . . . . . .
107
+ . . . . . . . . . . . . . . . .`, pmP);
108
+
109
+ const PM_WALK_D1 = p(`
110
+ . . . . . X X X X X X . . . . .
111
+ . . . . X H h H H h H X . . . .
112
+ . . . X H h H H H H h H X . . .
113
+ . . . X H H H H H H H H X . . .
114
+ . . . X S S S S S S S S X . . .
115
+ . . X S S E P S S E P S S X . .
116
+ . . X S S S S S s S S S S X . .
117
+ . . X S S S M M M S S S S X . .
118
+ . . . X S S S S S S S S X . . .
119
+ . . . . X X S S S S X X . . . .
120
+ . . . . X W W R W W X . . . . .
121
+ . . . X B W W R W W B X . . . .
122
+ . . X B B B W R W B B B X . . .
123
+ . . X s B B B R B B B s X . . .
124
+ . . . X B B B R B B B X . . . .
125
+ . . . X b B B B B B b X . . . .
126
+ . . . . X N N N N N X . . . . .
127
+ . . . . X N N . N N N X . . . .
128
+ . . . X N N X . . X N N X . . .
129
+ . . . X n N X . . X N n X . . .
130
+ . . . X K K X . . X K K X . . .
131
+ . . . X k k K . K k k X . . . .
132
+ . . . . . . . . . . . . . . . .
133
+ . . . . . . . . . . . . . . . .`, pmP);
134
+
135
+ const PM_WALK_UP0 = p(`
136
+ . . . . . X X X X X X . . . . .
137
+ . . . . X H H H H H H X . . . .
138
+ . . . X H H h H H h H H X . . .
139
+ . . . X H h H H H H h H X . . .
140
+ . . . X H H H H H H H H X . . .
141
+ . . . X H H H H H H H H X . . .
142
+ . . X S S H H H H H H S S X . .
143
+ . . . X S S S S S S S S X . . .
144
+ . . . . X X S S S S X X . . . .
145
+ . . . . X B B B B B B X . . . .
146
+ . . . X B B B B B B B B X . . .
147
+ . . X B B B B B B B B B B X . .
148
+ . . X s B B B B B B B B s X . .
149
+ . . . X B B B B B B B B X . . .
150
+ . . . X b B B B B B B b X . . .
151
+ . . . . X N N N N N N X . . . .
152
+ . . . . X N N N N N N X . . . .
153
+ . . . . X N N . . N N X . . . .
154
+ . . . . X N N . . N N X . . . .
155
+ . . . . X n n . . n n X . . . .
156
+ . . . . X K K . . K K X . . . .
157
+ . . . . K k k . . k k K . . . .
158
+ . . . . . . . . . . . . . . . .
159
+ . . . . . . . . . . . . . . . .`, pmP);
160
+
161
+ const PM_WALK_UP1 = p(`
162
+ . . . . . X X X X X X . . . . .
163
+ . . . . X H H H H H H X . . . .
164
+ . . . X H H h H H h H H X . . .
165
+ . . . X H h H H H H h H X . . .
166
+ . . . X H H H H H H H H X . . .
167
+ . . . X H H H H H H H H X . . .
168
+ . . X S S H H H H H H S S X . .
169
+ . . . X S S S S S S S S X . . .
170
+ . . . . X X S S S S X X . . . .
171
+ . . . . X B B B B B B X . . . .
172
+ . . . X B B B B B B B B X . . .
173
+ . . X B B B B B B B B B B X . .
174
+ . . X s B B B B B B B B s X . .
175
+ . . . X B B B B B B B B X . . .
176
+ . . . X b B B B B B B b X . . .
177
+ . . . . X N N N N N N X . . . .
178
+ . . . X N N N . . N N N X . . .
179
+ . . X N N X . . . . X N N X . .
180
+ . . X N n X . . . . X n N X . .
181
+ . . X K K X . . . . X K K X . .
182
+ . . K k k X . . . . X k k K . .
183
+ . . . . . . . . . . . . . . . .
184
+ . . . . . . . . . . . . . . . .
185
+ . . . . . . . . . . . . . . . .`, pmP);
186
+
187
+ const PM_SIDE_0 = p(`
188
+ . . . . . . X X X X X . . . . .
189
+ . . . . . X H h H H X . . . . .
190
+ . . . . X H h H H H H X . . . .
191
+ . . . . X H H H H H H X . . . .
192
+ . . . . X S S S S S S X . . . .
193
+ . . . . X S E P S S S X . . . .
194
+ . . . . X S S S s S X . . . . .
195
+ . . . . X S M M S S X . . . . .
196
+ . . . . . X S S S X . . . . . .
197
+ . . . . . X S S X . . . . . . .
198
+ . . . . X W R W X . . . . . . .
199
+ . . . X B W R W B X . . . . . .
200
+ . . X B B B R B B X . . . . . .
201
+ . . X s B B R B B X . . . . . .
202
+ . . . X B B B B X . . . . . . .
203
+ . . . X b B B b X . . . . . . .
204
+ . . . . X N N N X . . . . . . .
205
+ . . . . X N N N X . . . . . . .
206
+ . . . X N N . N N X . . . . . .
207
+ . . . X n n . n n X . . . . . .
208
+ . . X K K . . . K K X . . . . .
209
+ . . K k K . . . K k K . . . . .
210
+ . . . . . . . . . . . . . . . .
211
+ . . . . . . . . . . . . . . . .`, pmP);
212
+
213
+ const PM_SIDE_1 = p(`
214
+ . . . . . . X X X X X . . . . .
215
+ . . . . . X H h H H X . . . . .
216
+ . . . . X H h H H H H X . . . .
217
+ . . . . X H H H H H H X . . . .
218
+ . . . . X S S S S S S X . . . .
219
+ . . . . X S E P S S S X . . . .
220
+ . . . . X S S S s S X . . . . .
221
+ . . . . X S M M S S X . . . . .
222
+ . . . . . X S S S X . . . . . .
223
+ . . . . . X S S X . . . . . . .
224
+ . . . . X W R W X . . . . . . .
225
+ . . . X B W R W B X . . . . . .
226
+ . . X B B B R B B X . . . . . .
227
+ . . X s B B R B B X . . . . . .
228
+ . . . X B B B B X . . . . . . .
229
+ . . . X b B B b X . . . . . . .
230
+ . . . . X N N N X . . . . . . .
231
+ . . . X N N . N N X . . . . . .
232
+ . . X N N . . . N X . . . . . .
233
+ . . X n n . . . n X . . . . . .
234
+ . . K K X . . X K K . . . . . .
235
+ . . k k . . . . k k . . . . . .
236
+ . . . . . . . . . . . . . . . .
237
+ . . . . . . . . . . . . . . . .`, pmP);
238
+
239
+ const PM_WORK_0 = p(`
240
+ . . . . . X X X X X X . . . . .
241
+ . . . . X H h H H h H X . . . .
242
+ . . . X H h H H H H h H X . . .
243
+ . . . X H H H H H H H H X . . .
244
+ . . . X S S S S S S S S X . . .
245
+ . . X S S E P S S E P S S X . .
246
+ . . X S S S S S s S S S S X . .
247
+ . . X S S S S S S S S S S X . .
248
+ . . . X S S S S S S S S X . . .
249
+ . . . . X X S S S S X X . . . .
250
+ . . . . X W W R W W X . . . . .
251
+ . . . X B W W R W W B X . . . .
252
+ . . X s B B W R W B B s X . . .
253
+ . X S s B B B R B B B s S X . .
254
+ X S X B B B B R B B B B X S X .
255
+ . X X . B B B B B B B . X X . .
256
+ . . . . X N N N N N X . . . . .
257
+ . . . . X N N N N N X . . . . .
258
+ . . . . X N N . N N X . . . . .
259
+ . . . . X N N . N N X . . . . .
260
+ . . . . X n n . n n X . . . . .
261
+ . . . . X K K . K K X . . . . .
262
+ . . . . K k k . k k K . . . . .
263
+ . . . . . . . . . . . . . . . .`, pmP);
264
+
265
+ const PM_WORK_1 = p(`
266
+ . . . . . X X X X X X . . . . .
267
+ . . . . X H h H H h H X . . . .
268
+ . . . X H h H H H H h H X . . .
269
+ . . . X H H H H H H H H X . . .
270
+ . . . X S S S S S S S S X . . .
271
+ . . X S S E P S S E P S S X . .
272
+ . . X S S S S S s S S S S X . .
273
+ . . X S S S S S S S S S S X . .
274
+ . . . X S S S S S S S S X . . .
275
+ . . . . X X S S S S X X . . . .
276
+ . . . . X W W R W W X . . . . .
277
+ . . . X B W W R W W B X . . . .
278
+ . . X s B B W R W B B s X . . .
279
+ . X S s B B B R B B B s S X . .
280
+ . X S B B B B R B B B B S X . .
281
+ . X X . B B B B B B B . X X . .
282
+ . . . . X N N N N N X . . . . .
283
+ . . . . X N N N N N X . . . . .
284
+ . . . . X N N . N N X . . . . .
285
+ . . . . X N N . N N X . . . . .
286
+ . . . . X n n . n n X . . . . .
287
+ . . . . X K K . K K X . . . . .
288
+ . . . . K k k . k k K . . . . .
289
+ . . . . . . . . . . . . . . . .`, pmP);
290
+
291
+ const PM_SLEEP = p(`
292
+ . . . . . X X X X X X . . . . .
293
+ . . . . X H h H H h H X . . . .
294
+ . . . X H h H H H H h H X . . .
295
+ . . . X H H H H H H H H X . . .
296
+ . . . X S S S S S S S S X . . .
297
+ . . X S S s s S S s s S S X . .
298
+ . . X S S S S S s S S S S X . .
299
+ . . X S S S S S S S S S S X . .
300
+ . . . X S S S S S S S S X . . .
301
+ . . . . X X S S S S X X . . . .
302
+ . . . . X W W R W W X . . . . .
303
+ . . . X B W W R W W B X . . . .
304
+ . . X B B B W R W B B B X . . .
305
+ . . X B B B B R B B B B X . . .
306
+ . . . X B B B R B B B X . . . .
307
+ . . . X b B B B B B b X . . . .
308
+ . . . . X N N N N N X . . . . .
309
+ . . . . X N N N N N X . . . . .
310
+ . . . . X N N . N N X . . . . .
311
+ . . . . X N N . N N X . . . . .
312
+ . . . . X n n . n n X . . . . .
313
+ . . . . X K K . K K X . . . . .
314
+ . . . . K k k . k k K . . . . .
315
+ . . . . . . . . . . . . . . . .`, pmP);
316
+
317
+ const PM_CELEBRATE = p(`
318
+ . . . . . X X X X X X . . . . .
319
+ . . . . X H h H H h H X . . . .
320
+ . . . X H h H H H H h H X . . .
321
+ . . . X H H H H H H H H X . . .
322
+ . . . X S S S S S S S S X . . .
323
+ . . X S S E P S S E P S S X . .
324
+ . . X S S S S S s S S S S X . .
325
+ . . X S S M M M M S S S S X . .
326
+ . . . X S S S S S S S S X . . .
327
+ X S X . X X S S S S X X . X S X
328
+ X s X . X W W R W W X . . X s X
329
+ . X . X B W W R W W B X . . X .
330
+ . . X B B B W R W B B B X . . .
331
+ . . . X B B B R B B B X . . . .
332
+ . . . X B B B R B B B X . . . .
333
+ . . . X b B B B B B b X . . . .
334
+ . . . . X N N N N N X . . . . .
335
+ . . . . X N N N N N X . . . . .
336
+ . . . . X N N . N N X . . . . .
337
+ . . . . X N N . N N X . . . . .
338
+ . . . . X n n . n n X . . . . .
339
+ . . . . X K K . K K X . . . . .
340
+ . . . . K k k . k k K . . . . .
341
+ . . . . . . . . . . . . . . . .`, pmP);
342
+
343
+ // ============================================================
344
+ // ARCHITECT (Claude) — Medium skin, yellow hard hat, orange vest
345
+ // ============================================================
346
+ const arP = {
347
+ '.': null, X,
348
+ Y: '#e8c820', y: '#c8a810', Z: '#f0d830', // hard hat
349
+ S: '#dca870', s: '#b88050', P: '#f0c090', // skin (medium tone)
350
+ E: '#2a2a40', M: '#a06050', // eyes/mouth
351
+ V: '#e08020', v: '#c06010', // vest
352
+ G: '#808090', g: '#606070', // gray shirt
353
+ T: '#5a4a3a', // tool belt
354
+ N: '#404858', n: '#303848', // dark pants
355
+ A: '#5a3a20', a: '#4a2a10', // boots
356
+ };
357
+
358
+ const ARCH_IDLE_0 = p(`
359
+ . . . . X X X X X X X X . . . .
360
+ . . . X Y Y Y Z Y Y Y Y X . . .
361
+ . . X y Y Y Y Y Y Y Y Y y X . .
362
+ . . . X S S S S S S S S X . . .
363
+ . . . X S S S S S S S S X . . .
364
+ . . X S S E P S S E P S S X . .
365
+ . . X S S S S S s S S S S X . .
366
+ . . X S S S M M M S S S S X . .
367
+ . . . X S S S S S S S S X . . .
368
+ . . . . X X S S S S X X . . . .
369
+ . . . . X V V G G V V X . . . .
370
+ . . . X V V G G G G V V X . . .
371
+ . . X V V V G G G G V V V X . .
372
+ . . X s V V V V V V V V s X . .
373
+ . . . X V V V V V V V V X . . .
374
+ . . . X T T V V V V T T X . . .
375
+ . . . . X N N N N N N X . . . .
376
+ . . . . X N N N N N N X . . . .
377
+ . . . . X N N . . N N X . . . .
378
+ . . . . X N N . . N N X . . . .
379
+ . . . . X n n . . n n X . . . .
380
+ . . . . X A A . . A A X . . . .
381
+ . . . . A a a . . a a A . . . .
382
+ . . . . . . . . . . . . . . . .`, arP);
383
+
384
+ const ARCH_IDLE_1 = p(`
385
+ . . . . X X X X X X X X . . . .
386
+ . . . X Y Y Y Z Y Y Y Y X . . .
387
+ . . X y Y Y Y Y Y Y Y Y y X . .
388
+ . . . X S S S S S S S S X . . .
389
+ . . . X S S S S S S S S X . . .
390
+ . . X S S s s S S s s S S X . .
391
+ . . X S S S S S s S S S S X . .
392
+ . . X S S S M M M S S S S X . .
393
+ . . . X S S S S S S S S X . . .
394
+ . . . . X X S S S S X X . . . .
395
+ . . . . X V V G G V V X . . . .
396
+ . . . X V V G G G G V V X . . .
397
+ . . X V V V G G G G V V V X . .
398
+ . . X s V V V V V V V V s X . .
399
+ . . . X V V V V V V V V X . . .
400
+ . . . X T T V V V V T T X . . .
401
+ . . . . X N N N N N N X . . . .
402
+ . . . . X N N N N N N X . . . .
403
+ . . . . X N N . . N N X . . . .
404
+ . . . . X N N . . N N X . . . .
405
+ . . . . X n n . . n n X . . . .
406
+ . . . . X A A . . A A X . . . .
407
+ . . . . A a a . . a a A . . . .
408
+ . . . . . . . . . . . . . . . .`, arP);
409
+
410
+ const ARCH_WALK_D0 = p(`
411
+ . . . . X X X X X X X X . . . .
412
+ . . . X Y Y Y Z Y Y Y Y X . . .
413
+ . . X y Y Y Y Y Y Y Y Y y X . .
414
+ . . . X S S S S S S S S X . . .
415
+ . . . X S S S S S S S S X . . .
416
+ . . X S S E P S S E P S S X . .
417
+ . . X S S S S S s S S S S X . .
418
+ . . X S S S M M M S S S S X . .
419
+ . . . X S S S S S S S S X . . .
420
+ . . . . X X S S S S X X . . . .
421
+ . . . . X V V G G V V X . . . .
422
+ . . . X V V G G G G V V X . . .
423
+ . . X V V V G G G G V V V X . .
424
+ . . X s V V V V V V V V s X . .
425
+ . . . X V V V V V V V V X . . .
426
+ . . . X T T V V V V T T X . . .
427
+ . . . . X N N N N N N X . . . .
428
+ . . . X N N N . . N N N X . . .
429
+ . . X N N X . . . . X N N X . .
430
+ . . X n n X . . . . X n n X . .
431
+ . . X A A X . . . . X A A X . .
432
+ . . A a a X . . . . X a a A . .
433
+ . . . . . . . . . . . . . . . .
434
+ . . . . . . . . . . . . . . . .`, arP);
435
+
436
+ const ARCH_WALK_D1 = p(`
437
+ . . . . X X X X X X X X . . . .
438
+ . . . X Y Y Y Z Y Y Y Y X . . .
439
+ . . X y Y Y Y Y Y Y Y Y y X . .
440
+ . . . X S S S S S S S S X . . .
441
+ . . . X S S S S S S S S X . . .
442
+ . . X S S E P S S E P S S X . .
443
+ . . X S S S S S s S S S S X . .
444
+ . . X S S S M M M S S S S X . .
445
+ . . . X S S S S S S S S X . . .
446
+ . . . . X X S S S S X X . . . .
447
+ . . . . X V V G G V V X . . . .
448
+ . . . X V V G G G G V V X . . .
449
+ . . X V V V G G G G V V V X . .
450
+ . . X s V V V V V V V V s X . .
451
+ . . . X V V V V V V V V X . . .
452
+ . . . X T T V V V V T T X . . .
453
+ . . . . X N N N N N N X . . . .
454
+ . . . . X N N . . N N N X . . .
455
+ . . . . X N N . . X N N X . . .
456
+ . . . . X n n . . X n n X . . .
457
+ . . . . X A A . . X A A X . . .
458
+ . . . . X a a A A a a X . . . .
459
+ . . . . . . . . . . . . . . . .
460
+ . . . . . . . . . . . . . . . .`, arP);
461
+
462
+ const ARCH_WALK_UP0 = p(`
463
+ . . . . X X X X X X X X . . . .
464
+ . . . X Y Y Y Y Y Y Y Y X . . .
465
+ . . X y Y Y Y Y Y Y Y Y y X . .
466
+ . . . X S S S S S S S S X . . .
467
+ . . . X S S S S S S S S X . . .
468
+ . . . X S S S S S S S S X . . .
469
+ . . X S S S S S S S S S S X . .
470
+ . . . X S S S S S S S S X . . .
471
+ . . . . X X S S S S X X . . . .
472
+ . . . . X V V G G V V X . . . .
473
+ . . . X V V G G G G V V X . . .
474
+ . . X V V V G G G G V V V X . .
475
+ . . X s V V V V V V V V s X . .
476
+ . . . X V V V V V V V V X . . .
477
+ . . . X T T V V V V T T X . . .
478
+ . . . . X N N N N N N X . . . .
479
+ . . . . X N N N N N N X . . . .
480
+ . . . X N N N . . N N N X . . .
481
+ . . X N N X . . . . X N N X . .
482
+ . . X n n X . . . . X n n X . .
483
+ . . X A A X . . . . X A A X . .
484
+ . . A a a X . . . . X a a A . .
485
+ . . . . . . . . . . . . . . . .
486
+ . . . . . . . . . . . . . . . .`, arP);
487
+
488
+ const ARCH_DESIGN_0 = p(`
489
+ . . . . X X X X X X X X . . . .
490
+ . . . X Y Y Y Z Y Y Y Y X . . .
491
+ . . X y Y Y Y Y Y Y Y Y y X . .
492
+ . . . X S S S S S S S S X . . .
493
+ . . . X S S S S S S S S X . . .
494
+ . . X S S E P S S E P S S X . .
495
+ . . X S S S S S s S S S S X . .
496
+ . . X S S S M M M S S S S X . .
497
+ . . . X S S S S S S S S X . . .
498
+ . . . . X X S S S S X X . . . .
499
+ . . . . X V V G G V V X . . . .
500
+ . . . X V V G G G G V V X . . .
501
+ . . X s V V V V V V V V s X . .
502
+ . . . X V V V V V V V V s s X .
503
+ . . . X V V V V V V V X S S X .
504
+ . . . X T T V V V V T X X S X .
505
+ . . . . X N N N N N N X . X . .
506
+ . . . . X N N N N N N X . . . .
507
+ . . . . X N N . . N N X . . . .
508
+ . . . . X N N . . N N X . . . .
509
+ . . . . X n n . . n n X . . . .
510
+ . . . . X A A . . A A X . . . .
511
+ . . . . A a a . . a a A . . . .
512
+ . . . . . . . . . . . . . . . .`, arP);
513
+
514
+ const ARCH_DESIGN_1 = p(`
515
+ . . . . X X X X X X X X . . . .
516
+ . . . X Y Y Y Z Y Y Y Y X . . .
517
+ . . X y Y Y Y Y Y Y Y Y y X . .
518
+ . . . X S S S S S S S S X . . .
519
+ . . . X S S S S S S S S X . . .
520
+ . . X S S E P S S E P S S X . .
521
+ . . X S S S S S s S S S S X . .
522
+ . . X S S S M M M S S S S X . .
523
+ . . . X S S S S S S S S X . . .
524
+ . . . . X X S S S S X X . . . .
525
+ . . . . X V V G G V V X . . . .
526
+ . . . X V V G G G G V V X . . .
527
+ . X S s V V V V V V V V s X . .
528
+ X S X X V V V V V V V V X . . .
529
+ X S X X V V V V V V V V X . . .
530
+ . X . X T T V V V V T T X . . .
531
+ . . . . X N N N N N N X . . . .
532
+ . . . . X N N N N N N X . . . .
533
+ . . . . X N N . . N N X . . . .
534
+ . . . . X N N . . N N X . . . .
535
+ . . . . X n n . . n n X . . . .
536
+ . . . . X A A . . A A X . . . .
537
+ . . . . A a a . . a a A . . . .
538
+ . . . . . . . . . . . . . . . .`, arP);
539
+
540
+ // ============================================================
541
+ // CODER (Copilot) — Dark skin, black spiky hair, purple hoodie
542
+ // ============================================================
543
+ const cdP = {
544
+ '.': null, X,
545
+ H: '#1a1a2e', h: '#2a2a3e', D: '#3a3a4e', // spiky hair + highlights
546
+ Q: '#303040', q: '#404050', // headphones
547
+ S: '#8b6544', s: '#6a4c30', P: '#a07850', // dark skin
548
+ E: '#1a1a2e', W: '#e8e8e0', M: '#7a5040', // eyes/whites/mouth
549
+ C: '#5030a0', c: '#3a2080', L: '#6040b0', // hoodie
550
+ J: '#2a2a4a', j: '#1a1a3a', // jeans
551
+ K: '#d0d0d0', k: '#b0b0b0', // sneakers (white/gray)
552
+ };
553
+
554
+ const CODER_IDLE_0 = p(`
555
+ . . . . . X H D H X . . . . . .
556
+ . . . . X H H D H H H X . . . .
557
+ . . . X H H h H H h H H X . . .
558
+ . . X Q H H H H H H H H Q X . .
559
+ . . X q S S S S S S S S q X . .
560
+ . . X S S E W S S E W S S X . .
561
+ . . X S S S S S s S S S S X . .
562
+ . . X S S S M M M S S S S X . .
563
+ . . . X S S S S S S S S X . . .
564
+ . . . . X X S S S S X X . . . .
565
+ . . . X C C C C C C C C X . . .
566
+ . . X C C C c C C c C C C X . .
567
+ . . X C C C C C C C C C C X . .
568
+ . . X s C C C C C C C C s X . .
569
+ . . . X C C C C C C C C X . . .
570
+ . . . X c C C C C C C c X . . .
571
+ . . . . X J J J J J J X . . . .
572
+ . . . . X J J J J J J X . . . .
573
+ . . . . X J J . . J J X . . . .
574
+ . . . . X J J . . J J X . . . .
575
+ . . . . X j j . . j j X . . . .
576
+ . . . . X K K . . K K X . . . .
577
+ . . . . K k k . . k k K . . . .
578
+ . . . . . . . . . . . . . . . .`, cdP);
579
+
580
+ const CODER_IDLE_1 = p(`
581
+ . . . . . X H D H X . . . . . .
582
+ . . . . X H H D H H H X . . . .
583
+ . . . X H H h H H h H H X . . .
584
+ . . X Q H H H H H H H H Q X . .
585
+ . . X q S S S S S S S S q X . .
586
+ . . X S S s s S S s s S S X . .
587
+ . . X S S S S S s S S S S X . .
588
+ . . X S S S M M M S S S S X . .
589
+ . . . X S S S S S S S S X . . .
590
+ . . . . X X S S S S X X . . . .
591
+ . . . X C C C C C C C C X . . .
592
+ . . X C C C c C C c C C C X . .
593
+ . . X C C C C C C C C C C X . .
594
+ . . X s C C C C C C C C s X . .
595
+ . . . X C C C C C C C C X . . .
596
+ . . . X c C C C C C C c X . . .
597
+ . . . . X J J J J J J X . . . .
598
+ . . . . X J J J J J J X . . . .
599
+ . . . . X J J . . J J X . . . .
600
+ . . . . X J J . . J J X . . . .
601
+ . . . . X j j . . j j X . . . .
602
+ . . . . X K K . . K K X . . . .
603
+ . . . . K k k . . k k K . . . .
604
+ . . . . . . . . . . . . . . . .`, cdP);
605
+
606
+ const CODER_WALK_D0 = p(`
607
+ . . . . . X H D H X . . . . . .
608
+ . . . . X H H D H H H X . . . .
609
+ . . . X H H h H H h H H X . . .
610
+ . . X Q H H H H H H H H Q X . .
611
+ . . X q S S S S S S S S q X . .
612
+ . . X S S E W S S E W S S X . .
613
+ . . X S S S S S s S S S S X . .
614
+ . . X S S S M M M S S S S X . .
615
+ . . . X S S S S S S S S X . . .
616
+ . . . . X X S S S S X X . . . .
617
+ . . . X C C C C C C C C X . . .
618
+ . . X C C C c C C c C C C X . .
619
+ . . X C C C C C C C C C C X . .
620
+ . . X s C C C C C C C C s X . .
621
+ . . . X C C C C C C C C X . . .
622
+ . . . X c C C C C C C c X . . .
623
+ . . . . X J J J J J J X . . . .
624
+ . . . X J J J . . J J J X . . .
625
+ . . X J J X . . . . X J J X . .
626
+ . . X j j X . . . . X j j X . .
627
+ . . X K K X . . . . X K K X . .
628
+ . . K k k X . . . . X k k K . .
629
+ . . . . . . . . . . . . . . . .
630
+ . . . . . . . . . . . . . . . .`, cdP);
631
+
632
+ const CODER_WALK_D1 = p(`
633
+ . . . . . X H D H X . . . . . .
634
+ . . . . X H H D H H H X . . . .
635
+ . . . X H H h H H h H H X . . .
636
+ . . X Q H H H H H H H H Q X . .
637
+ . . X q S S S S S S S S q X . .
638
+ . . X S S E W S S E W S S X . .
639
+ . . X S S S S S s S S S S X . .
640
+ . . X S S S M M M S S S S X . .
641
+ . . . X S S S S S S S S X . . .
642
+ . . . . X X S S S S X X . . . .
643
+ . . . X C C C C C C C C X . . .
644
+ . . X C C C c C C c C C C X . .
645
+ . . X C C C C C C C C C C X . .
646
+ . . X s C C C C C C C C s X . .
647
+ . . . X C C C C C C C C X . . .
648
+ . . . X c C C C C C C c X . . .
649
+ . . . . X J J J J J J X . . . .
650
+ . . . . X J J . . J J J X . . .
651
+ . . . . X J J . . X J J X . . .
652
+ . . . . X j j . . X j j X . . .
653
+ . . . . X K K . . X K K X . . .
654
+ . . . . X k k K K k k X . . . .
655
+ . . . . . . . . . . . . . . . .
656
+ . . . . . . . . . . . . . . . .`, cdP);
657
+
658
+ const CODER_WALK_UP0 = p(`
659
+ . . . . . X H D H X . . . . . .
660
+ . . . . X H H D H H H X . . . .
661
+ . . . X H H h H H h H H X . . .
662
+ . . X Q H H H H H H H H Q X . .
663
+ . . X q H H H H H H H H q X . .
664
+ . . X S S H H H H H H S S X . .
665
+ . . X S S S S S S S S S S X . .
666
+ . . . X S S S S S S S S X . . .
667
+ . . . . X X S S S S X X . . . .
668
+ . . . . X C C C C C C X . . . .
669
+ . . . X C C C C C C C C X . . .
670
+ . . X C C C C C C C C C C X . .
671
+ . . X s C C C C C C C C s X . .
672
+ . . . X C C C C C C C C X . . .
673
+ . . . X c C C C C C C c X . . .
674
+ . . . . X J J J J J J X . . . .
675
+ . . . . X J J J J J J X . . . .
676
+ . . . X J J J . . J J J X . . .
677
+ . . X J J X . . . . X J J X . .
678
+ . . X j j X . . . . X j j X . .
679
+ . . X K K X . . . . X K K X . .
680
+ . . K k k X . . . . X k k K . .
681
+ . . . . . . . . . . . . . . . .
682
+ . . . . . . . . . . . . . . . .`, cdP);
683
+
684
+ const CODER_WORK_0 = p(`
685
+ . . . . . X H D H X . . . . . .
686
+ . . . . X H H D H H H X . . . .
687
+ . . . X H H h H H h H H X . . .
688
+ . . X Q H H H H H H H H Q X . .
689
+ . . X q S S S S S S S S q X . .
690
+ . . X S S E W S S E W S S X . .
691
+ . . X S S S S S s S S S S X . .
692
+ . . X S S S S S S S S S S X . .
693
+ . . . X S S S S S S S S X . . .
694
+ . . . . X X S S S S X X . . . .
695
+ . . . X C C C C C C C C X . . .
696
+ . . X C C C c C C c C C C X . .
697
+ . . X s C C C C C C C C s X . .
698
+ . X S s C C C C C C C C s S X .
699
+ X S X C C C C C C C C C C X S X
700
+ . X X . C C C C C C C C . X X .
701
+ . . . . X J J J J J J X . . . .
702
+ . . . . X J J J J J J X . . . .
703
+ . . . . X J J . . J J X . . . .
704
+ . . . . X J J . . J J X . . . .
705
+ . . . . X j j . . j j X . . . .
706
+ . . . . X K K . . K K X . . . .
707
+ . . . . K k k . . k k K . . . .
708
+ . . . . . . . . . . . . . . . .`, cdP);
709
+
710
+ const CODER_WORK_1 = p(`
711
+ . . . . . X H D H X . . . . . .
712
+ . . . . X H H D H H H X . . . .
713
+ . . . X H H h H H h H H X . . .
714
+ . . X Q H H H H H H H H Q X . .
715
+ . . X q S S S S S S S S q X . .
716
+ . . X S S E W S S E W S S X . .
717
+ . . X S S S S S s S S S S X . .
718
+ . . X S S S S S S S S S S X . .
719
+ . . . X S S S S S S S S X . . .
720
+ . . . . X X S S S S X X . . . .
721
+ . . . X C C C C C C C C X . . .
722
+ . . X C C C c C C c C C C X . .
723
+ . . X s C C C C C C C C s X . .
724
+ . X S s C C C C C C C C s S X .
725
+ . X S C C C C C C C C C C S X .
726
+ . X X . C C C C C C C C . X X .
727
+ . . . . X J J J J J J X . . . .
728
+ . . . . X J J J J J J X . . . .
729
+ . . . . X J J . . J J X . . . .
730
+ . . . . X J J . . J J X . . . .
731
+ . . . . X j j . . j j X . . . .
732
+ . . . . X K K . . K K X . . . .
733
+ . . . . K k k . . k k K . . . .
734
+ . . . . . . . . . . . . . . . .`, cdP);
735
+
736
+ const CODER_FIGHT = p(`
737
+ . . . . . X H D H X . . . . . .
738
+ . . . . X H H D H H H X . . . .
739
+ . . . X H H h H H h H H X . . .
740
+ . . X Q H H H H H H H H Q X . .
741
+ . . X q S S S S S S S S q X . .
742
+ . . X S S E W S S E W S S X . .
743
+ . . X S S S S S s S S S S X . .
744
+ . . X S S S M M M S S S S X . .
745
+ . . . X S S S S S S S S X . . .
746
+ . . . . X X S S S S X X . . . .
747
+ . . . X C C C C C C C C X . . .
748
+ . . X C C C c C C c C C C X . .
749
+ . . X s C C C C C C C C s X X .
750
+ . X S s C C C C C C C C s X X X
751
+ X S X C C C C C C C C C X X X .
752
+ . X X . C C C C C C C C X . . .
753
+ . . . . X J J J J J J X . . . .
754
+ . . . . X J J J J J J X . . . .
755
+ . . . X J J . . . . J J X . . .
756
+ . . X J J X . . . . X J J X . .
757
+ . . X j j X . . . . X j j X . .
758
+ . . X K K X . . . . X K K X . .
759
+ . . K k k X . . . . X k k K . .
760
+ . . . . . . . . . . . . . . . .`, cdP);
761
+
762
+ // ============================================================
763
+ // DEPLOYER — Tan skin, red cap, brown uniform
764
+ // ============================================================
765
+ const dpP = {
766
+ '.': null, X,
767
+ R: '#c03030', r: '#a02020', F: '#e04040', // cap
768
+ H: '#6a4830', h: '#8a6040', // short hair under cap
769
+ S: '#e8b080', s: '#c89060', P: '#ffc8a0', // tan skin
770
+ E: '#2a2a40', M: '#a07060', // eyes/mouth
771
+ U: '#6a4a2a', u: '#5a3a1a', B: '#7a5a3a', // uniform brown
772
+ G: '#c8a050', g: '#a88030', // package tan
773
+ N: '#a08050', n: '#907040', // khaki pants
774
+ K: '#3a2a1a', k: '#4a3a2a', // dark boots
775
+ W: '#e8e8e0', // white (badge)
776
+ };
777
+
778
+ const DEPLOY_IDLE_0 = p(`
779
+ . . . . X X X X X X X X X . . .
780
+ . . . X R R R F R R R R R X . .
781
+ . . . X r R R R R R R R r X . .
782
+ . . . X H S S S S S S H X . . .
783
+ . . . X S S S S S S S S X . . .
784
+ . . X S S E P S S E P S S X . .
785
+ . . X S S S S S s S S S S X . .
786
+ . . X S S S M M M S S S S X . .
787
+ . . . X S S S S S S S S X . . .
788
+ . . . . X X S S S S X X . . . .
789
+ . . . . X U U U U U U X . . . .
790
+ . . . X U U W U U W U U X . . .
791
+ . . X U U U U U U U U U U X . .
792
+ . . X s U U U U U U U U s X . .
793
+ . . . X U U U U U U U U X . . .
794
+ . . . X u U U U U U U u X . . .
795
+ . . . . X N N N N N N X . . . .
796
+ . . . . X N N N N N N X . . . .
797
+ . . . . X N N . . N N X . . . .
798
+ . . . . X N N . . N N X . . . .
799
+ . . . . X n n . . n n X . . . .
800
+ . . . . X K K . . K K X . . . .
801
+ . . . . K k k . . k k K . . . .
802
+ . . . . . . . . . . . . . . . .`, dpP);
803
+
804
+ const DEPLOY_IDLE_1 = p(`
805
+ . . . . X X X X X X X X X . . .
806
+ . . . X R R R F R R R R R X . .
807
+ . . . X r R R R R R R R r X . .
808
+ . . . X H S S S S S S H X . . .
809
+ . . . X S S S S S S S S X . . .
810
+ . . X S S s s S S s s S S X . .
811
+ . . X S S S S S s S S S S X . .
812
+ . . X S S S M M M S S S S X . .
813
+ . . . X S S S S S S S S X . . .
814
+ . . . . X X S S S S X X . . . .
815
+ . . . . X U U U U U U X . . . .
816
+ . . . X U U W U U W U U X . . .
817
+ . . X U U U U U U U U U U X . .
818
+ . . X s U U U U U U U U s X . .
819
+ . . . X U U U U U U U U X . . .
820
+ . . . X u U U U U U U u X . . .
821
+ . . . . X N N N N N N X . . . .
822
+ . . . . X N N N N N N X . . . .
823
+ . . . . X N N . . N N X . . . .
824
+ . . . . X N N . . N N X . . . .
825
+ . . . . X n n . . n n X . . . .
826
+ . . . . X K K . . K K X . . . .
827
+ . . . . K k k . . k k K . . . .
828
+ . . . . . . . . . . . . . . . .`, dpP);
829
+
830
+ const DEPLOY_WALK_D0 = p(`
831
+ . . . . X X X X X X X X X . . .
832
+ . . . X R R R F R R R R R X . .
833
+ . . . X r R R R R R R R r X . .
834
+ . . . X H S S S S S S H X . . .
835
+ . . . X S S S S S S S S X . . .
836
+ . . X S S E P S S E P S S X . .
837
+ . . X S S S S S s S S S S X . .
838
+ . . X S S S M M M S S S S X . .
839
+ . . . X S S S S S S S S X . . .
840
+ . . . . X X S S S S X X . . . .
841
+ . . . . X U U U U U U X . . . .
842
+ . . . X U U W U U W U U X . . .
843
+ . . X U U U U U U U U U U X . .
844
+ . . X s U U U U U U U U s X . .
845
+ . . . X U U U U U U U U X . . .
846
+ . . . X u U U U U U U u X . . .
847
+ . . . . X N N N N N N X . . . .
848
+ . . . X N N N . . N N N X . . .
849
+ . . X N N X . . . . X N N X . .
850
+ . . X n n X . . . . X n n X . .
851
+ . . X K K X . . . . X K K X . .
852
+ . . K k k X . . . . X k k K . .
853
+ . . . . . . . . . . . . . . . .
854
+ . . . . . . . . . . . . . . . .`, dpP);
855
+
856
+ const DEPLOY_WALK_D1 = p(`
857
+ . . . . X X X X X X X X X . . .
858
+ . . . X R R R F R R R R R X . .
859
+ . . . X r R R R R R R R r X . .
860
+ . . . X H S S S S S S H X . . .
861
+ . . . X S S S S S S S S X . . .
862
+ . . X S S E P S S E P S S X . .
863
+ . . X S S S S S s S S S S X . .
864
+ . . X S S S M M M S S S S X . .
865
+ . . . X S S S S S S S S X . . .
866
+ . . . . X X S S S S X X . . . .
867
+ . . . . X U U U U U U X . . . .
868
+ . . . X U U W U U W U U X . . .
869
+ . . X U U U U U U U U U U X . .
870
+ . . X s U U U U U U U U s X . .
871
+ . . . X U U U U U U U U X . . .
872
+ . . . X u U U U U U U u X . . .
873
+ . . . . X N N N N N N X . . . .
874
+ . . . . X N N . . N N N X . . .
875
+ . . . . X N N . . X N N X . . .
876
+ . . . . X n n . . X n n X . . .
877
+ . . . . X K K . . X K K X . . .
878
+ . . . . X k k K K k k X . . . .
879
+ . . . . . . . . . . . . . . . .
880
+ . . . . . . . . . . . . . . . .`, dpP);
881
+
882
+ const DEPLOY_WALK_UP0 = p(`
883
+ . . . . X X X X X X X X X . . .
884
+ . . . X R R R R R R R R R X . .
885
+ . . . X r R R R R R R R r X . .
886
+ . . . X H H H H H H H H X . . .
887
+ . . . X H H H H H H H H X . . .
888
+ . . . X S S H H H H S S X . . .
889
+ . . X S S S S S S S S S S X . .
890
+ . . . X S S S S S S S S X . . .
891
+ . . . . X X S S S S X X . . . .
892
+ . . . . X U U U U U U X . . . .
893
+ . . . X U U U U U U U U X . . .
894
+ . . X U U U U U U U U U U X . .
895
+ . . X s U U U U U U U U s X . .
896
+ . . . X U U U U U U U U X . . .
897
+ . . . X u U U U U U U u X . . .
898
+ . . . . X N N N N N N X . . . .
899
+ . . . . X N N N N N N X . . . .
900
+ . . . X N N N . . N N N X . . .
901
+ . . X N N X . . . . X N N X . .
902
+ . . X n n X . . . . X n n X . .
903
+ . . X K K X . . . . X K K X . .
904
+ . . K k k X . . . . X k k K . .
905
+ . . . . . . . . . . . . . . . .
906
+ . . . . . . . . . . . . . . . .`, dpP);
907
+
908
+ const DEPLOY_DEPLOY_0 = p(`
909
+ . . . . X X X X X X X X X . . .
910
+ . . . X R R R F R R R R R X . .
911
+ . . . X r R R R R R R R r X . .
912
+ . . . X H S S S S S S H X . . .
913
+ . . . X S S S S S S S S X . . .
914
+ . . X S S E P S S E P S S X . .
915
+ . . X S S S S S s S S S S X . .
916
+ . . X S S S S S S S S S S X . .
917
+ . . . X S S S S S S S S X . . .
918
+ . . . . X X S S S S X X . . . .
919
+ . . . . X U U U U U U X . . . .
920
+ . . . X U U W U U W U U X . . .
921
+ . . X s U U U U U U U U s X . .
922
+ . X S s U U U U U U U U s S X .
923
+ X S X G G G G G G G G G G X S X
924
+ . X X g G X G G X G g g X X X .
925
+ . . . g G G G G G G G g . . . .
926
+ . . . . X N N N N N N X . . . .
927
+ . . . . X N N . . N N X . . . .
928
+ . . . . X N N . . N N X . . . .
929
+ . . . . X n n . . n n X . . . .
930
+ . . . . X K K . . K K X . . . .
931
+ . . . . K k k . . k k K . . . .
932
+ . . . . . . . . . . . . . . . .`, dpP);
933
+
934
+ const DEPLOY_DEPLOY_1 = p(`
935
+ . . . . X X X X X X X X X . . .
936
+ . . . X R R R F R R R R R X . .
937
+ . . . X r R R R R R R R r X . .
938
+ . . . X H S S S S S S H X . . .
939
+ . . . X S S S S S S S S X . . .
940
+ . . X S S E P S S E P S S X . .
941
+ . . X S S S S S s S S S S X . .
942
+ . . X S S S S S S S S S S X . .
943
+ . . . X S S S S S S S S X . . .
944
+ . . . . X X S S S S X X . . . .
945
+ . . . . X U U U U U U X . . . .
946
+ . . . X U U W U U W U U X . . .
947
+ . . X s U U U U U U U U s X . .
948
+ . X S s U U U U U U U U s S X .
949
+ . X S G G G G G G G G G G S X .
950
+ . X X g G X G G X G g g X X X .
951
+ . . . g G G G G G G G g . . . .
952
+ . . . . X N N N N N N X . . . .
953
+ . . . X N N N . . N N N X . . .
954
+ . . X N N X . . . . X N N X . .
955
+ . . X n n X . . . . X n n X . .
956
+ . . X K K X . . . . X K K X . .
957
+ . . K k k X . . . . X k k K . .
958
+ . . . . . . . . . . . . . . . .`, dpP);
959
+
960
+ // ============================================================
961
+ // SPRITE REGISTRY
962
+ // ============================================================
963
+ const SPRITES = {
964
+ pm: {
965
+ idle: [PM_IDLE_0, PM_IDLE_1, PM_IDLE_0, PM_IDLE_0],
966
+ walk_down: [PM_WALK_D0, PM_WALK_D1, PM_WALK_D0, PM_WALK_D1],
967
+ walk_up: [PM_WALK_UP0, PM_WALK_UP1, PM_WALK_UP0, PM_WALK_UP1],
968
+ walk_side: [PM_SIDE_0, PM_SIDE_1, PM_SIDE_0, PM_SIDE_1],
969
+ working: [PM_WORK_0, PM_WORK_1, PM_WORK_0, PM_WORK_1],
970
+ thinking: [PM_IDLE_0, PM_IDLE_1, PM_IDLE_0, PM_IDLE_1],
971
+ reviewing: [PM_WORK_0, PM_WORK_1, PM_WORK_0, PM_WORK_1],
972
+ designing: [PM_WORK_0, PM_WORK_1, PM_WORK_0, PM_WORK_1],
973
+ fighting_bug: [PM_WORK_0, PM_WORK_1, PM_WORK_0, PM_WORK_1],
974
+ celebrating: [PM_CELEBRATE, PM_IDLE_0, PM_CELEBRATE, PM_IDLE_0],
975
+ frustrated: [PM_IDLE_0, PM_IDLE_1, PM_IDLE_0, PM_IDLE_1],
976
+ sleeping: [PM_SLEEP, PM_SLEEP, PM_SLEEP, PM_SLEEP],
977
+ deploying: [PM_WALK_D0, PM_WALK_D1, PM_WALK_D0, PM_WALK_D1],
978
+ handing_off: [PM_WORK_0, PM_WORK_1, PM_WORK_0, PM_WORK_1],
979
+ waiting_input:[PM_IDLE_0, PM_IDLE_1, PM_IDLE_0, PM_IDLE_1],
980
+ rate_limited: [PM_SLEEP, PM_SLEEP, PM_SLEEP, PM_SLEEP],
981
+ coffee_break: [PM_IDLE_0, PM_IDLE_1, PM_IDLE_0, PM_IDLE_1],
982
+ },
983
+ architect: {
984
+ idle: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_0],
985
+ walk_down: [ARCH_WALK_D0, ARCH_WALK_D1, ARCH_WALK_D0, ARCH_WALK_D1],
986
+ walk_up: [ARCH_WALK_UP0, ARCH_WALK_UP0, ARCH_WALK_UP0, ARCH_WALK_UP0],
987
+ walk_side: [ARCH_WALK_D0, ARCH_WALK_D1, ARCH_WALK_D0, ARCH_WALK_D1],
988
+ working: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
989
+ thinking: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
990
+ reviewing: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
991
+ designing: [ARCH_DESIGN_0, ARCH_DESIGN_1, ARCH_DESIGN_0, ARCH_DESIGN_1],
992
+ fighting_bug: [ARCH_DESIGN_0, ARCH_DESIGN_1, ARCH_DESIGN_0, ARCH_DESIGN_1],
993
+ celebrating: [ARCH_IDLE_0, ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0],
994
+ frustrated: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
995
+ sleeping: [ARCH_IDLE_1, ARCH_IDLE_1, ARCH_IDLE_1, ARCH_IDLE_1],
996
+ deploying: [ARCH_WALK_D0, ARCH_WALK_D1, ARCH_WALK_D0, ARCH_WALK_D1],
997
+ handing_off: [ARCH_DESIGN_0, ARCH_DESIGN_1, ARCH_DESIGN_0, ARCH_DESIGN_1],
998
+ waiting_input:[ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
999
+ rate_limited: [ARCH_IDLE_1, ARCH_IDLE_1, ARCH_IDLE_1, ARCH_IDLE_1],
1000
+ coffee_break: [ARCH_IDLE_0, ARCH_IDLE_1, ARCH_IDLE_0, ARCH_IDLE_1],
1001
+ },
1002
+ coder: {
1003
+ idle: [CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0, CODER_IDLE_0],
1004
+ walk_down: [CODER_WALK_D0, CODER_WALK_D1, CODER_WALK_D0, CODER_WALK_D1],
1005
+ walk_up: [CODER_WALK_UP0, CODER_WALK_UP0, CODER_WALK_UP0, CODER_WALK_UP0],
1006
+ walk_side: [CODER_WALK_D0, CODER_WALK_D1, CODER_WALK_D0, CODER_WALK_D1],
1007
+ working: [CODER_WORK_0, CODER_WORK_1, CODER_WORK_0, CODER_WORK_1],
1008
+ thinking: [CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0, CODER_IDLE_1],
1009
+ reviewing: [CODER_WORK_0, CODER_WORK_1, CODER_WORK_0, CODER_WORK_1],
1010
+ designing: [CODER_WORK_0, CODER_WORK_1, CODER_WORK_0, CODER_WORK_1],
1011
+ fighting_bug: [CODER_FIGHT, CODER_WORK_0, CODER_FIGHT, CODER_WORK_0],
1012
+ celebrating: [CODER_IDLE_0, CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0],
1013
+ frustrated: [CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0, CODER_IDLE_1],
1014
+ sleeping: [CODER_IDLE_1, CODER_IDLE_1, CODER_IDLE_1, CODER_IDLE_1],
1015
+ deploying: [CODER_WALK_D0, CODER_WALK_D1, CODER_WALK_D0, CODER_WALK_D1],
1016
+ handing_off: [CODER_WORK_0, CODER_WORK_1, CODER_WORK_0, CODER_WORK_1],
1017
+ waiting_input:[CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0, CODER_IDLE_1],
1018
+ rate_limited: [CODER_IDLE_1, CODER_IDLE_1, CODER_IDLE_1, CODER_IDLE_1],
1019
+ coffee_break: [CODER_IDLE_0, CODER_IDLE_1, CODER_IDLE_0, CODER_IDLE_1],
1020
+ },
1021
+ deployer: {
1022
+ idle: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_0],
1023
+ walk_down: [DEPLOY_WALK_D0, DEPLOY_WALK_D1, DEPLOY_WALK_D0, DEPLOY_WALK_D1],
1024
+ walk_up: [DEPLOY_WALK_UP0, DEPLOY_WALK_UP0, DEPLOY_WALK_UP0, DEPLOY_WALK_UP0],
1025
+ walk_side: [DEPLOY_WALK_D0, DEPLOY_WALK_D1, DEPLOY_WALK_D0, DEPLOY_WALK_D1],
1026
+ working: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1027
+ thinking: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1028
+ reviewing: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1029
+ designing: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1030
+ fighting_bug: [DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1, DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1],
1031
+ celebrating: [DEPLOY_IDLE_0, DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0],
1032
+ frustrated: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1033
+ sleeping: [DEPLOY_IDLE_1, DEPLOY_IDLE_1, DEPLOY_IDLE_1, DEPLOY_IDLE_1],
1034
+ deploying: [DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1, DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1],
1035
+ handing_off: [DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1, DEPLOY_DEPLOY_0, DEPLOY_DEPLOY_1],
1036
+ waiting_input:[DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1037
+ rate_limited: [DEPLOY_IDLE_1, DEPLOY_IDLE_1, DEPLOY_IDLE_1, DEPLOY_IDLE_1],
1038
+ coffee_break: [DEPLOY_IDLE_0, DEPLOY_IDLE_1, DEPLOY_IDLE_0, DEPLOY_IDLE_1],
1039
+ }
1040
+ };
1041
+
1042
+ // ============================================================
1043
+ // DIVERSE CHARACTER GENERATION
1044
+ // ============================================================
1045
+
1046
+ // ── DJB2 string hash ────────────────────────────────────────────────────────
1047
+ function simpleHash(str) {
1048
+ let hash = 5381;
1049
+ for (let i = 0; i < str.length; i++) {
1050
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0;
1051
+ }
1052
+ return hash;
1053
+ }
1054
+
1055
+ // ── Color pools ─────────────────────────────────────────────────────────────
1056
+
1057
+ const SKIN_TONES = [
1058
+ { base: '#f0c8a0', shadow: '#daa870', highlight: '#ffe0c0' }, // light peach
1059
+ { base: '#f5e0c8', shadow: '#e0c8a0', highlight: '#fff0e0' }, // fair warm
1060
+ { base: '#e8b888', shadow: '#c89868', highlight: '#fad0a8' }, // light olive
1061
+ { base: '#dca870', shadow: '#b88050', highlight: '#f0c090' }, // medium warm
1062
+ { base: '#c89060', shadow: '#a07048', highlight: '#e0a878' }, // tan
1063
+ { base: '#a07850', shadow: '#886038', highlight: '#b89068' }, // medium brown
1064
+ { base: '#8b6544', shadow: '#6a4c30', highlight: '#a07850' }, // dark warm
1065
+ { base: '#6b4423', shadow: '#4a2e14', highlight: '#8b6040' }, // deep brown
1066
+ ];
1067
+
1068
+ // ── Diversity skin tone pools ───────────────────────────────────────────────
1069
+ // Each role is assigned a diversity type to guarantee at least 1 Asian, 1 Black,
1070
+ // 1 White, and 1 Female character per project.
1071
+ const DIVERSITY_SKIN = {
1072
+ asian: [
1073
+ { base: '#D4A574', shadow: '#B8895C', highlight: '#E8BB8A' },
1074
+ { base: '#C8A078', shadow: '#AC8660', highlight: '#DCB68E' },
1075
+ { base: '#DEB887', shadow: '#C29E6F', highlight: '#F2CEA0' },
1076
+ { base: '#C19A6B', shadow: '#A58053', highlight: '#D5B081' },
1077
+ ],
1078
+ black: [
1079
+ { base: '#6B4423', shadow: '#4F3018', highlight: '#875A35' },
1080
+ { base: '#8B5E3C', shadow: '#6F4A2C', highlight: '#A7744E' },
1081
+ { base: '#7B4B2A', shadow: '#5F371E', highlight: '#97613C' },
1082
+ { base: '#5C3317', shadow: '#42230F', highlight: '#784929' },
1083
+ ],
1084
+ white: [
1085
+ { base: '#FFD5B8', shadow: '#E3BB9E', highlight: '#FFEBD2' },
1086
+ { base: '#F0C8A0', shadow: '#D4AE86', highlight: '#FFDEBA' },
1087
+ { base: '#FFDAB9', shadow: '#E3C09F', highlight: '#FFF0D3' },
1088
+ { base: '#FFE0BD', shadow: '#E3C6A3', highlight: '#FFF6D7' },
1089
+ ],
1090
+ female: [
1091
+ { base: '#F0C8A0', shadow: '#D4AE86', highlight: '#FFDEBA' },
1092
+ { base: '#D4A574', shadow: '#B8895C', highlight: '#E8BB8A' },
1093
+ { base: '#DEB887', shadow: '#C29E6F', highlight: '#F2CEA0' },
1094
+ { base: '#C68642', shadow: '#AA6C2E', highlight: '#E29C58' },
1095
+ ],
1096
+ };
1097
+
1098
+ // Map each role to a diversity type
1099
+ const ROLE_DIVERSITY = {
1100
+ pm: 'female', // PM → Female character
1101
+ arch: 'asian', // Architect → Asian skin tone
1102
+ architect:'asian', // alias
1103
+ coder: 'black', // Coder → Black skin tone
1104
+ deployer: 'white', // Deployer → White/European skin tone
1105
+ };
1106
+
1107
+ // Hair colors with brighter/longer-looking options for the female PM role
1108
+ const FEMALE_HAIR_COLORS = [
1109
+ { main: '#8B4513', shadow: '#6B3010' }, // warm chestnut
1110
+ { main: '#2a1a10', shadow: '#1a0c06' }, // dark brown
1111
+ { main: '#c8a050', shadow: '#a08030' }, // blonde
1112
+ { main: '#d06020', shadow: '#a04010' }, // ginger
1113
+ { main: '#6a3020', shadow: '#4a1810' }, // auburn
1114
+ { main: '#1a0a08', shadow: '#0a0404' }, // jet black
1115
+ { main: '#c07040', shadow: '#a05020' }, // copper
1116
+ { main: '#8040b0', shadow: '#602888' }, // purple-dyed
1117
+ ];
1118
+
1119
+ const HAIR_COLORS = [
1120
+ { main: '#0a0a10', shadow: '#050508' }, // black
1121
+ { main: '#2a1a10', shadow: '#1a0c06' }, // dark brown
1122
+ { main: '#3a2818', shadow: '#2a1808' }, // brown
1123
+ { main: '#6a3020', shadow: '#4a1810' }, // auburn
1124
+ { main: '#c8a050', shadow: '#a08030' }, // blonde
1125
+ { main: '#d06020', shadow: '#a04010' }, // ginger
1126
+ { main: '#808088', shadow: '#606068' }, // gray
1127
+ { main: '#e0e0e0', shadow: '#b8b8b8' }, // white
1128
+ { main: '#3060c0', shadow: '#204090' }, // blue-dyed
1129
+ { main: '#8040b0', shadow: '#602888' }, // purple-dyed
1130
+ ];
1131
+
1132
+ // Per-role clothing color pools
1133
+ const CLOTHING_COLORS = {
1134
+ pm: [
1135
+ { primary: '#2a4080', secondary: '#1a3060', accent: '#3a60a0', tie: '#c03030', tieDark: '#901818' }, // navy + red tie
1136
+ { primary: '#303030', secondary: '#1a1a1a', accent: '#484848', tie: '#c0a030', tieDark: '#907020' }, // charcoal + gold tie
1137
+ { primary: '#2a3a2a', secondary: '#1a2a1a', accent: '#3a4a3a', tie: '#4080c0', tieDark: '#306090' }, // dark green + blue tie
1138
+ { primary: '#40304a', secondary: '#2a1a3a', accent: '#58405a', tie: '#d08040', tieDark: '#a06020' }, // plum + orange tie
1139
+ { primary: '#3a3040', secondary: '#2a2030', accent: '#504050', tie: '#40a060', tieDark: '#208040' }, // dark mauve + green tie
1140
+ { primary: '#2a2a40', secondary: '#1a1a30', accent: '#3a3a58', tie: '#e04050', tieDark: '#b02838' }, // midnight + coral tie
1141
+ { primary: '#4a3828', secondary: '#3a2818', accent: '#5a4838', tie: '#3090c0', tieDark: '#207090' }, // brown + teal tie
1142
+ { primary: '#283848', secondary: '#182838', accent: '#385060', tie: '#d0a040', tieDark: '#a08020' }, // steel blue + amber tie
1143
+ { primary: '#3a2020', secondary: '#2a1010', accent: '#4a3030', tie: '#60a0d0', tieDark: '#4080a0' }, // burgundy + sky tie
1144
+ { primary: '#384030', secondary: '#283020', accent: '#485040', tie: '#c04080', tieDark: '#903060' }, // olive + magenta tie
1145
+ ],
1146
+ architect: [
1147
+ { primary: '#e08020', secondary: '#c06010', hat: '#e8c820', hatDark: '#c8a810', hatLight: '#f0d830', shirt: '#808090', shirtDark: '#606070', belt: '#5a4a3a' }, // orange vest, yellow hat
1148
+ { primary: '#2090d0', secondary: '#1070a0', hat: '#e0e0e0', hatDark: '#c0c0c0', hatLight: '#f0f0f0', shirt: '#404858', shirtDark: '#303848', belt: '#3a3a3a' }, // blue vest, white hat
1149
+ { primary: '#40a050', secondary: '#308040', hat: '#f0a030', hatDark: '#d08020', hatLight: '#ffc040', shirt: '#505050', shirtDark: '#383838', belt: '#4a3a2a' }, // green vest, orange hat
1150
+ { primary: '#c04040', secondary: '#a02828', hat: '#e0e040', hatDark: '#c0c020', hatLight: '#f0f060', shirt: '#606878', shirtDark: '#484858', belt: '#504030' }, // red vest, yellow-green hat
1151
+ { primary: '#8060b0', secondary: '#604890', hat: '#40c0c0', hatDark: '#30a0a0', hatLight: '#60e0e0', shirt: '#586058', shirtDark: '#404840', belt: '#3a3020' }, // purple vest, teal hat
1152
+ { primary: '#c08030', secondary: '#a06020', hat: '#d04040', hatDark: '#b02828', hatLight: '#e06060', shirt: '#485058', shirtDark: '#303840', belt: '#484030' }, // tan vest, red hat
1153
+ { primary: '#508050', secondary: '#386838', hat: '#c0c0d0', hatDark: '#a0a0b0', hatLight: '#e0e0f0', shirt: '#687078', shirtDark: '#505860', belt: '#4a4a3a' }, // sage vest, silver hat
1154
+ { primary: '#d06050', secondary: '#b04038', hat: '#3090c0', hatDark: '#2070a0', hatLight: '#40b0e0', shirt: '#585858', shirtDark: '#404040', belt: '#3a3020' }, // coral vest, blue hat
1155
+ { primary: '#3080a0', secondary: '#206080', hat: '#e8b040', hatDark: '#c89020', hatLight: '#f0c860', shirt: '#606068', shirtDark: '#484850', belt: '#5a4a3a' }, // teal vest, gold hat
1156
+ { primary: '#a06040', secondary: '#804828', hat: '#60b060', hatDark: '#409040', hatLight: '#80d080', shirt: '#585060', shirtDark: '#403848', belt: '#403830' }, // brown vest, green hat
1157
+ ],
1158
+ coder: [
1159
+ { primary: '#5030a0', secondary: '#3a2080', accent: '#6040b0' }, // purple hoodie
1160
+ { primary: '#206838', secondary: '#104828', accent: '#308848' }, // forest green hoodie
1161
+ { primary: '#a03030', secondary: '#802020', accent: '#c04040' }, // red hoodie
1162
+ { primary: '#2060a0', secondary: '#104878', accent: '#3078c0' }, // blue hoodie
1163
+ { primary: '#805020', secondary: '#603810', accent: '#a06830' }, // brown hoodie
1164
+ { primary: '#a03080', secondary: '#802060', accent: '#c040a0' }, // magenta hoodie
1165
+ { primary: '#208080', secondary: '#106060', accent: '#30a0a0' }, // teal hoodie
1166
+ { primary: '#605050', secondary: '#403838', accent: '#786868' }, // charcoal hoodie
1167
+ { primary: '#c06020', secondary: '#a04810', accent: '#d87830' }, // orange hoodie
1168
+ { primary: '#4050a0', secondary: '#303880', accent: '#5068c0' }, // indigo hoodie
1169
+ ],
1170
+ deployer: [
1171
+ { primary: '#6a4a2a', secondary: '#5a3a1a', accent: '#7a5a3a', cap: '#c03030', capDark: '#a02020', capLight: '#e04040', pants: '#a08050', pantsDark: '#907040' }, // brown uniform, red cap
1172
+ { primary: '#304880', secondary: '#203060', accent: '#405898', cap: '#d0a030', capDark: '#b08020', capLight: '#e8b840', pants: '#606870', pantsDark: '#485058' }, // navy uniform, gold cap
1173
+ { primary: '#486040', secondary: '#384830', accent: '#587050', cap: '#d06030', capDark: '#b04820', capLight: '#e87840', pants: '#807060', pantsDark: '#685848' }, // olive uniform, orange cap
1174
+ { primary: '#804838', secondary: '#603028', accent: '#985848', cap: '#3080b0', capDark: '#206898', capLight: '#4098c8', pants: '#786858', pantsDark: '#605040' }, // maroon uniform, blue cap
1175
+ { primary: '#585858', secondary: '#404040', accent: '#707070', cap: '#40a060', capDark: '#308048', capLight: '#58b878', pants: '#484858', pantsDark: '#383848' }, // gray uniform, green cap
1176
+ { primary: '#c07030', secondary: '#a05820', accent: '#d88840', cap: '#304060', capDark: '#203050', capLight: '#405878', pants: '#908060', pantsDark: '#786848' }, // hi-vis orange, navy cap
1177
+ { primary: '#305050', secondary: '#203838', accent: '#406060', cap: '#c0c040', capDark: '#a0a028', capLight: '#d8d860', pants: '#607058', pantsDark: '#485840' }, // dark teal uniform, yellow cap
1178
+ { primary: '#604878', secondary: '#483060', accent: '#785890', cap: '#d04850', capDark: '#b03038', capLight: '#e86068', pants: '#585060', pantsDark: '#403848' }, // purple uniform, red cap
1179
+ { primary: '#708048', secondary: '#586830', accent: '#889858', cap: '#e0e0e0', capDark: '#c0c0c0', capLight: '#f0f0f0', pants: '#686050', pantsDark: '#504838' }, // khaki-green uniform, white cap
1180
+ { primary: '#3a6080', secondary: '#284868', accent: '#4a7898', cap: '#c06040', capDark: '#a04828', capLight: '#d87858', pants: '#506068', pantsDark: '#384850' }, // blue-gray uniform, terra cap
1181
+ ],
1182
+ };
1183
+
1184
+ // ── Source color keys per role (the colors used in the base palettes) ────────
1185
+ // These are the colors we need to remap from the original sprite palettes
1186
+ const SOURCE_COLORS = {
1187
+ pm: {
1188
+ skin: '#f0c8a0',
1189
+ skinShadow: '#daa870',
1190
+ skinHighlight: '#ffe0c0',
1191
+ hair: '#3a2818',
1192
+ hairShadow: '#5a3828',
1193
+ clothPrimary: '#2a4080', // suit
1194
+ clothSecondary: '#1a3060',
1195
+ clothAccent: '#3a60a0',
1196
+ tie: '#c03030',
1197
+ tieDark: '#901818',
1198
+ },
1199
+ architect: {
1200
+ skin: '#dca870',
1201
+ skinShadow: '#b88050',
1202
+ skinHighlight: '#f0c090',
1203
+ hair: null, // architect has hat, not visible hair in most frames
1204
+ hairShadow: null,
1205
+ clothPrimary: '#e08020', // vest
1206
+ clothSecondary: '#c06010',
1207
+ hat: '#e8c820',
1208
+ hatDark: '#c8a810',
1209
+ hatLight: '#f0d830',
1210
+ shirt: '#808090',
1211
+ shirtDark: '#606070',
1212
+ belt: '#5a4a3a',
1213
+ },
1214
+ coder: {
1215
+ skin: '#8b6544',
1216
+ skinShadow: '#6a4c30',
1217
+ skinHighlight: '#a07850',
1218
+ hair: '#1a1a2e', // shared with outline — skip hair remap for coder
1219
+ hairShadow: '#2a2a3e',
1220
+ hairHighlight: '#3a3a4e',
1221
+ clothPrimary: '#5030a0', // hoodie
1222
+ clothSecondary: '#3a2080',
1223
+ clothAccent: '#6040b0',
1224
+ },
1225
+ deployer: {
1226
+ skin: '#e8b080',
1227
+ skinShadow: '#c89060',
1228
+ skinHighlight: '#ffc8a0',
1229
+ hair: '#6a4830',
1230
+ hairShadow: '#8a6040',
1231
+ clothPrimary: '#6a4a2a', // uniform
1232
+ clothSecondary: '#5a3a1a',
1233
+ clothAccent: '#7a5a3a',
1234
+ cap: '#c03030',
1235
+ capDark: '#a02020',
1236
+ capLight: '#e04040',
1237
+ pants: '#a08050',
1238
+ pantsDark: '#907040',
1239
+ },
1240
+ };
1241
+
1242
+ // ── Palette generation ──────────────────────────────────────────────────────
1243
+
1244
+ /**
1245
+ * Generate a deterministic color palette for a project+role combination.
1246
+ * Enforces diversity: PM=Female, Architect=Asian, Coder=Black, Deployer=White.
1247
+ * Skin tones are selected from diversity-constrained pools per role.
1248
+ * Hair and clothing remain hash-based for variety within each pool.
1249
+ * @param {string} projectName - project identifier
1250
+ * @param {string} role - pm, architect, coder, deployer
1251
+ * @returns {Object|null} color remap table { oldColor: newColor, ... } or null for defaults
1252
+ */
1253
+ function generateProjectPalette(projectName, role) {
1254
+ if (!projectName) return null;
1255
+
1256
+ const hash = simpleHash(projectName + ':' + role);
1257
+
1258
+ // Pick skin tone from diversity-constrained pool for the role
1259
+ const diversityType = ROLE_DIVERSITY[role];
1260
+ const skinPool = (diversityType && DIVERSITY_SKIN[diversityType]) || SKIN_TONES;
1261
+ const skinIdx = hash % skinPool.length;
1262
+
1263
+ // Use female-specific hair pool for PM, standard pool for others
1264
+ const hairPool = (diversityType === 'female') ? FEMALE_HAIR_COLORS : HAIR_COLORS;
1265
+ const hairIdx = (hash >>> 3) % hairPool.length;
1266
+
1267
+ const clothPool = CLOTHING_COLORS[role] || CLOTHING_COLORS.coder;
1268
+ const clothIdx = (hash >>> 6) % clothPool.length;
1269
+
1270
+ const skin = skinPool[skinIdx];
1271
+ const hair = hairPool[hairIdx];
1272
+ const cloth = clothPool[clothIdx];
1273
+
1274
+ const src = SOURCE_COLORS[role];
1275
+ if (!src) return null;
1276
+
1277
+ const remap = {};
1278
+
1279
+ // Skin
1280
+ remap[src.skin] = skin.base;
1281
+ remap[src.skinShadow] = skin.shadow;
1282
+ remap[src.skinHighlight] = skin.highlight;
1283
+
1284
+ // Hair (skip if source is null or same as outline to avoid breaking outlines)
1285
+ if (src.hair && src.hair !== '#1a1a2e') {
1286
+ remap[src.hair] = hair.main;
1287
+ remap[src.hairShadow] = hair.shadow;
1288
+ } else if (role === 'coder') {
1289
+ // Coder's hair key '#1a1a2e' is the same as outline X — we can still remap
1290
+ // the highlight and shadow which are unique
1291
+ remap[src.hairShadow] = hair.shadow; // '#2a2a3e' → new shadow
1292
+ remap[src.hairHighlight] = hair.main; // '#3a3a4e' → new main (highlights)
1293
+ }
1294
+
1295
+ // Deployer hair visible under cap
1296
+ if (role === 'deployer' && src.hair) {
1297
+ remap[src.hair] = hair.main;
1298
+ remap[src.hairShadow] = hair.shadow;
1299
+ }
1300
+
1301
+ // PM hair
1302
+ if (role === 'pm' && src.hair) {
1303
+ remap[src.hair] = hair.main;
1304
+ remap[src.hairShadow] = hair.shadow;
1305
+ }
1306
+
1307
+ // Clothing — role-specific mapping
1308
+ if (role === 'pm') {
1309
+ remap[src.clothPrimary] = cloth.primary;
1310
+ remap[src.clothSecondary] = cloth.secondary;
1311
+ remap[src.clothAccent] = cloth.accent;
1312
+ remap[src.tie] = cloth.tie;
1313
+ remap[src.tieDark] = cloth.tieDark;
1314
+ } else if (role === 'architect') {
1315
+ remap[src.clothPrimary] = cloth.primary;
1316
+ remap[src.clothSecondary] = cloth.secondary;
1317
+ remap[src.hat] = cloth.hat;
1318
+ remap[src.hatDark] = cloth.hatDark;
1319
+ remap[src.hatLight] = cloth.hatLight;
1320
+ remap[src.shirt] = cloth.shirt;
1321
+ remap[src.shirtDark] = cloth.shirtDark;
1322
+ remap[src.belt] = cloth.belt;
1323
+ } else if (role === 'coder') {
1324
+ remap[src.clothPrimary] = cloth.primary;
1325
+ remap[src.clothSecondary] = cloth.secondary;
1326
+ remap[src.clothAccent] = cloth.accent;
1327
+ } else if (role === 'deployer') {
1328
+ remap[src.clothPrimary] = cloth.primary;
1329
+ remap[src.clothSecondary] = cloth.secondary;
1330
+ remap[src.clothAccent] = cloth.accent;
1331
+ remap[src.cap] = cloth.cap;
1332
+ remap[src.capDark] = cloth.capDark;
1333
+ remap[src.capLight] = cloth.capLight;
1334
+ remap[src.pants] = cloth.pants;
1335
+ remap[src.pantsDark] = cloth.pantsDark;
1336
+ }
1337
+
1338
+ // Remove any null keys from incomplete mappings
1339
+ delete remap['null'];
1340
+ delete remap['undefined'];
1341
+
1342
+ return remap;
1343
+ }
1344
+
1345
+ // ── Palette cache (projectName:role → remap table) ──────────────────────────
1346
+ const _paletteCache = new Map();
1347
+
1348
+ function getCachedPalette(projectName, role) {
1349
+ const key = projectName + ':' + role;
1350
+ if (_paletteCache.has(key)) return _paletteCache.get(key);
1351
+ const palette = generateProjectPalette(projectName, role);
1352
+ _paletteCache.set(key, palette);
1353
+ return palette;
1354
+ }
1355
+
1356
+ // ============================================================
1357
+ // API
1358
+ // ============================================================
1359
+
1360
+ /**
1361
+ * Get sprite frame data for a character.
1362
+ * @param {string} role - pm, architect, coder, deployer
1363
+ * @param {string} state - idle, working, etc.
1364
+ * @param {number} frame - animation frame index
1365
+ * @param {string} projectName - project name for deterministic visual diversity
1366
+ */
1367
+ export function getSprite(role, state, frame, projectName = '') {
1368
+ const roleSprites = SPRITES[role];
1369
+ if (!roleSprites) return null;
1370
+ const stateFrames = roleSprites[state] || roleSprites['idle'];
1371
+ if (!stateFrames) return null;
1372
+ const spriteData = stateFrames[frame % stateFrames.length];
1373
+ if (!spriteData) return spriteData;
1374
+
1375
+ // No project name = default palette
1376
+ if (!projectName) return spriteData;
1377
+
1378
+ // Get or generate the remap table for this project+role
1379
+ const remap = getCachedPalette(projectName, role);
1380
+ if (!remap) return spriteData;
1381
+
1382
+ return remapSpriteColors(spriteData, remap);
1383
+ }
1384
+
1385
+ // ── Color remapping ─────────────────────────────────────────────────────────
1386
+
1387
+ function remapSpriteColors(spriteData, remap) {
1388
+ return spriteData.map(row =>
1389
+ row.map(pixel => {
1390
+ if (!pixel) return null;
1391
+ return remap[pixel] || pixel;
1392
+ })
1393
+ );
1394
+ }
1395
+
1396
+ export const ROLE_COLORS = {
1397
+ pm: '#4A90D9',
1398
+ architect: '#E8A020',
1399
+ coder: '#8050D0',
1400
+ deployer: '#D04040',
1401
+ };
1402
+
1403
+ // ── Item sprites ────────────────────────────────────────────────────────────
1404
+
1405
+ const _ = null;
1406
+ const O = '#2a2a3a';
1407
+ const W = '#ffffff';
1408
+ const w = '#d8d8d8';
1409
+
1410
+ export const BUG_SPRITE = [
1411
+ [_,_,O,'#40a040',O,_,_,_],
1412
+ [_,O,'#50c050','#40a040','#50c050',O,_,_],
1413
+ [O,'#40a040','#50c050',O,'#50c050','#40a040',O,_],
1414
+ [O,'#50c050','#40a040','#50c050','#40a040','#50c050',O,_],
1415
+ [_,O,'#50c050','#40a040','#50c050',O,_,_],
1416
+ [_,_,O,'#40a040',O,_,_,_],
1417
+ [_,O,_,O,_,O,_,_],
1418
+ [O,_,_,_,_,_,O,_],
1419
+ ];
1420
+
1421
+ export const MAGNIFIER_SPRITE = [
1422
+ [_,_,O,O,O,_,_,_],
1423
+ [_,O,'#a0d0f0','#80b8e0',O,_,_,_],
1424
+ [O,'#a0d0f0','#c0e0f8','#a0d0f0',O,_,_,_],
1425
+ [O,'#80b8e0','#a0d0f0','#80b8e0',O,_,_,_],
1426
+ [_,O,O,O,O,_,_,_],
1427
+ [_,_,_,_,O,O,_,_],
1428
+ [_,_,_,_,_,O,O,_],
1429
+ [_,_,_,_,_,_,O,_],
1430
+ ];
1431
+
1432
+ export const DOCUMENT_SPRITE = [
1433
+ [_,O,O,O,O,_],
1434
+ [O,W,W,W,O,O],
1435
+ [O,W,O,W,W,O],
1436
+ [O,W,W,W,W,O],
1437
+ [O,W,O,O,W,O],
1438
+ [O,W,W,W,W,O],
1439
+ [O,W,O,W,W,O],
1440
+ [O,O,O,O,O,O],
1441
+ ];
1442
+
1443
+ export const COFFEE_SPRITE = [
1444
+ [_,_,w,_,_,_],
1445
+ [_,w,_,w,_,_],
1446
+ [_,_,w,_,_,_],
1447
+ [O,O,O,O,O,_],
1448
+ [O,W,W,W,O,O],
1449
+ [O,W,W,W,O,O],
1450
+ [O,W,W,W,O,_],
1451
+ [_,O,O,O,_,_],
1452
+ ];
1453
+
1454
+ export { SPRITES };