@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,36 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Translate } from '../core/i18n.js';
|
|
3
|
+
import type { VirtualController } from '../input/virtual-controller.js';
|
|
4
|
+
import { type FaceTrackerLoad, type VisionDeps } from '../platform/vision.js';
|
|
5
|
+
import { type VisionLoopDeps } from '../platform/vision-loop.js';
|
|
6
|
+
import type { SwitchableControl } from './switchable-control.js';
|
|
7
|
+
/** A camera picture the tracker can read. */
|
|
8
|
+
export interface CameraFeed {
|
|
9
|
+
readonly frame: unknown;
|
|
10
|
+
ready(): boolean;
|
|
11
|
+
close(): void;
|
|
12
|
+
}
|
|
13
|
+
export interface EyeControlDeps {
|
|
14
|
+
/** Translates in the page's language — the root's translator (ADR-0232 D3). REQUIRED: text built from nowhere is a raw key. */
|
|
15
|
+
t: Translate;
|
|
16
|
+
readonly doc: Document;
|
|
17
|
+
/** Where the regions are drawn: `#game-region`. */
|
|
18
|
+
readonly region: HTMLElement;
|
|
19
|
+
/** The page's address, to reach `heavy/`. */
|
|
20
|
+
readonly base: string;
|
|
21
|
+
/** Whether a file is in the checked cache, handed to the tracker's loader (ADR-0232 D4: the root lends the cache). */
|
|
22
|
+
readonly hasFile: VisionDeps['hasFile'];
|
|
23
|
+
readonly loop: VisionLoopDeps;
|
|
24
|
+
/** Where the presses go: seat 0's virtual controller. */
|
|
25
|
+
readonly controller: VirtualController;
|
|
26
|
+
readonly say: (text: string) => void;
|
|
27
|
+
readonly alert: (text: string) => void;
|
|
28
|
+
/** A line for `problems`. */
|
|
29
|
+
readonly report: (line: string) => void;
|
|
30
|
+
/** Put the 📷 back to off: what cannot start must not show as on. */
|
|
31
|
+
readonly turnOff: () => void;
|
|
32
|
+
readonly loadTracker?: (deps: VisionDeps) => Promise<FaceTrackerLoad>;
|
|
33
|
+
readonly openFeed?: () => Promise<CameraFeed>;
|
|
34
|
+
}
|
|
35
|
+
export declare function videoFeed(doc: Document, media: MediaDevices): () => Promise<CameraFeed>;
|
|
36
|
+
export declare function createEyeControl(d: EyeControlDeps): SwitchableControl;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// ui/eye-control — PLAYING WITH THE EYES, PUT TOGETHER (ADR-0213; issues #194, #196).
|
|
3
|
+
//
|
|
4
|
+
// The pieces are each tested apart; this joins them for the root: the camera and the face tracker (platform/vision), a frame loop that
|
|
5
|
+
// cannot stop in silence (platform/vision-loop), the right eye's gaze read from its own rest (input/gaze-relative), the cycle that turns
|
|
6
|
+
// zones into actions (input/gaze-cycle), the presses on the virtual controller with the source `olhos` (input/virtual-controller, ADR-0111:
|
|
7
|
+
// never a disguised keyboard), and the regions drawn over the game
|
|
8
|
+
// (ui/gaze-overlay). The 📷 at its eyes position drives it (ADR-0215); any other position lets the camera go.
|
|
9
|
+
// · Nothing commands before the rest is measured: until then, and on a frame with no face or a head turning fast, the cycle is frozen.
|
|
10
|
+
// · A reading that re-centres itself cancels the gesture in hand.
|
|
11
|
+
// · Only the RIGHT eye is read (ADR-0213): the Dev's brain suppresses the left one, and a child's may too.
|
|
12
|
+
// · What cannot work is said to the child and written in `problems`, once: the files not on the device, the camera refused, frames that
|
|
13
|
+
// stop or crawl. A 📷 that is on and does nothing is the defect this module exists not to ship.
|
|
14
|
+
import { headPoseFromMatrix, scoresFromCategories, eyeGazeFromScores, bothEyesClosed } from '../input/face-signals.js';
|
|
15
|
+
import { createGazeReader, GAZE_DEFAULTS } from '../input/gaze-relative.js';
|
|
16
|
+
import { createGazeCycle } from '../input/gaze-cycle.js';
|
|
17
|
+
import { loadFaceTracker, openCamera, closeCamera } from '../platform/vision.js';
|
|
18
|
+
import { createVisionLoop } from '../platform/vision-loop.js';
|
|
19
|
+
import { drawGazeOverlay } from './gaze-overlay.js';
|
|
20
|
+
// 📌 THE SHAPE IS THE FAMILY'S (ADR-0221 step 7f): what this module returns IS a SwitchableControl — following the 📷: on in
|
|
21
|
+
// the eyes position it opens the camera and the drawing, off it lets go of everything.
|
|
22
|
+
export function videoFeed(doc, media) {
|
|
23
|
+
return async () => {
|
|
24
|
+
const stream = await openCamera(media);
|
|
25
|
+
const video = doc.createElement('video');
|
|
26
|
+
video.muted = true;
|
|
27
|
+
video.playsInline = true;
|
|
28
|
+
video.srcObject = stream;
|
|
29
|
+
await video.play();
|
|
30
|
+
return { frame: video, ready: () => video.readyState >= 2, close: () => { video.pause(); video.srcObject = null; closeCamera(stream); } };
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** What one detection says: the blendshapes (none without a face), the head's pose, and the RIGHT eye's gaze. */
|
|
34
|
+
function readDetection(det) {
|
|
35
|
+
const cats = det?.faceBlendshapes?.[0]?.categories;
|
|
36
|
+
const scores = cats ? scoresFromCategories(cats) : null;
|
|
37
|
+
return { scores, pose: headPoseFromMatrix(det?.facialTransformationMatrixes?.[0]?.data), eye: scores ? eyeGazeFromScores(scores).right : null };
|
|
38
|
+
}
|
|
39
|
+
/** What the cycle is told: frozen while nothing can be trusted — no rest yet, no face, a head turning fast — and cancelled when
|
|
40
|
+
* the reader re-centres under the gaze, because what was held was never a decision. */
|
|
41
|
+
function cycleFrameOf(reading, scores) {
|
|
42
|
+
return {
|
|
43
|
+
zone: reading.zone,
|
|
44
|
+
eyesClosed: !!scores && bothEyesClosed(scores),
|
|
45
|
+
frozen: !reading.ready || !scores || reading.reason === 'head-moving',
|
|
46
|
+
cancel: reading.reason === 'recentring',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** The reading, written on the drawing's own element: when a child's eyes are not answered, this says at which step it stops. */
|
|
50
|
+
function writeDiagnosis(canvas, reading, out, face, delegate) {
|
|
51
|
+
const f2 = (n) => (n === undefined ? '' : n.toFixed(2));
|
|
52
|
+
Object.assign(canvas.dataset, {
|
|
53
|
+
face: String(face), ready: String(reading.ready), reason: reading.reason ?? '', zone: reading.zone ?? '',
|
|
54
|
+
tremorH: f2(reading.tremor?.h), tremorV: f2(reading.tremor?.v), dh: f2(reading.displacement?.h), dv: f2(reading.displacement?.v),
|
|
55
|
+
stillMs: String(Math.round(reading.stillMs ?? 0)), armed: String(out.armed), preparing: String(out.preparing), preview: out.preview?.item ?? '',
|
|
56
|
+
delegate,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** The regions over the game at the region's size, the middle counting down while the rest is measured, and the face's lines. */
|
|
60
|
+
function drawFrame(t, canvas, region, reading, out, det, lines) {
|
|
61
|
+
const w = canvas.width = region.clientWidth, h = canvas.height = region.clientHeight;
|
|
62
|
+
drawGazeOverlay(t, canvas.getContext('2d'), w, h, {
|
|
63
|
+
zone: reading.zone, armed: out.armed, preparing: out.preparing, preview: out.preview, restReady: reading.ready,
|
|
64
|
+
restLeftMs: reading.ready ? undefined : Math.max(0, GAZE_DEFAULTS.restMs - (reading.stillMs ?? 0)),
|
|
65
|
+
}, { face: det?.faceLandmarks?.[0] ? { landmarks: det.faceLandmarks[0], lines } : null });
|
|
66
|
+
}
|
|
67
|
+
export function createEyeControl(d) {
|
|
68
|
+
const { t } = d;
|
|
69
|
+
const loadTracker = d.loadTracker ?? loadFaceTracker;
|
|
70
|
+
const openFeed = d.openFeed ?? videoFeed(d.doc, d.doc.defaultView.navigator.mediaDevices);
|
|
71
|
+
const said = new Set();
|
|
72
|
+
const once = (kind, line, spoken) => {
|
|
73
|
+
if (!said.has(kind)) {
|
|
74
|
+
said.add(kind);
|
|
75
|
+
d.report(line);
|
|
76
|
+
}
|
|
77
|
+
d.alert(spoken);
|
|
78
|
+
};
|
|
79
|
+
let on = false, running = false, starting = null;
|
|
80
|
+
const current = () => on; // read through a call: `apply` awaits, and `on` can change meanwhile
|
|
81
|
+
let tracker = null, feed = null, canvas = null;
|
|
82
|
+
let pressed = null, wasReady = false;
|
|
83
|
+
let reader = createGazeReader(), cycle = createGazeCycle();
|
|
84
|
+
let loop = null;
|
|
85
|
+
const release = () => { if (pressed)
|
|
86
|
+
d.controller.release(pressed, 'olhos'); pressed = null; };
|
|
87
|
+
/** Only a change reaches the controller: the old action is let go, the new one pressed, from the eyes. */
|
|
88
|
+
const followPress = (next) => {
|
|
89
|
+
if (next === pressed)
|
|
90
|
+
return;
|
|
91
|
+
if (pressed)
|
|
92
|
+
d.controller.release(pressed, 'olhos');
|
|
93
|
+
if (next)
|
|
94
|
+
d.controller.press(next, 'olhos');
|
|
95
|
+
pressed = next;
|
|
96
|
+
};
|
|
97
|
+
const frame = (ms) => {
|
|
98
|
+
if (!tracker || !feed || !canvas || !feed.ready())
|
|
99
|
+
return;
|
|
100
|
+
const det = tracker.detect(feed.frame, ms);
|
|
101
|
+
const { scores, pose, eye } = readDetection(det);
|
|
102
|
+
const reading = reader(ms, { h: eye?.h, v: eye?.v, pose });
|
|
103
|
+
if (reading.ready && !wasReady)
|
|
104
|
+
d.say(t('sr.eyes.ready'));
|
|
105
|
+
wasReady = reading.ready;
|
|
106
|
+
const out = cycle(ms, cycleFrameOf(reading, scores));
|
|
107
|
+
followPress(out.pressed);
|
|
108
|
+
writeDiagnosis(canvas, reading, out, !!scores, tracker.delegate());
|
|
109
|
+
drawFrame(t, canvas, d.region, reading, out, det, tracker.eyeLines);
|
|
110
|
+
};
|
|
111
|
+
const health = (h, fps) => {
|
|
112
|
+
if (h === 'stalled')
|
|
113
|
+
once('stalled', 'eye control: a second without a camera frame — meanwhile the child\'s gaze commands nothing; keep the tab in front and the camera free', t('sr.eyes.stopped'));
|
|
114
|
+
if (h === 'slow')
|
|
115
|
+
once('slow', `eye control: ${fps} frames a second, under 8 — the reading misses movements and the child may not be answered; close other heavy tabs or use a lighter device`, t('sr.eyes.slow'));
|
|
116
|
+
};
|
|
117
|
+
const stop = () => {
|
|
118
|
+
loop?.stop();
|
|
119
|
+
loop = null;
|
|
120
|
+
release();
|
|
121
|
+
feed?.close();
|
|
122
|
+
feed = null;
|
|
123
|
+
tracker?.close();
|
|
124
|
+
tracker = null;
|
|
125
|
+
canvas?.remove();
|
|
126
|
+
canvas = null;
|
|
127
|
+
running = false;
|
|
128
|
+
wasReady = false;
|
|
129
|
+
};
|
|
130
|
+
const start = async () => {
|
|
131
|
+
const load = await loadTracker({ base: d.base, hasFile: d.hasFile });
|
|
132
|
+
if (!load.ok) {
|
|
133
|
+
once('files', `eye control: ${load.missing.join(', ')} not on this device — the child cannot play with the eyes; open the game once online so the install fetches them`, t('sr.eyes.needsInternet'));
|
|
134
|
+
d.turnOff();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
feed = await openFeed();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
load.tracker.close();
|
|
142
|
+
once('camera', 'eye control: the camera did not open — the child cannot play with the eyes; allow the camera for this page, or plug one in', t('sr.eyes.noCamera'));
|
|
143
|
+
d.turnOff();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
tracker = load.tracker;
|
|
147
|
+
canvas = d.doc.createElement('canvas');
|
|
148
|
+
canvas.className = 'gaze-overlay';
|
|
149
|
+
canvas.setAttribute('aria-hidden', 'true');
|
|
150
|
+
Object.assign(canvas.style, { position: 'absolute', inset: '0', width: '100%', height: '100%', pointerEvents: 'none', zIndex: '5' });
|
|
151
|
+
d.region.appendChild(canvas);
|
|
152
|
+
reader = createGazeReader();
|
|
153
|
+
cycle = createGazeCycle();
|
|
154
|
+
pressed = null;
|
|
155
|
+
loop = createVisionLoop(d.loop, { onFrame: frame, onError: (e) => once('frame', `eye control: a frame failed (${String(e)}) — the loop goes on, but a repeated failure means the child is not being read`, t('sr.eyes.stopped')), onHealth: health });
|
|
156
|
+
running = true;
|
|
157
|
+
d.say(t('sr.eyes.lookMiddle'));
|
|
158
|
+
loop.start();
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
async apply(next) {
|
|
162
|
+
on = next;
|
|
163
|
+
if (starting)
|
|
164
|
+
await starting;
|
|
165
|
+
if (!on) {
|
|
166
|
+
if (running)
|
|
167
|
+
stop();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (running)
|
|
171
|
+
return;
|
|
172
|
+
starting = start().finally(() => { starting = null; });
|
|
173
|
+
await starting;
|
|
174
|
+
if (!current() && running)
|
|
175
|
+
stop(); // turned off while the camera was opening
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Translate } from '../core/i18n.js';
|
|
3
|
+
import type { VirtualController } from '../input/virtual-controller.js';
|
|
4
|
+
import { type FaceTrackerLoad, type VisionDeps } from '../platform/vision.js';
|
|
5
|
+
import { type VisionLoopDeps } from '../platform/vision-loop.js';
|
|
6
|
+
import type { CameraFeed } from './eye-control.js';
|
|
7
|
+
import type { SwitchableControl } from './switchable-control.js';
|
|
8
|
+
export interface FaceControlDeps {
|
|
9
|
+
/** Translates in the page's language — the root's translator (ADR-0232 D3). REQUIRED: text built from nowhere is a raw key. */
|
|
10
|
+
t: Translate;
|
|
11
|
+
readonly doc: Document;
|
|
12
|
+
readonly region: HTMLElement;
|
|
13
|
+
readonly base: string;
|
|
14
|
+
/** Whether a file is in the checked cache, handed to the tracker's loader (ADR-0232 D4: the root lends the cache). */
|
|
15
|
+
readonly hasFile: VisionDeps['hasFile'];
|
|
16
|
+
readonly loop: VisionLoopDeps;
|
|
17
|
+
readonly controller: VirtualController;
|
|
18
|
+
readonly say: (text: string) => void;
|
|
19
|
+
readonly alert: (text: string) => void;
|
|
20
|
+
readonly report: (line: string) => void;
|
|
21
|
+
readonly turnOff: () => void;
|
|
22
|
+
readonly openFeed: () => Promise<CameraFeed>;
|
|
23
|
+
readonly loadTracker?: (deps: VisionDeps) => Promise<FaceTrackerLoad>;
|
|
24
|
+
}
|
|
25
|
+
export declare function createFaceControl(d: FaceControlDeps): SwitchableControl;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// ui/face-control — PLAYING WITH THE FACE, PUT TOGETHER (ADR-0210 and its erratum, ADR-0212 §3; issue #191).
|
|
3
|
+
//
|
|
4
|
+
// The camera and the face tracker (platform/vision), the frame loop (platform/vision-loop), the Dev's face map (input/face-map), the
|
|
5
|
+
// presses on the virtual controller with the source `rosto` (input/virtual-controller, ADR-0111), and what is drawn over the game. The
|
|
6
|
+
// 📷 at its face position drives it (ADR-0215): it reads the face and draws the eyes, brows and lips — never the camera's picture
|
|
7
|
+
// (ADR-0212); any other position lets the camera go.
|
|
8
|
+
// · The rest measures itself (the Dev, 2026-09-16): the face still, looking at the middle, for 3 s in a row; until then the middle asks for
|
|
9
|
+
// it and nothing commands.
|
|
10
|
+
// · A frame with no face lets go of every held action: a face that left the camera is not holding anything.
|
|
11
|
+
// · What cannot start is said, written once in `problems`, and puts the 📷 back to off — the same promise as the eyes.
|
|
12
|
+
import { faceScoresFromCategories, headTurn, createFaceMapReader, createFaceRest } from '../input/face-map.js';
|
|
13
|
+
import { loadFaceTracker } from '../platform/vision.js';
|
|
14
|
+
import { createVisionLoop } from '../platform/vision-loop.js';
|
|
15
|
+
import { gazeFontPx } from './gaze-overlay.js';
|
|
16
|
+
// 📌 THE SHAPE IS THE FAMILY'S (ADR-0221 step 7f): this module declares no `FaceControl` of its own — what it returns IS a
|
|
17
|
+
// `SwitchableControl`, and the compiler sees it.
|
|
18
|
+
const REST_MS = 3000;
|
|
19
|
+
/** The middle's request while the rest is measured, and the face lines, mirrored so they move the way the child moves. */
|
|
20
|
+
function draw(ctx, w, h, restLeftMs, lines, landmarks, say) {
|
|
21
|
+
ctx.clearRect(0, 0, w, h);
|
|
22
|
+
const f = gazeFontPx(w, h);
|
|
23
|
+
if (restLeftMs !== null) {
|
|
24
|
+
ctx.textAlign = 'center';
|
|
25
|
+
ctx.textBaseline = 'middle';
|
|
26
|
+
ctx.fillStyle = '#ffd23f';
|
|
27
|
+
ctx.shadowColor = '#000';
|
|
28
|
+
ctx.shadowBlur = 4;
|
|
29
|
+
ctx.font = `bold ${f}px system-ui`;
|
|
30
|
+
ctx.fillText(say('gaze.lookHere'), w / 2, h / 2 - f * 0.7);
|
|
31
|
+
ctx.font = `${f * 0.85}px system-ui`;
|
|
32
|
+
ctx.fillText(`${(restLeftMs / 1000).toFixed(1)} s`, w / 2, h / 2 + f * 0.8);
|
|
33
|
+
ctx.shadowBlur = 0;
|
|
34
|
+
}
|
|
35
|
+
if (lines && landmarks) {
|
|
36
|
+
ctx.strokeStyle = '#ffffff';
|
|
37
|
+
ctx.lineWidth = Math.max(2, f / 8);
|
|
38
|
+
ctx.shadowColor = '#000';
|
|
39
|
+
ctx.shadowBlur = 3;
|
|
40
|
+
for (const { start, end } of [...lines.eyes, ...lines.brows, ...lines.lips]) {
|
|
41
|
+
const a = landmarks[start], b = landmarks[end];
|
|
42
|
+
if (!a || !b)
|
|
43
|
+
continue;
|
|
44
|
+
ctx.beginPath();
|
|
45
|
+
ctx.moveTo((1 - a.x) * w, a.y * h);
|
|
46
|
+
ctx.lineTo((1 - b.x) * w, b.y * h);
|
|
47
|
+
ctx.stroke();
|
|
48
|
+
}
|
|
49
|
+
ctx.shadowBlur = 0;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function createFaceControl(d) {
|
|
53
|
+
const { t } = d;
|
|
54
|
+
const loadTracker = d.loadTracker ?? loadFaceTracker;
|
|
55
|
+
const said = new Set();
|
|
56
|
+
const once = (kind, line, spoken) => { if (!said.has(kind)) {
|
|
57
|
+
said.add(kind);
|
|
58
|
+
d.report(line);
|
|
59
|
+
} d.alert(spoken); };
|
|
60
|
+
let on = false, running = false, starting = null;
|
|
61
|
+
const current = () => on;
|
|
62
|
+
let tracker = null, feed = null, canvas = null;
|
|
63
|
+
let loop = null;
|
|
64
|
+
let rest = null, measure = createFaceRest({ restMs: REST_MS }), read = null;
|
|
65
|
+
const held = new Set();
|
|
66
|
+
const releaseAll = () => { for (const a of held)
|
|
67
|
+
d.controller.release(a, 'rosto'); held.clear(); };
|
|
68
|
+
const frame = (ms) => {
|
|
69
|
+
if (!tracker || !feed || !canvas || !feed.ready())
|
|
70
|
+
return;
|
|
71
|
+
const det = tracker.detect(feed.frame, ms);
|
|
72
|
+
const cats = det?.faceBlendshapes?.[0]?.categories;
|
|
73
|
+
const landmarks = det?.faceLandmarks?.[0];
|
|
74
|
+
const w = canvas.width = d.region.clientWidth, h = canvas.height = d.region.clientHeight;
|
|
75
|
+
const g = canvas.getContext('2d');
|
|
76
|
+
if (!cats) {
|
|
77
|
+
releaseAll();
|
|
78
|
+
draw(g, w, h, rest ? null : REST_MS, null, undefined, t);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const scores = faceScoresFromCategories(cats);
|
|
82
|
+
const restLeft = measureRest(ms, scores, landmarks);
|
|
83
|
+
if (read)
|
|
84
|
+
holdExactly(new Set(read(ms, scores, landmarks).held)); // nothing commands before the rest: no reader yet
|
|
85
|
+
draw(g, w, h, restLeft, tracker.faceLines, landmarks, t);
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Until the rest is measured, measure it on this frame — the head counts too — and answer how long the middle is still asked
|
|
89
|
+
* for. Once it is measured: the reader is made, «ready» is said ONCE, and the answer is `null` from then on.
|
|
90
|
+
*/
|
|
91
|
+
const measureRest = (ms, scores, landmarks) => {
|
|
92
|
+
if (rest)
|
|
93
|
+
return null;
|
|
94
|
+
const m = measure(ms, scores, headTurn(landmarks).x);
|
|
95
|
+
if (!m.rest)
|
|
96
|
+
return Math.max(0, REST_MS - m.stillMs);
|
|
97
|
+
rest = m.rest;
|
|
98
|
+
read = createFaceMapReader({ rest });
|
|
99
|
+
d.say(t('sr.face.ready'));
|
|
100
|
+
return null;
|
|
101
|
+
};
|
|
102
|
+
/** Hold exactly what the reading holds now: let go of what left it, press what joined it — once. */
|
|
103
|
+
const holdExactly = (now) => {
|
|
104
|
+
for (const a of held)
|
|
105
|
+
if (!now.has(a)) {
|
|
106
|
+
d.controller.release(a, 'rosto');
|
|
107
|
+
held.delete(a);
|
|
108
|
+
}
|
|
109
|
+
for (const a of now)
|
|
110
|
+
if (!held.has(a)) {
|
|
111
|
+
d.controller.press(a, 'rosto');
|
|
112
|
+
held.add(a);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const health = (hh, fps) => {
|
|
116
|
+
if (hh === 'stalled')
|
|
117
|
+
once('stalled', 'face control: a second without a camera frame — meanwhile the child\'s face commands nothing; keep the tab in front and the camera free', t('sr.face.stopped'));
|
|
118
|
+
if (hh === 'slow')
|
|
119
|
+
once('slow', `face control: ${fps} frames a second, under 8 — expressions are missed and the child may not be answered; close other heavy tabs or use a lighter device`, t('sr.face.slow'));
|
|
120
|
+
};
|
|
121
|
+
const stop = () => {
|
|
122
|
+
loop?.stop();
|
|
123
|
+
loop = null;
|
|
124
|
+
releaseAll();
|
|
125
|
+
feed?.close();
|
|
126
|
+
feed = null;
|
|
127
|
+
tracker?.close();
|
|
128
|
+
tracker = null;
|
|
129
|
+
canvas?.remove();
|
|
130
|
+
canvas = null;
|
|
131
|
+
running = false;
|
|
132
|
+
rest = null;
|
|
133
|
+
read = null;
|
|
134
|
+
};
|
|
135
|
+
const start = async () => {
|
|
136
|
+
const load = await loadTracker({ base: d.base, hasFile: d.hasFile });
|
|
137
|
+
if (!load.ok) {
|
|
138
|
+
once('files', `face control: ${load.missing.join(', ')} not on this device — the child cannot play with the face; open the game once online so the install fetches them`, t('sr.face.needsInternet'));
|
|
139
|
+
d.turnOff();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
feed = await d.openFeed();
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
load.tracker.close();
|
|
147
|
+
once('camera', 'face control: the camera did not open — the child cannot play with the face; allow the camera for this page, or plug one in', t('sr.face.noCamera'));
|
|
148
|
+
d.turnOff();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
tracker = load.tracker;
|
|
152
|
+
canvas = d.doc.createElement('canvas');
|
|
153
|
+
canvas.className = 'face-overlay';
|
|
154
|
+
canvas.setAttribute('aria-hidden', 'true');
|
|
155
|
+
Object.assign(canvas.style, { position: 'absolute', inset: '0', width: '100%', height: '100%', pointerEvents: 'none', zIndex: '5' });
|
|
156
|
+
d.region.appendChild(canvas);
|
|
157
|
+
rest = null;
|
|
158
|
+
read = null;
|
|
159
|
+
measure = createFaceRest({ restMs: REST_MS });
|
|
160
|
+
loop = createVisionLoop(d.loop, { onFrame: frame, onError: (e) => once('frame', `face control: a frame failed (${String(e)}) — the loop goes on, but a repeated failure means the child is not being read`, t('sr.face.stopped')), onHealth: health });
|
|
161
|
+
running = true;
|
|
162
|
+
d.say(t('sr.face.lookMiddle'));
|
|
163
|
+
loop.start();
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
async apply(next) {
|
|
167
|
+
on = next;
|
|
168
|
+
if (starting)
|
|
169
|
+
await starting;
|
|
170
|
+
if (!on) {
|
|
171
|
+
if (running)
|
|
172
|
+
stop();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (running)
|
|
176
|
+
return;
|
|
177
|
+
starting = start().finally(() => { starting = null; });
|
|
178
|
+
await starting;
|
|
179
|
+
if (!current() && running)
|
|
180
|
+
stop();
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -1,71 +1,61 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* What counts as focusable. Deliberately WITHOUT `[contenteditable]` and without positive `tabindex`: both exist, but
|
|
4
|
+
* appear in no dialog of this engine, and a selector that promises more than was verified is a selector that lies at
|
|
5
|
+
* the next review.
|
|
6
6
|
*/
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const FOCUSABLE_SELECTOR: string;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Where focus has to go when Tab is about to leave the dialog — or `null` when there is nothing to do and the browser
|
|
10
|
+
* should carry on by itself.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* The four cases, and the third is why this exists:
|
|
13
13
|
*
|
|
14
|
-
* 1.
|
|
15
|
-
*
|
|
16
|
-
* 2.
|
|
17
|
-
*
|
|
18
|
-
* 3. ⚠️
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 4.
|
|
14
|
+
* 1. EMPTY list → `null`. A dialog with nothing focusable is the dialog's defect, and trapping focus in it would
|
|
15
|
+
* leave the child with no way out at all. Better to let it leave than to lock it in a mute place.
|
|
16
|
+
* 2. focus on the LAST going forward → back to the first; on the FIRST going backwards → to the last. That is the
|
|
17
|
+
* cycle, which is what "trap" means.
|
|
18
|
+
* 3. ⚠️ focus OUTSIDE the list → bring it back. The case the other three do not cover: focus may have escaped by a
|
|
19
|
+
* click on the board, or because the dialog opened without focusing anything. Without it the trap only works for
|
|
20
|
+
* whoever was already inside.
|
|
21
|
+
* 4. focus in the MIDDLE → `null`, and the browser walks. See the header.
|
|
22
22
|
*/
|
|
23
|
-
export declare function
|
|
24
|
-
interface
|
|
25
|
-
addEventListener: (
|
|
26
|
-
removeEventListener?: (
|
|
23
|
+
export declare function nextInTrap<T>(focusables: readonly T[], current: T | null, backwards: boolean): T | null;
|
|
24
|
+
interface KeydownTarget {
|
|
25
|
+
addEventListener: (kind: 'keydown', fn: (e: KeyboardEvent) => void, capture?: boolean) => void;
|
|
26
|
+
removeEventListener?: (kind: 'keydown', fn: (e: KeyboardEvent) => void, capture?: boolean) => void;
|
|
27
27
|
}
|
|
28
28
|
export interface FocusTrapCtx {
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
win:
|
|
29
|
+
/** The highest VISIBLE dialog in the stack, or `null`. It is `ui/settings-panel`'s `topVisibleOverlay`. */
|
|
30
|
+
topOverlay: () => HTMLElement | null;
|
|
31
|
+
/** Who has focus now — `() => document.activeElement`. Injected: the node project has no document. */
|
|
32
|
+
currentFocus: () => Element | null;
|
|
33
|
+
/** The focusables INSIDE the dialog, in document order and already filtered by visibility. */
|
|
34
|
+
focusablesIn: (isInside: HTMLElement) => HTMLElement[];
|
|
35
|
+
win: KeydownTarget;
|
|
36
36
|
}
|
|
37
37
|
export interface FocusTrapApi {
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/**
|
|
38
|
+
/** The handler, exposed so the test can call it without installing anything. */
|
|
39
|
+
onKeydown: (e: KeyboardEvent) => void;
|
|
40
|
+
/** Installs in the CAPTURE phase, for the same reason as `menu-nav`: see the key before whoever is underneath. */
|
|
41
41
|
attach: () => void;
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* Uninstalls.
|
|
44
44
|
*
|
|
45
|
-
* ⚠️
|
|
46
|
-
*
|
|
47
|
-
* diálogo aberto o Tab é do jogo» ficou vermelho por causa de uma armadilha que já devia ter saído.
|
|
48
|
-
*
|
|
49
|
-
* O que isso mostra vale fora do teste: uma armadilha que não se desinstala é um vazamento para qualquer
|
|
50
|
-
* página que monte a engine duas vezes — o `demos`, que troca de jogo sem recarregar, é exatamente isso.
|
|
45
|
+
* ⚠️ A trap that does not uninstall is a leak for any page that mounts the engine twice — one that switches games
|
|
46
|
+
* without reloading is exactly that: the first trap keeps holding focus during the second.
|
|
51
47
|
*/
|
|
52
48
|
detach: () => void;
|
|
53
49
|
}
|
|
54
50
|
export declare function initFocusTrap(ctx: FocusTrapCtx): FocusTrapApi;
|
|
55
51
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* ⚠️ A VISIBILIDADE É POR `getClientRects()`, e não por `offsetParent`.
|
|
60
|
-
*
|
|
61
|
-
* ⚠️ E A PRIMEIRA VERSÃO DESTE COMENTÁRIO ESTAVA ERRADA, o que vale mais registrar do que apagar: ele dizia
|
|
62
|
-
* que `offsetParent` é `null` para «qualquer elemento em `position: fixed`». Não é — é `null` para o elemento
|
|
63
|
-
* FIXO EM SI, e os descendentes dele devolvem o próprio contêiner. O teste de navegador reprovou a afirmação,
|
|
64
|
-
* que é exatamente o que um teste tem de fazer com uma justificativa inventada.
|
|
52
|
+
* The focusables of a container, in the browser. It lives here and not in a root so that two roots do not write two
|
|
53
|
+
* versions that would drift silently — one trapping focus and the other letting it escape, in the same product.
|
|
65
54
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
55
|
+
* ⚠️ VISIBILITY IS BY `getClientRects()`, not by `offsetParent`: `getClientRects()` answers "does this draw any box?",
|
|
56
|
+
* which covers `display:none` on ANY ancestor, zero-size elements and the fixed-container case — without the reader
|
|
57
|
+
* needing to know where `offsetParent` has holes (it is `null` for a FIXED element itself, while its descendants return
|
|
58
|
+
* the container).
|
|
69
59
|
*/
|
|
70
|
-
export declare function
|
|
60
|
+
export declare function focusablesInDom(isInside: HTMLElement): HTMLElement[];
|
|
71
61
|
export {};
|