@the-inclusionist/engine 9.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (532) hide show
  1. package/README.md +120 -78
  2. package/app/css/style.css +761 -377
  3. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  4. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  5. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  6. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  7. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  8. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  9. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  10. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  11. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  12. package/app/public/vendor/fonts.css +36 -84
  13. package/dist-pkg/boot/create-game.d.ts +499 -219
  14. package/dist-pkg/boot/create-game.js +3944 -562
  15. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  16. package/dist-pkg/core/a11y-sr.js +38 -19
  17. package/dist-pkg/core/accessible-label.d.ts +17 -0
  18. package/dist-pkg/core/accessible-label.js +37 -0
  19. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  20. package/dist-pkg/core/accommodation-subjects.js +32 -0
  21. package/dist-pkg/core/accommodations.d.ts +125 -0
  22. package/dist-pkg/core/accommodations.js +195 -0
  23. package/dist-pkg/core/actions.d.ts +108 -55
  24. package/dist-pkg/core/actions.js +122 -71
  25. package/dist-pkg/core/calm-mode.d.ts +31 -0
  26. package/dist-pkg/core/calm-mode.js +47 -0
  27. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  28. package/dist-pkg/core/camera-cycle.js +7 -0
  29. package/dist-pkg/core/caption-duration.d.ts +15 -0
  30. package/dist-pkg/core/caption-duration.js +19 -0
  31. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  32. package/dist-pkg/core/cartridge-problems.js +53 -0
  33. package/dist-pkg/core/constants.d.ts +0 -54
  34. package/dist-pkg/core/constants.js +9 -76
  35. package/dist-pkg/core/contract.d.ts +142 -164
  36. package/dist-pkg/core/contract.js +222 -208
  37. package/dist-pkg/core/dom-query.d.ts +4 -4
  38. package/dist-pkg/core/dom-query.js +12 -20
  39. package/dist-pkg/core/entity.d.ts +62 -77
  40. package/dist-pkg/core/entity.js +18 -32
  41. package/dist-pkg/core/escape-html.d.ts +9 -10
  42. package/dist-pkg/core/escape-html.js +16 -20
  43. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  44. package/dist-pkg/core/flash-threshold.js +113 -0
  45. package/dist-pkg/core/game-speed.d.ts +11 -0
  46. package/dist-pkg/core/game-speed.js +16 -0
  47. package/dist-pkg/core/genres.d.ts +20 -0
  48. package/dist-pkg/core/genres.js +44 -0
  49. package/dist-pkg/core/i18n.d.ts +71 -60
  50. package/dist-pkg/core/i18n.js +186 -200
  51. package/dist-pkg/core/loop.d.ts +17 -6
  52. package/dist-pkg/core/loop.js +26 -26
  53. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  54. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  55. package/dist-pkg/core/ring.d.ts +17 -0
  56. package/dist-pkg/core/ring.js +29 -0
  57. package/dist-pkg/core/rng.d.ts +7 -12
  58. package/dist-pkg/core/rng.js +23 -53
  59. package/dist-pkg/core/route.d.ts +26 -26
  60. package/dist-pkg/core/route.js +126 -121
  61. package/dist-pkg/core/scenes.d.ts +37 -40
  62. package/dist-pkg/core/scenes.js +41 -43
  63. package/dist-pkg/core/screens.d.ts +4 -4
  64. package/dist-pkg/core/screens.js +11 -16
  65. package/dist-pkg/core/session-clock.d.ts +23 -0
  66. package/dist-pkg/core/session-clock.js +37 -0
  67. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  68. package/dist-pkg/core/setting-defaults.js +66 -0
  69. package/dist-pkg/core/speech-rate.d.ts +29 -0
  70. package/dist-pkg/core/speech-rate.js +47 -0
  71. package/dist-pkg/core/state.d.ts +118 -118
  72. package/dist-pkg/core/state.js +322 -297
  73. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  74. package/dist-pkg/core/visual-cycles.js +52 -0
  75. package/dist-pkg/core/visual-state.d.ts +13 -0
  76. package/dist-pkg/core/visual-state.js +6 -0
  77. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  78. package/dist-pkg/educational/activities-registry.js +9 -8
  79. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  80. package/dist-pkg/educational/adaptive-engine.js +17 -17
  81. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  82. package/dist-pkg/educational/segment-bar.js +9 -9
  83. package/dist-pkg/i18n/en.js +324 -223
  84. package/dist-pkg/i18n/es.js +323 -223
  85. package/dist-pkg/i18n/pt.js +348 -226
  86. package/dist-pkg/input/default-bindings.d.ts +37 -38
  87. package/dist-pkg/input/default-bindings.js +127 -144
  88. package/dist-pkg/input/devices.d.ts +7 -7
  89. package/dist-pkg/input/devices.js +17 -16
  90. package/dist-pkg/input/edges.d.ts +23 -32
  91. package/dist-pkg/input/edges.js +23 -28
  92. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  93. package/dist-pkg/input/empathy-filter.js +34 -0
  94. package/dist-pkg/input/face-map.d.ts +96 -0
  95. package/dist-pkg/input/face-map.js +255 -0
  96. package/dist-pkg/input/face-signals.d.ts +40 -0
  97. package/dist-pkg/input/face-signals.js +48 -0
  98. package/dist-pkg/input/gamepad.d.ts +195 -145
  99. package/dist-pkg/input/gamepad.js +383 -556
  100. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  101. package/dist-pkg/input/gaze-cycle.js +133 -0
  102. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  103. package/dist-pkg/input/gaze-relative.js +142 -0
  104. package/dist-pkg/input/hand-map.d.ts +28 -0
  105. package/dist-pkg/input/hand-map.js +142 -0
  106. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  107. package/dist-pkg/input/input-cooldown.js +39 -0
  108. package/dist-pkg/input/key-default.d.ts +30 -0
  109. package/dist-pkg/input/key-default.js +60 -0
  110. package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
  111. package/dist-pkg/input/keyboard-runtime.js +23 -27
  112. package/dist-pkg/input/keyboard.d.ts +68 -63
  113. package/dist-pkg/input/keyboard.js +83 -105
  114. package/dist-pkg/input/keydown.d.ts +123 -137
  115. package/dist-pkg/input/keydown.js +284 -289
  116. package/dist-pkg/input/latch-edge.d.ts +33 -21
  117. package/dist-pkg/input/latch-edge.js +34 -35
  118. package/dist-pkg/input/latch-scope.d.ts +51 -50
  119. package/dist-pkg/input/latch-scope.js +61 -82
  120. package/dist-pkg/input/latch-store.d.ts +26 -30
  121. package/dist-pkg/input/latch-store.js +42 -50
  122. package/dist-pkg/input/latch-sync.d.ts +29 -29
  123. package/dist-pkg/input/latch-sync.js +25 -25
  124. package/dist-pkg/input/latch.d.ts +14 -17
  125. package/dist-pkg/input/latch.js +29 -37
  126. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  127. package/dist-pkg/input/pad-defaults.js +21 -28
  128. package/dist-pkg/input/pad-reading.d.ts +76 -0
  129. package/dist-pkg/input/pad-reading.js +169 -0
  130. package/dist-pkg/input/pad-wizard.d.ts +99 -0
  131. package/dist-pkg/input/pad-wizard.js +256 -0
  132. package/dist-pkg/input/pointer-space.d.ts +19 -20
  133. package/dist-pkg/input/pointer-space.js +27 -32
  134. package/dist-pkg/input/pointer.d.ts +39 -40
  135. package/dist-pkg/input/pointer.js +42 -45
  136. package/dist-pkg/input/state.d.ts +101 -89
  137. package/dist-pkg/input/state.js +54 -134
  138. package/dist-pkg/input/switch-scan.d.ts +59 -0
  139. package/dist-pkg/input/switch-scan.js +67 -0
  140. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  141. package/dist-pkg/input/synthetic-source.js +57 -0
  142. package/dist-pkg/input/touch-bindings.d.ts +127 -116
  143. package/dist-pkg/input/touch-bindings.js +158 -173
  144. package/dist-pkg/input/touch.d.ts +147 -72
  145. package/dist-pkg/input/touch.js +362 -126
  146. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  147. package/dist-pkg/input/transport-in-use.js +130 -0
  148. package/dist-pkg/input/transports.d.ts +90 -117
  149. package/dist-pkg/input/transports.js +104 -106
  150. package/dist-pkg/input/virtual-controller.d.ts +82 -0
  151. package/dist-pkg/input/virtual-controller.js +69 -0
  152. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  153. package/dist-pkg/input/vocabulary-migration.js +80 -79
  154. package/dist-pkg/input/voice-map.d.ts +59 -0
  155. package/dist-pkg/input/voice-map.js +123 -0
  156. package/dist-pkg/platform/audio-ambient.d.ts +13 -2
  157. package/dist-pkg/platform/audio-ambient.js +14 -14
  158. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  159. package/dist-pkg/platform/audio-earcons.js +51 -42
  160. package/dist-pkg/platform/audio-jingles.js +9 -10
  161. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  162. package/dist-pkg/platform/audio-mixer.js +31 -39
  163. package/dist-pkg/platform/audio-sonar.d.ts +49 -152
  164. package/dist-pkg/platform/audio-sonar.js +124 -302
  165. package/dist-pkg/platform/audio.d.ts +62 -19
  166. package/dist-pkg/platform/audio.js +193 -168
  167. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  168. package/dist-pkg/platform/choose-by-voice.js +157 -0
  169. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  170. package/dist-pkg/platform/flash-sampler.js +79 -0
  171. package/dist-pkg/platform/font-library.d.ts +77 -0
  172. package/dist-pkg/platform/font-library.js +98 -0
  173. package/dist-pkg/platform/font-library.json +721 -0
  174. package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
  175. package/dist-pkg/platform/heavy-catalogue.js +256 -0
  176. package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
  177. package/dist-pkg/platform/heavy-mirror.js +73 -0
  178. package/dist-pkg/platform/heavy.d.ts +136 -0
  179. package/dist-pkg/platform/heavy.js +324 -0
  180. package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
  181. package/dist-pkg/platform/interruptible-speech.js +77 -54
  182. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  183. package/dist-pkg/platform/kokoro-port.js +50 -0
  184. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  185. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  186. package/dist-pkg/platform/kokoro.d.ts +70 -0
  187. package/dist-pkg/platform/kokoro.js +133 -0
  188. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  189. package/dist-pkg/platform/listener-scope.js +90 -0
  190. package/dist-pkg/platform/locale-host.d.ts +14 -0
  191. package/dist-pkg/platform/locale-host.js +45 -0
  192. package/dist-pkg/platform/microphone.d.ts +51 -0
  193. package/dist-pkg/platform/microphone.js +118 -0
  194. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  195. package/dist-pkg/platform/onnx-runtime.js +42 -0
  196. package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
  197. package/dist-pkg/platform/reading-in-worker.js +125 -0
  198. package/dist-pkg/platform/reading-model.d.ts +94 -0
  199. package/dist-pkg/platform/reading-model.js +272 -0
  200. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  201. package/dist-pkg/platform/reading-runtime.js +164 -0
  202. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  203. package/dist-pkg/platform/reading-worker.js +58 -0
  204. package/dist-pkg/platform/reading.d.ts +80 -0
  205. package/dist-pkg/platform/reading.js +136 -0
  206. package/dist-pkg/platform/speech-recognition.d.ts +60 -0
  207. package/dist-pkg/platform/speech-recognition.js +104 -0
  208. package/dist-pkg/platform/speech.d.ts +23 -1
  209. package/dist-pkg/platform/speech.js +29 -18
  210. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  211. package/dist-pkg/platform/storage-keys.js +106 -0
  212. package/dist-pkg/platform/storage.d.ts +46 -111
  213. package/dist-pkg/platform/storage.js +104 -169
  214. package/dist-pkg/platform/tts.d.ts +85 -39
  215. package/dist-pkg/platform/tts.js +447 -127
  216. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  217. package/dist-pkg/platform/vision-loop.js +56 -0
  218. package/dist-pkg/platform/vision.d.ts +132 -0
  219. package/dist-pkg/platform/vision.js +117 -0
  220. package/dist-pkg/platform/voice-listener.d.ts +40 -0
  221. package/dist-pkg/platform/voice-listener.js +88 -0
  222. package/dist-pkg/platform/voice-plan.d.ts +15 -98
  223. package/dist-pkg/platform/voice-plan.js +56 -143
  224. package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
  225. package/dist-pkg/platform/vosk-runtime.js +151 -0
  226. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  227. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  228. package/dist-pkg/render/canvas.d.ts +13 -7
  229. package/dist-pkg/render/canvas.js +13 -13
  230. package/dist-pkg/render/crt.d.ts +48 -12
  231. package/dist-pkg/render/crt.js +78 -80
  232. package/dist-pkg/render/cvd-matrices.d.ts +22 -18
  233. package/dist-pkg/render/cvd-matrices.js +37 -38
  234. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  235. package/dist-pkg/render/hc-role-data.js +14 -14
  236. package/dist-pkg/render/high-contrast.d.ts +67 -56
  237. package/dist-pkg/render/high-contrast.js +226 -217
  238. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  239. package/dist-pkg/render/low-vision-drawing.js +46 -0
  240. package/dist-pkg/render/lq-filter.d.ts +32 -20
  241. package/dist-pkg/render/lq-filter.js +59 -65
  242. package/dist-pkg/render/port.d.ts +86 -88
  243. package/dist-pkg/render/port.js +17 -23
  244. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  245. package/dist-pkg/render/screen-pipeline.js +80 -87
  246. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  247. package/dist-pkg/render/sprite-fx.js +16 -14
  248. package/dist-pkg/render/viewports.d.ts +20 -15
  249. package/dist-pkg/render/viewports.js +83 -114
  250. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  251. package/dist-pkg/render/viz-axes-labels.js +88 -0
  252. package/dist-pkg/render/viz-axes.d.ts +89 -86
  253. package/dist-pkg/render/viz-axes.js +128 -116
  254. package/dist-pkg/render/viz-modes.d.ts +28 -29
  255. package/dist-pkg/render/viz-modes.js +40 -45
  256. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  257. package/dist-pkg/render/viz-refusal.js +57 -0
  258. package/dist-pkg/render/viz-setters.d.ts +104 -66
  259. package/dist-pkg/render/viz-setters.js +182 -191
  260. package/dist-pkg/ui/aac-sets.d.ts +45 -0
  261. package/dist-pkg/ui/aac-sets.js +41 -0
  262. package/dist-pkg/ui/audio-choices.d.ts +68 -0
  263. package/dist-pkg/ui/audio-choices.js +98 -0
  264. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  265. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  266. package/dist-pkg/ui/camera-control.d.ts +53 -0
  267. package/dist-pkg/ui/camera-control.js +48 -0
  268. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  269. package/dist-pkg/ui/changed-mark.js +22 -53
  270. package/dist-pkg/ui/control-choices.d.ts +37 -0
  271. package/dist-pkg/ui/control-choices.js +84 -0
  272. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  273. package/dist-pkg/ui/debug-panel.js +68 -69
  274. package/dist-pkg/ui/declared-words.d.ts +21 -0
  275. package/dist-pkg/ui/declared-words.js +66 -0
  276. package/dist-pkg/ui/dom.d.ts +10 -14
  277. package/dist-pkg/ui/dom.js +10 -47
  278. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  279. package/dist-pkg/ui/drawing-problems.js +94 -0
  280. package/dist-pkg/ui/eye-control.d.ts +36 -0
  281. package/dist-pkg/ui/eye-control.js +178 -0
  282. package/dist-pkg/ui/face-control.d.ts +25 -0
  283. package/dist-pkg/ui/face-control.js +183 -0
  284. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  285. package/dist-pkg/ui/focus-trap.js +56 -65
  286. package/dist-pkg/ui/fonts.d.ts +157 -68
  287. package/dist-pkg/ui/fonts.js +305 -115
  288. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  289. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  290. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  291. package/dist-pkg/ui/footer-scroll.js +55 -0
  292. package/dist-pkg/ui/game-options.d.ts +47 -0
  293. package/dist-pkg/ui/game-options.js +158 -0
  294. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  295. package/dist-pkg/ui/gaze-overlay.js +165 -0
  296. package/dist-pkg/ui/hand-control.d.ts +25 -0
  297. package/dist-pkg/ui/hand-control.js +143 -0
  298. package/dist-pkg/ui/help-panel.d.ts +87 -0
  299. package/dist-pkg/ui/help-panel.js +242 -0
  300. package/dist-pkg/ui/hud-bands.d.ts +62 -0
  301. package/dist-pkg/ui/hud-bands.js +146 -0
  302. package/dist-pkg/ui/hud-row.d.ts +34 -0
  303. package/dist-pkg/ui/hud-row.js +80 -0
  304. package/dist-pkg/ui/hud.d.ts +73 -73
  305. package/dist-pkg/ui/hud.js +94 -98
  306. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  307. package/dist-pkg/ui/item-announcement.js +25 -26
  308. package/dist-pkg/ui/layout.d.ts +103 -28
  309. package/dist-pkg/ui/layout.js +117 -99
  310. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  311. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  312. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  313. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  314. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  315. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  316. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  317. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  318. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  319. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  320. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  321. package/dist-pkg/ui/libras-glosses.js +161 -0
  322. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  323. package/dist-pkg/ui/locale-flags.js +30 -0
  324. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  325. package/dist-pkg/ui/loop-crash.js +33 -62
  326. package/dist-pkg/ui/menu-intent.d.ts +61 -0
  327. package/dist-pkg/ui/menu-intent.js +88 -0
  328. package/dist-pkg/ui/menu-items.d.ts +20 -0
  329. package/dist-pkg/ui/menu-items.js +51 -0
  330. package/dist-pkg/ui/menu-nav.d.ts +98 -92
  331. package/dist-pkg/ui/menu-nav.js +398 -286
  332. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  333. package/dist-pkg/ui/mobility-choices.js +41 -0
  334. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  335. package/dist-pkg/ui/motion-choices.js +68 -0
  336. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  337. package/dist-pkg/ui/motion-scene.js +29 -61
  338. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  339. package/dist-pkg/ui/mount-panel.js +61 -0
  340. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  341. package/dist-pkg/ui/panel-shell.js +92 -66
  342. package/dist-pkg/ui/panel-widgets.d.ts +150 -0
  343. package/dist-pkg/ui/panel-widgets.js +294 -0
  344. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  345. package/dist-pkg/ui/pause-buttons.js +66 -0
  346. package/dist-pkg/ui/pause-icons.d.ts +261 -347
  347. package/dist-pkg/ui/pause-icons.js +671 -601
  348. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  349. package/dist-pkg/ui/pause-markup.js +125 -0
  350. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  351. package/dist-pkg/ui/reach-notice.js +55 -58
  352. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  353. package/dist-pkg/ui/scan-overlay.js +50 -0
  354. package/dist-pkg/ui/screen-text.d.ts +25 -0
  355. package/dist-pkg/ui/screen-text.js +152 -0
  356. package/dist-pkg/ui/session-clock.d.ts +32 -0
  357. package/dist-pkg/ui/session-clock.js +67 -0
  358. package/dist-pkg/ui/settings-aac.d.ts +70 -0
  359. package/dist-pkg/ui/settings-aac.js +208 -0
  360. package/dist-pkg/ui/settings-audio.d.ts +97 -114
  361. package/dist-pkg/ui/settings-audio.js +493 -425
  362. package/dist-pkg/ui/settings-controls.d.ts +53 -96
  363. package/dist-pkg/ui/settings-controls.js +143 -215
  364. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  365. package/dist-pkg/ui/settings-empathy.js +53 -60
  366. package/dist-pkg/ui/settings-mobility.d.ts +192 -0
  367. package/dist-pkg/ui/settings-mobility.js +332 -0
  368. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  369. package/dist-pkg/ui/settings-motion.js +287 -198
  370. package/dist-pkg/ui/settings-panel.d.ts +58 -45
  371. package/dist-pkg/ui/settings-panel.js +189 -94
  372. package/dist-pkg/ui/settings-typo.d.ts +29 -78
  373. package/dist-pkg/ui/settings-typo.js +158 -129
  374. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  375. package/dist-pkg/ui/settings-visual.js +240 -193
  376. package/dist-pkg/ui/shell.d.ts +112 -135
  377. package/dist-pkg/ui/shell.js +148 -217
  378. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  379. package/dist-pkg/ui/simulation-list.js +76 -0
  380. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  381. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  382. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  383. package/dist-pkg/ui/simulation-refusal.js +8 -56
  384. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  385. package/dist-pkg/ui/switchable-control.js +19 -0
  386. package/dist-pkg/ui/title.d.ts +3 -12
  387. package/dist-pkg/ui/title.js +49 -18
  388. package/dist-pkg/ui/top-band.d.ts +26 -0
  389. package/dist-pkg/ui/top-band.js +96 -0
  390. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  391. package/dist-pkg/ui/typo-choices.js +85 -0
  392. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  393. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  394. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  395. package/dist-pkg/ui/visual-choices.js +107 -0
  396. package/dist-pkg/ui/vlibras.d.ts +77 -10
  397. package/dist-pkg/ui/vlibras.js +130 -81
  398. package/dist-pkg/ui/voice-control.d.ts +68 -0
  399. package/dist-pkg/ui/voice-control.js +276 -0
  400. package/dist-pkg/ui/voice-settings.d.ts +95 -0
  401. package/dist-pkg/ui/voice-settings.js +352 -0
  402. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  403. package/dist-pkg/ui/where-the-child-is.js +70 -0
  404. package/docs/CREDITS.md +300 -44
  405. package/docs/LICENSES.md +189 -145
  406. package/package.json +51 -27
  407. package/scripts/check-cartridge.mjs +78 -0
  408. package/scripts/game-build.d.mts +25 -0
  409. package/scripts/game-build.mjs +144 -0
  410. package/scripts/heavy-into-the-delivery.mjs +388 -0
  411. package/scripts/libras-avatar.json +680 -0
  412. package/scripts/libras-avatar.mjs +246 -0
  413. package/scripts/libras-glosses/gloss.py +95 -0
  414. package/scripts/libras-glosses/pyproject.toml +32 -0
  415. package/scripts/libras-glosses/uv.lock +781 -0
  416. package/scripts/libras-glosses.mjs +351 -0
  417. package/scripts/licences/Apache-2.0.txt +176 -0
  418. package/scripts/licences/GPL-3.0.txt +674 -0
  419. package/scripts/licences/MIT.txt +17 -0
  420. package/scripts/licences/OFL-1.1.txt +86 -0
  421. package/scripts/licences/UFL-1.0.txt +96 -0
  422. package/scripts/licences/fonts.mjs +389 -0
  423. package/scripts/licences/third-party.mjs +301 -0
  424. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  425. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  427. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  428. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  429. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  431. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  433. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  435. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  437. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  439. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  440. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  441. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  443. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  444. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  445. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  446. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  447. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  448. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  449. package/dist-pkg/core/anel.d.ts +0 -17
  450. package/dist-pkg/core/anel.js +0 -31
  451. package/dist-pkg/core/collision.d.ts +0 -21
  452. package/dist-pkg/core/collision.js +0 -62
  453. package/dist-pkg/core/layers.d.ts +0 -63
  454. package/dist-pkg/core/layers.js +0 -95
  455. package/dist-pkg/core/letter-grid.d.ts +0 -55
  456. package/dist-pkg/core/letter-grid.js +0 -116
  457. package/dist-pkg/core/password.d.ts +0 -34
  458. package/dist-pkg/core/password.js +0 -205
  459. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  460. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  461. package/dist-pkg/core/run-state.d.ts +0 -115
  462. package/dist-pkg/core/run-state.js +0 -40
  463. package/dist-pkg/core/tiles.d.ts +0 -12
  464. package/dist-pkg/core/tiles.js +0 -61
  465. package/dist-pkg/core/world.d.ts +0 -4
  466. package/dist-pkg/core/world.js +0 -58
  467. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  468. package/dist-pkg/input/origem-sintetica.js +0 -60
  469. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  470. package/dist-pkg/input/transporte-em-uso.js +0 -130
  471. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  472. package/dist-pkg/platform/audio-nav.js +0 -99
  473. package/dist-pkg/platform/guide-intensity.d.ts +0 -40
  474. package/dist-pkg/platform/guide-intensity.js +0 -73
  475. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  476. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  477. package/dist-pkg/platform/pesados.d.ts +0 -31
  478. package/dist-pkg/platform/pesados.js +0 -75
  479. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  480. package/dist-pkg/platform/vozes-prontas.js +0 -61
  481. package/dist-pkg/render/camera.d.ts +0 -58
  482. package/dist-pkg/render/camera.js +0 -105
  483. package/dist-pkg/render/cenario-data.d.ts +0 -127
  484. package/dist-pkg/render/cenario-data.js +0 -145
  485. package/dist-pkg/render/city-tex.d.ts +0 -63
  486. package/dist-pkg/render/city-tex.js +0 -228
  487. package/dist-pkg/render/city-tiles.d.ts +0 -11
  488. package/dist-pkg/render/city-tiles.js +0 -140
  489. package/dist-pkg/render/draw.d.ts +0 -149
  490. package/dist-pkg/render/draw.js +0 -231
  491. package/dist-pkg/render/fx.d.ts +0 -63
  492. package/dist-pkg/render/fx.js +0 -123
  493. package/dist-pkg/render/minimap.d.ts +0 -11
  494. package/dist-pkg/render/minimap.js +0 -94
  495. package/dist-pkg/render/parallax.d.ts +0 -85
  496. package/dist-pkg/render/parallax.js +0 -158
  497. package/dist-pkg/render/player-anim.d.ts +0 -71
  498. package/dist-pkg/render/player-anim.js +0 -152
  499. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  500. package/dist-pkg/render/recycling-tex.js +0 -164
  501. package/dist-pkg/render/scene-city.d.ts +0 -77
  502. package/dist-pkg/render/scene-city.js +0 -181
  503. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  504. package/dist-pkg/render/scene-parallax.js +0 -426
  505. package/dist-pkg/render/scene-sky.d.ts +0 -126
  506. package/dist-pkg/render/scene-sky.js +0 -295
  507. package/dist-pkg/render/set-cenario.d.ts +0 -54
  508. package/dist-pkg/render/set-cenario.js +0 -103
  509. package/dist-pkg/render/textures.d.ts +0 -75
  510. package/dist-pkg/render/textures.js +0 -240
  511. package/dist-pkg/render/title-scene.d.ts +0 -46
  512. package/dist-pkg/render/title-scene.js +0 -75
  513. package/dist-pkg/render/weather.d.ts +0 -96
  514. package/dist-pkg/render/weather.js +0 -171
  515. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  516. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  517. package/dist-pkg/render/world-tex.d.ts +0 -18
  518. package/dist-pkg/render/world-tex.js +0 -87
  519. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  520. package/dist-pkg/ui/activities-menu.js +0 -648
  521. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  522. package/dist-pkg/ui/caa-sets.js +0 -65
  523. package/dist-pkg/ui/latch-refusal.d.ts +0 -32
  524. package/dist-pkg/ui/latch-refusal.js +0 -60
  525. package/dist-pkg/ui/map-hub.d.ts +0 -56
  526. package/dist-pkg/ui/map-hub.js +0 -138
  527. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  528. package/dist-pkg/ui/settings-caa.js +0 -137
  529. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  530. package/dist-pkg/ui/settings-motor.js +0 -342
  531. package/dist-pkg/ui/webcam.d.ts +0 -7
  532. package/dist-pkg/ui/webcam.js +0 -93
