@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,71 +1,61 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  /**
3
- * O que conta como focável. Deliberadamente SEM `[contenteditable]` e sem `tabindex` positivo: os dois
4
- * existem, mas não aparecem em nenhum diálogo desta engine (conferido), e um seletor que promete mais do que
5
- * foi verificado é um seletor que mente na próxima revisão.
3
+ * What counts as focusable. Deliberately WITHOUT `[contenteditable]` and without positive `tabindex`: both exist, but
4
+ * appear in no dialog of this engine, and a selector that promises more than was verified is a selector that lies at
5
+ * the next review.
6
6
  */
7
- export declare const SELETOR_FOCAVEL: string;
7
+ export declare const FOCUSABLE_SELECTOR: string;
8
8
  /**
9
- * Para onde o foco tem de ir quando o Tab está prestes a sair do diálogo — ou `null` quando não há nada a
10
- * fazer e o navegador deve seguir sozinho.
9
+ * Where focus has to go when Tab is about to leave the dialog — or `null` when there is nothing to do and the browser
10
+ * should carry on by itself.
11
11
  *
12
- * Os quatro casos, e o terceiro é a razão de isto existir:
12
+ * The four cases, and the third is why this exists:
13
13
  *
14
- * 1. lista VAZIA → `null`. Um diálogo sem nada focável é um defeito do diálogo, e prender o foco nele
15
- * deixaria a criança sem saída nenhuma. Melhor deixar sair do que trancar num lugar mudo.
16
- * 2. o foco está no ÚLTIMO e vai para a frente → volta ao primeiro; no PRIMEIRO e vai para trás → vai ao
17
- * último. É o ciclo, que é o que «armadilha» quer dizer.
18
- * 3. ⚠️ o foco está FORA da lista → traz de volta. É o caso que os outros três não cobrem: o foco pode já
19
- * ter escapado antes de esta armadilha existir, ou por um clique no tabuleiro, ou porque o diálogo
20
- * abriu sem focar nada. Sem ele a armadilha só funciona para quem já estava dentro.
21
- * 4. o foco está no MEIO → `null`, e o navegador caminha. Ver o comentário do cabeçalho.
14
+ * 1. EMPTY list → `null`. A dialog with nothing focusable is the dialog's defect, and trapping focus in it would
15
+ * leave the child with no way out at all. Better to let it leave than to lock it in a mute place.
16
+ * 2. focus on the LAST going forward → back to the first; on the FIRST going backwards → to the last. That is the
17
+ * cycle, which is what "trap" means.
18
+ * 3. ⚠️ focus OUTSIDE the list → bring it back. The case the other three do not cover: focus may have escaped by a
19
+ * click on the board, or because the dialog opened without focusing anything. Without it the trap only works for
20
+ * whoever was already inside.
21
+ * 4. focus in the MIDDLE → `null`, and the browser walks. See the header.
22
22
  */
