@the-inclusionist/engine 9.0.0 → 10.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 (756) hide show
  1. package/README.md +89 -78
  2. package/app/css/style.css +584 -374
  3. package/app/public/vendor/fonts/bitter-var-ext.woff2 +0 -0
  4. package/app/public/vendor/fonts/bitter-var.woff2 +0 -0
  5. package/app/public/vendor/fonts/bodonimoda-var-ext.woff2 +0 -0
  6. package/app/public/vendor/fonts/bodonimoda-var.woff2 +0 -0
  7. package/app/public/vendor/fonts/cat-abril_fatface-400-ext.woff2 +0 -0
  8. package/app/public/vendor/fonts/cat-abril_fatface-400.woff2 +0 -0
  9. package/app/public/vendor/fonts/cat-adlam_display-400-ext.woff2 +0 -0
  10. package/app/public/vendor/fonts/cat-adlam_display-400.woff2 +0 -0
  11. package/app/public/vendor/fonts/cat-agu_display-400-ext.woff2 +0 -0
  12. package/app/public/vendor/fonts/cat-agu_display-400.woff2 +0 -0
  13. package/app/public/vendor/fonts/cat-alfa_slab_one-400-ext.woff2 +0 -0
  14. package/app/public/vendor/fonts/cat-alfa_slab_one-400.woff2 +0 -0
  15. package/app/public/vendor/fonts/cat-are_you_serious-400-ext.woff2 +0 -0
  16. package/app/public/vendor/fonts/cat-are_you_serious-400.woff2 +0 -0
  17. package/app/public/vendor/fonts/cat-asimovian-400-ext.woff2 +0 -0
  18. package/app/public/vendor/fonts/cat-asimovian-400.woff2 +0 -0
  19. package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400-ext.woff2 +0 -0
  20. package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400.woff2 +0 -0
  21. package/app/public/vendor/fonts/cat-bakbak_one-400-ext.woff2 +0 -0
  22. package/app/public/vendor/fonts/cat-bakbak_one-400.woff2 +0 -0
  23. package/app/public/vendor/fonts/cat-bangers-400-ext.woff2 +0 -0
  24. package/app/public/vendor/fonts/cat-bangers-400.woff2 +0 -0
  25. package/app/public/vendor/fonts/cat-barriecito-400-ext.woff2 +0 -0
  26. package/app/public/vendor/fonts/cat-barriecito-400.woff2 +0 -0
  27. package/app/public/vendor/fonts/cat-berkshire_swash-400-ext.woff2 +0 -0
  28. package/app/public/vendor/fonts/cat-berkshire_swash-400.woff2 +0 -0
  29. package/app/public/vendor/fonts/cat-bevan-400-ext.woff2 +0 -0
  30. package/app/public/vendor/fonts/cat-bevan-400.woff2 +0 -0
  31. package/app/public/vendor/fonts/cat-bitcount-400-ext.woff2 +0 -0
  32. package/app/public/vendor/fonts/cat-bitcount-400.woff2 +0 -0
  33. package/app/public/vendor/fonts/cat-bowlby_one_sc-400-ext.woff2 +0 -0
  34. package/app/public/vendor/fonts/cat-bowlby_one_sc-400.woff2 +0 -0
  35. package/app/public/vendor/fonts/cat-bungee_shade-400-ext.woff2 +0 -0
  36. package/app/public/vendor/fonts/cat-bungee_shade-400.woff2 +0 -0
  37. package/app/public/vendor/fonts/cat-charm-400-ext.woff2 +0 -0
  38. package/app/public/vendor/fonts/cat-charm-400.woff2 +0 -0
  39. package/app/public/vendor/fonts/cat-charm-700-ext.woff2 +0 -0
  40. package/app/public/vendor/fonts/cat-charm-700.woff2 +0 -0
  41. package/app/public/vendor/fonts/cat-cherry_bomb_one-400-ext.woff2 +0 -0
  42. package/app/public/vendor/fonts/cat-cherry_bomb_one-400.woff2 +0 -0
  43. package/app/public/vendor/fonts/cat-chokokutai-400-ext.woff2 +0 -0
  44. package/app/public/vendor/fonts/cat-chokokutai-400.woff2 +0 -0
  45. package/app/public/vendor/fonts/cat-chonburi-400-ext.woff2 +0 -0
  46. package/app/public/vendor/fonts/cat-chonburi-400.woff2 +0 -0
  47. package/app/public/vendor/fonts/cat-climate_crisis-400-ext.woff2 +0 -0
  48. package/app/public/vendor/fonts/cat-climate_crisis-400.woff2 +0 -0
  49. package/app/public/vendor/fonts/cat-cookie-400.woff2 +0 -0
  50. package/app/public/vendor/fonts/cat-dela_gothic_one-400-ext.woff2 +0 -0
  51. package/app/public/vendor/fonts/cat-dela_gothic_one-400.woff2 +0 -0
  52. package/app/public/vendor/fonts/cat-fascinate_inline-400-ext.woff2 +0 -0
  53. package/app/public/vendor/fonts/cat-fascinate_inline-400.woff2 +0 -0
  54. package/app/public/vendor/fonts/cat-ga_maamli-400-ext.woff2 +0 -0
  55. package/app/public/vendor/fonts/cat-ga_maamli-400.woff2 +0 -0
  56. package/app/public/vendor/fonts/cat-itim-400-ext.woff2 +0 -0
  57. package/app/public/vendor/fonts/cat-itim-400.woff2 +0 -0
  58. package/app/public/vendor/fonts/cat-jacquard_24-400-ext.woff2 +0 -0
  59. package/app/public/vendor/fonts/cat-jacquard_24-400.woff2 +0 -0
  60. package/app/public/vendor/fonts/cat-kablammo-400-ext.woff2 +0 -0
  61. package/app/public/vendor/fonts/cat-kablammo-400.woff2 +0 -0
  62. package/app/public/vendor/fonts/cat-kalam-400-ext.woff2 +0 -0
  63. package/app/public/vendor/fonts/cat-kalam-400.woff2 +0 -0
  64. package/app/public/vendor/fonts/cat-kalam-700-ext.woff2 +0 -0
  65. package/app/public/vendor/fonts/cat-kalam-700.woff2 +0 -0
  66. package/app/public/vendor/fonts/cat-katibeh-400-ext.woff2 +0 -0
  67. package/app/public/vendor/fonts/cat-katibeh-400.woff2 +0 -0
  68. package/app/public/vendor/fonts/cat-lemonada-400-ext.woff2 +0 -0
  69. package/app/public/vendor/fonts/cat-lemonada-400.woff2 +0 -0
  70. package/app/public/vendor/fonts/cat-lilita_one-400-ext.woff2 +0 -0
  71. package/app/public/vendor/fonts/cat-lilita_one-400.woff2 +0 -0
  72. package/app/public/vendor/fonts/cat-lobster-400-ext.woff2 +0 -0
  73. package/app/public/vendor/fonts/cat-lobster-400.woff2 +0 -0
  74. package/app/public/vendor/fonts/cat-luckiest_guy-400-ext.woff2 +0 -0
  75. package/app/public/vendor/fonts/cat-luckiest_guy-400.woff2 +0 -0
  76. package/app/public/vendor/fonts/cat-marhey-400-ext.woff2 +0 -0
  77. package/app/public/vendor/fonts/cat-marhey-400.woff2 +0 -0
  78. package/app/public/vendor/fonts/cat-modak-400-ext.woff2 +0 -0
  79. package/app/public/vendor/fonts/cat-modak-400.woff2 +0 -0
  80. package/app/public/vendor/fonts/cat-momo_signature-400-ext.woff2 +0 -0
  81. package/app/public/vendor/fonts/cat-momo_signature-400.woff2 +0 -0
  82. package/app/public/vendor/fonts/cat-monofett-400-ext.woff2 +0 -0
  83. package/app/public/vendor/fonts/cat-monofett-400.woff2 +0 -0
  84. package/app/public/vendor/fonts/cat-monomakh-400-ext.woff2 +0 -0
  85. package/app/public/vendor/fonts/cat-monomakh-400.woff2 +0 -0
  86. package/app/public/vendor/fonts/cat-monoton-400-ext.woff2 +0 -0
  87. package/app/public/vendor/fonts/cat-monoton-400.woff2 +0 -0
  88. package/app/public/vendor/fonts/cat-nerko_one-400-ext.woff2 +0 -0
  89. package/app/public/vendor/fonts/cat-nerko_one-400.woff2 +0 -0
  90. package/app/public/vendor/fonts/cat-noto_sans_adlam-400-ext.woff2 +0 -0
  91. package/app/public/vendor/fonts/cat-noto_sans_adlam-400.woff2 +0 -0
  92. package/app/public/vendor/fonts/cat-noto_sans_arabic-400-ext.woff2 +0 -0
  93. package/app/public/vendor/fonts/cat-noto_sans_arabic-400.woff2 +0 -0
  94. package/app/public/vendor/fonts/cat-noto_sans_devanagari-400-ext.woff2 +0 -0
  95. package/app/public/vendor/fonts/cat-noto_sans_devanagari-400.woff2 +0 -0
  96. package/app/public/vendor/fonts/cat-noto_sans_hebrew-400-ext.woff2 +0 -0
  97. package/app/public/vendor/fonts/cat-noto_sans_hebrew-400.woff2 +0 -0
  98. package/app/public/vendor/fonts/cat-noto_sans_jp-400-ext.woff2 +0 -0
  99. package/app/public/vendor/fonts/cat-noto_sans_jp-400.woff2 +0 -0
  100. package/app/public/vendor/fonts/cat-noto_sans_khmer-400-ext.woff2 +0 -0
  101. package/app/public/vendor/fonts/cat-noto_sans_khmer-400.woff2 +0 -0
  102. package/app/public/vendor/fonts/cat-noto_sans_kr-400-ext.woff2 +0 -0
  103. package/app/public/vendor/fonts/cat-noto_sans_kr-400.woff2 +0 -0
  104. package/app/public/vendor/fonts/cat-noto_sans_sc-400-ext.woff2 +0 -0
  105. package/app/public/vendor/fonts/cat-noto_sans_sc-400.woff2 +0 -0
  106. package/app/public/vendor/fonts/cat-noto_sans_thai-400-ext.woff2 +0 -0
  107. package/app/public/vendor/fonts/cat-noto_sans_thai-400.woff2 +0 -0
  108. package/app/public/vendor/fonts/cat-ole-400-ext.woff2 +0 -0
  109. package/app/public/vendor/fonts/cat-ole-400.woff2 +0 -0
  110. package/app/public/vendor/fonts/cat-pacifico-400-ext.woff2 +0 -0
  111. package/app/public/vendor/fonts/cat-pacifico-400.woff2 +0 -0
  112. package/app/public/vendor/fonts/cat-patrick_hand-400-ext.woff2 +0 -0
  113. package/app/public/vendor/fonts/cat-patrick_hand-400.woff2 +0 -0
  114. package/app/public/vendor/fonts/cat-petit_formal_script-400-ext.woff2 +0 -0
  115. package/app/public/vendor/fonts/cat-petit_formal_script-400.woff2 +0 -0
  116. package/app/public/vendor/fonts/cat-pixelify_sans-400-ext.woff2 +0 -0
  117. package/app/public/vendor/fonts/cat-pixelify_sans-400.woff2 +0 -0
  118. package/app/public/vendor/fonts/cat-plaster-400-ext.woff2 +0 -0
  119. package/app/public/vendor/fonts/cat-plaster-400.woff2 +0 -0
  120. package/app/public/vendor/fonts/cat-playwrite_ar_guides-400-0.woff2 +0 -0
  121. package/app/public/vendor/fonts/cat-playwrite_at-400-0.woff2 +0 -0
  122. package/app/public/vendor/fonts/cat-playwrite_at_guides-400-0.woff2 +0 -0
  123. package/app/public/vendor/fonts/cat-playwrite_au_nsw-400-0.woff2 +0 -0
  124. package/app/public/vendor/fonts/cat-playwrite_au_nsw_guides-400-0.woff2 +0 -0
  125. package/app/public/vendor/fonts/cat-playwrite_au_qld-400-0.woff2 +0 -0
  126. package/app/public/vendor/fonts/cat-playwrite_au_qld_guides-400-0.woff2 +0 -0
  127. package/app/public/vendor/fonts/cat-playwrite_au_sa-400-0.woff2 +0 -0
  128. package/app/public/vendor/fonts/cat-playwrite_au_sa_guides-400-0.woff2 +0 -0
  129. package/app/public/vendor/fonts/cat-playwrite_au_tas-400-0.woff2 +0 -0
  130. package/app/public/vendor/fonts/cat-playwrite_au_tas_guides-400-0.woff2 +0 -0
  131. package/app/public/vendor/fonts/cat-playwrite_au_vic-400-0.woff2 +0 -0
  132. package/app/public/vendor/fonts/cat-playwrite_au_vic_guides-400-0.woff2 +0 -0
  133. package/app/public/vendor/fonts/cat-playwrite_be_vlg-400-0.woff2 +0 -0
  134. package/app/public/vendor/fonts/cat-playwrite_be_vlg_guides-400-0.woff2 +0 -0
  135. package/app/public/vendor/fonts/cat-playwrite_be_wal-400-0.woff2 +0 -0
  136. package/app/public/vendor/fonts/cat-playwrite_be_wal_guides-400-0.woff2 +0 -0
  137. package/app/public/vendor/fonts/cat-playwrite_br_guides-400-0.woff2 +0 -0
  138. package/app/public/vendor/fonts/cat-playwrite_ca_guides-400-0.woff2 +0 -0
  139. package/app/public/vendor/fonts/cat-playwrite_cl_guides-400-0.woff2 +0 -0
  140. package/app/public/vendor/fonts/cat-playwrite_co_guides-400-0.woff2 +0 -0
  141. package/app/public/vendor/fonts/cat-playwrite_cu_guides-400-0.woff2 +0 -0
  142. package/app/public/vendor/fonts/cat-playwrite_cz-400-0.woff2 +0 -0
  143. package/app/public/vendor/fonts/cat-playwrite_cz_guides-400-0.woff2 +0 -0
  144. package/app/public/vendor/fonts/cat-playwrite_de_grund-400-0.woff2 +0 -0
  145. package/app/public/vendor/fonts/cat-playwrite_de_grund_guides-400-0.woff2 +0 -0
  146. package/app/public/vendor/fonts/cat-playwrite_de_la-400-0.woff2 +0 -0
  147. package/app/public/vendor/fonts/cat-playwrite_de_la_guides-400-0.woff2 +0 -0
  148. package/app/public/vendor/fonts/cat-playwrite_de_sas-400-0.woff2 +0 -0
  149. package/app/public/vendor/fonts/cat-playwrite_de_sas_guides-400-0.woff2 +0 -0
  150. package/app/public/vendor/fonts/cat-playwrite_de_va-400-0.woff2 +0 -0
  151. package/app/public/vendor/fonts/cat-playwrite_de_va_guides-400-0.woff2 +0 -0
  152. package/app/public/vendor/fonts/cat-playwrite_dk_loopet-400-0.woff2 +0 -0
  153. package/app/public/vendor/fonts/cat-playwrite_dk_loopet_guides-400-0.woff2 +0 -0
  154. package/app/public/vendor/fonts/cat-playwrite_dk_uloopet-400-0.woff2 +0 -0
  155. package/app/public/vendor/fonts/cat-playwrite_dk_uloopet_guides-400-0.woff2 +0 -0
  156. package/app/public/vendor/fonts/cat-playwrite_es_deco_guides-400-0.woff2 +0 -0
  157. package/app/public/vendor/fonts/cat-playwrite_es_guides-400-0.woff2 +0 -0
  158. package/app/public/vendor/fonts/cat-playwrite_fr_moderne-400-0.woff2 +0 -0
  159. package/app/public/vendor/fonts/cat-playwrite_fr_moderne_guides-400-0.woff2 +0 -0
  160. package/app/public/vendor/fonts/cat-playwrite_fr_trad-400-0.woff2 +0 -0
  161. package/app/public/vendor/fonts/cat-playwrite_fr_trad_guides-400-0.woff2 +0 -0
  162. package/app/public/vendor/fonts/cat-playwrite_gb_j_guides-400-0.woff2 +0 -0
  163. package/app/public/vendor/fonts/cat-playwrite_gb_s_guides-400-0.woff2 +0 -0
  164. package/app/public/vendor/fonts/cat-playwrite_hr-400-0.woff2 +0 -0
  165. package/app/public/vendor/fonts/cat-playwrite_hr_guides-400-0.woff2 +0 -0
  166. package/app/public/vendor/fonts/cat-playwrite_hr_lijeva-400-0.woff2 +0 -0
  167. package/app/public/vendor/fonts/cat-playwrite_hr_lijeva_guides-400-0.woff2 +0 -0
  168. package/app/public/vendor/fonts/cat-playwrite_hu-400-0.woff2 +0 -0
  169. package/app/public/vendor/fonts/cat-playwrite_hu_guides-400-0.woff2 +0 -0
  170. package/app/public/vendor/fonts/cat-playwrite_id-400-0.woff2 +0 -0
  171. package/app/public/vendor/fonts/cat-playwrite_id_guides-400-0.woff2 +0 -0
  172. package/app/public/vendor/fonts/cat-playwrite_ie-400-0.woff2 +0 -0
  173. package/app/public/vendor/fonts/cat-playwrite_ie_guides-400-0.woff2 +0 -0
  174. package/app/public/vendor/fonts/cat-playwrite_in-400-0.woff2 +0 -0
  175. package/app/public/vendor/fonts/cat-playwrite_in_guides-400-0.woff2 +0 -0
  176. package/app/public/vendor/fonts/cat-playwrite_is-400-0.woff2 +0 -0
  177. package/app/public/vendor/fonts/cat-playwrite_is_guides-400-0.woff2 +0 -0
  178. package/app/public/vendor/fonts/cat-playwrite_it_moderna-400-0.woff2 +0 -0
  179. package/app/public/vendor/fonts/cat-playwrite_it_moderna_guides-400-0.woff2 +0 -0
  180. package/app/public/vendor/fonts/cat-playwrite_it_trad-400-0.woff2 +0 -0
  181. package/app/public/vendor/fonts/cat-playwrite_it_trad_guides-400-0.woff2 +0 -0
  182. package/app/public/vendor/fonts/cat-playwrite_mx_guides-400-0.woff2 +0 -0
  183. package/app/public/vendor/fonts/cat-playwrite_ng_modern-400-0.woff2 +0 -0
  184. package/app/public/vendor/fonts/cat-playwrite_ng_modern_guides-400-0.woff2 +0 -0
  185. package/app/public/vendor/fonts/cat-playwrite_nl-400-0.woff2 +0 -0
  186. package/app/public/vendor/fonts/cat-playwrite_nl_guides-400-0.woff2 +0 -0
  187. package/app/public/vendor/fonts/cat-playwrite_no-400-0.woff2 +0 -0
  188. package/app/public/vendor/fonts/cat-playwrite_no_guides-400-0.woff2 +0 -0
  189. package/app/public/vendor/fonts/cat-playwrite_nz-400-0.woff2 +0 -0
  190. package/app/public/vendor/fonts/cat-playwrite_nz_basic-400-0.woff2 +0 -0
  191. package/app/public/vendor/fonts/cat-playwrite_nz_basic_guides-400-0.woff2 +0 -0
  192. package/app/public/vendor/fonts/cat-playwrite_nz_guides-400-0.woff2 +0 -0
  193. package/app/public/vendor/fonts/cat-playwrite_pe_guides-400-0.woff2 +0 -0
  194. package/app/public/vendor/fonts/cat-playwrite_pl-400-0.woff2 +0 -0
  195. package/app/public/vendor/fonts/cat-playwrite_pl_guides-400-0.woff2 +0 -0
  196. package/app/public/vendor/fonts/cat-playwrite_pt_guides-400-0.woff2 +0 -0
  197. package/app/public/vendor/fonts/cat-playwrite_ro-400-0.woff2 +0 -0
  198. package/app/public/vendor/fonts/cat-playwrite_ro_guides-400-0.woff2 +0 -0
  199. package/app/public/vendor/fonts/cat-playwrite_sk-400-0.woff2 +0 -0
  200. package/app/public/vendor/fonts/cat-playwrite_sk_guides-400-0.woff2 +0 -0
  201. package/app/public/vendor/fonts/cat-playwrite_tz-400-0.woff2 +0 -0
  202. package/app/public/vendor/fonts/cat-playwrite_tz_guides-400-0.woff2 +0 -0
  203. package/app/public/vendor/fonts/cat-playwrite_us_modern_guides-400-0.woff2 +0 -0
  204. package/app/public/vendor/fonts/cat-playwrite_us_trad_guides-400-0.woff2 +0 -0
  205. package/app/public/vendor/fonts/cat-playwrite_vn-400-0.woff2 +0 -0
  206. package/app/public/vendor/fonts/cat-playwrite_vn_guides-400-0.woff2 +0 -0
  207. package/app/public/vendor/fonts/cat-playwrite_za-400-0.woff2 +0 -0
  208. package/app/public/vendor/fonts/cat-playwrite_za_guides-400-0.woff2 +0 -0
  209. package/app/public/vendor/fonts/cat-potta_one-400-ext.woff2 +0 -0
  210. package/app/public/vendor/fonts/cat-potta_one-400.woff2 +0 -0
  211. package/app/public/vendor/fonts/cat-ranchers-400-ext.woff2 +0 -0
  212. package/app/public/vendor/fonts/cat-ranchers-400.woff2 +0 -0
  213. package/app/public/vendor/fonts/cat-ranga-400-ext.woff2 +0 -0
  214. package/app/public/vendor/fonts/cat-ranga-400.woff2 +0 -0
  215. package/app/public/vendor/fonts/cat-ranga-700-ext.woff2 +0 -0
  216. package/app/public/vendor/fonts/cat-ranga-700.woff2 +0 -0
  217. package/app/public/vendor/fonts/cat-risque-400-ext.woff2 +0 -0
  218. package/app/public/vendor/fonts/cat-risque-400.woff2 +0 -0
  219. package/app/public/vendor/fonts/cat-rowdies-400-ext.woff2 +0 -0
  220. package/app/public/vendor/fonts/cat-rowdies-400.woff2 +0 -0
  221. package/app/public/vendor/fonts/cat-rowdies-700-ext.woff2 +0 -0
  222. package/app/public/vendor/fonts/cat-rowdies-700.woff2 +0 -0
  223. package/app/public/vendor/fonts/cat-ruge_boogie-400-ext.woff2 +0 -0
  224. package/app/public/vendor/fonts/cat-ruge_boogie-400.woff2 +0 -0
  225. package/app/public/vendor/fonts/cat-ruslan_display-400-ext.woff2 +0 -0
  226. package/app/public/vendor/fonts/cat-ruslan_display-400.woff2 +0 -0
  227. package/app/public/vendor/fonts/cat-sacramento-400-ext.woff2 +0 -0
  228. package/app/public/vendor/fonts/cat-sacramento-400.woff2 +0 -0
  229. package/app/public/vendor/fonts/cat-sancreek-400-ext.woff2 +0 -0
  230. package/app/public/vendor/fonts/cat-sancreek-400.woff2 +0 -0
  231. package/app/public/vendor/fonts/cat-sankofa_display-400-ext.woff2 +0 -0
  232. package/app/public/vendor/fonts/cat-sankofa_display-400.woff2 +0 -0
  233. package/app/public/vendor/fonts/cat-sedgwick_ave_display-400-ext.woff2 +0 -0
  234. package/app/public/vendor/fonts/cat-sedgwick_ave_display-400.woff2 +0 -0
  235. package/app/public/vendor/fonts/cat-shantell_sans-400-ext.woff2 +0 -0
  236. package/app/public/vendor/fonts/cat-shantell_sans-400.woff2 +0 -0
  237. package/app/public/vendor/fonts/cat-smokum-400-ext.woff2 +0 -0
  238. package/app/public/vendor/fonts/cat-smokum-400.woff2 +0 -0
  239. package/app/public/vendor/fonts/cat-solitreo-400-ext.woff2 +0 -0
  240. package/app/public/vendor/fonts/cat-solitreo-400.woff2 +0 -0
  241. package/app/public/vendor/fonts/cat-spicy_rice-400-ext.woff2 +0 -0
  242. package/app/public/vendor/fonts/cat-spicy_rice-400.woff2 +0 -0
  243. package/app/public/vendor/fonts/cat-sriracha-400-ext.woff2 +0 -0
  244. package/app/public/vendor/fonts/cat-sriracha-400.woff2 +0 -0
  245. package/app/public/vendor/fonts/cat-srisakdi-400-ext.woff2 +0 -0
  246. package/app/public/vendor/fonts/cat-srisakdi-400.woff2 +0 -0
  247. package/app/public/vendor/fonts/cat-srisakdi-700-ext.woff2 +0 -0
  248. package/app/public/vendor/fonts/cat-srisakdi-700.woff2 +0 -0
  249. package/app/public/vendor/fonts/cat-stix_two_math-400-0.woff2 +0 -0
  250. package/app/public/vendor/fonts/cat-tillana-400-ext.woff2 +0 -0
  251. package/app/public/vendor/fonts/cat-tillana-400.woff2 +0 -0
  252. package/app/public/vendor/fonts/cat-tillana-700-ext.woff2 +0 -0
  253. package/app/public/vendor/fonts/cat-tillana-700.woff2 +0 -0
  254. package/app/public/vendor/fonts/cat-titan_one-400-ext.woff2 +0 -0
  255. package/app/public/vendor/fonts/cat-titan_one-400.woff2 +0 -0
  256. package/app/public/vendor/fonts/cat-yatra_one-400-ext.woff2 +0 -0
  257. package/app/public/vendor/fonts/cat-yatra_one-400.woff2 +0 -0
  258. package/app/public/vendor/fonts/cat-yomogi-400-ext.woff2 +0 -0
  259. package/app/public/vendor/fonts/cat-yomogi-400.woff2 +0 -0
  260. package/app/public/vendor/fonts/dmserifdisplay-400-ext.woff2 +0 -0
  261. package/app/public/vendor/fonts/dmserifdisplay-400.woff2 +0 -0
  262. package/app/public/vendor/fonts/domine-var-ext.woff2 +0 -0
  263. package/app/public/vendor/fonts/domine-var.woff2 +0 -0
  264. package/app/public/vendor/fonts/fraunces-var-ext.woff2 +0 -0
  265. package/app/public/vendor/fonts/fraunces-var.woff2 +0 -0
  266. package/app/public/vendor/fonts/fredoka-var-ext.woff2 +0 -0
  267. package/app/public/vendor/fonts/fredoka-var.woff2 +0 -0
  268. package/app/public/vendor/fonts/jakarta-var-ext.woff2 +0 -0
  269. package/app/public/vendor/fonts/jakarta-var.woff2 +0 -0
  270. package/app/public/vendor/fonts/lora-var-ext.woff2 +0 -0
  271. package/app/public/vendor/fonts/lora-var.woff2 +0 -0
  272. package/app/public/vendor/fonts/merriweather-var-ext.woff2 +0 -0
  273. package/app/public/vendor/fonts/merriweather-var.woff2 +0 -0
  274. package/app/public/vendor/fonts/notosans-var-ext.woff2 +0 -0
  275. package/app/public/vendor/fonts/notosans-var.woff2 +0 -0
  276. package/app/public/vendor/fonts/nunito-var-ext.woff2 +0 -0
  277. package/app/public/vendor/fonts/nunito-var.woff2 +0 -0
  278. package/app/public/vendor/fonts/playfair-var-ext.woff2 +0 -0
  279. package/app/public/vendor/fonts/playfair-var.woff2 +0 -0
  280. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  281. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  282. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  283. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  284. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  285. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  286. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  287. package/app/public/vendor/fonts/quicksand-var-ext.woff2 +0 -0
  288. package/app/public/vendor/fonts/quicksand-var.woff2 +0 -0
  289. package/app/public/vendor/fonts/robotoflex-var-ext.woff2 +0 -0
  290. package/app/public/vendor/fonts/robotoflex-var.woff2 +0 -0
  291. package/app/public/vendor/fonts/sora-var-ext.woff2 +0 -0
  292. package/app/public/vendor/fonts/sora-var.woff2 +0 -0
  293. package/app/public/vendor/fonts/spacegrotesk-var-ext.woff2 +0 -0
  294. package/app/public/vendor/fonts/spacegrotesk-var.woff2 +0 -0
  295. package/app/public/vendor/fonts/spectral-400-ext.woff2 +0 -0
  296. package/app/public/vendor/fonts/spectral-400.woff2 +0 -0
  297. package/app/public/vendor/fonts/spectral-700-ext.woff2 +0 -0
  298. package/app/public/vendor/fonts/spectral-700.woff2 +0 -0
  299. package/app/public/vendor/fonts/teachers-var-ext.woff2 +0 -0
  300. package/app/public/vendor/fonts/teachers-var.woff2 +0 -0
  301. package/app/public/vendor/fonts/ubuntu-400-ext.woff2 +0 -0
  302. package/app/public/vendor/fonts/ubuntu-400.woff2 +0 -0
  303. package/app/public/vendor/fonts/ubuntu-700-ext.woff2 +0 -0
  304. package/app/public/vendor/fonts/ubuntu-700.woff2 +0 -0
  305. package/app/public/vendor/fonts.css +1167 -51
  306. package/dist-pkg/boot/create-game.d.ts +444 -215
  307. package/dist-pkg/boot/create-game.js +3530 -549
  308. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  309. package/dist-pkg/core/a11y-sr.js +40 -19
  310. package/dist-pkg/core/accessible-label.d.ts +17 -0
  311. package/dist-pkg/core/accessible-label.js +37 -0
  312. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  313. package/dist-pkg/core/accommodation-subjects.js +32 -0
  314. package/dist-pkg/core/accommodations.d.ts +107 -0
  315. package/dist-pkg/core/accommodations.js +178 -0
  316. package/dist-pkg/core/actions.d.ts +75 -51
  317. package/dist-pkg/core/actions.js +98 -69
  318. package/dist-pkg/core/calm-mode.d.ts +31 -0
  319. package/dist-pkg/core/calm-mode.js +47 -0
  320. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  321. package/dist-pkg/core/camera-cycle.js +7 -0
  322. package/dist-pkg/core/caption-duration.d.ts +15 -0
  323. package/dist-pkg/core/caption-duration.js +19 -0
  324. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  325. package/dist-pkg/core/cartridge-problems.js +53 -0
  326. package/dist-pkg/core/constants.d.ts +0 -54
  327. package/dist-pkg/core/constants.js +9 -76
  328. package/dist-pkg/core/contract.d.ts +143 -163
  329. package/dist-pkg/core/contract.js +223 -207
  330. package/dist-pkg/core/dom-query.d.ts +4 -4
  331. package/dist-pkg/core/dom-query.js +12 -20
  332. package/dist-pkg/core/entity.d.ts +62 -77
  333. package/dist-pkg/core/entity.js +18 -32
  334. package/dist-pkg/core/escape-html.d.ts +9 -10
  335. package/dist-pkg/core/escape-html.js +16 -20
  336. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  337. package/dist-pkg/core/flash-threshold.js +113 -0
  338. package/dist-pkg/core/game-speed.d.ts +11 -0
  339. package/dist-pkg/core/game-speed.js +16 -0
  340. package/dist-pkg/core/genres.d.ts +20 -0
  341. package/dist-pkg/core/genres.js +44 -0
  342. package/dist-pkg/core/i18n.d.ts +87 -41
  343. package/dist-pkg/core/i18n.js +206 -153
  344. package/dist-pkg/core/loop.d.ts +17 -6
  345. package/dist-pkg/core/loop.js +26 -26
  346. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  347. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  348. package/dist-pkg/core/ring.d.ts +17 -0
  349. package/dist-pkg/core/ring.js +29 -0
  350. package/dist-pkg/core/rng.d.ts +7 -12
  351. package/dist-pkg/core/rng.js +23 -53
  352. package/dist-pkg/core/route.d.ts +26 -26
  353. package/dist-pkg/core/route.js +126 -121
  354. package/dist-pkg/core/scenes.d.ts +37 -40
  355. package/dist-pkg/core/scenes.js +41 -43
  356. package/dist-pkg/core/screens.d.ts +4 -4
  357. package/dist-pkg/core/screens.js +11 -16
  358. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  359. package/dist-pkg/core/setting-defaults.js +66 -0
  360. package/dist-pkg/core/speech-rate.d.ts +29 -0
  361. package/dist-pkg/core/speech-rate.js +47 -0
  362. package/dist-pkg/core/state.d.ts +118 -118
  363. package/dist-pkg/core/state.js +322 -297
  364. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  365. package/dist-pkg/core/visual-cycles.js +52 -0
  366. package/dist-pkg/core/visual-state.d.ts +13 -0
  367. package/dist-pkg/core/visual-state.js +6 -0
  368. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  369. package/dist-pkg/educational/activities-registry.js +9 -8
  370. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  371. package/dist-pkg/educational/adaptive-engine.js +17 -17
  372. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  373. package/dist-pkg/educational/segment-bar.js +9 -9
  374. package/dist-pkg/i18n/en.js +321 -215
  375. package/dist-pkg/i18n/es.js +320 -215
  376. package/dist-pkg/i18n/pt.js +342 -215
  377. package/dist-pkg/input/default-bindings.d.ts +37 -38
  378. package/dist-pkg/input/default-bindings.js +127 -144
  379. package/dist-pkg/input/devices.d.ts +7 -7
  380. package/dist-pkg/input/devices.js +17 -16
  381. package/dist-pkg/input/edges.d.ts +23 -32
  382. package/dist-pkg/input/edges.js +23 -28
  383. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  384. package/dist-pkg/input/empathy-filter.js +34 -0
  385. package/dist-pkg/input/face-map.d.ts +96 -0
  386. package/dist-pkg/input/face-map.js +255 -0
  387. package/dist-pkg/input/face-signals.d.ts +40 -0
  388. package/dist-pkg/input/face-signals.js +48 -0
  389. package/dist-pkg/input/gamepad.d.ts +164 -145
  390. package/dist-pkg/input/gamepad.js +351 -559
  391. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  392. package/dist-pkg/input/gaze-cycle.js +133 -0
  393. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  394. package/dist-pkg/input/gaze-relative.js +142 -0
  395. package/dist-pkg/input/hand-map.d.ts +28 -0
  396. package/dist-pkg/input/hand-map.js +142 -0
  397. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  398. package/dist-pkg/input/input-cooldown.js +39 -0
  399. package/dist-pkg/input/keyboard-runtime.d.ts +18 -20
  400. package/dist-pkg/input/keyboard-runtime.js +23 -27
  401. package/dist-pkg/input/keyboard.d.ts +68 -62
  402. package/dist-pkg/input/keyboard.js +83 -105
  403. package/dist-pkg/input/keydown.d.ts +124 -132
  404. package/dist-pkg/input/keydown.js +283 -288
  405. package/dist-pkg/input/latch-edge.d.ts +25 -21
  406. package/dist-pkg/input/latch-edge.js +33 -35
  407. package/dist-pkg/input/latch-scope.d.ts +43 -47
  408. package/dist-pkg/input/latch-scope.js +66 -75
  409. package/dist-pkg/input/latch-store.d.ts +28 -29
  410. package/dist-pkg/input/latch-store.js +44 -47
  411. package/dist-pkg/input/latch-sync.d.ts +28 -29
  412. package/dist-pkg/input/latch-sync.js +25 -25
  413. package/dist-pkg/input/latch.d.ts +14 -17
  414. package/dist-pkg/input/latch.js +29 -37
  415. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  416. package/dist-pkg/input/pad-defaults.js +21 -28
  417. package/dist-pkg/input/pad-reading.d.ts +76 -0
  418. package/dist-pkg/input/pad-reading.js +164 -0
  419. package/dist-pkg/input/pad-wizard.d.ts +96 -0
  420. package/dist-pkg/input/pad-wizard.js +205 -0
  421. package/dist-pkg/input/pointer-space.d.ts +19 -20
  422. package/dist-pkg/input/pointer-space.js +27 -32
  423. package/dist-pkg/input/pointer.d.ts +39 -40
  424. package/dist-pkg/input/pointer.js +42 -45
  425. package/dist-pkg/input/state.d.ts +101 -89
  426. package/dist-pkg/input/state.js +54 -134
  427. package/dist-pkg/input/switch-scan.d.ts +42 -0
  428. package/dist-pkg/input/switch-scan.js +54 -0
  429. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  430. package/dist-pkg/input/synthetic-source.js +57 -0
  431. package/dist-pkg/input/touch-bindings.d.ts +127 -113
  432. package/dist-pkg/input/touch-bindings.js +158 -173
  433. package/dist-pkg/input/touch.d.ts +130 -70
  434. package/dist-pkg/input/touch.js +321 -123
  435. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  436. package/dist-pkg/input/transport-in-use.js +130 -0
  437. package/dist-pkg/input/transports.d.ts +96 -114
  438. package/dist-pkg/input/transports.js +104 -106
  439. package/dist-pkg/input/virtual-controller.d.ts +46 -0
  440. package/dist-pkg/input/virtual-controller.js +41 -0
  441. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  442. package/dist-pkg/input/vocabulary-migration.js +80 -79
  443. package/dist-pkg/input/voice-map.d.ts +43 -0
  444. package/dist-pkg/input/voice-map.js +125 -0
  445. package/dist-pkg/platform/audio-ambient.d.ts +13 -1
  446. package/dist-pkg/platform/audio-ambient.js +11 -13
  447. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  448. package/dist-pkg/platform/audio-earcons.js +51 -42
  449. package/dist-pkg/platform/audio-jingles.js +9 -10
  450. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  451. package/dist-pkg/platform/audio-mixer.js +36 -39
  452. package/dist-pkg/platform/audio-sonar.d.ts +96 -113
  453. package/dist-pkg/platform/audio-sonar.js +245 -238
  454. package/dist-pkg/platform/audio.d.ts +53 -19
  455. package/dist-pkg/platform/audio.js +161 -169
  456. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  457. package/dist-pkg/platform/flash-sampler.js +79 -0
  458. package/dist-pkg/platform/guide-intensity.d.ts +26 -27
  459. package/dist-pkg/platform/guide-intensity.js +50 -52
  460. package/dist-pkg/platform/heavy-catalogue.d.ts +31 -0
  461. package/dist-pkg/platform/heavy-catalogue.js +223 -0
  462. package/dist-pkg/platform/heavy-mirror.d.ts +26 -0
  463. package/dist-pkg/platform/heavy-mirror.js +76 -0
  464. package/dist-pkg/platform/heavy.d.ts +104 -0
  465. package/dist-pkg/platform/heavy.js +169 -0
  466. package/dist-pkg/platform/interruptible-speech.d.ts +16 -16
  467. package/dist-pkg/platform/interruptible-speech.js +50 -51
  468. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  469. package/dist-pkg/platform/kokoro-port.js +50 -0
  470. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  471. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  472. package/dist-pkg/platform/kokoro.d.ts +70 -0
  473. package/dist-pkg/platform/kokoro.js +133 -0
  474. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  475. package/dist-pkg/platform/listener-scope.js +81 -0
  476. package/dist-pkg/platform/locale-host.d.ts +10 -0
  477. package/dist-pkg/platform/locale-host.js +34 -0
  478. package/dist-pkg/platform/microphone.d.ts +51 -0
  479. package/dist-pkg/platform/microphone.js +118 -0
  480. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  481. package/dist-pkg/platform/onnx-runtime.js +42 -0
  482. package/dist-pkg/platform/reading-in-worker.d.ts +40 -0
  483. package/dist-pkg/platform/reading-in-worker.js +87 -0
  484. package/dist-pkg/platform/reading-model.d.ts +73 -0
  485. package/dist-pkg/platform/reading-model.js +247 -0
  486. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  487. package/dist-pkg/platform/reading-runtime.js +159 -0
  488. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  489. package/dist-pkg/platform/reading-worker.js +58 -0
  490. package/dist-pkg/platform/reading.d.ts +69 -0
  491. package/dist-pkg/platform/reading.js +128 -0
  492. package/dist-pkg/platform/speech-recognition.d.ts +51 -0
  493. package/dist-pkg/platform/speech-recognition.js +84 -0
  494. package/dist-pkg/platform/speech.d.ts +14 -1
  495. package/dist-pkg/platform/speech.js +13 -13
  496. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  497. package/dist-pkg/platform/storage-keys.js +106 -0
  498. package/dist-pkg/platform/storage.d.ts +46 -111
  499. package/dist-pkg/platform/storage.js +104 -169
  500. package/dist-pkg/platform/tts.d.ts +51 -38
  501. package/dist-pkg/platform/tts.js +217 -119
  502. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  503. package/dist-pkg/platform/vision-loop.js +56 -0
  504. package/dist-pkg/platform/vision.d.ts +132 -0
  505. package/dist-pkg/platform/vision.js +117 -0
  506. package/dist-pkg/platform/voice-listener.d.ts +36 -0
  507. package/dist-pkg/platform/voice-listener.js +88 -0
  508. package/dist-pkg/platform/voice-plan.d.ts +6 -102
  509. package/dist-pkg/platform/voice-plan.js +9 -151
  510. package/dist-pkg/platform/vosk-runtime.d.ts +71 -0
  511. package/dist-pkg/platform/vosk-runtime.js +93 -0
  512. package/dist-pkg/render/canvas.d.ts +13 -7
  513. package/dist-pkg/render/canvas.js +13 -13
  514. package/dist-pkg/render/crt.d.ts +46 -12
  515. package/dist-pkg/render/crt.js +82 -80
  516. package/dist-pkg/render/cvd-matrices.d.ts +18 -18
  517. package/dist-pkg/render/cvd-matrices.js +33 -38
  518. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  519. package/dist-pkg/render/hc-role-data.js +14 -14
  520. package/dist-pkg/render/high-contrast.d.ts +66 -54
  521. package/dist-pkg/render/high-contrast.js +221 -216
  522. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  523. package/dist-pkg/render/low-vision-drawing.js +46 -0
  524. package/dist-pkg/render/lq-filter.d.ts +32 -20
  525. package/dist-pkg/render/lq-filter.js +59 -65
  526. package/dist-pkg/render/port.d.ts +86 -88
  527. package/dist-pkg/render/port.js +17 -23
  528. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  529. package/dist-pkg/render/screen-pipeline.js +80 -87
  530. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  531. package/dist-pkg/render/sprite-fx.js +16 -14
  532. package/dist-pkg/render/viewports.d.ts +20 -15
  533. package/dist-pkg/render/viewports.js +83 -114
  534. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  535. package/dist-pkg/render/viz-axes-labels.js +88 -0
  536. package/dist-pkg/render/viz-axes.d.ts +80 -86
  537. package/dist-pkg/render/viz-axes.js +115 -116
  538. package/dist-pkg/render/viz-modes.d.ts +28 -29
  539. package/dist-pkg/render/viz-modes.js +40 -45
  540. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  541. package/dist-pkg/render/viz-refusal.js +57 -0
  542. package/dist-pkg/render/viz-setters.d.ts +104 -66
  543. package/dist-pkg/render/viz-setters.js +182 -191
  544. package/dist-pkg/ui/aac-sets.d.ts +40 -0
  545. package/dist-pkg/ui/aac-sets.js +49 -0
  546. package/dist-pkg/ui/audio-choices.d.ts +63 -0
  547. package/dist-pkg/ui/audio-choices.js +94 -0
  548. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  549. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  550. package/dist-pkg/ui/camera-control.d.ts +6 -0
  551. package/dist-pkg/ui/camera-control.js +14 -0
  552. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  553. package/dist-pkg/ui/changed-mark.js +22 -53
  554. package/dist-pkg/ui/control-choices.d.ts +37 -0
  555. package/dist-pkg/ui/control-choices.js +84 -0
  556. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  557. package/dist-pkg/ui/debug-panel.js +68 -69
  558. package/dist-pkg/ui/dom.d.ts +10 -14
  559. package/dist-pkg/ui/dom.js +10 -47
  560. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  561. package/dist-pkg/ui/drawing-problems.js +93 -0
  562. package/dist-pkg/ui/eye-control.d.ts +36 -0
  563. package/dist-pkg/ui/eye-control.js +178 -0
  564. package/dist-pkg/ui/face-control.d.ts +25 -0
  565. package/dist-pkg/ui/face-control.js +183 -0
  566. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  567. package/dist-pkg/ui/focus-trap.js +56 -65
  568. package/dist-pkg/ui/fonts.d.ts +118 -63
  569. package/dist-pkg/ui/fonts.js +267 -111
  570. package/dist-pkg/ui/game-options.d.ts +42 -0
  571. package/dist-pkg/ui/game-options.js +138 -0
  572. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  573. package/dist-pkg/ui/gaze-overlay.js +165 -0
  574. package/dist-pkg/ui/hand-control.d.ts +25 -0
  575. package/dist-pkg/ui/hand-control.js +143 -0
  576. package/dist-pkg/ui/help-panel.d.ts +76 -0
  577. package/dist-pkg/ui/help-panel.js +232 -0
  578. package/dist-pkg/ui/hud-bands.d.ts +45 -0
  579. package/dist-pkg/ui/hud-bands.js +108 -0
  580. package/dist-pkg/ui/hud.d.ts +73 -70
  581. package/dist-pkg/ui/hud.js +94 -98
  582. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  583. package/dist-pkg/ui/item-announcement.js +25 -26
  584. package/dist-pkg/ui/latch-refusal.d.ts +22 -21
  585. package/dist-pkg/ui/latch-refusal.js +37 -37
  586. package/dist-pkg/ui/layout.d.ts +103 -28
  587. package/dist-pkg/ui/layout.js +114 -99
  588. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  589. package/dist-pkg/ui/locale-flags.js +30 -0
  590. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  591. package/dist-pkg/ui/loop-crash.js +33 -62
  592. package/dist-pkg/ui/menu-intent.d.ts +32 -0
  593. package/dist-pkg/ui/menu-intent.js +54 -0
  594. package/dist-pkg/ui/menu-items.d.ts +10 -0
  595. package/dist-pkg/ui/menu-items.js +22 -0
  596. package/dist-pkg/ui/menu-nav.d.ts +60 -90
  597. package/dist-pkg/ui/menu-nav.js +301 -274
  598. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  599. package/dist-pkg/ui/mobility-choices.js +41 -0
  600. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  601. package/dist-pkg/ui/motion-choices.js +68 -0
  602. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  603. package/dist-pkg/ui/motion-scene.js +29 -61
  604. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  605. package/dist-pkg/ui/mount-panel.js +61 -0
  606. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  607. package/dist-pkg/ui/panel-shell.js +92 -66
  608. package/dist-pkg/ui/panel-widgets.d.ts +116 -0
  609. package/dist-pkg/ui/panel-widgets.js +208 -0
  610. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  611. package/dist-pkg/ui/pause-buttons.js +66 -0
  612. package/dist-pkg/ui/pause-icons.d.ts +249 -351
  613. package/dist-pkg/ui/pause-icons.js +614 -605
  614. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  615. package/dist-pkg/ui/pause-markup.js +125 -0
  616. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  617. package/dist-pkg/ui/reach-notice.js +55 -58
  618. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  619. package/dist-pkg/ui/scan-overlay.js +42 -0
  620. package/dist-pkg/ui/settings-aac.d.ts +68 -0
  621. package/dist-pkg/ui/settings-aac.js +189 -0
  622. package/dist-pkg/ui/settings-audio.d.ts +91 -113
  623. package/dist-pkg/ui/settings-audio.js +407 -405
  624. package/dist-pkg/ui/settings-controls.d.ts +53 -92
  625. package/dist-pkg/ui/settings-controls.js +143 -215
  626. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  627. package/dist-pkg/ui/settings-empathy.js +53 -60
  628. package/dist-pkg/ui/settings-mobility.d.ts +195 -0
  629. package/dist-pkg/ui/settings-mobility.js +374 -0
  630. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  631. package/dist-pkg/ui/settings-motion.js +287 -198
  632. package/dist-pkg/ui/settings-panel.d.ts +48 -45
  633. package/dist-pkg/ui/settings-panel.js +164 -93
  634. package/dist-pkg/ui/settings-typo.d.ts +28 -76
  635. package/dist-pkg/ui/settings-typo.js +145 -125
  636. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  637. package/dist-pkg/ui/settings-visual.js +240 -193
  638. package/dist-pkg/ui/shell.d.ts +113 -134
  639. package/dist-pkg/ui/shell.js +143 -216
  640. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  641. package/dist-pkg/ui/simulation-list.js +76 -0
  642. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  643. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  644. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  645. package/dist-pkg/ui/simulation-refusal.js +8 -56
  646. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  647. package/dist-pkg/ui/switchable-control.js +19 -0
  648. package/dist-pkg/ui/title.d.ts +4 -4
  649. package/dist-pkg/ui/title.js +11 -13
  650. package/dist-pkg/ui/top-band.d.ts +24 -0
  651. package/dist-pkg/ui/top-band.js +100 -0
  652. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  653. package/dist-pkg/ui/typo-choices.js +84 -0
  654. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  655. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  656. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  657. package/dist-pkg/ui/visual-choices.js +107 -0
  658. package/dist-pkg/ui/vlibras.d.ts +33 -10
  659. package/dist-pkg/ui/vlibras.js +58 -81
  660. package/dist-pkg/ui/voice-control.d.ts +46 -0
  661. package/dist-pkg/ui/voice-control.js +143 -0
  662. package/dist-pkg/ui/voice-settings.d.ts +96 -0
  663. package/dist-pkg/ui/voice-settings.js +302 -0
  664. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  665. package/dist-pkg/ui/where-the-child-is.js +70 -0
  666. package/docs/CREDITS.md +198 -54
  667. package/docs/LICENSES.md +160 -145
  668. package/package.json +24 -25
  669. package/scripts/heavy-into-the-delivery.mjs +144 -0
  670. package/scripts/licences/Apache-2.0.txt +176 -0
  671. package/scripts/licences/GPL-3.0.txt +674 -0
  672. package/scripts/licences/MIT.txt +17 -0
  673. package/scripts/licences/third-party.mjs +287 -0
  674. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  675. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  676. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  677. package/dist-pkg/core/anel.d.ts +0 -17
  678. package/dist-pkg/core/anel.js +0 -31
  679. package/dist-pkg/core/collision.d.ts +0 -21
  680. package/dist-pkg/core/collision.js +0 -62
  681. package/dist-pkg/core/layers.d.ts +0 -63
  682. package/dist-pkg/core/layers.js +0 -95
  683. package/dist-pkg/core/letter-grid.d.ts +0 -55
  684. package/dist-pkg/core/letter-grid.js +0 -116
  685. package/dist-pkg/core/password.d.ts +0 -34
  686. package/dist-pkg/core/password.js +0 -205
  687. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  688. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  689. package/dist-pkg/core/run-state.d.ts +0 -115
  690. package/dist-pkg/core/run-state.js +0 -40
  691. package/dist-pkg/core/tiles.d.ts +0 -12
  692. package/dist-pkg/core/tiles.js +0 -61
  693. package/dist-pkg/core/world.d.ts +0 -4
  694. package/dist-pkg/core/world.js +0 -58
  695. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  696. package/dist-pkg/input/origem-sintetica.js +0 -60
  697. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  698. package/dist-pkg/input/transporte-em-uso.js +0 -130
  699. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  700. package/dist-pkg/platform/audio-nav.js +0 -99
  701. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  702. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  703. package/dist-pkg/platform/pesados.d.ts +0 -31
  704. package/dist-pkg/platform/pesados.js +0 -75
  705. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  706. package/dist-pkg/platform/vozes-prontas.js +0 -61
  707. package/dist-pkg/render/camera.d.ts +0 -58
  708. package/dist-pkg/render/camera.js +0 -105
  709. package/dist-pkg/render/cenario-data.d.ts +0 -127
  710. package/dist-pkg/render/cenario-data.js +0 -145
  711. package/dist-pkg/render/city-tex.d.ts +0 -63
  712. package/dist-pkg/render/city-tex.js +0 -228
  713. package/dist-pkg/render/city-tiles.d.ts +0 -11
  714. package/dist-pkg/render/city-tiles.js +0 -140
  715. package/dist-pkg/render/draw.d.ts +0 -149
  716. package/dist-pkg/render/draw.js +0 -231
  717. package/dist-pkg/render/fx.d.ts +0 -63
  718. package/dist-pkg/render/fx.js +0 -123
  719. package/dist-pkg/render/minimap.d.ts +0 -11
  720. package/dist-pkg/render/minimap.js +0 -94
  721. package/dist-pkg/render/parallax.d.ts +0 -85
  722. package/dist-pkg/render/parallax.js +0 -158
  723. package/dist-pkg/render/player-anim.d.ts +0 -71
  724. package/dist-pkg/render/player-anim.js +0 -152
  725. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  726. package/dist-pkg/render/recycling-tex.js +0 -164
  727. package/dist-pkg/render/scene-city.d.ts +0 -77
  728. package/dist-pkg/render/scene-city.js +0 -181
  729. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  730. package/dist-pkg/render/scene-parallax.js +0 -426
  731. package/dist-pkg/render/scene-sky.d.ts +0 -126
  732. package/dist-pkg/render/scene-sky.js +0 -295
  733. package/dist-pkg/render/set-cenario.d.ts +0 -54
  734. package/dist-pkg/render/set-cenario.js +0 -103
  735. package/dist-pkg/render/textures.d.ts +0 -75
  736. package/dist-pkg/render/textures.js +0 -240
  737. package/dist-pkg/render/title-scene.d.ts +0 -46
  738. package/dist-pkg/render/title-scene.js +0 -75
  739. package/dist-pkg/render/weather.d.ts +0 -96
  740. package/dist-pkg/render/weather.js +0 -171
  741. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  742. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  743. package/dist-pkg/render/world-tex.d.ts +0 -18
  744. package/dist-pkg/render/world-tex.js +0 -87
  745. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  746. package/dist-pkg/ui/activities-menu.js +0 -648
  747. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  748. package/dist-pkg/ui/caa-sets.js +0 -65
  749. package/dist-pkg/ui/map-hub.d.ts +0 -56
  750. package/dist-pkg/ui/map-hub.js +0 -138
  751. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  752. package/dist-pkg/ui/settings-caa.js +0 -137
  753. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  754. package/dist-pkg/ui/settings-motor.js +0 -342
  755. package/dist-pkg/ui/webcam.d.ts +0 -7
  756. package/dist-pkg/ui/webcam.js +0 -93