@@ -1,64 +1,63 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  import { type Action } from '../core/actions.js';
3
- /** `null` = este transporte NÃO alcança esta ação por padrão. Ausência declarada, nunca esquecimento. */
3
+ /** `null` = this transport does NOT reach this action by default. A declared absence, never an oversight. */
4
4
  export type Binding<T> = T | null;
5
5
  /**
6
- * Teclado, esquema SOLO. Códigos de `KeyboardEvent.code` — físicos, não a letra impressa, que muda com o
7
- * layout ABNT2/US e é a razão de nunca se usar `key` aqui.
6
+ * Keyboard, SOLO scheme. `KeyboardEvent.code` codes — physical, not the printed letter, which changes with the
7
+ * ABNT2/US layout and is the reason `key` is never used here.
8
8
  */
9
9
  export declare const KEYBOARD_SOLO: Readonly<Record<Action, Binding<readonly string[]>>>;
10
10
  /**
11
- * Teclado, esquema de DOIS JOGADORES — as quatorze posições para cada um (ADR-0096).
11
+ * Keyboard, TWO-PLAYER scheme — the fourteen positions for each (ADR-0096).
12
12
  *
13
- * ⚠️ O JOGADOR 1 AQUI NÃO É O `KEYBOARD_SOLO`, e a diferença é UMA e obrigatória: as SETAS saem dele. No solo
14
- * elas são um segundo caminho para o direcional; em dupla são o direcional DO OUTRO. Deixá-las nos dois faria
15
- * os dois bonecos andarem juntos — um defeito que não dá erro em lado nenhum e que só se vê jogando a dois.
16
- * `conflitosEntreTabelas` existe por causa desta linha.
13
+ * ⚠️ PLAYER 1 HERE IS NOT `KEYBOARD_SOLO`, and the difference is ONE and mandatory: the ARROWS leave it. In solo
14
+ * they are a second path for the d-pad; in duo they are the OTHER player's d-pad. Leaving them in both would make
15
+ * the two characters walk together — a defect that raises no error anywhere and only shows when playing as two.
16
+ * `conflictsBetweenTables` exists because of this line.
17
17
  *
18
- * ⚠️ E A GEOMETRIA DO JOGADOR 2 É A MESMA DO JOGADOR 1, TRANSPOSTA PARA O TECLADO NUMÉRICO — o que faz a
19
- * memória muscular atravessar de um lado da mesa para o outro:
18
+ * ⚠️ AND PLAYER 2'S GEOMETRY IS PLAYER 1'S, MOVED TO THE NUMERIC KEYPAD — which is what carries muscle memory from
19
+ * one side of the table to the other:
20
20
  *
21
- * 7 8 / * ombros na linha DE CIMA
22
- * Y U I O 7 8 9 + gatilhos nas PONTAS da linha das ações
21
+ * 7 8 / * shoulders on the TOP row
22
+ * Y U I O 7 8 9 + triggers at the ENDS of the action row
23
23
  * J K 5 6
24
24
  *
25
- * action1 U ↔ Numpad8 (cima-esquerda) action4 I ↔ Numpad9 (cima-direita)
26
- * action2 J ↔ Numpad5 (baixo-esquerda) action3 K ↔ Numpad6 (baixo-direita)
25
+ * action1 U ↔ Numpad8 (top-left) action4 I ↔ Numpad9 (top-right)
26
+ * action2 J ↔ Numpad5 (bottom-left) action3 K ↔ Numpad6 (bottom-right)
27
27
  *
28
- * O bloco `U I / J K` e o bloco `8 9 / 5 6` têm a MESMA forma, então a rotação de 45° que o cabeçalho deste
29
- * ficheiro descreve para o Xbox vale igual para o jogador 2. Não é coincidência de teclado: é o que torna o
30
- * padrão ensinável uma vez só.
28
+ * The `U I / J K` block and the `8 9 / 5 6` block have the SAME shape, so the 45° rotation this file's header
29
+ * describes for the Xbox holds for player 2 as well. It is not a keyboard coincidence: it is what makes the default
30
+ * teachable once.
31
31
  *
32
- * ⚠️ `Digit7`/`Digit8` (jogador 1) e `Numpad7` (jogador 2) SÃO TECLAS DIFERENTES, e é por isso que a
33
- * especificação do Dev diz «alphanumeric» e «numeric» em tantas palavras. `KeyboardEvent.code` distingue-as
34
- * sempre; `key` não — com Num Lock desligado o numérico chega como `ArrowUp`/`Home`, e um esquema lido por
35
- * `key` juntaria o direcional do jogador 2 com as ações dele. Mais uma razão de este ficheiro só falar
36
- * `code`.
32
+ * ⚠️ `Digit7`/`Digit8` (player 1) and `Numpad7` (player 2) ARE DIFFERENT KEYS, which is why the Dev's specification
33
+ * says «alphanumeric» and «numeric» in so many words. `KeyboardEvent.code` always tells them apart; `key` does not —
34
+ * with Num Lock off the keypad arrives as `ArrowUp`/`Home`, and a scheme read by `key` would merge player 2's d-pad
35
+ * with their actions. One more reason this file only speaks `code`.
37
36
  */
