@the-inclusionist/engine 8.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 +467 -162
  307. package/dist-pkg/boot/create-game.js +3563 -426
  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 +250 -343
  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,201 +1,121 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // ui/menu-nav.ts — NAVEGAÇÃO UNIVERSAL de menus e diálogos: andar, escolher e voltar sem mouse.
2
+ // ui/menu-nav.ts — UNIVERSAL menu and dialog navigation: move, choose and go back without a mouse.
3
3
  //
4
- // Este módulo é acessibilidade pura, e é o coração do pilar de a11y no que diz respeito a operação por
5
- // teclado (WCAG 2.1.1) e a ordem de foco (2.4.3). A regra que ele encarna é a do projeto, escrita no game.js
6
- // antes de qualquer código: QUALQUER menu aberto — o de pausa OU um submenu de configuração — é navegável
7
- // pelos MESMOS seis gestos, e esses seis gestos valem igualmente para teclado, controle, olhos e fala:
8
- // · cima/baixo/esquerda/direita — andam entre itens; nos `select`/`slider`, esquerda/direita AJUSTAM o valor
9
- // · sim — confirma, alterna, entra
10
- // · não — volta ao menu anterior; na raiz, volta ao jogo (= Continuar)
11
- // Por isso o módulo não fala em "tecla": ele fala em INTENÇÃO (`NavKeys`). O teclado é só um dos tradutores —
12
- // input/gamepad.ts monta exatamente o mesmo `{yes,no,up,down,left,right}` e chama `navDialog`/`navPause` daqui.
13
- // É essa forma comum que faz "o jogo inteiro é operável de seis maneiras" ser verdade por construção e não por
14
- // disciplina.
4
+ // Operation by keyboard (WCAG 2.1.1) and focus order (2.4.3). Any open menu — the pause card or a settings panel —
5
+ // answers the SAME six intents, whether they come from the keyboard, a controller, the eyes or speech:
6
+ // · up/down/left/right — move between items; on a list, a slider or a steps control, left/right ADJUST the value
7
+ // · yes — confirm, toggle, enter
8
+ // · no — back one level; at the pause card's root, back to the game
9
+ // So the module speaks of INTENT (`NavKeys`), never of keys. The keyboard is one translator (`menuNavKey`, below);
10
+ // `input/gamepad` builds the same `NavKeys` and calls `navDialog`/`navPause` from here. That shared shape is what makes
11
+ // «every menu works six ways» true by construction rather than by discipline.
15
12
  //
16
- // O QUE VEIO, E DE ONDE (bloco "NAVEGAÇÃO UNIVERSAL de menus" do game.js)
17
- // · `sharedDialogOpen` · `menuItems` · `menuFocus` · `dialogBack` — a leitura do "onde estou" e o voltar.
18
- // · `navDialog` — andar dentro de um diálogo de configuração (o único lugar que ajusta select/slider).
19
- // · `pauseSetSel` · `navPause` — andar dentro de um menu de pausa, que NÃO usa foco do navegador e sim uma
20
- // classe de seleção própria (`.pm-sel`/`.pi-sel`), porque ele é desenhado dentro da tela do jogador.
21
- // · `menuNavKey` — o tradutor de teclado, em fase de CAPTURA.
13
+ // TWO KINDS OF MENU. A settings panel selects by browser FOCUS (`navDialog`). The pause card is drawn inside the player's
14
+ // screen and selects by a CLASS (`.pm-sel`, `navPause`) — and a class fires no announcement, which is why the pause card
15
+ // speaks its items through `srSay` and a panel does not need to for its focus.
22
16
  //
23
- // A DUPLICAÇÃO QUE ESTA EXTRAÇÃO CUROU
24
- // `sharedDialogOpen` do game.js e `topVisibleOverlay` de ui/settings-panel.ts eram A MESMA FUNÇÃO escrita
25
- // duas vezes: mesmo seletor de escopo (`#game-region .overlay`), mesmo filtro (`!hidden`), mesma ordenação
26
- // estável por z-index efetivo, mesmo "vence o último". Conferi as duas linha a linha antes de unificar. Aqui
27
- // `sharedDialogOpen` é um ALIAS de `ctx.topVisibleOverlay` — o nome antigo sobrevive porque input/gamepad.ts o
28
- // consome por esse nome, mas o CÓDIGO agora existe uma vez só, em ui/settings-panel.ts. O ganho não é linha de
29
- // menos: enquanto eram duas, uma correção de escopo (é justamente o que o defeito 1 abaixo pede) podia ser
30
- // aplicada num lado e não no outro, e o sintoma seria "às vezes o foco volta".
17
+ // `sharedDialogOpen` is an ALIAS of `ui/settings-panel.topVisibleOverlay`, not a copy: the two were once the same function
18
+ // written twice, and a scope fix applied to one would not have reached the other.
31
19
  //
32
- // ======================= DOIS DEFEITOS CONHECIDOS — PRESERVADOS VERBATIM, NÃO CONSERTE =======================
20
+ // ======================= TWO KNOWN DEFECTS, PINNED BY TESTS — DO NOT FIX ONE WITHOUT THE OTHER =======================
33
21
  //
34
- // DEFEITO 1 — o escopo de `sharedDialogOpen` não alcança os menus de pausa (WCAG 2.4.3 · foco perdido).
35
- // O escopo é `#game-region .overlay`. Os nove diálogos de configuração estão lá (o `inCanvasMenus()` do game.js
36
- // reparenta os onze elementos para dentro do `#game-region`), MAS os menus de pausa por tela são
37
- // `.screen-pause` — classe diferente, construída por ui/pause-icons.ts, e nunca `.overlay`. Consequência:
38
- // `menuFocus(sharedDialogOpen())` devolve `null` quando o último diálogo se fecha, `menuFocus` sai pelo guarda
39
- // de nulo, e o foco fica no botão que acabou de ficar `hidden` — o navegador o joga no `<body>`. Quem sofre são
40
- // `#typo` (closeTypo) e `#help` (closeHelp), os dois únicos que devolvem o foco por esse caminho.
22
+ // DEFECT 1 — `sharedDialogOpen`'s scope does not see the pause card (WCAG 2.4.3, focus lost). The scope is
23
+ // `#game-region .overlay`; the pause card is `.screen-pause`, never `.overlay`. When the last dialog closes over an open
24
+ // pause card, `menuFocus(sharedDialogOpen())` receives `null`, leaves at its guard, and the focus stays on a button that
25
+ // has just become hidden — the browser drops it on `<body>`.
41
26
  //