@@ -1,132 +1,114 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // input/keydown.ts — O ROTEADOR DE TECLADO: o que UMA tecla SIGNIFICA, aqui e agora.
2
+ // input/keydown.ts — THE KEYBOARD ROUTER: what ONE key MEANS, here and now.
3
3
  //
4
- // Este é o ouvinte de `keydown` de BOLHA do game.js — o único ponto do jogo por onde passa toda tecla que não
5
- // foi interceptada antes. Ele não é "o controle do personagem": andar/pular são consequência da ÚLTIMA das
6
- // nove perguntas que ele faz. As oito primeiras decidem se a tecla é do jogo ou de outra coisa — demo,
7
- // remapeamento, diálogo, tela de vitória, menu inicial, número de telas, pausa, quiz — e é essa SEQUÊNCIA que
8
- // é a especificação: quem vem antes vence, e mudar a ordem de duas guardas muda o jogo sem quebrar nada que
9
- // um build, um `tsc` ou um olho consigam ver.
4
+ // The BUBBLING `keydown` listener a cartridge mounts (`initKeydown(ctx).attach()`) — the one point every key passes
5
+ // that was not intercepted before. It is not "the character's control": walking and jumping are the consequence of the
6
+ // LAST of the nine questions it asks. The first eight decide whether the key belongs to the game or to something else —
7
+ // demo, remapping, dialog, win screen, title menu, number of screens, pause, modal — and that SEQUENCE is the
8
+ // specification: the earlier one wins, and swapping two guards changes the game without breaking anything a build, a
9
+ // `tsc` or an eye could see. (The engine's own root has its own keyboard conductor, for the virtual controller.)
10
10
  //