38
37
  export declare const KEYBOARD_DUO: readonly Readonly<Record<Action, Binding<readonly string[]>>>[];
39
38
  /**
40
- * Gamepad, mapa PADRÃO da Gamepad API (`mapping: "standard"`), que é o que um controle de Xbox reporta.
41
- * O número é o índice em `gamepad.buttons`.
39
+ * Gamepad, the Gamepad API's STANDARD map (`mapping: "standard"`), which is what an Xbox controller reports.
40
+ * The number is the index into `gamepad.buttons`.
42
41
  */
43
42
  export declare const GAMEPAD_STANDARD: Readonly<Record<Action, Binding<number>>>;
44
43
  /**
45
- * Todos os problemas de uma tabela de binding. VAZIA quer dizer conforme.
44
+ * Every problem in a binding table. EMPTY means conformant.
46
45
  *
47
- * ⚠️ O QUE ISTO EXISTE PARA APANHAR É O DUPLO, e ele já aconteceu: a especificação chegou com `I` em duas
48
- * ações. Um binding duplicado não dá erro em lado nenhum — as duas ações disparam juntas, e a criança vê uma
49
- * ação dupla intermitente que ninguém consegue reproduzir de propósito.
46
+ * ⚠️ WHAT THIS EXISTS TO CATCH IS THE DOUBLE, and it has already happened: the specification arrived with `I` on two
47
+ * actions. A duplicated binding raises no error anywhere — the two actions fire together, and the child sees an
48
+ * intermittent double action nobody can reproduce on purpose.
50
49
  */
