@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,146 +1,101 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  import type { PlayerView } from '../core/entity.js';
3
3
  import type { NavKeys } from '../input/edges.js';
4
- import { type Tema, type Correcao, type VisualState } from '../render/viz-axes.js';
4
+ import type { Translate, Translator } from '../core/i18n.js';
5
+ import { type PauseMenuButton, type PauseSub } from './pause-markup.js';
6
+ import { type PauseIcon } from '../core/pause-icon-catalogue.js';
7
+ import { type Theme, type Correction, type VisualState } from '../render/viz-axes.js';
5
8
  import type { MotionSceneFlags, MotionSceneKey, MotionCharDef } from './settings-motion.js';
6
- import type { AudioCatState } from './settings-audio.js';
9
+ import type { AudioCatState } from './audio-choices.js';
10
+ import { type MediaQuery } from '../core/setting-defaults.js';
11
+ import { type CameraControl } from '../core/camera-cycle.js';
7
12
  /**
8
- * A LEGENDA de um ícone da barra de acessibilidade — uma função, e não três cópias da mesma expressão.
13
+ * THE THREE POSITIONS OF ☝️ (ADR-0218): how the child's presses are read.
9
14
  *
10
- * Ela é escrita em TRÊS momentos que parecem diferentes e são o mesmo: o cursor direcional pousa no ícone
11
- * (`ui/menu-nav`), o dedo o aciona, e o mouse ou o foco passa por cima. Enquanto eram três linhas soltas, o
12
- * índice do ADR-0044 teria de ser acrescentado em três lugares — e a chance de um ficar para trás é a mesma
13
- * que este repositório já pagou dezesseis vezes com o `DomQuery`.
14
- *
15
- * O `aria-label` já conta o ESTADO ("Alto contraste, ativado"): é ele que o `reflectIconBtn` reescreve a cada
16
- * mudança, e é por isso que a legenda o lê de volta em vez de recompor o texto por conta própria.
15
+ * They are not three settings but three READINGS of the same press, which is why one icon holds them and why they are shown as
16
+ * one position. `standard` is the press as it arrives; `sticky` makes a tap last until the next one (ADR-0113); `scan` offers
17
+ * the game's positions one at a time and lets any press take the one showing.
17
18
  */
18
- export declare function legendaDoIcone(barra: ParentNode, el: HTMLElement): string;
19
- export interface PauseIcon {
20
- /** `data-pi` key — the dispatch key of iconAct/iconLabel/reflectIconBtn. */
21
- k: string;
22
- /** The emoji glyph rendered inside the button. */
23
- e: string;
24
- /** i18n KEY of the base name; also the `aria-label` when the icon carries no state (or is `soon`). */
25
- n: string;
26
- /** Under construction: the button announces itself and does nothing else. */
27
- soon?: boolean;
28
- }
29
- /** The accessibility shortcut bar at the top of every pause screen (and of the splash `#title-icons`).
30
- * Sound-bound icons (blind/TTS) require a private audio output; webcam/voice are still `soon`.
31
- * VERBATIM from game.js in order and behaviour; the names became i18n keys in the Fase-5 pass. */
32
- export declare const PAUSE_ICONS: readonly PauseIcon[];
33
- export declare function pauseIcon(k: string): PauseIcon | undefined;
34
- /** TEA cycle: 0 = normal · 1 = calmo (reduces) · 2 = silencioso (switches off). Never touches TTS/blind mode. */
35
- export declare const CALM_NAMES: readonly string[];
19
+ export type InputMode = 'standard' | 'sticky' | 'scan';
36
20
  /**
37
- * O nível TEA guardado, saneado. Fora de 0..2 devolve o padrão — dado do navegador é dado de fora, e um
38
- * nível inventado escolheria `CALM_NAMES[3]`, que é `undefined`, e o anúncio ao leitor de tela sairia vazio.
21
+ * Which of the three is showing. The SCAN WINS over the latch on purpose: with one button there is nothing to hold, so a stored
22
+ * latch would otherwise make the icon claim a position the child is not in.
39
23
  */
40
- export declare function saneiaNivelTea(bruto: number): number;
41
- /** The audio categories `applyCalm` governs. TTS/sonar/guarda/guia stay untouched — a calm player still needs them. */
42
- export declare const CALM_AUDIO_CATS: readonly string[];
43
- /** Colour-vision-deficiency cycle, in `player.viz` values. */
44
- export declare const CVD_SEQ: readonly string[];
45
- /** i18n keys of the CVD announcement names, indexed the same as CVD_SEQ.
46
- *
47
- * ⚠️ POSITION 0 IS `cvd.tricro` AND NOT `cvd.off`, AND THE TWO KEYS ARE NOT INTERCHANGEABLE.
48
- * This list names the four CHOICES of the cycle, so position 0 is a way of seeing — trichromatic
49
- * vision, the one that needs no correction — and it is said as one. `cvd.off` below is a FALLBACK
50
- * for `s.viz` values that are not corrections at all, and 13 of the 16 viz modes are exactly that:
51
- * the three simulations, the three contrast levels, the five low-vision modes and blind mode.
52
- * Announcing "trichromatic vision" there would have the software assert what the child sees, while
53
- * she is simulating not seeing it. The choice is named; the fallback is switched off. */
54
- export declare const CVD_NAMES: readonly string[];
55
- /** `player.viz` → i18n key of the label used by iconLabel (anything else falls back to the 'off' key). */
56
- export declare const CVD_LABELS: Readonly<Record<string, string>>;
57
- /** The slice of a player object the pause icons touch. `players` (core/state) is typed `unknown[]`. */
24
+ export declare function inputModeOf(s: {
25
+ readonly toggleMove?: boolean;
26
+ readonly switchScan?: boolean;
27
+ }): InputMode;
28
+ export declare function nextInputMode(m: InputMode, holdsKeys: boolean): InputMode;
29
+ import type { Store } from '../platform/storage.js';
58
30
  /**
59
- * A fatia que os ícones de pausa tocam — derivada de core/entity, e SEM assinatura de índice.
60
- *
61
- * Havia uma (`[prop: string]: unknown`), posta ali porque `applyCalm` escreve por nome calculado
62
- * (`p[c.prop] = …`). Era andaime: `c.prop` tem tipo `MotionCharProp`, que é a união literal
63
- * `'rmWalk' | 'rmBreath' | 'rmFlavor'`, e o TypeScript verifica acesso por chave literal sem precisar de
64
- * assinatura nenhuma — bastava que os três campos tivessem nome, que é o que a derivação deu.
31
+ * Hover and focus on a bar's icons write its NAME in the bar's `.pause-icons-cap` and ask for its EXPLANATION.
65
32
  *
66
- * E ela custava caro: uma assinatura de índice aceita QUALQUER propriedade, com valor `unknown`. Enquanto
67
- * existiu, um erro de digitação em qualquer campo deste objeto compilava em silêncio. Quem a denunciou foi
68
- * tipar `core/state.players` como `Player[]`: o compilador recusou converter um `Player` — que não tem
69
- * assinatura de índice — para ela, e essa recusa é a informação.
33
+ * Shared by the per-screen quick bars and the bar the engine mounts in `#title-icons`: two copies of this wiring is
34
+ * how one bar showed the name and the other did not — the Dev found the engine's bar silent on hover and on the
35
+ * cursor. Leaving an icon falls back to the CURSOR of the bar's mode when there is one (`.pi-sel`): it is the only
36
+ * thing saying where that cursor is.
70
37
  */
