@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.
- package/README.md +89 -78
- package/app/css/style.css +584 -374
- package/app/public/vendor/fonts/bitter-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bitter-var.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cookie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ar_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_br_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ca_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_co_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_deco_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_j_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_s_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_mx_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pe_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pt_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-stix_two_math-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700.woff2 +0 -0
- package/app/public/vendor/fonts.css +1167 -51
- package/dist-pkg/boot/create-game.d.ts +467 -162
- package/dist-pkg/boot/create-game.js +3563 -426
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +40 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +107 -0
- package/dist-pkg/core/accommodations.js +178 -0
- package/dist-pkg/core/actions.d.ts +75 -51
- package/dist-pkg/core/actions.js +98 -69
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +143 -163
- package/dist-pkg/core/contract.js +223 -207
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +87 -41
- package/dist-pkg/core/i18n.js +206 -153
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +321 -215
- package/dist-pkg/i18n/es.js +320 -215
- package/dist-pkg/i18n/pt.js +342 -215
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +164 -145
- package/dist-pkg/input/gamepad.js +351 -559
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +18 -20
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -62
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +124 -132
- package/dist-pkg/input/keydown.js +283 -288
- package/dist-pkg/input/latch-edge.d.ts +25 -21
- package/dist-pkg/input/latch-edge.js +33 -35
- package/dist-pkg/input/latch-scope.d.ts +43 -47
- package/dist-pkg/input/latch-scope.js +66 -75
- package/dist-pkg/input/latch-store.d.ts +28 -29
- package/dist-pkg/input/latch-store.js +44 -47
- package/dist-pkg/input/latch-sync.d.ts +28 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +164 -0
- package/dist-pkg/input/pad-wizard.d.ts +96 -0
- package/dist-pkg/input/pad-wizard.js +205 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +42 -0
- package/dist-pkg/input/switch-scan.js +54 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -113
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +130 -70
- package/dist-pkg/input/touch.js +321 -123
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +96 -114
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +46 -0
- package/dist-pkg/input/virtual-controller.js +41 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +43 -0
- package/dist-pkg/input/voice-map.js +125 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -1
- package/dist-pkg/platform/audio-ambient.js +11 -13
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +36 -39
- package/dist-pkg/platform/audio-sonar.d.ts +96 -113
- package/dist-pkg/platform/audio-sonar.js +245 -238
- package/dist-pkg/platform/audio.d.ts +53 -19
- package/dist-pkg/platform/audio.js +161 -169
- package/dist-pkg/platform/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -0
- package/dist-pkg/platform/guide-intensity.d.ts +26 -27
- package/dist-pkg/platform/guide-intensity.js +50 -52
- package/dist-pkg/platform/heavy-catalogue.d.ts +31 -0
- package/dist-pkg/platform/heavy-catalogue.js +223 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +26 -0
- package/dist-pkg/platform/heavy-mirror.js +76 -0
- package/dist-pkg/platform/heavy.d.ts +104 -0
- package/dist-pkg/platform/heavy.js +169 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +16 -16
- package/dist-pkg/platform/interruptible-speech.js +50 -51
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +81 -0
- package/dist-pkg/platform/locale-host.d.ts +10 -0
- package/dist-pkg/platform/locale-host.js +34 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +40 -0
- package/dist-pkg/platform/reading-in-worker.js +87 -0
- package/dist-pkg/platform/reading-model.d.ts +73 -0
- package/dist-pkg/platform/reading-model.js +247 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +159 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +69 -0
- package/dist-pkg/platform/reading.js +128 -0
- package/dist-pkg/platform/speech-recognition.d.ts +51 -0
- package/dist-pkg/platform/speech-recognition.js +84 -0
- package/dist-pkg/platform/speech.d.ts +14 -1
- package/dist-pkg/platform/speech.js +13 -13
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +51 -38
- package/dist-pkg/platform/tts.js +217 -119
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +36 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +6 -102
- package/dist-pkg/platform/voice-plan.js +9 -151
- package/dist-pkg/platform/vosk-runtime.d.ts +71 -0
- package/dist-pkg/platform/vosk-runtime.js +93 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +46 -12
- package/dist-pkg/render/crt.js +82 -80
- package/dist-pkg/render/cvd-matrices.d.ts +18 -18
- package/dist-pkg/render/cvd-matrices.js +33 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +66 -54
- package/dist-pkg/render/high-contrast.js +221 -216
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +80 -86
- package/dist-pkg/render/viz-axes.js +115 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +40 -0
- package/dist-pkg/ui/aac-sets.js +49 -0
- package/dist-pkg/ui/audio-choices.d.ts +63 -0
- package/dist-pkg/ui/audio-choices.js +94 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +6 -0
- package/dist-pkg/ui/camera-control.js +14 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +93 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +118 -63
- package/dist-pkg/ui/fonts.js +267 -111
- package/dist-pkg/ui/game-options.d.ts +42 -0
- package/dist-pkg/ui/game-options.js +138 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +76 -0
- package/dist-pkg/ui/help-panel.js +232 -0
- package/dist-pkg/ui/hud-bands.d.ts +45 -0
- package/dist-pkg/ui/hud-bands.js +108 -0
- package/dist-pkg/ui/hud.d.ts +73 -70
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/latch-refusal.d.ts +22 -21
- package/dist-pkg/ui/latch-refusal.js +37 -37
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +114 -99
- package/dist-pkg/ui/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +32 -0
- package/dist-pkg/ui/menu-intent.js +54 -0
- package/dist-pkg/ui/menu-items.d.ts +10 -0
- package/dist-pkg/ui/menu-items.js +22 -0
- package/dist-pkg/ui/menu-nav.d.ts +60 -90
- package/dist-pkg/ui/menu-nav.js +301 -274
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +116 -0
- package/dist-pkg/ui/panel-widgets.js +208 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +250 -343
- package/dist-pkg/ui/pause-icons.js +614 -605
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +42 -0
- package/dist-pkg/ui/settings-aac.d.ts +68 -0
- package/dist-pkg/ui/settings-aac.js +189 -0
- package/dist-pkg/ui/settings-audio.d.ts +91 -113
- package/dist-pkg/ui/settings-audio.js +407 -405
- package/dist-pkg/ui/settings-controls.d.ts +53 -92
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +195 -0
- package/dist-pkg/ui/settings-mobility.js +374 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +48 -45
- package/dist-pkg/ui/settings-panel.js +164 -93
- package/dist-pkg/ui/settings-typo.d.ts +28 -76
- package/dist-pkg/ui/settings-typo.js +145 -125
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +113 -134
- package/dist-pkg/ui/shell.js +143 -216
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +4 -4
- package/dist-pkg/ui/title.js +11 -13
- package/dist-pkg/ui/top-band.d.ts +24 -0
- package/dist-pkg/ui/top-band.js +100 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +84 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +33 -10
- package/dist-pkg/ui/vlibras.js +58 -81
- package/dist-pkg/ui/voice-control.d.ts +46 -0
- package/dist-pkg/ui/voice-control.js +143 -0
- package/dist-pkg/ui/voice-settings.d.ts +96 -0
- package/dist-pkg/ui/voice-settings.js +302 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +198 -54
- package/docs/LICENSES.md +160 -145
- package/package.json +24 -25
- package/scripts/heavy-into-the-delivery.mjs +144 -0
- package/scripts/licences/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -0
- package/scripts/licences/third-party.mjs +287 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/heavy.ts — THE HEAVY THINGS, DOWNLOADED ON FIRST LOAD (ADR-0110, ADR-0116, ADR-0119).
|
|
3
|
+
//
|
|
4
|
+
// ========================= WHAT THIS IS =========================
|
|
5
|
+
// Pillar 8 says "PWA ONLINE on the first day, then OFFLINE-FIRST", and ADR-0116 removed the contradiction that blocked
|
|
6
|
+
// this: installing is already a network act, so fetching at install violates nothing. What was missing was someone
|
|
7
|
+
// fetching.
|
|
8
|
+
//
|
|
9
|
+
// ⚠️ AND IT DOES NOT BLOCK THE GAME. The child plays while the heavy files come down; what must not happen is them
|
|
10
|
+
// reaching the second day, offline, and finding the voice was never fetched.
|
|
11
|
+
//
|
|
12
|
+
// ========================= THE THREE RULES THE SHAPE IMPOSES =========================
|
|
13
|
+
// 1. **ONE AT A TIME.** Four 60 MB downloads in parallel on a school link fight for the same bandwidth and none
|
|
14
|
+
// finishes first — and the game, which needs the network for its own images, waits behind them.
|
|
15
|
+
// 2. **NEVER THROWS.** A network failure is REPORTED and the list goes on. A `throw` here would bring down a game's
|
|
16
|
+
// start over a resource it may not even use today.
|
|
17
|
+
// 3. **IDEMPOTENT.** What is already in Cache Storage is not fetched again — which is what makes this safe to call on
|
|
18
|
+
// every start instead of only "on the first", which nobody can detect honestly.
|
|
19
|
+
import { CACHE_HEAVY, HEAVY_FILES, readingLanguageOf, commandsLanguageOf } from './heavy-catalogue.js';
|
|
20
|
+
export { CACHE_HEAVY, HEAVY_FILES };
|
|
21
|
+
/**
|
|
22
|
+
* WHAT A GAME'S START FETCHES (ADR-0216 §3): the catalogue, less what this game did not ask for.
|
|
23
|
+
*
|
|
24
|
+
* · The neural voice — its model, its voices AND the runtime that speaks them: without that answer they are 372 MB taken from a
|
|
25
|
+
* school's link and a child's device for nothing.
|
|
26
|
+
* · The reading models: 850 MiB for the three languages, so `reading` is not a yes or no but a LANGUAGE — the child's, known at
|
|
27
|
+
* boot. A delivery may carry more than one; a device downloads the one being read in. A game that never listens gets none.
|
|
28
|
+
* · 🔴 THE GRAPH RUNTIME IS NOT THE VOICE'S, and its `voz:` name said otherwise. `platform/onnx-runtime` runs Kokoro AND the
|
|
29
|
+
* reading models, so a game that only LISTENS needs it: without this line its delivery carried a 378 MiB model and nothing
|
|
30
|
+
* able to open it, and the first `listen()` asked for a file the build never wrote. Measured on 2026-09-21, building the
|
|
31
|
+
* very delivery this exists to serve. The PHONEMIZER (`voz:runtime:fonemas`, 18.7 MiB) stays the voice's — nothing else
|
|
32
|
+
* turns letters into sounds.
|
|
33
|
+
* · The command models (issue #184): one per language too, 112 MiB for the three, and the runtime that loads them. Nothing in
|
|
34
|
+
* the game decides this — speaking instead of pressing is a way INTO the controller, and a cartridge does not get to close
|
|
35
|
+
* one (ADR-0111). What decides is the delivery: `inclusionist-heavy --commands pt` puts Portuguese in it.
|
|
36
|
+
*/
|
|
37
|
+
export function heavyAtBoot(declared) {
|
|
38
|
+
const reading = declared.reading ? declared.reading.split('-')[0].toLowerCase() : null;
|
|
39
|
+
const commands = declared.commands ? declared.commands.split('-')[0].toLowerCase() : null;
|
|
40
|
+
return HEAVY_FILES.filter((p) => {
|
|
41
|
+
const language = readingLanguageOf(p.id);
|
|
42
|
+
if (language)
|
|
43
|
+
return language === reading;
|
|
44
|
+
// 📌 THE COMMAND MODELS ARE A TRANSPORT'S, not a game's: no cartridge declares them, because a child who speaks instead of
|
|
45
|
+
// pressing is reaching the controller, and a cartridge does not get to deny her a way in (ADR-0111). The LANGUAGE is still
|
|
46
|
+
// asked — 112 MiB for the three — and the runtime comes with whichever one does.
|
|
47
|
+
const commanded = commandsLanguageOf(p.id);
|
|
48
|
+
if (commanded)
|
|
49
|
+
return commanded === commands;
|
|
50
|
+
if (p.id.startsWith('commands:runtime'))
|
|
51
|
+
return !!commands;
|
|
52
|
+
if (p.id.startsWith('voz:runtime:onnx'))
|
|
53
|
+
return declared.kokoro || !!reading;
|
|
54
|
+
return declared.kokoro || !(p.id.startsWith('voz:kokoro:') || p.id.startsWith('voz:runtime:'));
|
|
55
|
+
}).map((p) => p.id);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* WHERE THE DELIVERY SERVES A HEAVY FILE (ADR-0177, issue #173): `heavy/<host><path>` beside the page. The child's device
|
|
59
|
+
* reads it from the game's own origin; the upstream address is only where the build fetched it from.
|
|
60
|
+
* 📌 The upstream address stays the CACHE KEY: it is what the voice and vision libraries ask for, and the service worker answers
|
|
61
|
+
* them from the checked cache without a network request.
|
|
62
|
+
*
|
|
63
|
+
* 🔴 THE FOLDER WAS CALLED «pesados» UNTIL 2026-09-21 (ADR-0219). 📏 What that costs a school was measured before it changed:
|
|
64
|
+
* the entries are kept under the UPSTREAM address, so nothing is re-downloaded — what breaks is a delivery built by the old
|
|
65
|
+
* `bin` under a new engine, which asks for `heavy/…` and gets a 404 until the delivery is built again.
|
|
66
|
+
*/
|
|
67
|
+
export function deliveryPath(url) {
|
|
68
|
+
const u = new URL(url);
|
|
69
|
+
return `heavy/${u.host}${u.pathname}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The inverse, for the service worker: a request for `…/heavy/<host><path>` is answered from the entry kept under
|
|
73
|
+
* `https://<host><path>`; any other address has no key (`null`). It is the route's `cacheKeyWillBeUsed` itself, so it also
|
|
74
|
+
* takes Workbox's `{ request }`. Self-contained on purpose — the PWA plugin copies this function's SOURCE into `sw.js`, where
|
|
75
|
+
* nothing else from this module exists.
|
|
76
|
+
*
|
|
77
|
+
* ⚠️ THE OFFSET COMES FROM THE FOLDER'S OWN LENGTH, and it is written this way because of what a blind rename would have done
|
|
78
|
+
* here: the old code advanced by 9, the length of the old folder's name with its slashes, and `/heavy/` is 7 — a text
|
|
79
|
+
* replacement of the name alone would
|
|
80
|
+
* have left every cache key with two characters of the host eaten, and the only symptom would be a cache that never hits.
|
|
81
|
+
*/
|
|
82
|
+
export function deliveryCacheKey(urlOrRequest) {
|
|
83
|
+
const folder = '/heavy/';
|
|
84
|
+
const urlPath = new URL(typeof urlOrRequest === 'string' ? urlOrRequest : urlOrRequest.request.url).pathname;
|
|
85
|
+
const i = urlPath.indexOf(folder);
|
|
86
|
+
return i < 0 ? null : 'https://' + urlPath.slice(i + folder.length);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* DOWNLOADS WHAT IS MISSING, ONE AT A TIME, AND RETURNS WHAT HAPPENED TO EACH.
|
|
90
|
+
*
|
|
91
|
+
* ⚠️ ENTRIES WITHOUT A `url` ARE NOT SKIPPED IN SILENCE — they return `sem-fonte`. It is the difference between "this
|
|
92
|
+
* subsystem has nowhere to come from yet" and "this subsystem is handled", exactly the distinction ADR-0119 measured as
|
|
93
|
+
* missing: the engine PROMISED four things and delivered one, with nothing saying so.
|
|
94
|
+
*/
|
|
95
|
+
export async function downloadHeavy(options) {
|
|
96
|
+
const targets = options.only ? HEAVY_FILES.filter((p) => options.only.includes(p.id)) : HEAVY_FILES;
|
|
97
|
+
const out = [];
|
|
98
|
+
const record = (r) => { out.push(r); options.onProgress?.(r); };
|
|
99
|
+
const { cacheStorage, fetch: fetchFile, digest, base } = options;
|
|
100
|
+
if (!cacheStorage || !fetchFile) {
|
|
101
|
+
for (const p of targets)
|
|
102
|
+
record({ id: p.id, outcome: 'falhou', error: 'sem Cache Storage ou sem fetch' });
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
const tools = { cache: await cacheStorage.open(CACHE_HEAVY), fetchFile, digest, base };
|
|
106
|
+
for (const p of targets)
|
|
107
|
+
record(await fetchOne(p, tools));
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/** One file's fate: already kept, fetched from the delivery and checked, or refused — always with the reason. */
|
|
111
|
+
async function fetchOne(p, t) {
|
|
112
|
+
if (!p.url)
|
|
113
|
+
return { id: p.id, outcome: 'sem-fonte', error: p.whyNoSource };
|
|
114
|
+
try {
|
|
115
|
+
if (await t.cache.match(p.url))
|
|
116
|
+
return { id: p.id, outcome: 'ja-tinha' };
|
|
117
|
+
// from the delivery's own origin, never from the upstream host (ADR-0177)
|
|
118
|
+
const resp = await t.fetchFile(new URL(deliveryPath(p.url), t.base).href);
|
|
119
|
+
if (!resp.ok)
|
|
120
|
+
return { id: p.id, outcome: 'falhou', error: `HTTP ${resp.status}` };
|
|
121
|
+
return await keepIfChecked(p, p.url, resp, t);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
return { id: p.id, outcome: 'falhou', error: e instanceof Error ? e.message : String(e) };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* CHECKED BEFORE KEPT (issue #168; STRIDE client pass). What is kept runs in the child's page and is served offline from then
|
|
129
|
+
* on, so a body whose SHA-256 is not the measured one never enters the cache. It is kept under the UPSTREAM address, which is
|
|
130
|
+
* what the voice and vision libraries ask for.
|
|
131
|
+
*/
|
|
132
|
+
async function keepIfChecked(p, url, resp, t) {
|
|
133
|
+
const refused = (reason) => ({ id: p.id, outcome: 'falhou', error: reason });
|
|
134
|
+
if (!p.sha256)
|
|
135
|
+
return refused('this entry pins its sha256 nowhere: there is nothing to check it against');
|
|
136
|
+
if (!t.digest)
|
|
137
|
+
return refused('this host cannot compute a sha256 (crypto.subtle needs a secure context)');
|
|
138
|
+
const body = await resp.arrayBuffer();
|
|
139
|
+
const got = await t.digest(body);
|
|
140
|
+
if (got !== p.sha256)
|
|
141
|
+
return refused(`sha256 mismatch: expected ${p.sha256}, got ${got} — not kept`);
|
|
142
|
+
await t.cache.put(url, new Response(body, { status: resp.status, statusText: resp.statusText, headers: resp.headers }));
|
|
143
|
+
return { id: p.id, outcome: 'baixado', bytes: p.bytes };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* THE SHA-256 OF A BODY AS LOWERCASE HEX, by the `crypto.subtle` it is handed (issue #168) — or `null` when there is none,
|
|
147
|
+
* which is a host outside a secure context: the answer `HeavyOptions.digest` reads as «cannot hash, so keep nothing».
|
|
148
|
+
*/
|
|
149
|
+
export function sha256With(subtle) {
|
|
150
|
+
if (!subtle)
|
|
151
|
+
return null;
|
|
152
|
+
return async (payload) => {
|
|
153
|
+
const bytes = new Uint8Array(await subtle.digest('SHA-256', payload));
|
|
154
|
+
return [...bytes].map((x) => x.toString(16).padStart(2, '0')).join('');
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* WHETHER A CATALOGUE FILE IS IN THE CHECKED CACHE, by its upstream address — what `platform/vision` and
|
|
159
|
+
* `platform/vosk-runtime` ask before loading anything. The host's `caches` is handed in; `undefined` (an insecure context)
|
|
160
|
+
* holds nothing, so every file is missing and the loader names them.
|
|
161
|
+
*/
|
|
162
|
+
export function checkedCacheHas(cacheStorage) {
|
|
163
|
+
return async (url) => !!cacheStorage && !!(await (await cacheStorage.open(CACHE_HEAVY)).match(url));
|
|
164
|
+
}
|
|
165
|
+
/** The size of what is still missing, in bytes — so a notice can say how much is left before it starts. */
|
|
166
|
+
export function bytesLeftToDownload(soFar) {
|
|
167
|
+
const feitos = new Set(soFar.filter((r) => r.outcome === 'ja-tinha' || r.outcome === 'baixado').map((r) => r.id));
|
|
168
|
+
return HEAVY_FILES.filter((p) => p.url && !feitos.has(p.id)).reduce((s, p) => s + (p.bytes ?? 0), 0);
|
|
169
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
/**
|
|
3
|
-
export interface
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
|
|
2
|
+
/** What the caller provides. Nothing here knows the neural engine, Web Audio or the browser. */
|
|
3
|
+
export interface SpeechEngine<Audio, Fonte> {
|
|
4
|
+
/** Text → audio. ASYNCHRONOUS on purpose: it is where neural synthesis spends its time. */
|
|
5
|
+
synthesize(text: string): Promise<Audio>;
|
|
6
|
+
/** Starts playing and returns the source, so it can be stopped. `null` = it could not play right now. */
|
|
7
|
+
play(audio: Audio, onEnded: () => void): Fonte | null;
|
|
8
|
+
/** Silences the source. Called with what `play` returned, and never with `null`. */
|
|
9
|
+
stop(playing: Fonte): void;
|
|
10
10
|
}
|
|
11
|
-
export interface
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
|
|
11
|
+
export interface InterruptibleSpeech {
|
|
12
|
+
/** Speaks `text`, SILENCING at once whatever is speaking. It does not queue: the latest request is the one that counts. */
|
|
13
|
+
speak(text: string): void;
|
|
14
|
+
/** Silences and forgets. Used when a menu closes or narration is switched off. */
|
|
15
|
+
silence(): void;
|
|
16
|
+
/** Is anything playing? For tests and debugging only — the policy does not depend on it. */
|
|
17
|
+
speaking(): boolean;
|
|
18
18
|
}
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function createInterruptibleSpeech<Audio, Fonte>(engine: SpeechEngine<Audio, Fonte>): InterruptibleSpeech;
|
|
@@ -1,79 +1,78 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// platform/interruptible-speech —
|
|
2
|
+
// platform/interruptible-speech — SPEAK THE LATEST REQUEST, AND SILENCE THE PREVIOUS ONE AT ONCE (ADR-0044, item 2).
|
|
3
3
|
//
|
|
4
|
-
// =========================
|
|
5
|
-
//
|
|
4
|
+
// ========================= THE DEFECT THIS REPLACES =========================
|
|
5
|
+
// The neural engine used to speak like this:
|
|
6
6
|
//
|
|
7
|
-
// speak: (text) => { if (busy) next = text; else speakNow(text); } //
|
|
7
|
+
// speak: (text) => { if (busy) next = text; else speakNow(text); } // a queue of 1
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// escuta estava vários itens atrás do foco.
|
|
9
|
+
// A QUEUE, of size one. Sweeping five menu items, the child heard the FIRST one whole and then the LAST — the three in
|
|
10
|
+
// between vanished in silence, because each new request overwrote `next`. It is slow AND it loses information, and both
|
|
11
|
+
// hurt in the same place: a person who cannot see navigates BY EAR, and the ear was several items behind the focus.
|
|
13
12
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// XAG 106 says what to do, and why: if the focused item's narration is still being read when the focus moves, the
|
|
14
|
+
// original element's narration stops IMMEDIATELY and the new element's begins.
|
|
16
15
|
//
|
|
17
|
-
// =========================
|
|
16
|
+
// ========================= THE TWO THINGS THIS GUARANTEES =========================
|
|
18
17
|
//
|
|
19
|
-
// 1.
|
|
20
|
-
//
|
|
21
|
-
//
|
|
18
|
+
// 1. SILENCE BEFORE SYNTHESISING, not after. Neural synthesis takes time; stopping only once the new audio is ready would
|
|
19
|
+
// leave the old voice speaking during the wait — the wrong item, with conviction. Silence is the right answer: the
|
|
20
|
+
// child knows they moved, and the silence confirms it.
|
|
22
21
|
//
|
|
23
|
-
// 2.
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
22
|
+
// 2. A GENERATION, which is what prevents the race. `synthesize` is asynchronous, and two requests can finish out of
|
|
23
|
+
// order: the second is ready first and starts playing, then the first arrives and runs it over — the child would
|
|
24
|
+
// hear the item they ALREADY passed, on top of the current one. Each request carries its number; whatever comes back
|
|
25
|
+
// with an old number is dropped, at each of the two `await`s.
|
|
27
26
|
//
|
|
28
|
-
// =========================
|
|
29
|
-
//
|
|
30
|
-
// runtime
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
export function
|
|
34
|
-
let
|
|
35
|
-
let
|
|
36
|
-
/**
|
|
37
|
-
function
|
|
38
|
-
if (
|
|
27
|
+
// ========================= WHY A MODULE, AND NOT A LINE IN `tts` =========================
|
|
28
|
+
// Because this way it can be PROVEN. The neural block lives inside a dynamic `import()` that only resolves with the
|
|
29
|
+
// runtime present; testing it there would need the real engine. Here the policy is pure — it receives "how to
|
|
30
|
+
// synthesise", "how to play" and "how to stop" — and the node test exercises the race and the interruption with fakes,
|
|
31
|
+
// in milliseconds.
|
|
32
|
+
export function createInterruptibleSpeech(engine) {
|
|
33
|
+
let nowPlaying = null;
|
|
34
|
+
let currentTurn = 0;
|
|
35
|
+
/** Silences whatever is playing. The `try` exists because stopping an already finished source throws in some engines. */
|
|
36
|
+
function stopPlayback() {
|
|
37
|
+
if (nowPlaying !== null) {
|
|
39
38
|
try {
|
|
40
|
-
|
|
39
|
+
engine.stop(nowPlaying);
|
|
41
40
|
}
|
|
42
|
-
catch (e) { /*
|
|
43
|
-
|
|
41
|
+
catch (e) { /* the source already ended — stopping again is no error */ }
|
|
42
|
+
nowPlaying = null;
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
|
-
async function
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
if (!
|
|
45
|
+
async function speakNow(text) {
|
|
46
|
+
const myTurn = ++currentTurn; // claims the turn BEFORE any wait
|
|
47
|
+
stopPlayback(); // guarantee 1: immediate silence, not at the end of synthesis
|
|
48
|
+
if (!text)
|
|
50
49
|
return;
|
|
51
50
|
try {
|
|
52
|
-
const audio = await
|
|
53
|
-
if (
|
|
54
|
-
return; //
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
if (
|
|
51
|
+
const audio = await engine.synthesize(text);
|
|
52
|
+
if (myTurn !== currentTurn)
|
|
53
|
+
return; // guarantee 2: it arrived late — another request already took over
|
|
54
|
+
stopPlayback(); // again: something may have started playing during the wait
|
|
55
|
+
const playing = engine.play(audio, () => { if (nowPlaying === playing)
|
|
56
|
+
nowPlaying = null; });
|
|
57
|
+
if (myTurn !== currentTurn) {
|
|
58
|
+
if (playing !== null) {
|
|
60
59
|
try {
|
|
61
|
-
|
|
60
|
+
engine.stop(playing);
|
|
62
61
|
}
|
|
63
62
|
catch (e) { /* noop */ }
|
|
64
63
|
}
|
|
65
64
|
return;
|
|
66
65
|
}
|
|
67
|
-
|
|
66
|
+
nowPlaying = playing;
|
|
68
67
|
}
|
|
69
68
|
catch (e) {
|
|
70
|
-
//
|
|
71
|
-
//
|
|
69
|
+
// Synthesis failed for THIS text. No reason to bring the whole narration down: the next request tries again, and one
|
|
70
|
+
// silent item is better than a dead engine.
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
speak: (text) => { void speakNow(text); },
|
|
75
|
+
silence: () => { currentTurn++; stopPlayback(); }, // the `++` invalidates whatever is being synthesised now
|
|
76
|
+
speaking: () => nowPlaying !== null,
|
|
78
77
|
};
|
|
79
78
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { KokoroModule } from './kokoro.js';
|
|
3
|
+
import type { OnnxRuntime } from './onnx-runtime.js';
|
|
4
|
+
/** The file system espeak-ng's Emscripten module exposes — only what this uses. */
|
|
5
|
+
export interface EspeakFileSystem {
|
|
6
|
+
readonly writeFile: (path: string, text: string) => void;
|
|
7
|
+
readonly readFile: (path: string, options: {
|
|
8
|
+
encoding: 'utf8';
|
|
9
|
+
}) => string;
|
|
10
|
+
}
|
|
11
|
+
/** espeak-ng's module factory: one program run per call, with its arguments and the hooks run before `main`. */
|
|
12
|
+
export type EspeakFactory = (options: {
|
|
13
|
+
readonly arguments: readonly string[];
|
|
14
|
+
readonly preRun: readonly ((m: {
|
|
15
|
+
FS: EspeakFileSystem;
|
|
16
|
+
}) => void)[];
|
|
17
|
+
}) => Promise<{
|
|
18
|
+
FS: EspeakFileSystem;
|
|
19
|
+
}>;
|
|
20
|
+
export interface KokoroPortDeps {
|
|
21
|
+
readonly espeak: EspeakFactory;
|
|
22
|
+
readonly ort: OnnxRuntime;
|
|
23
|
+
readonly fetch: (url: string) => Promise<Response>;
|
|
24
|
+
/** The page's address `heavy/` is resolved against. */
|
|
25
|
+
readonly base: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function createKokoroPort(d: KokoroPortDeps): KokoroModule;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { KOKORO_MODEL_URL, URL_DO_TOKENIZADOR_KOKORO, kokoroVoiceUrl } from './kokoro.js';
|
|
3
|
+
import { deliveryPath } from './heavy.js';
|
|
4
|
+
const INPUT = 'entrada.txt';
|
|
5
|
+
const OUTPUT = 'fonemas.txt';
|
|
6
|
+
export function createKokoroPort(d) {
|
|
7
|
+
const fromDelivery = async (url) => {
|
|
8
|
+
const path = deliveryPath(url);
|
|
9
|
+
const r = await d.fetch(new URL(path, d.base).href);
|
|
10
|
+
if (!r.ok)
|
|
11
|
+
throw new Error(`Kokoro: HTTP ${r.status} for ${path} — the delivery does not carry it (inclusionist-heavy --kokoro)`);
|
|
12
|
+
return r;
|
|
13
|
+
};
|
|
14
|
+
let vocabulary = null;
|
|
15
|
+
// ⚠️ ONE COPY of the 325 MB model for every session: the engine tries WebGPU and may fall back to WASM
|
|
16
|
+
let model = null;
|
|
17
|
+
return {
|
|
18
|
+
async phonemize(text, espeak) {
|
|
19
|
+
// the sentence goes in as a FILE and never as an argument: a line starting with «-» would be read as an option
|
|
20
|
+
const e = await d.espeak({
|
|
21
|
+
arguments: ['-q', '--ipa', '--phonout', OUTPUT, '-v', espeak, '-f', INPUT],
|
|
22
|
+
preRun: [(m) => m.FS.writeFile(INPUT, text.replace(/\s+/g, ' '))],
|
|
23
|
+
});
|
|
24
|
+
return e.FS.readFile(OUTPUT, { encoding: 'utf8' }).trim().replace(/\s*\n\s*/g, ' ');
|
|
25
|
+
},
|
|
26
|
+
vocabulary() {
|
|
27
|
+
vocabulary ??= fromDelivery(URL_DO_TOKENIZADOR_KOKORO)
|
|
28
|
+
.then(async (r) => (await r.json()).model.vocab);
|
|
29
|
+
return vocabulary;
|
|
30
|
+
},
|
|
31
|
+
async voice(id) {
|
|
32
|
+
return new Float32Array(await (await fromDelivery(kokoroVoiceUrl(id))).arrayBuffer());
|
|
33
|
+
},
|
|
34
|
+
async session(device) {
|
|
35
|
+
model ??= fromDelivery(KOKORO_MODEL_URL).then(async (r) => new Uint8Array(await r.arrayBuffer()));
|
|
36
|
+
const s = await d.ort.InferenceSession.create(await model, { executionProviders: [device] });
|
|
37
|
+
const session = {
|
|
38
|
+
async synthesize(ids, style) {
|
|
39
|
+
const out = await s.run({
|
|
40
|
+
input_ids: new d.ort.Tensor('int64', BigInt64Array.from(ids, (id) => BigInt(id)), [1, ids.length]),
|
|
41
|
+
style: new d.ort.Tensor('float32', style, [1, style.length]),
|
|
42
|
+
speed: new d.ort.Tensor('float32', Float32Array.of(1), [1]), // the pace is the engine's, on playback (ADR-0196)
|
|
43
|
+
});
|
|
44
|
+
return out[s.outputNames[0]].data;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
return session;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { KokoroModule } from './kokoro.js';
|
|
3
|
+
export interface KokoroRuntimeDeps {
|
|
4
|
+
/** The page's address, which `heavy/` is resolved against. */
|
|
5
|
+
readonly base: string;
|
|
6
|
+
/**
|
|
7
|
+
* The host's `fetch`, and the host's `WebAssembly.compile` and `instantiate` below: REQUIRED (ADR-0232 D4). The root lends
|
|
8
|
+
* them from `host.win`; a default would be the page's globals reached from `platform/`, and a case answers without a network.
|
|
9
|
+
*/
|
|
10
|
+
readonly fetch: (url: string) => Promise<Response>;
|
|
11
|
+
/** `import()`, injected so a case can hand in the two modules without a network. Optional: `import()` is not a global. */
|
|
12
|
+
readonly importModule?: (url: string) => Promise<unknown>;
|
|
13
|
+
readonly compileWasm: (bytes: ArrayBuffer) => Promise<WebAssembly.Module>;
|
|
14
|
+
readonly instantiateWasm: (module: WebAssembly.Module, imports: WebAssembly.Imports) => Promise<WebAssembly.Instance>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds the neural voice. Everything it needs is fetched from the delivery, so a device that never had a network day has it all
|
|
18
|
+
* or has none of it — and «none of it» is a refusal the caller reports, not a silence.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadKokoroRuntime(d: KokoroRuntimeDeps): Promise<KokoroModule>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/kokoro-runtime — THE ENGINE LOADS THE NEURAL VOICE ITSELF (ADR-0216 and its erratum; issue #200).
|
|
3
|
+
//
|
|
4
|
+
// The Dev, 2026-09-21: «a engine deve oferecer objetos de leitura e TTS. O jogo não deve precisar saber como isso funciona». So the
|
|
5
|
+
// phonemizer and the ONNX runtime are no longer a game's dependency: they are catalogued heavy files (`voz:runtime:*`), the build
|
|
6
|
+
// puts them in the delivery, and this loads them from `heavy/` on the page's own origin — the same path the vision runtime
|
|
7
|
+
// already takes (ADR-0177, `platform/vision`).
|
|
8
|
+
//
|
|
9
|
+
// ⚠️ NOTHING HERE IS IMPORTED FROM npm, and that is the point: an `import 'espeak-ng'` would put the phonemizer in the bundle of
|
|
10
|
+
// every game that merely links the engine, and would need a bundler to resolve it. `import(url)` of an address on our own origin
|
|
11
|
+
// needs neither, and it happens only when a child picks a neural voice.
|
|
12
|
+
//
|
|
13
|
+
// · The wasm of espeak-ng is compiled ONCE and instantiated per sentence: its module runs one program and exits.
|
|
14
|
+
// · onnxruntime's threads load their own glue and wasm; they are pointed at `heavy/` too, because a worker that goes looking for
|
|
15
|
+
// them on a CDN finds nothing in a school with no network, and the child hears silence (measured in the quiz demo, #181).
|
|
16
|
+
import { createKokoroPort } from './kokoro-port.js';
|
|
17
|
+
import { atDelivery, loadOnnxRuntime } from './onnx-runtime.js';
|
|
18
|
+
// The addresses are the catalogue's, reached by id through `platform/onnx-runtime` — never written twice (ADR-0114, ADR-0177).
|
|
19
|
+
const ESPEAK_GLUE = 'voz:runtime:fonemas';
|
|
20
|
+
const ESPEAK_WASM = 'voz:runtime:fonemas:wasm';
|
|
21
|
+
/**
|
|
22
|
+
* Builds the neural voice. Everything it needs is fetched from the delivery, so a device that never had a network day has it all
|
|
23
|
+
* or has none of it — and «none of it» is a refusal the caller reports, not a silence.
|
|
24
|
+
*/
|
|
25
|
+
export async function loadKokoroRuntime(d) {
|
|
26
|
+
const { compileWasm: compile, instantiateWasm: instantiate, fetch: get } = d;
|
|
27
|
+
const loadModule = d.importModule ?? ((url) => import(/* @vite-ignore */ url));
|
|
28
|
+
const espeakModule = await loadModule(atDelivery(ESPEAK_GLUE, d.base));
|
|
29
|
+
const factory = (typeof espeakModule === 'function' ? espeakModule : espeakModule.default);
|
|
30
|
+
if (typeof factory !== 'function')
|
|
31
|
+
throw new Error('Kokoro: espeak-ng did not load from the delivery (voz:runtime:fonemas)');
|
|
32
|
+
// by BYTES and not by stream: a server that sends the file without `application/wasm` must not break the voice
|
|
33
|
+
let compiled = null;
|
|
34
|
+
const espeak = (options) => {
|
|
35
|
+
compiled ??= get(atDelivery(ESPEAK_WASM, d.base)).then(async (r) => {
|
|
36
|
+
if (!r.ok)
|
|
37
|
+
throw new Error(`Kokoro: HTTP ${r.status} for espeak-ng's wasm — the delivery does not carry it`);
|
|
38
|
+
return compile(await r.arrayBuffer());
|
|
39
|
+
});
|
|
40
|
+
const module = compiled;
|
|
41
|
+
return factory({
|
|
42
|
+
...options,
|
|
43
|
+
instantiateWasm: (imports, ready) => {
|
|
44
|
+
void module.then(async (m) => ready(await instantiate(m, imports), m));
|
|
45
|
+
return {};
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
// the runtime, and the rule about its threads, are `platform/onnx-runtime`'s — the reading loads the same one the same way
|
|
50
|
+
const ort = await loadOnnxRuntime({ base: d.base, importModule: loadModule });
|
|
51
|
+
return createKokoroPort({ espeak, ort, fetch: get, base: d.base });
|
|
52
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { NeuralVoice } from './voice-plan.js';
|
|
3
|
+
/** A Kokoro inference session on one device: token ids and a style row in, a 24 kHz waveform out. */
|
|
4
|
+
export interface KokoroSession {
|
|
5
|
+
readonly synthesize: (ids: readonly number[], styleVector: Float32Array) => Promise<Float32Array>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* WHAT SPEAKING NEEDS OF KOKORO — `platform/kokoro-runtime` fills it from the delivery (ADR-0216 §1).
|
|
9
|
+
* `phonemize` is espeak-ng in the voice's language (`pt-br`, `es-419`, `en-us`, `en-gb`); `vocabulary` the model tokenizer's symbols;
|
|
10
|
+
* `voice` a voice's style table; `session` a session on WebGPU or WASM.
|
|
11
|
+
*
|
|
12
|
+
* 📌 IT LIVES IN THIS LEAF and not beside the speaking, so that the runtime that builds one can be reached from `platform/tts` by
|
|
13
|
+
* `import()` without the two naming each other — a cycle the direction gate (ADR-0173) refuses, and rightly: the loader must not
|
|
14
|
+
* have to load the speaker to be loaded by it.
|
|
15
|
+
*/
|
|
16
|
+
export interface KokoroModule {
|
|
17
|
+
readonly phonemize: (text: string, espeak: string) => Promise<string>;
|
|
18
|
+
readonly vocabulary: () => Promise<Readonly<{
|
|
19
|
+
[symbol: string]: number;
|
|
20
|
+
}>>;
|
|
21
|
+
readonly voice: (id: string) => Promise<Float32Array>;
|
|
22
|
+
readonly session: (device: 'webgpu' | 'wasm') => Promise<KokoroSession>;
|
|
23
|
+
}
|
|
24
|
+
/** How the neural voice arrives. Until ADR-0216 every game wrote one of these; now the engine has its own. */
|
|
25
|
+
export type LoadKokoro = () => Promise<KokoroModule>;
|
|
26
|
+
/** A Kokoro voice of the engine's three languages. `recommended` marks the two the Dev rated good (ADR-0198 §3). */
|
|
27
|
+
export interface KokoroVoice extends NeuralVoice {
|
|
28
|
+
readonly engine: 'kokoro';
|
|
29
|
+
/** The espeak-ng voice that phonemizes this voice's text. */
|
|
30
|
+
readonly espeak: string;
|
|
31
|
+
readonly recommended: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Kokoro-82M v1.0's voices for Portuguese, Spanish and English, as the model repository lists them (read 2026-09-14). The model's
|
|
35
|
+
* first letter is the language — `p` Brazilian Portuguese, `e` Spanish, `a` American and `b` British English — and the second the
|
|
36
|
+
* voice's gender. The others (French, Hindi, Italian, Japanese, Chinese) are not the engine's languages.
|
|
37
|
+
*/
|
|
38
|
+
export declare const KOKORO_VOICES: readonly KokoroVoice[];
|
|
39
|
+
export declare const KOKORO_MODEL_URL = "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main/onnx/model.onnx";
|
|
40
|
+
export declare const URL_DO_TOKENIZADOR_KOKORO = "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main/tokenizer.json";
|
|
41
|
+
export declare const kokoroVoiceUrl: (id: string) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Each voice file's SHA-256 and size, read from the repository's LFS metadata on 2026-09-14 (all 522 240 bytes); `pf_dora` also
|
|
44
|
+
* measured on the downloaded file. The model: 325 532 232 bytes, measured on the file. Checked before anything is kept (#168).
|
|
45
|
+
*/
|
|
46
|
+
export declare const KOKORO_VOICES_SHA256: Readonly<{
|
|
47
|
+
[id: string]: string;
|
|
48
|
+
}>;
|
|
49
|
+
export declare const KOKORO_VOICE_BYTES = 522240;
|
|
50
|
+
export declare const KOKORO_MODEL_SHA256 = "8fbea51ea711f2af382e88c833d9e288c6dc82ce5e98421ea61c058ce21a34cb";
|
|
51
|
+
export declare const KOKORO_MODEL_BYTES = 325532232;
|
|
52
|
+
export declare const SHA256_DO_TOKENIZADOR_KOKORO = "77a02c8e164413299b4b4c403b14f8e0e1c1b727db4d46a09d6327b861060a34";
|
|
53
|
+
export declare const BYTES_DO_TOKENIZADOR_KOKORO = 3497;
|
|
54
|
+
/** The model's context: ids between the two pad tokens. A longer sentence is cut here (the caller splits text by sentence). */
|
|
55
|
+
export declare const MAX_KOKORO_TOKENS = 510;
|
|
56
|
+
/** A voice file is a table of style rows, one per token count, 256 numbers each. */
|
|
57
|
+
export declare const STYLE_DIMENSION = 256;
|
|
58
|
+
/** The token ids of a phoneme string: each symbol the vocabulary knows, in order, between two pad tokens (id 0). */
|
|
59
|
+
export declare function tokenize(phonemes: string, symbolIds: Readonly<{
|
|
60
|
+
[symbol: string]: number;
|
|
61
|
+
}>): number[];
|
|
62
|
+
/** The style row a sentence of `tokens` ids (pads excluded) takes from a voice table. */
|
|
63
|
+
export declare function sentenceStyle(styleTable: Float32Array, tokens: number): Float32Array;
|
|
64
|
+
/**
|
|
65
|
+
* Is a synthesis speech? Measured on 2026-09-14: WebGPU on one AMD GPU gave a waveform whose samples ran to 2×10⁷ — noise a child
|
|
66
|
+
* would hear as a burst. A speech waveform stays within ±1 (a sample or two past it is clipping, not noise) and is not silent.
|
|
67
|
+
*/
|
|
68
|
+
export declare function eFala(waveform: ArrayLike<number>): boolean;
|
|
69
|
+
/** A 16-bit mono PCM WAV of a waveform, clipped to ±1 — what the narration's media element plays. */
|
|
70
|
+
export declare function wavDe(waveform: ArrayLike<number>, sampleRate?: number): ArrayBuffer;
|