51
- export declare function bindingProblems<T>(tabela: Readonly<Record<Action, Binding<T | readonly T[]>>>): string[];
50
+ export declare function bindingProblems<T>(table: Readonly<Record<Action, Binding<T | readonly T[]>>>): string[];
52
51
  /**
53
- * As teclas que DUAS OU MAIS tabelas reclamam para si. VAZIA quer dizer que os jogadores não se atropelam.
52
+ * The keys TWO OR MORE tables claim. EMPTY means the players do not trample each other.
54
53
  *
55
- * ⚠️ ISTO É UM PROBLEMA DIFERENTE DO `bindingProblems`, E FOI POR ISSO QUE PRECISOU DE FUNÇÃO PRÓPRIA: aquele
56
- * olha UMA tabela e apanha a mesma tecla em duas ações; este olha DUAS tabelas e apanha a mesma tecla em dois
57
- * JOGADORES. Cada esquema do `KEYBOARD_DUO` passa no primeiro sozinho — e as setas, se ficassem nos dois,
58
- * fariam os dois bonecos andarem juntos sem que nada reprovasse.
54
+ * ⚠️ THIS IS A DIFFERENT PROBLEM FROM `bindingProblems`, WHICH IS WHY IT NEEDED ITS OWN FUNCTION: that one looks at
55
+ * ONE table and catches the same key on two actions; this one looks at TWO tables and catches the same key on two
56
+ * PLAYERS. Each `KEYBOARD_DUO` scheme passes the first on its own — and the arrows, if they stayed in both, would make
57
+ * the two characters walk together with nothing failing.
59
58
  *
60
- * A mensagem nomeia os dois donos, porque «tecla repetida» manda procurar o que a função já sabe.
59
+ * The message names both owners, because "repeated key" sends someone looking for what the function already knows.
61
60
  */