42
- // O QUE EU VERIFIQUEI ANTES DE ESCREVER ISTO (a nota do coordenador estava certa, e a conclusão dela também):
43
- // li os NOVE `close*` e o `app/index.html` inteiro, um por um. De todos os nove, só UM devolve o foco de fato:
44
- // · touchcfg → `#opt-touchcfg` — EXISTE (index.html, dentro do painel #movement). Funciona.
45
- // · options → `#opt-controls` — NÃO existe no index.html. No-op silencioso.
46
- // · movement → `#opt-movement` — NÃO existe. No-op.
47
- // · visual → `#opt-visual` — NÃO existe. No-op.
48
- // · audio → `#opt-sound` — NÃO existe. No-op.
49
- // · animation → `#opt-animation` — NÃO existe (o próprio game.js já anota isso na linha do `#animation-close`).
50
- // · empathy → `#opt-empathy` — NÃO existe. No-op.
51
- // · typo/help → `menuFocus(sharedDialogOpen())` — o caminho quebrado descrito acima.
52
- // Os ids que EXISTEM no index.html com prefixo `opt-` são: opt-title, opt-telas, opt-letra, opt-facil,
53
- // opt-altmove, opt-touchcfg, opt-eyes, opt-modocego, opt-tts, opt-onebtn, opt-wheelchair, opt-hearing,
54
- // opt-captions. Nenhum `#opt-visual`/`#opt-sound`/`#opt-movement`/`#opt-controls`/`#opt-empathy`/`#opt-animation`
55
- // — são ganchos para uma barra de botões que ainda não existe. Ou seja: NÃO é "sete certos e dois errados". É
56
- // "um certo e oito quebrados, por duas causas diferentes" — e a causa dos oito (botão inexistente) não é a
57
- // mesma dos dois (escopo do seletor). Quem consertar precisa saber disso, porque arrumar só o escopo deixa oito
58
- // painéis ainda largando o foco.
27
+ // DEFECT 2 — Escape is resolved in CAPTURE, by z-index, and consumed with `stopPropagation()`. `menuNavKey` runs before
28
+ // any bubble listener on the window, so the topmost visible dialog is the one that closes, and the registration-order
29
+ // chain (`overlays.escapeTarget()`, read by `input/keydown`) never decides while a dialog is open. Escape is also the same
30
+ // intent as action3 (`no`): at the pause card's root it means «back to the game», and nothing tells «close a dialog» from
31
+ // «leave the pause» apart. The capture and the `stopPropagation()` are also what keep a later window listener — a game's
32
+ // own keydown — from acting on the same Escape: removing them without a replacement lets one key do two things.
59
33
  //
60
- // DEFEITO 2 — `menuNavKey` trata Escape como "voltar", em CAPTURA, com `stopPropagation()`, e resolve por
61
- // z-index em vez de pela cadeia registrada. `addEventListener('keydown', menuNavKey, true)` roda ANTES do
62
- // ouvinte principal do game.js (que é de BOLHA, na mesma janela); o `stopPropagation()` na fase de captura
63
- // impede o evento de descer e, portanto, de voltar — o ouvinte de bolha nunca vê a tecla. Efeitos verificados
64
- // lendo os dois ouvintes lado a lado:
65
- // (a) a cadeia `overlays.escapeTarget()` (ORDEM DE REGISTRO: options→movement→animation→visual→empathy→
66
- // audio→typo→touchcfg→help) é código morto com o jogo pausado. Quem decide é o topo da pilha de z-index.
67
- // O próprio game.js já anota isso ("MEDIDO no navegador") no ouvinte de bolha.
68
- // (b) `#help` e `#touchcfg` estão registrados com `inEscapeChain:false` e por isso ficam fora da cadeia de Escape.
69
- // Enquanto a captura os cobrir por z-index, Escape os fecha; se alguém tirar o `stopPropagation()` ou a
70
- // fase de captura sem antes dar flag aos dois, a tecla cai no ouvinte de bolha e o
71
- // `if(Escape||Enter) togglePause()` de lá DESPAUSA O JOGO com o diálogo de Ajuda ainda aberto.
72
- // Ou seja: o comportamento correto de hoje depende de um `stopPropagation()`, não da cadeia — é uma rede
73
- // de segurança acidental, e é exatamente o que o conserto vai mexer.
74
- // (c) Escape é a MESMA intenção que "especial" do gamepad (`no`). Não há como distinguir "fechar diálogo" de
75
- // "voltar ao jogo" — na raiz do menu de pausa, `no` faz `setPhase('playing')`.
76
- // `menuNavKey` é exportado por si só (e não só instalado) justamente para o teste poder dispará-lo sem depender
77
- // de fase de propagação, e `attach()` existe para o game.js instalar exatamente como antes.
34
+ // `tests/menu-nav.browser.test.js` and `tests/menu-nav.node.test.js` pin both as they are today, and fail on purpose if
35
+ // the region is «improved» without the whole fix. `menuNavKey` is exported on its own so a test can fire it without
36
+ // depending on the propagation phase; `attach()` installs it.
37
+ // ======================================================================================================================
78
38
  //
79
- // Os testes de `menu-nav` PINAM os dois comportamentos ACIMA como estão hoje. Eles falham de propósito se
80
- // alguém "melhorar" a região sem tratar o conserto inteiro — que é o ponto: o conserto futuro precisa da rede.
81
- // ============================================================================================================
39
+ // WHAT IS NOT HERE: the overlay stack, the registry and closing by id belong to `ui/settings-panel` — this module
40
+ // consumes `topVisibleOverlay` and `closeById` and reimplements nothing. The quick bar belongs to `ui/pause-icons`; this
41
+ // module only asks whether a screen is on it (`onBar`) and hands it a step (`navBar`).
82
42
  //