11
- // ======================= A ENTREGA: DECIDIR ≠ EXECUTAR =======================
12
- // O bloco original é uma CADEIA DE DECISÃO PURA DISFARÇADA DE EFEITO. Dado (código da tecla, fase, quem tem
13
- // quiz aberto, qual diálogo está visível, número de telas, esquemas de tecla), existe UMA resposta sobre o que
14
- // a tecla significa — e o `preventDefault`, o `click()`, o `togglePause()` vêm só DEPOIS dessa resposta. No
15
- // monólito as duas metades estavam trançadas: cada `if` misturava a pergunta ("tem diálogo aberto?") com a
16
- // resposta ("então esconde e sai"), e por isso a ordem de precedência — a parte que realmente importa — só
17
- // podia ser verificada jogando.
11
+ // ======================= DECIDING ≠ DOING =======================
12
+ // Given (key code, scene, who has a modal open, which dialog is visible, number of screens, key schemes) there is ONE
13
+ // answer about what the key means — and the `preventDefault`, the `click()`, the `togglePause()` come only AFTER that
14
+ // answer. With the two halves braided, each `if` mixing the question ("is a dialog open?") with the answer ("then hide
15
+ // and leave"), the precedence — the part that matters — could only be checked by playing.
18
16
  //
19
- // Aqui elas são dois objetos separados:
20
- // · `decideKeydown(evento, estado) -> KeydownDecision` — PURA. Sem DOM, sem PIXI, sem áudio, sem `window`.
21
- // Roda no project `node`. Cada ramo da ordem de precedência é um caso de teste, e a precedência ENTRE os
22
- // ramos (quiz aberto E diálogo visível: quem ganha?) é uma asserção, não um relato.
23
- // · `initKeydown(ctx).onKeydown(e)` — a metade IMPURA: pega a decisão pronta e a carimba no mundo.
24
- // Mesmo movimento que `ui/shell.ts` fez com `phaseView`/`applyPhaseView` e `ui/title.ts` com
25
- // `computeTitleMenuView`; é o precedente da casa, e aqui ele vale mais do que lá, porque o que está em jogo é
26
- // o teclado — a única modalidade que TODA pessoa que joga sem mouse, sem visão ou sem controle depende.
17
+ // Here they are two separate objects:
18
+ // · `decideKeydown(event, state) -> KeydownDecision` — PURE. No DOM, no PIXI, no audio, no `window`. It runs in the
19
+ // `node` project. Each branch of the precedence is a test case, and the precedence BETWEEN branches (modal open AND
20
+ // dialog visible: who wins?) is an assertion, not an anecdote.
21
+ // · `initKeydown(ctx).onKeydown(e)` — the IMPURE half: takes the ready decision and stamps it on the world.
22
+ // It matters more here than anywhere, because what is at stake is the keyboard — the one modality EVERY person who
23
+ // plays without a mouse, without sight or without a pad depends on.
27
24
  //