62
- export declare function conflitosEntreTabelas<T>(tabelas: readonly Readonly<Record<Action, Binding<T | readonly T[]>>>[]): string[];
63
- /** As ações que este transporte NÃO alcança. É o que uma tela de seleção precisa dizer ANTES de a criança começar. */
64
- export declare function unreachable<T>(tabela: Readonly<Record<Action, Binding<T | readonly T[]>>>): Action[];
61
+ export declare function conflictsBetweenTables<T>(tables: readonly Readonly<Record<Action, Binding<T | readonly T[]>>>[]): string[];
62
+ /** The actions this transport does NOT reach. It is what a selection screen has to say BEFORE the child starts. */
63
+ export declare function unreachable<T>(table: Readonly<Record<Action, Binding<T | readonly T[]>>>): Action[];
@@ -1,66 +1,50 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // input/default-bindings — O QUE CADA TRANSPORTE OFERECE, POR PADRÃO, PARA CADA UMA DAS QUATORZE AÇÕES.
2
+ // input/default-bindings — WHAT EACH TRANSPORT OFFERS, BY DEFAULT, FOR EACH OF THE FOURTEEN ACTIONS.
3
3
  //
4
- // ========================= O QUE ISTO É, E ONDE ELE MORA DE PROPÓSITO =========================
5
- // O ADR-0085 decidiu as quatorze POSIÇÕES (`core/actions.ts`) e disse, em tantas palavras, que os nomes
6
- // físicos — L1, R2, X, A — são BINDING e vivem no transporte, não no vocabulário. Este é o ficheiro onde eles
7
- // vivem. Um transporte novo (fala, olhar, toque) traz a sua tabela e não toca em `core/actions`.
4
+ // ========================= WHAT THIS IS, AND WHY IT LIVES WHERE IT DOES =========================
5
+ // ADR-0085 decided the fourteen POSITIONS (`core/actions.ts`) and said, in so many words, that the physical
6
+ // names — L1, R2, X, A — are BINDINGS and live in the transport, not in the vocabulary. This is the file where
7
+ // they live. A new transport (speech, gaze, touch) brings its own table and does not touch `core/actions`.
8
8
  //
9
- // ✅ AS TRÊS ESTÃO LIGADAS, e esta nota já mentiu duas vezes — cada versão dela era verdade no dia em que foi
10
- // escrita e deixou de ser sem ninguém a corrigir. A primeira dizia «NADA AQUI ESTÁ LIGADO AINDA» (morreu com a
11
- // issue #103, 06/09); a segunda dizia que só o gamepad estava, e morreu com a issue #118, que uniu as duas
12
- // tabelas de teclado. 📏 Medido em 2026-09-09:
9
+ // ✅ ALL THREE ARE WIRED:
13
10
  //
14
- // · `GAMEPAD_STANDARD` — `input/gamepad.ts:129` lê os índices desta tabela em vez de literais, e a ligação
15
- // apanhou uma discordância real: `action1` corria em X, R1 e R2 enquanto a tabela declarava R1 e R2 como
16
- // ombro e gatilho.
17
- // · `KEYBOARD_SOLO` / `KEYBOARD_DUO` — `input/keyboard.ts:73` constrói o `KB_DEFAULTS` a partir delas
18
- // (`vivo(KEYBOARD_SOLO)` e `KEYBOARD_DUO.map(vivo)`). Deixaram de ser duas listas paralelas: são a MESMA
19
- // decisão, derivada, e por isso a divergência de antes não pode voltar por esquecimento.
11
+ // · `GAMEPAD_STANDARD` — `input/pad-reading` reads this table's indices instead of literals (and
12
+ // `input/pad-defaults` lays the game's mapping over it). Wiring it caught a real disagreement: `action1` ran
13
+ // on X, R1 and R2 while the table declared R1 and R2 as shoulder and trigger.
14
+ // · `KEYBOARD_SOLO` / `KEYBOARD_DUO` — `input/keyboard` builds `KB_DEFAULTS` from them (`mutableCopy`). They
15
+ // stopped being two parallel lists: they are the SAME decision, derived, so the old divergence cannot come
16
+ // back by forgetting.
20
17
  //
21
- // ⚠️ E A DERIVAÇÃO É POR CÓPIA PROFUNDA (`vivo` faz JSON round-trip), em DUAS camadas — verificado antes de
22
- // escrito, porque a primeira versão desta linha dizia mais do que é verdade. `input/keyboard.ts` copia estas
23
- // tabelas para o `KB_DEFAULTS`, e copia OUTRA VEZ para o `kb` mutável. O remapeamento da criança muta o `kb`
24
- // («remapear uma tecla MUTA o objeto», diz o `setKB`), logo ele já não alcançaria isto nem sem a primeira
25
- // cópia. O que a primeira camada compra é o resto: `KB_DEFAULTS` é exportado, e sem ela qualquer consumidor
26
- // que lhe escrevesse dentro alterava o padrão de fábrica desta tabela para toda a gente.
18
+ // ⚠️ AND THE DERIVATION IS BY DEEP COPY (`mutableCopy` is a JSON round-trip), in TWO layers. `input/keyboard`
19
+ // copies these tables into `KB_DEFAULTS`, and copies AGAIN into the mutable `kb`. The child's remapping mutates
20
+ // `kb` ("remapping one key MUTATES the object", says `setKB`), so it would not reach this even without the first
21
+ // copy. What the first layer buys is the rest: `KB_DEFAULTS` is exported, and without it any consumer writing
22
+ // into it would change this table's factory default for everyone.
27
23
  //
28
- // 📌 A LIÇÃO QUE ESTA NOTA CARREGA AGORA É SOBRE SI PRÓPRIA: um comentário que descreve estado de ligação
29
- // apodrece a cada entrega. Este diz a DATA da medição, para que a próxima pessoa saiba contra o que a
30
- // comparar em vez de acreditar.
24
+ // ========================= THE KEYBOARD'S SYMMETRY, WHICH IS NOT DECORATION =========================
25
+ // The default the Dev specified rests on a block of the QWERTY:
31
26
  //
32
- // ========================= A SIMETRIA DO TECLADO, QUE NÃO É DECORAÇÃO =========================
33
- // O padrão que o Dev especificou apoia-se num bloco do QWERTY:
34
- //
35
- // 7 8 ← L1 sobre U, R1 sobre I
36
- // Y U I O ← L2 à esquerda de U, R2 à direita de I
27
+ // 7 8 ← L1 over U, R1 over I
28
+ // Y U I O ← L2 left of U, R2 right of I
37
29
  // H J K L