83
- // O QUE FICOU DE FORA, E POR QUÊ
84
- // · `updateTitleLegend` foi para ui/shell.ts, não para cá. Ela não navega nada — não lê foco, não trata tecla,
85
- // não anda entre itens; pinta o rodapé de UMA tela (o título) e quem a chama é `setPhase('title')`. Trazê-la
86
- // obrigaria a casca a importar o módulo de navegação só para desenhar uma legenda.
87
- // · `padKind()` não veio para lugar nenhum: JÁ ESTÁ em `input/touch.ts` (Onda A), com corpo idêntico, e a
88
- // cópia do game.js não tem chamador nenhum. É código morto duplicado — apagar, não mover.
89
- // · `navTitle`/`titleButtons` são de ui/activities-menu.ts (menu inicial), já extraídos.
90
- // · A pilha de z-index, o registro de overlays e o fechar por id são de ui/settings-panel.ts. Este módulo
91
- // CONSOME (`topVisibleOverlay`, `closeById`) e não reimplementa.
43
+ // INJECTION: nothing is reached. `isNavigable`, `withIndex` and `onBar` are QUESTIONS asked of the ctx rather than state
44
+ // read from `core/state`, so a game answers in its own model — a quiz whose settings are always open answers
45
+ // `isNavigable(): true` without pretending to be paused. `getPauseMenu`, `closePadWiz`, `isCapturing` and `setPhase` are
46
+ // resolved at call time, because what they reach is built in the root after this module.
92
47
  //
93
- // INJEÇÃO E ORDEM DE BOOT
94
- // · `phase` entra como binding vivo de core/state.ts (deixou de ser `let` do game.js na Fase 2) — mesmo
95
- // precedente de game/session.ts e input/touch.ts. O que AINDA é `let` do game.js entra por getter:
96
- // `vpPause` (`getPauseMenu(i)`), reatribuído por `buildGameHud`.
97
- // · `closePadWiz` é LAZY (`(save) => gamepadApi.closePadWiz(save)`): input/gamepad.ts é `const` do game.js e o
98
- // ctx DELE consome `sharedDialogOpen`/`navDialog`/`navPause` daqui. A dependência é mútua, e a única forma
99
- // de quebrar o ciclo sem reordenar o boot é ela ser resolvida na CHAMADA. Mesmo motivo para `isCapturing`
100
- // (ui/settings-controls.ts) e para `setPhase` (o envelope içado do game.js sobre ui/shell.ts).
101
- // · `actionOf`/`whichPlayer` entram já ligados a input/keyboard-runtime.ts, que é `const` declarado bem no
102
- // alto do game.js — mas entram como callback mesmo assim, porque o roteamento por jogador é dele e não daqui.
103
- //
104
- // SEM I/O NO IMPORT: o corpo do módulo só declara dados e funções puras. Todo efeito passa por `initMenuNav`.
105
- //
106
- // Ver docs/5-Refactoring/plano-modularizacao-mapa.md (C3).
48
+ // NO I/O ON IMPORT: the module body only declares data and pure functions. Every effect goes through `initMenuNav`.
107
49
  // ---------------------------------------------------------------------------------------------------------
108
- // PURO — a decisão de navegação, sem DOM. Testável no project `node`.
50
+ // PURE — the navigation decision, without a DOM. Testable in the `node` project.
109
51
  // ---------------------------------------------------------------------------------------------------------
110
- /* As tabelas de tecla GENÉRICA (as que valem para qualquer jogador, mesmo sem remap). Viraram `Set` porque é
111
- o que elas sempre foram semanticamente — pertinência, não ordem — e porque um `Set` nomeado deixa a tabela
112
- auditável de fora (o teste importa a constante em vez de repetir os literais). Conteúdo VERBATIM. */
113
- /** Confirma/entra. `NumpadEnter` conta aqui (mas NÃO pausa: ver o ouvinte de bolha do game.js). */
114
- export const KEY_YES = new Set(['Space', 'KeyJ', 'Enter', 'NumpadEnter']);
115
- /** Volta. ⚠️ DEFEITO 2: `Escape` é a MESMA intenção que a ação "especial" do gamepad. Verbatim. */
116
- export const KEY_NO = new Set(['Escape']);
117
- export const KEY_UP = new Set(['ArrowUp', 'KeyW']);
118
- export const KEY_DOWN = new Set(['ArrowDown', 'KeyS']);
119
- export const KEY_LEFT = new Set(['ArrowLeft', 'KeyA']);
120
- export const KEY_RIGHT = new Set(['ArrowRight', 'KeyD']);
121
- /**
122
- * Traduz (tecla física, ação remapeada do dono da tecla) → intenção. `act` é `null` quando a tecla não é de
123
- * nenhum jogador (tecla genérica). Verbatim das seis linhas de `menuNavKey`.
124
- */
125
- export function menuKeyIntent(code, act) {
126
- return {
127
- yes: KEY_YES.has(code) || act === 'action2',
128
- no: KEY_NO.has(code) || act === 'action3',
129
- up: KEY_UP.has(code) || act === 'up',
130
- down: KEY_DOWN.has(code) || act === 'down',
131
- left: KEY_LEFT.has(code) || act === 'left',
132
- right: KEY_RIGHT.has(code) || act === 'right',
133
- };
134
- }
135
- /** Alguma intenção foi expressa? Definição única em input/edges; aqui só o nome que este módulo sempre teve. */
52
+ /** Was any intent expressed? Defined once in input/edges; here under the name this module has always used. */
136
53
  import { hasNavIntent as hasIntent } from '../input/edges.js';
137
- import { mostrarSubmenuDaPausa, PM_ITENS_VISIVEIS } from './pause-icons.js';
138
- import { anunciarItem } from './item-announcement.js';
139
- import { rotuloAcessivel } from '../core/rotulo-acessivel.js';
140
- import { passoNoAnel } from '../core/anel.js';
54
+ import { showPauseOptions, PM_VISIBLE_ITEMS } from './pause-icons.js';
55
+ import { announceItem } from './item-announcement.js';
56
+ import { accessibleLabel } from '../core/accessible-label.js';
57
+ import { stepInRing } from '../core/ring.js';
58
+ import { navigableItems } from './menu-items.js';
59
+ import { menuKeyIntent, selectStep, selectWrap, rangeStep, stepInPause } from './menu-intent.js';
141
60
  export { hasNavIntent as hasIntent } from '../input/edges.js';
