@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
|
@@ -1,137 +1,176 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// ui/settings-audio —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// live in this overlay, the state does not). Overlay open/close plumbing (#audio hidden toggle, frontOverlay,
|
|
12
|
-
// focus management, Escape, `ensureAC()`) is the shared infra every settings panel uses and stays in game.js,
|
|
13
|
-
// which calls `renderAudio()` from its `openAudio()`. `reflectModoCego`/`reflectTts` are also exported because
|
|
14
|
-
// game.js's own `setModoCego()` and the pause-menu icon bar (`iconAct('tts'|'blind', …)`) call them directly.
|
|
2
|
+
// ui/settings-audio — the hearing accessibility and audio panels (#audio overlay): the thin DOM-touching render/wire
|
|
3
|
+
// functions; what a choice IS lives in ./audio-choices.js and the voice section in ./voice-settings.js. DI via
|
|
4
|
+
// initSettingsAudio(ctx): `$`, `srSay`, `store` (narrow get/set), the browser through three required ports
|
|
5
|
+
// (`newElement`, `speech`, `audioOutputs`), the live sound/mixer primitives from platform/audio.ts
|
|
6
|
+
// (getSoundOn/setSoundOn/getVolume/setVolume/getAudioCat/setCatGain), the injected `tts` panel API (platform/tts.ts), and
|
|
7
|
+
// the host's shared helpers (`toggleBtn`, `getNumPlayers`/`getPlayers`) plus state that lives outside audio
|
|
8
|
+
// (`getBlindMode`/`setBlindMode`, `getCaneBlockDiv`/`setCaneBlockDiv` — the widgets live in this overlay, the state does
|
|
9
|
+
// not). Overlay open/close plumbing (frontOverlay, focus management, Escape) is the shared infrastructure every settings
|
|
10
|
+
// panel uses. `reflectBlindMode`/`reflectTts` are exported because the pause-menu icon bar calls them directly.
|
|
15
11
|
/** Minimal DOM-selector shape (matches ui/dom.ts's `$`). */
|
|
16
12
|
import { toggleLabel } from './dom.js';
|
|
17
|
-
import {
|
|
18
|
-
import { DEFAULTS } from '../core/state.js';
|
|
19
|
-
// O módulo INTEIRO, e não os nomes soltos: `menuIndexOn` é ligação viva e `setMenuIndexOnValue` a muda — ler
|
|
20
|
-
// pelo namespace deixa isso à vista em cada uso, em vez de parecer uma constante importada.
|
|
21
|
-
import * as state from '../core/state.js';
|
|
13
|
+
import { DEFAULTS } from '../core/setting-defaults.js';
|
|
22
14
|
import { markChanged, markMenuChanged } from './changed-mark.js';
|
|
23
15
|
import { defaultAudioCat } from '../platform/audio-mixer.js';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const c = cats.find((x) => x.k === k);
|
|
39
|
-
const a = state[k];
|
|
40
|
-
if (!c || !a)
|
|
41
|
-
return '';
|
|
42
|
-
return `<div class="ctrl-row"><span>${c.lbl}</span><span style="display:flex;gap:.5rem;align-items:center;flex-shrink:0">` +
|
|
43
|
-
`<input class="vol" type="range" min="0" max="100" step="5" value="${volPercent(a.vol)}" data-avol="${k}" aria-label="Volume de ${c.lbl}">` +
|
|
44
|
-
`<button class="mode-btn switch${a.on ? ' is-on' : ''}" data-acat="${k}" type="button" aria-pressed="${a.on}" aria-label="${c.lbl}"></button></span></div>`;
|
|
45
|
-
}
|
|
46
|
-
/** Full innerHTML for a category list (#audio-list or #navsound-list). Pure string building — no DOM. */
|
|
47
|
-
export function catsListHTML(keys, cats, state) {
|
|
48
|
-
return keys.map((k) => catRowHTML(k, cats, state)).join('');
|
|
49
|
-
}
|
|
50
|
-
/** #navsound-master's value: the loudest of the nav categories, as a 0..100 slider value. */
|
|
51
|
-
export function navMasterVolume(state, navCats = NAV_CATS) {
|
|
52
|
-
return volPercent(Math.max(...navCats.map((k) => state[k].vol)));
|
|
53
|
-
}
|
|
54
|
-
/** Cane-hit spacing select -> validated int (garbage/empty -> 1, "a batida por bloco"). */
|
|
55
|
-
export function parseCaneDiv(raw) {
|
|
56
|
-
return (+raw) || 1;
|
|
57
|
-
}
|
|
58
|
-
/** srSay text for a cane-hit spacing choice. The two halves are ONE sentence per case, not a shared prefix
|
|
59
|
-
* plus a tail: a language that renders this as "One tap per block (cane)" needs to move the word "cane". */
|
|
60
|
-
export function caneDivMessage(div) {
|
|
61
|
-
return t(div === 2 ? 'sr.audio.caneHalfBlock' : 'sr.audio.canePerBlock');
|
|
62
|
-
}
|
|
63
|
-
/** #tts-engine's option catalog: (value, i18n KEY of the label). The engine NAMES are proper nouns and stay
|
|
64
|
-
* put; what translates is the parenthetical that explains each one. Keys, not text — see input/devices. */
|
|
65
|
-
export const TTS_ENGINE_OPTIONS = [
|
|
66
|
-
['webspeech', 'tts.engine.webspeech'],
|
|
67
|
-
['piper', 'tts.engine.piper'],
|
|
68
|
-
['kokoro', 'tts.engine.kokoro'],
|
|
69
|
-
['kitten', 'tts.engine.kitten'],
|
|
70
|
-
['espeak', 'tts.engine.espeak'],
|
|
71
|
-
];
|
|
16
|
+
import { controlRow, labelRow } from './panel-widgets.js';
|
|
17
|
+
/*
|
|
18
|
+
* 🔴 THE VOICE SECTION LIVES IN `ui/voice-settings` (ADR-0221, issue #203): speech — the narration switch, the engine, the
|
|
19
|
+
* voice, the rate, the spoken index and the test button — and the sound categories, cane, blind mode and outputs never
|
|
20
|
+
* needed each other.
|
|
21
|
+
*/
|
|
22
|
+
import { createVoiceSettings } from './voice-settings.js';
|
|
23
|
+
/*
|
|
24
|
+
* 🔴 THE PURE HALF LIVES IN `ui/audio-choices` (ADR-0221, issue #203): what a choice IS — the category list, the volume
|
|
25
|
+
* arithmetic, the engine catalogue, the voice filter, an output's label — needs no document, and this file is about
|
|
26
|
+
* FINDING the controls and wiring them. The suite had already made the cut: the node test imported exactly those names
|
|
27
|
+
* and the browser test drove the rest.
|
|
28
|
+
*/
|
|
29
|
+
import { NAV_CATS, GEN_CATS, volPercent, navMasterVolume, parseCaneDiv, caneDivMessage, sinksSupported, sinkOptionLabel, sinkSelectValue, } from './audio-choices.js';
|
|
72
30
|
/**
|
|
73
|
-
*
|
|
31
|
+
* MOUNTS THIS PANEL'S INSIDE — the controls and containers it reaches.
|
|
32
|
+
*
|
|
33
|
+
* 🔴 IT IS THE LARGEST INVISIBLE CONTRACT OF THE PANELS: this file looks for `#opt-modocego`, `#cane-div`,
|
|
34
|
+
* `#opt-menuindex`, `#opt-tts`, `#tts-vol` and more, and nothing in the type says so — which is why it builds them.
|
|
74
35
|
*
|
|
75
|
-
* ⚠️
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* quem navega por escuta não tem como ver que não começou.
|
|
36
|
+
* ⚠️ AND EACH ONE'S TAG MATTERS, which makes this the worst place to guess: `#cane-div` and the voice selects have to be
|
|
37
|
+
* `<select>` — the panel writes `.value` into them —, and the volumes have to be `<input type=range>`. On a `<button>`,
|
|
38
|
+
* writing `.value` gives no error at all: it creates a property nobody reads, and the child's choice vanishes silently.
|
|
79
39
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
40
|
+
* 📌 THE ORDER IS THE DECISION (ADR-0044 §2), from general to particular (see the composition below).
|
|
41
|
+
*
|
|
42
|
+
* ⚠️ `#opt-sound` IS NOT CREATED HERE, deliberately: it is this setting's mirror on the quick bar, outside the panel.
|
|
43
|
+
* `reflectMaster` reaches it with a guard (`if (sb)`), because a game may have no bar.
|
|
44
|
+
*
|
|
45
|
+
* Idempotent: calling it twice reuses what exists instead of duplicating it.
|
|
82
46
|
*/
|
|
83
|
-
export function
|
|
84
|
-
|
|
47
|
+
export function mountAudioInside(t, ctx, card, list) {
|
|
48
|
+
// Each entry is either a control row or a CONTAINER the panel fills with rows of its own.
|
|
49
|
+
const pieces = [
|
|
50
|
+
/*
|
|
51
|
+
* 🔴 THE COMPOSITION OF ADR-0151 AND ITS ERRATA, from general to particular:
|
|
52
|
+
* · BLIND MODE first, because it is the mode where the other sounds become the screen — and WITHOUT the hint: «é
|
|
53
|
+
* redundante. Quem precisa sabe o que é»;
|
|
54
|
+
* · the CANE beside it (and only in a game that answers that someone walks, ADR-0153);
|
|
55
|
+
* · the SONAR, GUARD and GUIDE, each with its switch and volume: they are the shell's list;
|
|
56
|
+
* · NARRATION and its volume, with the SPOKEN INDEX right after, because narration is what it shortens.
|
|
57
|
+
* 🔴 The GENERAL sound and volume live in the audio panel (`mountSoundInside`) — «toggle + barra para som geral
|
|
58
|
+
* voltam», the Dev said, and they came back to the sound panel, not the accessibility one. There is no separate
|
|
59
|
+
* navigation volume: it would be a second place for the list's three volumes (one place per choice, D2 of the record).
|
|
60
|
+
*/
|
|
61
|
+
// ⚠️ Their own short keys, not the bar's `icon.blind`/`icon.tts`: those carry «(navegação sonora)» and «(TTS)», and
|
|
62
|
+
// a row keeps no explanation in parentheses (ADR-0158).
|
|
63
|
+
{ id: 'opt-modocego', label: t('audio.modocego') },
|
|
64
|
+
{ id: 'cane-div', label: t('audio.cane'), hint: t('audio.cane.dica'), shape: 'escolha' },
|
|
65
|
+
{ container: '@lista' }, // the shell's list: sonar, guard and guide
|
|
66
|
+
{ id: 'opt-tts', label: t('audio.narracao'), hint: t('audio.tts.dica') },
|
|
67
|
+
{ id: 'tts-vol', label: t('audio.ttsVol'), shape: 'cursor' },
|
|
68
|
+
// ADR-0183 §1, ADR-0196: the speech rate, 254 to 504 by 50 — six positions, so a list (ADR-0130 erratum)
|
|
69
|
+
{ id: 'tts-ppm', label: t('audio.ttsPpm'), hint: t('audio.ttsPpm.dica'), shape: 'escolha' },
|
|
70
|
+
// ADR-0185: the child picks the voice, among the voices that speak the language — a list, since English passes five
|
|
71
|
+
{ id: 'tts-voz', label: t('audio.voz'), shape: 'escolha' },
|
|
72
|
+
{ id: 'opt-menuindex', label: t('audio.menuindex'), hint: t('audio.menuindex.dica') },
|
|
73
|
+
/*
|
|
74
|
+
* 🔴 NOT OFFERED by the engine (ADR-0151), in the Dev's words:
|
|
75
|
+
* · the ENGINE, the VOICE and the voice TEST — «quem escolhe a voz é o jogo (cartucho), não o jogador. Jogador só
|
|
76
|
+
* habilita/desabilita o TTS»;
|
|
77
|
+
* · the PER-PLAYER AUDIO OUTPUTS and their detect button — «navegadores não são bons nisso».
|
|
78
|
+
* 📌 `initSettingsAudio`'s wiring for those ids STAYS and is guarded (`if (el)`): a game with markup of its own does
|
|
79
|
+
* not break. What changed is that the engine no longer OFFERS the choice to the child.
|
|
80
|
+
*/
|
|
81
|
+
];
|
|
82
|
+
/*
|
|
83
|
+
* ⚠️ IT RELABELS INSTEAD OF SKIPPING what already exists, which is why this function is also called from every open's
|
|
84
|
+
* `render()`: anything built once at boot captures the fallback language's text — `initI18n` applies the fallback
|
|
85
|
+
* synchronously and REQUESTS the preferred one, which arrives later — and a panel would serve its TITLE in one
|
|
86
|
+
* language and its ROWS in another. No unit test catches it: they all run in one language.
|
|
87
|
+
*/
|
|
88
|
+
// ADR-0158: the rows go BEFORE the reset, never after it — the reset is the panel's last item, and «Voltar» its first.
|
|
89
|
+
const actions = card.querySelector(':scope > .overlay__actions');
|
|
90
|
+
for (const piece of pieces) {
|
|
91
|
+
if ('container' in piece) {
|
|
92
|
+
if (piece.container === '@lista') {
|
|
93
|
+
card.insertBefore(list, actions);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const jaHa = ctx.find('#' + piece.container);
|
|
97
|
+
if (jaHa) {
|
|
98
|
+
if (piece.label)
|
|
99
|
+
jaHa.setAttribute('aria-label', piece.label);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const c = ctx.create('div');
|
|
103
|
+
c.id = piece.container;
|
|
104
|
+
c.className = 'ctrl-list';
|
|
105
|
+
c.setAttribute('role', 'group');
|
|
106
|
+
if (piece.label)
|
|
107
|
+
c.setAttribute('aria-label', piece.label);
|
|
108
|
+
card.insertBefore(c, actions);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const alreadyThere = ctx.find('#' + piece.id);
|
|
112
|
+
if (alreadyThere) {
|
|
113
|
+
const rowNode = alreadyThere.closest('.ctrl-row');
|
|
114
|
+
if (rowNode)
|
|
115
|
+
labelRow(rowNode, piece);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
card.insertBefore(controlRow(ctx, piece).row, actions);
|
|
119
|
+
}
|
|
85
120
|
}
|
|
86
121
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* Chamava-se `pickPtVoices` e filtrava `/^pt/i` fixo, de modo que o jogo em inglês oferecia à pessoa uma
|
|
90
|
-
* lista de vozes PORTUGUESAS para ler texto em inglês. O nome dizia a verdade sobre o que fazia e mentia
|
|
91
|
-
* sobre o que devia fazer.
|
|
122
|
+
* MOUNTS THE AUDIO PANEL'S INSIDE (ADR-0151 §2 item 4): the general sound — switch and volume — and then the shell's
|
|
123
|
+
* list with the four taste categories (music, ambience, interaction, earcons).
|
|
92
124
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* exata. O recuo para a lista inteira fica: uma lista vazia seria pior que uma lista no idioma errado, que
|
|
96
|
-
* ao menos a pessoa pode ouvir e rejeitar.
|
|
125
|
+
* ⚠️ THE IDS ARE THE ONES `initSettingsAudio` ALREADY LISTENS TO (`#audio-master`, `#audio-master-vol`, `#audio-list`). And
|
|
126
|
+
* the same order rule: mount BEFORE `init`. Idempotent and relabellable, like its hearing sibling.
|
|
97
127
|
*/
|
|
98
|
-
export function
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
/** A player's current sink select value ('' = default/shared). */
|
|
117
|
-
export function sinkSelectValue(p) {
|
|
118
|
-
return (p && p.audioSink) || '';
|
|
128
|
+
export function mountSoundInside(t, ctx, card, list) {
|
|
129
|
+
const actions = card.querySelector(':scope > .overlay__actions');
|
|
130
|
+
const rows = [
|
|
131
|
+
{ id: 'audio-master', label: t('audio.som'), hint: t('audio.som.dica') },
|
|
132
|
+
{ id: 'audio-master-vol', label: t('audio.volume'), shape: 'cursor' },
|
|
133
|
+
];
|
|
134
|
+
for (const piece of rows) {
|
|
135
|
+
const alreadyThere = ctx.find('#' + piece.id);
|
|
136
|
+
if (alreadyThere) {
|
|
137
|
+
const rowNode = alreadyThere.closest('.ctrl-row');
|
|
138
|
+
if (rowNode)
|
|
139
|
+
labelRow(rowNode, piece);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
card.insertBefore(controlRow(ctx, piece).row, list.parentNode === card ? list : actions);
|
|
143
|
+
}
|
|
144
|
+
if (list.parentNode !== card)
|
|
145
|
+
card.insertBefore(list, actions);
|
|
119
146
|
}
|
|
120
147
|
// ---------------------------------------------------------------------------------------------
|
|
121
148
|
// DOM-facing (thin) — requires `document`/injected ctx
|
|
122
149
|
// ---------------------------------------------------------------------------------------------
|
|
123
150
|
export function initSettingsAudio(ctx) {
|
|
124
|
-
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
151
|
+
const { t } = ctx.translator;
|
|
152
|
+
// ⚠️ THE ENGINE'S DEFAULT (ADR-0106 §4): whoever injects rules; whoever does not still gets blind mode.
|
|
153
|
+
// `setBlindModeValue` does the three things `core/state` says a setter does — store, persist, notify — and nothing
|
|
154
|
+
// more: the effects are reactions, and whoever reacts subscribes to the event.
|
|
155
|
+
const writeBlindMode = ctx.setBlindMode ?? ((on) => { ctx.settings.setBlindModeValue(on); });
|
|
128
156
|
let audioDevices = [];
|
|
157
|
+
/*
|
|
158
|
+
* ⚠️ THE BROWSER TRAVELS AS FOUR FUNCTIONS, not as a global reached inside: a module that reaches `document` or
|
|
159
|
+
* `window` is refused by the ratchet (the reach ceiling is ZERO). What this file received through its own ports it
|
|
160
|
+
* passes down as ports.
|
|
161
|
+
*/
|
|
162
|
+
const voice = createVoiceSettings(ctx, {
|
|
163
|
+
newOption: () => ctx.newElement('option'),
|
|
164
|
+
systemVoices: () => [...ctx.speech.voices()],
|
|
165
|
+
speakSample: (sample, chosen) => ctx.speech.speakSample(sample, chosen),
|
|
166
|
+
whenVoicesChange: (again) => ctx.speech.whenVoicesChange(again),
|
|
167
|
+
});
|
|
129
168
|
function reflectMaster() {
|
|
130
169
|
const b = ctx.$('#audio-master');
|
|
131
170
|
if (b) {
|
|
132
171
|
b.classList.toggle('is-on', ctx.getSoundOn());
|
|
133
172
|
b.setAttribute('aria-pressed', String(ctx.getSoundOn()));
|
|
134
|
-
b.textContent = ctx.getSoundOn()
|
|
173
|
+
b.textContent = toggleLabel(t, ctx.getSoundOn()); // the dictionary's words, no glyph in the name (ADR-0159 rule 12)
|
|
135
174
|
}
|
|
136
175
|
const v = ctx.$('#audio-master-vol');
|
|
137
176
|
if (v)
|
|
@@ -140,40 +179,144 @@ export function initSettingsAudio(ctx) {
|
|
|
140
179
|
if (sb)
|
|
141
180
|
ctx.toggleBtn(sb, ctx.getSoundOn());
|
|
142
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* The kit's ctx comes from the LIST NODE itself, not from a global `document` nor from a new contract field —
|
|
184
|
+
* `ownerDocument` is the document that list lives in, which is where its rows have to be born. Same shape as
|
|
185
|
+
* `ui/settings-aac`, and it is what removes this file's reach to `document` without touching `SettingsAudioCtx`.
|
|
186
|
+
*/
|
|
187
|
+
const kitCtx = (list) => ({
|
|
188
|
+
find: (sel) => ctx.$(sel),
|
|
189
|
+
create: (tag) => list.ownerDocument.createElement(tag),
|
|
190
|
+
});
|
|
191
|
+
/**
|
|
192
|
+
* The same document, but KEEPING the element type.
|
|
193
|
+
*
|
|
194
|
+
* 📌 `PanelShellCtx.create` is `string → HTMLElement` on purpose: the shell only ever appends generic nodes, and
|
|
195
|
+
* widening it would be a one-way door on a published shape (ADR-0172). The sinks section needs a `<select>` that
|
|
196
|
+
* answers `.value`, so the typed factory lives HERE, over the same `ownerDocument`, instead of the contract
|
|
197
|
+
* growing a field for one caller.
|
|
198
|
+
*/
|
|
199
|
+
const makerFor = (host) => (tag) => host.ownerDocument.createElement(tag);
|
|
200
|
+
/**
|
|
201
|
+
* ONE CATEGORY ROW, in nodes: label, volume slider and toggle.
|
|
202
|
+
*
|
|
203
|
+
* 📌 NOT A KIT ROW, and not by taste: 📏 measured on 2026-09-23, `controlRow` builds «a label, a hint and ONE
|
|
204
|
+
* control» and this row carries TWO — the volume and the on/off of the same category. Same reason the visual
|
|
205
|
+
* panel's four paper-colour row stayed hand-built: inventing a shape for it would be giving a second answer to
|
|
206
|
+
* the question «what is a row».
|
|
207
|
+
*/
|
|
208
|
+
function buildCatRow(kit, k) {
|
|
209
|
+
const row = kit.create('div');
|
|
210
|
+
row.className = 'ctrl-row';
|
|
211
|
+
const text = kit.create('span');
|
|
212
|
+
text.appendChild(kit.create('strong'));
|
|
213
|
+
row.appendChild(text);
|
|
214
|
+
const box = kit.create('span');
|
|
215
|
+
box.style.cssText = 'display:flex;gap:.5rem;align-items:center;flex-shrink:0';
|
|
216
|
+
const vol = kit.create('input');
|
|
217
|
+
vol.className = 'vol';
|
|
218
|
+
vol.setAttribute('type', 'range');
|
|
219
|
+
vol.setAttribute('min', '0');
|
|
220
|
+
vol.setAttribute('max', '100');
|
|
221
|
+
vol.setAttribute('step', '5');
|
|
222
|
+
vol.setAttribute('data-avol', k);
|
|
223
|
+
box.appendChild(vol);
|
|
224
|
+
const toggle = kit.create('button');
|
|
225
|
+
toggle.className = 'mode-btn switch';
|
|
226
|
+
toggle.setAttribute('type', 'button');
|
|
227
|
+
toggle.setAttribute('aria-pressed', 'false');
|
|
228
|
+
toggle.setAttribute('data-acat', k);
|
|
229
|
+
box.appendChild(toggle);
|
|
230
|
+
row.appendChild(box);
|
|
231
|
+
return row;
|
|
232
|
+
}
|
|
233
|
+
/** Creates what is missing IN THE RIGHT POSITION, rewrites the words of what stayed, removes what is no longer asked for. */
|
|
234
|
+
function mountCatRows(list, keys) {
|
|
235
|
+
const kit = kitCtx(list);
|
|
236
|
+
let previous = null;
|
|
237
|
+
// ⚠️ WHAT SURVIVES IS WHAT THE HOST STILL NAMES, not simply what is in `keys`. A row whose category lost its
|
|
238
|
+
// name would otherwise stay on screen with the old label — asked for by the key list, offered by nobody.
|
|
239
|
+
const named = new Set();
|
|
240
|
+
for (const k of keys) {
|
|
241
|
+
const c = ctx.audioCats.find((x) => x.k === k);
|
|
242
|
+
if (!c)
|
|
243
|
+
continue; // a category this host does not name: what has no name is not offered
|
|
244
|
+
named.add(k);
|
|
245
|
+
let row = list.querySelector(`[data-acat="${k}"]`)?.closest('.ctrl-row') ?? null;
|
|
246
|
+
if (!row) {
|
|
247
|
+
row = buildCatRow(kit, k);
|
|
248
|
+
// ⚠️ INSERTED in place, never appended and reordered: a node that changes parent is removed and put back,
|
|
249
|
+
// and the browser blurs it on removal — that would take the cursor from whoever is setting the volume.
|
|
250
|
+
list.insertBefore(row, previous ? previous.nextSibling : list.firstChild);
|
|
251
|
+
}
|
|
252
|
+
const label = t(c.lbl);
|
|
253
|
+
const strong = row.querySelector('strong');
|
|
254
|
+
if (strong)
|
|
255
|
+
strong.textContent = label;
|
|
256
|
+
row.querySelector(`[data-avol="${k}"]`)?.setAttribute('aria-label', t('audio.cat.volumeDe', { c: label }));
|
|
257
|
+
row.querySelector(`[data-acat="${k}"]`)?.setAttribute('aria-label', label);
|
|
258
|
+
previous = row;
|
|
259
|
+
}
|
|
260
|
+
for (const b of [...list.querySelectorAll('[data-acat]')]) {
|
|
261
|
+
if (!named.has(b.dataset.acat ?? ''))
|
|
262
|
+
b.closest('.ctrl-row')?.remove();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** The STATE of each row — the volume where it is and the toggle saying what it says. */
|
|
266
|
+
function reflectCatRows(list, keys) {
|
|
267
|
+
const state = ctx.getAudioCat();
|
|
268
|
+
if (!state)
|
|
269
|
+
return;
|
|
270
|
+
for (const k of keys) {
|
|
271
|
+
const a = state[k];
|
|
272
|
+
if (!a)
|
|
273
|
+
continue;
|
|
274
|
+
const vol = list.querySelector(`input[data-avol="${k}"]`);
|
|
275
|
+
if (vol)
|
|
276
|
+
vol.value = String(volPercent(a.vol));
|
|
277
|
+
const toggle = list.querySelector(`button[data-acat="${k}"]`);
|
|
278
|
+
if (toggle) {
|
|
279
|
+
toggle.classList.toggle('is-on', a.on);
|
|
280
|
+
toggle.setAttribute('aria-pressed', String(a.on));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/** The listeners, ONCE per list and by delegation — rows come and go, the list stays. */
|
|
143
285
|
function wireCatControls(el) {
|
|
144
|
-
el.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
286
|
+
if (el.dataset.catsWired)
|
|
287
|
+
return;
|
|
288
|
+
el.dataset.catsWired = '1';
|
|
289
|
+
el.addEventListener('click', (ev) => {
|
|
290
|
+
const b = ev.target?.closest('button[data-acat]');
|
|
291
|
+
const k = b?.dataset.acat;
|
|
292
|
+
if (!b || !k)
|
|
293
|
+
return;
|
|
294
|
+
const state = ctx.getAudioCat();
|
|
295
|
+
if (!state || !state[k])
|
|
296
|
+
return;
|
|
297
|
+
state[k].on = !state[k].on;
|
|
298
|
+
ctx.setCatGain(k);
|
|
299
|
+
b.classList.toggle('is-on', state[k].on);
|
|
300
|
+
b.setAttribute('aria-pressed', String(state[k].on));
|
|
301
|
+
refreshMarks(); // the mark follows the CHANGE, not only the redraw — see the note in refreshMarks
|
|
158
302
|
});
|
|
159
|
-
el.
|
|
160
|
-
s.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
});
|
|
303
|
+
el.addEventListener('input', (ev) => {
|
|
304
|
+
const s = ev.target?.closest('input[data-avol]');
|
|
305
|
+
const k = s?.dataset.avol;
|
|
306
|
+
if (!s || !k)
|
|
307
|
+
return;
|
|
308
|
+
const state = ctx.getAudioCat();
|
|
309
|
+
if (!state || !state[k])
|
|
310
|
+
return;
|
|
311
|
+
state[k].vol = (+s.value) / 100;
|
|
312
|
+
state[k].on = true;
|
|
313
|
+
ctx.setCatGain(k);
|
|
314
|
+
const bb = el.querySelector('button[data-acat="' + k + '"]');
|
|
315
|
+
if (bb) {
|
|
316
|
+
bb.classList.add('is-on');
|
|
317
|
+
bb.setAttribute('aria-pressed', 'true');
|
|
318
|
+
}
|
|
319
|
+
refreshMarks();
|
|
177
320
|
});
|
|
178
321
|
}
|
|
179
322
|
function renderCategoryList(sel, keys) {
|
|
@@ -181,10 +324,12 @@ export function initSettingsAudio(ctx) {
|
|
|
181
324
|
const state = ctx.getAudioCat();
|
|
182
325
|
if (!el || !state)
|
|
183
326
|
return;
|
|
184
|
-
el
|
|
327
|
+
mountCatRows(el, keys);
|
|
328
|
+
reflectCatRows(el, keys);
|
|
185
329
|
wireCatControls(el);
|
|
186
|
-
//
|
|
187
|
-
|
|
330
|
+
// The prose goes back to the footer after the rows change (CLAUDE.md §4, #109) — in the card of WHOEVER holds
|
|
331
|
+
// this list: since ADR-0151 there are two panels, and the other one's footer is not this child's.
|
|
332
|
+
ctx.fillExplain?.(el.closest('.overlay__card'));
|
|
188
333
|
}
|
|
189
334
|
function renderNavSound() {
|
|
190
335
|
renderCategoryList('#navsound-list', NAV_CATS);
|
|
@@ -193,113 +338,50 @@ export function initSettingsAudio(ctx) {
|
|
|
193
338
|
if (m && state)
|
|
194
339
|
m.value = String(navMasterVolume(state, NAV_CATS));
|
|
195
340
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (b) {
|
|
201
|
-
ctx.toggleBtn(b, on);
|
|
202
|
-
b.textContent = toggleLabel(on);
|
|
203
|
-
}
|
|
204
|
-
const e = ctx.$('#tts-engine');
|
|
205
|
-
if (e)
|
|
206
|
-
e.value = ctx.tts.getEngineSel();
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* O alternador do ÍNDICE "6 de 10" (ADR-0044, item 3).
|
|
210
|
-
*
|
|
211
|
-
* Ele mora ao lado da narração por voz e não num painel de visual, porque é a NARRAÇÃO que ele muda: quem
|
|
212
|
-
* desliga o índice está encurtando o que ouve a cada passo, e é aqui que essa pessoa vem quando o que ouve
|
|
213
|
-
* incomoda.
|
|
214
|
-
*/
|
|
215
|
-
function reflectMenuIndex() {
|
|
216
|
-
const b = ctx.$('#opt-menuindex');
|
|
217
|
-
if (b) {
|
|
218
|
-
ctx.toggleBtn(b, state.menuIndexOn);
|
|
219
|
-
b.textContent = toggleLabel(state.menuIndexOn);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function populateTtsEngines() {
|
|
223
|
-
const sel = ctx.$('#tts-engine');
|
|
224
|
-
if (!sel || sel.dataset.filled)
|
|
225
|
-
return;
|
|
226
|
-
sel.dataset.filled = '1';
|
|
227
|
-
opcoesDeMotor(ctx.tts.neuralDisponivel !== false).forEach(([v, l]) => {
|
|
228
|
-
const o = document.createElement('option');
|
|
229
|
-
o.value = v;
|
|
230
|
-
o.textContent = t(l);
|
|
231
|
-
sel.appendChild(o);
|
|
232
|
-
});
|
|
233
|
-
sel.value = ctx.tts.getEngineSel();
|
|
234
|
-
}
|
|
235
|
-
function populateTtsVoices() {
|
|
236
|
-
const sel = ctx.$('#tts-voice');
|
|
237
|
-
if (!sel)
|
|
238
|
-
return;
|
|
239
|
-
let voices = [];
|
|
240
|
-
try {
|
|
241
|
-
voices = (window.speechSynthesis && window.speechSynthesis.getVoices()) || [];
|
|
242
|
-
}
|
|
243
|
-
catch (e) { /* noop */ }
|
|
244
|
-
const list = pickVoicesFor(voices, bcp47());
|
|
245
|
-
sel.innerHTML = '';
|
|
246
|
-
if (!list.length) {
|
|
247
|
-
const o = document.createElement('option');
|
|
248
|
-
o.textContent = t('audio.noSystemVoices');
|
|
249
|
-
sel.appendChild(o);
|
|
250
|
-
ctx.tts.setVoiceObj(null);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
list.forEach((v) => {
|
|
254
|
-
const o = document.createElement('option');
|
|
255
|
-
o.value = v.name;
|
|
256
|
-
o.textContent = voiceLabel(v);
|
|
257
|
-
sel.appendChild(o);
|
|
258
|
-
});
|
|
259
|
-
const saved = ctx.store.get('incl_tts_voice', null);
|
|
260
|
-
const pick = list.find((v) => v.name === saved) || list[0];
|
|
261
|
-
sel.value = pick.name;
|
|
262
|
-
ctx.tts.setVoiceObj(pick);
|
|
263
|
-
}
|
|
264
|
-
function hasEnumerateDevices() {
|
|
265
|
-
return !!(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices);
|
|
266
|
-
}
|
|
267
|
-
function hasAudioContextCtor() {
|
|
268
|
-
const w = window;
|
|
269
|
-
return typeof (w.AudioContext || w.webkitAudioContext) !== 'undefined';
|
|
270
|
-
}
|
|
341
|
+
// 📌 Both questions are the HOST's (ADR-0227), and they stay TWO because they produce different sentences: the browser
|
|
342
|
+
// cannot do it, and there is no device at all, are not the same news to someone looking for their headphones.
|
|
343
|
+
const hasEnumerateDevices = () => ctx.audioOutputs.canList();
|
|
344
|
+
const hasAudioContextCtor = () => ctx.audioOutputs.canRoute();
|
|
271
345
|
function renderSinks(devices) {
|
|
272
346
|
const el = ctx.$('#audio-sinks');
|
|
273
347
|
if (!el)
|
|
274
348
|
return;
|
|
275
|
-
|
|
349
|
+
// 📌 The document comes from the list node, never from the global one — same shape as the rest of this file
|
|
350
|
+
// since the conversion to nodes, and it is what removes the reach to `document` without asking the contract
|
|
351
|
+
// for a new field (ADR-0221 step 7d).
|
|
352
|
+
const make = makerFor(el);
|
|
353
|
+
while (el.firstChild)
|
|
354
|
+
el.removeChild(el.firstChild);
|
|
276
355
|
if (!devices.length) {
|
|
277
356
|
const supported = sinksSupported(hasEnumerateDevices(), hasAudioContextCtor());
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
357
|
+
// ⚠️ TWO SENTENCES, not one: «this browser CANNOT do it» and «there is no device yet» are different things to
|
|
358
|
+
// a child who is looking for their own headphones, and the dictionary has always had both.
|
|
359
|
+
const hint = make('p');
|
|
360
|
+
hint.className = 'opt-hint';
|
|
361
|
+
hint.textContent = t(supported ? 'audio.sinksHint' : 'audio.sinksUnsupported');
|
|
362
|
+
el.appendChild(hint);
|
|
281
363
|
return;
|
|
282
364
|
}
|
|
283
365
|
const players = ctx.getPlayers();
|
|
284
366
|
const n = Math.max(1, ctx.getNumPlayers());
|
|
285
367
|
for (let i = 0; i < n; i++) {
|
|
286
368
|
const p = players[i];
|
|
287
|
-
const row =
|
|
369
|
+
const row = make('div');
|
|
288
370
|
row.className = 'ctrl-row';
|
|
289
|
-
const lbl =
|
|
371
|
+
const lbl = make('label');
|
|
290
372
|
lbl.textContent = t('audio.playerN', { n: i + 1 });
|
|
291
|
-
lbl.
|
|
292
|
-
const sel =
|
|
373
|
+
lbl.htmlFor = 'sink-p' + i;
|
|
374
|
+
const sel = make('select');
|
|
293
375
|
sel.className = 'vol';
|
|
294
376
|
sel.id = 'sink-p' + i;
|
|
295
|
-
const o0 =
|
|
377
|
+
const o0 = make('option');
|
|
296
378
|
o0.value = '';
|
|
297
379
|
o0.textContent = t('audio.sinkShared');
|
|
298
380
|
sel.appendChild(o0);
|
|
299
381
|
devices.forEach((d, k) => {
|
|
300
|
-
const o =
|
|
382
|
+
const o = make('option');
|
|
301
383
|
o.value = d.deviceId;
|
|
302
|
-
o.textContent = sinkOptionLabel(d, k);
|
|
384
|
+
o.textContent = sinkOptionLabel(t, d, k);
|
|
303
385
|
sel.appendChild(o);
|
|
304
386
|
});
|
|
305
387
|
sel.value = sinkSelectValue(p);
|
|
@@ -324,78 +406,83 @@ export function initSettingsAudio(ctx) {
|
|
|
324
406
|
}
|
|
325
407
|
}
|
|
326
408
|
async function enumerateSinks() {
|
|
409
|
+
// without asking permission: only the outputs already known
|
|
327
410
|
try {
|
|
328
|
-
|
|
329
|
-
const devs = await navigator.mediaDevices.enumerateDevices();
|
|
330
|
-
audioDevices = devs.filter((d) => d.kind === 'audiooutput');
|
|
331
|
-
}
|
|
411
|
+
audioDevices = [...await ctx.audioOutputs.list()];
|
|
332
412
|
}
|
|
333
|
-
catch (e) { /*
|
|
413
|
+
catch (e) { /* the port refused; the list stays as it is */ }
|
|
334
414
|
renderSinks(audioDevices);
|
|
335
415
|
}
|
|
336
416
|
async function detectAudioDevices() {
|
|
417
|
+
// ⚠️ THE LIST EMPTIES when detection fails, and `enumerateSinks` above does NOT empty it: there an error means "I
|
|
418
|
+
// could not ask", here it means "the child asked and the answer is none". The two sentences the panel draws next are
|
|
419
|
+
// different, and so are the two `catch`es.
|
|
337
420
|
try {
|
|
338
|
-
|
|
339
|
-
const devs = await navigator.mediaDevices.enumerateDevices();
|
|
340
|
-
audioDevices = devs.filter((d) => d.kind === 'audiooutput');
|
|
421
|
+
audioDevices = [...await ctx.audioOutputs.detect()];
|
|
341
422
|
}
|
|
342
423
|
catch (e) {
|
|
343
424
|
audioDevices = [];
|
|
344
425
|
}
|
|
345
426
|
renderSinks(audioDevices);
|
|
346
427
|
}
|
|
347
|
-
function
|
|
428
|
+
function drawBlindMode() {
|
|
348
429
|
const b = ctx.$('#opt-modocego');
|
|
349
430
|
if (b) {
|
|
350
|
-
ctx.toggleBtn(b, ctx.
|
|
351
|
-
b.textContent = toggleLabel(ctx.
|
|
431
|
+
ctx.toggleBtn(b, ctx.getBlindMode());
|
|
432
|
+
b.textContent = toggleLabel(t, ctx.getBlindMode());
|
|
352
433
|
}
|
|
353
434
|
}
|
|
354
435
|
function renderAudio() {
|
|
355
436
|
reflectMaster();
|
|
356
437
|
renderCategoryList('#audio-list', GEN_CATS);
|
|
357
438
|
renderNavSound();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
populateTtsEngines();
|
|
361
|
-
populateTtsVoices();
|
|
439
|
+
drawBlindMode();
|
|
440
|
+
voice.render();
|
|
362
441
|
const cd = ctx.$('#cane-div');
|
|
363
442
|
if (cd)
|
|
364
443
|
cd.value = String(ctx.getCaneBlockDiv());
|
|
365
|
-
void enumerateSinks(); //
|
|
444
|
+
void enumerateSinks(); // not awaited: fire and carry on (the asynchronous list updates by itself)
|
|
366
445
|
refreshMarks();
|
|
367
446
|
}
|
|
368
447
|
/**
|
|
369
|
-
*
|
|
448
|
+
* The left-the-default mark (ADR-0029).
|
|
370
449
|
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* mudança" — e eu escrevi o aviso e caí nele na mesma tarde. A regra que sobra: a marca anda com quem
|
|
375
|
-
* ESCREVE o valor, nunca com quem desenha.
|
|
450
|
+
* Called from inside the change HANDLERS, not only from `renderAudio()`: changing a category updates that row by
|
|
451
|
+
* itself, without redrawing the panel, so a mark hung only on render goes stale on screen — ADR-0029 warns about it.
|
|
452
|
+
* The rule: the mark travels with whoever WRITES the value, never with whoever draws.
|
|
376
453
|
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
454
|
+
* The cut is the SAME as this menu's reset, and that is the rule, not thrift: only what has a default in
|
|
455
|
+
* DEFAULTS/`defaultAudioCat` can be marked. The voice engine and the per-player audio output have none, because they
|
|
456
|
+
* are a DEVICE choice and not a restorable preference; marking them would mean inventing a second opinion on what a
|
|
457
|
+
* headset's "default" is.
|
|
381
458
|
*/
|
|
382
459
|
function refreshMarks() {
|
|
383
460
|
const state = ctx.getAudioCat();
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
markChanged(ctx.$(sel)?.closest('.ctrl-row') ?? null, changed);
|
|
461
|
+
const didChange = [];
|
|
462
|
+
const mark = (sel, changed) => {
|
|
463
|
+
didChange.push(changed);
|
|
464
|
+
markChanged(t, ctx.$(sel)?.closest('.ctrl-row') ?? null, changed);
|
|
388
465
|
};
|
|
389
|
-
|
|
390
|
-
|
|
466
|
+
mark('#opt-modocego', ctx.getBlindMode() !== DEFAULTS.blindMode);
|
|
467
|
+
mark('#cane-div', ctx.getCaneBlockDiv() !== DEFAULTS.caneBlockDiv);
|
|
468
|
+
// ⚠️ TWO MENU MARKS, one per panel: the audio panel's lit by a changed sonar would send the child searching the
|
|
469
|
+
// wrong panel.
|
|
470
|
+
const fromSound = [];
|
|
391
471
|
for (const c of ctx.audioCats) {
|
|
392
472
|
const d = defaultAudioCat(c.k);
|
|
393
473
|
const a = state?.[c.k];
|
|
394
|
-
|
|
474
|
+
const changedHere = !!a && (a.on !== d.on || a.vol !== d.vol);
|
|
475
|
+
if (GEN_CATS.includes(c.k)) {
|
|
476
|
+
fromSound.push(changedHere);
|
|
477
|
+
markChanged(t, ctx.$(`[data-acat="${c.k}"]`)?.closest('.ctrl-row') ?? null, changedHere);
|
|
478
|
+
}
|
|
479
|
+
else
|
|
480
|
+
mark(`[data-acat="${c.k}"]`, changedHere);
|
|
395
481
|
}
|
|
396
|
-
markMenuChanged(ctx.$('[data-act="audio"]'),
|
|
482
|
+
markMenuChanged(t, ctx.$('[data-act="audio"]'), didChange);
|
|
483
|
+
markMenuChanged(t, ctx.$('[data-act="som"]'), fromSound);
|
|
397
484
|
}
|
|
398
|
-
// ----- widgets
|
|
485
|
+
// ----- static widgets (always present in #audio; wired ONCE, never recreated by renderAudio) -----
|
|
399
486
|
const audioMasterBtn = ctx.$('#audio-master');
|
|
400
487
|
if (audioMasterBtn)
|
|
401
488
|
audioMasterBtn.addEventListener('click', () => {
|
|
@@ -424,25 +511,21 @@ export function initSettingsAudio(ctx) {
|
|
|
424
511
|
renderNavSound();
|
|
425
512
|
});
|
|
426
513
|
/*
|
|
427
|
-
* ⚠️
|
|
428
|
-
*
|
|
429
|
-
*
|
|
514
|
+
* ⚠️ THIS BUTTON ANNOUNCES, like its siblings (sound, TTS, cane spacing, menu index, audio output): with the engine's
|
|
515
|
+
* default setter (`setBlindModeValue`, which stores/persists/notifies and does NOT speak), a game that does not inject
|
|
516
|
+
* its own setter would otherwise get a mute button. A toggle that changes state without saying so is invisible to a
|
|
517
|
+
* screen-reader user.
|
|
430
518
|
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
* tela — a mesma família de defeito que o `reflectTTS` e o `reflectModoCego` já custaram aqui.
|
|
435
|
-
*
|
|
436
|
-
* O anúncio pertence a QUEM É ACCIONADO, não ao setter: `core/state` diz que o setter faz três coisas e só
|
|
437
|
-
* três. ⚠️ Consequência de lockstep, escrita para não se descobrir depois: quando o `game-platformer` subir
|
|
438
|
-
* de versão, tem de TIRAR o `srSay` do `setModoCego` dele, senão a criança ouve o estado duas vezes.
|
|
519
|
+
* The announcement belongs to WHOEVER IS ACTIVATED, not to the setter: `core/state` says a setter does three things
|
|
520
|
+
* and only three. ⚠️ Lockstep consequence, written so it is not discovered later: a cartridge whose own `setBlindMode`
|
|
521
|
+
* also speaks must drop that, or the child hears the state twice.
|
|
439
522
|
*/
|
|
440
523
|
const mcBtn = ctx.$('#opt-modocego');
|
|
441
524
|
if (mcBtn) {
|
|
442
525
|
mcBtn.addEventListener('click', () => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
ctx.srSay(t(ctx.
|
|
526
|
+
writeBlindMode(!ctx.getBlindMode());
|
|
527
|
+
drawBlindMode();
|
|
528
|
+
ctx.srSay(t(ctx.getBlindMode() ? 'sr.blind.on' : 'sr.blind.off'));
|
|
446
529
|
});
|
|
447
530
|
}
|
|
448
531
|
const caneDivSel = ctx.$('#cane-div');
|
|
@@ -451,148 +534,67 @@ export function initSettingsAudio(ctx) {
|
|
|
451
534
|
caneDivSel.addEventListener('change', () => {
|
|
452
535
|
const div = parseCaneDiv(caneDivSel.value);
|
|
453
536
|
ctx.setCaneBlockDiv(div);
|
|
454
|
-
ctx.srSay(caneDivMessage(div));
|
|
537
|
+
ctx.srSay(caneDivMessage(t, div));
|
|
455
538
|
});
|
|
456
539
|
}
|
|
457
|
-
const ttsBtn = ctx.$('#opt-tts');
|
|
458
|
-
if (ttsBtn)
|
|
459
|
-
ttsBtn.addEventListener('click', () => {
|
|
460
|
-
const state = ctx.getAudioCat();
|
|
461
|
-
if (!state)
|
|
462
|
-
return;
|
|
463
|
-
state.tts.on = !state.tts.on;
|
|
464
|
-
ctx.setCatGain('tts');
|
|
465
|
-
reflectTts();
|
|
466
|
-
ctx.srSay(t(state.tts.on ? 'sr.audio.ttsOn' : 'sr.audio.ttsOff'));
|
|
467
|
-
if (state.tts.on)
|
|
468
|
-
ctx.tts.narrate(t('sr.audio.ttsOnSpoken'));
|
|
469
|
-
});
|
|
470
|
-
const idxBtn = ctx.$('#opt-menuindex');
|
|
471
|
-
if (idxBtn)
|
|
472
|
-
idxBtn.addEventListener('click', () => {
|
|
473
|
-
state.setMenuIndexOnValue(!state.menuIndexOn);
|
|
474
|
-
reflectMenuIndex();
|
|
475
|
-
// O anúncio da troca NÃO leva índice: ele não é item de lista nenhuma, e um "1 de 1" aqui seria ruído
|
|
476
|
-
// justamente no momento em que a criança está julgando se o ruído incomoda.
|
|
477
|
-
ctx.srSay(t(state.menuIndexOn ? 'sr.menu.indexOn' : 'sr.menu.indexOff'));
|
|
478
|
-
});
|
|
479
|
-
const ttsEngSel = ctx.$('#tts-engine');
|
|
480
|
-
if (ttsEngSel)
|
|
481
|
-
ttsEngSel.addEventListener('change', () => {
|
|
482
|
-
ctx.tts.setEngineSel(ttsEngSel.value);
|
|
483
|
-
ctx.store.set('incl_tts_engine', ttsEngSel.value);
|
|
484
|
-
if (ttsEngSel.value !== 'webspeech')
|
|
485
|
-
ctx.tts.loadTTS();
|
|
486
|
-
const opt = ttsEngSel.options[ttsEngSel.selectedIndex];
|
|
487
|
-
ctx.tts.narrate(t('sr.audio.engineSet', { motor: opt ? opt.text : '' }));
|
|
488
|
-
});
|
|
489
|
-
const ttsVoiceSel = ctx.$('#tts-voice');
|
|
490
|
-
if (ttsVoiceSel)
|
|
491
|
-
ttsVoiceSel.addEventListener('change', () => {
|
|
492
|
-
try {
|
|
493
|
-
const vs = window.speechSynthesis.getVoices();
|
|
494
|
-
ctx.tts.setVoiceObj(vs.find((v) => v.name === ttsVoiceSel.value) || null);
|
|
495
|
-
ctx.store.set('incl_tts_voice', ttsVoiceSel.value);
|
|
496
|
-
}
|
|
497
|
-
catch (e) { /* noop */ }
|
|
498
|
-
ctx.tts.narrate(t('sr.audio.voicePicked'));
|
|
499
|
-
});
|
|
500
|
-
const ttsTestBtn = ctx.$('#opt-tts-test');
|
|
501
|
-
if (ttsTestBtn)
|
|
502
|
-
ttsTestBtn.addEventListener('click', () => {
|
|
503
|
-
const txt = t('audio.voiceSample');
|
|
504
|
-
const engine = ctx.tts.getEngine();
|
|
505
|
-
if (ctx.tts.getEngineSel() !== 'webspeech' && engine && engine.speak) {
|
|
506
|
-
try {
|
|
507
|
-
engine.speak(txt);
|
|
508
|
-
}
|
|
509
|
-
catch (e) { /* noop */ } // motor neural já carregado
|
|
510
|
-
}
|
|
511
|
-
else {
|
|
512
|
-
try {
|
|
513
|
-
const ss = window.speechSynthesis;
|
|
514
|
-
if (ss) {
|
|
515
|
-
ss.cancel();
|
|
516
|
-
const u = new SpeechSynthesisUtterance(txt);
|
|
517
|
-
u.lang = 'pt-BR';
|
|
518
|
-
const vo = ctx.tts.getVoiceObj();
|
|
519
|
-
if (vo)
|
|
520
|
-
u.voice = vo;
|
|
521
|
-
u.rate = 1;
|
|
522
|
-
u.volume = 1;
|
|
523
|
-
ss.speak(u);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
catch (e) { /* noop */ } // fallback audível (volume 1) + dispara download do neural
|
|
527
|
-
if (ctx.tts.getEngineSel() !== 'webspeech')
|
|
528
|
-
ctx.tts.loadTTS();
|
|
529
|
-
}
|
|
530
|
-
ctx.srSay(t('sr.audio.testingVoice'));
|
|
531
|
-
});
|
|
532
|
-
// ---- restaurar os padrões DESTE menu (ADR-0028) ----
|
|
533
540
|
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
//
|
|
541
|
+
// The hard rule is scope: this button restores what the HEARING menu contains and nothing else. A reset that reached
|
|
542
|
+
// beyond itself would be worse than the trap it exists to undo — a child who undoes a sound setting and loses the
|
|
543
|
+
// mobility setup along with it can no longer play, and does not understand why.
|
|
537
544
|
//
|
|
538
|
-
//
|
|
539
|
-
//
|
|
540
|
-
//
|
|
545
|
+
// What belongs to this menu: blind mode, the cane spacing and the mixer categories that are not the audio panel's.
|
|
546
|
+
// The voice engine and the per-player audio output do NOT — they are a device choice, not a restorable preference,
|
|
547
|
+
// and clearing them would take away the child's own headset in a shared room.
|
|
548
|
+
/** Resets the categories in `keys` (those that exist in the mixer) to their factory state. */
|
|
549
|
+
function resetCategories(keys) {
|
|
550
|
+
const state = ctx.getAudioCat();
|
|
551
|
+
if (!state)
|
|
552
|
+
return;
|
|
553
|
+
for (const k of keys) {
|
|
554
|
+
if (!state[k])
|
|
555
|
+
continue;
|
|
556
|
+
const d = defaultAudioCat(k);
|
|
557
|
+
state[k].on = d.on;
|
|
558
|
+
state[k].vol = d.vol;
|
|
559
|
+
ctx.setCatGain(k);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
541
562
|
const resetBtn = ctx.$('#audio-reset');
|
|
542
563
|
if (resetBtn)
|
|
543
564
|
resetBtn.addEventListener('click', () => {
|
|
544
|
-
|
|
565
|
+
writeBlindMode(DEFAULTS.blindMode);
|
|
545
566
|
ctx.setCaneBlockDiv(DEFAULTS.caneBlockDiv);
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const d = defaultAudioCat(c.k);
|
|
550
|
-
if (!state[c.k])
|
|
551
|
-
continue;
|
|
552
|
-
state[c.k].on = d.on;
|
|
553
|
-
state[c.k].vol = d.vol;
|
|
554
|
-
ctx.setCatGain(c.k);
|
|
555
|
-
}
|
|
567
|
+
// 🔴 THIS MENU DOES NOT HOLD THE MUSIC (ADR-0151): resetting it here would reach beyond itself — the scope rule,
|
|
568
|
+
// above. Everything that is not a taste category belongs to this panel.
|
|
569
|
+
resetCategories(ctx.audioCats.map((c) => c.k).filter((k) => !GEN_CATS.includes(k)));
|
|
556
570
|
renderAudio();
|
|
557
|
-
|
|
558
|
-
reflectTts();
|
|
559
|
-
reflectMenuIndex();
|
|
571
|
+
drawBlindMode();
|
|
560
572
|
ctx.srSay(t('sr.audio.reset'));
|
|
561
573
|
});
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
ttsVolEl.addEventListener('input', () => {
|
|
570
|
-
const state = ctx.getAudioCat();
|
|
571
|
-
if (!state)
|
|
572
|
-
return;
|
|
573
|
-
state.tts.vol = (+ttsVolEl.value) / 100;
|
|
574
|
-
state.tts.on = true;
|
|
575
|
-
ctx.setCatGain('tts');
|
|
576
|
-
reflectTts();
|
|
574
|
+
// The AUDIO panel's reset: the taste categories and nothing else.
|
|
575
|
+
const soundReset = ctx.$('#som-reset');
|
|
576
|
+
if (soundReset)
|
|
577
|
+
soundReset.addEventListener('click', () => {
|
|
578
|
+
resetCategories(GEN_CATS);
|
|
579
|
+
renderAudio();
|
|
580
|
+
ctx.srSay(t('sr.audio.reset'));
|
|
577
581
|
});
|
|
578
582
|
const audioDetectBtn = ctx.$('#audio-detect');
|
|
579
583
|
if (audioDetectBtn)
|
|
580
584
|
audioDetectBtn.addEventListener('click', () => { void detectAudioDevices(); });
|
|
581
|
-
reflectMaster(); //
|
|
585
|
+
reflectMaster(); // initial state of the master button/slider, before the panel is ever opened
|
|
582
586
|
/*
|
|
583
|
-
* ⚠️
|
|
584
|
-
*
|
|
585
|
-
* efeitos … são reação, e quem reage assina o evento».
|
|
587
|
+
* ⚠️ THE PANEL SUBSCRIBES TO THE EVENT — the decision `core/state` writes next to `setBlindModeValue`: a setter stores,
|
|
588
|
+
* persists and notifies, and effects are reactions, subscribed by whoever reacts.
|
|
586
589
|
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
* registado no `ui/pause-icons`, e não vale a pena descobri-lo uma terceira vez.
|
|
590
|
+
* Without it, a game that does NOT inject its own `setBlindMode` switches blind mode on through the bar's icon and this
|
|
591
|
+
* panel's `#opt-modocego` keeps saying off, with `aria-pressed=false` — the control lying about the state to the screen
|
|
592
|
+
* reader.
|
|
591
593
|
*
|
|
592
|
-
* ⚠️
|
|
593
|
-
*
|
|
594
|
-
*
|
|
594
|
+
* ⚠️ It is safe for whoever ALREADY reflects from their own setter: reflecting is idempotent — it rereads the state and
|
|
595
|
+
* rewrites the button. A duplicated announcement would be another matter, which is why the subscription does NOT
|
|
596
|
+
* announce: the bar's icon already speaks for itself.
|
|
595
597
|
*/
|
|
596
|
-
|
|
597
|
-
return { renderAudio,
|
|
598
|
+
ctx.on('blindMode', () => { drawBlindMode(); }); // through the root's door: released by its `dispose()`
|
|
599
|
+
return { renderAudio, reflectBlindMode: drawBlindMode, reflectTts: voice.reflectTts };
|
|
598
600
|
}
|