38
30
  //
39
- // ⚠️ E O MAPEAMENTO TECLADO↔XBOX É UMA ROTAÇÃO DE 45°, consistente nos quatro: X(oeste)→U(noroeste),
40
- // Y(norte)→I(nordeste), B(leste)→K(sudeste), A(sul)→J(sudoeste). O losango do controle pousa no quadrado
41
- // `U I / J K` girando um oitavo de volta. É por isso que a tabela cai bem no dedo: o que a memória muscular
42
- // guarda é a POSIÇÃO RELATIVA, não a letra.
31
+ // ⚠️ AND THE KEYBOARD↔XBOX MAPPING IS A 45° ROTATION, consistent across all four: X(west)→U(northwest),
32
+ // Y(north)→I(northeast), B(east)→K(southeast), A(south)→J(southwest). The pad's diamond lands on the `U I / J K`
33
+ // square by turning an eighth. That is why the table sits well under the finger: what muscle memory keeps is the
34
+ // RELATIVE POSITION, not the letter.
43
35
  //
44
- // ⚠️ E FOI ESSA SIMETRIA QUE DENUNCIOU UM ERRO NA ESPECIFICAÇÃO. Ela chegou com `I` atribuído DUAS vezes —
45
- // para `action4` e para R2 —, e o par simétrico de `Y` (à esquerda de U) é `O` (à direita de I). Adotado `O`.
46
- // O gate deste ficheiro reprova tecla repetida, então o erro não teria passado de qualquer forma; o que a
47
- // simetria deu foi a tecla CERTA em vez de só a notícia de que havia uma errada.
36
+ // ⚠️ AND IT WAS THAT SYMMETRY THAT EXPOSED AN ERROR IN THE SPECIFICATION. It arrived with `I` assigned TWICE —
37
+ // to `action4` and to R2 —, and the symmetric pair of `Y` (left of U) is `O` (right of I). `O` was adopted. This
38
+ // file's gate fails a repeated key, so the error would not have passed anyway; what the symmetry gave was the
39
+ // RIGHT key instead of only the news that one was wrong.
48
40
  import { ACTIONS } from '../core/actions.js';
49
- // ⚠️ A `Space` ESTÁ EM `action2`, E ISTO É A HISTÓRIA DE COMO LÁ FOI PARAR — porque este bloco dizia o
50
- // contrário e sobreviveu à decisão que o revogou.
51
- //
52
- // Ela ficou de fora da primeira versão desta tabela, e a razão estava certa: a barra é o segundo atalho do
53
- // pulo desde sempre, a especificação do padrão não a mencionava, e pô-la em `action2` por conta própria
54
- // seria decidir que o pulo mora ali. Se o preset da plataforma puser o pulo noutra posição, a barra segue o
55
- // verbo errado — pior do que ela não existir.
56
- //
57
- // O Dev decidiu (ADR-0086 §2) que o pulo mora em `action2`, e a barra voltou. O texto acima continuou a
58
- // dizer «fica de fora» durante todo esse tempo, ao lado de duas linhas que a declaram. Corrigido em
59
- // 2026-09-07, na mesma passagem da issue #118 — que trata exactamente desta classe de erro: um comentário
60
- // que descreve um estado que já passou.
41
+ // ⚠️ `Space` IS ON `action2` because ADR-0086 §2 put jump there. It was left out of the first version of this
42
+ // table, and for a sound reason at the time: the bar has been jump's second shortcut forever, the specification
43
+ // did not mention it, and putting it on `action2` unasked would have decided where jump lives. Once the Dev
44
+ // decided that (ADR-0086 §2), the bar came back.
61
45
  /**
62
- * Teclado, esquema SOLO. Códigos de `KeyboardEvent.code` — físicos, não a letra impressa, que muda com o
63
- * layout ABNT2/US e é a razão de nunca se usar `key` aqui.
46
+ * Keyboard, SOLO scheme. `KeyboardEvent.code` codes — physical, not the printed letter, which changes with the
47
+ * ABNT2/US layout and is the reason `key` is never used here.
64
48
  */