142
- // A CONTA DO ANEL mudou de casa para `core/anel` no item 7 do ADR-0044: `ui/pause-icons` passou a precisar
143
- // dela, e como ESTE módulo já importa aquele, a volta fecharia um ciclo de importação — que em ESM não
144
- // estoura na hora, estoura no boot em TDZ. O nome público fica: é daqui que os menus e os testes já a
145
- // importavam, e mudar isso seria pedir uma edição em cada um deles para não ganhar nada.
146
- export { passoNoAnel } from '../core/anel.js';
147
- /** `select` com esquerda/direita: um passo, SEM dar a volta — ajustar VALOR não é navegar lista (ver acima). */
148
- export function selectStep(selectedIndex, optionsLen, delta) {
149
- return Math.max(0, Math.min(optionsLen - 1, selectedIndex + delta));
150
- }
151
- /** `select` com "sim": um passo, COM volta. É a diferença deliberada entre confirmar e ajustar. */
152
- export function selectWrap(selectedIndex, optionsLen) {
153
- return (selectedIndex + 1) % optionsLen;
154
- }
155
- /** `input[type=range]` com esquerda/direita: um `step` (default 1), preso entre `min` e `max`. */
156
- export function rangeStep(value, min, max, step, delta) {
157
- const st = step || 1; // `+cur.step||1`: step ausente/0/NaN vira 1, verbatim
158
- return Math.max(min, Math.min(max, value + delta * st));
159
- }
61
+ // The ring's arithmetic lives in `core/ring`: `ui/pause-icons` needs it too, and this module imports that one, so keeping
62
+ // it here would close an import cycle — which in ESM does not fail on the spot, it fails at boot in the TDZ. The public
63
+ // name stays here because the menus and the tests import it from here.
64
+ export { stepInRing } from '../core/ring.js';
65
+ // The items' selector lives in `ui/menu-items` (ADR-0158): what counts as an item is defined once, and the spoken
66
+ // «N of M» and the panel shell read the same list.
160
67
  /**
161
- * O PASSO DO CURSOR NO MENU DE PAUSA — um ANEL, agora que a pausa é uma lista (ADR-0044, itens 1 e 7).
68
+ * The parts a panel control SAYS (ADR-0159 rule 1, XAG 106: «Gamma, slider, 38%, 6 of 9»): the label with the ROLE, and
69
+ * the VALUE. The index is added by `announceItem`.
162
70
  *
163
- * ISTO SUBSTITUI `pauseGridMove`, e a substituição é o desfecho do ADR-0044, não uma limpeza. O que havia
164
- * era uma GRADE de duas zonas — a barra de dez ícones em cima, a lista de itens em duas colunas embaixo — e
165
- * uma fronteira entre elas com quatro regras próprias ("de cima, 'baixo' cai sempre no primeiro item", "da
166
- * primeira linha, 'cima' sobe para o ícone de mesmo índice", …). Cada regra dessas era uma coisa a mais para
167
- * a criança descobrir sem ver, e nenhuma delas era descobrível: só se aprendia esbarrando.
168
- *
169
- * A XAG 106 permite laço para menu LINEAR e o PROÍBE para grade de duas dimensões — numa grade, dar a volta
170
- * teleporta o cursor para o outro canto e a pessoa perde a noção de onde está. Era por isso que o anel do
171
- * item 1 valia para todo menu do jogo MENOS este. Com a barra no HUD (item 7), o cartão passou a ter uma
172
- * lista só, e o laço deixou de ser proibido para virar o recomendado.
173
- *
174
- * O que se ganha em troca das quatro regras: `quit` fica a UMA tecla para CIMA de `resume`. Último na
175
- * leitura, vizinho no dedo.
71
+ * The label is the row's `<strong>` when the control lives in one (it is what is SEEN, and a switch's text is its state,
72
+ * not its name); outside a row, or on a slider with a name of its own («Volume de Música»), it is the accessible name.
176
73
  */
