@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
@@ -0,0 +1,332 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // ui/settings-mobility — the per-player MOBILITY panel: the thin DOM-touching render/reflect functions; what a choice IS
3
+ // lives in ./mobility-choices.js. DI via initSettingsMobility(ctx): `$` (DOM selector), `srSay`, `store`
4
+ // (platform/storage shape), `players`/`getNumPlayers` (the live round) and optionally `rebuildCoins` (the game's reaction
5
+ // to Easy Mode).
6
+ //
7
+ // ⚠️ The movement latch setter is the ENGINE's (`setMoveLatch`, ADR-0106 §4, step 1b): being shared by two ENGINE
8
+ // surfaces — this panel and the pause bar's `altmove` icon — is a reason for the engine to own it. The ctx field is
9
+ // OPTIONAL, so whoever injects still rules and whoever does not still gets it.
10
+ // Overlay open/close plumbing (frontOverlay, Escape handling) is the SHARED helper every settings panel uses.
11
+ import { markChanged, markMenuChanged } from './changed-mark.js';
12
+ import { DEFAULTS } from '../core/setting-defaults.js';
13
+ // ⚠️ A DIRECT IMPORT, not one more `ctx` piece: an injected key name is a field a consumer may omit, and omitting it here
14
+ // would make the panel write under a crooked name. The table is stateless (`platform/storage-keys`, ADR-0232), so the
15
+ // import brings names and no storage.
16
+ import { KEYS } from '../platform/storage-keys.js';
17
+ import { writeLatch } from '../input/latch-store.js';
18
+ import { applyLatch, BASE_DA_MARCHA, } from '../input/latch-sync.js';
19
+ import { clampSelPlayer, anyMobilityActive, onOffLabel, playerTabsHTML, easyAnnouncement, playerPrefix } from './mobility-choices.js';
20
+ import { controlRow, labelRow } from './panel-widgets.js';
21
+ // ---------------------------------------------------------------------------------------------
22
+ // Pure logic (no `document`, testable in node)
23
+ // ---------------------------------------------------------------------------------------------
24
+ /** localStorage key for a player's Modo Fácil flag (== platform/storage.ts's `easy_p{i}` pattern). */
25
+ export function easyKey(i) {
26
+ // ⚠️ IT DELEGATES, like its siblings: two copies of a name change one at a time, and `platform/storage` makes the keys
27
+ // functions to stop anyone writing under a crooked name. A gate asserts the three agree with `KEYS`.
28
+ return KEYS.easyP(i);
29
+ }
30
+ /**
31
+ * localStorage key of the RUN button's latch, in the LEGACY form (no transport).
32
+ *
33
+ * ⚠️ IT DELEGATES to `platform/storage`, so there is one name only.
34
+ *
35
+ * ⚠️ AND IT IS THE LEGACY KEY. ADR-0104 §C put the TRANSPORT in the name, because the latch belongs to the device and not
36
+ * the person; this one is still read to inherit what the child already had, and is not written. The new key is
37
+ * `latchKey`, in `input/latch-scope`.
38
+ */
39
+ export function toggleRunKey(i) {
40
+ return KEYS.toggleRunP(i);
41
+ }
42
+ /** localStorage key of the MOVEMENT latch, per player. It delegates, like the two siblings above. */
43
+ export function toggleMoveKey(i) {
44
+ return KEYS.toggleMoveP(i);
45
+ }
46
+ /**
47
+ * SWITCHES A PLAYER'S MOVEMENT LATCH ON OR OFF — the engine does it (ADR-0106 §4).
48
+ *
49
+ * ⚠️ Being shared by TWO engine surfaces (this panel and the pause bar's `altmove` icon) is a reason for the engine to
50
+ * own it, not for the cartridge to keep it — and every step is the engine's: `toggleMove` and `walkDir` are
51
+ * `PlayerBase` fields, the key is `platform/storage`'s, and `sr.motor.toggleMove*` are engine i18n keys. There is no
52
+ * game effect left to inject.
53
+ */
54
+ export function setMoveLatch(ctx, i, on) {
55
+ const p = ctx.players[i];
56
+ if (!p)
57
+ return;
58
+ // 📌 THE SWITCH-OFF RULE LIVES IN ONE PLACE (issue #127): `applyLatch` sets the value AND stops whoever walks by latch.
59
+ // It is shared with the edge sync (`input/latch-sync`), which answers the SAME question when the device changes — two
60
+ // copies of "otherwise the character walks by itself" would drift the day one of them changed.
61
+ applyLatch(p, on);
62
+ // ⚠️ BOTH KEYS, AND THE OLD ONE STAYS FOR NOW — the same shape as `p.visual` beside `p.viz` (#104 step 1a), for the same
63
+ // reason: a cartridge may still READ it through `KEYS.toggleMoveP(i)`. Stopping writing it now would make the child
64
+ // lose the choice at the next boot — the cost ADR-0113 names.
65
+ ctx.store.setBool(toggleMoveKey(i), on);
66
+ // 📌 And the NEW key, when the device is known — on every device (ADR-0249): on eyes, face, gestures and speech this is the
67
+ // child's choice overriding the game's `holdsKeys()` default for that transport.
68
+ const transport = ctx.transportInUse ? ctx.transportInUse(i) : null;
69
+ if (transport)
70
+ writeLatch((key, isOn) => ctx.store.setBool(key, isOn), BASE_DA_MARCHA, i, transport, on);
71
+ // 📌 THE ANNOUNCEMENT IS UNCONDITIONAL, unlike `applyLatch`, which returns "changed". The child pressed the icon:
72
+ // staying silent because the value already was that would leave the button with no answer for whoever listens.
73
+ const { t } = ctx;
74
+ ctx.srSay(playerPrefix(t, i, ctx.getNumPlayers()) + t(on ? 'sr.motor.toggleMoveOn' : 'sr.motor.toggleMoveOff'));
75
+ }
76
+ /**
77
+ * SWITCHES THE RUN LATCH ON OR OFF — `setMoveLatch`'s sibling, and simpler.
78
+ *
79
+ * 🎯 THE SAME REASON TO EXIST: every step is the engine's — `toggleRun` is a `PlayerBase` field, the key is
80
+ * `platform/storage`'s `KEYS.toggleRunP(i)`, and `sr.motor.toggleRun*` are engine i18n keys. **There is no game effect
81
+ * to inject**, which is why `SettingsMobilityCtx.setToggleRun` is optional: a game that does not supply it still gets a
82
+ * live run row instead of a dead one.
83
+ *
84
+ * ⚠️ AND IT DOES NOT CALL `applyLatch`, unlike its sibling. That one stops whoever walks by latch on switch-off, because
85
+ * the MOVEMENT latch leaves the character walking by itself; the run latch governs a speed lock, which cannot leave anyone
86
+ * moving. Copying the line "for symmetry" would touch `walkDir` because of a button that does not.
87
+ *
88
+ * 📌 The announcement is UNCONDITIONAL, like its sibling's: the child pressed the button, and staying silent because the
89
+ * value already was that leaves the control with no answer for whoever listens instead of looking.
90
+ */
91
+ export function setRunLatch(ctx, i, on) {
92
+ const p = ctx.players[i];
93
+ if (!p)
94
+ return;
95
+ p.toggleRun = on;
96
+ ctx.store.setBool(toggleRunKey(i), on);
97
+ const { t } = ctx;
98
+ ctx.srSay(playerPrefix(t, i, ctx.getNumPlayers()) + t(on ? 'sr.motor.toggleRunOn' : 'sr.motor.toggleRunOff'));
99
+ }
100
+ /**
101
+ * MOUNTS THIS PANEL'S INSIDE — the per-seat tabs and the three rows it reaches.
102
+ *
103
+ * 🔴 THE CONTRACT WOULD OTHERWISE BE INVISIBLE (the shape `ui/panel-shell` names one level up): this module looks for
104
+ * `#movement-players`, `#opt-facil`, `#opt-altmove` and `#opt-togglerun`, and nothing in the type says so — so it builds
105
+ * them, instead of a panel that opens with nothing but a card, a title and a reset button.
106
+ *
107
+ * ⚠️ AND IT LIVES HERE, not in the composition root: whoever knows these four ids and each control's shape is this file,
108
+ * and nobody else. A root writing them would be a root guessing.
109
+ *
110
+ * ⚠️ THE THREE ROWS ARE ALWAYS CREATED, the latch row included. Whether it is SEEN is decided at init by `holdsKeys`
111
+ * (ADR-0115), with `hidden`, which takes the row off the screen AND out of the accessibility tree. Creating it only when
112
+ * it applies would put the same rule in two places, and the day they diverged the row would appear in a game where it
113
+ * does nothing.
114
+ *
115
+ * 📌 THE ORDER IS THE DECISION, as in every menu of this project (ADR-0044 §2): the tabs first, because they say WHOSE
116
+ * the next choices are; then Easy Mode, the most sought; and the two latches together, the same idea applied to two
117
+ * buttons.
118
+ *
119
+ * Idempotent: calling it twice reuses the list instead of duplicating it.
120
+ */
121
+ export function mountMobilityInside(t, ctx, card, list) {
122
+ if (!ctx.find('#movement-players')) {
123
+ const abas = ctx.create('div');
124
+ abas.id = 'movement-players';
125
+ // Born hidden and empty: `renderMovPlayers()` draws them, because it knows how many seats there are NOW — and the
126
+ // number changes during the match.
127
+ abas.hidden = true;
128
+ card.insertBefore(abas, list);
129
+ }
130
+ const rows = [
131
+ { id: 'opt-facil', label: t('motor.facil'), hint: t('motor.facil.dica') },
132
+ { id: 'opt-altmove', label: t('motor.altmove'), hint: t('motor.altmove.dica') },
133
+ { id: 'opt-togglerun', label: t('motor.togglerun'), hint: t('motor.togglerun.dica') },
134
+ ];
135
+ for (const spec of rows) {
136
+ // ⚠️ IT RELABELS INSTEAD OF SKIPPING when the row exists, which is why this function is also called from every
137
+ // open's `render()`: text captured at boot may be in the fallback language, and the title and the rows would end
138
+ // up in different languages on the same screen. See `ui/panel-widgets.labelRow`.
139
+ const existingRow = ctx.find('#' + spec.id);
140
+ if (existingRow) {
141
+ const rowNode = existingRow.closest('.ctrl-row');
142
+ if (rowNode)
143
+ labelRow(rowNode, spec);
144
+ continue;
145
+ }
146
+ list.appendChild(controlRow(ctx, spec).row);
147
+ }
148
+ }
149
+ // ---------------------------------------------------------------------------------------------
150
+ // DOM-facing (thin) — requires `document`/injected ctx
151
+ // ---------------------------------------------------------------------------------------------
152
+ export function initSettingsMobility(ctx) {
153
+ const { t } = ctx;
154
+ // ⚠️ RESOLVED ONCE: whoever injects rules, whoever does not still gets it — the engine does it itself (`setMoveLatch`).
155
+ const setToggleMove = ctx.setToggleMove ?? ((i, on) => setMoveLatch(ctx, i, on));
156
+ // Its sibling, by the same rule and for the same reason — see `setRunLatch`.
157
+ const setToggleRun = ctx.setToggleRun ?? ((i, on) => setRunLatch(ctx, i, on));
158
+ // ⚠️ THE WORLD'S REACTION IS THE GAME'S, and its absence is not a dead button: `setEasy` has already written,
159
+ // persisted and announced before getting here.
160
+ const rebuildCoins = ctx.rebuildCoins ?? (() => { });
161
+ let selMovPlayer = 0; // the player selected in the mobility panel
162
+ const easyModeButton = ctx.$('#opt-facil');
163
+ const altMoveBtn = ctx.$('#opt-altmove');
164
+ const altMoveRow = altMoveBtn?.closest('.ctrl-row') ?? null;
165
+ /*
166
+ * ADR-0115 · THE ROW DISAPPEARS IN A GAME THAT HOLDS NOTHING — and disappears for EVERYONE.
167
+ *
168
+ * 🔴 `hidden` and not `aria-disabled`: the child who depends on the latch opens this panel to switch it on, and in a
169
+ * quiz there is nothing to switch on. A control disabled with a reason is still a control that does nothing — and it
170
+ * still takes a place in keyboard navigation, between two that work.
171
+ * 📌 Where the game holds keys the row is offered on EVERY device, eyes and voice included (ADR-0249): there the latch
172
+ * starts as the game's answer, and this row is how the child changes it.
173
+ * ⚠️ `hidden` and not removal: the row may be the page's own markup, and `hidden` is reversible and idempotent where
174
+ * removing someone else's markup is neither.
175
+ */
176
+ if (!ctx.holdsKeys && altMoveRow)
177
+ altMoveRow.hidden = true;
178
+ const toggleRunBtn = ctx.$('#opt-togglerun');
179
+ // the bar lights up if ANY player uses Easy Mode or a latch
180
+ function reflectMovementBtn() {
181
+ const b = ctx.$('#opt-movement');
182
+ if (b)
183
+ b.classList.toggle('is-on', anyMobilityActive(ctx.players));
184
+ refreshMarks();
185
+ }
186
+ /**
187
+ * The left-the-default mark (ADR-0029). Hung on the reflect that ALREADY runs on every change of the two controls,
188
+ * because a mark that needs its own call is a mark someone will forget — and a wrong mark sends the child to undo what
189
+ * they never touched.
190
+ *
191
+ * The scope follows this menu's reset: the PREFERENCES. The input methods (eyes, mapping) stay out here too — not
192
+ * because they cannot change, but because their default does not live in DEFAULTS, and marking without a single source
193
+ * of "default" would invent a second opinion on it.
194
+ */
195
+ function refreshMarks() {
196
+ const easy = ctx.players.some((p) => !!p.easy) !== DEFAULTS.easy;
197
+ const alt = ctx.players.some((p) => !!p.toggleMove) !== DEFAULTS.toggleMove;
198
+ // THE RUN LATCH ASKS DIFFERENTLY, because it SWITCHES ON BY ITSELF on the touch controls. Marking by STATE would
199
+ // light the mark for everyone playing on a tablet, with nobody touching anything — and a mark always lit means
200
+ // nothing.
201
+ //
202
+ // So what marks is the STORED CHOICE. A saved value means someone touched that control; the automatic switch-on
203
+ // saves nothing, so it does not mark.
204
+ const anyRunToggleChosen = ctx.players.some((p, i) => ctx.store.get(toggleRunKey(i)) != null && !!p.toggleRun !== DEFAULTS.toggleRun);
205
+ markChanged(t, easyModeButton?.closest('.ctrl-row') ?? null, easy);
206
+ markChanged(t, altMoveBtn?.closest('.ctrl-row') ?? null, alt);
207
+ markChanged(t, toggleRunBtn?.closest('.ctrl-row') ?? null, anyRunToggleChosen);
208
+ markMenuChanged(t, ctx.$('[data-act="motora"]'), [easy, alt, anyRunToggleChosen]);
209
+ }
210
+ function drawEasy() {
211
+ const p = ctx.players[selMovPlayer];
212
+ const on = !!(p && p.easy);
213
+ if (easyModeButton) {
214
+ easyModeButton.classList.toggle('is-on', on);
215
+ easyModeButton.setAttribute('aria-pressed', String(on));
216
+ easyModeButton.textContent = onOffLabel(t, on);
217
+ }
218
+ reflectMovementBtn();
219
+ }
220
+ function reflectToggleRun() {
221
+ const p = ctx.players[selMovPlayer];
222
+ const on = !!(p && p.toggleRun);
223
+ if (toggleRunBtn) {
224
+ toggleRunBtn.classList.toggle('is-on', on);
225
+ toggleRunBtn.setAttribute('aria-pressed', String(on));
226
+ toggleRunBtn.textContent = onOffLabel(t, on);
227
+ }
228
+ reflectMovementBtn();
229
+ }
230
+ function reflectAltMove() {
231
+ const p = ctx.players[selMovPlayer];
232
+ const on = !!(p && p.toggleMove);
233
+ if (altMoveBtn) {
234
+ altMoveBtn.classList.toggle('is-on', on);
235
+ altMoveBtn.setAttribute('aria-pressed', String(on));
236
+ altMoveBtn.textContent = onOffLabel(t, on);
237
+ }
238
+ reflectMovementBtn();
239
+ }
240
+ function setEasy(i, on) {
241
+ const p = ctx.players[i];
242
+ if (!p)
243
+ return;
244
+ p.easy = on;
245
+ ctx.store.setBool(easyKey(i), on);
246
+ drawEasy();
247
+ rebuildCoins();
248
+ ctx.srSay(easyAnnouncement(t, i, ctx.getNumPlayers(), on));
249
+ }
250
+ function renderMovPlayers() {
251
+ const tabs = ctx.$('#movement-players');
252
+ if (!tabs)
253
+ return;
254
+ const numPlayers = ctx.getNumPlayers();
255
+ selMovPlayer = clampSelPlayer(selMovPlayer, numPlayers);
256
+ tabs.hidden = true; // no tabs — each player edits only their own (scope = the pause actor)
257
+ tabs.innerHTML = playerTabsHTML(numPlayers, selMovPlayer);
258
+ tabs.querySelectorAll('button[data-mp]').forEach((b) => {
259
+ b.addEventListener('click', () => {
260
+ selMovPlayer = Number(b.dataset.mp);
261
+ renderMovPlayers();
262
+ drawEasy();
263
+ reflectAltMove();
264
+ });
265
+ });
266
+ // The prose goes back to the footer after the rows are rebuilt (CLAUDE.md §4, #109).
267
+ ctx.fillExplain?.(ctx.$('#movement .overlay__card'));
268
+ }
269
+ /**
270
+ * The panel's four buttons — easy mode, the move toggle, the run toggle and the reset — wired where the page carries
271
+ * them. The engine builds none of them here; a page that lacks one simply has that row missing.
272
+ */
273
+ function wireButtons() {
274
+ if (easyModeButton) {
275
+ easyModeButton.addEventListener('click', () => setEasy(selMovPlayer, !ctx.players[selMovPlayer].easy));
276
+ }
277
+ if (altMoveBtn) {
278
+ altMoveBtn.addEventListener('click', () => {
279
+ setToggleMove(selMovPlayer, !ctx.players[selMovPlayer].toggleMove);
280
+ reflectAltMove();
281
+ });
282
+ }
283
+ if (toggleRunBtn) {
284
+ toggleRunBtn.addEventListener('click', () => {
285
+ setToggleRun(selMovPlayer, !ctx.players[selMovPlayer].toggleRun);
286
+ reflectToggleRun();
287
+ });
288
+ }
289
+ // ---- reset THIS menu's defaults (ADR-0028) ----
290
+ //
291
+ // The reach here is SMALLER than the screen, on purpose. The mobility panel also hosts the input methods (key and
292
+ // controller mapping); the reset returns the PREFERENCES and does not touch the INPUT METHOD, for a reason worth more
293
+ // than symmetry:
294
+ //
295
+ // A RESET MAY ONLY UNDO WHAT IT CAN ALSO REDO.
296
+ //
297
+ // Whoever remapped the keys did it because they reach only some: returning the factory map returns keys their hand
298
+ // does not reach. That mapping has its own reset (#ctrl-reset), where the choice is explicit and not a side effect.
299
+ //
300
+ // That is why the announcement SAYS what was left out: a button that restores less than its name promises has to say
301
+ // so aloud, or the child concludes it did not work.
302
+ const resetBtn = ctx.$('#movement-reset');
303
+ if (resetBtn)
304
+ resetBtn.addEventListener('click', () => {
305
+ ctx.players.forEach((p, i) => {
306
+ if (p.easy)
307
+ setEasy(i, false);
308
+ if (p.toggleMove)
309
+ setToggleMove(i, false);
310
+ if (p.toggleRun)
311
+ setToggleRun(i, false);
312
+ });
313
+ drawEasy();
314
+ reflectAltMove();
315
+ reflectToggleRun();
316
+ ctx.srSay(t('sr.motor.reset'));
317
+ });
318
+ }
319
+ wireButtons();
320
+ drawEasy();
321
+ reflectAltMove();
322
+ reflectToggleRun();
323
+ return {
324
+ renderMovPlayers,
325
+ reflectEasy: drawEasy,
326
+ reflectAltMove,
327
+ reflectToggleRun,
328
+ setEasy,
329
+ setSelPlayer: (i) => { selMovPlayer = i; },
330
+ getSelPlayer: () => selMovPlayer,
331
+ };
332
+ }
@@ -1,4 +1,8 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { type Crt } from '../render/crt.js';
3
+ import { type MediaQuery } from '../core/setting-defaults.js';
4
+ import type { Translate } from '../core/i18n.js';
5
+ import type { Store } from '../platform/storage.js';
2
6
  import type { MotionSceneKey as ChaveDeCenaLeaf, MotionCharProp as PropDoPersonagemLeaf, MotionCharDef as DefDoPersonagemLeaf, MotionPlayer as JogadorDeMovimentoLeaf, MotionSceneFlags as BandeirasDeCenaLeaf } from './motion-scene.js';