71
- export type PausePlayer = PlayerView<'visual' | 'toggleMove' | 'walkDir' | 'audioSink' | 'rmWalk' | 'rmBreath' | 'rmFlavor'>;
72
- /** One `.pm-btn` descriptor — the shape of game.js's PM_BTNS (owned by ui/activities-menu). */
73
- export interface PauseMenuButton {
74
- act: string;
75
- /** Só é lido quando o botão tem rótulo dinâmico; ver a nota em `PauseBtnDef` (ui/activities-menu). */
76
- lbl?: string;
77
- /** Dynamic label (the ABC cycle) — rendered from `lbl`, not from i18n, and NOT given `data-i18n`. */
78
- letra?: boolean;
79
- /** Dynamic label (the literacy level) — rendered from quizLevel + qlName. Currently dormant: no PM_BTNS
80
- * entry sets it, but the branch is live code and is ported verbatim. */
81
- nivel?: boolean;
38
+ export declare function wireBarCaption(bar: HTMLElement, explain: (k: string | null) => void): void;
39
+ /**
40
+ * THE SETTINGS THE BAR READS AND WRITES — the page's settings store, built by the root (ADR-0232 D2c, issue #207). The
41
+ * names are `core/state`'s own, so the root passes the store itself; the reads are LIVE (a getter or a live binding),
42
+ * because another surface — the motion panel, a gamepad, a second screen — changes them between two presses.
43
+ */
44
+ export interface PauseIconsSettings {
45
+ /** The «N de M» at the end of an announcement (ADR-0044 item 3). */
46
+ readonly menuIndexOn: boolean;
47
+ readonly gameSpeed: number;
48
+ setGameSpeedValue(speed: number): void;
49
+ readonly cameraControl: CameraControl;
50
+ setCameraControlValue(mode: CameraControl): void;
51
+ readonly voiceControl: boolean;
52
+ setVoiceControlValue(on: boolean): void;
53
+ readonly switchScan: boolean;
54
+ setSwitchScanValue(on: boolean): void;
55
+ /** The blind-mode writer used when the host injects no `setBlindMode`: write, persist, notify. */
56
+ setBlindModeValue(on: boolean): void;
82
57
  }
58
+ /** What the bar reads and writes through: the calm level, the movement latch and the scene flags' default. */
59
+ export type PauseIconsStore = Pick<Store, 'getNum' | 'set' | 'setBool' | 'getJSON' | 'setJSON'>;
60
+ /**
61
+ * The slice of a player the pause icons touch — derived from core/entity, and WITHOUT an index signature: one would
62
+ * accept ANY property with an `unknown` value, so a typo in any field would compile silently. `applyCalm` writes by a
63
+ * computed name (`p[c.prop] = …`), and `c.prop` is the literal union `'rmWalk' | 'rmBreath' | 'rmFlavor'`, which TypeScript
64
+ * checks without any signature.
65
+ */
66
+ export type PausePlayer = PlayerView<'visual' | 'toggleMove' | 'walkDir' | 'audioSink' | 'rmWalk' | 'rmBreath' | 'rmFlavor'>;
83
67
  /** Everything the label/visual of ONE icon depends on, gathered in one value. */
84
68
  export interface IconStateSnapshot {
85
- modoCego: boolean;
69
+ blindMode: boolean;
86
70
  ttsOn: boolean;
87
71
  librasOn: boolean;
88
72
  calmMode: number;
89
73
  toggleMove: boolean;
90
74
  /**
91
- * O estado visual em DOIS EIXOS (#104).
92
- *
93
- * ⚠️ ERA `viz: string`, E O COMENTÁRIO DIZIA: «shared by the contrast and CVD icons (they overwrite each
94
- * other; **that is by design**)». Não era desenho — era o campo único a impor-se, e a frase é o defeito
95
- * escrito como se fosse decisão. Os dois ícones sempre ciclaram DENTRO do seu eixo (`nextContrast` e
96
- * `nextCvd` existem desde sempre, separados); só não tinham onde guardar o resultado sem apagar o vizinho.
75
+ * The visual state on TWO AXES (#104): the contrast icon cycles the theme and the colour icon cycles the correction,
76
+ * each within its own axis, and neither erases the other.
97
77
  */
98
78
  visual: VisualState;
79
+ /** Playing by SPEAKING (ADR-0189): the 👄 of the bar, on or off. */
80
+ voice?: boolean;
81
+ /** Playing with ONE button (ADR-0218): the third position of ☝️, which wins over the latch when it is on. */
82
+ switchScan?: boolean;
83
+ /** The game speed (ADR-0180), a step of `core/game-speed`; absent reads as 100%. */
84
+ speed?: number;
85
+ /** Playing through the webcam (ADR-0215); absent reads as off. */
86
+ camera?: CameraControl;
87
+ /** The current locale (`core/i18n`), for the language button. */
88
+ locale?: string;
99
89
  /** False disables the blind/TTS icons: those need an audio output nobody else is listening to. */
100
90
  privateOutput: boolean;
101
- /**
102
- * O aparelho em uso EXIGE a alternância? (ADR-0113 cláusula 3.)
103
- *
104
- * ⚠️ Em olhos, rosto, gestos e fala ela é o que faz a entrada funcionar, logo não há escolha a oferecer.
105
- * O ícone fica desabilitado COM MOTIVO, como o painel — e não pode divergir dele: as duas superfícies
106
- * escrevem o mesmo valor, e uma que aceitasse o clique enquanto a outra recusa deixaria a criança com
107
- * dois botões que discordam sobre o mesmo ajuste.
108
- *
109
- * 🔴 OPCIONAL PORQUE O GATE DA FORMA ME APANHOU: eu escrevi-o obrigatório, e o
110
- * `tests/superficie-publica` reprovou com «ENTROU como obrigatório» — que é uma MUDANÇA QUEBRANTE do
111
- * pacote, porque quem constrói este snapshot passa a ter de o preencher. Foi para isto que o gate da
112
- * FORMA (`2f2582f`) foi escrito, e é a primeira vez que ele apanha um campo A ENTRAR e não a sair.
113
- * Ausente significa «ninguém me disse», que degrada para «não exijo» — o comportamento de hoje.
114
- */
115
- alternanciaExigida?: boolean;
91
+ /** No voice speaks the current language (ADR-0185): the narration icon is locked. Absent reads as a voice. */
92
+ noVoice?: boolean;
116
93
  }
117
- /** A player has private output when nobody else is on the same sink. Single screen ⇒ always private.
118
- * Pure form of game.js's hasPrivateOutput (see the report: it had no other caller left). */
94
+ /** A player has private output when nobody else is on the same sink. Single screen ⇒ always private. */
119
95
  export declare function hasPrivateOutputIn(list: readonly PausePlayer[], count: number, i: number): boolean;
120
- /** TEA cycle step. */
121
- export declare function nextCalmMode(cur: number): number;
122
- /** Next high-contrast level. An unlisted `viz` (e.g. a CVD filter) is treated as index 0 ⇒ jumps to 'hc-direto'. */
123
- export declare function nextContrast(cur: string | undefined): string;
124
- /** Next CVD filter. NOTE the asymmetry with nextContrast: an unlisted `viz` maps to index 1 ('fix-protan'),
125
- * not 0 — verbatim from game.js (`idx = idx<0 ? 1 : (idx+1)%seq.length`). */
126
- export declare function nextCvd(cur: string | undefined): {
127
- idx: number;
128
- mode: string;
129
- };
130
- /** What `applyCalm` does to ONE audio category, given the TEA level. Extracted so the (destructive) volume
131
- * clamp at level 1 is visible and testable — see the report. */
132
- export declare function calmAudioPlan(calmMode: number, vol: number): {
133
- on: boolean;
134
- vol: number;
135
- };
136
- /** What `applyCalm` does to the scene/character reduced-motion flags. */
137
- export declare function calmMotionPlan(calmMode: number): {
138
- sceneReduced: boolean;
139
- charFrozen: boolean;
140
- };
141
96
  /** The `aria-label` of one icon — it MUST reflect the current state, on/off or level. This is the whole
142
97
  * point of the function: a toggle that looks pressed but does not say so is invisible to a screen reader. */
143
- export declare function computeIconLabel(k: string, s: IconStateSnapshot): string;
98
+ export declare function computeIconLabel(t: Translate, k: string, s: IconStateSnapshot): string;
144
99
  /** The visual state of one icon button. `active` is what becomes `aria-pressed`. */
145
100
  export interface IconVisual {
146
101
  /** `.pi-on` — the yellow "this is on" state. */
@@ -154,316 +109,275 @@ export interface IconVisual {
154
109
  /** aria-pressed: on OR calm OR a CVD tint. */
155
110
  active: boolean;
156
111
  }
157
- /** Pure form of reflectIconBtn's branching. A `soon` icon lands on all-false — it never claims to be on. */
112
+ /** Pure form of reflectIconBtn's branching. */
158
113
  export declare function computeIconVisual(k: string, s: IconStateSnapshot): IconVisual;
159
114
  /** The CSS classes reflectIconBtn clears before applying a fresh visual — in the original order. */
160
115
  export declare const ICON_STATE_CLASSES: readonly string[];
161
- /** One `.pi-btn`. `soon` icons get `.pi-soon` and the "under construction" suffix baked into the aria-label.
162
- * The label is the RESTING one: reflectIconBtn overwrites it with the stateful label as soon as the bar is
163
- * reflected. `ic.n` is an i18n key, so it must be resolved here too — the markup is rendered once at build
164
- * time and would otherwise ship the raw key to a screen reader. */
165
- export declare function iconBtnMarkup(ic: PauseIcon): string;
166
116
  /**
167
- * OS ÍCONES QUE ESTE JOGO CONSEGUE MESMO ACCIONAR (ADR-0106 §5).
168
- *
169
- * ⚠️ NENHUMA ETAPA PODE ENTREGAR BOTÃO MORTO, e o registo diz porquê com todas as letras: «uma barra que
170
- * oferece a uma criança um caminho e depois o recusa é pior do que uma barra que ela vê que não está lá,
171
- * porque a primeira ensina-lhe que o caminho não é para ela».
172
- *
173
- * ⚠️ E O CONTRASTE E A COR SÃO O CASO REAL, medido em 2026-09-08 e diferente dos outros seis campos
174
- * «acidentais»: eles não são estado que um cartucho calhou de guardar — precisam de um `render/viz-setters`,
175
- * cujo contexto tem **34 campos** do grafo de render de UM jogo (`parallaxLayers`, `decoSprites`,
176
- * `getPowerups`, `rebuildCoins`, `worldSprite`…). O `createGame` não monta isso, e um quiz não tem nada
177
- * disso para montar. Então aqui a engine não pode oferecer um padrão — o que ela pode é **não fingir**.
178
- *
179
- * ⚠️ Isto NÃO é o mesmo que `soon`. `soon` é «ainda não construímos»; isto é «este jogo não tem por onde», e
180
- * um botão que anuncia «em breve» diria a coisa errada.
117
+ * THE ICONS THIS GAME CAN ACTUALLY ACTIVATE (ADR-0106 §5): no stage may ship a dead button — «a bar that offers a child a
118
+ * way and then refuses it is worse than a bar she sees is not there, because the first teaches her the way is not for
119
+ * her». An icon with nothing to activate it is not mounted, rather than mounted to announce «soon».
181
120
  */
182
- export interface AccionaveisDoJogo {
183
- /** Há quem escreva o TEMA (o alto contraste)? Sem ele, o ícone `contrast` não é montado. */
184
- readonly tema: boolean;
185
- /** Há quem escreva a CORREÇÃO de cor? Sem ela, o ícone `cvd` não é montado. */
186
- readonly correcao: boolean;
121
+ export interface ActionableIcons {
122
+ /** Is there anyone to write the THEME (high contrast)? Without it, the `contrast` icon is not mounted. */
123
+ readonly theme: boolean;
124
+ /** Is there anyone to write the colour CORRECTION? Without it, the `cvd` icon is not mounted. */
125
+ readonly correction: boolean;
187
126
  /**
188
- * ESTE JOGO SEGURA ALGUMA TECLA? — `GameDeclaration.seguraTeclas`, o campo do ADR-0115.
127
+ * DOES THIS GAME HOLD ANY KEY? — `GameDeclaration.holdsKeys`, the field of ADR-0115.
189
128
  *
190
- * 🔴 Sem ele o ícone `altmove` não é montado, e a AUSÊNCIA é a decisão. A alternância existe para quem não
191
- * consegue manter uma tecla premida; num jogo onde nada se segura ela não tem o que travar, e um controle
192
- * que não faz nada ensina a uma criança que o ajuste de que ela depende está partido.
129
+ * The latch exists for whoever cannot keep a key pressed; in a game where nothing is held it has nothing to hold, and a
130
+ * control that does nothing teaches a child that the setting she depends on is broken. On eyes, face, gestures and
131
+ * speech it is also the latch's default (ADR-0249) — read by the root at every command, not here.
193
132
  *
194
- * ⚠️ E ISTO É UMA AUSÊNCIA DIFERENTE DA DO ADR-0113 cláusula 3, que também vive neste ficheiro: lá o
195
- * controle fica DESABILITADO com o motivo, porque o aparelho EXIGE a alternância e ela não se pode
196
- * desligar. Aqui não há nada a travar, e um controle que explica por que não faz nada continua a ser um
197
- * controle que não faz nada.
133
+ * A FUNCTION, not a value (as in ADR-0084): an answer read once goes stale silently, and with one `createGame` serving
134
+ * several cartridges (ADR-0142) the icon would describe the game that booted first.
135
+ */
136
+ readonly holdsKeys: () => boolean;
137
+ /**
138
+ * HOW MANY POSITIONS THIS GAME DECLARED (`CreateGameOptions.preset`, ADR-0162) — what a scan would have to offer (ADR-0218).
139
+ * A function like its neighbour, so a cartridge mounted later answers for itself (ADR-0142); absent reads as none.
140
+ */
141
+ readonly declaredPositions?: () => number;
142
+ /**
143
+ * Does this game's time run by itself? (`tick: 'clock'`, ADR-0180.) Without it the hourglass is not mounted. A function,
144
+ * like `holdsKeys`, so a cartridge mounted later answers for itself (ADR-0142).
145
+ */
146
+ readonly clock?: () => boolean;
147
+ /**
148
+ * Does anyone know how to walk the typography cycle? (ADR-0149 §1.)
198
149
  *
199
- * ⚠️ É FUNÇÃO E NÃO VALOR, e a razão é a mesma do ADR-0084: uma resposta lida uma vez envelhece em
200
- * silêncio. Aqui envelhecia no pior sítio — o `reflectPauseIcons` existe justamente porque «a tabela de
201
- * acções deste jogo pode ter mudado desde a montagem» (ADR-0106 §5), e refrescava a partir de um booleano
202
- * congelado no arranque. Com um `createGame` a servir vários cartuchos (ADR-0142), o ícone descrevia o
203
- * jogo que arrancou primeiro. O contrato nunca esteve errado: `GameDeclaration.seguraTeclas` já é função.
150
+ * OPTIONAL, absent meaning `false` — unlike `holdsKeys`, which is required because both of its values can be wrong.
151
+ * Here `false` hides an icon that would do nothing, which is exactly what ADR-0106 §5 wants.
204
152
  */
205
- readonly seguraTeclas: () => boolean;
153
+ readonly typography?: boolean;
154
+ /** Can this device play through the webcam — is there a camera to ask for? Without it the 📷 is not mounted (ADR-0215). */
155
+ readonly camera?: boolean;
156
+ /** Is there a microphone to ask for? Without one the 👄 is not mounted. */
157
+ readonly microphone?: boolean;
158
+ /** Is there a card of menus to open? Without it the ☰ is not mounted. */
159
+ readonly menus?: boolean;
206
160
  }
207
161
  /**
208
- * @deprecated O nome dizia «escritores VISUAIS» e a pergunta deixou de ser só visual quando o `seguraTeclas`
209
- * entrou (ADR-0115). Use `AccionaveisDoJogo`. O alias fica para o consumidor não pagar duas quebras no mesmo
210
- * major — uma pelo campo novo e outra pelo nome.
211
- */
212
- export type EscritoresVisuais = AccionaveisDoJogo;
213
- export declare function iconesQueAccionam(escritores: AccionaveisDoJogo): readonly PauseIcon[];
214
- /**
215
- * OS TRÊS ITENS QUE A ENGINE ACCIONA SOZINHA, e que por isso nunca dependem do `getPauseActs` de um jogo.
216
- *
217
- * 📏 Lidos do despacho, e não decididos aqui: `options`/`pmback` trocam qual lista está no cartão e
218
- * `acessibilidade` leva o cursor à barra rápida — os três são tratados neste módulo e voltam antes de a
219
- * tabela do jogo ser consultada.
220
- */
221
- export declare const ITENS_DA_ENGINE: ReadonlySet<string>;
222
- /**
223
- * OS ITENS DO MENU QUE ESTE JOGO CONSEGUE MESMO ACCIONAR (ADR-0106 §5).
224
- *
225
- * ⚠️ HOJE UM ITEM SEM ACÇÃO É UM BOTÃO MORTO, E EM SILÊNCIO. O despacho faz `const fn = acts[act]; if (fn)
226
- * fn();` — quem carrega num item que o jogo não implementou não recebe erro, não recebe anúncio, não recebe
227
- * nada. Para quem vê, parece que o clique falhou; para quem navega por leitor de tela, o menu leu-lhe um
228
- * item que não existe. É exactamente o que o §5 chama de pior do que a ausência: «uma barra que oferece um
229
- * caminho e depois o recusa ensina-lhe que o caminho não é para ela».
162
+ * @deprecated The name said «VISUAL writers», and the question stopped being only visual when `holdsKeys` joined it
163
+ * (ADR-0115). Use `ActionableIcons`.
230
164
  */
231
- export declare function itensQueAccionam(botoes: readonly PauseMenuButton[], acts: Record<string, (() => void) | undefined>): readonly PauseMenuButton[];
165
+ export type VisualWriters = ActionableIcons;
166
+ export declare function iconsThatAct(writers: ActionableIcons): readonly PauseIcon[];
232
167
  /**
233
- * A LISTA RAIZ, com uma regra a mais: `options` é uma PORTA, e uma porta para uma sala vazia também é um
234
- * botão morto.
235
- *
236
- * ⚠️ Esta é a parte que um filtro item-a-item não apanha. Se todos os painéis de ajuste forem filtrados —
237
- * um jogo que não monta nenhum —, o item `options` sobrevive (a engine acciona-o) e abre uma lista sem nada.
238
- * A criança atravessa uma porta e fica presa num submenu vazio, cuja única saída é o `pmback` que também
239
- * sumiu com ele.
168
+ * THE ROOT LIST, with one more rule: `options` is a DOOR, and a door to an empty room acts no more than a dead button.
169
+ * An item-by-item filter misses this: the engine activates `options` itself, so it would pass and open a list with
170
+ * nothing in it.
240
171
  */
241
- export declare function raizQueAcciona(raiz: readonly PauseMenuButton[], opcoes: readonly PauseMenuButton[], acts: Record<string, (() => void) | undefined>): readonly PauseMenuButton[];
242
- /** The whole icon bar. Used by the pause screen AND by the splash `#title-icons` (which built the same string
243
- * by hand in game.js — that duplication dies with this export).
244
- * O parâmetro é ADITIVO e o padrão é a lista inteira: quem já chamava sem argumentos não muda de resultado. */
245
- export declare function iconsMarkup(icones?: readonly PauseIcon[]): string;
246
- /** One `.pm-btn`. Dynamic labels (`letra`/`nivel`) are rendered eagerly and carry NO `data-i18n`, so
247
- * i18n.applyDom() cannot overwrite them. */
172
+ export declare function rootThatActs(rootEl: readonly PauseMenuButton[], options: readonly PauseMenuButton[], acts: Record<string, (() => void) | undefined>, fromGame?: readonly PauseMenuButton[]): readonly PauseMenuButton[];
248
173
  /**
249
- * ⚠️ O RÓTULO DINÂMICO ENTRA PRONTO (item 19), e a mudança conserta DUAS coisas de uma vez.
250
- *
251
- * A linha era `'📚 Nível ' + level + ' · ' + qlName[level]` — e ela tinha dois defeitos que só se enxergam
252
- * juntos:
174
+ * The navigable items of a pause card — those of the VISIBLE list, and only those.
253
175
  *
254
- * 1. FRONTEIRA. `level` vinha de `core/state.quizLevel` e `qlName` de uma tabela do jogo. Um menu de pausa
255
- * da ENGINE montava o rótulo de uma atividade de alfabetização — conteúdo pedagógico, não mecânica.
256
- * 2. IDIOMA. "Nível" é pt-BR CRU dentro de um módulo de engine. O gate do item 14 vigia o `main.js` e não
257
- * alcança `ui/`, então esta linha atravessou a i18n inteira sem ser vista. Num build em inglês, o menu
258
- * de pausa de uma criança dizia "📚 Nível 2 · …".
259
- *
260
- * Agora o jogo entrega a frase montada (`dynLabel`), e a engine só a coloca no botão. O jogo é quem sabe o
261
- * que é um nível, quem sabe o nome dele e quem sabe em que idioma dizê-lo.
176
+ * One constant because THREE modules ask (navigation in `ui/menu-nav`, the first selection in `ui/shell` and the list
177
+ * switch here): if one of them forgot `:not([hidden])`, the ring would step into the invisible list and the child would
178
+ * hear items of a menu that is not on screen. `:not([hidden])` on the ITEM too: a hidden item must not be reached nor
179
+ * counted in «N de M» (a locked one is not hidden — it is reached, and says why).
262
180
  */
263
- export declare function pmBtnMarkup(b: PauseMenuButton, dynLabel: (b: PauseMenuButton) => string | null, tr: (key: string) => string): string;
181
+ export declare const PM_VISIBLE_ITEMS = ".pause-menu:not([hidden]) .pm-btn:not([hidden])";
264
182
  /**
265
- * Qual das duas listas o cartão de pausa está mostrando.
266
- *
267
- * DUAS listas no markup, UMA visível — e a escondida carrega `hidden`, que a tira da árvore de acessibilidade
268
- * inteira. É o que faz "um menu por tela" (ADR-0044 §5) valer para quem escuta e não só para quem vê, e é o
269
- * que permite o anel dar a volta DENTRO da lista visível sem nunca atravessar para a outra.
183
+ * The other direction of the same table: the item of the root that opens each list. It is where «back» puts the cursor
184
+ * (ADR-0130 rule 1), and the name a list is announced by (`ui/where-the-child-is`). The root has no door.
270
185
  */
271
- export type PauseSub = 'raiz' | 'opcoes';
186
+ export declare const LIST_DOOR: Readonly<Record<PauseSub, string | null>>;
272
187
  /**
273
- * Os itens navegáveis de um cartão de pausa — os da lista VISÍVEL, e só eles.
188
+ * Switches the visible list of ONE pause card, and puts the cursor on the FIRST item of the list that came in.
274
189
  *
275
- * Uma constante porque TRÊS módulos a consultam (a navegação em `ui/menu-nav`, a seleção inicial em
276
- * `ui/shell` e a troca de submenu aqui). Enquanto fosse `.pm-btn` escrito três vezes, bastaria um deles
277
- * esquecer o `:not([hidden])` para o anel atravessar para a lista invisível — e a criança ouviria itens de um
278
- * menu que não está na tela.
190
+ * Free-standing (not a method of `init`) on purpose: `ui/menu-nav` needs it for «no» to go back to the root, and it has no
191
+ * access to the button tables. Every list already exists in the markup, so the switch is DOM only.
279
192
  */
280
- export declare const PM_ITENS_VISIVEIS = ".pause-menu:not([hidden]) .pm-btn";
281
- /** O innerHTML de UMA `.pause-menu`: a lista, e só ela. */
282
- export declare function pauseMenuHtml(bs: readonly PauseMenuButton[], sub: PauseSub, dynLabel: (b: PauseMenuButton) => string | null, tr: (key: string) => string): string;
193
+ export declare function showPauseOptions(sp: HTMLElement, sub: PauseSub): HTMLElement | null;
283
194
  /**
284
- * Troca a lista visível de UM cartão de pausa, e põe o cursor no PRIMEIRO item da lista que entrou.
285
- *
286
- * Livre (e não um método do `init`) de propósito: `ui/menu-nav` precisa dela para o "não" voltar da lista de
287
- * opções à raiz, e não tem acesso às tabelas de botões. Como as duas listas já existem no markup, a troca é
288
- * só DOM — nada a re-renderizar, nada a injetar.
195
+ * PUTS THE CARD'S CURSOR ON `el` — the one place every move of it goes through, whatever moved it: the arrows and the pad
196
+ * (`ui/menu-nav`), a finger, a held press, a door between lists, «back». The card selects by class, not by browser focus,
197
+ * so nothing scrolls it by itself: an item past the visible part of a long list would be marked where the child cannot see
198
+ * it. So the list is scrolled HERE, inside the card, until the item is wholly in view (issue #134, `keepInView`).
289
199
  */
290
- export declare function mostrarSubmenuDaPausa(sp: HTMLElement, sub: PauseSub): HTMLElement | null;
200
+ export declare function markPauseItem(sp: HTMLElement, el: HTMLElement | null | undefined): void;
291
201
  /**
292
- * A BARRA RÁPIDA DE ACESSIBILIDADE — dez alternadores e a legenda que os explica (ADR-0044, item 7).
293
- *
294
- * Saiu do cartão de pausa e passou a viver no HUD. O motivo é de uso, não de arrumação: é DURANTE a partida
295
- * que uma criança precisa mudar um ajuste que está a atrapalhando, e não depois de pausar. E o motivo
296
- * secundário é estrutural — sem ela, o cartão deixa de ter duas zonas e vira uma LISTA, o que é o que
297
- * finalmente autoriza o anel (a XAG 106 permite laço para menu linear e o proíbe para grade).
202
+ * «BACK» FROM A LIST OF THE CARD: the root comes in with the cursor on THE ITEM THAT OPENED the list being left, not on
203
+ * the root's first item (ADR-0130 rule 1). A child who went into «Opções», looked, and came back is where she was; landing
204
+ * on «Voltar» would send her walking the root again to find her place, and a child who cannot see the mark would not even
205
+ * know she had been moved.
298
206
  *
299
- * A LEGENDA VIAJA JUNTO. Ela é a dica que substitui, para quem não vê, o `title` que só o mouse revela;
300
- * deixá-la no cartão tornaria a barra do HUD muda.
207
+ * Opening the card is another question and keeps `showPauseOptions(sp, 'raiz')`: a card opens on item 1 (ADR-0158).
208
+ * A door that is gone or hidden leaves the cursor on the first item, which is all there is to return to.
301
209
  */
302
- export declare function quickBarMarkup(icones?: readonly PauseIcon[]): string;
210
+ export declare function backToRoot(sp: HTMLElement): HTMLElement | null;
303
211
  /**
304
- * O QUE UMA INTENÇÃO SIGNIFICA DENTRO DO MODO `accessibility` (ADR-0044, item 7).
212
+ * WHAT AN INTENT MEANS INSIDE THE `accessibility` MODE (ADR-0044 item 7).
305
213
  *
306
- * O registro listou este modo entre as consequências NEGATIVAS da decisão, e disse por quê: "um modo em que
307
- * se entra e não se sabe sair é a própria armadilha de que este registro trata — então a saída dele (START ou
308
- * VOLTAR) é parte da decisão, e não um detalhe de implementação".
214
+ * The record lists this mode among the decision's NEGATIVE consequences, and says why: a mode one enters and does not
215
+ * know how to leave is the very trap the record is about — so its way out (START or BACK) is part of the decision.
309
216
  *
310
- * Daí a forma desta função: SAIR vem primeiro, e vem por DUAS portas. Não é redundância. VOLTAR é a saída de
311
- * tudo no jogo, e é o que quem já o conhece tenta primeiro; START é o botão que ABRE a pausa, e a pausa é de
312
- * onde se entrou aqui — quem se perde tenta voltar por onde veio. Ter só uma das duas seria apostar que a
313
- * criança adivinhe qual delas foi escolhida.
217
+ * Hence the shape: LEAVING comes first, through TWO doors. BACK is the way out of everything in the game, the one a child
218
+ * who knows it tries first; START is the button that OPENS the pause, and the pause is where this mode was entered from —
219
+ * whoever gets lost tries to go back the way they came. One door only would be betting that the child guesses which.
314
220
  *
315
- * E a precedência é decisão também: um controle registra mais de uma borda no mesmo quadro (dedos apertam
316
- * junto), e nesse quadro `sair` não pode ficar atrás de `ativar`.
221
+ * The precedence is a decision too: a controller can report more than one edge in the same frame (fingers press
222
+ * together), and in that frame leaving must not come after activating.
317
223
  */
318
- export type AcaoNaBarra = 'sair' | 'ativar' | 'andar' | 'nada';
319
- export declare function acaoNaBarra(k: NavKeys, temStart: boolean): AcaoNaBarra;
320
- export interface ScreenPauseMarkupOpts {
321
- /** Screen/player index (0-based); the dialog label and the "· Jogador N" suffix are 1-based. */
322
- player: number;
323
- /** Live player count — the suffix only appears in multiplayer. */
324
- numPlayers: number;
325
- /** A lista RAIZ: os sete itens do ADR-0044, `resume` primeiro e `quit` último. */
326
- pmButtons: readonly PauseMenuButton[];
327
- /** O submenu de opções: os sete painéis de ajuste, com o "Voltar" na frente. */
328
- optionsButtons: readonly PauseMenuButton[];
329
- /** Rótulo pronto de um botão DINÂMICO, ou `null` se aquele botão não tem um. Quem monta a frase é o jogo. */
330
- dynLabel: (b: PauseMenuButton) => string | null;
331
- t: (key: string) => string;
332
- }
333
- /** The full innerHTML of a `.screen-pause`. Pure — every input is a parameter. */
334
- export declare function screenPauseMarkup(o: ScreenPauseMarkupOpts): string;
224
+ export type BarAction = 'sair' | 'ativar' | 'andar' | 'nada';
225
+ export declare function barAction(k: NavKeys, hasStart: boolean): BarAction;
335
226
  export interface PauseIconsCtx {
336
227
  /**
337
- * O DOCUMENTO onde a pausa e a barra são CONSTRUÍDAS. Ausente, vale o global.
338
- *
339
- * ⚠️ ISTO É O ACHADO 15 OUTRA VEZ, e o `boot/create-game` já o descreve no próprio cabeçalho: «`initI18n()`
340
- * chamava `applyDom(document)`, o GLOBAL, por baixo de quem a chamasse. Num navegador dá no mesmo e por
341
- * isso sobreviveu; num teste de lógica pura é a diferença entre bootar e não bootar, e num futuro com dois
342
- * documentos (uma engine em iframe, um editor ao lado do jogo) seria a diferença entre traduzir o documento
343
- * certo e o outro.»
344
- *
345
- * 📏 Medido em 2026-09-08: as duas metades que constroem DOM (`buildScreenPause`, `buildQuickBar`) faziam
346
- * `document.createElement` no global. Enquanto a raiz de composição de cada jogo era um `main.ts` a correr
347
- * num navegador, dava no mesmo — e foi por isso que sobreviveu. Deixa de dar assim que a ENGINE monta,
348
- * porque o `createGame` recebe o documento por `host.doc` e pode estar a montar noutro.
228
+ * The root's translator (ADR-0232 D3 erratum): its `t`, the page's language — the 🌐 shows it as a flag — and the setter
229
+ * the 🌐 switches it with. A Pick and not a bare `t`, because the bar reads and sets the language.
230
+ */
231
+ translator: Pick<Translator, 't' | 'locale' | 'setLocale'>;
232
+ /**
233
+ * The DOCUMENT where the pause card and the bar are BUILT. REQUIRED (ADR-0232 D4): `createGame` receives its document
234
+ * through `host.doc` and may be building in another one (an iframe, an editor beside the game), and a fallback to the
235
+ * global would put the card in the wrong document — or throw where there is none.
349
236
  */
350
- doc?: Document;
351
- /** Quantos jogadores/telas. Estado de RODADA (ADR-0038): vem da instância que a raiz possui.
352
- * Era `numPlayers`, um `let` de `core/state` importado como binding vivo — e um `let` de módulo
353
- * é compartilhado por qualquer segundo jogo que a mesma página carregue (D13 do `demos`). */
237
+ doc: Pick<Document, 'createElement'>;
238
+ /** How many players/screens. ROUND state (ADR-0038): it comes from the instance the host owns — a module-level
239
+ * binding would be shared by a second game on the same page. */
354
240
  getNumPlayers: () => number;
355
- /** Os jogadores. Estado de RODADA, pelo mesmo motivo. `readonly unknown[]` porque cada consumidor
356
- * estreita para a SUA fatia — o tipo real é do jogo, não da engine (ADR-0033). */
241
+ /** The players. ROUND state, for the same reason. `readonly unknown[]` because each consumer narrows to ITS slice —
242
+ * the real type is the game's, not the engine's (ADR-0033). */
357
243
  getPlayers: () => readonly unknown[];
358
244
  /** aria-live "polite" — every successful toggle announces its NEW state. */
359
245
  srSay: (text: string) => void;
360
- /** aria-live "assertive" — the two refusals (`soon` icon, shared audio output). */
246
+ /** aria-live "assertive" — the refusals (a shared audio output, no voice for the language). */
361
247
  srAlert: (text: string) => void;
362
248
  /**
363
- * As BARRAS RÁPIDAS por tela (`.screen-a11y`), na ordem dos jogadores.
364
- *
365
- * Existe pelo mesmo motivo de `getPauseScreens`: `buildGameHud` REATRIBUI a array a cada remontagem, então
366
- * o que se injeta é o getter e não a array. E existe separada da pausa porque, desde o item 7, a barra não
367
- * mora mais dentro dela — o daltonismo é POR JOGADOR, e refletir os ícones exige achar a barra daquela tela.
249
+ * Called after EVERY exit from the bar mode, with the screen and whether it was silent. Absent, nothing happens. It lets
250
+ * the root unfreeze the game whichever door was used (ADR-0155) — the bar knows nothing of phases.
251
+ */
252
+ onLeaveBar?: (i: number, silent: boolean) => void;
253
+ /**
254
+ * The icon screen `i` is pointing at — by the cursor of the bar, or hover/focus — or `null` when nothing is. The
255
+ * root writes that icon's EXPLANATION in the footer (the Dev: the name below the row, what it does in the footer;
256
+ * `CLAUDE.md` §4, the three zones). Absent, the bar still shows the name.
257
+ */
258
+ explainIcon?: (i: number, k: string | null) => void;
259
+ /** A text for the screen footer — the reason of a locked pause item (ADR-0161) — or `null` to clear it. */
260
+ explainItem?: (text: string | null) => void;
261
+ /**
262
+ * The per-screen QUICK BARS (`.screen-a11y`), in player order. A getter, because the host rebuilds them when the number of
263
+ * screens changes. Separate from the pause card because the bar does not live inside it (ADR-0044 item 7) — colour
264
+ * correction is PER PLAYER, and reflecting the icons means finding that screen's bar.
368
265
  */
369
266
  getA11yBars: () => readonly HTMLElement[];
370
- /** PM_OPTIONS_BTNS — o submenu de opções. Mesma dona, mesmo motivo: ninguém tem duas cópias de uma lista. */
267
+ /** PM_OPTIONS_BTNS — the options sub-list. */
371
268
  optionsButtons?: readonly PauseMenuButton[];
372
- /** PM_BTNS — the `.pm-btn` list. Owned by ui/activities-menu; injected, never copied. */
269
+ /** The GAME's list (ADR-0146). Absent = `PM_GAME_BTNS`, which is only «back» — and the door drops by itself. */
270
+ gameButtons?: readonly PauseMenuButton[];
271
+ /** PM_BTNS — the root `.pm-btn` list (`ui/pause-buttons`). */
373
272
  pmButtons?: readonly PauseMenuButton[];
374
- /** QL_NAME — literacy-level names, for the (dormant) `nivel` button. Same owner as pmButtons. */
375
273
  /**
376
- * O RÓTULO de um botão dinâmico, pronto — ou `null` quando aquele botão não tem um (item 19).
377
- *
378
- * Era `quizLevel` (importado de `core/state`) mais `qlName` (tabela do jogo), e este módulo montava a
379
- * frase. Um menu de pausa da ENGINE não sabe o que é nível de alfabetização, nem em que idioma dizê-lo.
380
- * Função e não valor, porque o rótulo muda em execução — de nível E de idioma.
274
+ * The ready LABEL of a dynamic button, or `null` when that button has none. A function, because the label changes at run
275
+ * time — in value and in language. A pause card of the ENGINE does not know what a literacy level is, nor how to say it.
381
276
  */
382
- /** O rótulo dinâmico, pronto — ou `null`. Ausente: nenhum botão deste jogo tem rótulo dinâmico. */
383
277
  dynLabel?: (b: PauseMenuButton) => string | null;
384
- /** The `.pm-btn` action table. LAZY: `pauseActs` is a `const` declared far below the init site in game.js. */
278
+ /** The `.pm-btn` action table, asked when an item is pressed (so it can be wired after this module). */
385
279
  getPauseActs?: () => Record<string, (() => void) | undefined>;
386
- /** Records which player opened the menu. `pauseActor` itself stays in game.js — the gamepad, the keyboard
387
- * router, openHelp() and openOptions() all read it there. */
280
+ /** Records which player opened the card; the panels open scoped to that player. */
388
281
  setPauseActor?: (i: number) => void;
389
- getModoCego: () => boolean;
390
- setModoCego?: (on: boolean) => void;
282
+ getBlindMode: () => boolean;
283
+ setBlindMode?: (on: boolean) => void;
391
284
  /**
392
- * O mixer por categoria. NULO até `initAudioMixer()` — `platform/audio` o declara
393
- * `Record<string, CatState> | null` porque o import dele é PURO (não lê localStorage), e quem inicializa
394
- * é o boot do consumidor. Este ctx pedia não-nulo, o que era uma promessa que a fonte não faz.
285
+ * The mixer by category. NULL until `initAudioMixer()`: `platform/audio`'s import is PURE (it reads no storage), and the
286
+ * host's boot initialises it.
395
287
  */
396
288
  getAudioCat: () => Record<string, AudioCatState> | null;
397
289
  /** Re-applies a category's gain node after `on`/`vol` changed. */
398
290
  setCatGain: (k: string) => void;
399
- /** Repaints the TTS row of the auditory panel. See BUG #1 in the report: in game.js this call is behind a
400
- * `typeof reflectTTS==='function'` guard on a symbol that no longer exists, so it never fires. The guard is
401
- * ported verbatim as `reflectTtsPanelEnabled` below rather than silently fixed. */
291
+ /** Repaints the TTS row of the auditory panel after the icon changes it. */
402
292
  reflectTtsPanel: () => void;
403
- /** Verbatim port of game.js's dead guard: `typeof reflectTTS === 'function'`. Pass `false` to preserve
404
- * today's behaviour (the panel is NOT refreshed), `true` to restore the intended call. */
293
+ /**
294
+ * Whether the TTS icon also calls `reflectTtsPanel`. `createGame` passes `false`: it repaints the panel from the mixer's
295
+ * `onCatChange`, which hears this icon's write like any other (ADR-0247). A host without that listener passes `true`.
296
+ */
405
297
  reflectTtsPanelEnabled: boolean;
406
298
  isLibrasOn: () => boolean;
407
299
  toggleLibras: () => void;
300
+ /**
301
+ * THE PAGE'S STORE, built by the root (ADR-0232, issue #207): the calm level, the movement latch's default writer and the
302
+ * scene flags' default read and write through it. REQUIRED: a bar that stored nowhere would forget the calm level at every
303
+ * visit — for the child whom unexpected noise costs most — with no error at all.
304
+ */
305
+ store: PauseIconsStore;
306
+ /**
307
+ * THE PAGE'S SETTINGS STORE (ADR-0232 D2c): what the icons read and cycle — game speed, the camera and voice controls,
308
+ * switch scanning, the menu index — and the default blind-mode writer. REQUIRED: a bar reading settings from nowhere
309
+ * would show every icon at its default and write the child's choice where no game reads it.
310
+ */
311
+ settings: PauseIconsSettings;
408
312
  rm?: MotionSceneFlags;
409
313
  rmKeys?: readonly MotionSceneKey[];
410
314
  rmChar?: readonly MotionCharDef[];
411
315
  saveRM?: () => void;
316
+ /**
317
+ * The browser's media query (`win.matchMedia`), asked for `prefers-reduced-motion` when `rm` is absent and nothing is
318
+ * stored. MANDATORY and injected (ADR-0232, ADR-0227): this module reaches no global, and an optional port would let a
319
+ * host forget it and switch the animation back on for a child whose system asked for less.
320
+ */
321
+ matchMedia: MediaQuery;
412
322
  setToggleMove?: (i: number, on: boolean) => void;
413
323
  /**
414
- * QUAL APARELHO ESTE JOGADOR ESTÁ A USAR (ADR-0113).
415
- *
416
- * 📌 O ícone `altmove` desta barra é a OUTRA superfície que escreve a alternância — a mesma razão pela
417
- * qual o escritor voltou para a engine (ADR-0106 §4). Sem este campo, ele escreveria só a chave antiga
418
- * enquanto o painel escreve as duas, e as duas superfícies divergiriam em silêncio.
324
+ * WHICH DEVICE THIS PLAYER IS USING (ADR-0113). The `altmove` icon is the OTHER surface that writes the latch, besides
325
+ * the panel: without this it would write a different key from the panel's, and the two surfaces would disagree silently.
419
326
  */
420
- transporteEmUso?: (jogador: number) => string;
327
+ transportInUse?: (player: number) => string;
421
328
  setPlayerViz?: (i: number, mode: string) => void;
422
- /** Os escritores POR EIXO (#104): mexer no tema não apaga a correção, e vice-versa. */
423
- setTemaDoJogador?: (i: number, tema: Tema) => void;
424
- setCorrecaoDoJogador?: (i: number, correcao: Correcao) => void;
329
+ /** The writers PER AXIS (#104): changing the theme does not erase the correction, and vice versa. */
330
+ setPlayerTheme?: (i: number, theme: Theme) => void;
331
+ setPlayerCorrection?: (i: number, correction: Correction) => void;
425
332
  /**
426
- * ESTE JOGO SEGURA ALGUMA TECLA? — o valor de `GameDeclaration.seguraTeclas` (ADR-0115). Sem ele o ícone
427
- * `altmove` não é montado.
428
- *
429
- * ⚠️ OBRIGATÓRIO, e vai contra a direcção do ADR-0106, que passou a tornar campos deste ctx OPCIONAIS para
430
- * a engine poder montar sozinha. A excepção tem razão medida: os campos que ganharam padrão têm um padrão
431
- * SEGURO — o modo cego começa desligado, a lista de botões vem da engine. Aqui não há: `true` monta um
432
- * controle que pode não fazer nada, e `false` esconde um de que uma criança depende. Os dois lados erram, e
433
- * é essa a condição que o `holdsAtOnce` já usou para ser obrigatório também.
434
- *
435
- * 📌 Quem passa pelo `createGame` não escreve isto: a raiz lê a declaração, que já é obrigatória. O campo
436
- * só é visível para um cartucho que chame `initPauseIcons` por fora — e é exactamente esse que não pode
437
- * ficar em silêncio.
333
+ * MOVES ONE STEP IN THE TYPOGRAPHY CYCLE and returns the face it landed on (ADR-0149 §1). ONE field, not two (read and
334
+ * write): the position belongs to whoever keeps the cycle; this module only needs the face's NAME to announce it.
335
+ * ABSENT = THE ICON IS NOT MOUNTED (ADR-0106 §5).
336
+ */
337
+ cycleTypography?: () => string | null;
338
+ /**
339
+ * DOES THIS GAME HOLD ANY KEY? — `GameDeclaration.holdsKeys` (ADR-0115). Without it the `altmove` icon is not mounted.
438
340
  *
439
- * ⚠️ FUNÇÃO, não valor — ver a nota no campo homónimo de `EscritoresVisuais`. Um cartucho que monte isto
440
- * por fora passa `() => this.declaration.seguraTeclas()` e não o resultado dela.
341
+ * ⚠️ REQUIRED, against ADR-0106's direction of making this ctx's fields optional: the fields that got a default have a
342
+ * SAFE one (blind mode starts off, the button lists come from the engine). This one has none — `true` mounts a control
343
+ * that may do nothing, `false` hides one a child depends on. Both are wrong, which is the same reason `holdsAtOnce` is
344
+ * required. Whoever goes through `createGame` never writes it: the root reads the declaration. A FUNCTION, not a value
345
+ * (see `ActionableIcons.holdsKeys`): a cartridge wiring this itself passes `() => declaration.holdsKeys()`.
441
346
  */
442
- seguraTeclas: () => boolean;
347
+ holdsKeys: () => boolean;
348
+ /** How many positions the current game declared — what «one button only» would scan (ADR-0218). Absent reads as none. */
349
+ declaredPositions?: () => number;
350
+ /** Does the current game's time run by itself? (ADR-0180: the hourglass.) Optional; absent, no hourglass. */
351
+ clock?: () => boolean;
352
+ /** Can this device play through the webcam? (ADR-0215: the 📷.) Optional; absent, no 📷. */
353
+ camera?: boolean;
354
+ /** Can this device hear the child — is there a microphone to ask for? (issue #184: the 👄.) Absent, no 👄. */
355
+ microphone?: boolean;
356
+ /** Opens the menus of seat `i`, as SELECT does (the ☰). Optional; absent, no ☰. */
357
+ openMenus?: (i: number) => void;
358
+ /** Does no voice speak the current language? (ADR-0185: the narration icon locks.) Optional; absent, a voice. */
359
+ noVoice?: () => boolean;
443
360
  }
444
361
  export interface PauseIconsApi {
445
362
  /** Builds one `.screen-pause` (hidden), wired for click + hover/focus caption. Caller appends it. */
446
363
  buildScreenPause: (i: number) => HTMLElement;
447
- /** Monta a BARRA RÁPIDA (`.screen-a11y`) da tela `i`, já fiada. Chamada por ui/hud.ts, uma por tela. */
364
+ /** Builds screen `i`'s QUICK BAR (`.screen-a11y`), already wired. Called by ui/hud.ts, one per screen. */
448
365
  buildQuickBar: (i: number) => HTMLElement;
449
366
  /**
450
- * OS ÍCONES QUE ESTA INSTÂNCIA MONTA — já filtrados pelo §5 do ADR-0106.
451
- *
452
- * ⚠️ Existe para que quem monta a barra do TÍTULO não repita o filtro. A barra do título não pode usar
453
- * `buildQuickBar` (ele põe `tabIndex = -1`, e o próprio comentário lá diz porquê: no título não se está a
454
- * jogar), então ela chama `iconsMarkup` directamente — e sem este acessor teria de recalcular quais ícones
455
- * accionam, que é uma segunda cópia da mesma decisão.
367
+ * THE ICONS THIS INSTANCE MOUNTS — already filtered by ADR-0106 §5. It exists so the bar the root mounts in
368
+ * `#title-icons` (which cannot use `buildQuickBar`: that one sets `tabIndex = -1`, for a game in play) does not repeat
369
+ * the filter — a second copy of the same decision.
456
370
  */
457
- iconesMontados: readonly PauseIcon[];
458
- /** ENTRA no modo `accessibility` da tela `i` — é o que o item `acessibilidade` da pausa faz. */
459
- entrarNaBarra: (i: number) => void;
460
- /** SAI do modo e devolve o direcional ao personagem. */
461
- sairDaBarra: (i: number) => void;
462
- /** A tela `i` está com o direcional na BARRA em vez de no personagem? Perguntado a cada quadro. */
463
- naBarraDe: (i: number) => boolean;
464
- /** Um passo dentro do modo. `temStart` é a borda do botão de pausa — a segunda saída (ADR-0044, item 7). */
465
- navBar: (i: number, k: NavKeys, temStart?: boolean) => void;
466
- /** Runs the icon `k` for screen `i`. Does NOT reflect — callers reflect after, as game.js always did. */
371
+ mountedIcons: readonly PauseIcon[];
372
+ /** ENTERS screen `i`'s `accessibility` mode — the bar half of the quick pause (ADR-0155). Does not touch the phase. */
373
+ enterBar: (i: number) => void;
374
+ /** LEAVES the mode and gives the d-pad back to the character. `silent` = leaving for another screen, not for the game. */
375
+ leaveBar: (i: number, silent?: boolean) => void;
376
+ /** Is screen `i`'s d-pad on the BAR instead of on the character? Asked every frame. */
377
+ onBar: (i: number) => boolean;
378
+ /** One step inside the mode. `hasStart` is the pause button's edge — the second way out (ADR-0044 item 7). */
379
+ navBar: (i: number, k: NavKeys, hasStart?: boolean) => void;
380
+ /** Runs the icon `k` for screen `i`. Does NOT reflect — callers reflect after. */
467
381
  iconAct: (k: string, i: number) => void;
468
382
  /** The state-reflecting `aria-label` of icon `k` for screen `i`. */
469
383
  iconLabel: (k: string, i: number) => string;