177
- export function passoNaPausa(len, idx, k) {
178
- const d = (k.down || k.right) ? 1 : -1;
179
- return passoNoAnel(len, idx < 0 ? 0 : idx, d);
74
+ export function controlParts(t, el) {
75
+ const row = el.closest('.ctrl-row')?.querySelector('strong')?.textContent?.trim() || '';
76
+ const [, role, read] = CONTROL_KINDS.find(([recognises]) => recognises(el));
77
+ const { label, value } = read(el, row, accessibleLabel(el), t);
78
+ return { label: `${label}, ${t(role)}`, state: value };
180
79
  }
181
- /** Os controles que contam como "item navegável" de um menu. Verbatim do seletor do `menuItems`. */
182
- const ITEM_SELECTOR = 'button:not([disabled]), select:not([disabled]), input[type=range]:not([disabled])';
183
- /** Onde os itens moram: o card do diálogo (`.overlay__card`) ou o card da pausa (`.pause-card`). */
80
+ /** A slider's position as a whole percentage: a missing maximum reads as 100, and a range of zero width as 0. */
81
+ function sliderPercent(r) {
82
+ const min = +r.min || 0, max = +r.max || 100;
83
+ const pct = max > min ? Math.round(((+r.value - min) / (max - min)) * 100) : 0;
84
+ return `${pct}%`;
85
+ }
86
+ /**
87
+ * HOW EACH KIND OF CONTROL IS RECOGNISED AND READ, and the ORDER is the rule: the first row that recognises the element reads
88
+ * it, and the last — a button — recognises everything. A stepper and a slider prefer their own name (a slider can be «Music
89
+ * volume» on a row called «Sound»); the others prefer the row's label, because the text of a switch is its state, not its name.
90
+ */
91
+ const CONTROL_KINDS = [
92
+ [(el) => el.hasAttribute('data-passos'), 'sr.papel.passos',
93
+ (el, row) => ({ label: el.getAttribute('aria-label') || row, value: el.getAttribute('aria-valuetext') ?? '' })],
94
+ [(el) => el.tagName === 'SELECT', 'sr.papel.lista',
95
+ (el, row, name) => ({ label: row || name, value: el.selectedOptions?.[0]?.textContent?.trim() ?? '' })],
96
+ [(el) => el.tagName === 'INPUT', 'sr.papel.cursor',
97
+ (el, row) => ({ label: el.getAttribute('aria-label') || row, value: sliderPercent(el) })],
98
+ [(el) => el.hasAttribute('aria-pressed'), 'sr.papel.interruptor',
99
+ (el, row, name, t) => ({ label: row || name, value: t(el.getAttribute('aria-pressed') === 'true' ? 'state.on' : 'state.off') })],
100
+ [(el) => el.getAttribute('role') === 'radio', 'sr.papel.opcao',
101
+ (el, row, name, t) => ({ label: row || name, value: el.getAttribute('aria-checked') === 'true' ? t('sr.estado.selecionado') : '' })],
102
+ [() => true, 'sr.papel.botao', (_el, _row, name) => ({ label: name, value: '' })],
103
+ ];
104
+ /** Where the items live: the dialog's card (`.overlay__card`) or the pause card (`.pause-card`). */
184
105
  const CARD_SELECTOR = '.overlay__card, .pause-card';
185
106
  export function initMenuNav(ctx) {
186
- /* ===================== diálogos de configuração ===================== */
187
- // ALIAS, não cópia: o corpo mora em ui/settings-panel.ts. Ver "a duplicação que esta extração curou".
107
+ const { t } = ctx;
108
+ /* ===================== settings dialogs ===================== */
109
+ // An ALIAS, not a copy: the body lives in ui/settings-panel.ts (see the header).
188
110
  const sharedDialogOpen = () => ctx.topVisibleOverlay();
189
111
  function menuItems(menu) {
190
112
  const card = menu.querySelector(CARD_SELECTOR) || menu;
191
- // `offsetParent === null` = fora do fluxo de layout (escondido, `display:none` ou dentro de aba oculta).
192
- // É o único filtro de VISIBILIDADE real que existe aqui: sem ele o cursor pousa em botão invisível e o
193
- // leitor de tela anuncia um controle que ninguém vê. Verbatim.
194
- return [...card.querySelectorAll(ITEM_SELECTOR)].filter((el) => el.offsetParent !== null);
113
+ // The VISIBILITY filter (`offsetParent`) lives with the selector in `ui/menu-items`.
114
+ return navigableItems(card);
195
115
  }
196
116
  function menuFocus(menu) {
197
117
  if (!menu)
198
- return; // ⚠️ DEFEITO 1: com os menus de pausa fora do escopo, este guarda é o fim da linha
118
+ return; // ⚠️ DEFECT 1: with the pause card outside the scope, this guard is the end of the line
199
119
  const it = menuItems(menu);
200
120
  if (!it.length)
201
121
  return;
@@ -204,116 +124,158 @@ export function initMenuNav(ctx) {
204
124
  }
205
125
  function dialogBack(menu) {
206
126
  if (!ctx.closeById(menu.id))
207
- menu.hidden = true; // sem entrada no registro: some na marra
127
+ menu.hidden = true; // no registered entry: hide it outright
208
128
  menuFocus(sharedDialogOpen());
209
129
  }
210
- /** Ajusta um `select` (esquerda/direita = passo preso; sim = passo com volta) e dispara `change`. */
130
+ /** Adjusts a `select` (left/right = a step that stops at the ends; yes = a step that wraps) and fires `change`. */
211
131
  function tweakSelect(el, delta) {
212
132
  el.selectedIndex = delta === 'wrap' ? selectWrap(el.selectedIndex, el.options.length) : selectStep(el.selectedIndex, el.options.length, delta);
213
133
  el.dispatchEvent(new Event('change', { bubbles: true }));
214
134
  }
215
- /** Ajusta um `input[type=range]` em um `step` e dispara `input` (é o evento que os painéis escutam). */
135
+ /** Moves an `input[type=range]` by one `step` and fires `input` (the event the panels listen to). */
216
136
  function tweakRange(el, delta) {
217
137
  el.value = String(rangeStep(+el.value, +el.min, +el.max, +el.step, delta));
218
138
  el.dispatchEvent(new Event('input', { bubbles: true }));
219
139
  }
140
+ /**
141
+ * THE ITEM REACHED SAYS ITSELF (ADR-0159 rule 1): label, role, value and «N de M», in that order.
142
+ *
143
+ * The browser's focus moves by itself, but the engine's narration (the one a child playing in blind mode hears) does
144
+ * not listen to focus; it listens to this.
145
+ */
146
+ function sayItem(items, n) {
147
+ const el = items[n];
148
+ if (!el)
149
+ return;
150
+ const { label: partLabel, state: partState } = controlParts(t, el);
151
+ ctx.srSay(announceItem(t, { label: partLabel, state: partState, position: n + 1, total: items.length }, ctx.withIndex()));
152
+ }
153
+ function focusAndSay(items, n) {
154
+ items[n]?.focus();
155
+ sayItem(items, n);
156
+ }
157
+ /** Where the cursor is. With the focus outside the dialog (or on its card), it enters by the first item — and says it. */
158
+ function cursorIn(items) {
159
+ const idx = items.indexOf(ctx.getActiveElement());
160
+ if (idx >= 0)
161
+ return idx;
162
+ focusAndSay(items, 0);
163
+ return 0;
164
+ }
165
+ /**
166
+ * Left or right: a list, a slider or a steps control is ADJUSTED, and the new value is said — someone adjusting by ear has
167
+ * no other way to know where it stopped; anything else walks the ring, like up and down.
168
+ */
169
+ function sideways(items, idx, d) {
170
+ const cur = items[idx];
171
+ if (cur.tagName === 'SELECT') {
172
+ const before = cur.value;
173
+ tweakSelect(cur, d);
174
+ // an adjustment its owner refused (and put back) says nothing here: the owner already said why
175
+ if (cur.value !== before)
176
+ sayItem(items, idx);
177
+ return;
178
+ }
179
+ if (cur.tagName === 'INPUT') {
180
+ tweakRange(cur, d);
181
+ sayItem(items, idx);
182
+ return;
183
+ }
184
+ // A steps control ⯇ ⯈ (ADR-0151): left and right are the adjustment itself; its owner listens to `passo` (and announces).
185
+ if (cur.hasAttribute('data-passos')) {
186
+ cur.dispatchEvent(new CustomEvent('passo', { detail: d, bubbles: true }));
187
+ return;
188
+ }
189
+ focusAndSay(items, stepInRing(items.length, idx, d));
190
+ }
191
+ /** «Yes»: a list goes round and says the new option; a slider or a steps control has nothing to confirm; anything else is clicked. */
192
+ function confirm(items, idx) {
193
+ const cur = items[idx];
194
+ if (cur.tagName === 'SELECT') {
195
+ tweakSelect(cur, 'wrap');
196
+ sayItem(items, idx);
197
+ return;
198
+ }
199
+ if (cur.tagName === 'INPUT' || cur.hasAttribute('data-passos'))
200
+ return;
201
+ cur.click();
202
+ }
220
203
  function navDialog(menu, k) {
221
204
  const items = menuItems(menu);
222
205
  if (!items.length)
223
206
  return;
224
- let idx = items.indexOf(ctx.getActiveElement());
225
- if (idx < 0) {
226
- idx = 0;
227
- items[0].focus();
228
- } // foco fora do diálogo (ou no card): entra pelo primeiro
229
- const cur = items[idx];
207
+ const idx = cursorIn(items);
230
208
  if (k.no) {
231
209
  dialogBack(menu);
232
210
  return;
233
211
  }
234
212
  if (k.left || k.right) {
235
- const d = k.right ? 1 : -1;
236
- if (cur.tagName === 'SELECT') {
237
- tweakSelect(cur, d);
238
- return;
239
- }
240
- if (cur.tagName === 'INPUT') {
241
- tweakRange(cur, d);
242
- return;
243
- }
244
- items[passoNoAnel(items.length, idx, d)].focus();
213
+ sideways(items, idx, k.right ? 1 : -1);
245
214
  return;
246
215
  }
247
216
  if (k.up || k.down) {
248
- items[passoNoAnel(items.length, idx, k.down ? 1 : -1)].focus();
217
+ focusAndSay(items, stepInRing(items.length, idx, k.down ? 1 : -1));
249
218
  return;
250
219
  }
251
- if (k.yes) {
252
- if (cur.tagName === 'SELECT') {
253
- tweakSelect(cur, 'wrap');
254
- return;
255
- }
256
- if (cur.tagName === 'INPUT')
257
- return; // slider não tem "confirmar" — só ajuste
258
- cur.click();
259
- }
220
+ if (k.yes)
221
+ confirm(items, idx);
260
222
  }
261
- /* ===================== menu de pausa (seleção por classe, não por foco) ===================== */
223
+ /* ===================== pause card (selected by class, not by focus) ===================== */
262
224
  /**
263
- * Move o cursor do menu de pausa. Só ITENS: desde o item 7 do ADR-0044 a barra de ícones vive no HUD, e o
264
- * cursor dela é dela.
265
- *
266
- * O QUE SAIU DAQUI, e vale registrar: esta função também escrevia a legenda dos ícones, porque o cursor
267
- * atravessava a fronteira entre as duas zonas. Sem a fronteira, escrever legenda de ícone a partir do menu
268
- * de pausa seria um módulo mexendo na tela de outro.
225
+ * Moves the pause card's cursor. Items only: since ADR-0044 item 7 the quick bar lives in the HUD and keeps its own
226
+ * cursor — writing the bar's caption from here would be one module drawing on another's screen.
269
227
  */
270
228
  function pauseSetSel(menu, el) {
271
229
  if (!el)
272
- return; // índice fora da lista (menu vazio): não mexe em nada — verbatim
230
+ return; // an index outside the list (an empty card): touch nothing
273
231
  menu.querySelectorAll('.pm-sel').forEach((b) => b.classList.remove('pm-sel'));
274
232
  el.classList.add('pm-sel');
275
233
  }
276
234
  function navPause(menu, playerIndex, k) {
277
235
  if (k.no) {
278
- // "não" DENTRO do submenu de opções volta à raiz, e não ao jogo (ADR-0044, item 5). A regra "voltar sai
279
- // um nível" já valia para os diálogos de configuração (`dialogBack`); o que mudou é que o menu de pausa
280
- // passou a TER um nível a mais. Sem esta linha, quem entra em Opções sem enxergar só sairia despausando.
281
- const aberto = menu.querySelector('.pause-menu:not([hidden])');
282
- if (aberto && aberto.dataset.sub === 'opcoes') {
283
- mostrarSubmenuDaPausa(menu, 'raiz');
236
+ // «No» inside any sub-list goes up ONE level, to the root, and not back to the game (ADR-0044 item 5) — the same
237
+ // «back leaves one level» the settings dialogs have (`dialogBack`). The question is «is this NOT the root?», not
238
+ // «is this the options list?»: with three lists (ADR-0146), asking the second would make «no» from the game's own
239
+ // options resume the game when the child asked to go back.
240
+ const open = menu.querySelector('.pause-menu:not([hidden])');
241
+ if (open && open.dataset.sub && open.dataset.sub !== 'raiz') {
242
+ showPauseOptions(menu, 'raiz');
284
243
  return;
285
244
  }
286
245
  ctx.setPhase('playing');
287
- return; // "não" na raiz → volta ao jogo (retoma todos)
246
+ return; // «no» at the root → back to the game (resumes everyone)
288
247
  }
289
- const items = [...menu.querySelectorAll(PM_ITENS_VISIVEIS)];
248
+ const items = [...menu.querySelectorAll(PM_VISIBLE_ITEMS)];
290
249
  const cur = menu.querySelector('.pm-sel') || items[0];
291
- // "sim": o jogador que agiu vira o `pauseActor` (o submenu de a11y abre na aba dele) e o item é clicado.
250
+ // «Yes»: the player who acted becomes the `pauseActor` (the accessibility options open on their tab) and the item is clicked.
292
251
  if (k.yes) {
293
252
  ctx.setPauseActor(playerIndex);
294
253
  if (cur)
295
254
  cur.click();
296
255
  return;
297
256
  }
298
- // Guarda NOVA (o original estouraria em `cur.classList` aqui): menu sem `.pm-btn` nenhum. Não é o defeito
299
- // preservado — é um TypeError, e trocar um crash por um no-op não tira rede de conserto nenhum.
257
+ // A card with no item at all: nothing to move (without this guard the next line throws on `cur`).
300
258
  if (!cur)
301
259
  return;
302
- // UMA LISTA, um anel. A barra de ícones saiu do cartão no item 7 do ADR-0044, e com ela saíram as quatro
303
- // regras de fronteira que ninguém conseguia descobrir sem esbarrar.
304
- const n = passoNaPausa(items.length, items.indexOf(cur), k);
260
+ // ONE list, one ring: the quick bar is not in the card (ADR-0044 item 7), so there are no borders between zones to cross.
261
+ const n = stepInPause(items.length, items.indexOf(cur), k);
262
+ selectAndSayInPause(menu, items, n);
263
+ }
264
+ function selectAndSayInPause(menu, items, n) {
305
265
  pauseSetSel(menu, items[n]);
306
- // E O ITEM NOVO É FALADO. Este menu não usa foco do navegador — seleciona por classe, porque é desenhado
307
- // dentro da tela do jogador —, então nada dispara anúncio sozinho: nem foco, nem `aria-activedescendant`,
308
- // nem região viva. MEDIDO no jogo construído: a seta andava e o `#sr-status` ficava vazio. O item 3 do
309
- // ADR-0044 pede posição e total "em todo lugar", e este era o lugar onde ele não tinha chegado — o menu
310
- // que o item 5 reconstruiu.
311
- // `rotuloAcessivel` e não `textContent`: um item com `aria-label` seria narrado de um jeito pelo jogo e de
312
- // outro pelo leitor de tela, e quem ouve os dois não teria como saber qual é a verdadeira.
313
- ctx.srSay(anunciarItem({ rotulo: rotuloAcessivel(items[n]), posicao: n + 1, total: items.length }, ctx.comIndice()));
266
+ // AND THE NEW ITEM IS SPOKEN. This card selects by class, not by browser focus — it is drawn inside the player's
267
+ // screen — so nothing announces it by itself: no focus, no `aria-activedescendant`, no live region. ADR-0044 item 3
268
+ // asks for position and total everywhere.
269
+ // `accessibleLabel` and not `textContent`: an item with an `aria-label` would otherwise be narrated one way by the
270
+ // game and another by the screen reader, and whoever hears both could not tell which is true.
271
+ // 🔴 A LOCKED ITEM SAYS WHY when it is reached (ADR-0161): right after its name, and written in the footer.
272
+ const reason = items[n].getAttribute('aria-disabled') === 'true' ? (items[n].dataset.motivo ?? '') : '';
273
+ const announcement = announceItem(t, { label: accessibleLabel(items[n]), position: n + 1, total: items.length }, ctx.withIndex());
274
+ ctx.srSay(reason ? `${announcement}. ${reason}` : announcement);
275
+ ctx.explainItem?.(reason || null);
314
276
  }
315
- /* ===================== teclado ===================== */
316
- /** O assistente de gamepad fica POR CIMA de tudo: com ele aberto, só Escape passa (e cancela). */
277
+ /* ===================== keyboard ===================== */
278
+ /** The controller-mapping panel sits ON TOP of everything: while it is open, only Escape gets through (and cancels). */
317
279
  function padWizKey(e) {
318
280
  const pw = ctx.$('#padwiz');
319
281
  if (!pw || pw.hidden)
@@ -323,68 +285,133 @@ export function initMenuNav(ctx) {
323
285
  e.preventDefault();
324
286
  e.stopPropagation();
325
287
  }
326
- return true; // aberto = consome (mesmo sem ser Escape: o resto do menu não navega por baixo dele)
288
+ return true; // open = consumed (even when it is not Escape: no menu underneath navigates while it is open)
327
289
  }
328
- /** Consome a tecla: ela era nossa, e ninguém mais deve vê-la. Uma função só para o par nunca se separar. */
329
- const consumir = (e) => { e.preventDefault(); e.stopPropagation(); };
290
+ /** Consumes the key: it was ours, and nobody else should see it. One function, so the pair never comes apart. */
291
+ const consume = (e) => { e.preventDefault(); e.stopPropagation(); };
330
292
  function menuNavKey(e) {
331
293
  if (ctx.isCapturing())
332
- return; // remap em andamento: a tecla é dele
294
+ return; // a remap in progress: the key is its
333
295
  if (padWizKey(e))
334
296
  return;
335
- // ===================== O MODO `accessibility` VEM ANTES DO GUARDA DE "NAVEGÁVEL" =====================
336
- // `isNavigable()` é `phase === 'paused'`, e este modo roda com o jogo ANDANDO — é para isso que ele
337
- // existe: ajustar a acessibilidade DURANTE a partida, sem parar. Se ele ficasse depois do guarda, a
338
- // direção cairia no personagem e o modo não faria nada, que é a versão silenciosa da armadilha.
297
+ // ===================== THE QUICK BAR COMES BEFORE THE «NAVIGABLE» GUARD =====================
298
+ // `isNavigable()` can be false while the game runs (a platformer answers `phase === 'paused'`), and the bar works
299
+ // with the game RUNNING — that is what it is for: adjusting accessibility DURING play. After the guard, the
300
+ // direction would fall to the character and the bar would do nothing, silently.
339
301
  //
340
- // No TECLADO a saída é Escape (o `no` do projeto). O START do controle é a segunda saída e entra por
341
- // `input/gamepad`; aqui ele não tem par próprio, porque Enter já é "confirmar" e roubá-lo tiraria da
342
- // criança o único jeito de ATIVAR o ícone sob o cursor.
343
- const donoTecla = ctx.whichPlayer(e.code);
344
- const pTecla = donoTecla < 0 ? 0 : donoTecla;
345
- if (ctx.naBarraDe(pTecla)) {
346
- const kb = menuKeyIntent(e.code, donoTecla >= 0 ? ctx.actionOf(e.code, pTecla) : null);
347
- if (hasIntent(kb)) {
348
- consumir(e);
349
- ctx.navBar(pTecla, kb);
302
+ // On the KEYBOARD the way out is Escape (the project's `no`). A controller's START is the second way out and comes
303
+ // through `input/gamepad`; the keyboard has no pair of its own for it, because Enter is already «confirm» and taking
304
+ // it would leave the child no way to ACTIVATE the icon under the cursor.
305
+ const { player, keys } = intentOf(e.code);
306
+ if (ctx.onBar(player)) {
307
+ if (hasIntent(keys)) {
308
+ consume(e);
309
+ ctx.navBar(player, keys);
350
310
  }
351
- return; // na barra, tecla de menu é da barra — com ou sem intenção, não desce para o personagem
311
+ return; // on the bar, a menu key belongs to the bar — with or without an intent, it does not reach the character
352
312
  }
353
- if (!ctx.isNavigable())
354
- return;
355
- const owner = ctx.whichPlayer(e.code);
356
- const pi = owner < 0 ? 0 : owner; // tecla genérica → Jogador 1
357
- const k = menuKeyIntent(e.code, owner >= 0 ? ctx.actionOf(e.code, pi) : null);
358
- if (!hasIntent(k))
313
+ if (!ctx.isNavigable() || !hasIntent(keys))
359
314
  return;
360
- // A TECLA SÓ É CONSUMIDA SE HOUVER O QUE NAVEGAR. Antes, `preventDefault()` + `stopPropagation()` vinham
361
- // AQUI, antes de se saber se havia diálogo ou menu aberto — e o `menuNavKey` matava o evento para depois
362
- // descobrir que não tinha nada a fazer com ele. Na plataforma isso era invisível: `isNavigable()` é
363
- // `phase === 'paused'`, e pausar ABRE o menu, então quase nunca havia um caso "navegável e nada aberto".
364
- //
365
- // No segundo consumidor não era invisível — era total. Um quiz cujos ajustes estão SEMPRE disponíveis
366
- // responde `isNavigable(): true`, e com isso TODA tecla com intenção de menu morria aqui: as setas de
367
- // escolher alternativa, e o `S` do sonar. Duas funcionalidades que existiam e não chegavam à criança.
315
+ navOpenMenu(e, player, keys);
316
+ }
317
+ /** Whose key this is — a key no player owns is Player 1's — and what it asks of a menu. */
318
+ function intentOf(code) {
319
+ const owner = ctx.whichPlayer(code);
320
+ const player = owner < 0 ? 0 : owner;
321
+ return { player, keys: menuKeyIntent(code, owner >= 0 ? ctx.actionOf(code, player) : null) };
322
+ }
323
+ /** The key moves the dialog on top if there is one, else the player's own pause card if it is open, else nothing. */
324
+ function navOpenMenu(e, pi, k) {
325
+ // THE KEY IS CONSUMED ONLY IF THERE IS SOMETHING TO NAVIGATE. A game whose settings are always open answers
326
+ // `isNavigable(): true`, and consuming before knowing would swallow every key with a menu intent — the arrows that
327
+ // choose an answer in the quiz, for one.
368
328
  //
369
- // A REDE DE SEGURANÇA DO ESCAPE FICA INTACTA, e era o risco real desta mudança. O bloco (b) acima explica
370
- // que `#help` e `#touchcfg` dependem do `stopPropagation()` para não deixarem a tecla cair no ouvinte de
371
- // bolha, que despausaria o jogo com o diálogo aberto. Esses dois casos entram por `sharedDialogOpen()`
372
- // — há diálogo, logo a tecla É consumida, exatamente como antes.
329
+ // DEFECT 2's safety net stays: with a dialog open the key IS consumed, so one Escape closes the dialog and no later
330
+ // listener sees it.
373
331
  const dlg = sharedDialogOpen();
374
332
  if (dlg) {
375
- consumir(e);
333
+ consume(e);
376
334
  navDialog(dlg, k);
377
335
  return;
378
- } // diálogo de a11y aberto: navega ele (compartilhado)
379
- const menu = ctx.getPauseMenu(pi); // senão: menu de pausa do PRÓPRIO jogador
336
+ } // an accessibility dialog is open: it is the one navigated
337
+ const menu = ctx.getPauseMenu(pi); // otherwise: the player's OWN pause card
380
338
  if (menu && !menu.hidden) {
381
- consumir(e);
339
+ consume(e);
382
340
  navPause(menu, pi, k);
383
341
  }
384
- // Sem diálogo e sem menu: a tecla NÃO é nossa. Segue o caminho dela até quem for o dono.
342
+ // No dialog and no card: the key is NOT ours. It goes on to whoever owns it.
343
+ }
344
+ /* ===================== holding on an item ===================== */
345
+ /*
346
+ * A PRESS HELD ON AN ITEM PLACES THE CURSOR THERE AND SAYS IT, WITHOUT ACTIVATING IT (ADR-0159 rule 2, erratum of
347
+ * 2026-09-13). «Deixar o dedo apertado ou o botão do mouse apertado sobre o item deve dar a função de posicionar o
348
+ * cursor sem "apertar".» (Dev) — the pad left the menus (ADR-0166), and a pointer had one meaning only: activation.
349
+ * 📌 A short press is untouched; after a hold, the ONE click the browser fires on release is swallowed, in capture,
350
+ * before the item's own listener. Threshold: the iOS long-press default, 0.5 s.
351
+ */
352
+ const HOLD_MS = 500;
353
+ let holding = null;
354
+ let clickToSwallow = null;
355
+ /** The open menu and the item under `target`, when `target` is inside one: the top dialog first, else a pause card. */
356
+ function itemUnder(target) {
357
+ const no = target;
358
+ if (!no || typeof no.closest !== 'function')
359
+ return null;
360
+ const dlg = sharedDialogOpen();
361
+ if (dlg) {
362
+ const items = menuItems(dlg);
363
+ const n = items.findIndex((el) => el.contains(no));
364
+ return n >= 0 ? { menu: dlg, items, n, inPause: false } : null;
365
+ }
366
+ const menu = no.closest('.screen-pause');
367
+ if (!menu || menu.hidden)
368
+ return null;
369
+ const items = [...menu.querySelectorAll(PM_VISIBLE_ITEMS)];
370
+ const n = items.findIndex((el) => el.contains(no));
371
+ return n >= 0 ? { menu, items, n, inPause: true } : null;
372
+ }
373
+ function release() {
374
+ if (holding)
375
+ clearTimeout(holding.timer);
376
+ holding = null;
377
+ }
378
+ function onPress(e) {
379
+ release();
380
+ clickToSwallow = null;
381
+ const under = itemUnder(e.target);
382
+ if (!under)
383
+ return;
384
+ const id = e.pointerId;
385
+ holding = {
386
+ id,
387
+ timer: setTimeout(() => {
388
+ holding = null;
389
+ clickToSwallow = under.items[under.n] ?? null;
390
+ if (under.inPause)
391
+ selectAndSayInPause(under.menu, under.items, under.n);
392
+ else
393
+ focusAndSay(under.items, under.n);
394
+ }, HOLD_MS),
395
+ };
396
+ }
397
+ function onRelease(e) {
398
+ if (holding && holding.id === e.pointerId)
399
+ release();
400
+ }
401
+ function onClick(e) {
402
+ const swallowed = clickToSwallow;
403
+ clickToSwallow = null;
404
+ if (swallowed && e.target instanceof Node && swallowed.contains(e.target)) {
405
+ e.preventDefault();
406
+ e.stopPropagation();
407
+ }
385
408
  }
386
409
  function attach() {
387
410
  ctx.win.addEventListener('keydown', menuNavKey, true);
411
+ ctx.win.addEventListener('pointerdown', onPress, true);
412
+ ctx.win.addEventListener('pointerup', onRelease, true);
413
+ ctx.win.addEventListener('pointercancel', onRelease, true);
414
+ ctx.win.addEventListener('click', onClick, true);
388
415
  }
389
416
  return { sharedDialogOpen, menuItems, menuFocus, dialogBack, navDialog, pauseSetSel, navPause, menuNavKey, attach };
390
417
  }