3
7
  export type MotionSceneKey = ChaveDeCenaLeaf;
4
8
  export type MotionCharProp = PropDoPersonagemLeaf;
@@ -6,96 +10,113 @@ export type MotionCharDef = DefDoPersonagemLeaf;
6
10
  export type MotionPlayer = JogadorDeMovimentoLeaf;
7
11
  export type MotionSceneFlags = BandeirasDeCenaLeaf;
8
12
  export interface SettingsMotionCtx {
9
- /** Quantos jogadores/telas. Estado de RODADA (ADR-0038): vem da instância que a raiz possui.
10
- * Era `numPlayers`, um `let` de `core/state` importado como binding vivo — e um `let` de módulo
11
- * é compartilhado por qualquer segundo jogo que a mesma página carregue (D13 do `demos`). */
13
+ /** Translates in the page's language — the root's translator (ADR-0232 D3). REQUIRED: text built from nowhere is a raw key. */
14
+ t: Translate;
15
+ /** How many players/screens. ROUND state (ADR-0038): it comes from the instance the root owns — a module `let` would
16
+ * be shared by any second game the same page loads. */
12
17
  getNumPlayers: () => number;
13
- /** Os jogadores. Estado de RODADA, pelo mesmo motivo. `readonly unknown[]` porque cada consumidor
14
- * estreita para a SUA fatia — o tipo real é do jogo, não da engine (ADR-0033). */
18
+ /** The players. ROUND state, for the same reason. `readonly unknown[]` because each consumer narrows to ITS slice —
19
+ * the real type is the game's, not the engine's (ADR-0033). */
15
20
  getPlayers: () => readonly unknown[];
16
- /** Seletor DOM (ui/dom.ts `$`). */
21
+ /** DOM selector (ui/dom.ts `$`). */
17
22
  $: <T extends Element = Element>(sel: string) => T | null;
18
- /** Anúncio "polite" para leitor de tela (core/a11y-sr.ts). */
23
+ /** "Polite" screen-reader announcement (core/a11y-sr.ts). */
19
24
  srSay: (text: string) => void;
20
- /** Persistência (platform/storage.ts) — só o necessário aqui: gravar as flags por jogador. */
21
- store: {
22
- setBool: (key: string, on: boolean) => void;
23
- };
24
- /** Empilha o overlay (z-index) + liga o rodapé de explicação — compartilhado por todos os painéis "Sensibilidade". */
25
+ /**
26
+ * The page's store (ADR-0232, issue #207) — only what is needed here: storing the per-player flags, and reading and
27
+ * writing the scene flags when the host does not share its own `rm`.
28
+ */
29
+ store: Pick<Store, 'setBool' | 'getJSON' | 'setJSON'>;
30
+ /**
31
+ * The browser's media query (`win.matchMedia`), asked for `prefers-reduced-motion` at every mark and every reset — the
32
+ * default follows the operating system NOW, not at boot. MANDATORY and injected (ADR-0232, ADR-0227): this module
33
+ * reaches no global, and an optional port would let a host forget it and turn the animation back on at the reset.
34
+ */
35
+ matchMedia: MediaQuery;
36
+ /**
37
+ * The root's CRT (`render/crt`'s `createCrt`, ADR-0232 D4): the live config the three CRT rows read and write, and its
38
+ * `apply`. REQUIRED: the panel used to reach the page's one CRT by import, and a second root would have toggled the
39
+ * first root's scanlines.
40
+ */
41
+ crt: Pick<Crt, 'cfg' | 'apply'>;
42
+ /** Stacks the overlay (z-index) + wires the explanation footer — shared by every settings panel. */
25
43
  frontOverlay: (el: HTMLElement | null) => void;
26
- /** Devolve o foco a quem abriu o diálogo (ui/settings-panel `restoreFocus`). Injetado, e não um `#opt-*`
27
- * fixo: o id que este módulo focava não existe no documento, então fechar deixava o foco no `<body>`. */
44
+ /** Returns focus to whoever opened the dialog (ui/settings-panel `restoreFocus`). Injected, not a fixed `#opt-*`: that
45
+ * id does not exist in the document, so closing would leave focus on `<body>`. */
28
46
  restoreFocus?: (id: string) => boolean;
29
- /** Reflete on/off num botão (classe is-on + aria-pressed) — helper genérico usado por vários botões-mestre. */
47
+ /** Reflects on/off on a button (is-on class + aria-pressed) — a generic helper used by several master buttons. */
30
48
  toggleBtn: (el: HTMLElement, on: boolean) => void;
31
- /** Movimento reduzido de CENA (parallax/decor/items/particles) — objeto VIVO, mutado in-place. */
49
+ /** SCENE reduced motion (parallax/decor/items/particles) — a LIVE object, mutated in place. */
32
50
  rm?: MotionSceneFlags;
33
- /** Persiste `rm` (localStorage 'inclusionist.reducedmotion.v1'). */
51
+ /** Persists `rm` (localStorage 'inclusionist.reducedmotion.v1'). */
34
52
  saveRM?: () => void;
35
- /** As 4 chaves de cena — a MESMA array que applyCalm() itera. */
53
+ /** The 4 scene keys. */
36
54
  rmKeys?: readonly MotionSceneKey[];
37
- /** Os 3 alvos de movimento reduzido do PERSONAGEM — a MESMA array que applyCalm() itera. */
55
+ /** The 3 CHARACTER reduced-motion targets. */
38
56
  rmChar?: readonly MotionCharDef[];
39
57
  /**
40
- * Move a prosa das linhas para o rodapé (`ui/settings-panel` → `fillExplain`). Chamado a CADA render.
58
+ * DOES THIS GAME HAVE A CHARACTER THAT WALKS, BREATHES OR PLAYS AROUND? (ADR-0153, `reducedCharacterMotion`.)
41
59
  *
42
- * ⚠️ NÃO É OPCIONAL POR ELEGÂNCIA: `fillExplain` roda uma vez quando o overlay é frontalizado e move o
43
- * `.opt-hint` de dentro de cada linha para o rodapé. Este painel RECONSTRÓI as linhas, e as linhas novas
44
- * voltam com a prosa lá dentro — então a explicação aparece duas vezes, no rodapé e sob o rótulo, a
45
- * partir do primeiro clique. O `CLAUDE.md` §4 regista exatamente isto, e a issue #109 já o consertou
46
- * uma vez noutros painéis.
60
+ * 🔴 Without it the character section would mount in EVERY game — three switches to stop the walk, the breath and the
61
+ * flourishes of a character a board game does not have. It is ADR-0145's subjectless button. `false` removes the
62
+ * section, and its rows stop counting for the master button and the reset.
47
63
  *
48
- * Opcional na assinatura porque um consumidor pode montar o painel sem a casca (um teste, o segundo
49
- * consumidor): sem casca não há rodapé para duplicar.
64
+ * ⚠️ OPTIONAL, defaulting to `true`: whoever mounts this panel outside `createGame` is unchanged.
65
+ */
66
+ hasCharacter?: () => boolean;
67
+ /**
68
+ * The GAME's word for its character (ADR-0153: what applies carries the game's word), the section's title. Optional:
69
+ * absent, the section keeps the engine's own title, as for a panel mounted outside `createGame`.
70
+ */
71
+ characterLabel?: () => string | null;
72
+ /**
73
+ * Moves the rows' prose to the footer (`ui/settings-panel` → `fillExplain`). Called on EVERY render.
74
+ *
75
+ * ⚠️ Relabelling a row puts its `.opt-hint` back inside it — so without this call the explanation appears twice, in
76
+ * the footer and under the label, from the first click. `CLAUDE.md` §4 records exactly this (issue #109).
77
+ *
78
+ * Optional in the signature because a consumer can mount the panel without the shell (a test): without the shell
79
+ * there is no footer to duplicate.
50
80
  */
51
81
  fillExplain?: (card: HTMLElement | null) => void;
52
82
  }