28
- // ======================= O QUE FICOU DE FORA DA PARTE PURA, E POR QUÊ =======================
29
- // Duas guardas do topo NÃO cabem em `decideKeydown`, e forçá-las lá seria mentira:
30
- // · `attractCtl.onInput()` (game/attract.ts) — ela DECIDE E AGE na mesma chamada: zera o contador de
31
- // ociosidade, encerra a demo se estiver rodando, e devolve se encerrou. Não há como perguntar sem mexer.
32
- // · `ctrlPanel.handleCaptureKeydown(e)` (ui/settings-controls.ts) — idem: se há remapeamento em curso, ela
33
- // GRAVA a tecla no esquema e devolve `true`.
34
- // As duas continuam sendo as duas primeiras linhas de `onKeydown`, na mesma ordem, e o teste que prova que
35
- // elas vêm antes de tudo é do wrapper (com sondas de mentira), não da função pura.
36
- // A leitura de VISIBILIDADE dos diálogos também não entra pura: ela é `querySelector` + `.hidden`. O que entra
37
- // na parte pura é o RESULTADO dela (três booleanos e um id), montado por `snapshot()`.
25
+ // ======================= WHAT STAYED OUT OF THE PURE PART, AND WHY =======================
26
+ // Two guards at the top do NOT fit in `decideKeydown`, and forcing them in would be a lie:
27
+ // · `attractOnInput()` (the demo) — it DECIDES AND ACTS in one call: resets the idleness counter, ends the demo if it
28
+ // is running, and returns whether it ended. There is no asking without touching.
29
+ // · `handleCaptureKeydown(e)` (ui/settings-controls.ts) — likewise: if a remap is in progress, it WRITES the key into
30
+ // the scheme and returns `true`.
31
+ // Both are the first two lines of `onKeydown`, in that order, and the test proving they come before everything is the
32
+ // wrapper's (with fake probes), not the pure function's.
33
+ // Reading the dialogs' VISIBILITY does not enter the pure part either: it is `querySelector` + `.hidden`. What enters is
34
+ // its RESULT (three booleans and an id), built by `snapshot()`.
38
35
  //