23
- export declare function proximoNaArmadilha<T>(focaveis: readonly T[], atual: T | null, paraTras: boolean): T | null;
24
- interface AlvoDeEvento {
25
- addEventListener: (tipo: 'keydown', fn: (e: KeyboardEvent) => void, captura?: boolean) => void;
26
- removeEventListener?: (tipo: 'keydown', fn: (e: KeyboardEvent) => void, captura?: boolean) => void;
23
+ export declare function nextInTrap<T>(focusables: readonly T[], current: T | null, backwards: boolean): T | null;
24
+ interface KeydownTarget {
25
+ addEventListener: (kind: 'keydown', fn: (e: KeyboardEvent) => void, capture?: boolean) => void;
26
+ removeEventListener?: (kind: 'keydown', fn: (e: KeyboardEvent) => void, capture?: boolean) => void;
27
27
  }
28
28
  export interface FocusTrapCtx {
29
- /** O diálogo VISÍVEL mais alto da pilha, ou `null`. É o `topVisibleOverlay` de `ui/settings-panel`. */
30
- overlayDeCima: () => HTMLElement | null;
31
- /** Quem tem o foco agora — `() => document.activeElement`. Injetado: o project node não tem documento. */
32
- focoAtual: () => Element | null;
33
- /** Os focáveis DENTRO do diálogo, na ordem do documento e já filtrados por visibilidade. */
34
- focaveisDe: (dentro: HTMLElement) => HTMLElement[];
35
- win: AlvoDeEvento;
29
+ /** The highest VISIBLE dialog in the stack, or `null`. It is `ui/settings-panel`'s `topVisibleOverlay`. */
30
+ topOverlay: () => HTMLElement | null;
31
+ /** Who has focus now — `() => document.activeElement`. Injected: the node project has no document. */
32
+ currentFocus: () => Element | null;
33
+ /** The focusables INSIDE the dialog, in document order and already filtered by visibility. */
34
+ focusablesIn: (isInside: HTMLElement) => HTMLElement[];
35
+ win: KeydownTarget;
36
36
  }
37
37
  export interface FocusTrapApi {
38
- /** O manipulador, exposto para o teste o chamar sem instalar nada. */
39
- aoTeclar: (e: KeyboardEvent) => void;
40
- /** Instala na fase de CAPTURA, pelo mesmo motivo do `menu-nav`: ver a tecla antes de quem está por baixo. */
38
+ /** The handler, exposed so the test can call it without installing anything. */
39
+ onKeydown: (e: KeyboardEvent) => void;
40
+ /** Installs in the CAPTURE phase, for the same reason as `menu-nav`: see the key before whoever is underneath. */
41
41
  attach: () => void;
42
42
  /**
43
- * Desinstala.
43
+ * Uninstalls.
44
44
  *
45
- * ⚠️ ELE NASCEU DE UM TESTE QUE REPROVOU, e não de simetria: dois casos no mesmo ficheiro instalaram duas
46
- * armadilhas na mesma janela, e a primeira continuou a prender o foco durante o segundo — o caso «sem
47
- * diálogo aberto o Tab é do jogo» ficou vermelho por causa de uma armadilha que já devia ter saído.
48
- *
49
- * O que isso mostra vale fora do teste: uma armadilha que não se desinstala é um vazamento para qualquer
50
- * página que monte a engine duas vezes — o `demos`, que troca de jogo sem recarregar, é exatamente isso.
45
+ * ⚠️ A trap that does not uninstall is a leak for any page that mounts the engine twice — one that switches games
46
+ * without reloading is exactly that: the first trap keeps holding focus during the second.
51
47
  */
52
48
  detach: () => void;
53
49
  }
54
50
  export declare function initFocusTrap(ctx: FocusTrapCtx): FocusTrapApi;
55
51
  /**
56
- * Os focáveis de um contêiner, no navegador. Vive aqui e não na raiz para as duas raízes não escreverem duas
57
- * versões que divergiriam em silêncio — uma prenderia o foco e a outra deixaria escapar, no mesmo produto.
58
- *
59
- * ⚠️ A VISIBILIDADE É POR `getClientRects()`, e não por `offsetParent`.
60
- *
61
- * ⚠️ E A PRIMEIRA VERSÃO DESTE COMENTÁRIO ESTAVA ERRADA, o que vale mais registrar do que apagar: ele dizia
62
- * que `offsetParent` é `null` para «qualquer elemento em `position: fixed`». Não é — é `null` para o elemento
63
- * FIXO EM SI, e os descendentes dele devolvem o próprio contêiner. O teste de navegador reprovou a afirmação,
64
- * que é exatamente o que um teste tem de fazer com uma justificativa inventada.
52
+ * The focusables of a container, in the browser. It lives here and not in a root so that two roots do not write two
53
+ * versions that would drift silently — one trapping focus and the other letting it escape, in the same product.
65
54
  *
66
- * A razão verdadeira é mais simples e mais forte: `getClientRects()` responde *«isto desenha alguma caixa?»*,
67
- * o que cobre `display:none` em QUALQUER ancestral, elementos de tamanho zero e o caso do contêiner fixo —
68
- * sem que quem lê precise de saber em que casos `offsetParent` tem buracos.
55
+ * ⚠️ VISIBILITY IS BY `getClientRects()`, not by `offsetParent`: `getClientRects()` answers "does this draw any box?",
56
+ * which covers `display:none` on ANY ancestor, zero-size elements and the fixed-container case — without the reader
57
+ * needing to know where `offsetParent` has holes (it is `null` for a FIXED element itself, while its descendants return
58
+ * the container).
69
59
  */
70
- export declare function focaveisNoDom(dentro: HTMLElement): HTMLElement[];
60
+ export declare function focusablesInDom(isInside: HTMLElement): HTMLElement[];
71
61
  export {};
@@ -1,28 +1,25 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // ui/focus-trap.ts — A ARMADILHA DE FOCO. O segundo fio da issue #109, e o único dos três que não existia
3
- // EM LADO NENHUM da engine: os outros dois eram construídos e deixados desligados, este nunca foi escrito.
4
- // `ui/settings-panel.ts:17-19` diz isso por escrito — *"não instala armadilha de foco (o original também não
5
- // tem)"*.
2
+ // ui/focus-trap.ts — THE FOCUS TRAP (issue #109).
6
3
  //
7
- // ⚠️ E O DOCUMENTO JÁ PROMETE O CONTRÁRIO. Todo `.overlay__card` do `index.html` tem `aria-modal="true"`, o
8
- // que diz à tecnologia assistiva que o resto da página está inerte. O Tab não concorda: ele sai do diálogo e
9
- // entra no tabuleiro por baixo. É a pior forma de defeito de acessibilidade — não a ausência de uma promessa,
10
- // mas uma promessa que o teclado desmente. Quem usa leitor de tela sai para um jogo cujo estado não consegue
11
- // perceber, e não tem caminho de volta que perceba.
4
+ // ⚠️ THE DOCUMENT ALREADY PROMISES IT. Every `.overlay__card` carries `aria-modal="true"`, which tells assistive
5
+ // technology the rest of the page is inert. Without a trap, Tab disagrees: it leaves the dialog and enters the board
6
+ // underneath. That is the worst shape of accessibility defect — not the absence of a promise, but a promise the keyboard
7
+ // contradicts. A screen-reader user steps out into a game whose state they cannot perceive, with no way back they can
8
+ // perceive.
12
9
  //
13
- // ⚠️ SÓ INTERVÉM NAS BORDAS, e isso é decisão e não economia. Reimplementar a ordem de tabulação inteira
14
- // significaria reproduzir regras que o navegador já acerta — `tabindex` positivo, ordem do DOM em `shadow
15
- // root`, elementos que ficam focáveis por `contenteditable`. Uma armadilha que se mete no meio erra ao
16
- // caminhar; uma que só fecha o ciclo nas pontas não tem como errar o meio, porque não o toca.
10
+ // ⚠️ IT ONLY INTERVENES AT THE EDGES, and that is a decision, not thrift. Reimplementing the whole tab order would mean
11
+ // reproducing rules the browser already gets right — positive `tabindex`, DOM order in a shadow root, elements made
12
+ // focusable by `contenteditable`. A trap that steps into the middle errs while walking; one that only closes the cycle
13
+ // at the ends cannot err in the middle, because it does not touch it.
17
14
  //
18
- // A regra fica em UMA função pura (`proximoNaArmadilha`), testável no project node sem DOM nenhum. O que
19
- // precisa de navegador é só ler quem está focado e chamar `.focus()`.
15
+ // The rule lives in ONE pure function (`nextInTrap`), testable in the node project with no DOM. What needs a browser is
16
+ // only reading who is focused and calling `.focus()`.
20
17
  /**
21
- * O que conta como focável. Deliberadamente SEM `[contenteditable]` e sem `tabindex` positivo: os dois
22
- * existem, mas não aparecem em nenhum diálogo desta engine (conferido), e um seletor que promete mais do que
23
- * foi verificado é um seletor que mente na próxima revisão.
18
+ * What counts as focusable. Deliberately WITHOUT `[contenteditable]` and without positive `tabindex`: both exist, but
19
+ * appear in no dialog of this engine, and a selector that promises more than was verified is a selector that lies at
20
+ * the next review.
24
21
  */
25
- export const SELETOR_FOCAVEL = [
22
+ export const FOCUSABLE_SELECTOR = [
26
23
  'a[href]',
27
24
  'button:not([disabled])',
28
25
  'input:not([disabled])',
@@ -31,69 +28,63 @@ export const SELETOR_FOCAVEL = [
31
28
  '[tabindex]:not([tabindex="-1"])',
32
29
  ].join(',');
33
30
  /**
34
- * Para onde o foco tem de ir quando o Tab está prestes a sair do diálogo — ou `null` quando não há nada a
35
- * fazer e o navegador deve seguir sozinho.
31
+ * Where focus has to go when Tab is about to leave the dialog — or `null` when there is nothing to do and the browser
32
+ * should carry on by itself.
36
33
  *
37
- * Os quatro casos, e o terceiro é a razão de isto existir:
34
+ * The four cases, and the third is why this exists:
38
35
  *
39
- * 1. lista VAZIA → `null`. Um diálogo sem nada focável é um defeito do diálogo, e prender o foco nele
40
- * deixaria a criança sem saída nenhuma. Melhor deixar sair do que trancar num lugar mudo.
41
- * 2. o foco está no ÚLTIMO e vai para a frente → volta ao primeiro; no PRIMEIRO e vai para trás → vai ao
42
- * último. É o ciclo, que é o que «armadilha» quer dizer.
43
- * 3. ⚠️ o foco está FORA da lista → traz de volta. É o caso que os outros três não cobrem: o foco pode já
44
- * ter escapado antes de esta armadilha existir, ou por um clique no tabuleiro, ou porque o diálogo
45
- * abriu sem focar nada. Sem ele a armadilha só funciona para quem já estava dentro.
46
- * 4. o foco está no MEIO → `null`, e o navegador caminha. Ver o comentário do cabeçalho.
36
+ * 1. EMPTY list → `null`. A dialog with nothing focusable is the dialog's defect, and trapping focus in it would
37
+ * leave the child with no way out at all. Better to let it leave than to lock it in a mute place.
38
+ * 2. focus on the LAST going forward → back to the first; on the FIRST going backwards → to the last. That is the
39
+ * cycle, which is what "trap" means.
40
+ * 3. ⚠️ focus OUTSIDE the list → bring it back. The case the other three do not cover: focus may have escaped by a
41
+ * click on the board, or because the dialog opened without focusing anything. Without it the trap only works for
42
+ * whoever was already inside.
43
+ * 4. focus in the MIDDLE → `null`, and the browser walks. See the header.
47
44
  */
48
- export function proximoNaArmadilha(focaveis, atual, paraTras) {
49
- if (focaveis.length === 0)
45
+ export function nextInTrap(focusables, current, backwards) {
46
+ if (focusables.length === 0)
50
47
  return null;
51
- const primeiro = focaveis[0];
52
- const ultimo = focaveis[focaveis.length - 1];
53
- const i = atual === null ? -1 : focaveis.indexOf(atual);
48
+ const first = focusables[0];
49
+ const last = focusables[focusables.length - 1];
50
+ const i = current === null ? -1 : focusables.indexOf(current);
54
51
  if (i < 0)
55
- return paraTras ? ultimo : primeiro; // caso 3: o foco estava fora
56
- if (!paraTras && i === focaveis.length - 1)
57
- return primeiro;
58
- if (paraTras && i === 0)
59
- return ultimo;
60
- return null; // caso 4: o meio é do navegador
52
+ return backwards ? last : first; // case 3: focus was outside
53
+ if (!backwards && i === focusables.length - 1)
54
+ return first;
55
+ if (backwards && i === 0)
56
+ return last;
57
+ return null; // case 4: the middle belongs to the browser
61
58
  }
62
59
  export function initFocusTrap(ctx) {
63
- function aoTeclar(e) {
60
+ function trapKey(e) {
64
61
  if (e.key !== 'Tab')
65
62
  return;
66
- const dialogo = ctx.overlayDeCima();
63
+ const dialogo = ctx.topOverlay();
67
64
  if (!dialogo)
68
- return; // sem diálogo aberto o Tab é do jogo, e tem de continuar a ser
69
- const alvo = proximoNaArmadilha(ctx.focaveisDe(dialogo), ctx.focoAtual(), e.shiftKey);
70
- if (!alvo)
65
+ return; // with no dialog open, Tab belongs to the game, and has to stay that way
66
+ const target = nextInTrap(ctx.focusablesIn(dialogo), ctx.currentFocus(), e.shiftKey);
67
+ if (!target)
71
68
  return;
72
69
  e.preventDefault();
73
- alvo.focus();
70
+ target.focus();
74
71
  }
75
72
  return {
76
- aoTeclar,
77
- attach: () => ctx.win.addEventListener('keydown', aoTeclar, true),
78
- detach: () => ctx.win.removeEventListener?.('keydown', aoTeclar, true),
73
+ onKeydown: trapKey,
74
+ attach: () => ctx.win.addEventListener('keydown', trapKey, true),
75
+ detach: () => ctx.win.removeEventListener?.('keydown', trapKey, true),
79
76
  };
80
77
  }
81
78
  /**
82
- * Os focáveis de um contêiner, no navegador. Vive aqui e não na raiz para as duas raízes não escreverem duas
83
- * versões que divergiriam em silêncio — uma prenderia o foco e a outra deixaria escapar, no mesmo produto.
79
+ * The focusables of a container, in the browser. It lives here and not in a root so that two roots do not write two
80
+ * versions that would drift silently — one trapping focus and the other letting it escape, in the same product.
84
81
  *
85
- * ⚠️ A VISIBILIDADE É POR `getClientRects()`, e não por `offsetParent`.
86
- *
87
- * ⚠️ E A PRIMEIRA VERSÃO DESTE COMENTÁRIO ESTAVA ERRADA, o que vale mais registrar do que apagar: ele dizia
88
- * que `offsetParent` é `null` para «qualquer elemento em `position: fixed`». Não é — é `null` para o elemento
89
- * FIXO EM SI, e os descendentes dele devolvem o próprio contêiner. O teste de navegador reprovou a afirmação,
90
- * que é exatamente o que um teste tem de fazer com uma justificativa inventada.
91
- *
92
- * A razão verdadeira é mais simples e mais forte: `getClientRects()` responde *«isto desenha alguma caixa?»*,
93
- * o que cobre `display:none` em QUALQUER ancestral, elementos de tamanho zero e o caso do contêiner fixo —
94
- * sem que quem lê precise de saber em que casos `offsetParent` tem buracos.
82
+ * ⚠️ VISIBILITY IS BY `getClientRects()`, not by `offsetParent`: `getClientRects()` answers "does this draw any box?",
83
+ * which covers `display:none` on ANY ancestor, zero-size elements and the fixed-container case — without the reader
84
+ * needing to know where `offsetParent` has holes (it is `null` for a FIXED element itself, while its descendants return
85
+ * the container).
95
86
  */
96
- export function focaveisNoDom(dentro) {
97
- const todos = [...dentro.querySelectorAll(SELETOR_FOCAVEL)];
98
- return todos.filter((el) => !el.hidden && el.getClientRects().length > 0);
87
+ export function focusablesInDom(isInside) {
88
+ const candidates = [...isInside.querySelectorAll(FOCUSABLE_SELECTOR)];
89
+ return candidates.filter((el) => !el.hidden && el.getClientRects().length > 0);
99
90
  }
@@ -1,111 +1,200 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  /**
3
- * Uma fonte do catálogo. `fam` é o NOME DA FONTE — nome próprio, nunca traduzido. `d` guarda CHAVE i18n da
4
- * descrição, não o texto: mesma decisão de `VIZ_MODES` e `RM_LABEL`, e pelo mesmo motivo — uma tabela de
5
- * `const` com texto resolve uma vez, no import, e fica congelada no idioma do boot.
3
+ * A face's ROLE — the ADR-0012 amendment turned into data (issue #87).
4
+ *
5
+ * ⚠️ IT IS NOT THE SAME AS THE GROUP. The group (`sans`/`serif`/`hand`) is APPEARANCE and serves to read the list; the
6
+ * role is WHERE THE FACE MAY BE USED, and it is a rule:
7
+ *
8
+ * · `geral` — anywhere. The only ones the typography menu offers.
9
+ * · `caligrafica` — **only INSIDE school activities**, never in the HUD or menus, and so **not in the font menu**. They
10
+ * exist for the child to LEARN to read cursive, which is subject matter; using them as interface would hand the
11
+ * child the subject as an obstacle everywhere they only want to navigate.
12
+ * · `jogo` — the face the GAME uses in the HUD, the title and short arcade labels. Not in the menu either, for the same
13
+ * kind of reason: an 8-bit pixel face is drawn to say FEW words at a large size. As an interface face it contradicts
14
+ * the argument that makes Atkinson Hyperlegible the default — little differentiation between letters, a wide
15
+ * advance, no height variation. Right in a pixel-art game's HUD, wrong in a menu the child has to READ.
16
+ *
17
+ * ⚠️ AND THE CUT IS NOT THE `hand` GROUP. `pwbr` is there by appearance — it is the group's GENERAL face (ADR-0176) and
18
+ * often recommended for dyslexia. Removing it from the menu would remove a legitimately accessible option. The good
19
+ * definition is the list in #87 item 2, which names the handwriting faces by giving them a minimum size.
20
+ */
21
+ export type FontRole = 'geral' | 'caligrafica' | 'jogo';
22
+ /** One position of the eleventh button's typography cycle: the CASE and the FACE, together (ADR-0149 §1). */
23
+ export interface TypographyStep {
24
+ /** `upper` = UPPER CASE; `mixed` = upper and lower case. The values of `core/state.letterCase`. */
25
+ readonly letterCase: 'upper' | 'mixed';
26
+ /** The face's key in the catalogue. */
27
+ readonly font: string;
28
+ /**
29
+ * This position's size multiplier — 1 on the reading faces, **1.25 on the country hand** (ADR-0149 §1).
30
+ *
31
+ * 🔴 NOT A PREFERENCE, IT IS THE LEGIBILITY FLOOR ALREADY MEASURED. The Playwrite faces declare `minPx: 20` (ADR-0012
32
+ * amendment): below it the face stops being DIFFICULT and becomes ILLEGIBLE — difficulty is the exercise, illegibility
33
+ * is the child giving up. The document's base is 16 px, and 16 × 1.25 = 20 — the multiplier IS the floor, written as a
34
+ * ratio instead of a loose number.
35
+ */
36
+ readonly scale: number;
37
+ }
38
+ /** The country hand's increase. Named so the gate can assert it against `minPx` instead of repeating it. */
39
+ export declare const HANDWRITING_SCALE = 1.25;
40
+ /** The document's base, in px — the `font-size` of `html,body`. The floor comes from multiplying it by the scale. */
41
+ export declare const BASE_EM_PX = 16;
42
+ /**
43
+ * THE ELEVENTH BUTTON'S CYCLE — five positions, or six where the country teaches two hands (ADR-0149 §1, ADR-0150 §2).
44
+ *
45
+ * 🎯 EACH STEP CHANGES THE CASE **AND** THE FACE, and that is the whole decision: `letterCase` (`core/state`, ADR-0028)
46
+ * and the face are two settings, but Andika in upper case is ONE pedagogical choice of whoever teaches literacy, not
47
+ * two. A child should not have to know the model to make it.
48
+ *
49
+ * 📌 IT STARTS AT ATKINSON, which is position (c) and the project's default. The cycle is a ring: from it, one press goes
50
+ * to Lexend and the last goes back to the start.
51
+ *
52
+ * ⚠️ THE COUNTRY HAND MAY NOT EXIST — a tag with no region and a language outside the repertoire returns nothing. Then the
53
+ * cycle has FOUR positions, which is the right answer: one position fewer is better than one showing the hand of a
54
+ * country that is not that child's.
55
+ *
56
+ * 🔴 ARASAAC AND PCS ARE NOT POSITIONS, a decision and not an oversight: ADR-0155 §3 says to skip them — while the licence
57
+ * does not allow, the cycle neither stops on them nor announces them. A position existing only to be skipped would be
58
+ * data with no reader; they enter the day they work.
6
59
  */
60
+ export declare function typographyCycle(tag: string | null | undefined): readonly TypographyStep[];
61
+ /** The index where the cycle STARTS — position (c). Named so the gate can assert it without recounting. */
62
+ export declare const CYCLE_START = 2;
7
63
  /**
8
- * O PAPEL de uma face, e é a emenda do ADR-0012 (27/08) posta em dado (issue #87).
9
- *
10
- * ⚠️ NÃO É O MESMO QUE O GRUPO. O grupo (`sans`/`serif`/`hand`) é APARÊNCIA e serve para ler a lista; o papel
11
- * é ONDE A FACE PODE SER USADA, e é regra:
12
- *
13
- * · `geral` — em qualquer lugar. São as únicas que o menu de tipografia oferece.
14
- * · `caligrafica` — **só DENTRO das atividades escolares**, nunca no HUD nem nos menus, e por isso **não
15
- * aparecem no menu de fonte**. Elas existem para a criança APRENDER a ler letra cursiva, o que é matéria;
16
- * usá-las como interface é dar-lhe a matéria como obstáculo em todos os lugares onde ela só quer navegar.
17
- * · `jogo` — a face que o JOGO usa no HUD, no título e em rótulos curtos de arcade. Também não aparece no
18
- * menu, e pelo mesmo tipo de razão que as caligráficas: uma face de pixel de 8 bits é desenhada para
19
- * dizer POUCAS palavras em tamanho grande. Como face de interface ela contradiz o argumento que faz a
20
- * Atkinson Hyperlegible ser o padrão — pouca diferenciação entre letras, avanço largo, nenhuma variação
21
- * de altura. É certa no HUD de um jogo de pixel-art e errada num menu que a criança precisa de LER.
22
- *
23
- * ⚠️ E O CORTE NÃO É O GRUPO `hand`. O `comicneue` está lá por aparência — a face é de propósito geral e é
24
- * frequentemente recomendada para dislexia. Tirá-la do menu removeria uma opção legitimamente acessível. A
25
- * definição boa é a lista do item 2 da #87, que nomeia as caligráficas dando-lhes tamanho mínimo.
64
+ * The handwriting font keys for a BCP-47 tag — `pt-BR` → `['pwbr']`, `es-MX` → `['pwmx']`.
65
+ *
66
+ * ⚠️ IT READS THE REGION AND THEN THE LANGUAGE, in that order, and the forgotten case is the tag WITHOUT a region: `en`
67
+ * alone names no country, and falling back is the right answer — not an error, a child whose browser did not say where
68
+ * they are.
69
+ *
70
+ * 📌 It returns a LIST and not one face: where the country teaches two hands, both enter the cycle.
71
+ * 📌 It returns NOTHING for a language outside the repertoire, and nothing is sayable: the caller drops the position
72
+ * from the cycle instead of showing a hand that is nobody's.
73
+ */
74
+ export declare function handsForTag(tag: string | null | undefined): readonly string[];
75
+ /**
76
+ * A catalogue font. `fam` is the FONT'S NAME — a proper noun, never translated. `d` holds the i18n KEY of the description,
77
+ * not the text: the same decision as `VIZ_MODES` and `RM_LABEL`, for the same reason — a `const` table of text resolves
78
+ * once, on import, and stays frozen in the boot language.
26
79
  */
27
- export type FontRole = 'geral' | 'caligrafica' | 'jogo';
28
80
  export type FontItem = {
81
+ /** The face's `id` in `catalogo_tipografico.json` (ADR-0176): the key that holds it to the catalogue's status, layer, floor and coverage. */
82
+ id: string;
29
83
  k: string;
30
84
  fam: string;
31
85
  fb: string;
32
86
  d?: string;
33
87
  off?: string;
34
- /** Ausente = `geral`. Só as caligráficas se declaram, porque são a excepção. */
35
- papel?: FontRole;
36
88
  /**
37
- * O menor tamanho, em px, em que esta face ainda é legível (item 2 da #87, números do Dev).
89
+ * The i18n KEY of a sentence ALWAYS shown after the description — unlike `off`, which only speaks while the face is
90
+ * disabled. It is for a stack whose preferred faces the device may lack: the ronde's names the three to install, because
91
+ * without them the child sees Cookie, a related hand that is not the one taught at school (ADR-0154).
92
+ */
93
+ notice?: string;
94
+ /** Absent = `geral`. Only the handwriting faces declare it, because they are the exception. */
95
+ role?: FontRole;
96
+ /**
97
+ * The smallest size, in px, at which this face is still legible (#87 item 2, the Dev's numbers).
38
98
  *
39
- * ⚠️ Abaixo disto a face deixa de ser DIFÍCIL e passa a ser ILEGÍVEL, que são coisas diferentes: a
40
- * dificuldade é o exercício, a ilegibilidade é a criança a desistir. Por isso é gate e não recomendação.
99
+ * ⚠️ Below it the face stops being DIFFICULT and becomes ILLEGIBLE, which are different things: difficulty is the
100
+ * exercise, illegibility is the child giving up. That is why it is a gate and not a recommendation.
41
101
  */
42
102
  minPx?: number;
43
103
  };
44
- /** Um grupo do catálogo. `g` também guarda CHAVE ('font.group.sans'), pelo mesmo motivo. */
104
+ /** A catalogue group. `g` holds a KEY too ('font.group.sans'), for the same reason. */
45
105
  export type FontGroup = {
46
106
  g: string;
47
107
  items: FontItem[];
48
108
  };
109
+ /**
110
+ * THE TYPOGRAPHY PANEL'S KIT — every face a panel may list, grouped. The engine mounts no panel since ADR-0151 («quem escolhe a
111
+ * tipografia é o jogo»), and the kit stays for whoever mounts one (`ui/settings-typo`), because the eleventh button's cycle and
112
+ * the boot's stored choice go through its writer.
113
+ *
114
+ * 📌 MOST OF THESE FACES ARE THE FONT LIBRARY'S, not the engine's (ADR-0255): only the cycle's faces are packaged. A library face
115
+ * reaches a page when its cartridge declares the family in `uses.fonts` and the delivery carries it, so `faceAvailable` answers
116
+ * for it through the host's detector — a row whose family nobody declared is shown disabled, never offered and then drawn in the
117
+ * system font. Keeping the rows is what lets a game that declares its families offer them with no list of its own.
118
+ */
49
119
  export declare const FONT_GROUPS: FontGroup[];
50
- /** O papel de uma face; ausente no catálogo quer dizer `geral`. */
51
- export declare function papelDaFonte(it: FontItem): FontRole;
52
120
  /**
53
- * AS FAMÍLIAS QUE UMA FACE ACEITA, do `fam` que pode ser uma PILHA.
121
+ * How much larger the text is drawn with this face: enough to reach its `minPx` from the document's base, never smaller.
122
+ * A face whose catalogue floor is above the base (a display sans, the handwriting) is offered at that size, not under it
123
+ * (ADR-0176 §4, the catalogue's rule R2). The cycle's hand of the country is the same rule (`HANDWRITING_SCALE`).
124
+ */
125
+ export declare function faceScale(it: FontItem): number;
126
+ /** A face's role; absent in the catalogue means `geral`. */
127
+ export declare function fontRole(it: FontItem): FontRole;
128
+ /**
129
+ * THE FAMILIES A FACE ACCEPTS, from a `fam` that may be a STACK.
54
130
  *
55
- * 📌 A Ronde declara três (`'Ronde Script, OPTIFrench-Script, Merveille'`) porque qualquer uma delas serve —
56
- * são três desenhos da mesma letra de mão, e um adulto instala a que encontrar. As outras faces declaram uma
57
- * só, e para elas isto devolve uma lista de um.
131
+ * 📌 The ronde declares four (`'Ronde Script, OPTIFrench-Script, Merveille, Cookie'`): the three drawings of the same
132
+ * hand an adult may install, then the packaged fallback (ADR-0154). The other faces declare one, and for them this
133
+ * returns a list of one.
58
134
  */
59
- export declare function familiasDaFace(it: FontItem): string[];
135
+ export declare function faceFamilies(it: FontItem): string[];
60
136
  /**
61
- * ESTA FACE PODE SER USADA AGORA? — o `off` deixa de ser uma sentença e passa a ser uma CONDIÇÃO.
62
- *
63
- * O ADR-0012 decidiu que a opção da ronde «fica DESABILITADA enquanto nenhuma fonte estiver presente», e o
64
- * ADR-0108 §4 acrescentou o que ela diz. A palavra «enquanto» é o que esta função constrói: uma face `off`
65
- * volta a ficar disponível no instante em que o adulto instala uma das que a mensagem nomeia.
66
- *
67
- * ⚠️ O DETECTOR É INJECTADO, e nunca `document.fonts` lido daqui: este módulo é o catálogo, corre em node nos
68
- * gates, e ler um global do navegador aqui é o ACHADO 15 outra vez — o `srAlert` que rebentou o boot contra um
69
- * documento injectado.
70
- * 📌 E o PADRÃO É «não instalada», que é seguro por uma razão que não vale para todos os padrões deste
71
- * repositório: sem detector a opção fica desabilitada COM a mensagem, e a mensagem diz ao adulto exactamente
72
- * o que fazer. O silêncio não decide nada contra a criança — ele mantém o estado que já existia e que é
73
- * accionável. É o oposto do `seguraTeclas`, onde os dois lados do padrão erravam.
137
+ * A `fam` as a CSS `font-family` value — each family quoted on its own: `'Ronde Script','OPTIFrench-Script',…,'Cookie'`.
138
+ *
139
+ * 🔴 QUOTING THE WHOLE STRING ONCE NAMES ONE FAMILY THAT DOES NOT EXIST. `'Ronde Script, …, Cookie'` is a single name with
140
+ * commas in it, so the browser skips it and draws the generic fallback — the stack would never reach Cookie, and the
141
+ * fallback ADR-0154 decided would exist only in the catalogue. For a one-family `fam` the result is the same `'Inter'`.
74
142
  */
75
- export declare function faceDisponivel(it: FontItem, instalada?: (familia: string) => boolean): boolean;
76
- /** As faces que o MENU pode oferecer: só as gerais (emenda do ADR-0012). */
143
+ export declare function familyStack(fam: string): string;
144
+ /**
145
+ * THE FACES THE ENGINE DRAWS WITH ITSELF, by key — the eleventh button's cycle over EVERY hand a tag can pick (ADR-0149,
146
+ * ADR-0150). With the mathematics face (`MATHEMATICS_FAMILY`) they are the only faces packaged and precached (ADR-0255 §1); every
147
+ * other face of the kit is the font library's. `tests/what-fonts-the-package-carries.node.test.js` holds `fonts.css` to this list.
148
+ */
149
+ export declare const ENGINE_FACE_KEYS: readonly string[];
150
+ /** The face the engine draws mathematics in (`--font-math` in `style.css`): packaged, never a typography choice (ADR-0012). */
151
+ export declare const MATHEMATICS_FAMILY = "Atkinson Hyperlegible Mono";
152
+ /**
153
+ * CAN THIS FACE BE USED NOW? — `off` stops being a sentence and becomes a CONDITION.
154
+ *
155
+ * An engine face is always there: it is packaged and precached (ADR-0255 §1). Any other face is used WHILE one of its families
156
+ * is present — a library family its cartridge declared in `uses.fonts` (the root's detector answers for those), or, for an `off`
157
+ * face, one the adult installed from the ones its message names (ADR-0012's «enquanto»). The ronde's stack ends in Cookie, a
158
+ * library family, so it is available where the game declares Cookie (ADR-0154, ADR-0255).
159
+ *
160
+ * ⚠️ THE DETECTOR IS INJECTED, and `document.fonts` is never read here: this module is the catalogue, it runs in node in
161
+ * the gates, and reading a browser global here would be a boot waiting to crash against an injected document.
162
+ * 📌 And the DEFAULT is not present, which is safe: with no detector a library row stays disabled, never offered and then drawn
163
+ * in the system font, and an `off` row keeps the message that tells the adult exactly what to do.
164
+ */
165
+ export declare function faceAvailable(it: FontItem, installed?: (family: string) => boolean): boolean;
166
+ /** The faces the MENU may offer: only the general ones (ADR-0012 amendment). */
77
167
  export declare const OFERECIVEIS: FontItem[];
168
+ /**
169
+ * The catalogue by key. BUILT IN ONE EXPRESSION and never filled after it (ADR-0232 D4): the table was an empty object the
170
+ * module wrote into at import, which the code-health measure reads as module state. The last item with a key wins, as it did.
171
+ */
78
172
  export declare const FONT_BY_KEY: Record<string, FontItem>;
173
+ /** The families `vendor/fonts.css` declares — the engine's faces and the mathematics face. A cartridge never declares these. */
174
+ export declare const ENGINE_FAMILIES: ReadonlySet<string>;
79
175
  /** Narrow store shape these need — lets a caller inject a fake without touching real storage. */
80
176
  export interface FontStore {
81
177
  get(key: string, fallback: string | null): string | null;
82
178
  set(key: string, v: string): void;
83
179
  }
84
- export declare const FONT_KEY = "incl_font_k";
85
- export declare const FONT_KEY_LEGACY = "incl_fonte";
86
180
  /**
87
- * A fonte de fábrica, com nome. Atkinson Hyperlegible foi desenhada pelo Braille Institute justamente para
88
- * quem tem baixa visão — distingue as formas que mais se confundem (I/l/1, O/0). É por isso que ela é o padrão
89
- * e não uma preferência estética, e é por isso que o "restaurar padrões" da tipografia (ADR-0028) volta para
90
- * cá: o caminho de volta de um menu de acessibilidade tem que terminar na escolha mais legível, não numa
91
- * qualquer. Usada em DOIS lugares — o fim da cadeia de boot logo abaixo e o reset do painel —, e uma constante
92
- * porque duas cópias de um padrão são duas chances de o reset devolver algo que o jogo nunca usou.
181
+ * The factory font, named. Atkinson Hyperlegible was designed by the Braille Institute precisely for low vision — it
182
+ * tells apart the shapes most often confused (I/l/1, O/0). That is why it is the default and not an aesthetic preference,
183
+ * and why typography's reset (ADR-0028) returns here: the way back from an accessibility menu has to end at the most
184
+ * legible choice, not at any one. Used in TWO places — the end of the boot chain just below and the panel's reset —, and
185
+ * a constant because two copies of a default are two chances for the reset to return something the game never used.
93
186
  */
94
187
  export declare const DEFAULT_FONT_KEY = "atkinson";
95
188
  /**
96
189
  * Boot choice: validated persisted key (ignores .off fonts) -> legacy-key migration -> DEFAULT_FONT_KEY.
97
190
  *
98
- * ⚠️ E UMA CALIGRÁFICA GUARDADA VOLTA AO PADRÃO (issue #87, 2026-09-07). Antes da emenda do ADR-0012 o menu
99
- * oferecia as sete caligráficas, então há crianças com `pinyon` ou `ufmag` guardados — e o valor salvo
100
- * continua a ser escolha delas, que não é nossa para desfazer sem motivo. O motivo existe: a emenda diz que
101
- * uma caligráfica **não pode ser a face da interface**, e o menu deixou de a oferecer. Deixá-la valer daria
102
- * uma interface inteira em letra cursiva a quem já não tem como sair dela pelo menu — uma armadilha, e das
103
- * silenciosas.
191
+ * ⚠️ AND A STORED HANDWRITING FACE GOES BACK TO THE DEFAULT (issue #87). A child may have one stored from when the menu
192
+ * offered them, and a stored value is their choice, not ours to undo without a reason. The reason exists: the ADR-0012
193
+ * amendment says a handwriting face **cannot be the interface face**, and the menu no longer offers it. Letting it stand
194
+ * would give a whole interface in cursive to someone with no way out of it through the menu — a trap, and a silent one.
104
195
  *
105
- * ⚠️ E UMA CHAVE APAGADA TAMBÉM VOLTA, pelo mesmo caminho: as quatro faces que saíram do roster já não estão
106
- * no `FONT_BY_KEY`, então quem tinha `greatvibes` guardado cai no padrão em vez de ficar sem face nenhuma.
196
+ * ⚠️ AND A DELETED KEY GOES BACK TOO, by the same path: a face no longer in `FONT_BY_KEY` falls back to the default
197
+ * instead of leaving the child with no face at all.
107
198
  */
108
199
  export declare function resolveFontKey(s: FontStore): string;
109
200
  export declare function persistFontKey(s: FontStore, k: string): void;
110
- export declare function loadFontKey(): string;
111
- export declare function saveFontKey(k: string): void;