65
49
  export const KEYBOARD_SOLO = {
66
50
  up: ['KeyW', 'ArrowUp'],
@@ -74,46 +58,45 @@ export const KEYBOARD_SOLO = {
74
58
  leftShoulder: ['Digit7'], // L1
75
59
  leftTrigger: ['KeyY'], // L2
76
60
  rightShoulder: ['Digit8'], // R1
77
- rightTrigger: ['KeyO'], // R2 — ver a nota da simetria acima
78
- // ⚠️ E ESTAS DUAS FECHAM UMA DÍVIDA QUE O ADR-0074 §1 REGISTROU: `start` existia em dois transportes de
79
- // nove e faltava no teclado. Deixa de faltar. A simetria é de MÃO: `F` fica ao lado do polegar da mão que
80
- // se move (o bloco WASD), `H` ao lado da mão que age (o bloco UIJK).
81
- // `Enter` acompanha `H` porque JÁ pausava — `input/keydown.ts:240` tem `PAUSE_KEYS = {Escape, Enter}` —,
82
- // então declará-lo aqui descreve o que a tecla faz há muito, em vez de lhe dar um trabalho novo.
61
+ rightTrigger: ['KeyO'], // R2 — see the symmetry note above
62
+ // ⚠️ AND THESE TWO CLOSE A DEBT ADR-0074 §1 RECORDED: `start` existed in two transports of nine and was missing
63
+ // from the keyboard. It is no longer missing. The symmetry is one of HANDS: `F` sits by the thumb of the hand that
64
+ // moves (the WASD block), `H` by the hand that acts (the UIJK block).
65
+ // `Enter` goes with `H` because it ALREADY paused — `input/keydown` has `PAUSE_KEYS = {Escape, Enter}` —, so
66
+ // declaring it here describes what the key has long done instead of giving it a new job.
83
67
  start: ['KeyH', 'Enter'],
84
68
  select: ['KeyF'],
85
69
  };
86
70
  /**
87
- * Teclado, esquema de DOIS JOGADORES — as quatorze posições para cada um (ADR-0096).
71
+ * Keyboard, TWO-PLAYER scheme — the fourteen positions for each (ADR-0096).
88
72
  *
89
- * ⚠️ O JOGADOR 1 AQUI NÃO É O `KEYBOARD_SOLO`, e a diferença é UMA e obrigatória: as SETAS saem dele. No solo
90
- * elas são um segundo caminho para o direcional; em dupla são o direcional DO OUTRO. Deixá-las nos dois faria
91
- * os dois bonecos andarem juntos — um defeito que não dá erro em lado nenhum e que só se vê jogando a dois.
92
- * `conflitosEntreTabelas` existe por causa desta linha.
73
+ * ⚠️ PLAYER 1 HERE IS NOT `KEYBOARD_SOLO`, and the difference is ONE and mandatory: the ARROWS leave it. In solo
74
+ * they are a second path for the d-pad; in duo they are the OTHER player's d-pad. Leaving them in both would make
75
+ * the two characters walk together — a defect that raises no error anywhere and only shows when playing as two.
76
+ * `conflictsBetweenTables` exists because of this line.
93
77
  *
94
- * ⚠️ E A GEOMETRIA DO JOGADOR 2 É A MESMA DO JOGADOR 1, TRANSPOSTA PARA O TECLADO NUMÉRICO — o que faz a
95
- * memória muscular atravessar de um lado da mesa para o outro:
78
+ * ⚠️ AND PLAYER 2'S GEOMETRY IS PLAYER 1'S, MOVED TO THE NUMERIC KEYPAD — which is what carries muscle memory from
79
+ * one side of the table to the other:
96
80
  *
97
- * 7 8 / * ombros na linha DE CIMA
98
- * Y U I O 7 8 9 + gatilhos nas PONTAS da linha das ações
81
+ * 7 8 / * shoulders on the TOP row
82
+ * Y U I O 7 8 9 + triggers at the ENDS of the action row
99
83
  * J K 5 6
100
84
  *
101
- * action1 U ↔ Numpad8 (cima-esquerda) action4 I ↔ Numpad9 (cima-direita)
102
- * action2 J ↔ Numpad5 (baixo-esquerda) action3 K ↔ Numpad6 (baixo-direita)
85
+ * action1 U ↔ Numpad8 (top-left) action4 I ↔ Numpad9 (top-right)
86
+ * action2 J ↔ Numpad5 (bottom-left) action3 K ↔ Numpad6 (bottom-right)
103
87
  *
104
- * O bloco `U I / J K` e o bloco `8 9 / 5 6` têm a MESMA forma, então a rotação de 45° que o cabeçalho deste
105
- * ficheiro descreve para o Xbox vale igual para o jogador 2. Não é coincidência de teclado: é o que torna o
106
- * padrão ensinável uma vez só.
88
+ * The `U I / J K` block and the `8 9 / 5 6` block have the SAME shape, so the 45° rotation this file's header
89
+ * describes for the Xbox holds for player 2 as well. It is not a keyboard coincidence: it is what makes the default
90
+ * teachable once.
107
91
  *
108
- * ⚠️ `Digit7`/`Digit8` (jogador 1) e `Numpad7` (jogador 2) SÃO TECLAS DIFERENTES, e é por isso que a
109
- * especificação do Dev diz «alphanumeric» e «numeric» em tantas palavras. `KeyboardEvent.code` distingue-as
110
- * sempre; `key` não — com Num Lock desligado o numérico chega como `ArrowUp`/`Home`, e um esquema lido por
111
- * `key` juntaria o direcional do jogador 2 com as ações dele. Mais uma razão de este ficheiro só falar
112
- * `code`.
92
+ * ⚠️ `Digit7`/`Digit8` (player 1) and `Numpad7` (player 2) ARE DIFFERENT KEYS, which is why the Dev's specification
93
+ * says «alphanumeric» and «numeric» in so many words. `KeyboardEvent.code` always tells them apart; `key` does not —
94
+ * with Num Lock off the keypad arrives as `ArrowUp`/`Home`, and a scheme read by `key` would merge player 2's d-pad
95
+ * with their actions. One more reason this file only speaks `code`.
113
96
  */
114
97
  export const KEYBOARD_DUO = Object.freeze([
115
98
  {
116
- // JOGADOR 1 — a mão esquerda anda (WASD), a direita age (UIJK). Sem as setas: são do jogador 2.
99
+ // PLAYER 1 — the left hand moves (WASD), the right acts (UIJK). No arrows: they are player 2's.
117
100
  up: ['KeyW'],
118
101
  down: ['KeyS'],
119
102
  left: ['KeyA'],
@@ -130,9 +113,9 @@ export const KEYBOARD_DUO = Object.freeze([
130
113
  select: ['KeyF'],
131
114
  },
132
115
  {
133
- // JOGADOR 2 — as setas andam, o teclado numérico age. `Enter` fica com o jogador 1; o `NumpadEnter` não
134
- // entra aqui de propósito, porque `ui/menu-nav` já o usa como CONFIRMAR em qualquer menu (KEY_YES) e
135
- // `input/keydown` registra, verbatim, que ele NÃO pausa. Dar-lhe um terceiro trabalho seria sobrepor.
116
+ // PLAYER 2 — the arrows move, the numeric keypad acts. `Enter` stays with player 1; `NumpadEnter` is left out on
117
+ // purpose, because `ui/menu-intent` already uses it as CONFIRM in every menu (KEY_YES) and `input/keydown`
118
+ // records that it does NOT pause. Giving it a third job would overlap.
136
119
  up: ['ArrowUp'],
137
120
  down: ['ArrowDown'],
138
121
  left: ['ArrowLeft'],
@@ -141,41 +124,41 @@ export const KEYBOARD_DUO = Object.freeze([
141
124
  action2: ['Numpad5'],
142
125
  action3: ['Numpad6'],
143
126
  action4: ['Numpad9'],
144
- leftShoulder: ['NumpadDivide'], // a tecla `/` do bloco numérico
127
+ leftShoulder: ['NumpadDivide'], // the keypad's `/` key
145
128
  leftTrigger: ['Numpad7'],
146
- rightShoulder: ['NumpadMultiply'], // a tecla `*`
147
- rightTrigger: ['NumpadAdd'], // a tecla `+`
129
+ rightShoulder: ['NumpadMultiply'], // the `*` key
130
+ rightTrigger: ['NumpadAdd'], // the `+` key
148
131
  /**
149
- * ⚠️ `ShiftRight` É A PORTA DE SAÍDA, E ELA FALTAVA (#122).
132
+ * ⚠️ `ShiftRight` IS THE WAY OUT, AND IT WAS MISSING (#122).
150
133
  *
151
- * Um Chromebook não tem bloco numérico, e um Chromebook é o hardware que o pilar 1 nomeia. Medido em
152
- * 2026-09-07: das catorze posições deste assento, **DEZ só se alcançam pelo numpad** — as oito ações
153
- * mais o `start` e o `select`. A criança da segunda cadeira anda pelas setas, não age em nada, e **não
154
- * consegue abrir o menu para consertar**, porque a tecla que abre o menu está no mesmo bloco que falta.
134
+ * A Chromebook has no numeric keypad, and a Chromebook is the hardware pillar 1 names. Of this seat's fourteen
135
+ * positions, **TEN are reachable only through the keypad** — the eight actions plus `start` and `select`. The
136
+ * child in the second chair moves with the arrows, acts on nothing, and **cannot open the menu to fix it**,
137
+ * because the key that opens the menu is in the same missing block.
155
138
  *
156
- * Isso é o que a auditoria chamou de «um padrão do qual a criança não escapa», e o conserto que ela pede
157
- * é textual: *«tornar o próprio padrão remapeável, e não trocar as teclas que ele escolheu».* As teclas
158
- * ficam — o layout do numpad é melhor onde ele existe, é um bloco físico sob uma mão, e não tira nada ao
159
- * primeiro jogador. O que entra é UMA porta que todo teclado tem, para o remapeamento ser alcançável.
139
+ * That is what the audit called «um padrão do qual a criança não escapa», and the fix it asks for is literal:
140
+ * *«tornar o próprio padrão remapeável, e não trocar as teclas que ele escolheu».* The keys stay — the keypad
141
+ * layout is better where it exists, it is one physical block under one hand, and it takes nothing from the first
142
+ * player. What enters is ONE door every keyboard has, so the remapping is reachable.
160
143
  *
161
- * ⚠️ E É SÓ NO `start`, de propósito: da pausa alcança-se a tela de remapeamento, e de lá TODAS as outras
162
- * treze posições. Uma porta chega para escapar; cada padrão a mais é uma tecla tirada do bolo comum, e
163
- * este teclado já é repartido por duas crianças.
144
+ * ⚠️ AND ONLY ON `start`, on purpose: from the pause the remapping screen is reachable, and from there ALL the
145
+ * other thirteen positions. One door is enough to escape; each extra default is a key taken from the common pool,
146
+ * and this keyboard is already shared by two children.
164
147
  *
165
- * `ShiftRight` porque existe em todo o teclado, fica ao lado do bloco de setas (a mesma mão que já as
166
- * usa), não é tecla de texto — e está LIVRE nas quatro tabelas, o que foi medido e não suposto.
148
+ * `ShiftRight` because every keyboard has it, it sits beside the arrow block (the same hand that already uses
149
+ * them), it is not a text key — and it is FREE in all four tables, which was measured and not assumed.
167
150
  */
168
151
  start: ['Numpad1', 'ShiftRight'],
169
152
  select: ['Numpad0'],
170
153
  },
171
154
  ]);
172
155
  /**
173
- * Gamepad, mapa PADRÃO da Gamepad API (`mapping: "standard"`), que é o que um controle de Xbox reporta.
174
- * O número é o índice em `gamepad.buttons`.
156
+ * Gamepad, the Gamepad API's STANDARD map (`mapping: "standard"`), which is what an Xbox controller reports.
157
+ * The number is the index into `gamepad.buttons`.
175
158
  */
176
159
  export const GAMEPAD_STANDARD = {
177
- // As direções não vêm de botões: vêm do stick 0/1 e do D-pad 12–15, em `stdDirs`. Declarar `null` aqui
178
- // diria "não alcança", que é falso — por isso os índices do D-pad estão nomeados.
160
+ // The directions do not come from buttons: they come from stick 0/1 and the D-pad 12–15, in `stdDirs`. Declaring
161
+ // `null` here would say "does not reach", which is false — that is why the D-pad indices are named.
179
162
  up: 12,
180
163
  down: 13,
181
164
  left: 14,
@@ -185,80 +168,80 @@ export const GAMEPAD_STANDARD = {
185
168
  action3: 1, // B
186
169
  action4: 3, // Y
187
170
  leftShoulder: 4, // L1
188
- leftTrigger: 6, // L2 — ⚠️ gatilho ANALÓGICO: a API expõe-no como botão com `.value`, e em alguns
189
- // controles também como eixo. `bindActive` já trata os dois; `padActions` só lê
190
- // `pressed`, o que funciona mas descarta o curso do gatilho.
171
+ leftTrigger: 6, // L2 — ⚠️ ANALOGUE trigger: the API exposes it as a button with `.value`, and on some
172
+ // controllers also as an axis. `bindActive` already handles both; `padActions` only reads
173
+ // `pressed`, which works but throws away the trigger's travel.
191
174
  rightShoulder: 5, // R1
192
- rightTrigger: 7, // R2 — mesma ressalva analógica
175
+ rightTrigger: 7, // R2 — same analogue caveat
193
176
  start: 9, // Start / Menu
194
177
  select: 8, // Select / Back / View
195
178
  };
196
179
  /**
197
- * Todos os problemas de uma tabela de binding. VAZIA quer dizer conforme.
180
+ * Every problem in a binding table. EMPTY means conformant.
198
181
  *
199
- * ⚠️ O QUE ISTO EXISTE PARA APANHAR É O DUPLO, e ele já aconteceu: a especificação chegou com `I` em duas
200
- * ações. Um binding duplicado não dá erro em lado nenhum — as duas ações disparam juntas, e a criança vê uma
201
- * ação dupla intermitente que ninguém consegue reproduzir de propósito.
182
+ * ⚠️ WHAT THIS EXISTS TO CATCH IS THE DOUBLE, and it has already happened: the specification arrived with `I` on two
183
+ * actions. A duplicated binding raises no error anywhere — the two actions fire together, and the child sees an
184
+ * intermittent double action nobody can reproduce on purpose.
202
185
  */
203
- export function bindingProblems(tabela) {
186
+ export function bindingProblems(table) {
204
187
  const p = [];
205
- const dono = new Map();
206
- for (const acao of ACTIONS) {
207
- if (!(acao in tabela)) {
208
- p.push(`binding: ${acao} is not declared - write null if the transport cannot reach it`);
188
+ const actionOfKey = new Map();
189
+ for (const action of ACTIONS) {
190
+ if (!(action in table)) {
191
+ p.push(`binding: ${action} is not declared - write null if the transport cannot reach it`);
209
192
  continue;
210
193
  }
211
- const v = tabela[acao];
194
+ const v = table[action];
212
195
  if (v === null)
213
196
  continue;
214
- const itens = Array.isArray(v) ? v : [v];
215
- if (itens.length === 0) {
216
- p.push(`binding: ${acao} has an empty list - write null instead`);
197
+ const keyList = Array.isArray(v) ? v : [v];
198
+ if (keyList.length === 0) {
199
+ p.push(`binding: ${action} has an empty list - write null instead`);
217
200
  continue;
218
201
  }
219
- for (const item of itens) {
220
- const chave = String(item);
221
- const anterior = dono.get(chave);
222
- if (anterior)
223
- p.push(`binding: ${chave} is bound to both ${anterior} and ${acao}`);
202
+ for (const item of keyList) {
203
+ const key = String(item);
204
+ const previous = actionOfKey.get(key);
205
+ if (previous)
206
+ p.push(`binding: ${key} is bound to both ${previous} and ${action}`);
224
207
  else
225
- dono.set(chave, acao);
208
+ actionOfKey.set(key, action);
226
209
  }
227
210
  }
228
211
  return p;
229
212
  }
230
213
  /**
231
- * As teclas que DUAS OU MAIS tabelas reclamam para si. VAZIA quer dizer que os jogadores não se atropelam.
214
+ * The keys TWO OR MORE tables claim. EMPTY means the players do not trample each other.
232
215
  *
233
- * ⚠️ ISTO É UM PROBLEMA DIFERENTE DO `bindingProblems`, E FOI POR ISSO QUE PRECISOU DE FUNÇÃO PRÓPRIA: aquele
234
- * olha UMA tabela e apanha a mesma tecla em duas ações; este olha DUAS tabelas e apanha a mesma tecla em dois
235
- * JOGADORES. Cada esquema do `KEYBOARD_DUO` passa no primeiro sozinho — e as setas, se ficassem nos dois,
236
- * fariam os dois bonecos andarem juntos sem que nada reprovasse.
216
+ * ⚠️ THIS IS A DIFFERENT PROBLEM FROM `bindingProblems`, WHICH IS WHY IT NEEDED ITS OWN FUNCTION: that one looks at
217
+ * ONE table and catches the same key on two actions; this one looks at TWO tables and catches the same key on two
218
+ * PLAYERS. Each `KEYBOARD_DUO` scheme passes the first on its own — and the arrows, if they stayed in both, would make
219
+ * the two characters walk together with nothing failing.
237
220
  *
238
- * A mensagem nomeia os dois donos, porque «tecla repetida» manda procurar o que a função já sabe.
221
+ * The message names both owners, because "repeated key" sends someone looking for what the function already knows.
239
222
  */
240
- export function conflitosEntreTabelas(tabelas) {
223
+ export function conflictsBetweenTables(tables) {
241
224
  const p = [];
242
- const dono = new Map();
243
- tabelas.forEach((tabela, i) => {
244
- for (const acao of ACTIONS) {
245
- const v = tabela[acao];
225
+ const actionOfKey = new Map();
226
+ tables.forEach((table, i) => {
227
+ for (const action of ACTIONS) {
228
+ const v = table[action];
246
229
  if (v === null || v === undefined)
247
230
  continue;
248
231
  for (const item of (Array.isArray(v) ? v : [v])) {
249
- const chave = String(item);
250
- const aqui = `p${i + 1}.${acao}`;
251
- const anterior = dono.get(chave);
252
- if (anterior)
253
- p.push(`cross: ${chave} is claimed by both ${anterior} and ${aqui}`);
232
+ const key = String(item);
233
+ const here = `p${i + 1}.${action}`;
234
+ const previous = actionOfKey.get(key);
235
+ if (previous)
236
+ p.push(`cross: ${key} is claimed by both ${previous} and ${here}`);
254
237
  else
255
- dono.set(chave, aqui);
238
+ actionOfKey.set(key, here);
256
239
  }
257
240
  }
258
241
  });
259
242
  return p;
260
243
  }
261
- /** As ações que este transporte NÃO alcança. É o que uma tela de seleção precisa dizer ANTES de a criança começar. */
262
- export function unreachable(tabela) {
263
- return ACTIONS.filter((a) => tabela[a] === null || tabela[a] === undefined);
244
+ /** The actions this transport does NOT reach. It is what a selection screen has to say BEFORE the child starts. */
245
+ export function unreachable(table) {
246
+ return ACTIONS.filter((a) => table[a] === null || table[a] === undefined);
264
247
  }
@@ -1,15 +1,15 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  export declare const PAD_DESIGNS: Record<string, Record<string, string[]>>;
3
3
  /**
4
- * Glifos de controle que NÃO SE LEEM — chave i18n do nome falado de cada um (ADR-0044, item 4).
4
+ * Pad glyphs that CANNOT BE READ ALOUD — the i18n key of each one's spoken name (ADR-0044, item 4).
5
5
  *
6
- * Um leitor de tela lê `✕` como "sinal de multiplicação", ou não lê nada, e `△` costuma sair mudo. É por isso
7
- * que a legenda da pausa carregava `aria-hidden="true"`: escondiam-se o ruído E a informação juntos. Aqui está
8
- * a metade que faltava para poder tirar o atributo — o glifo continua na tela para quem o reconhece, e a
9
- * PALAVRA existe para quem o escuta.
6
+ * A screen reader reads `✕` as "multiplication sign", or reads nothing, and `△` usually comes out mute. That is why the
7
+ * pause legend carried `aria-hidden="true"`: the noise AND the information were hidden together. Here is the half that
8
+ * was missing to take the attribute off — the glyph stays on screen for whoever recognises it, and the WORD exists for
9
+ * whoever hears it.
10
10
  *
11
- * Só os quatro do PlayStation entram. `A`, `B`, `X`, `Y` e `0`–`3` já se leem, e traduzi-los para "letra A"
12
- * seria acrescentar ruído em nome de acessibilidade — o defeito que este item conserta pelo avesso.
11
+ * Only the four PlayStation ones are here. `A`, `B`, `X`, `Y` and `0`–`3` already read, and translating them to "letter
12
+ * A" would add noise in accessibility's name — the defect this item fixes, inside out.
13
13
  */
14
14
  export declare const PAD_GLYPH_SPOKEN: Record<string, string>;
15
15
  export declare const TOUCH_DEFAULT: Record<string, string>;