39
- // ======================= ⚠️ PAUSADO, ESTE OUVINTE NÃO É ALCANÇADO PARA Escape =======================
40
- // `ui/menu-nav.ts` registra o PRÓPRIO `keydown` em fase de CAPTURA e dá `stopPropagation()`. Com o jogo
41
- // PAUSADO (`phase==='paused'`), toda tecla com intenção de menu — Escape inclusive — morre lá em cima e nunca
42
- // desce até aqui. Consequência MEDIDA no navegador, e anotada tanto no game.js quanto no cabeçalho de
43
- // menu-nav (DEFEITO 2): a cadeia `overlays.escapeTarget()` e o `togglePause()` de Escape são, na prática,
44
- // código morto enquanto pausado; quem fecha é sempre o topo da pilha de z-index.
45
- // ISTO É COMPORTAMENTO ATUAL E FOI PRESERVADO — não é bug para consertar aqui, é rede de segurança de que o
46
- // conserto futuro vai precisar (tirar o `stopPropagation()` sem mais nada faz o `if(Escape||Enter)
47
- // togglePause()` daqui DESPAUSAR o jogo com a Ajuda aberta). Os testes o ancoram como está: `decideKeydown`
48
- // devolve a decisão que ELE tomaria, e o teste do wrapper documenta que, pausado, ela não é consultada porque
49
- // o evento não chega. Ver `tests/keydown.node.test.js`, bloco "a captura do menu-nav chega antes".
36
+ // ======================= ⚠️ PAUSED, THIS LISTENER IS NOT REACHED FOR Escape =======================
37
+ // `ui/menu-nav.ts` registers its OWN `keydown` in the CAPTURE phase and calls `stopPropagation()`. With the game PAUSED,
38
+ // every key with a menu intent — Escape included — dies up there and never comes down here (menu-nav's header, DEFECT
39
+ // 2): the `escapeTarget()` chain and Escape's `togglePause()` are dead code while paused; whoever closes is always the
40
+ // top of the z-index stack.
41
+ // THIS IS CURRENT BEHAVIOUR AND IT IS KEPT — not a bug to fix here, but a safety net the future fix will need (removing
42
+ // the `stopPropagation()` with nothing else makes this module's `if(Escape||Enter) togglePause()` UNPAUSE the game with
43
+ // Help open). The tests anchor it as it is: `decideKeydown` returns the decision IT would take, and the wrapper test
44
+ // documents that, paused, it is not consulted because the event does not arrive. See `tests/keydown.node.test.js`.
50
45
  //
51
- // ======================= O QUE VEIO JUNTO, E O QUE NÃO VEIO =======================
52
- // · `keyup` VEIO. Ele é a outra metade exata do `keys.add(e.code)` da última linha do keydown: sem os dois no
53
- // mesmo lugar, quem lê "quando uma tecla entra em `keys`" tem de procurar a saída em outro arquivo. `attach()`
54
- // instala os dois, na mesma ordem de antes.
55
- // · `blur` NÃO veio. Parece irmão, mas não é: `keys` também recebe códigos INJETADOS pelos botões de toque
56
- // (o `press`/`release` do game.js, que faz `keys.add(codeFor(act))`) e pelo controle por webcam
57
- // (`ui/webcam.ts` despacha `KeyboardEvent` sintético). `blur -> keys.clear()` é uma rede de ciclo de vida da
58
- // JANELA sobre um conjunto que não é só do teclado; trazê-la para cá daria a este módulo a
59
- // responsabilidade de limpar estado que ele não escreve. Fica no game.js, uma linha, ao lado do `resize`.
60
- // · A cadeia de Escape, o registro de overlays e o `closeById` são de `ui/settings-panel.ts`. Este módulo
61
- // CONSOME (`escapeTarget`, `closeOverlayById`) e não reimplementa — mesma disciplina de menu-nav.
62
- // · `whichPlayer`/`actionOf`/`controlsState` são de `input/keyboard-runtime.ts`, que é quem sabe de esquema de
63
- // teclas. Aqui eles entram injetados e são só consultados. `controlsState()` é MEMORIZADO lá: este módulo o
64
- // chama uma vez por tecla, como o original.
65
- // · A navegação do menu inicial (`navTitle`) é de `ui/activities-menu.ts`; a do menu de pausa é de
66
- // `ui/menu-nav.ts`. Este módulo decide QUE a tecla é de navegação e para QUEM ela vai — nunca desenha menu.
46
+ // ======================= WHAT CAME ALONG, AND WHAT DID NOT =======================
47
+ // · `keyup` CAME. It is the exact other half of the keydown's hold: with the two apart, whoever reads "when a key
48
+ // enters `keys`" would have to look for the exit in another file. `attach()` installs both, in the same order.
49
+ // · `blur` did NOT come. It looks like a sibling and is not: `keys` also holds codes the virtual controller writes
50
+ // for a position the eyes pressed (`input/virtual-controller`), so letting go on `blur` is a lifecycle net of the
51
+ // WINDOW over a set that is not only the keyboard's. It lives in the root (`boot/create-game`), which dispatches
52
+ // the keyup each keyboard-held key is owed and leaves the camera's alone.
53
+ // · The Escape chain, the overlay registry and `closeById` belong to `ui/settings-panel.ts`. This module CONSUMES them
54
+ // (`escapeTarget`, `closeOverlayById`) and does not reimplement them — the same discipline as menu-nav.
55
+ // · `whichPlayer`/`actionOf`/`controlsState` belong to `input/keyboard-runtime.ts`, which is what knows key schemes.
56
+ // Here they come in injected and are only consulted. `controlsState()` is MEMOISED there: this module calls it once
57
+ // per key.
58
+ // · The title menu's navigation (`navTitle`) is the game's; the pause menu's is `ui/menu-nav.ts`'s. This module
59
+ // decides THAT the key is navigation and for WHOM — it never draws a menu.
67
60
  //