53
- /**
54
- * Alvo → CHAVE i18n do rótulo. CHAVES, e não texto, pelo motivo de sempre: uma tabela de `const` com texto
55
- * resolve UMA vez, no import, e fica congelada no idioma do boot.
56
- *
57
- * E é UMA tabela onde eram DUAS. A nota anterior dizia que `walk/breath/flavor` ficavam "redundantes com
58
- * rmChar[].lbl" e que não haviam sido podados "por fidelidade de porte" — havia uma terceira cópia, morta, no
59
- * main.js. Três tabelas dos mesmos rótulos, sem nada ligando as três: mudar um rótulo pedia três edições e
60
- * esquecer uma era silencioso. Agora `rmChar[].lbl` guarda a chave DESTA tabela, e a do main.js foi apagada.
61
- */
62
- export declare const RM_LABEL: Record<string, string>;
63
- export declare const RM_SOON: ReadonlySet<MotionSceneKey>;
64
- /** selAnimPlayer nunca aponta pra fora do nº de telas atual. */
65
- export declare function clampSelectedPlayer(selected: number, total: number): number;
66
- /** Uma linha de switch "Animado/Congelado" (usada tanto para o personagem quanto para a cena). */
67
- export declare function motionRowHtml(label: string, frozen: boolean, attr: string, soon: boolean): string;
68
- /** Linhas "Personagem" (por jogador selecionado). */
69
- export declare function buildCharRowsHtml(rmChar: readonly MotionCharDef[], player: MotionPlayer | undefined): string;
70
- /** Linhas "Cena" (globais, valem para todos os jogadores). */
71
- export declare function buildSceneRowsHtml(rmKeys: readonly MotionSceneKey[], rm: MotionSceneFlags, labels: Record<string, string>, soon: ReadonlySet<MotionSceneKey>): string;
72
- /** Toggle liga/desliga da estética CRT (scanlines/vinheta). */
73
- export declare function crtToggleRowHtml(label: string, key: string, on: boolean): string;
74
- /** Cantos CRT: 3 níveis (0=quadrado · 1=pequeno · 2=grande). */
75
- export declare function crtRoundRowHtml(label: string, round: number): string;
76
- /** true quando TUDO (cena + personagem selecionado) já está com movimento reduzido LIGADO, isto é,
77
- * congelado — nome fiel ao `rm[k]`/`player[prop]` que representam "reduzido", não "animado". Controla
78
- * se o botão-mestre oferece "Retomar" (true) ou "Parar" (false) — mesma variável `allOn` do game.js
79
- * original, aqui renomeada por clareza (o valor/comportamento não muda). */
80
- export declare function allMotionFrozen(rmKeys: readonly MotionSceneKey[], rm: MotionSceneFlags, rmChar: readonly MotionCharDef[], player: MotionPlayer | undefined): boolean;
81
- /** allFrozen=true (tudo já congelado) → oferece "Retomar"; caso contrário → oferece "Parar". */
82
- export declare function motionMasterLabel(allFrozen: boolean): string;
83
- /** `label` chega JÁ TRADUZIDO; o que era concatenação (' congelado.') virou moldura com `{alvo}` — é o que
84
- * permite a uma língua pôr o estado ANTES do alvo, coisa que uma concatenação não deixa. */
85
- export declare function sceneMotionAnnouncement(label: string, frozen: boolean): string;
86
- export declare function crtToggleAnnouncement(label: string, on: boolean): string;
87
- export declare function crtLevelLabel(level: number): string;
88
- export declare function crtRoundAnnouncement(label: string, level: number): string;
89
- /** `nowFrozen` = o NOVO valor de rm[k]/player[prop] aplicado pelo botão-mestre (true = acabou de congelar
90
- * tudo; false = acabou de descongelar/retomar tudo) — mesma variável `v` do game.js original. */
91
- export declare function stopResumeAllAnnouncement(nowFrozen: boolean): string;
92
- export declare function getSelectedPlayer(): number;
93
- /** Chamado de fora (ex.: o atalho "anim" do menu de pausa) antes de open(). */
94
- export declare function setSelectedPlayer(i: number): void;
95
- /** Espelha `animationOpen` do game.js — só LIDO por quem despacha Escape entre os diálogos abertos. */
83
+ /** What mounting needs to know, already translated — the kit does not decide language, it builds shape. */
84
+ export interface MotionInsideSpec {
85
+ /** The character section's title, or `null` when this game has no character (ADR-0153). */
86
+ readonly charTitle: string | null;
87
+ /** ⚠️ The character's tag is DIFFERENT, not by oversight: its rows hold per PLAYER, the other two sections' hold for
88
+ * everyone. A single tag would say the same thing about different things. */
89
+ readonly charTag: string;
90
+ readonly charRows: readonly {
91
+ readonly prop: string;
92
+ readonly label: string;
93
+ }[];
94
+ readonly sceneTitle: string;
95
+ readonly sceneRows: readonly {
96
+ readonly key: string;
97
+ readonly label: string;
98
+ }[];
99
+ readonly crtTitle: string;
100
+ /** The for-everyone tag, shared by the scene and CRT sections. */
101
+ readonly allTag: string;
102
+ readonly crtToggles: readonly {
103
+ readonly key: string;
104
+ readonly label: string;
105
+ }[];
106
+ /** The corners' name and positions, for the steps control (ADR-0151). */
107
+ readonly roundSpec: () => {
108
+ readonly label: string;
109
+ readonly values: readonly string[];
110
+ readonly current: number;
111
+ };
112
+ }
96
113
  export interface SettingsMotionApi {
97
114
  render: () => void;
98
115
  open: () => void;
99
116
  close: () => void;
117
+ /** The player whose character rows the panel edits. */
118
+ selectedPlayer: () => number;
119
+ /** Chooses that player — called from outside (e.g. the pause menu's "anim" entry) before `open()`. */
120
+ setSelectedPlayer: (i: number) => void;
100
121
  }
101
122
  export declare function initSettingsMotion(ctx: SettingsMotionCtx): SettingsMotionApi;