@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
@@ -0,0 +1,73 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /** What the engine asks of a language: which catalogue files, and what the encoder eats. */
3
+ export interface ReadingModelPlan {
4
+ readonly language: string;
5
+ /** Whisper eats a log-mel spectrogram; Moonshine eats the samples. */
6
+ readonly input: 'log-mel' | 'waveform';
7
+ readonly encoder: string;
8
+ readonly decoder: string;
9
+ /** The second decoder graph, where the model has one: the first pass builds the cache, this one uses it. */
10
+ readonly decoderPast?: string;
11
+ readonly tokenizer: string;
12
+ readonly generation: string;
13
+ /** How many heads the caches hold and how wide each is — what a merged decoder needs to be handed empty ones. */
14
+ readonly config: string;
15
+ /** Only the mel front end needs one. */
16
+ readonly preprocessor?: string;
17
+ }
18
+ /** 16 kHz mono, for every one of them: it is what all three were trained on, and resampling is the caller's job. */
19
+ export declare const READING_RATE = 16000;
20
+ /** Whisper reads a 30 s window at a time, always: shorter is padded with silence, longer is cut. */
21
+ export declare const WHISPER_SAMPLES: number;
22
+ export declare const WHISPER_FRAMES = 3000;
23
+ export declare const WHISPER_BANDS = 80;
24
+ export declare const READING_MODELS: readonly ReadingModelPlan[];
25
+ /** The model of a language tag (`pt-BR` → pt), or `null` where the project has none — which the caller must SAY, not hide. */
26
+ export declare function readingModelFor(language: string): ReadingModelPlan | null;
27
+ /**
28
+ * WHAT WHISPER'S ENCODER EATS: a log-mel spectrogram of 80 bands by 3000 frames, from a 30 s window at 16 kHz.
29
+ *
30
+ * The steps are `WhisperFeatureExtractor`'s, in its order, and each one matters: the window is a PERIODIC Hann (a symmetric one
31
+ * moves every value); the signal is reflected at both ends by half a window, so frame 0 is centred on sample 0; the power
32
+ * spectrum is the magnitude SQUARED; the last frame is dropped, which is why 480 000 samples give 3000 and not 3001; the floor is
33
+ * eight decades below the LOUDEST point of this window, not a constant; and the scale ends in (x + 4) / 4.
34
+ */
35
+ export declare function logMel(samples: Float32Array, melFilters: readonly (readonly number[])[]): Float32Array;
36
+ /** A `tokenizer.json`, in the parts a reading reads: the vocabulary, the added tokens, and which decoder undoes them. */
37
+ export interface TokenizerFile {
38
+ readonly model?: {
39
+ readonly vocab?: Readonly<Record<string, number>>;
40
+ };
41
+ readonly added_tokens?: readonly {
42
+ readonly id: number;
43
+ readonly content: string;
44
+ readonly special?: boolean;
45
+ }[];
46
+ readonly decoder?: {
47
+ readonly type?: string;
48
+ };
49
+ }
50
+ /**
51
+ * WHAT THE CHILD ACTUALLY SAID, from the ids the decoder answered.
52
+ *
53
+ * The two families undo themselves differently and the file says which: Whisper writes every byte as a printable character
54
+ * (`ByteLevel`), Moonshine writes a space as `▁` and a rare byte as `<0x..>` (`Replace` + `ByteFallback` + `Fuse` + `Strip`).
55
+ * Both end in ONE decode of UTF-8, which is what keeps an accent that spans two tokens from becoming two broken characters.
56
+ */
57
+ export declare function readingTextOf(tokenizer: TokenizerFile, ids: readonly number[]): string;
58
+ /** What a `generation_config.json` says must never be answered — Whisper's list of tokens that are not speech. */
59
+ export interface GenerationConfig {
60
+ readonly suppress_tokens?: readonly number[];
61
+ readonly begin_suppress_tokens?: readonly number[];
62
+ readonly eos_token_id?: number;
63
+ readonly decoder_start_token_id?: number;
64
+ }
65
+ /**
66
+ * The tokens refused at this step. `atStart` is the first answered token, where Whisper also refuses the ones that would make it
67
+ * open with a silence or a punctuation mark — without this it answers «.» to a child who read a whole sentence.
68
+ */
69
+ export declare function suppressedTokens(config: GenerationConfig, atStart: boolean): ReadonlySet<number>;
70
+ /** The id of a named token (`<|pt|>`, `<|transcribe|>`), or `null` — a model that does not have it must be SAID, not guessed. */
71
+ export declare function tokenIdOf(tokenizer: TokenizerFile, content: string): number | null;
72
+ /** The next token: the biggest logit that is not refused. Greedy, because a child reading a known text needs no imagination. */
73
+ export declare function nextToken(logits: ArrayLike<number>, suppressed?: ReadonlySet<number>): number;
@@ -0,0 +1,247 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // platform/reading-model — WHAT A READING MODEL NEEDS DONE TO SOUND AND TO TOKENS, in its pure half (ADR-0216 §2; issues #185, #200).
3
+ //
4
+ // The engine hears a child read aloud with one model per language (ADR-0201 erratum): Whisper small for Portuguese, Moonshine
5
+ // streaming small for English and Spanish. Around the graphs there is arithmetic that has nothing to do with a browser — turning
6
+ // sound into what the encoder eats, and turning the numbers the decoder answers back into words — and it lives here, where it can
7
+ // be measured. `platform/reading-runtime` is the half that opens sessions and fetches files.
8
+ //
9
+ // 🎯 MEASURED AGAINST THE ORIGINALS, not against my idea of them: `tests/fixtures/reading-ground-truth.json` is what
10
+ // `WhisperFeatureExtractor` and the three tokenizers answer for one deterministic signal and three phrases, written by
11
+ // `scratchpad/verdade-da-leitura.py`. A front end that is subtly wrong still runs and still returns text — the wrong text — so
12
+ // «it produced something» is not a check.
13
+ //
14
+ // · THE MEL FILTERS ARE NOT COMPUTED HERE. Whisper's own `preprocessor_config.json` carries them (80 × 201), which is most of its
15
+ // 185 KB, and the catalogue already fetches it: a filterbank rebuilt from a formula is a second opinion about the model's input.
16
+ // · Moonshine takes the WAVEFORM. No spectrogram, no padding to 30 s — it is a different front end, not a variant of this one.
17
+ /** 16 kHz mono, for every one of them: it is what all three were trained on, and resampling is the caller's job. */
18
+ export const READING_RATE = 16_000;
19
+ /** Whisper reads a 30 s window at a time, always: shorter is padded with silence, longer is cut. */
20
+ export const WHISPER_SAMPLES = 30 * READING_RATE;
21
+ export const WHISPER_FRAMES = 3000;
22
+ export const WHISPER_BANDS = 80;
23
+ const N_FFT = 400;
24
+ const HOP = 160;
25
+ const HALF = N_FFT / 2;
26
+ const BINS = HALF + 1;
27
+ /** What a band is when its power is clipped: the original clips at 1e-10 before the log. */
28
+ const CLIPPED = Math.log10(1e-10);
29
+ export const READING_MODELS = Object.freeze([
30
+ {
31
+ language: 'pt', input: 'log-mel',
32
+ encoder: 'reading:pt:encoder', decoder: 'reading:pt:decoder', decoderPast: 'reading:pt:decoder:past',
33
+ tokenizer: 'reading:pt:tokenizer', generation: 'reading:pt:generation', config: 'reading:pt:config',
34
+ preprocessor: 'reading:pt:preprocessor',
35
+ },
36
+ {
37
+ language: 'en', input: 'waveform',
38
+ encoder: 'reading:en:encoder', decoder: 'reading:en:decoder',
39
+ tokenizer: 'reading:en:tokenizer', generation: 'reading:en:generation', config: 'reading:en:config',
40
+ },
41
+ {
42
+ language: 'es', input: 'waveform',
43
+ encoder: 'reading:es:encoder', decoder: 'reading:es:decoder', decoderPast: 'reading:es:decoder:past',
44
+ tokenizer: 'reading:es:tokenizer', generation: 'reading:es:generation', config: 'reading:es:config',
45
+ },
46
+ ]);
47
+ /** The model of a language tag (`pt-BR` → pt), or `null` where the project has none — which the caller must SAY, not hide. */
48
+ export function readingModelFor(language) {
49
+ const tag = language.split('-')[0].toLowerCase();
50
+ return READING_MODELS.find((m) => m.language === tag) ?? null;
51
+ }
52
+ /**
53
+ * WHAT WHISPER'S ENCODER EATS: a log-mel spectrogram of 80 bands by 3000 frames, from a 30 s window at 16 kHz.
54
+ *
55
+ * The steps are `WhisperFeatureExtractor`'s, in its order, and each one matters: the window is a PERIODIC Hann (a symmetric one
56
+ * moves every value); the signal is reflected at both ends by half a window, so frame 0 is centred on sample 0; the power
57
+ * spectrum is the magnitude SQUARED; the last frame is dropped, which is why 480 000 samples give 3000 and not 3001; the floor is
58
+ * eight decades below the LOUDEST point of this window, not a constant; and the scale ends in (x + 4) / 4.
59
+ */
60
+ export function logMel(samples, melFilters) {
61
+ const audio = new Float32Array(WHISPER_SAMPLES);
62
+ audio.set(samples.subarray(0, WHISPER_SAMPLES));
63
+ // the reflected padding, written once: `at(i)` is the padded signal, so no copy of 480 000 samples is made
64
+ const at = (i) => {
65
+ const j = i - HALF;
66
+ if (j < 0)
67
+ return audio[-j];
68
+ if (j >= WHISPER_SAMPLES)
69
+ return audio[2 * WHISPER_SAMPLES - j - 2];
70
+ return audio[j];
71
+ };
72
+ const turns = dftTurns();
73
+ const out = new Float32Array(WHISPER_BANDS * WHISPER_FRAMES);
74
+ const power = new Float64Array(BINS);
75
+ let loudest = -Infinity;
76
+ for (let frame = 0; frame < WHISPER_FRAMES; frame++) {
77
+ const start = frame * HOP;
78
+ // 🎯 A WINDOW OF PURE SILENCE IS ANSWERED, NOT COMPUTED, and it is EXACT: every bin of a window of zeros is zero, so every
79
+ // band is the clipped value. A child reads for a few seconds into a 30 s window, so most frames are this one. It never
80
+ // raises the loudest point: no computed band is ever below the clip, and an all-silent window floors at −∞.
81
+ let quiet = true;
82
+ for (let n = 0; n < N_FFT && quiet; n++)
83
+ quiet = at(start + n) === 0;
84
+ if (quiet) {
85
+ for (let band = 0; band < WHISPER_BANDS; band++)
86
+ out[band * WHISPER_FRAMES + frame] = CLIPPED;
87
+ continue;
88
+ }
89
+ powerOf(at, start, turns, power);
90
+ loudest = Math.max(loudest, melOf(power, melFilters, out, frame));
91
+ }
92
+ // the floor is eight decades below the LOUDEST point of this window, not a constant, and the scale ends in (x + 4) / 4
93
+ const floor = loudest - 8;
94
+ for (let i = 0; i < out.length; i++)
95
+ out[i] = (Math.max(out[i], floor) + 4) / 4;
96
+ return out;
97
+ }
98
+ /** A PERIODIC Hann window: a symmetric one moves every value. 400 numbers, computed once. */
99
+ const HANN = Float64Array.from({ length: N_FFT }, (_, i) => 0.5 - 0.5 * Math.cos((2 * Math.PI * i) / N_FFT));
100
+ /**
101
+ * ⚠️ THE TURNS ARE COMPUTED ONCE. A 400-point real DFT for 201 bins is 80 400 sines and cosines per frame, and there are 3000
102
+ * frames: asking `Math.cos` for them each time is a quarter of a billion calls, which on a school machine is not «slower», it is
103
+ * a child waiting half a minute to be told what they read.
104
+ */
105
+ function dftTurns() {
106
+ const cos = new Float64Array(BINS * N_FFT);
107
+ const sin = new Float64Array(BINS * N_FFT);
108
+ for (let k = 0; k < BINS; k++) {
109
+ for (let n = 0; n < N_FFT; n++) {
110
+ const angle = (-2 * Math.PI * k * n) / N_FFT;
111
+ cos[k * N_FFT + n] = Math.cos(angle);
112
+ sin[k * N_FFT + n] = Math.sin(angle);
113
+ }
114
+ }
115
+ return { cos, sin };
116
+ }
117
+ /** One frame's power spectrum: the windowed DFT's magnitude SQUARED, one value per bin. */
118
+ function powerOf(at, start, turns, power) {
119
+ for (let k = 0; k < BINS; k++) {
120
+ let re = 0, im = 0;
121
+ const row = k * N_FFT;
122
+ for (let n = 0; n < N_FFT; n++) {
123
+ const x = at(start + n) * HANN[n];
124
+ re += x * turns.cos[row + n];
125
+ im += x * turns.sin[row + n];
126
+ }
127
+ power[k] = re * re + im * im;
128
+ }
129
+ }
130
+ /** One frame's 80 bands, each the power through its mel filter, clipped at 1e-10 BEFORE the log. Answers the frame's loudest. */
131
+ function melOf(power, melFilters, out, frame) {
132
+ let loudest = -Infinity;
133
+ for (let band = 0; band < WHISPER_BANDS; band++) {
134
+ const filter = melFilters[band];
135
+ let sum = 0;
136
+ for (let k = 0; k < BINS; k++)
137
+ sum += power[k] * filter[k];
138
+ const value = Math.log10(Math.max(sum, 1e-10));
139
+ out[band * WHISPER_FRAMES + frame] = value;
140
+ if (value > loudest)
141
+ loudest = value;
142
+ }
143
+ return loudest;
144
+ }
145
+ /** id → the piece of text that token stands for, with the special ones (`<|pt|>`, `</s>`…) marked so they never reach a child. */
146
+ function piecesOf(tokenizer) {
147
+ const text = new Map();
148
+ for (const [piece, id] of Object.entries(tokenizer.model?.vocab ?? {}))
149
+ text.set(id, piece);
150
+ const special = new Set();
151
+ for (const added of tokenizer.added_tokens ?? []) {
152
+ text.set(added.id, added.content);
153
+ // ⚠️ `special` is absent on some files and the mark is what keeps `<|startoftranscript|>` out of a child's sentence, so the
154
+ // shape of the content decides when the flag does not: every one of them is bracketed.
155
+ if (added.special ?? /^<.*>$/.test(added.content))
156
+ special.add(added.id);
157
+ }
158
+ return { text, special };
159
+ }
160
+ /** The bytes GPT-2 writes as themselves: its three printable ranges, inclusive (`bytes_to_unicode`, openai/gpt-2 `encoder.py`). */
161
+ const PRINTABLE_RANGES = [[33, 126], [161, 172], [174, 255]];
162
+ // GPT-2's byte alphabet: the printable character each byte is written as, so a tokenizer file stays text. Whisper's decoder is
163
+ // this one (`ByteLevel`), and reversing it is the whole of it.
164
+ const byteOfChar = (() => {
165
+ const map = new Map();
166
+ const printable = [];
167
+ for (const [lo, hi] of PRINTABLE_RANGES)
168
+ for (let b = lo; b <= hi; b++)
169
+ printable.push(b);
170
+ for (const b of printable)
171
+ map.set(String.fromCharCode(b), b);
172
+ let next = 0;
173
+ for (let b = 0; b < 256; b++) {
174
+ if (printable.includes(b))
175
+ continue;
176
+ map.set(String.fromCharCode(256 + next), b);
177
+ next++;
178
+ }
179
+ return map;
180
+ })();
181
+ const BYTE_FALLBACK = /^<0x([0-9A-Fa-f]{2})>$/;
182
+ /**
183
+ * WHAT THE CHILD ACTUALLY SAID, from the ids the decoder answered.
184
+ *
185
+ * The two families undo themselves differently and the file says which: Whisper writes every byte as a printable character
186
+ * (`ByteLevel`), Moonshine writes a space as `▁` and a rare byte as `<0x..>` (`Replace` + `ByteFallback` + `Fuse` + `Strip`).
187
+ * Both end in ONE decode of UTF-8, which is what keeps an accent that spans two tokens from becoming two broken characters.
188
+ */
189
+ export function readingTextOf(tokenizer, ids) {
190
+ const { text, special } = piecesOf(tokenizer);
191
+ const byteLevel = tokenizer.decoder?.type === 'ByteLevel';
192
+ const bytes = [];
193
+ for (const id of ids) {
194
+ if (special.has(id))
195
+ continue;
196
+ const piece = text.get(id);
197
+ if (piece === undefined)
198
+ continue; // an id the vocabulary does not have is not a character: it is dropped, never guessed
199
+ if (byteLevel) {
200
+ for (const ch of piece)
201
+ bytes.push(byteOfChar.get(ch) ?? ch.charCodeAt(0));
202
+ continue;
203
+ }
204
+ const fallback = BYTE_FALLBACK.exec(piece);
205
+ if (fallback) {
206
+ bytes.push(parseInt(fallback[1], 16));
207
+ continue;
208
+ }
209
+ for (const b of new TextEncoder().encode(piece.replaceAll('▁', ' ')))
210
+ bytes.push(b);
211
+ }
212
+ const whole = new TextDecoder().decode(Uint8Array.from(bytes));
213
+ return byteLevel ? whole : whole.replace(/^ /, '');
214
+ }
215
+ /**
216
+ * The tokens refused at this step. `atStart` is the first answered token, where Whisper also refuses the ones that would make it
217
+ * open with a silence or a punctuation mark — without this it answers «.» to a child who read a whole sentence.
218
+ */
219
+ export function suppressedTokens(config, atStart) {
220
+ const out = new Set(config.suppress_tokens ?? []);
221
+ if (atStart)
222
+ for (const id of config.begin_suppress_tokens ?? [])
223
+ out.add(id);
224
+ return out;
225
+ }
226
+ /** The id of a named token (`<|pt|>`, `<|transcribe|>`), or `null` — a model that does not have it must be SAID, not guessed. */
227
+ export function tokenIdOf(tokenizer, content) {
228
+ for (const added of tokenizer.added_tokens ?? [])
229
+ if (added.content === content)
230
+ return added.id;
231
+ const fromVocab = tokenizer.model?.vocab?.[content];
232
+ return fromVocab ?? null;
233
+ }
234
+ /** The next token: the biggest logit that is not refused. Greedy, because a child reading a known text needs no imagination. */
235
+ export function nextToken(logits, suppressed) {
236
+ let best = -1, bestValue = -Infinity;
237
+ for (let id = 0; id < logits.length; id++) {
238
+ if (suppressed?.has(id))
239
+ continue;
240
+ const value = logits[id];
241
+ if (value > bestValue) {
242
+ bestValue = value;
243
+ best = id;
244
+ }
245
+ }
246
+ return best;
247
+ }
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { type OnnxRuntime } from './onnx-runtime.js';
3
+ /** What the engine gets back: something that turns samples into words. */
4
+ export interface ReadingTranscriber {
5
+ /** 16 kHz mono samples in, the child's words out. Empty when the model answered nothing. */
6
+ transcribe(samples: Float32Array): Promise<string>;
7
+ }
8
+ export interface ReadingRuntimeDeps {
9
+ /** The page's address, which `heavy/` is resolved against. */
10
+ readonly base: string;
11
+ /** The child's language tag (`pt-BR`). A language the project has no model for is refused BY NAME. */
12
+ readonly language: string;
13
+ /**
14
+ * The `fetch` of the realm this runs in, lent by whoever opens the reading (ADR-0232 D4): the root's window where there is
15
+ * no worker, the worker's own scope inside `platform/reading-worker`. REQUIRED — this module reaches no global.
16
+ */
17
+ readonly fetch: (url: string) => Promise<Response>;
18
+ /** Injected so a case can replay a real model's numbers without its 378 MiB; the default is the delivery's runtime. */
19
+ readonly ort?: OnnxRuntime;
20
+ readonly importModule?: (url: string) => Promise<unknown>;
21
+ /** A ceiling on the answer, so a model that loops does not hold the microphone for ever. */
22
+ readonly maxTokens?: number;
23
+ }
24
+ export declare function loadReadingRuntime(d: ReadingRuntimeDeps): Promise<ReadingTranscriber>;
@@ -0,0 +1,159 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // platform/reading-runtime — THE READING, RUN (ADR-0216 §2; issues #185, #200): sound in, the child's words out.
3
+ //
4
+ // The model of the child's language is opened from the delivery (`heavy/` on the page's own origin, ADR-0177) and run here:
5
+ // the encoder once, then the decoder token by token until it says it is done. What each graph is called, what it takes and what
6
+ // comes back is not guessed — `scratchpad/leitura-de-referencia-3.py` ran the real files and its trace is what
7
+ // `tests/reading-runtime.node.test.js` replays.
8
+ //
9
+ // THREE FAMILIES, and they differ in ways that matter:
10
+ // · Whisper (pt) eats a log-mel spectrogram and opens with four tokens — «transcribe, in Portuguese, without timestamps» — and
11
+ // refuses 88 tokens that are not speech. Without that opening it answers in whatever language it feels like.
12
+ // · Moonshine (es) eats the waveform and opens with one token, in two decoder graphs like Whisper's.
13
+ // · Moonshine (en) is the same model with ONE MERGED decoder graph, told which pass it is on by `use_cache_branch` and fed empty
14
+ // caches on the first. It is the shape most easily written wrong from a guess, which is why it is traced too.
15
+ //
16
+ // ⚠️ THE CROSS-ATTENTION CACHE IS COMPUTED ONCE AND NEVER AGAIN. The first pass answers a `present.*.encoder.*` per layer that
17
+ // depends only on the sound; feeding back the new one each step is how a loop gets slower with every token AND drifts.
18
+ import { atDelivery, loadOnnxRuntime } from './onnx-runtime.js';
19
+ import { logMel, nextToken, readingModelFor, readingTextOf, suppressedTokens, tokenIdOf, WHISPER_BANDS, WHISPER_FRAMES, } from './reading-model.js';
20
+ const MAX_TOKENS = 200;
21
+ export async function loadReadingRuntime(d) {
22
+ const plan = readingModelFor(d.language);
23
+ if (!plan)
24
+ throw new Error(`reading: the project has no model for ${d.language}`);
25
+ const get = d.fetch;
26
+ const ort = d.ort ?? await loadOnnxRuntime({ base: d.base, importModule: d.importModule });
27
+ const asJson = async (id) => {
28
+ const r = await get(atDelivery(id, d.base));
29
+ if (!r.ok)
30
+ throw new Error(`reading: HTTP ${r.status} for ${id} — the delivery does not carry this language's model`);
31
+ return await r.json();
32
+ };
33
+ const asSession = async (id) => {
34
+ const r = await get(atDelivery(id, d.base));
35
+ if (!r.ok)
36
+ throw new Error(`reading: HTTP ${r.status} for ${id} — the delivery does not carry this language's model`);
37
+ return ort.InferenceSession.create(new Uint8Array(await r.arrayBuffer()), { executionProviders: ['wasm'] });
38
+ };
39
+ const [tokenizer, generation, config] = await Promise.all([
40
+ asJson(plan.tokenizer),
41
+ asJson(plan.generation),
42
+ asJson(plan.config),
43
+ ]);
44
+ const melFilters = plan.input === 'log-mel' && plan.preprocessor
45
+ ? (await asJson(plan.preprocessor)).mel_filters
46
+ : null;
47
+ const [encoder, decoder, decoderPast] = await Promise.all([
48
+ asSession(plan.encoder),
49
+ asSession(plan.decoder),
50
+ plan.decoderPast ? asSession(plan.decoderPast) : Promise.resolve(null),
51
+ ]);
52
+ const start = openingOf(plan, tokenizer, generation);
53
+ const eos = generation.eos_token_id ?? -1;
54
+ const { heads, width } = cacheSizeOf(config);
55
+ const ceiling = d.maxTokens ?? MAX_TOKENS;
56
+ return {
57
+ async transcribe(samples) {
58
+ const encoded = await encoder.run(soundFor(ort, plan, samples, melFilters));
59
+ const hidden = encoded[encoder.outputNames[0]];
60
+ const shape = {
61
+ ort, start, hidden, heads, width,
62
+ frames: hidden.dims?.[1] ?? 0,
63
+ // the merged graph wants the caches present and EMPTY on the first pass, and the flag that says which pass this is
64
+ merged: !decoderPast,
65
+ };
66
+ const past = {};
67
+ const ids = [];
68
+ for (let step = 0; step < ceiling; step++) {
69
+ const first = step === 0;
70
+ const session = first || shape.merged ? decoder : decoderPast;
71
+ const answered = await session.run(stepInputs(shape, session, first, ids, past));
72
+ keepPast(past, session, answered, first);
73
+ const chosen = nextToken(lastLogits(answered[session.outputNames[0]]), suppressedTokens(generation, first));
74
+ // no token at all (a row of NaN) is an end, like the end-of-text: pushing it would ask for a word the vocabulary lacks
75
+ if (chosen < 0 || chosen === eos)
76
+ break;
77
+ ids.push(chosen);
78
+ }
79
+ return readingTextOf(tokenizer, ids).trim();
80
+ },
81
+ };
82
+ }
83
+ /**
84
+ * WHAT THE ENCODER HEARS. Whisper a log-mel picture of 30 s drawn with the model's own filters (80 bands × 3000 frames), Moonshine
85
+ * the wave itself, every sample. The names are the graphs' own: a real session refuses any other.
86
+ */
87
+ function soundFor(ort, plan, samples, melFilters) {
88
+ return plan.input === 'log-mel'
89
+ ? { input_features: new ort.Tensor('float32', logMel(samples, melFilters ?? []), [1, WHISPER_BANDS, WHISPER_FRAMES]) }
90
+ : { input_values: new ort.Tensor('float32', samples, [1, samples.length]) };
91
+ }
92
+ /** What one decoder step is handed: the opening on the first, then only the newest token, and the caches so far. */
93
+ function stepInputs(shape, session, first, ids, past) {
94
+ const { ort } = shape;
95
+ const inputIds = first ? shape.start : [ids[ids.length - 1]];
96
+ const inputs = {
97
+ input_ids: new ort.Tensor('int64', BigInt64Array.from(inputIds, BigInt), [1, inputIds.length]),
98
+ encoder_hidden_states: shape.hidden,
99
+ ...(first && shape.merged ? emptyCaches(ort, session, shape.heads, shape.width, shape.frames) : past),
100
+ };
101
+ if (shape.merged)
102
+ inputs.use_cache_branch = new ort.Tensor('bool', Uint8Array.of(first ? 0 : 1), [1]);
103
+ return inputs;
104
+ }
105
+ /**
106
+ * The caches carried to the next step: each `present.*` the decoder answered, renamed to the `past_key_values.*` it takes. The
107
+ * `logits` beside them are the answer, never a cache.
108
+ * ⚠️ ONLY the self-attention half grows. The cross-attention half is the sound, and the sound does not change.
109
+ */
110
+ function keepPast(past, session, answered, first) {
111
+ for (const name of session.outputNames) {
112
+ if (!name.startsWith('present.'))
113
+ continue;
114
+ if (first || name.includes('.decoder.'))
115
+ past[name.replace('present.', 'past_key_values.')] = answered[name];
116
+ }
117
+ }
118
+ /**
119
+ * HOW THE DECODER IS TOLD WHAT TO DO. Moonshine opens with one token and reads what it hears. Whisper opens with four, and they
120
+ * are an instruction: transcribe (not translate), in THIS language, without timestamps. 📏 Measured: without them it answers in
121
+ * whatever language it decides, and with `<|translate|>` it answers in English — a child reading Portuguese would be corrected
122
+ * against an English transcript.
123
+ */
124
+ function openingOf(plan, tokenizer, generation) {
125
+ const first = generation.decoder_start_token_id ?? 0;
126
+ if (plan.input !== 'log-mel')
127
+ return [first];
128
+ const named = [`<|${plan.language}|>`, '<|transcribe|>', '<|notimestamps|>'].map((c) => tokenIdOf(tokenizer, c));
129
+ if (named.some((id) => id === null))
130
+ throw new Error(`reading: this model has no token for ${plan.language} transcription`);
131
+ return [first, ...named];
132
+ }
133
+ /**
134
+ * How big one cache is, from `config.json`: the KEY-VALUE heads (a model with grouped attention keeps fewer than it attends with),
135
+ * and a width of `hidden_size / heads`, 64 where the config does not say.
136
+ */
137
+ function cacheSizeOf(config) {
138
+ return {
139
+ heads: config.num_key_value_heads ?? config.num_attention_heads ?? 0,
140
+ width: config.hidden_size && config.num_attention_heads ? config.hidden_size / config.num_attention_heads : 64,
141
+ };
142
+ }
143
+ /** The caches a merged decoder wants on its first pass: the self-attention halves empty, the cross-attention ones the sound's. */
144
+ function emptyCaches(ort, session, heads, width, frames) {
145
+ const out = {};
146
+ for (const name of session.inputNames ?? []) {
147
+ if (!name.startsWith('past_key_values.'))
148
+ continue;
149
+ const length = name.includes('.decoder.') ? 0 : frames;
150
+ out[name] = new ort.Tensor('float32', new Float32Array(heads * length * width), [1, heads, length, width]);
151
+ }
152
+ return out;
153
+ }
154
+ /** The logits of the LAST position: the decoder answers one row per token it was given, and only the newest one is a choice. */
155
+ function lastLogits(tensor) {
156
+ const t = tensor;
157
+ const vocab = t.dims?.[2] ?? t.data.length;
158
+ return t.data.subarray(t.data.length - vocab);
159
+ }
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { loadReadingRuntime } from './reading-runtime.js';
3
+ /** What the client asks for. */
4
+ export type ReadingRequest = {
5
+ readonly kind: 'load';
6
+ readonly base: string;
7
+ readonly language: string;
8
+ } | {
9
+ readonly kind: 'transcribe';
10
+ readonly id: number;
11
+ readonly samples: Float32Array;
12
+ };
13
+ /** What the worker answers. `id` is absent only on the answer to `load`, which nobody can ask twice. */
14
+ export type ReadingAnswer = {
15
+ readonly kind: 'ready';
16
+ } | {
17
+ readonly kind: 'text';
18
+ readonly id: number;
19
+ readonly text: string;
20
+ } | {
21
+ readonly kind: 'failed';
22
+ readonly id?: number;
23
+ readonly message: string;
24
+ };
25
+ /** The side of the conversation this file needs, so a gate can run the whole protocol without a thread. */
26
+ export interface WorkerScope {
27
+ onmessage: ((event: {
28
+ data: ReadingRequest;
29
+ }) => void) | null;
30
+ postMessage(answer: ReadingAnswer): void;
31
+ /**
32
+ * The worker realm's own `fetch`, which the model's files are fetched with (ADR-0232 D4): the runtime receives it from the
33
+ * scope, so the worker's entry reaches no bare global either.
34
+ */
35
+ fetch(url: string): Promise<Response>;
36
+ }
37
+ /**
38
+ * Wires the protocol onto a scope. Exported — and not only run at import — so the gate exercises the REAL handler instead of a
39
+ * copy of it written in the test, which is the difference between measuring the protocol and measuring a description of it.
40
+ */
41
+ export declare function serveReading(scope: WorkerScope, load?: typeof loadReadingRuntime): void;
@@ -0,0 +1,58 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // platform/reading-worker — THE TRANSCRIPTION, OFF THE MAIN THREAD (ADR-0216 §2; issue #185).
3
+ //
4
+ // 🔴 WHY A THREAD OF ITS OWN, and it is measured and not hygiene: `platform/reading-runtime` runs an encoder and then a decoder
5
+ // token by token, each one a wasm call of tens of milliseconds. On the main thread that is the thread that also draws the game
6
+ // and feeds the microphone — 📏 measured in the lab, Whisper transcribing on the main thread CUT THE AUDIO IN GAPS OF 4 s; the
7
+ // same work in a worker left a biggest gap of 264 ms. A child who reads aloud while the page transcribes loses the words she
8
+ // said during the pause, and nothing anywhere says so.
9
+ //
10
+ // The protocol is three messages and no state the caller cannot see:
11
+ // · `{ kind: 'load', base, language }` → `{ kind: 'ready' }` or `{ kind: 'failed', message }`
12
+ // · `{ kind: 'transcribe', id, samples }` → `{ kind: 'text', id, text }` or `{ kind: 'failed', id, message }`
13
+ // Every answer carries the `id` of the question, because a second reading may be asked for while the first is still running and
14
+ // an answer that cannot be matched to its question is an answer given to the wrong child.
15
+ //
16
+ // ⚠️ THE MODEL IS OPENED HERE, INSIDE THE WORKER, and that is the whole point: `loadReadingRuntime` fetches the graphs from the
17
+ // delivery and the ONNX runtime compiles them. Doing that on the main thread freezes the game for as long as it takes to open
18
+ // 378 MiB of model, which is the other half of the defect this file exists to remove.
19
+ import { loadReadingRuntime } from './reading-runtime.js';
20
+ const reason = (e) => (e instanceof Error ? e.message : String(e));
21
+ /**
22
+ * Wires the protocol onto a scope. Exported — and not only run at import — so the gate exercises the REAL handler instead of a
23
+ * copy of it written in the test, which is the difference between measuring the protocol and measuring a description of it.
24
+ */
25
+ export function serveReading(scope, load = loadReadingRuntime) {
26
+ let transcriber = null;
27
+ scope.onmessage = (event) => {
28
+ const msg = event.data;
29
+ if (msg.kind === 'load') {
30
+ void (async () => {
31
+ try {
32
+ // a METHOD call on the scope: `fetch` detached from its realm throws «Illegal invocation»
33
+ transcriber = await load({ base: msg.base, language: msg.language, fetch: (url) => scope.fetch(url) });
34
+ scope.postMessage({ kind: 'ready' });
35
+ }
36
+ catch (e) {
37
+ scope.postMessage({ kind: 'failed', message: reason(e) });
38
+ }
39
+ })();
40
+ return;
41
+ }
42
+ // ⚠️ A REQUEST BEFORE THE MODEL IS OPEN IS ANSWERED, not dropped: a dropped message leaves the caller's promise pending for
43
+ // ever, and a child waiting for words that will never come has no way to know she should try again.
44
+ void (async () => {
45
+ try {
46
+ if (!transcriber)
47
+ throw new Error('reading worker: asked to transcribe before the model was opened');
48
+ scope.postMessage({ kind: 'text', id: msg.id, text: await transcriber.transcribe(msg.samples) });
49
+ }
50
+ catch (e) {
51
+ scope.postMessage({ kind: 'failed', id: msg.id, message: reason(e) });
52
+ }
53
+ })();
54
+ };
55
+ }
56
+ if (typeof WorkerGlobalScope !== 'undefined' && typeof self !== 'undefined' && self instanceof WorkerGlobalScope) {
57
+ serveReading(self);
58
+ }