68
- // ======================= INJEÇÃO E ORDEM DE BOOT =======================
69
- // `initKeydown` tem de ser chamado NO LUGAR EXATO onde o `addEventListener('keydown', …)` estava (logo depois
70
- // de `assignControls()`), por dois motivos independentes:
71
- // 1. ORDEM DE REGISTRO. Os ouvintes de bolha do mesmo alvo disparam na ordem em que foram registrados. Este é
72
- // hoje o primeiro `keydown` de bolha da janela, e o único de captura (menu-nav) já vence por fase.
73
- // Registrar mais tarde não muda nada HOJE, mas passa a depender de nenhum outro ouvinte de janela nascer
74
- // no meio — dependência invisível que não vale a pena criar.
75
- // 2. TDZ. Quase tudo o que este módulo aciona (`attractCtl`, `ctrlPanel`, `gamepadApi`, `hud`, `navTitle`,
76
- // `activateScreens`, `togglePause`, `hideTouchControls`, as quatro funções de quiz) é `const`/`function`
77
- // declarado CENTENAS de linhas ABAIXO desse ponto. O ouvinte original só funcionava porque o corpo dele é
78
- // preguiçoso: nada é lido até a primeira tecla. Por isso TODO o ctx é `() => …`: valor nenhum é resolvido
79
- // na montagem. Passar `attractCtl` (ou `hud`, ou `navTitle`) por VALOR derruba o boot em TDZ.
80
- // A regra da casa vale igual: o que o game.js REATRIBUI entra por GETTER (`oneButton`, `numPlayers`, `players`,
81
- // o estado de controles). `keys` é `const` de `input/state.ts`, mutado in place — entra por VALOR (é o mesmo
82
- // objeto para sempre). `phase` é binding vivo de `core/state.ts`, importado direto, como em menu-nav.
61
+ // ======================= INJECTION AND BOOT ORDER =======================
62
+ // 1. REGISTRATION ORDER. Bubbling listeners on the same target fire in the order they were registered; the only
63
+ // capture one (menu-nav) already wins by phase. Registering elsewhere changes nothing as long as no other window
64
+ // listener is born in between — an invisible dependency worth not creating.
65
+ // 2. LAZINESS. The whole ctx is `() => …`: no value is resolved at mount, only on the first key. A host that builds
66
+ // the demo, the panels or the pad AFTER mounting this module works; passing them by VALUE would read them before
67
+ // they exist.
68
+ // What the host REASSIGNS comes in by GETTER (`oneButton`, `numPlayers`, `players`, the controls state). `keys` is a
69
+ // `const` of `input/state.ts`, mutated in place — it comes in by VALUE (the same object forever).
83
70
  //
84
- // ÚNICA DIFERENÇA DE COMPORTAMENTO EM RELAÇÃO AO MONÓLITO, declarada: `snapshot()` lê os três `hidden` e o
85
- // `escapeTarget()` de uma vez, enquanto o original os lia em curto-circuito (só chegava ao `#padwiz` se não
86
- // houvesse overlay nem `#touchcfg`). São no máximo quatro `querySelector` a mais por tecla, todos de leitura
87
- // pura (`escapeTarget` só varre o registro e testa `.hidden` — conferido em ui/settings-panel.ts). Nada
88
- // observável muda; anotado porque medir depois é mais caro do que escrever agora.
71
+ // One behaviour note, declared: `snapshot()` reads the three `hidden` flags and `escapeTarget()` at once, rather than in
72
+ // short circuit. That is at most four extra `querySelector` per key, all pure reads (`escapeTarget` only walks the
73
+ // registry and tests `.hidden`). Nothing observable changes; noted because measuring later costs more than writing now.
89
74
  //
90
- // SEM I/O NO IMPORT: o corpo do módulo só declara tabelas congeladas e funções puras. Todo efeito passa por
91
- // `initKeydown` (e mesmo ele não faz nada até `attach()`).
92
- //
93
- // Ver docs/5-Refactoring/plano-modularizacao-mapa.md (D2-a).
94
- import { t } from '../core/i18n.js';
75
+ // NO I/O ON IMPORT: the module body only declares frozen tables and pure functions. Every effect goes through
76
+ // `initKeydown` (and even it does nothing until `attach()`).
95
77
  import { EDGE_BY_ACTION, edgeAllowed } from './edges.js';
96
- /* --- tabelas (congeladas: são dados, e um `Set` nomeado deixa a tabela auditável de fora) --- */
97
- /** Fácil (SOLO): Ctrl = Especial, Shift = Trocar poder. Fora de Win/Alt/AltGr, de propósito. */
78
+ /* --- tables (frozen: they are data, and a named `Set` keeps the table auditable from outside) --- */
79
+ /** Easy (SOLO): Ctrl = Special, Shift = Swap power. Not Win/Alt/AltGr, on purpose. */
98
80
  export const EASY_SHORTCUTS = new Set(['ControlLeft', 'ControlRight', 'ShiftLeft', 'ShiftRight']);
99
- /** Alt + fileira de números (NÃO o teclado numérico) = 1..4 telas. Alt fica livre: o solo não o usa. */
81
+ /** Alt + the digit row (NOT the numeric keypad) = 1..4 screens. Alt is free: solo does not use it. */
100
82
  export const SCREEN_DIGITS = /^Digit[1234]$/;
101
- /** Pausa: Escape ou o Enter CENTRAL. `NumpadEnter` NÃO pausa (E14, verbatim). */
83
+ /** Pause: Escape or the MAIN Enter. `NumpadEnter` does NOT pause. */
102
84
  export const PAUSE_KEYS = new Set(['Escape', 'Enter']);
103
- // A tabela e a regra do Fácil vivem em input/edges.ts, compartilhadas com gamepad e touch-bindings. Reexporta
104
- // pelo nome antigo porque quem importa daqui (teste e leitor) espera achá-la aqui.
85
+ // The table and the Easy rule live in input/edges.ts, shared with gamepad and touch-bindings. Re-exported under the old
86
+ // name because whoever imports from here (tests and readers) expects to find it here.
105
87
  export { EDGE_BY_ACTION, edgeAllowed } from './edges.js';
106
- /* --- predicados puros (exportados: o teste importa a peça, não repete a expressão) --- */
107
- /** A tecla vale como PULO para alguém? O alias do J1 OU a ação `jump` de qualquer jogador (é o que faz
108
- * "qualquer um pode apertar Jogar de novo" e "qualquer um confirma no título" serem verdade). */
88
+ /* --- pure predicates (exported: the test imports the piece instead of repeating the expression) --- */
89
+ /** Does the key count as JUMP for anybody? P1's alias OR any player's `action2` (it is what makes "anyone can press
90
+ * Play again" and "anyone confirms on the title" true). */
109
91
  export function isJumpKey(code, s) {
110
92
  return s.controls.action2.includes(code) || s.players.some((_p, i) => s.actionOf(code, i) === 'action2');
111
93
  }
112
- /** A tecla é de JOGO? Verbatim do `isGameKeyCode` do game.js — o alias achatado OU o esquema de algum
113
- * jogador. NÃO inclui os atalhos do Fácil (o original também não: por isso `easyKey` é somado à parte). */
94
+ /** Is the key a GAME key? The flattened alias OR some player's scheme. It does NOT include the Easy shortcuts: those
95
+ * are added apart (`isEasyShortcut`). */
114
96
  export function isGameKeyCode(code, s) {
115
97
  return s.controls.gameKeys.includes(code)
116
- // `arr &&` porque uma posição sem alcance é `null` desde a #118 — e `null.includes` seria uma exceção
117
- // no caminho do teclado, ou seja, o jogo a parar de responder a qualquer tecla.
98
+ // `arr &&` because a position with no reach is `null` since #118 — and `null.includes` would be an exception on the
99
+ // keyboard path, that is, the game ceasing to answer any key.
118
100
  || s.players.some((p) => !!p.ctrl && Object.values(p.ctrl).some((arr) => !!arr && arr.includes(code)));
119
101
  }
120
- /** Os atalhos de acessibilidade do Fácil só existem SOLO (`numPlayers<=1`) e só para o Jogador 1. */
102
+ /** Easy's accessibility shortcuts exist only in SOLO (`numPlayers<=1`) and only for Player 1. */
121
103
  export function isEasyShortcut(code, s) {
122
104
  return !!s.players[0]?.easy && s.numPlayers <= 1 && EASY_SHORTCUTS.has(code);
123
105
  }
124
106
  /**
125
- * A intenção no menu inicial. Repare na ASSIMETRIA, preservada verbatim: `up`/`down` aceitam ArrowUp/ArrowDown
126
- * ALÉM do alias configurado, `left`/`right` não aceitam ArrowLeft/ArrowRight. No esquema de fábrica isso não
127
- * aparece (o solo já tem as setas nos quatro lados); aparece para quem REMAPEIA — remapeou esquerda para KeyA
128
- * e a seta deixa de andar no menu, enquanto cima continua funcionando pelas duas. Está anotado como caso de
129
- * teste em tests/keydown.node.test.js, e é candidato a conserto, não a "limpeza" silenciosa.
107
+ * The title menu intent. Note the ASYMMETRY, kept as it is: `up`/`down` accept ArrowUp/ArrowDown ON TOP of the
108
+ * configured alias, `left`/`right` do not accept ArrowLeft/ArrowRight. It does not show in the factory scheme (solo
109
+ * already has the arrows on all four sides); it shows for whoever REMAPS — remap left to KeyA and the arrow stops moving
110
+ * in the menu, while up keeps working both ways. It is a test case in tests/keydown.node.test.js, and a candidate for a
111
+ * fix, not for a silent "cleanup".
130
112
  */
