@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,152 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /**
3
+ * THE SONAR'S POSITION WHILE A MENU IS OPEN. In play the position is the game's (its `preset`); with a menu open the positions
4
+ * are the engine's, and there R1 reads the menu — the Dev's default for the sonar («Tecla padrão para o sonar deve ser R1»).
5
+ */
6
+ const MENU_SONAR = 'rightShoulder';
7
+ /** The engine's chrome the child did not ask about (see the header). */
8
+ const NOT_ASKED_ABOUT = [
9
+ '.pause-icons', '.screen-a11y', '.rodape-da-tela', '.scan-now', '#touch-controls', '.touch', '.sr-only',
10
+ '.gaze-overlay', '.face-overlay', '.hand-overlay', '.hud-row-clock',
11
+ ].join(', ');
12
+ /** What is open in front of the world. */
13
+ const DIALOG = '[role="dialog"], [role="alertdialog"], [aria-modal="true"]';
14
+ /** Elements whose content is not words on the screen (a `<select>` shows its chosen option only — see `spokenAs`). */
15
+ const NOT_WORDS = /^(script|style|template|noscript|svg|canvas|video|audio|iframe|object|option|optgroup)$/i;
16
+ /** A line that already ends a sentence is not given a full stop. */
17
+ const ENDS_A_SENTENCE = /[.!?…:;]$/u;
18
+ /**
19
+ * Is this one element drawn for the eye, and meant for everyone? Its ancestors are asked by whoever walks down to it.
20
+ * 📌 The RENDERING decides, not the `hidden` attribute: `hidden` hides by `display: none`, which is read here, and a stylesheet
21
+ * that shows a `[hidden]` element puts it on the screen.
22
+ */
23
+ function isShown(el) {
24
+ if (el.hasAttribute('inert') || el.getAttribute('aria-hidden') === 'true')
25
+ return false;
26
+ const style = el.ownerDocument?.defaultView?.getComputedStyle(el);
27
+ return !style || (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0');
28
+ }
29
+ /** Is it drawn, with every ancestor drawn too? For an element found by a query rather than walked down to. */
30
+ function isOnScreen(el) {
31
+ for (let node = el; node; node = node.parentElement)
32
+ if (!isShown(node))
33
+ return false;
34
+ return true;
35
+ }
36
+ /**
37
+ * Can this node be walked and asked? A host double may hand elements without the DOM's questions; then there is nothing the
38
+ * engine can read, and it says nothing rather than throwing into the sonar (a capability of the environment, ADR-0169).
39
+ */
40
+ function canBeRead(el) {
41
+ return !!el && typeof el.matches === 'function' && typeof el.querySelectorAll === 'function' && typeof el.hasAttribute === 'function';
42
+ }
43
+ /** The dialog in front, or `null`: the one holding the focus, else the last one open in the document. */
44
+ function dialogInFront(doc) {
45
+ if (typeof doc.querySelectorAll !== 'function')
46
+ return null;
47
+ const open = [...doc.querySelectorAll(DIALOG)].filter((d) => canBeRead(d) && isOnScreen(d) && !d.matches(NOT_ASKED_ABOUT));
48
+ const focused = doc.activeElement;
49
+ return open.find((d) => !!focused && d.contains(focused)) ?? open[open.length - 1] ?? null;
50
+ }
51
+ /** The world's element, or `null` when the game declared none, its selector matches nothing, or it cannot be read. */
52
+ function worldElement(ctx) {
53
+ const scope = ctx.world();
54
+ const el = scope.kind === 'element' && typeof ctx.doc.querySelector === 'function' ? ctx.doc.querySelector(scope.selector) : null;
55
+ return canBeRead(el) ? el : null;
56
+ }
57
+ /** Does the world draw on a canvas the engine did not put there? Then its words are pixels. */
58
+ function drawsOnCanvas(world) {
59
+ const canvases = world.matches('canvas') ? [world] : [...world.querySelectorAll('canvas')];
60
+ return canvases.some((c) => !c.closest(NOT_ASKED_ABOUT) && isOnScreen(c));
61
+ }
62
+ /** The words an element stands for instead of its children, or `null` to read its children. */
63
+ function spokenAs(el) {
64
+ if (el.getAttribute('role') === 'img')
65
+ return el.getAttribute('aria-label') ?? '';
66
+ if (el.localName === 'img')
67
+ return el.getAttribute('alt') ?? '';
68
+ if (el.localName === 'select')
69
+ return el.selectedOptions[0]?.textContent ?? '';
70
+ return null;
71
+ }
72
+ /** Does the element start a line of its own? Everything that is not inline does — a button, a heading, a row. */
73
+ function breaksTheLine(el) {
74
+ const display = el.ownerDocument?.defaultView?.getComputedStyle(el).display ?? 'block';
75
+ return el.localName === 'br' || (display !== 'inline' && display !== 'contents');
76
+ }
77
+ /**
78
+ * The text under `root`, in DOM order, one line per block. Lines are joined as sentences, so the voice pauses between the
79
+ * statement and each option and the interpreter receives them apart.
80
+ */
81
+ function textOf(root) {
82
+ const lines = [];
83
+ let line = '';
84
+ const endLine = () => {
85
+ const words = line.replace(/\s+/gu, ' ').trim();
86
+ if (words)
87
+ lines.push(words);
88
+ line = '';
89
+ };
90
+ const readChildren = (el) => {
91
+ for (const child of el.childNodes ?? []) {
92
+ if (child.nodeType === 3)
93
+ line += child.textContent ?? '';
94
+ else if (child.nodeType === 1)
95
+ visit(child);
96
+ }
97
+ };
98
+ const visit = (el) => {
99
+ if (!isShown(el) || el.matches(NOT_ASKED_ABOUT) || NOT_WORDS.test(el.localName))
100
+ return;
101
+ const own = breaksTheLine(el);
102
+ if (own)
103
+ endLine();
104
+ const said = spokenAs(el);
105
+ if (said === null)
106
+ readChildren(el);
107
+ else
108
+ line += ` ${said} `;
109
+ if (own)
110
+ endLine();
111
+ };
112
+ visit(root);
113
+ endLine();
114
+ return lines.map((l) => (ENDS_A_SENTENCE.test(l) ? l : `${l}.`)).join(' ');
115
+ }
116
+ /**
117
+ * WHAT IS ON THE SCREEN NOW, as the sonar reads it — `''` when there is nothing the engine can read: no world, an empty one,
118
+ * or a world drawn on a canvas.
119
+ */
120
+ export function screenText(ctx) {
121
+ const front = dialogInFront(ctx.doc);
122
+ if (front)
123
+ return textOf(front);
124
+ const world = worldElement(ctx);
125
+ return world && !drawsOnCanvas(world) ? textOf(world) : '';
126
+ }
127
+ /**
128
+ * The `problems` line for a world the sonar cannot read — none, or one (ADR-0169: the subject, the child's cost, the fix).
129
+ * Measured at every read of `problems`: a canvas is often drawn after the boot.
130
+ */
131
+ export function unreadableWorldProblems(ctx) {
132
+ const world = worldElement(ctx);
133
+ if (!world || !drawsOnCanvas(world))
134
+ return [];
135
+ return ['the sonar cannot read this game\'s screen: its world draws on a <canvas>, whose words are pixels to the engine, so '
136
+ + 'a child who presses the sonar hears only the nearest target\'s name and side instead of what is written on screen — '
137
+ + 'and in deaf mode the interpreter signs that, not the screen (ADR-0234). Write the words the child must read as text '
138
+ + 'in the page, inside the world; a contract field for a game to hand the engine its screen\'s text is a decision the '
139
+ + 'Dev has not taken'];
140
+ }
141
+ /**
142
+ * A press made WITH A MENU OPEN: the menu sonar's position reads what is in front (`read`) and takes the press. Any other
143
+ * position is left to the menus — answers whether this one was taken.
144
+ */
145
+ export function menuSonarPress(action, ctx, read) {
146
+ if (action !== MENU_SONAR)
147
+ return false;
148
+ const text = screenText(ctx);
149
+ if (text)
150
+ read(text);
151
+ return true;
152
+ }
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import type { Translate } from '../core/i18n.js';
3
+ /**
4
+ * What the clock needs, all lent by the root. The three host ports are REQUIRED and may carry `undefined` — a host without
5
+ * them is answered here, not with a branch in the root (ADR-0232 erratum of 2026-09-25): with no clock or no tick there is no
6
+ * session to measure, and nothing is mounted, silently, as a capability of the environment (ADR-0169).
7
+ */
8
+ export interface SessionClockCtx {
9
+ readonly doc: Document;
10
+ /** Where the clock goes: the HUD row's centre cell. Absent, or a node that takes no children, and nothing is mounted. */
11
+ readonly slot: HTMLElement | null;
12
+ readonly t: Translate;
13
+ /** The host's `performance`, milliseconds and monotonic. The session starts at the mount. */
14
+ readonly performance: {
15
+ now(): number;
16
+ } | undefined;
17
+ readonly setInterval: ((fn: () => void, ms: number) => number) | undefined;
18
+ readonly clearInterval: ((handle: number) => void) | undefined;
19
+ /** The polite announcer: said once, when the hour runs out. */
20
+ readonly announce: (text: string) => void;
21
+ /** Called after every redraw, so the root can measure the row again when the clock's size changed. */
22
+ readonly drawn: () => void;
23
+ }
24
+ export interface SessionClockMounted {
25
+ readonly el: HTMLElement;
26
+ /** Reads the time again and redraws what changed (the tick calls it; a language change too). */
27
+ refresh(): void;
28
+ /** Stops the tick and takes the clock off the page. */
29
+ remove(): void;
30
+ }
31
+ /** Mounts the clock in its slot, draws it now, and redraws it every second until `remove()`; `null` where it cannot. */
32
+ export declare function mountSessionClock(ctx: SessionClockCtx): SessionClockMounted | null;
@@ -0,0 +1,67 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { readSession, clockWords, clockDigits } from '../core/session-clock.js';
3
+ /** One tick a second: the digits move by the second, and the hour's pie by a tenth of a degree, which reads as continuous. */
4
+ const TICK_MS = 1000;
5
+ /** Writes `text` into `node` only when it changed — a rewrite is a repaint, and on school hardware a repaint costs. */
6
+ function write(node, text) {
7
+ if (node.textContent !== text)
8
+ node.textContent = text;
9
+ }
10
+ /**
11
+ * Builds the clock's three parts: the label and the digits in a column, the pie to their right.
12
+ *
13
+ * 🔴 THE PARTS ARE `aria-hidden`: they are the picture, and the image's name is what a listener gets. ARIA calls an image's
14
+ * children presentational, but not every accessibility API prunes them — Gecko keeps a graphic's children unless it has exactly
15
+ * one text child, and NVDA then read «TEMPO. 56:07.» instead of the words (the Dev, 2026-09-25). Hidden here, no API has any
16
+ * text under the image to hand out. Gate: `tests/quiz-accessibility-tree.browser.test.js`, on the browser's own tree.
17
+ */
18
+ function build(doc) {
19
+ const part = (cls) => { const n = doc.createElement('span'); n.className = cls; return n; };
20
+ const el = doc.createElement('div');
21
+ el.className = 'session-clock';
22
+ el.setAttribute('role', 'img');
23
+ const text = part('session-clock-text');
24
+ const label = part('session-clock-label');
25
+ const digits = part('session-clock-digits');
26
+ const pie = part('session-clock-pie');
27
+ text.setAttribute('aria-hidden', 'true');
28
+ pie.setAttribute('aria-hidden', 'true');
29
+ text.append(label, digits);
30
+ el.append(text, pie);
31
+ return { el, label, digits, pie };
32
+ }
33
+ /** Mounts the clock in its slot, draws it now, and redraws it every second until `remove()`; `null` where it cannot. */
34
+ export function mountSessionClock(ctx) {
35
+ const { slot, performance: clock, setInterval: every } = ctx;
36
+ if (!slot || typeof slot.appendChild !== 'function' || !clock || typeof every !== 'function')
37
+ return null;
38
+ const { el, label, digits, pie } = build(ctx.doc);
39
+ slot.appendChild(el);
40
+ const timer = clock; // the guard's answer, kept for the tick
41
+ const start = timer.now();
42
+ let look = null;
43
+ function refresh() {
44
+ const reading = readSession(timer.now() - start);
45
+ const next = reading.over ? 'red' : 'running';
46
+ pie.style.setProperty('--left', reading.left.toFixed(4));
47
+ write(label, ctx.t('clock.label'));
48
+ write(digits, clockDigits(reading.leftMs));
49
+ const words = clockWords(reading);
50
+ const name = ctx.t(words.key, { minutes: words.minutes });
51
+ if (el.getAttribute('aria-label') !== name)
52
+ el.setAttribute('aria-label', name);
53
+ if (next !== 'running' && look === 'running')
54
+ ctx.announce(name);
55
+ if (next !== look)
56
+ el.dataset.look = next;
57
+ look = next;
58
+ ctx.drawn();
59
+ }
60
+ refresh();
61
+ const handle = every(refresh, TICK_MS);
62
+ return {
63
+ el,
64
+ refresh,
65
+ remove: () => { ctx.clearInterval?.(handle); el.remove(); },
66
+ };
67
+ }
@@ -0,0 +1,70 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import type { Translate } from '../core/i18n.js';
3
+ import type { LetterCase } from '../core/state.js';
4
+ import { type AacSet } from './aac-sets.js';
5
+ import { type ControlRowSpec } from './panel-widgets.js';
6
+ import type { PanelShellCtx } from './panel-shell.js';
7
+ /**
8
+ * The LETTERS row is a SWITCH, not two options (the Dev's decision). On = upper case only; off = upper and lower case.
9
+ * A binary question presented as two rows makes the child compare both to discover they are the same question.
10
+ */
11
+ export declare function upperCaseOn(letterCase: LetterCase): boolean;
12
+ /** The id of a set's control. It comes from the catalogue `key`, unique by construction (`AAC_BY_KEY`). */
13
+ export declare const aacControlId: (key: string) => string;
14
+ /** The letters switch. Always available: it is the offline floor, and never depended on any file. */
15
+ export declare function lettersRowSpec(t: Translate): ControlRowSpec;
16
+ /**
17
+ * A menu row: a SHORT LABEL and nothing else in view.
18
+ *
19
+ * Everything that explains — note, licence, status — goes into a single `.opt-hint`, which the shell (`fillExplain`)
20
+ * recognises and MOVES to the footer. Prose hung inside the row turns the menu into a manual, closer to a configuration
21
+ * file than to a videogame menu — the Dev saw exactly that.
22
+ *
23
+ * `ariaLabel` carries the reason, so whoever navigates by keyboard hears why the row does not respond without hunting
24
+ * for the footer. `disabled` belongs to the CONTROL and not the text: the status leaves the label, never the button.
25
+ */
26
+ export declare function aacRowSpec(t: Translate, s: AacSet): ControlRowSpec;
27
+ /**
28
+ * The menu's two sections: what works now (the letters switch), and the pictogram sets, each only with a licence
29
+ * (ADR-0233). Whether a set row is locked is the row's own business (its reason and its `disabled`), so a licence that
30
+ * arrives changes one row, not the sections.
31
+ *
32
+ * 📌 Each produces its own rows instead of filtering the catalogue, because the first does not come from the catalogue
33
+ * — the letters are a switch and not a set, the Dev's decision that took them out of the list. A table whose first row
34
+ * is the exception to all the others lies about what it is.
35
+ */
36
+ export declare const AAC_SECTIONS: ReadonlyArray<{
37
+ title: string;
38
+ tag: string;
39
+ rows: (t: Translate) => ControlRowSpec[];
40
+ }>;
41
+ /**
42
+ * Mounts the menu's inside ONCE. Called again, it RELABELS instead of rebuilding.
43
+ *
44
+ * ⚠️ Relabel and not rebuild, for the reason `labelRow` already states: listeners are wired at boot, and remaking the
45
+ * row would leave a control in the document with no listener — a dead button that looks alive (ADR-0106 §5). And the
46
+ * text may have been captured at boot, while the language was still the fallback.
47
+ */
48
+ export declare function mountAacInside(t: Translate, ctx: PanelShellCtx, list: HTMLElement): void;
49
+ export interface SettingsAacCtx {
50
+ /** Translates in the page's language — the root's translator (ADR-0232 D3). REQUIRED: text built from nowhere is a raw key. */
51
+ t: Translate;
52
+ $: <T extends Element = Element>(sel: string) => T | null;
53
+ srSay: (msg: string) => void;
54
+ /** Live read of core/state `letterCase` (the binding is reassigned by the setter). */
55
+ getLetterCase: () => LetterCase;
56
+ /** core/state `setLetterCaseValue` PLUS the reflection the game needs (re-rendering its text, labels). */
57
+ setLetterCase: (c: LetterCase) => void;
58
+ frontOverlay: (el: HTMLElement | null) => void;
59
+ /** Moves the rows' prose to the footer (ui/settings-panel `fillExplain`). Called on EVERY render, not only on open:
60
+ * relabelling a row puts the hint back inside it, and without this call the menu turns into a manual again on the
61
+ * first click. */
62
+ fillExplain: (card: HTMLElement | null) => void;
63
+ restoreFocus?: (id: string) => boolean;
64
+ }
65
+ export interface SettingsAacApi {
66
+ render: () => void;
67
+ open: () => void;
68
+ close: () => void;
69
+ }
70
+ export declare function initSettingsAac(ctx: SettingsAacCtx): SettingsAacApi;
@@ -0,0 +1,208 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { DEFAULTS } from '../core/setting-defaults.js';
3
+ import { AAC_SETS, AAC_BY_KEY, aacMenuLocked, aacReason, aacSelectable } from './aac-sets.js';
4
+ import { markChanged, markMenuChanged } from './changed-mark.js';
5
+ import { controlRow, labelRow, sectionHeader } from './panel-widgets.js';
6
+ import { toggleLabel } from './dom.js';
7
+ /**
8
+ * The LETTERS row is a SWITCH, not two options (the Dev's decision). On = upper case only; off = upper and lower case.
9
+ * A binary question presented as two rows makes the child compare both to discover they are the same question.
10
+ */
11
+ export function upperCaseOn(letterCase) {
12
+ return letterCase === 'upper';
13
+ }
14
+ /** The id of a set's control. It comes from the catalogue `key`, unique by construction (`AAC_BY_KEY`). */
15
+ export const aacControlId = (key) => `caa-set-${key}`;
16
+ /** The letters switch. Always available: it is the offline floor, and never depended on any file. */
17
+ export function lettersRowSpec(t) {
18
+ return { id: 'caa-caixa-alta', label: t('aac.letras'), hint: t('aac.letras.dica') };
19
+ }
20
+ /**
21
+ * A menu row: a SHORT LABEL and nothing else in view.
22
+ *
23
+ * Everything that explains — note, licence, status — goes into a single `.opt-hint`, which the shell (`fillExplain`)
24
+ * recognises and MOVES to the footer. Prose hung inside the row turns the menu into a manual, closer to a configuration
25
+ * file than to a videogame menu — the Dev saw exactly that.
26
+ *
27
+ * `ariaLabel` carries the reason, so whoever navigates by keyboard hears why the row does not respond without hunting
28
+ * for the footer. `disabled` belongs to the CONTROL and not the text: the status leaves the label, never the button.
29
+ */
30
+ export function aacRowSpec(t, s) {
31
+ const reason = aacReason(s);
32
+ const explains = [s.note, s.license ? `Licença: ${s.license}` : '', reason ? t(reason) : '']
33
+ .filter(Boolean).join(' · ');
34
+ return {
35
+ id: aacControlId(s.key),
36
+ label: s.name,
37
+ ...(explains ? { hint: explains } : {}),
38
+ ariaLabel: `${s.name}${reason ? ', ' + t(reason) : ''}`,
39
+ };
40
+ }
41
+ /**
42
+ * The menu's two sections: what works now (the letters switch), and the pictogram sets, each only with a licence
43
+ * (ADR-0233). Whether a set row is locked is the row's own business (its reason and its `disabled`), so a licence that
44
+ * arrives changes one row, not the sections.
45
+ *
46
+ * 📌 Each produces its own rows instead of filtering the catalogue, because the first does not come from the catalogue
47
+ * — the letters are a switch and not a set, the Dev's decision that took them out of the list. A table whose first row
48
+ * is the exception to all the others lies about what it is.
49
+ */
50
+ export const AAC_SECTIONS = [
51
+ { title: 'aac.secao.agora', tag: 'aac.secao.agoraTag', rows: (t) => [lettersRowSpec(t)] },
52
+ {
53
+ title: 'aac.section.pictograms',
54
+ tag: 'aac.section.pictogramsTag',
55
+ rows: (t) => AAC_SETS.map((s) => aacRowSpec(t, s)),
56
+ },
57
+ ];
58
+ /**
59
+ * Mounts the menu's inside ONCE. Called again, it RELABELS instead of rebuilding.
60
+ *
61
+ * ⚠️ Relabel and not rebuild, for the reason `labelRow` already states: listeners are wired at boot, and remaking the
62
+ * row would leave a control in the document with no listener — a dead button that looks alive (ADR-0106 §5). And the
63
+ * text may have been captured at boot, while the language was still the fallback.
64
+ */
65
+ export function mountAacInside(t, ctx, list) {
66
+ for (const section of AAC_SECTIONS) {
67
+ const specs = section.rows(t);
68
+ const header = sectionHeader(ctx, t(section.title), t(section.tag), specs.length);
69
+ if (header && !list.querySelector(`[data-caa-section="${section.title}"]`)) {
70
+ header.setAttribute('data-caa-section', section.title);
71
+ list.appendChild(header);
72
+ }
73
+ for (const spec of specs) {
74
+ const old = ctx.find('#' + spec.id)?.closest('.ctrl-row');
75
+ if (old)
76
+ labelRow(old, spec);
77
+ else
78
+ list.appendChild(newRow(ctx, spec));
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * A new row, with what the kit does not know about this panel: the set's key and the lock.
84
+ *
85
+ * No set is licensed today (ADR-0233). A button that does nothing is worse than absence, because it spends trust — so an
86
+ * unlicensed set comes locked, and the reason is already in `ariaLabel` for whoever navigates by keyboard.
87
+ */
88
+ function newRow(ctx, spec) {
89
+ const { row: row, control: control } = controlRow(ctx, spec);
90
+ if (spec.id === 'caa-caixa-alta') {
91
+ row.id = 'caa-letras';
92
+ return row;
93
+ }
94
+ const key = spec.id.replace('caa-set-', '');
95
+ control.setAttribute('data-caa', key);
96
+ const set = AAC_BY_KEY[key];
97
+ if (!set || !aacSelectable(set))
98
+ control.setAttribute('disabled', '');
99
+ return row;
100
+ }
101
+ export function initSettingsAac(ctx) {
102
+ const { t } = ctx;
103
+ /*
104
+ * 📌 THE KIT'S CTX COMES FROM THE LIST NODE ITSELF, not from a global `document` nor a new contract field.
105
+ * `ownerDocument` is the document that list LIVES in — exactly the document the rows must be born in —, so this
106
+ * module's global reach stays ZERO (ADR-0221) and `SettingsAacCtx`, which is published surface, gains no required
107
+ * member (ADR-0172).
108
+ */
109
+ const panelCtx = (list) => ({
110
+ find: (sel) => ctx.$(sel),
111
+ create: (tag) => list.ownerDocument.createElement(tag),
112
+ });
113
+ function reflect() {
114
+ const b = ctx.$('#caa-caixa-alta');
115
+ if (!b)
116
+ return;
117
+ const on = upperCaseOn(ctx.getLetterCase());
118
+ b.classList.toggle('is-on', on);
119
+ b.setAttribute('aria-pressed', String(on));
120
+ // The switch's text is the STATE; its name is in the `<strong>` beside it and in the `aria-label`.
121
+ b.textContent = toggleLabel(t, on);
122
+ }
123
+ function render() {
124
+ const el = ctx.$('#caa-list');
125
+ if (!el)
126
+ return;
127
+ mountAacInside(t, panelCtx(el), el);
128
+ reflect();
129
+ ctx.fillExplain(ctx.$('#caa .overlay__card'));
130
+ refreshMarks();
131
+ }
132
+ /** The left-the-default mark (ADR-0029), on the chosen row and on the menu's button. */
133
+ function refreshMarks() {
134
+ const changed = ctx.getLetterCase() !== DEFAULTS.letterCase;
135
+ markChanged(t, ctx.$('#caa-letras'), changed);
136
+ markMenuChanged(t, ctx.$('[data-act="caa"]'), [changed]);
137
+ }
138
+ /**
139
+ * THE MENU'S DOOR IS DISABLED while no pictogram set is licensed (ADR-0233 erratum), with the pause card's lock
140
+ * (ADR-0161): `aria-disabled` and the reason in `data-motivo`, which the menu navigation speaks on reach and writes in
141
+ * the footer. The reason is ONLY «menu disabled»: the licence story is not the child's to hear. No unlock branch: the
142
+ * catalogue is static, so a licensed set means the door is never locked in the first place.
143
+ */
144
+ function lockDoor() {
145
+ const door = ctx.$('[data-act="caa"]');
146
+ if (!door || !aacMenuLocked())
147
+ return;
148
+ door.setAttribute('aria-disabled', 'true');
149
+ door.dataset.motivo = t('pause.motivo.caa');
150
+ }
151
+ function open() {
152
+ // A game that wires its own door to `open` meets the same lock: the reason is said and nothing opens, so no
153
+ // per-set licence row reaches the child.
154
+ if (aacMenuLocked()) {
155
+ lockDoor();
156
+ ctx.srSay(t('pause.motivo.caa'));
157
+ return;
158
+ }
159
+ const ov = ctx.$('#caa');
160
+ if (!ov)
161
+ return;
162
+ render();
163
+ ov.hidden = false;
164
+ ctx.frontOverlay(ov);
165
+ const f = ov.querySelector('button');
166
+ if (f)
167
+ f.focus();
168
+ }
169
+ function close() {
170
+ const ov = ctx.$('#caa');
171
+ if (!ov)
172
+ return;
173
+ ov.hidden = true;
174
+ ctx.restoreFocus?.('caa');
175
+ }
176
+ /*
177
+ * The listeners are wired ONCE, on the list, by delegation — which mounting once allows. What protects an
178
+ * unavailable set is its own button's `disabled`, written where it is born; a listener that only guards and then does
179
+ * nothing would be inert code dressed as protection.
180
+ */
181
+ const list = ctx.$('#caa-list');
182
+ if (list)
183
+ list.addEventListener('click', (ev) => {
184
+ const hit = ev.target?.closest('#caa-caixa-alta');
185
+ if (!hit)
186
+ return;
187
+ const turnOn = !upperCaseOn(ctx.getLetterCase());
188
+ ctx.setLetterCase(turnOn ? 'upper' : 'mixed');
189
+ render();
190
+ ctx.srSay(t(turnOn ? 'sr.aac.caixaAltaOn' : 'sr.aac.caixaAltaOff'));
191
+ });
192
+ const closeBtn = ctx.$('#caa-close');
193
+ if (closeBtn)
194
+ closeBtn.addEventListener('click', close);
195
+ lockDoor();
196
+ // ---- reset THIS menu's defaults (ADR-0028) ----
197
+ // The menu has one choice, so the reset is one line — but where it returns to is worth saying: the default case,
198
+ // where Brazilian literacy usually starts. A child who switched the case and can no longer read the screen needs a way
199
+ // back that ends at what their teacher uses.
200
+ const resetBtn = ctx.$('#caa-reset');
201
+ if (resetBtn)
202
+ resetBtn.addEventListener('click', () => {
203
+ ctx.setLetterCase(DEFAULTS.letterCase);
204
+ render();
205
+ ctx.srSay(t('sr.aac.reset'));
206
+ });
207
+ return { render, open, close };
208
+ }