131
113
  export function titleNavOf(code, s, action2) {
132
114
  return {
@@ -138,18 +120,18 @@ export function titleNavOf(code, s, action2) {
138
120
  right: s.controls.right.includes(code),
139
121
  };
140
122
  }
141
- /** Alguma intenção foi expressa? Definição única em input/edges; aqui só o nome que este módulo sempre teve. */
123
+ /** Was any intent expressed? One definition in input/edges; here only the name this module always had. */
142
124
  import { hasNavIntent as hasTitleIntent } from './edges.js';
143
- // ⚠️ IMPORTADA E NÃO INJECTADA, ao contrário dos três escritores logo abaixo, e a linha que separa os dois é
144
- // esta: `origemDoEvento` é uma função PURA do evento — não toca estado nenhum que o cartucho possua. Os
145
- // escritores tocam o `input/state`, que é mutado in-place e partilhado, e é por isso que continuam a entrar.
146
- import { origemDoEvento } from './origem-sintetica.js';
125
+ // ⚠️ IMPORTED AND NOT INJECTED, unlike the three writers below, and the line between them is this: `sourceOfEvent` is a
126
+ // PURE function of the event — it touches no state the cartridge owns. The writers touch `input/state`, which is mutated
127
+ // in place and shared, and that is why they keep coming in through the ctx.
128
+ import { sourceOfEvent } from './synthetic-source.js';
147
129
  export { hasNavIntent as hasTitleIntent } from './edges.js';
148
130
  /**
149
- * Quem é o dono do modal que esta tecla comanda? Devolve a POSIÇÃO no array, ou -1.
150
- * Regra verbatim: tecla de um jogador vai para o modal DAQUELE jogador (e só se ele tiver um aberto); tecla
151
- * genérica cai no Jogador 1. Tecla de um jogador SEM modal aberto não cai no P1 — ela desce para o jogo
152
- * normal, que é o que deixa a partida dele continuar enquanto o outro resolve o desafio.
131
+ * Who owns the modal this key commands? Returns the POSITION in the array, or -1.
132
+ * A player's key goes to THAT player's modal (and only if they have one open); a generic key falls to Player 1. A key of
133
+ * a player WITHOUT an open modal does not fall to P1 — it goes down to normal play, which is what lets their match go on
134
+ * while the other solves the challenge.
153
135
  */
154
136
  export function modalOwnerIndex(code, s) {
155
137
  const owner = s.whichPlayer(code);
@@ -158,47 +140,39 @@ export function modalOwnerIndex(code, s) {
158
140
  return s.modalOpen[0] ? 0 : -1;
159
141
  }
160
142
  /**
161
- * Que INTENÇÃO esta tecla exprime dentro do modal do dono. `owner` é a posição no array; `generic` diz se a
162
- * tecla chegou sem dono (aí as seis leituras usam os aliases do J1 em vez da ação remapeada).
143
+ * Which INTENT this key expresses inside its owner's modal. `owner` is the position in the array; `generic` says whether
144
+ * the key arrived with no owner (then the six readings use P1's aliases instead of the remapped action).
163
145
  *
164
- * As seis leituras são as mesmas de antes, letra por letra. O que saiu foi a linha seguinte: a que trocava
165
- * "cima" por `delta:-3` e "esquerda" por `delta:-1`, e o desvio de Braille. Isso é grade, e grade é do jogo.
146
+ * What a direction DOES inside the challenge (move one cell or three, dictate a Braille cell) is grid, and grid is the
147
+ * game's.
148
+ */
149
+ /*
150
+ * The six readings, IN THIS ORDER — and the order is the rule: with a scheme where the same key is `left` and jump,
151
+ * `left` wins. Each row says which ACTION means that intent and, for a key with no owner, which alias list carries it.
152
+ * ⚠️ SPECIAL = erase the last syllable/letter, and its generic reading comes from `pl.ctrl` and NOT `controls` — an
153
+ * asymmetry kept, because `ControlsSnapshot` has no `action3` alias.
166
154
  */
155
+ const MODAL_READINGS = [
156
+ { intent: 'left', action: 'left', alias: (s) => s.controls.left },
157
+ { intent: 'right', action: 'right', alias: (s) => s.controls.right },
158
+ { intent: 'up', action: 'up', alias: (s) => s.controls.up },
159
+ { intent: 'down', action: 'down', alias: (s) => s.controls.down },
160
+ { intent: 'confirm', action: 'action2', alias: (s) => s.controls.action2 },
161
+ { intent: 'erase', action: 'action3', alias: (_s, pl) => pl.ctrl?.action3 || [] },
162
+ ];
167
163
  export function modalIntentOf(code, s, owner, generic) {
168
164
  const pl = s.players[owner];
169
165
  if (!pl)
170
166
  return null;
171
- const act = generic ? null : s.actionOf(code, pl.i); // `qpl.i`, não a posição — verbatim
172
- const K = s.controls;
173
- const L = act ? act === 'left' : K.left.includes(code);
174
- const R = act ? act === 'right' : K.right.includes(code);
175
- const U = act ? act === 'up' : K.up.includes(code);
176
- const D = act ? act === 'down' : K.down.includes(code);
177
- const J = act ? act === 'action2' : K.action2.includes(code);
178
- // ESPECIAL = apagar a última sílaba/letra. A leitura genérica sai de `pl.ctrl`, NÃO de `K` — assimetria do
179
- // original preservada (não existe alias `KESPECIAL` em ControlsState; o original alcançava `qpl.ctrl`).
180
- const E = act ? act === 'action3' : ((pl.ctrl?.action3 || []).includes(code));
181
- // A ORDEM é a do original e importa: com um esquema em que a mesma tecla é `left` e `jump`, ganha `left`.
182
- if (L)
183
- return 'left';
184
- if (R)
185
- return 'right';
186
- if (U)
187
- return 'up';
188
- if (D)
189
- return 'down';
190
- if (J)
191
- return 'confirm';
192
- if (E)
193
- return 'erase';
194
- return null;
167
+ const act = generic ? null : s.actionOf(code, pl.i); // the player's own `i`, not the position
168
+ const read = MODAL_READINGS.find((r) => (act ? act === r.action : r.alias(s, pl).includes(code)));
169
+ return read ? read.intent : null;
195
170
  }
196
171
  /**
197
- * As bordas que esta tecla levanta. Só é chamada quando a tecla AINDA NÃO está segurada — é isso que a torna
198
- * uma BORDA e não um estado, e é o que impede o auto-repeat do sistema de virar dez pulos.
199
- * `p.ctrl[act] || []`: o original alcançava `p.ctrl.jump` direto e estouraria num esquema sem a ação. Trocar
200
- * um TypeError por um no-op não remove rede de conserto nenhuma (o precedente é a guarda de `navPause` em
201
- * ui/menu-nav.ts) — é a única linha desta função que não é cópia literal.
172
+ * The edges this key raises. It is only called when the key is NOT YET held — that is what makes it an EDGE and not a
173
+ * state, and what keeps the system's auto-repeat from becoming ten jumps.
174
+ * `p.ctrl[act] || []`: a scheme without the action turns a TypeError into a no-op (the precedent is `navPause`'s guard
175
+ * in ui/menu-nav.ts) — a net that removes no chance of a fix.
202
176
  */
203
177
  export function edgesFor(code, s) {
204
178
  const out = [];
@@ -207,84 +181,115 @@ export function edgesFor(code, s) {
207
181
  return;
208
182
  for (const [act, edge] of EDGE_BY_ACTION) {
209
183
  if (!edgeAllowed(act, p.easy))
210
- continue; // Fácil: sem correr (input/edges.ts, valendo nos três caminhos)
184
+ continue; // Easy: no running (input/edges.ts, holding on all three paths)
211
185
  if ((p.ctrl?.[act] || []).includes(code))
212
186
  out.push({ playerIndex: idx, edge });
213
187
  }
214
188
  });
215
- // Fácil (solo): Ctrl vira Especial e Shift vira Trocar poder, SEMPRE no Jogador 1 (`player` do original).
189
+ // Easy (solo): Ctrl becomes Special and Shift becomes Swap power, ALWAYS on Player 1.
216
190
  if (isEasyShortcut(code, s))
217
191
  out.push({ playerIndex: 0, edge: code.startsWith('Control') ? 'specialEdge' : 'swapEdge' });
218
192
  return out;
219
193
  }
220
- /**
221
- * A CADEIA. Nove perguntas, nesta ordem — e a ordem É a especificação.
222
- * O que NÃO está aqui, e vem antes no wrapper: a demo (attract) e a captura de remapeamento. Ver o cabeçalho.
194
+ /*
195
+ * 🔴 THE CHAIN, AND THE ORDER IS THE SPECIFICATION — which is exactly why it is a LIST and no longer a ladder.
196
+ * The header of this module says it in as many words: "the earlier one wins, and swapping two guards changes the game
197
+ * without breaking anything a build, a `tsc` or an eye could see". A ladder buries that claim in indentation; an array
198
+ * states it. Moving two questions is now moving two lines, and reading the precedence is
199
+ * reading the array from the top.
200
+ *
201
+ * ⚠️ Eight questions here and the ninth below, and the asymmetry is the point: the first eight may DECLINE, and
202
+ * normal play never does. Putting it in the list would give the list a member whose null can never happen, and
203
+ * would cost every caller a branch for a case that does not exist.
204
+ *
205
+ * 📌 The comments are the ones each question always carried, moved with the code they explain — a comment left
206
+ * behind starts explaining code that is no longer there (ADR-0171).
223
207
  */
224
- export function decideKeydown(ev, s) {
225
- const code = ev.code;
226
- // 1..3 · diálogo aberto BLOQUEIA o jogo — mas só se o elemento estiver DE FATO visível (uma flag presa não
227
- // trava mais o teclado). Os três saem sem `preventDefault`, verbatim: o diálogo é DOM e quer o comportamento
228
- // nativo do navegador (Tab, digitação num range) por baixo.
229
- if (s.escapeTargetId)
230
- return { kind: 'overlay', closeId: code === 'Escape' ? s.escapeTargetId : null, preventDefault: false };
231
- if (s.touchCfgVisible)
232
- return { kind: 'touchcfg', close: code === 'Escape', preventDefault: false };
233
- if (s.padWizVisible)
234
- return { kind: 'padwiz', close: code === 'Escape', preventDefault: false };
235
- // 4..5 · fim de fase / título. O pulo de QUALQUER jogador aciona o botão principal, sem depender do foco do
236
- // mouse (clicar na tela tirava o foco do botão e o teclado parava de funcionar — report do José).
237
- const action2 = isJumpKey(code, s);
238
- const pauseKey = PAUSE_KEYS.has(code);
239
- if (s.winVisible) {
240
- const again = action2 || pauseKey;
208
+ const CHAIN = [
209
+ // 1..3 · an open dialog BLOCKS the game — but only if the element is REALLY visible (a stuck flag does not lock the
210
+ // keyboard). The three leave without `preventDefault`: the dialog is DOM and wants the browser's native behaviour
211
+ // (Tab, typing in a range) underneath.
212
+ (_ev, s, f) => (s.escapeTargetId
213
+ ? { kind: 'overlay', closeId: f.code === 'Escape' ? s.escapeTargetId : null, preventDefault: false }
214
+ : null),
215
+ (_ev, s, f) => (s.touchCfgVisible ? { kind: 'touchcfg', close: f.code === 'Escape', preventDefault: false } : null),
216
+ (_ev, s, f) => (s.padWizVisible ? { kind: 'padwiz', close: f.code === 'Escape', preventDefault: false } : null),
217
+ // 4 · end of the level. ANY player's jump presses the main button, without depending on the mouse's focus (clicking
218
+ // the screen took focus off the button and the keyboard stopped working — the Dev's report).
219
+ (_ev, s, f) => {
220
+ if (!s.winVisible)
221
+ return null;
222
+ const again = f.action2 || f.pauseKey;
241
223
  return { kind: 'win', again, preventDefault: again };
242
- }
243
- if (s.telaDeTitulo) {
244
- // multi-tela: só o Jogador 1 escolhe o jogo. A tecla de um dos outros é consumida com um aviso falado.
245
- if (s.numPlayers > 1 && s.whichPlayer(code) > 0)
224
+ },
225
+ // 5 · title.
226
+ (_ev, s, f) => {
227
+ if (!s.titleScreen)
228
+ return null;
229
+ // multi-screen: only Player 1 picks the game. Another player's key is consumed with a spoken notice.
230
+ if (s.numPlayers > 1 && s.whichPlayer(f.code) > 0)
246
231
  return { kind: 'title', wait: true, nav: null, preventDefault: true };
247
- const nav = titleNavOf(code, s, action2);
232
+ const nav = titleNavOf(f.code, s, f.action2);
248
233
  const has = hasTitleIntent(nav);
249
234
  return { kind: 'title', wait: false, nav: has ? nav : null, preventDefault: has };
250
- }
251
- // 6..7 · número de telas e pausa. As DUAS exigem quiz FECHADO: com um desafio aberto na tela, Alt+3 não pode
252
- // reconfigurar o jogo por baixo dele, e Enter é a confirmação do quiz, não a pausa.
253
- const anyModal = s.modalOpen.some(Boolean);
254
- const inGame = s.emJogo;
255
- if (ev.altKey && !ev.ctrlKey && SCREEN_DIGITS.test(code) && inGame && !anyModal) {
256
- return { kind: 'screens', count: +code.slice(5), preventDefault: true };
257
- }
258
- if (!anyModal && pauseKey && inGame)
259
- return { kind: 'pause', preventDefault: true };
260
- // 8 · modal. A tecla age no modal do DONO dela; genérica cai no P1. `preventDefault` NÃO depende de a
261
- // tecla ter significado lá dentro: basta ser tecla de jogo — o desafio engole a tecla de qualquer forma.
262
- if (anyModal) {
263
- const owner = modalOwnerIndex(code, s);
264
- if (owner >= 0) {
265
- return { kind: 'modal', playerIndex: owner, intent: modalIntentOf(code, s, owner, s.whichPlayer(code) < 0),
266
- preventDefault: s.controls.gameKeys.includes(code) };
267
- }
268
- // tecla de um jogador SEM modal cai no jogo normal (a partida dele continua) — segue adiante
269
- }
270
- // 9 · jogo normal.
235
+ },
236
+ // 6..7 · number of screens and pause. BOTH require no modal open: with a challenge open on screen, Alt+3 must not
237
+ // reconfigure the game beneath it, and Enter is the challenge's confirmation, not the pause.
238
+ (ev, s, f) => (ev.altKey && !ev.ctrlKey && SCREEN_DIGITS.test(f.code) && s.inGame && !f.anyModal
239
+ ? { kind: 'screens', count: +f.code.slice(5), preventDefault: true }
240
+ : null),
241
+ (_ev, s, f) => (!f.anyModal && f.pauseKey && s.inGame ? { kind: 'pause', preventDefault: true } : null),
242
+ // 8 · modal. The key acts on its OWNER's modal; a generic one falls to P1. `preventDefault` does NOT depend on the key
243
+ // meaning something inside: being a game key is enough — the challenge swallows the key either way.
244
+ (_ev, s, f) => {
245
+ if (!f.anyModal)
246
+ return null;
247
+ const owner = modalOwnerIndex(f.code, s);
248
+ // a key of a player WITHOUT a modal falls to normal play (their match goes on) — move along
249
+ if (owner < 0)
250
+ return null;
251
+ return {
252
+ kind: 'modal', playerIndex: owner, intent: modalIntentOf(f.code, s, owner, s.whichPlayer(f.code) < 0),
253
+ preventDefault: s.controls.gameKeys.includes(f.code),
254
+ };
255
+ },
256
+ ];
257
+ /** 9 · normal play — the one question that ALWAYS answers, and so the one that closes the chain instead of being in it. */
258
+ function playDecision(s, f) {
259
+ const code = f.code;
271
260
  const gameKey = isEasyShortcut(code, s) || isGameKeyCode(code, s);
272
261
  const wake = s.players.reduce((acc, p, idx) => { if (p.waiting && s.actionOf(code, p.i))
273
262
  acc.push(idx); return acc; }, []);
274
263
  const edges = s.heldKeys.has(code) ? [] : edgesFor(code, s);
275
- // Empatia motora (um botão por vez): a tecla nova entra e as OUTRAS de jogo saem. `keys.add` vem depois da
276
- // limpeza no wrapper, então a recém-chegada sobrevive mesmo se já estivesse na lista.
264
+ // Motor empathy (one button at a time): the new key comes in and the OTHER game keys go out. The hold comes after the
265
+ // clearing in the wrapper, so the newcomer survives even if it was already on the list.
277
266
  const releaseKeys = s.oneButton && gameKey ? [...s.heldKeys].filter((k) => isGameKeyCode(k, s)) : [];
278
267
  return { kind: 'play', gameKey, wake, edges, releaseKeys, preventDefault: gameKey };
279
268
  }
269
+ /**
270
+ * THE CHAIN. Nine questions, in this order — and the order IS the specification.
271
+ * What is NOT here, and comes first in the wrapper: the demo (attract) and the remapping capture. See the header.
272
+ */
273
+ export function decideKeydown(ev, s) {
274
+ const facts = {
275
+ code: ev.code, action2: isJumpKey(ev.code, s), pauseKey: PAUSE_KEYS.has(ev.code), anyModal: s.modalOpen.some(Boolean),
276
+ };
277
+ for (const ask of CHAIN) {
278
+ const decided = ask(ev, s, facts);
279
+ if (decided)
280
+ return decided;
281
+ }
282
+ return playDecision(s, facts);
283
+ }
280
284
  export function initKeydown(ctx) {
281
- /** Diálogo aberto = elemento que existe E não está `hidden`. Verbatim do `dlgVis` do monólito, que nasceu
282
- * justamente para uma flag presa em `true` não travar o teclado do jogo inteiro. */
285
+ const { t } = ctx;
286
+ /** An open dialog = an element that exists AND is not `hidden` — so a flag stuck on `true` cannot lock the whole
287
+ * game's keyboard. */
283
288
  const visible = (id) => { const el = ctx.$('#' + id); return !!el && !el.hidden; };
284
289
  function snapshot() {
285
290
  return {
286
- telaDeTitulo: ctx.isTelaDeTitulo(), emJogo: ctx.isEmJogo(), numPlayers: ctx.getNumPlayers(), players: ctx.getPlayers(), controls: ctx.getControls(),
287
- // A RESPOSTA, ao lado dos jogadores — e montada aqui, onde eles já estão na mão (ADR-0033).
291
+ titleScreen: ctx.isTitleScreen(), inGame: ctx.isInGame(), numPlayers: ctx.getNumPlayers(), players: ctx.getPlayers(), controls: ctx.getControls(),
292
+ // THE ANSWER, beside the players — built here, where they are already in hand (ADR-0033).
288
293
  modalOpen: ctx.getPlayers().map((_, i) => ctx.hasModal(i)),
289
294
  heldKeys: ctx.heldKeys, oneButton: ctx.isOneButton(),
290
295
  escapeTargetId: ctx.escapeTarget(),
@@ -292,110 +297,100 @@ export function initKeydown(ctx) {
292
297
  actionOf: ctx.actionOf, whichPlayer: ctx.whichPlayer,
293
298
  };
294
299
  }
295
- /** A metade IMPURA: pega a decisão pronta e a carimba no mundo. */
296
- function apply(d, code, origem) {
297
- switch (d.kind) {
298
- case 'overlay':
299
- if (d.closeId)
300
- ctx.closeOverlayById(d.closeId);
300
+ /**
301
+ * ⚠️ THE SOURCE COMES FROM THE EVENT AND IS NOT INVENTED HERE (ADR-0109). `transport` is `undefined` for an event
302
+ * nobody signed — every real key — and then the narrow door ERASES the previous entry instead of letting the key
303
+ * inherit whoever held it last time. See `markKeyWithoutSource`.
304
+ *
305
+ * 📌 THE EDGE FEEDS THE AUTOMATON AT THE SAME POINT AND UNDER THE SAME CONDITION the source is written on the key — an
306
+ * unknown source is no device's edge, and inventing `teclado` for it would let a touch key turn off the latch of
307
+ * whoever plays by gaze, with no error and mid-match.
308
+ * ⚠️ A generic key (no owner) counts for player 1, the same convention as `ui/menu-nav`: whoever presses a key that
309
+ * belongs to no seat is playing in the first seat.
310
+ */
311
+ function rememberWhoPressed({ code, transport }) {
312
+ // one question: a key with no source says so and stops; a key with one marks it and the seat's transport
313
+ if (!transport) {
314
+ ctx.markKeyWithoutSource(code);
315
+ return;
316
+ }
317
+ ctx.markKey(code, transport);
318
+ const keyOwner = ctx.whichPlayer(code);
319
+ ctx.playerEdge(keyOwner < 0 ? 0 : keyOwner, transport);
320
+ }
321
+ const EFFECTS = {
322
+ overlay: (d) => { if (d.closeId)
323
+ ctx.closeOverlayById(d.closeId); },
324
+ touchcfg: (d) => { if (!d.close)
325
+ return; const el = ctx.$('#touchcfg'); if (el)
326
+ el.hidden = true; },
327
+ padwiz: (d) => { if (d.close)
328
+ ctx.closePadWiz(false); }, // the pad wizard: Esc CANCELS (does not save)
329
+ win: (d) => {
330
+ if (!d.again)
301
331
  return;
302
- case 'touchcfg': {
303
- if (!d.close)
304
- return;
305
- const t = ctx.$('#touchcfg');
306
- if (t)
307
- t.hidden = true;
332
+ const b = ctx.$('#btn-again');
333
+ if (b)
334
+ b.click();
335
+ },
336
+ title: (d) => {
337
+ ctx.hideTouchControls(); // the keyboard on the title hides the virtual controls — BEFORE the notice
338
+ if (d.wait) {
339
+ ctx.srSay(t('sr.title.waitP1'));
308
340
  return;
309
341
  }
310
- case 'padwiz':
311
- if (d.close)
312
- ctx.closePadWiz(false);
313
- return; // wizard de gamepad: Esc CANCELA (não salva)
314
- case 'win': {
315
- if (!d.again)
316
- return;
317
- const b = ctx.$('#btn-again');
318
- if (b)
319
- b.click();
320
- return;
342
+ if (d.nav)
343
+ ctx.navTitle(d.nav);
344
+ },
345
+ screens: (d) => ctx.activateScreens(d.count),
346
+ pause: () => ctx.togglePause(),
347
+ // THE INDEX, NOT THE PLAYER: looking the player up here would only pass on an object whose challenge this module
348
+ // cannot describe — which is exactly what the other side needs to read.
349
+ modal: (d) => { if (d.intent)
350
+ ctx.modalInput(d.playerIndex, d.intent); },
351
+ play: (d, key) => {
352
+ const players = ctx.getPlayers();
353
+ if (d.gameKey)
354
+ ctx.hideTouchControls('teclado'); // playing on the keyboard hides the touch buttons
355
+ for (const idx of d.wake) { // THAT player's key activates the screen on standby
356
+ const p = players[idx];
357
+ if (!p)
358
+ continue;
359
+ p.waiting = false;
360
+ ctx.clearWaitingBadge(p.i);
361
+ ctx.srSay(t('sr.player.entered', { n: p.i + 1 }));
321
362
  }
322
- case 'title':
323
- ctx.hideTouchControls(); // teclado no splash oculta os controles virtuais — ANTES do aviso, verbatim
324
- if (d.wait) {
325
- ctx.srSay(t('sr.title.waitP1'));
326
- return;
327
- }
328
- if (d.nav)
329
- ctx.navTitle(d.nav);
330
- return;
331
- case 'screens':
332
- ctx.activateScreens(d.count);
333
- return;
334
- case 'pause':
335
- ctx.togglePause();
336
- return;
337
- case 'modal': {
338
- // A BUSCA DO JOGADOR SAIU DAQUI: este módulo a fazia só para repassar o objeto, e o objeto que ele
339
- // sabia descrever não tinha `quiz` — que é justamente o que o outro lado precisa ler. Passa o índice.
340
- if (!d.intent)
341
- return;
342
- ctx.modalInput(d.playerIndex, d.intent);
343
- return;
363
+ for (const { playerIndex, edge } of d.edges) {
364
+ const p = players[playerIndex];
365
+ if (p)
366
+ p[edge] = true;
344
367
  }
345
- case 'play': {
346
- const players = ctx.getPlayers();
347
- if (d.gameKey)
348
- ctx.hideTouchControls('teclado'); // E13: jogar no teclado oculta os botões de toque
349
- for (const idx of d.wake) { // a tecla DAQUELE jogador ativa a tela em espera
350
- const p = players[idx];
351
- if (!p)
352
- continue;
353
- p.waiting = false;
354
- ctx.clearWaitingBadge(p.i);
355
- ctx.srSay(t('sr.player.entered', { n: p.i + 1 }));
356
- }
357
- for (const { playerIndex, edge } of d.edges) {
358
- const p = players[playerIndex];
359
- if (p)
360
- p[edge] = true;
361
- }
362
- for (const k of d.releaseKeys)
363
- ctx.soltarTecla(k);
364
- // ⚠️ A ORIGEM CHEGA DO EVENTO E NÃO É INVENTADA AQUI (ADR-0109). `origem` é `undefined` só para o
365
- // evento sintético que ninguém assinou — e nesse caso a porta estreita APAGA a entrada anterior, em
366
- // vez de deixar a tecla herdar de quem a segurou da última vez. Ver `marcarTeclaSemOrigem`.
367
- if (origem)
368
- ctx.marcarTecla(code, origem);
369
- else
370
- ctx.marcarTeclaSemOrigem(code);
371
- // 📌 A ARESTA ALIMENTA O AUTÓMATO NO MESMO PONTO E SOB A MESMA CONDIÇÃO em que a origem é gravada na
372
- // tecla — origem desconhecida não é aresta de aparelho nenhum, e inventar-lhe `teclado` faria uma
373
- // tecla do toque desligar a alternância de quem joga por olhar, sem erro e no meio da partida.
374
- // ⚠️ Tecla genérica (sem dono) conta para o jogador 1, que é a mesma convenção do `ui/menu-nav`: quem
375
- // carrega numa tecla que não é de assento nenhum está a jogar no primeiro assento.
376
- if (origem) {
377
- const dono = ctx.whichPlayer(code);
378
- ctx.arestaDoJogador(dono < 0 ? 0 : dono, origem);
379
- }
380
- return;
381
- }
382
- }
368
+ for (const k of d.releaseKeys)
369
+ ctx.releaseKey(k);
370
+ rememberWhoPressed(key);
371
+ },
372
+ };
373
+ /** Takes the ready decision and stamps it on the world. */
374
+ function apply(d, key) {
375
+ // ⚠️ The cast is the one thing the mapped type does not give for free: TypeScript does not narrow `d` and the table
376
+ // entry at the same time. The exhaustiveness — which is what matters — is guaranteed above.
377
+ EFFECTS[d.kind](d, key);
383
378
  }
384
379
  function onKeydown(e) {
385
380
  if (ctx.attractOnInput()) {
386
381
  e.preventDefault();
387
382
  return;
388
- } // qualquer tecla encerra a demo
383
+ } // any key ends the demo
389
384
  if (ctx.handleCaptureKeydown(e))
390
- return; // remap: a próxima tecla vira o controle
385
+ return; // remap: the next key becomes the control
391
386
  const d = decideKeydown(e, snapshot());
392
387
  if (d.preventDefault)
393
388
  e.preventDefault();
394
- apply(d, e.code, origemDoEvento(e));
389
+ apply(d, { code: e.code, transport: sourceOfEvent(e) });
395
390
  }
396
- // ⚠️ SOLTA NOS DOIS. Um `keys.delete` cru deixava a origem para trás, e um mapa que descreve teclas que já
397
- // ninguém segura responde à alternância com o aparelho errado — sem erro, e só na aresta seguinte.
398
- function onKeyup(e) { ctx.soltarTecla(e.code); }
391
+ // ⚠️ IT RELEASES IN BOTH. A raw `keys.delete` would leave the source behind, and a map describing keys nobody holds
392
+ // answers the latch with the wrong device — with no error, and only on the next edge.
393
+ function onKeyup(e) { ctx.releaseKey(e.code); }
399
394
  function attach() {
400
395
  ctx.win.addEventListener('keydown', onKeydown);
401
396
  ctx.win.addEventListener('keyup', onKeyup);