@the-inclusionist/engine 6.36.1
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/LICENSE +661 -0
- package/README.md +107 -0
- package/app/css/style.css +622 -0
- package/app/public/vendor/fonts/andika-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/andika-400.woff2 +0 -0
- package/app/public/vendor/fonts/andika-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/andika-700.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-400.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-700.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-mono-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-mono-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
- package/app/public/vendor/fonts/greatvibes-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-400.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufcook-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/app/public/vendor/fonts.css +88 -0
- package/dist-pkg/boot/create-game.d.ts +159 -0
- package/dist-pkg/boot/create-game.js +266 -0
- package/dist-pkg/core/a11y-sr.d.ts +4 -0
- package/dist-pkg/core/a11y-sr.js +20 -0
- package/dist-pkg/core/actions.d.ts +100 -0
- package/dist-pkg/core/actions.js +149 -0
- package/dist-pkg/core/anel.d.ts +17 -0
- package/dist-pkg/core/anel.js +31 -0
- package/dist-pkg/core/collision.d.ts +21 -0
- package/dist-pkg/core/collision.js +62 -0
- package/dist-pkg/core/constants.d.ts +84 -0
- package/dist-pkg/core/constants.js +64 -0
- package/dist-pkg/core/contract.d.ts +227 -0
- package/dist-pkg/core/contract.js +184 -0
- package/dist-pkg/core/dom-query.d.ts +9 -0
- package/dist-pkg/core/dom-query.js +25 -0
- package/dist-pkg/core/entity.d.ts +150 -0
- package/dist-pkg/core/entity.js +38 -0
- package/dist-pkg/core/escape-html.d.ts +16 -0
- package/dist-pkg/core/escape-html.js +32 -0
- package/dist-pkg/core/i18n.d.ts +71 -0
- package/dist-pkg/core/i18n.js +236 -0
- package/dist-pkg/core/layers.d.ts +39 -0
- package/dist-pkg/core/layers.js +71 -0
- package/dist-pkg/core/letter-grid.d.ts +55 -0
- package/dist-pkg/core/letter-grid.js +116 -0
- package/dist-pkg/core/loop.d.ts +17 -0
- package/dist-pkg/core/loop.js +36 -0
- package/dist-pkg/core/password.d.ts +34 -0
- package/dist-pkg/core/password.js +205 -0
- package/dist-pkg/core/rng.d.ts +20 -0
- package/dist-pkg/core/rng.js +61 -0
- package/dist-pkg/core/rotulo-acessivel.d.ts +17 -0
- package/dist-pkg/core/rotulo-acessivel.js +41 -0
- package/dist-pkg/core/run-state.d.ts +115 -0
- package/dist-pkg/core/run-state.js +40 -0
- package/dist-pkg/core/scenes.d.ts +68 -0
- package/dist-pkg/core/scenes.js +64 -0
- package/dist-pkg/core/screens.d.ts +16 -0
- package/dist-pkg/core/screens.js +28 -0
- package/dist-pkg/core/state.d.ts +138 -0
- package/dist-pkg/core/state.js +290 -0
- package/dist-pkg/core/tiles.d.ts +12 -0
- package/dist-pkg/core/tiles.js +61 -0
- package/dist-pkg/core/world.d.ts +4 -0
- package/dist-pkg/core/world.js +58 -0
- package/dist-pkg/educational/activities-registry.d.ts +47 -0
- package/dist-pkg/educational/activities-registry.js +95 -0
- package/dist-pkg/i18n/en.d.ts +3 -0
- package/dist-pkg/i18n/en.js +560 -0
- package/dist-pkg/i18n/es.d.ts +3 -0
- package/dist-pkg/i18n/es.js +558 -0
- package/dist-pkg/i18n/pt.d.ts +3 -0
- package/dist-pkg/i18n/pt.js +618 -0
- package/dist-pkg/input/default-bindings.d.ts +24 -0
- package/dist-pkg/input/default-bindings.js +122 -0
- package/dist-pkg/input/devices.d.ts +15 -0
- package/dist-pkg/input/devices.js +31 -0
- package/dist-pkg/input/edges.d.ts +58 -0
- package/dist-pkg/input/edges.js +49 -0
- package/dist-pkg/input/gamepad.d.ts +203 -0
- package/dist-pkg/input/gamepad.js +531 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +61 -0
- package/dist-pkg/input/keyboard-runtime.js +83 -0
- package/dist-pkg/input/keyboard.d.ts +45 -0
- package/dist-pkg/input/keyboard.js +80 -0
- package/dist-pkg/input/keydown.d.ts +270 -0
- package/dist-pkg/input/keydown.js +381 -0
- package/dist-pkg/input/latch.d.ts +30 -0
- package/dist-pkg/input/latch.js +63 -0
- package/dist-pkg/input/pointer-space.d.ts +40 -0
- package/dist-pkg/input/pointer-space.js +51 -0
- package/dist-pkg/input/state.d.ts +11 -0
- package/dist-pkg/input/state.js +12 -0
- package/dist-pkg/input/touch-bindings.d.ts +210 -0
- package/dist-pkg/input/touch-bindings.js +365 -0
- package/dist-pkg/input/touch.d.ts +173 -0
- package/dist-pkg/input/touch.js +314 -0
- package/dist-pkg/input/transports.d.ts +90 -0
- package/dist-pkg/input/transports.js +96 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +58 -0
- package/dist-pkg/input/vocabulary-migration.js +125 -0
- package/dist-pkg/platform/audio-ambient.d.ts +27 -0
- package/dist-pkg/platform/audio-ambient.js +89 -0
- package/dist-pkg/platform/audio-earcons.d.ts +24 -0
- package/dist-pkg/platform/audio-earcons.js +62 -0
- package/dist-pkg/platform/audio-jingles.d.ts +17 -0
- package/dist-pkg/platform/audio-jingles.js +54 -0
- package/dist-pkg/platform/audio-mixer.d.ts +14 -0
- package/dist-pkg/platform/audio-mixer.js +62 -0
- package/dist-pkg/platform/audio-nav.d.ts +51 -0
- package/dist-pkg/platform/audio-nav.js +99 -0
- package/dist-pkg/platform/audio-sonar.d.ts +71 -0
- package/dist-pkg/platform/audio-sonar.js +173 -0
- package/dist-pkg/platform/audio.d.ts +32 -0
- package/dist-pkg/platform/audio.js +191 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +19 -0
- package/dist-pkg/platform/interruptible-speech.js +79 -0
- package/dist-pkg/platform/speech.d.ts +2 -0
- package/dist-pkg/platform/speech.js +35 -0
- package/dist-pkg/platform/storage.d.ts +87 -0
- package/dist-pkg/platform/storage.js +148 -0
- package/dist-pkg/platform/tts.d.ts +33 -0
- package/dist-pkg/platform/tts.js +142 -0
- package/dist-pkg/render/camera.d.ts +58 -0
- package/dist-pkg/render/camera.js +105 -0
- package/dist-pkg/render/canvas.d.ts +13 -0
- package/dist-pkg/render/canvas.js +26 -0
- package/dist-pkg/render/cenario-data.d.ts +127 -0
- package/dist-pkg/render/cenario-data.js +145 -0
- package/dist-pkg/render/city-tex.d.ts +63 -0
- package/dist-pkg/render/city-tex.js +228 -0
- package/dist-pkg/render/city-tiles.d.ts +11 -0
- package/dist-pkg/render/city-tiles.js +140 -0
- package/dist-pkg/render/crt.d.ts +19 -0
- package/dist-pkg/render/crt.js +92 -0
- package/dist-pkg/render/cvd-matrices.d.ts +35 -0
- package/dist-pkg/render/cvd-matrices.js +91 -0
- package/dist-pkg/render/draw.d.ts +149 -0
- package/dist-pkg/render/draw.js +221 -0
- package/dist-pkg/render/fx.d.ts +63 -0
- package/dist-pkg/render/fx.js +123 -0
- package/dist-pkg/render/hc-role-data.d.ts +14 -0
- package/dist-pkg/render/hc-role-data.js +24 -0
- package/dist-pkg/render/high-contrast.d.ts +109 -0
- package/dist-pkg/render/high-contrast.js +254 -0
- package/dist-pkg/render/lq-filter.d.ts +37 -0
- package/dist-pkg/render/lq-filter.js +94 -0
- package/dist-pkg/render/minimap.d.ts +11 -0
- package/dist-pkg/render/minimap.js +94 -0
- package/dist-pkg/render/parallax.d.ts +85 -0
- package/dist-pkg/render/parallax.js +158 -0
- package/dist-pkg/render/player-anim.d.ts +71 -0
- package/dist-pkg/render/player-anim.js +152 -0
- package/dist-pkg/render/port.d.ts +143 -0
- package/dist-pkg/render/port.js +29 -0
- package/dist-pkg/render/recycling-tex.d.ts +48 -0
- package/dist-pkg/render/recycling-tex.js +164 -0
- package/dist-pkg/render/scene-city.d.ts +77 -0
- package/dist-pkg/render/scene-city.js +181 -0
- package/dist-pkg/render/scene-parallax.d.ts +72 -0
- package/dist-pkg/render/scene-parallax.js +426 -0
- package/dist-pkg/render/scene-sky.d.ts +126 -0
- package/dist-pkg/render/scene-sky.js +295 -0
- package/dist-pkg/render/screen-pipeline.d.ts +134 -0
- package/dist-pkg/render/screen-pipeline.js +177 -0
- package/dist-pkg/render/set-cenario.d.ts +54 -0
- package/dist-pkg/render/set-cenario.js +103 -0
- package/dist-pkg/render/sprite-fx.d.ts +3 -0
- package/dist-pkg/render/sprite-fx.js +40 -0
- package/dist-pkg/render/textures.d.ts +75 -0
- package/dist-pkg/render/textures.js +240 -0
- package/dist-pkg/render/title-scene.d.ts +46 -0
- package/dist-pkg/render/title-scene.js +75 -0
- package/dist-pkg/render/viewports.d.ts +52 -0
- package/dist-pkg/render/viewports.js +185 -0
- package/dist-pkg/render/viz-axes.d.ts +98 -0
- package/dist-pkg/render/viz-axes.js +184 -0
- package/dist-pkg/render/viz-modes.d.ts +61 -0
- package/dist-pkg/render/viz-modes.js +74 -0
- package/dist-pkg/render/viz-setters.d.ts +130 -0
- package/dist-pkg/render/viz-setters.js +244 -0
- package/dist-pkg/render/weather.d.ts +96 -0
- package/dist-pkg/render/weather.js +171 -0
- package/dist-pkg/render/wheelchair-sprites.d.ts +24 -0
- package/dist-pkg/render/wheelchair-sprites.js +63 -0
- package/dist-pkg/render/world-tex.d.ts +18 -0
- package/dist-pkg/render/world-tex.js +87 -0
- package/dist-pkg/ui/activities-menu.d.ts +258 -0
- package/dist-pkg/ui/activities-menu.js +648 -0
- package/dist-pkg/ui/caa-sets.d.ts +39 -0
- package/dist-pkg/ui/caa-sets.js +65 -0
- package/dist-pkg/ui/changed-mark.d.ts +15 -0
- package/dist-pkg/ui/changed-mark.js +96 -0
- package/dist-pkg/ui/debug-panel.d.ts +67 -0
- package/dist-pkg/ui/debug-panel.js +173 -0
- package/dist-pkg/ui/dom.d.ts +24 -0
- package/dist-pkg/ui/dom.js +47 -0
- package/dist-pkg/ui/focus-trap.d.ts +71 -0
- package/dist-pkg/ui/focus-trap.js +99 -0
- package/dist-pkg/ui/fonts.d.ts +41 -0
- package/dist-pkg/ui/fonts.js +59 -0
- package/dist-pkg/ui/hud.d.ts +137 -0
- package/dist-pkg/ui/hud.js +229 -0
- package/dist-pkg/ui/item-announcement.d.ts +19 -0
- package/dist-pkg/ui/item-announcement.js +36 -0
- package/dist-pkg/ui/layout.d.ts +6 -0
- package/dist-pkg/ui/layout.js +54 -0
- package/dist-pkg/ui/loop-crash.d.ts +19 -0
- package/dist-pkg/ui/loop-crash.js +60 -0
- package/dist-pkg/ui/map-hub.d.ts +56 -0
- package/dist-pkg/ui/map-hub.js +138 -0
- package/dist-pkg/ui/menu-nav.d.ts +141 -0
- package/dist-pkg/ui/menu-nav.js +390 -0
- package/dist-pkg/ui/pause-icons.d.ts +327 -0
- package/dist-pkg/ui/pause-icons.js +620 -0
- package/dist-pkg/ui/reach-notice.d.ts +34 -0
- package/dist-pkg/ui/reach-notice.js +71 -0
- package/dist-pkg/ui/settings-audio.d.ts +139 -0
- package/dist-pkg/ui/settings-audio.js +544 -0
- package/dist-pkg/ui/settings-caa.d.ts +45 -0
- package/dist-pkg/ui/settings-caa.js +137 -0
- package/dist-pkg/ui/settings-controls.d.ts +100 -0
- package/dist-pkg/ui/settings-controls.js +152 -0
- package/dist-pkg/ui/settings-empathy.d.ts +62 -0
- package/dist-pkg/ui/settings-empathy.js +137 -0
- package/dist-pkg/ui/settings-motion.d.ts +95 -0
- package/dist-pkg/ui/settings-motion.js +282 -0
- package/dist-pkg/ui/settings-motor.d.ts +77 -0
- package/dist-pkg/ui/settings-motor.js +215 -0
- package/dist-pkg/ui/settings-panel.d.ts +76 -0
- package/dist-pkg/ui/settings-panel.js +187 -0
- package/dist-pkg/ui/settings-typo.d.ts +74 -0
- package/dist-pkg/ui/settings-typo.js +150 -0
- package/dist-pkg/ui/settings-visual.d.ts +111 -0
- package/dist-pkg/ui/settings-visual.js +252 -0
- package/dist-pkg/ui/shell.d.ts +239 -0
- package/dist-pkg/ui/shell.js +430 -0
- package/dist-pkg/ui/title.d.ts +36 -0
- package/dist-pkg/ui/title.js +60 -0
- package/dist-pkg/ui/vlibras.d.ts +11 -0
- package/dist-pkg/ui/vlibras.js +87 -0
- package/dist-pkg/ui/webcam.d.ts +7 -0
- package/dist-pkg/ui/webcam.js +88 -0
- package/docs/CREDITS.md +64 -0
- package/docs/LICENSES.md +132 -0
- package/package.json +115 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
|
2
|
+
:root{
|
|
3
|
+
--bg:#0b1020; --panel:#1b2440; --ink:#f5f8ff; --ink-soft:#cdd6f2;
|
|
4
|
+
--accent:#ffd23f; --accent-ink:#1a1400; --focus:#ffd23f; --good:#34e29b;
|
|
5
|
+
--changed:#fff; /* ADR-0029: moldura de quem saiu do padrão */
|
|
6
|
+
/* Alto contraste no DOM (issue #83): o véu do painel sem transparência, e o fundo de botão. Ficam aqui,
|
|
7
|
+
junto dos outros tokens, para o teste de contraste poder lê-los do CSS em vez de os copiar. */
|
|
8
|
+
--bg-solid:#04070f; --panel-btn:#1a2740;
|
|
9
|
+
--maxw:1000px; --tap:44px;
|
|
10
|
+
--ui-fs:16px; /* fonte-base da UI (<p>): 16px = MÍNIMO a 640×360; o JS (layout) aumenta conforme o canvas cresce */
|
|
11
|
+
/* ===== Tipografia oficial EdSP ===== */
|
|
12
|
+
/* 'Noto Color Emoji' no fim do stack → emoji consistentes (nativo no Chromebook/Android; woff2 abaixo p/ Windows) */
|
|
13
|
+
--font-fallback:system-ui,"Segoe UI",Roboto,Arial,sans-serif,'Noto Color Emoji';
|
|
14
|
+
--font:'Atkinson Hyperlegible',var(--font-fallback); /* PADRÃO */
|
|
15
|
+
--font-math:'Atkinson Hyperlegible Mono',ui-monospace,"Cascadia Mono",Consolas,monospace; /* matemática */
|
|
16
|
+
/* Espaçamento padrão do projeto (≥ recomendações WCAG 2.2 §1.4.12) */
|
|
17
|
+
--ls:0.12em; /* letter-spacing */
|
|
18
|
+
--ws:0.16em; /* word-spacing */
|
|
19
|
+
--lh:1.5; /* line-height */
|
|
20
|
+
|
|
21
|
+
/* ===== ORDEM-Z CANÔNICA — a faixa de OVERLAY do `core/layers.ts` (ADR-0020) =====
|
|
22
|
+
Estes valores são a MESMA fonte que o mundo usa em PIXI, trazida para o CSS. Eles existem antes do
|
|
23
|
+
primeiro consumidor DE PROPÓSITO, e o motivo é o mesmo que a Fase C deu ao barramento tipado: o contrato
|
|
24
|
+
precisa nascer certo em vez de ser retipado depois. `tests/z-order-css.node.test.js` compara este bloco,
|
|
25
|
+
valor a valor, com o `Z` do TypeScript — divergir fica vermelho.
|
|
26
|
+
|
|
27
|
+
⚠️ NENHUM SELETOR AINDA OS USA, e isso NÃO é esquecimento. Adotá-los inverte três ordens que hoje valem,
|
|
28
|
+
e inverter ordem é decisão de produto:
|
|
29
|
+
|
|
30
|
+
· `.caption` (8) está ABAIXO de `#touch-controls` (14). Canonicamente CAPTIONS(26000) fica ACIMA de
|
|
31
|
+
TOUCH_CONTROLS(25000). A inversão CONSERTA um defeito — legenda é recurso de surdez, e controle de
|
|
32
|
+
toque cobrindo legenda é a coisa errada —, mas muda a tela.
|
|
33
|
+
· `.quiz` (12) está ABAIXO de `#touch-controls` (14); canonicamente DIALOGUE(27000) fica acima.
|
|
34
|
+
· `.skip-link` (100) está ACIMA dos modais (60). O comentário do `Z` põe o skip-link em CAPTIONS
|
|
35
|
+
(26000), o que o deixaria ABAIXO de MENU(30000) — e um "pular para o conteúdo" embaixo de um modal
|
|
36
|
+
não é alcançável. Aqui o comentário do `Z` é que está errado, não o CSS.
|
|
37
|
+
|
|
38
|
+
E DUAS COISAS NÃO TÊM SLOT: os dois pseudo-elementos do CRT (`crt-vig-1::before` em 5 e
|
|
39
|
+
`crt-scan-1::after` em 500). Pelo ADR-0020 o CRT é PÓS-PROCESSO, não camada — inventar um número para
|
|
40
|
+
ele repetiria o erro de categoria que a emenda de 2026-08-26 já registrou no `app.stage`.
|
|
41
|
+
|
|
42
|
+
⚠️ E `z-index` de CSS NÃO É PLANO. `#game-hud` tem `z-index:4` e CRIA CONTEXTO DE EMPILHAMENTO, então o
|
|
43
|
+
`.screen-pause` (6) compete só lá dentro — o menu de pausa vive efetivamente em "4" na raiz. Uma lista
|
|
44
|
+
plana de valores globais não expressa isso. Adotar exige decidir, por elemento, em que contexto ele vive. */
|
|
45
|
+
--z-hud:24000;
|
|
46
|
+
--z-touch-controls:25000;
|
|
47
|
+
--z-captions:26000;
|
|
48
|
+
--z-dialogue:27000;
|
|
49
|
+
--z-game-msg:28000;
|
|
50
|
+
--z-modal-scrim:29000;
|
|
51
|
+
--z-menu:30000;
|
|
52
|
+
--z-menu-max:39999;
|
|
53
|
+
--z-transition:40000;
|
|
54
|
+
--z-debug:90000;
|
|
55
|
+
}
|
|
56
|
+
/* Emoji: usa o Noto Color Emoji do sistema (Chromebook/Android/Linux) e, se ausente, o woff2 embutido
|
|
57
|
+
(offline). Se o arquivo não estiver presente, o navegador cai no emoji do SO — sem quebrar. */
|
|
58
|
+
@font-face{ font-family:'Noto Color Emoji'; src:local('Noto Color Emoji'); /* só a fonte do sistema; sem download (o .woff2 nunca existiu) */ font-display:swap; }
|
|
59
|
+
/* Modo ALFABETIZAÇÃO → Andika */
|
|
60
|
+
:root[data-fonte="alfabetizacao"]{ --font:'Andika',var(--font-fallback); }
|
|
61
|
+
/* Modo DISLEXIA/TDAH → Lexend + espaçamento da British Dyslexia Association
|
|
62
|
+
(palavra ≥ 3,5× letra: letter 0.18em / word 0.63em) */
|
|
63
|
+
:root[data-fonte="dislexia"]{ --font:'Lexend',var(--font-fallback); --ls:0.18em; --ws:0.63em; }
|
|
64
|
+
/* Tipografia: qualquer fonte do catálogo (menu próprio na pausa); --font-custom traz a pilha com fallback */
|
|
65
|
+
:root[data-fonte="custom"]{ --font:var(--font-custom,'Atkinson Hyperlegible'),var(--font-fallback); }
|
|
66
|
+
/* Menu Tipografia: caixa branca de pré-visualização (pangrama), escrita escura */
|
|
67
|
+
.typo-preview{background:#fff;color:#14141f;border:2px solid var(--ink-soft);border-radius:8px;padding:.65rem .9rem;margin:.2rem 0 .6rem;font-size:1.3em;line-height:1.3;text-align:center}
|
|
68
|
+
/* Tela de título (visual da v3): overlay TRANSPARENTE — a cena (céu/nuvens/grama) vem do canvas */
|
|
69
|
+
#title-overlay{background:transparent;font-size:var(--ui-fs,16px)} /* UI do splash escala com o k inteiro do canvas (igual pausa/diálogos) — NÃO fica fixa em 16px */
|
|
70
|
+
body.at-title #game-hud,body.at-title .start-tips,body.at-title .hud{display:none} /* HUD do jogo não vaza no menu inicial (display: filhos não conseguem re-exibir) */
|
|
71
|
+
.title-wrap{display:flex;flex-direction:column;align-items:center;gap:12px;max-height:96%;}
|
|
72
|
+
.game-title{color:#fff;font-size:2em;line-height:1.2;margin:0;text-align:center;letter-spacing:1px;text-shadow:2px 2px 0 #0d0d1a,-1px -1px 0 #0d0d1a}
|
|
73
|
+
.title-block{display:inline-block}
|
|
74
|
+
.game-byline{color:#f6f5f0;font-size:.8em;text-align:right;margin-top:2px;text-shadow:1px 1px 0 #0d0d1a}
|
|
75
|
+
.game-version{color:#9999b3;font-size:.6em;text-align:right;letter-spacing:1px;margin-top:2px;text-shadow:1px 1px 0 #0d0d1a}
|
|
76
|
+
.game-subtitle{color:#f6f5f0;font-size:.8em;margin:0 0 4px;text-shadow:1px 1px 0 #0d0d1a;text-align:center}
|
|
77
|
+
/* Splash DENTRO do canvas, SEM rolagem. GESTALT (José): a11y no CABEÇALHO · menu no ESPAÇO DE TRABALHO · legenda no RODAPÉ */
|
|
78
|
+
.title-wrap{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;max-height:none}
|
|
79
|
+
.title-legend{position:absolute;left:0;right:0;bottom:8px} /* RODAPÉ, como a legenda da pausa */
|
|
80
|
+
.title-menu{display:flex;flex-direction:column;gap:.35em;align-items:stretch;padding:2px;width:13em;margin:0 auto} /* largura fixa ENXUTA */
|
|
81
|
+
.title-menu[hidden]{display:none}
|
|
82
|
+
/* O menu principal com o DOBRO da largura base (13em → 26em): a 13em os rótulos quebravam em DUAS linhas, e
|
|
83
|
+
um botão de duas linhas muda de altura conforme o idioma — a mesma tela com uma geometria em pt-BR e outra
|
|
84
|
+
em espanhol. Quem se orienta por alinhamento perde a referência; quem escuta nem percebe que ela existia. */
|
|
85
|
+
#tm-main{width:26em}
|
|
86
|
+
/* ===================== SUBMENUS DA ABERTURA: LISTA VERTICAL COM ROLAGEM (ADR-0044) =====================
|
|
87
|
+
Eram GRADES de duas colunas, e a seta anda em ordem de DOM: “para baixo” pulava para a coluna da direita,
|
|
88
|
+
atravessando a tela. O anel do item 1 já estava certo no código (`nextTitleIndex` dá a volta) — era o
|
|
89
|
+
LAYOUT que mentia sobre ele. Em lista, a ordem que se VÊ é a ordem em que se ANDA.
|
|
90
|
+
|
|
91
|
+
Onze frações não cabem no quadro, então a lista ROLA — foi o que o Dev pediu, e o preço é barato:
|
|
92
|
+
`focus()` traz o item para dentro da janela sozinho, de modo que quem anda por teclado ou controle nunca
|
|
93
|
+
perde o foco fora da vista.
|
|
94
|
+
|
|
95
|
+
O painel é OPACO pelo mesmo motivo do véu da pausa: por trás da abertura corre o modo de atração, e
|
|
96
|
+
texto sobre quadro variável tem a razão de contraste que o quadro permitir — média de sorte, não garantia. */
|
|
97
|
+
#tm-alf,#tm-mat,#tm-tab,#tm-fr,#tm-cen{width:26em;max-height:72%;overflow-y:auto;overflow-x:hidden;background:var(--bg-solid);border-radius:10px;padding:.5em .7em}
|
|
98
|
+
/* O título do submenu fica GRUDADO no topo: numa lista que rola, um cabeçalho que sobe leva embora a única
|
|
99
|
+
pista de “onde estou” que quem lê por resto de visão tem. */
|
|
100
|
+
#tm-alf .tm-title,#tm-mat .tm-title,#tm-tab .tm-title,#tm-fr .tm-title,#tm-cen .tm-title{position:sticky;top:-.5em;z-index:1;background:var(--bg-solid);padding:.35em 0 .25em;margin:0}
|
|
101
|
+
/* …e por isso os itens precisam de MARGEM DE ROLAGEM: um cabeçalho grudado cobre o item que o navegador acaba
|
|
102
|
+
de "trazer para a vista", porque para ele o item já estava dentro do quadro. MEDIDO no navegador antes de
|
|
103
|
+
existir esta linha: dando a volta do último para o primeiro, o primeiro botão parava com o topo em 143px e
|
|
104
|
+
o cabeçalho terminava em 155 — 12px encobertos, e a criança via um item cortado no lugar do foco. O valor
|
|
105
|
+
cobre a altura do cabeçalho (34px ≈ 2,1em) com folga. */
|
|
106
|
+
#tm-alf .title-btn,#tm-mat .title-btn,#tm-tab .title-btn,#tm-fr .title-btn,#tm-cen .title-btn{scroll-margin-top:2.4em;scroll-margin-bottom:.5em}
|
|
107
|
+
/* As notações de fração continuam LADO A LADO: são cinco alternadores de UM grupo, e não itens da lista —
|
|
108
|
+
virar coluna aqui alongaria a rolagem sem ganhar ordem nenhuma. */
|
|
109
|
+
#tm-fr .frac-nots{display:flex;flex-direction:column;gap:.25em}
|
|
110
|
+
/* AS CINCO NOTAÇÕES SÃO AJUSTE, NÃO ITEM DE MENU (pedido do Dev). Elas usavam `.title-btn` — a mesma classe
|
|
111
|
+
dos botões que ABREM uma atividade — e ficavam empilhadas logo acima deles: cinco coisas com cara de
|
|
112
|
+
"entrar" que na verdade ligam e desligam. A moldura (`fieldset`/`legend`) é a fronteira, e a marca ☑/☐ é o
|
|
113
|
+
estado sem depender de cor (a cor sozinha reprova a WCAG 1.4.1). */
|
|
114
|
+
#tm-fr .frac-nots{border:2px solid var(--ink-soft);border-radius:10px;padding:.3em .5em .5em;margin:0 0 .45em}
|
|
115
|
+
#tm-fr .frac-nots legend{padding:0 .4em;font-size:.8em;font-weight:700;color:var(--ink-soft)}
|
|
116
|
+
#tm-fr .fnot-opt{display:flex;align-items:center;gap:.5em;width:100%;min-height:44px;padding:.2em .4em;background:transparent;color:#fff;border:0;border-radius:8px;font:inherit;cursor:pointer;text-align:left}
|
|
117
|
+
#tm-fr .fnot-opt:hover,#tm-fr .fnot-opt:focus-visible{background:#16233f}
|
|
118
|
+
#tm-fr .fnot-marca{font-size:1.15em;line-height:1;min-width:1.1em}
|
|
119
|
+
#tm-fr .fnot-opt[aria-checked="true"] .fnot-marca{color:var(--accent)}
|
|
120
|
+
#tm-fr .fnot-sym{font-size:1em}
|
|
121
|
+
#tm-fr .fnot-opt .fv{font-size:.8em}
|
|
122
|
+
.tm-title{color:#fff;font-size:1em;margin:0 0 .1em;text-align:center;text-shadow:1px 1px 0 #0d0d1a} /* título do submenu */
|
|
123
|
+
.title-btn{background:var(--accent);color:var(--accent-ink);border:3px solid #0d0d1a;font-family:inherit;font-weight:bold;font-size:.95em;padding:.4em .6em;border-radius:6px;cursor:pointer;min-width:0;width:100%;min-height:2.3em} /* contorno PRETO grosso (3px) = mesma cor do texto (José) */
|
|
124
|
+
.title-btn.ghost{background:#e8862b;color:#0d0d1a;border:2px solid #0d0d1a} /* Voltar = preenchimento LARANJA */
|
|
125
|
+
.act-sub{display:block;font-size:.72em;font-weight:600;opacity:.7;letter-spacing:.02em;margin-top:.06em;font-family:var(--font-math,inherit);white-space:nowrap} /* subtítulo de exemplo (2ª linha, NUNCA quebra — botão largo o bastante) */
|
|
126
|
+
/* Seletor VERMELHO fixo (piscar removido a pedido do José). Especificidade via #title-overlay. */
|
|
127
|
+
#title-overlay .title-btn:focus-visible,#title-overlay .title-btn:focus{outline:4px solid #ff3b30;outline-offset:2px}
|
|
128
|
+
#title-overlay .title-btn.act-fx{animation:titleAct .22s ease} /* efeito de ATIVAÇÃO (antes de trocar de tela) */
|
|
129
|
+
@keyframes titleAct{0%{transform:scale(.92);filter:brightness(1.6)}60%{transform:scale(1.03)}100%{transform:scale(1)}}
|
|
130
|
+
@media (prefers-reduced-motion: reduce){ #title-overlay .title-btn.act-fx{animation:none;filter:brightness(1.4)} }
|
|
131
|
+
.title-btn.tab-on{box-shadow:inset 0 0 0 3px #14141f}
|
|
132
|
+
/* As fileiras da tabuada eram DUAS linhas de números lado a lado, e o Dev cobrou de novo depois de ver o
|
|
133
|
+
resultado: menu "misto" é menu onde "para baixo" às vezes anda para o lado. Viraram coluna, como todo o
|
|
134
|
+
resto da abertura. O seletor ganhou o `#tm-tab` na frente de propósito — é o que deixa o gate de layout
|
|
135
|
+
enxergar esta regra como sendo DE um submenu da abertura, em vez de uma classe solta que ninguém vigia. */
|
|
136
|
+
#tm-tab .tab-row{display:flex;flex-direction:column;gap:.35em}
|
|
137
|
+
#tm-tab .tab-row .title-btn{width:100%;padding:.4em .5em}
|
|
138
|
+
/* RODAPÉ (mesmo estilo do menu de pausa): descrição no fundo do canvas, NÃO colada ao grupo de botões (José).
|
|
139
|
+
Fundo fumê PRETO → contraste ≥7:1 entre o texto claro (#f6f5f0) e o fundo (≈#0a0a12). */
|
|
140
|
+
.tm-desc:not(:empty){position:absolute;left:50%;transform:translateX(-50%);bottom:10px;max-width:88%;color:#f6f5f0;font-size:.8em;text-align:center;background:rgba(8,8,16,.92);padding:.35em .7em;border-radius:8px;line-height:1.25}
|
|
141
|
+
.tm-desc:empty{position:absolute;left:0;bottom:10px}
|
|
142
|
+
/* Legenda de controles: mesmo visual/posição da legenda do menu de pausa (chips), em 2 LINHAS */
|
|
143
|
+
.title-legend{display:flex;flex-direction:column;gap:.25em;align-items:center;margin:.5em 0 .1em;font-size:.82em;color:#c3cfe0}
|
|
144
|
+
.title-legend .lg-row{display:flex;gap:1.1em;justify-content:center;flex-wrap:wrap}
|
|
145
|
+
.title-legend .lg{display:inline-flex;align-items:center;gap:.35em}
|
|
146
|
+
.title-legend .lg-ico{display:inline-flex;align-items:center;justify-content:center;min-width:1.35em;height:1.35em;padding:0 .2em;border-radius:.68em;font-weight:800;font-size:.9em;color:#fff;background:rgba(13,13,26,.85);text-shadow:0 1px 1px rgba(0,0,0,.55)}
|
|
147
|
+
#title-icons{position:absolute;top:10px;left:50%;transform:translateX(-50%);display:flex;gap:.3em;justify-content:center;flex-wrap:nowrap;white-space:nowrap} /* CABEÇALHO: 10px do topo, UMA fileira */
|
|
148
|
+
/* Seletor de jogadores = UM botão só ("◀ Nº de jogadores: X ▶"); o lado clicado decide +1/−1 */
|
|
149
|
+
#np-btn{letter-spacing:.02em}
|
|
150
|
+
#np-btn #np-n{display:inline-block;min-width:1.1em;text-align:center}
|
|
151
|
+
/* Fração VERTICAL: pilha número/traço/número em HTML puro (zero dependência) */
|
|
152
|
+
.fv{display:inline-flex;flex-direction:column;align-items:center;vertical-align:middle;line-height:1.05;margin:0 .1em}
|
|
153
|
+
.fv b{font-weight:800;padding:0 .25em}
|
|
154
|
+
.fv b:first-child{border-bottom:2px solid currentColor}
|
|
155
|
+
/* Fração como FIGURA (pizza/quadrado): SVG inline, 2-6 partes iguais; imprópria = várias unidades lado a lado */
|
|
156
|
+
:root{--frac-fill:#f2a03d} /* laranja: alto contraste sobre branco + contorno preto (não depende só da cor — WCAG 1.4.1) */
|
|
157
|
+
.frac-fig{display:inline-flex;align-items:center;gap:.25em;vertical-align:middle}
|
|
158
|
+
.frac-shape{display:inline-flex;align-items:center;gap:.15em} /* círculo + quadrado da mesma fração, lado a lado */
|
|
159
|
+
.frac-op{display:inline-flex;flex-direction:column;align-items:center;gap:.15em;vertical-align:middle} /* operando da conta: número EM CIMA, gráfico embaixo */
|
|
160
|
+
.frac-svg{width:2.4em;height:2.4em;display:inline-block;vertical-align:middle}
|
|
161
|
+
.quiz-choice .frac-svg{width:2.6em;height:2.6em}
|
|
162
|
+
.quiz-prob .frac-svg{width:2.6em;height:2.6em}
|
|
163
|
+
.quiz-dots{font-size:1.3em;letter-spacing:.15em;line-height:1.3;margin:.3rem 0;max-width:12em}
|
|
164
|
+
@media (prefers-contrast: more){
|
|
165
|
+
/* Aqui `--ink-soft` JÁ é branco: a moldura de "alterado" tem que deixar de ser branca, ou marcado e
|
|
166
|
+
não-marcado viram a mesma moldura — justamente para a criança cujos ajustes têm mais chance de estar
|
|
167
|
+
fora do padrão. Uma marca cuja visibilidade depende do tema não é uma marca (ADR-0029). */
|
|
168
|
+
:root{ --bg:#000; --panel:#000; --ink:#fff; --ink-soft:#fff; --accent:#ffe600; --changed:#ffe600; }
|
|
169
|
+
}
|
|
170
|
+
*{box-sizing:border-box}
|
|
171
|
+
html,body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);font-size:16px;line-height:var(--lh);letter-spacing:var(--ls);word-spacing:var(--ws)}
|
|
172
|
+
/* matemática em mono tabular (algarismos alinhados/legíveis) */
|
|
173
|
+
.quiz-box--math .quiz-prob,.quiz-box--math .quiz-choice,#hud-coins,#hud-total{font-family:var(--font-math);font-variant-numeric:tabular-nums}
|
|
174
|
+
/* espaçamento de parágrafo ≥2× só em blocos de leitura (não quebra HUD/menus) */
|
|
175
|
+
.overlay__card p + p{margin-top:2em}
|
|
176
|
+
/* A página NUNCA rola (José): altura travada no viewport e overflow escondido — o excedente do canvas
|
|
177
|
+
(tolerância de 5px lógicos/lado) é cortado pelo .stage-wrap, e os menus rolam DENTRO dos cards. */
|
|
178
|
+
body{display:flex;flex-direction:column;height:100vh;height:100dvh;overflow:hidden}
|
|
179
|
+
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
180
|
+
.skip-link{position:absolute;left:8px;top:-60px;background:var(--accent);color:var(--accent-ink);padding:.6em 1em;border-radius:0 0 10px 10px;font-weight:700;z-index:100;transition:top .15s}
|
|
181
|
+
.skip-link:focus{top:0}
|
|
182
|
+
:focus-visible{outline:4px solid var(--focus);outline-offset:2px;border-radius:6px}
|
|
183
|
+
|
|
184
|
+
.topbar{max-width:var(--maxw);margin:0 auto;padding:.6rem 1rem;display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
|
|
185
|
+
body:not(.dbg) .topbar{display:none} /* título da PÁGINA só em ?debug=true (o jogo já mostra no splash); recupera a vertical */
|
|
186
|
+
.title{font-size:1.3rem;margin:0}
|
|
187
|
+
.ver{color:var(--ink-soft);font-weight:400;font-size:.9rem}
|
|
188
|
+
.badge{margin:0;color:var(--accent-ink);background:var(--accent);border-radius:999px;padding:.2em .8em;font-weight:700;font-size:.8rem}
|
|
189
|
+
|
|
190
|
+
.hud{max-width:var(--maxw);margin:0 auto;padding:0 1rem .5rem;display:flex;gap:1.5rem;flex-wrap:wrap}
|
|
191
|
+
.hud__item{margin:0;font-size:1.05rem}
|
|
192
|
+
/* moedas/missão/poder migraram para dentro da tela de cada jogador; ficam sr-only (leitor de tela) */
|
|
193
|
+
.hud__item--sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
194
|
+
/* HUD por jogador SOBRE o canvas (DOM = alta definição, não pixela). Um por viewport; moedas na 1ª coluna, poder na 2ª. */
|
|
195
|
+
#game-hud{position:absolute;inset:0;pointer-events:none;z-index:4;font-family:var(--font);font-size:var(--hud-fs,14px);font-weight:800}
|
|
196
|
+
/* "Tela do jogador": um contêiner por jogador (posicionado na fatia do viewport dele). Hospeda HUD, e nas
|
|
197
|
+
próximas etapas a pausa e os menus daquele jogador. O render segue compartilhado (um contexto WebGL). */
|
|
198
|
+
.player-screen{position:absolute;pointer-events:none}
|
|
199
|
+
.vphud{position:absolute;top:0;left:0;width:100%;display:flex;align-items:flex-start;gap:0;padding:.4em .55em;box-sizing:border-box;color:#fff;text-shadow:0 1px 2px #000,0 0 3px #000,0 0 6px #000;line-height:1.15}
|
|
200
|
+
.vphud-obj,.vphud-power{flex:1 1 50%;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
201
|
+
.vphud-ico{font-weight:400}
|
|
202
|
+
/* jogador que saiu (MP): viewport preto com "Jogo abandonado" no centro; os outros seguem */
|
|
203
|
+
.vphud-quit{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#000;color:#cdd6f2;font-family:var(--font);font-weight:800;font-size:var(--hud-fs,14px);text-align:center}
|
|
204
|
+
.vphud-quit[hidden]{display:none}
|
|
205
|
+
/* PAUSA dentro do canvas (tela = canvas) — sobreposta ao #game-region, não à página */
|
|
206
|
+
.pause-incanvas{position:absolute;inset:0;z-index:6;display:flex;align-items:center;justify-content:center;background:var(--bg-solid);font-family:var(--font)}
|
|
207
|
+
.pause-incanvas[hidden]{display:none}
|
|
208
|
+
/* Etapa 2: menu de pausa POR TELA (dentro de cada .player-screen). Cada jogador vê e navega o seu. */
|
|
209
|
+
.screen-pause{position:absolute;inset:0;z-index:6;display:flex;align-items:center;justify-content:center;background:var(--bg-solid);font-family:var(--font);font-size:var(--ui-fs,16px);pointer-events:auto} /* base = --ui-fs (16 no mínimo, escala com o canvas) */
|
|
210
|
+
.screen-pause[hidden]{display:none}
|
|
211
|
+
.screen-pause .pause-card{max-width:94%;max-height:98%;padding:.5rem .7rem}
|
|
212
|
+
.screen-pause .pause-card h2{font-size:1.2em;margin:.05rem 0 .28rem}
|
|
213
|
+
.screen-pause .pause-menu{gap:.3rem}
|
|
214
|
+
/* O quadro por jogador aperta o PADDING, nunca a altura mínima: o quadro apertado é o do jogo com quatro
|
|
215
|
+
crianças, onde os dedos disputam espaço — o pior lugar possível para encolher um alvo de toque. O cartão
|
|
216
|
+
tem `overflow:auto` e rola; o botão não diminui. */
|
|
217
|
+
.screen-pause .pm-btn{padding:.3rem .7rem}
|
|
218
|
+
.screen-pause .pause-legend{margin:.28rem 0 0}
|
|
219
|
+
/* Atalhos de a11y = botões do menu em forma de ícone, DENTRO do card (sem barra/sombra própria).
|
|
220
|
+
Navegáveis por teclado (cima a partir de Continuar) e por toque/clique. */
|
|
221
|
+
.pause-icons{display:flex;flex-wrap:wrap;gap:.4rem;justify-content:center;align-items:center;margin:.1rem 0 .35rem}
|
|
222
|
+
/* ===================== A BARRA RÁPIDA NO HUD (ADR-0044, item 7) =====================
|
|
223
|
+
Ela saiu do cartão de pausa e passou a viver na tela do jogador, disponível DURANTE a partida — que é
|
|
224
|
+
quando uma criança precisa mudar um ajuste que está a atrapalhando, e não depois de pausar.
|
|
225
|
+
|
|
226
|
+
É IRMÃ da `.screen-exp` e não filha, e a razão é o #82: `filter` de CSS desce para os descendentes e um
|
|
227
|
+
filho não consegue cancelá-lo. Dentro da experiência, o modo empatia degradaria justamente o que existe
|
|
228
|
+
para DAR acesso — e simulação não é acessibilidade, é o contrário dela.
|
|
229
|
+
|
|
230
|
+
`pointer-events:auto` porque a `.player-screen` inteira é `none` (o jogo recebe o toque); os dez ícones
|
|
231
|
+
são a exceção, como o cartão de pausa já era. */
|
|
232
|
+
/* A ALTURA DA BARRA, num token: é ela que empurra o HUD para baixo. Sem isto os dois ficavam ancorados no
|
|
233
|
+
topo e se sobrepunham — o HUD lido por cima dos ícones, que foi o que o Dev viu e chamou de péssimo. */
|
|
234
|
+
.player-screen{--a11y-h:calc(var(--tap) + .5rem)}
|
|
235
|
+
.screen-a11y{position:absolute;left:0;right:0;top:0;height:var(--a11y-h);z-index:5;pointer-events:auto;font-family:var(--font);font-size:var(--ui-fs,16px)}
|
|
236
|
+
.screen-a11y .pause-icons{flex-wrap:nowrap;white-space:nowrap;gap:.25rem;margin:0;height:100%}
|
|
237
|
+
/* SÓ OS BOTÕES OCUPAM ESPAÇO. A explicação é ABSOLUTA e fica fora do fluxo — ela aparece por cima do jogo ao
|
|
238
|
+
passar o mouse (ou quando o cursor do modo `accessibility` pousa num ícone) e some sem deixar buraco. Uma
|
|
239
|
+
faixa de texto reservando altura na tela de jogo é o contrário do que uma barra de atalho serve. */
|
|
240
|
+
.screen-a11y .pause-icons-cap{position:absolute;left:50%;transform:translateX(-50%);top:calc(var(--a11y-h) + .1rem);margin:0;max-width:92%;text-align:center;font-size:.8em;color:#f6f5f0;pointer-events:none}
|
|
241
|
+
.screen-a11y .pause-icons-cap:not(:empty){background:rgba(8,8,16,.92);border-radius:8px;padding:.2em .6em}
|
|
242
|
+
/* O HUD desce para DEBAIXO da barra. É a mesma conta, e é por isso que ela mora num token: as duas medidas
|
|
243
|
+
não podem divergir sem que uma tape a outra. */
|
|
244
|
+
.screen-exp .vphud{top:var(--a11y-h)}
|
|
245
|
+
.pi-btn{width:var(--tap);height:var(--tap);min-width:var(--tap);min-height:var(--tap);border-radius:10px;border:2px solid var(--ink-soft);background:#1a2740;font-size:1.25em;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
|
|
246
|
+
/* Wizard de gamepad: demonstração com ANIMAÇÃO REAL (frames do jogo trocados via JS) + deslocamento CSS */
|
|
247
|
+
#padwiz-demo{height:86px;display:flex;align-items:flex-end;justify-content:center;position:relative;margin:.15rem 0 .4rem;overflow:hidden}
|
|
248
|
+
#padwiz-demo-img{height:64px;image-rendering:pixelated}
|
|
249
|
+
#padwiz-demo-fx{position:absolute;top:2px;font-size:1.5em;line-height:1}
|
|
250
|
+
#padwiz-demo.pw-left #padwiz-demo-img{animation:pwSlideL 1.4s linear infinite}
|
|
251
|
+
#padwiz-demo.pw-right #padwiz-demo-img{animation:pwSlideR 1.4s linear infinite}
|
|
252
|
+
#padwiz-demo.pw-up #padwiz-demo-img{animation:pwClimbUp 1.4s linear infinite}
|
|
253
|
+
#padwiz-demo.pw-down #padwiz-demo-img{animation:pwClimbDown 1.4s linear infinite}
|
|
254
|
+
#padwiz-demo.pw-jump #padwiz-demo-img{animation:pwJump .9s cubic-bezier(.3,0,.7,1) infinite}
|
|
255
|
+
#padwiz-demo.pw-run #padwiz-demo-img{animation:pwSlideR .8s linear infinite}
|
|
256
|
+
#padwiz-demo.pw-swap,#padwiz-demo.pw-start{align-items:center}
|
|
257
|
+
#padwiz-demo.pw-swap #padwiz-demo-fx{position:static;white-space:nowrap;font-size:1.7em;animation:pwIcons 4s linear infinite}
|
|
258
|
+
#padwiz-demo.pw-especial #padwiz-demo-fx{animation:pwPulse .8s ease-in-out infinite}
|
|
259
|
+
#padwiz-demo.pw-start #padwiz-demo-fx{position:static;font-weight:800;font-size:1.9em;letter-spacing:.1em;animation:pwBlink 1s steps(2,end) infinite}
|
|
260
|
+
@keyframes pwSlideL{0%{translate:34px 0}100%{translate:-34px 0}}
|
|
261
|
+
@keyframes pwSlideR{0%{translate:-34px 0}100%{translate:34px 0}}
|
|
262
|
+
@keyframes pwClimbUp{0%{translate:0 22px}100%{translate:0 -22px}}
|
|
263
|
+
@keyframes pwClimbDown{0%{translate:0 -22px}100%{translate:0 22px}}
|
|
264
|
+
@keyframes pwJump{0%,100%{translate:0 0}35%{translate:0 -26px}55%{translate:0 -22px}}
|
|
265
|
+
@keyframes pwIcons{0%{translate:60px 0}100%{translate:-60px 0}}
|
|
266
|
+
@keyframes pwPulse{0%,100%{scale:1;opacity:.7}50%{scale:1.5;opacity:1}}
|
|
267
|
+
@keyframes pwBlink{0%,100%{opacity:1}50%{opacity:.25}}
|
|
268
|
+
@media (prefers-reduced-motion: reduce){ #padwiz-demo *{animation:none !important} }
|
|
269
|
+
.pi-btn.pi-on{background:var(--accent);border-color:var(--accent)}
|
|
270
|
+
/* Modo TEA (🧩): pi-on preenchido de amarelo = silencioso · fundo branco = calmo · base (azul) = off.
|
|
271
|
+
(fundo, não borda — a borda é reservada ao realce de seleção :focus/.pi-sel e sobreporia o sinal.) */
|
|
272
|
+
.pi-btn.pi-calm{background:#fff;border-color:var(--ink-soft)}
|
|
273
|
+
/* Correção de daltonismo (🚥): fundo bicolor "diagnóstico" — pares escolhidos por busca (simulação Machado
|
|
274
|
+
2009, ΔE Lab) p/ que quem TEM a deficiência-alvo veja o maior contraste e as outras duas o menor. Tritan
|
|
275
|
+
(eixo azul-amarelo, isolado) separa limpo com vermelho/verde; protan e deutan compartilham o eixo
|
|
276
|
+
vermelho-verde → separação só PARCIAL (limite físico). off = base (azul, borda cinza); borda clara = ativo. */
|
|
277
|
+
.pi-btn.pi-cvd-protan{background:linear-gradient(90deg,#b3671b 0 50%,#b31b41 50% 100%);border-color:var(--ink)}
|
|
278
|
+
.pi-btn.pi-cvd-deuter{background:linear-gradient(90deg,#0000f2 0 50%,#aa61f2 50% 100%);border-color:var(--ink)}
|
|
279
|
+
.pi-btn.pi-cvd-tritan{background:linear-gradient(90deg,#f23d00 0 50%,#1bb341 50% 100%);border-color:var(--ink)}
|
|
280
|
+
.pi-btn.pi-dis{opacity:.35;cursor:not-allowed}
|
|
281
|
+
.pi-btn.pi-soon{opacity:.55}
|
|
282
|
+
.pi-btn.pi-sel,.pi-btn:focus,.pi-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
|
|
283
|
+
.pause-icons-cap{text-align:center;margin:0 0 .3rem;font-size:.82em;color:var(--ink-soft);min-height:1.1em}
|
|
284
|
+
/* `scrollbar-gutter: stable both-edges` — MEDIDO no navegador depois do item 6: com a lista em 44 px o
|
|
285
|
+
cartão passa a rolar, a barra de rolagem come largura de UM lado só, e a lista centrada saía 7,5 px do
|
|
286
|
+
centro. Reservar a calha nos dois lados devolve a simetria, role ou não. */
|
|
287
|
+
.pause-card{background:#0e1626;border:2px solid #ffd23f;border-radius:14px;padding:.8rem 1rem;max-width:88%;max-height:92%;overflow:auto;scrollbar-gutter:stable both-edges;text-align:center;box-shadow:0 8px 30px rgba(0,0,0,.5)}
|
|
288
|
+
.pause-card h2{margin:.1rem 0 .6rem;color:#ffd23f}
|
|
289
|
+
/* ===================== A LISTA DE PAUSA (ADR-0044, item 6) =====================
|
|
290
|
+
Era `grid-template-columns:1fr 1fr`, e a grade contava a mesma mentira dos submenus da abertura: a seta
|
|
291
|
+
anda em ordem de DOM, então "para baixo" pulava para a coluna da direita. Uma coluna, e o que se vê volta
|
|
292
|
+
a ser a ordem em que se anda.
|
|
293
|
+
CENTRADA E MAIS LARGA: 26rem contra os 262 px medidos antes — o número está no gate, não na opinião.
|
|
294
|
+
`width` e não `min(26rem,100%)`: com a barra de ícones fora do cartão (item 7), o cartão passou a se
|
|
295
|
+
encolher ao conteúdo, e um `100%` medido contra ele virava circular — a lista caiu para 182 px. Quem
|
|
296
|
+
declara a largura é a LISTA; o cartão a acompanha até o `max-width` dele. */
|
|
297
|
+
.pause-menu{display:flex;flex-direction:column;gap:.45rem;width:26rem;max-width:100%;margin:0 auto}
|
|
298
|
+
/* A lista ESCONDIDA tem de sumir de verdade: `display:grid` de autor vence o `[hidden]{display:none}` do
|
|
299
|
+
navegador, e sem esta linha as duas listas do cartão de pausa apareceriam empilhadas (ADR-0044, item 5). */
|
|
300
|
+
.pause-menu[hidden]{display:none}
|
|
301
|
+
/* 44 px NÃO é o mínimo da WCAG — o 2.5.8 pede 24×24, e o cartão já passava nisso com folga. 44 é a
|
|
302
|
+
recomendação da Apple (HIG), e este projeto trata piso como piso. `min-height` e não `padding` porque a
|
|
303
|
+
altura de antes (35,6 px) não estava declarada em lugar nenhum: ela RESULTAVA da soma de padding, fonte e
|
|
304
|
+
entrelinha. Um alvo que ninguém escreveu é um alvo que ninguém defende. */
|
|
305
|
+
.pm-btn{background:#1a2740;color:#eaf2f8;border:1px solid #3a4a6a;border-radius:10px;padding:.5rem .8rem;min-height:44px;display:flex;align-items:center;justify-content:center;font:inherit;font-weight:700;cursor:pointer;white-space:nowrap}
|
|
306
|
+
.pm-btn:hover,.pm-btn:focus,.pm-btn.pm-sel{background:#2a3a5e;border-color:#ffd23f;outline:2px solid #ffd23f;outline-offset:1px}
|
|
307
|
+
/* Legenda sim/não: ícone do botão (conforme layout do controle) + a palavra. Sony/Nintendo invertem 0↔1. */
|
|
308
|
+
.pause-legend{display:flex;gap:1.1rem;justify-content:center;margin:.7rem 0 .1rem;font-size:.82em;color:#c3cfe0}
|
|
309
|
+
.pause-legend .lg{display:inline-flex;align-items:center;gap:.35rem}
|
|
310
|
+
.pause-legend .lg-ico{display:inline-flex;align-items:center;justify-content:center;width:1.35rem;height:1.35rem;border-radius:50%;font-weight:800;font-size:.8rem;color:#fff;text-shadow:0 1px 1px rgba(0,0,0,.55)}
|
|
311
|
+
.hud__item strong{font-variant-numeric:tabular-nums}
|
|
312
|
+
.hud__fps{color:var(--ink-soft)}
|
|
313
|
+
|
|
314
|
+
main{flex:1;display:flex;flex-direction:column;width:100%;margin:0 auto;padding:0 .25rem .25rem;min-height:0;overflow:hidden}
|
|
315
|
+
/* tela = prioridade: ocupa todo o espaço; o excedente (até 5px×k por lado) é cortado sem rolagem */
|
|
316
|
+
.stage-wrap{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:0;overflow:hidden}
|
|
317
|
+
.stage{position:relative;display:flex;align-items:center}
|
|
318
|
+
/* ===== A CAMADA DOM (issue #82) =====
|
|
319
|
+
Tudo o que não é a canvas. Existe para o filtro de acessibilidade poder cair numa superfície que contém os
|
|
320
|
+
MENUS e não contém o mundo — filtro de PIXI não alcança DOM, e filtrar o `#game-region` inteiro aplicaria
|
|
321
|
+
duas vezes na canvas.
|
|
322
|
+
|
|
323
|
+
`pointer-events:none` porque o invólucro cobre a região inteira e não pode engolir clique; os quatro filhos
|
|
324
|
+
que precisam de clique e não o declaravam (herdavam do `#game-region`) ganham `auto` logo abaixo.
|
|
325
|
+
|
|
326
|
+
`z-index:1`: acima da canvas, ABAIXO dos dois pseudo-elementos do CRT (vinheta em 5, scanline em 500), que
|
|
327
|
+
ficam no `#game-region`. O CRT é efeito de tela e passa por cima de tudo — o que a scanline já fazia por
|
|
328
|
+
decisão do Dev, e a vinheta agora acompanha. */
|
|
329
|
+
#dom-layer{position:absolute;inset:0;z-index:1;pointer-events:none}
|
|
330
|
+
|
|
331
|
+
/* ===== ALTO CONTRASTE NO DOM (issue #83) =====
|
|
332
|
+
O alto contraste NÃO é filtro: ele é Renderização Direta, e repinta as TEXTURAS da canvas. No DOM não há
|
|
333
|
+
textura para repintar — há que escrever o equivalente, e é isto.
|
|
334
|
+
|
|
335
|
+
MEDIDO, não estimado (WCAG 1.4.3, razão sobre sRGB linearizado). O que falhava, e só no nível 7:1:
|
|
336
|
+
|
|
337
|
+
· o VÉU do painel de pausa é `rgba(4,7,15,.72)` — translúcido. A razão do texto sobre ele DEPENDE do
|
|
338
|
+
jogo por trás: 19,17:1 sobre um quadro preto e 8,07:1 sobre um branco. Com `--ink-soft`, `--accent` e
|
|
339
|
+
`--good` a conta cai a 5,92 / 5,94 / 5,11:1 — AA, não AAA. Nos níveis 3:1 e 4,5:1 nada falhava.
|
|
340
|
+
· o botão SELECIONADO é `#2a3a5e`, e `--good` sobre ele dá 6,70:1.
|
|
341
|
+
|
|
342
|
+
Duas mudanças, e nenhuma inventa cor:
|
|
343
|
+
|
|
344
|
+
1. O VÉU FICA OPACO. É o que "alto contraste" quer dizer: sai o meio-tom, e com ele a dependência do que
|
|
345
|
+
está atrás. Sozinha, esta já leva tudo a AAA menos um caso.
|
|
346
|
+
2. O CURSOR INVERTE — fundo `--accent`, texto `--accent-ink`, 12,71:1. Escurecer o selecionado o
|
|
347
|
+
aproximaria do não-selecionado (`#1a2740`) e a criança PERDERIA O CURSOR; inverter resolve as duas
|
|
348
|
+
coisas de uma vez, e é o padrão de alto contraste de qualquer sistema operacional.
|
|
349
|
+
|
|
350
|
+
Resultado: o pior par do menu vai de 5,11:1 para 10,29:1 (`--ink-soft` sobre botão). Margem de +47% sobre
|
|
351
|
+
o 7:1. `tests/contraste-menu.node.test.js` afirma isso a cada rodada, com as razões calculadas do próprio
|
|
352
|
+
CSS — não copiadas para dentro do teste.
|
|
353
|
+
|
|
354
|
+
⚠️ VALE PARA OS TRÊS NÍVEIS, e não só para o 7:1: nos outros dois o menu já passava, mas passava POR SORTE
|
|
355
|
+
do que estivesse na tela. Determinismo é ganho em todos. */
|
|
356
|
+
/* (A regra do véu SAIU daqui em 2026-08-26: ele passou a ser opaco NA BASE, por decisão do Dev — os menus
|
|
357
|
+
de título e de pausa têm de estar em 7:1 DESDE O INÍCIO, porque é justamente neles que a pessoa com
|
|
358
|
+
deficiência ajusta os controles para si. Um contraste que só chega depois de achar o ajuste chega tarde.
|
|
359
|
+
Sobra aqui o que é específico do modo: o cursor invertido.) */
|
|
360
|
+
#dom-layer.hc .pm-btn{background:var(--panel-btn)}
|
|
361
|
+
#dom-layer.hc .pm-btn:hover,
|
|
362
|
+
#dom-layer.hc .pm-btn:focus,
|
|
363
|
+
#dom-layer.hc .pm-btn.pm-sel{background:var(--accent);color:var(--accent-ink);border-color:var(--accent-ink)}
|
|
364
|
+
#dom-layer #viz-indicator,#dom-layer .overlay,#dom-layer .quiz,#dom-layer .pause-incanvas{pointer-events:auto}
|
|
365
|
+
|
|
366
|
+
.game-region{position:relative;background:#05070f;box-shadow:0 0 0 3px var(--ink-soft);border-radius:8px;overflow:hidden;flex:none}
|
|
367
|
+
.libras-slot{flex:none;width:0;height:0;background:#0b1020;border-radius:8px;overflow:hidden}
|
|
368
|
+
.game-region:focus-visible{outline:4px solid var(--focus);outline-offset:3px}
|
|
369
|
+
/* ===== O AVISO DE ALCANCE (issue #112) =====
|
|
370
|
+
Reaproveita `.overlay` e `.overlay__card` inteiros — o cartão nasce com a mesma casca dos outros diálogos,
|
|
371
|
+
e é isso que o faz parecer parte do jogo em vez de um erro do navegador. Só o destaque do título é próprio. */
|
|
372
|
+
#reach-notice .reach-notice__titulo{font-weight:700;margin:0 0 .5rem}
|
|
373
|
+
#reach-notice p{margin:0 0 .5rem}
|
|
374
|
+
#reach-notice button{margin-top:.75rem}
|
|
375
|
+
/* ===== O LAÇO PAROU (ADR-0054, issue #109) =====
|
|
376
|
+
O TEXTO VEM DO ATRIBUTO, e é esse o ponto: `ui/loop-crash` escreve a frase JÁ TRADUZIDA em
|
|
377
|
+
`data-incl-parou`, e o CSS só a mostra. Um aviso cravado aqui estaria em inglês para uma criança
|
|
378
|
+
brasileira — o defeito que o pilar 3 existe para impedir.
|
|
379
|
+
⚠️ E AS CORES SÃO CRUAS, DE PROPÓSITO: nada de `var(--…)`. Este aviso aparece justamente quando alguma
|
|
380
|
+
coisa quebrou, e a máquina de temas é candidata plausível. Branco sobre vinho dá 9,5:1, acima do 7:1 do
|
|
381
|
+
1.4.6, e não depende de nada ter sobrevivido. */
|
|
382
|
+
.game-region[data-incl-parou]::after{
|
|
383
|
+
content:attr(data-incl-parou);
|
|
384
|
+
position:absolute;inset:auto 0 0 0;z-index:60;
|
|
385
|
+
padding:14px 18px;
|
|
386
|
+
background:#7f1d1d;color:#fff;border-top:3px solid #fff;
|
|
387
|
+
font:700 15px/1.35 system-ui,-apple-system,"Segoe UI",sans-serif;
|
|
388
|
+
text-align:center;text-wrap:balance
|
|
389
|
+
}
|
|
390
|
+
.pixi-mount,.pixi-mount canvas{display:block;width:100%;height:100%}
|
|
391
|
+
/* pixel-art nítida ao escalar */
|
|
392
|
+
.pixi-mount canvas{image-rendering:pixelated;image-rendering:crisp-edges}
|
|
393
|
+
/* L2: Estética CRT (menu Sensibilidade visual) em 3 níveis: -1=pequeno, -2=grande. z-index 5 = sobre o
|
|
394
|
+
canvas/HUD do jogo, ABAIXO da pausa in-canvas (6) e dos diálogos (60) → menus nunca perdem legibilidade. */
|
|
395
|
+
.game-region.crt-scan-1::after,
|
|
396
|
+
.game-region.crt-vig-1::before{content:'';position:absolute;inset:0;z-index:5;pointer-events:none}
|
|
397
|
+
/* Scanlines ALINHADAS: período = 1 pixel LÓGICO do jogo (k px), arredondado p/ pixel FÍSICO (dpr) e
|
|
398
|
+
linha = 1 pixel físico — o JS (layout/applyCrt) calcula --scan-per/--scan-line; sem isso o gradiente
|
|
399
|
+
1px/3px em px CSS caía fora da grade (linhas desiguais em telas com escala do Windows). */
|
|
400
|
+
.game-region.crt-scan-1::after{z-index:500;background:repeating-linear-gradient(to bottom, rgba(0,0,0,.16) 0 var(--scan-line,1px), transparent var(--scan-line,1px) var(--scan-per,3px))} /* z-index alto = scanlines POR CIMA de tudo (canvas E menus DOM), pedido do José */
|
|
401
|
+
.game-region.crt-vig-1::before{background:radial-gradient(ellipse at center, transparent 60%, rgba(0,0,0,.34) 100%)}
|
|
402
|
+
.game-region.crt-round-0{border-radius:0} /* tela quadrada */
|
|
403
|
+
.game-region.crt-round-2{border-radius:24px} /* nível 1 (pequeno) = o padrão de 8px, sem classe */
|
|
404
|
+
@media (prefers-reduced-transparency: reduce){ .game-region.crt-scan-1::after,.game-region.crt-vig-1::before{display:none} }
|
|
405
|
+
|
|
406
|
+
/* dicas de início sobre o canvas */
|
|
407
|
+
.start-tips{position:absolute;left:50%;top:14%;transform:translateX(-50%);
|
|
408
|
+
display:flex;flex-direction:column;gap:.5rem;align-items:center;pointer-events:none;
|
|
409
|
+
transition:opacity .5s ease;z-index:6;max-width:92%}
|
|
410
|
+
.start-tips p{margin:0;background:rgba(5,7,15,.85);color:#fff;border:2px solid rgba(255,255,255,.45);
|
|
411
|
+
border-radius:10px;padding:.4em .9em;font-size:1.05rem;font-weight:600;text-align:center}
|
|
412
|
+
.start-tips kbd{background:var(--accent);color:var(--accent-ink);border-radius:6px;padding:.05em .5em;font-weight:800}
|
|
413
|
+
.start-tips.hide{opacity:0}
|
|
414
|
+
@media (prefers-reduced-motion: reduce){ .start-tips{transition:none} }
|
|
415
|
+
|
|
416
|
+
/* seletor de modo */
|
|
417
|
+
.modes{max-width:var(--maxw);margin:0 auto .5rem;padding:0 1rem;display:flex;gap:.5rem;flex-wrap:wrap}
|
|
418
|
+
.mode-btn{min-height:var(--tap);padding:.4em .9em;font:inherit;font-weight:700;color:var(--ink);background:var(--panel);border:2px solid var(--ink-soft);border-radius:999px;cursor:pointer}
|
|
419
|
+
.mode-btn.is-on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
420
|
+
/* TOGGLE (switch): substitui os botões "ícone + Ligado/Desligado". Estado = trilho + manopla que desliza.
|
|
421
|
+
Semântica de botão de alternância via aria-pressed (o texto interno fica oculto por font-size:0). */
|
|
422
|
+
.mode-btn.switch{--sw-w:52px;--sw-h:28px;position:relative;width:var(--sw-w);min-width:var(--sw-w);height:var(--sw-h);min-height:var(--sw-h);padding:0;flex:0 0 auto;border-radius:999px;border:2px solid var(--ink-soft);background:#0e1326;color:transparent;font-size:0;transition:background .18s,border-color .18s}
|
|
423
|
+
.mode-btn.switch::after{content:"";position:absolute;top:50%;left:3px;transform:translateY(-50%);width:calc(var(--sw-h) - 10px);height:calc(var(--sw-h) - 10px);border-radius:50%;background:var(--ink-soft);transition:left .18s,background .18s}
|
|
424
|
+
.mode-btn.switch[aria-pressed="true"]{background:var(--accent);border-color:var(--accent)}
|
|
425
|
+
.mode-btn.switch[aria-pressed="true"]::after{left:calc(var(--sw-w) - (var(--sw-h) - 10px) - 5px);background:var(--accent-ink)}
|
|
426
|
+
.mode-btn.switch:focus-visible,.mode-btn.switch:focus{outline:3px solid var(--accent);outline-offset:2px}
|
|
427
|
+
@media (prefers-reduced-motion: reduce){ .mode-btn.switch,.mode-btn.switch::after{transition:none} }
|
|
428
|
+
|
|
429
|
+
/* desafio Soma-Sub (overlay sobre o canvas) */
|
|
430
|
+
.quiz{position:absolute;inset:0;z-index:12;display:grid;place-items:center;background:rgba(0,0,0,.55)}
|
|
431
|
+
.quiz-box{position:relative;background:#14141f;color:var(--ink);border:3px solid var(--accent);border-radius:12px;padding:1rem 1.1rem;max-width:90%;text-align:center}
|
|
432
|
+
/* 3 luzes de progresso (canto sup. direito): apagada = cinza; acesa = amarela com luz acesa em volta */
|
|
433
|
+
.quiz-wins{position:absolute;top:.5rem;right:.6rem;display:flex;gap:.4rem}
|
|
434
|
+
.qw-dot{width:.95rem;height:.95rem;border-radius:50%;background:#3a4152;border:2px solid #0d0d1a}
|
|
435
|
+
.qw-dot.on{background:var(--accent);border-color:#8a6d00;box-shadow:0 0 .55rem .12rem var(--accent)} /* iluminação em volta (luz acesa) */
|
|
436
|
+
.quiz-wins.celebrate .qw-dot.on{animation:qwPop .6s ease}
|
|
437
|
+
@keyframes qwPop{0%{transform:scale(1)}45%{transform:scale(1.4);box-shadow:0 0 .9rem .3rem var(--accent)}100%{transform:scale(1)}}
|
|
438
|
+
@media (prefers-reduced-motion:reduce){ .quiz-wins.celebrate .qw-dot.on{animation:none} }
|
|
439
|
+
.quiz-shape{color:var(--accent);font-weight:800;text-transform:capitalize}
|
|
440
|
+
.quiz-prob{font-size:1.6rem;font-weight:800;margin:.4rem 0 .8rem}
|
|
441
|
+
.quiz-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.4rem}
|
|
442
|
+
.quiz-choice{min-height:var(--tap);min-width:var(--tap);font:inherit;font-size:1.2rem;font-weight:700;color:var(--ink);background:#131a30;border:2px solid var(--ink-soft);border-radius:8px;cursor:pointer}
|
|
443
|
+
.quiz-choice.sel{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
444
|
+
.quiz-choice.reveal{outline:3px solid var(--good);outline-offset:2px}
|
|
445
|
+
.quiz-hint{font-size:.85rem;margin-top:.6rem;color:var(--ink-soft)}
|
|
446
|
+
.quiz-emoji{font-size:2.4rem;line-height:1}
|
|
447
|
+
/* Palavra do topo = emoji SELECIONÁVEL (pular sobre ela repete a fala / VLibras gesticula) */
|
|
448
|
+
.quiz-word{font-size:2.4rem;line-height:1;background:transparent;border:2px solid transparent;border-radius:12px;padding:.05em .2em;cursor:pointer}
|
|
449
|
+
.quiz-word.sel{border-color:var(--accent);background:rgba(255,230,0,.12)}
|
|
450
|
+
.quiz-letter{font-size:.8rem;color:var(--ink-soft);margin:.1rem 0 .4rem}
|
|
451
|
+
.silaba-boxes{display:flex;gap:.4rem;justify-content:center;margin-bottom:.5rem}
|
|
452
|
+
.silaba-box{min-width:34px;min-height:28px;border:2px dashed var(--ink-soft);border-radius:6px;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:1.15rem}
|
|
453
|
+
.silaba-box.filled{border-style:solid;border-color:var(--accent);background:rgba(255,255,255,.08)}
|
|
454
|
+
.silaba-actions{display:flex;gap:.4rem;justify-content:center;margin-top:.4rem}
|
|
455
|
+
/* E8: cela Braille */
|
|
456
|
+
.bcells{display:flex;gap:.5rem;justify-content:center;flex-wrap:wrap;margin:.4rem 0}
|
|
457
|
+
.bcell{display:flex;flex-direction:column;align-items:center;gap:.2rem}
|
|
458
|
+
.bcell-grid{display:grid;grid-template-columns:repeat(2,10px);grid-auto-rows:10px;gap:3px;padding:4px;background:#0e1326;border:1px solid var(--ink-soft);border-radius:4px}
|
|
459
|
+
.bdot{width:10px;height:10px;border-radius:50%;background:#2a2f45}
|
|
460
|
+
.bdot.on{background:var(--accent)}
|
|
461
|
+
.bcell-l{font-weight:800}
|
|
462
|
+
@media (prefers-contrast: more){ .quiz-box{background:#000} .quiz-choice{background:#000} .quiz-choice.sel{background:#fff;color:#000} }
|
|
463
|
+
|
|
464
|
+
.opts{max-width:var(--maxw);margin:0 auto .5rem;padding:0 1rem;display:flex;gap:.4rem;flex-wrap:wrap;justify-content:center}
|
|
465
|
+
/* barra de controles compacta → cabe em UMA fileira em telas comuns (não afeta botões de overlay) */
|
|
466
|
+
.opts .mode-btn{padding:.35em .65em;font-size:.92rem;white-space:nowrap}
|
|
467
|
+
.caption{position:absolute;left:50%;bottom:8px;transform:translateX(-50%);background:rgba(0,0,0,.82);color:#fff;
|
|
468
|
+
border:2px solid rgba(255,255,255,.5);border-radius:8px;padding:.25em .7em;font-weight:700;font-size:.95rem;
|
|
469
|
+
z-index:8;pointer-events:none;max-width:90%;opacity:0;transition:opacity .15s}
|
|
470
|
+
.caption.show{opacity:1}
|
|
471
|
+
@media (prefers-reduced-motion: reduce){ .caption{transition:none} }
|
|
472
|
+
|
|
473
|
+
.help{max-width:var(--maxw);margin:1rem auto 0;color:var(--ink-soft)}
|
|
474
|
+
.help summary{cursor:pointer;font-weight:700;color:var(--ink);min-height:var(--tap);display:flex;align-items:center}
|
|
475
|
+
.help ul{padding-left:1.1rem}
|
|
476
|
+
.help li{margin:.3rem 0}
|
|
477
|
+
|
|
478
|
+
.btn{min-height:var(--tap);min-width:var(--tap);padding:.5em 1em;font:inherit;font-weight:600;color:var(--ink);background:var(--panel);border:2px solid var(--ink-soft);border-radius:10px;cursor:pointer}
|
|
479
|
+
.btn--primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
480
|
+
|
|
481
|
+
.overlay{position:fixed;inset:0;z-index:50;display:grid;place-items:center;background:rgba(0,0,0,.7);padding:1rem}
|
|
482
|
+
/* "tela = canvas": os diálogos de a11y são reparentados para dentro do #game-region (JS) e ficam
|
|
483
|
+
presos aos limites do canvas; o último aberto sobe (z-index via JS). Só afeta os que estão dentro. */
|
|
484
|
+
#game-region .overlay{position:absolute;z-index:60;padding:.6rem}
|
|
485
|
+
#game-region .overlay__card{max-height:94%;max-width:96%}
|
|
486
|
+
/* Rodapé de explicação: branco sobre preto translúcido 0,82 → contraste do branco >7:1 mesmo sobre 100% branco
|
|
487
|
+
(composição: 1-0,82=0,18 → L≈0,027 → ~13:1), sem ser 100% opaco. Fixo no rodapé do card. */
|
|
488
|
+
.opt-explain{position:sticky;bottom:calc(-1 * var(--card-pad,1.5rem));margin:.8rem calc(-1 * var(--card-pad,1.5rem)) calc(-1 * var(--card-pad,1.5rem));padding:.6rem .9rem;min-height:2.8rem;display:flex;align-items:center;text-align:left;
|
|
489
|
+
background:rgba(0,0,0,.82);color:#fff;font-size:.9em;line-height:1.35;border-top:1px solid rgba(255,255,255,.18);border-radius:0 0 9px 9px;backdrop-filter:blur(1px)}
|
|
490
|
+
#game-region .overlay__actions{position:static;background:transparent;padding:.5rem 0 0;margin:0}
|
|
491
|
+
#visual{background:rgba(0,0,0,.28);align-items:start;padding-top:3.5rem} /* cor: fundo translúcido p/ ver o efeito imediato no jogo */
|
|
492
|
+
|
|
493
|
+
/* Indicador de simulação (canto sup. dir.): branca=cegueira, verde=baixa visão. Duplo toque volta ao normal. */
|
|
494
|
+
#viz-indicator{position:absolute;top:6px;right:6px;z-index:20;width:16px;height:16px;border-radius:50%;border:2px solid rgba(0,0,0,.6);padding:0;cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.7)} /* DENTRO do canvas (game-region) — funciona como botão */
|
|
495
|
+
#viz-indicator.blind{background:#fff}
|
|
496
|
+
#viz-indicator.low{background:#36d36a}
|
|
497
|
+
/* Baixa visão — 5 simulações (desfoque vem do filter na canvas; aqui só os overlays) */
|
|
498
|
+
#viz-overlay{position:absolute;inset:0;z-index:8;pointer-events:none}
|
|
499
|
+
#viz-overlay.lv-blur{background:none} /* miopia/astigmatismo: só desfoque */
|
|
500
|
+
#viz-overlay.lv-haze{background:rgba(244,246,250,.42)} /* catarata: película esbranquiçada */
|
|
501
|
+
#viz-overlay.lv-tunnel{background:radial-gradient(circle at 50% 50%, transparent 0 15%, rgba(0,0,0,.55) 27%, rgba(0,0,0,.99) 42%)} /* glaucoma: visão de túnel */
|
|
502
|
+
#viz-overlay.lv-macular{background:radial-gradient(circle at 50% 50%, rgba(12,12,15,.95) 0 10%, rgba(12,12,15,.55) 17%, transparent 28%)} /* degeneração macular: borrão central */
|
|
503
|
+
#viz-overlay.lv-diabetic{background: /* retinopatia diabética: manchas dispersas */
|
|
504
|
+
radial-gradient(circle at 22% 30%, rgba(10,10,14,.95) 0 4%, transparent 11%),
|
|
505
|
+
radial-gradient(circle at 64% 22%, rgba(10,10,14,.9) 0 3%, transparent 9%),
|
|
506
|
+
radial-gradient(circle at 80% 58%, rgba(10,10,14,.95) 0 5%, transparent 12%),
|
|
507
|
+
radial-gradient(circle at 40% 70%, rgba(10,10,14,.9) 0 4%, transparent 10%),
|
|
508
|
+
radial-gradient(circle at 16% 80%, rgba(10,10,14,.85) 0 3%, transparent 9%),
|
|
509
|
+
radial-gradient(circle at 54% 48%, rgba(10,10,14,.8) 0 3%, transparent 8%)}
|
|
510
|
+
/* Cegueira total: a canvas vira preta (filter brightness(0)); escondemos HUD e controles na tela */
|
|
511
|
+
body.blind-mode .hud, body.blind-mode #touch-controls, body.blind-mode #start-tips, body.blind-mode #caption{visibility:hidden}
|
|
512
|
+
[hidden]{display:none!important}
|
|
513
|
+
/* CAIXA ALTA (menu de CAA, ADR-0028). O jogo tem DOIS caminhos de texto e por isso dois mecanismos, que não
|
|
514
|
+
são redundância: o `disp()` do main.js cobre o que a PIXI desenha na canvas, e esta regra cobre o que o
|
|
515
|
+
navegador desenha no DOM — menus, HUD, legendas. O botão só ligava o primeiro, então a criança escolhia
|
|
516
|
+
"maiúsculas" e os menus continuavam mistos.
|
|
517
|
+
`text-transform` e NÃO transformar o texto: o conteúdo acessível fica intacto, e um leitor de tela não passa
|
|
518
|
+
a soletrar letra por letra, que é o que ALL CAPS de verdade provoca em NVDA/JAWS. */
|
|
519
|
+
/* Alternativas do quiz (segundo consumidor): altura mínima em MILÍMETROS REAIS, calculada por
|
|
520
|
+
`input/touch.padPxPerMm` — WCAG 2.5.5 / GAG. O valor chega em `--quiz-alt-min`. */
|
|
521
|
+
.quiz-alt{min-height:var(--quiz-alt-min,44px);display:block;width:100%;margin:.25rem 0}
|
|
522
|
+
.quiz-alts{display:flex;flex-direction:column;gap:.25rem}
|
|
523
|
+
:root[data-letras="upper"] body,
|
|
524
|
+
:root[data-letras="upper"] button,
|
|
525
|
+
:root[data-letras="upper"] select,
|
|
526
|
+
:root[data-letras="upper"] option,
|
|
527
|
+
:root[data-letras="upper"] input,
|
|
528
|
+
:root[data-letras="upper"] textarea{text-transform:uppercase}
|
|
529
|
+
/* Os controles de formulário estão na lista porque a folha do NAVEGADOR lhes impõe `text-transform:none`, e
|
|
530
|
+
`none` numa regra do UA vence a herança. Sem eles a caixa alta pegava no texto das telas e falhava em cada
|
|
531
|
+
BOTÃO — que é justamente onde os rótulos dos menus moram. Foi o que o Dev viu: "não torna todas as letras
|
|
532
|
+
do menu maiúsculas". */
|
|
533
|
+
/* menus nunca ultrapassam a tela: limitados à altura do viewport e roláveis (rodapé de ações fica fixo embaixo) */
|
|
534
|
+
.overlay__card{background:var(--panel);border:3px solid var(--accent);border-radius:12px;padding:1.5rem;max-width:420px;width:100%;text-align:center;font-size:var(--ui-fs,16px);
|
|
535
|
+
max-height:92dvh;overflow-y:auto;overscroll-behavior:contain} /* base = --ui-fs (16 mín, escala com o canvas); internos em em */
|
|
536
|
+
.overlay__card h2{margin-top:0}
|
|
537
|
+
.topbar__right{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
|
|
538
|
+
.title-card{text-align:center}
|
|
539
|
+
.title-big{font-size:2rem;margin:.2rem 0;color:var(--accent)}
|
|
540
|
+
.title-by{color:var(--ink-soft);margin:.2rem 0 1rem}
|
|
541
|
+
.title-card .btn{margin-top:.4rem;font-size:1.1rem;padding:.6em 1.6em}
|
|
542
|
+
.overlay__actions{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:1rem;justify-content:flex-end;
|
|
543
|
+
position:sticky;bottom:-1.5rem;background:var(--panel);padding:.6rem 0 1.5rem;margin-bottom:-1.5rem}
|
|
544
|
+
.opt-hint{color:var(--ink-soft);font-size:.9em;margin:.2rem 0 .8rem}
|
|
545
|
+
.panel-sub{text-align:left;font-size:1rem;margin:1rem 0 .4rem;border-bottom:1px solid var(--accent);padding-bottom:.2rem}
|
|
546
|
+
.panel-sub:first-of-type{margin-top:.4rem}
|
|
547
|
+
.panel-sub__tag{color:var(--ink-soft);font-size:.78em;font-weight:400}
|
|
548
|
+
.vol{width:140px;max-width:45%;accent-color:var(--accent);height:1.5rem;cursor:pointer} /* barra de volume (range) */
|
|
549
|
+
/* Caixas de seleção com a IDENTIDADE do jogo: fonte escolhida, cores e tamanho (não o estilo do SO) */
|
|
550
|
+
select.vol, .overlay__card select, .ctrl-col select{
|
|
551
|
+
font-family:var(--font);font-size:.95em;font-weight:600;color:var(--ink);
|
|
552
|
+
width:auto;max-width:100%;height:auto;min-height:var(--tap);
|
|
553
|
+
background:#0e1326;border:2px solid var(--ink-soft);border-radius:8px;
|
|
554
|
+
padding:.35em 2em .35em .7em;cursor:pointer;
|
|
555
|
+
-webkit-appearance:none;-moz-appearance:none;appearance:none;
|
|
556
|
+
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23ffd23f' stroke-width='2' stroke-linecap='round'/></svg>");
|
|
557
|
+
background-repeat:no-repeat;background-position:right .7em center}
|
|
558
|
+
select.vol:focus, .overlay__card select:focus{outline:3px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
|
|
559
|
+
.overlay__card select option{background:#0e1326;color:var(--ink);font-weight:600}
|
|
560
|
+
.ctrl-players{display:flex;gap:.4rem;flex-wrap:wrap;justify-content:center;margin-bottom:.7rem}
|
|
561
|
+
.ctrl-players .mode-btn{padding:.3em .7em;font-size:.95rem}
|
|
562
|
+
.ctrl-list{display:flex;flex-direction:column;gap:.45rem;text-align:left}
|
|
563
|
+
.ctrl-row{display:flex;align-items:center;justify-content:space-between;gap:.6rem;background:#0e1326;border:2px solid var(--ink-soft);border-radius:8px;padding:.4rem .6rem}
|
|
564
|
+
/* ADR-0029 — SAIU DO PADRÃO. Dois canais visuais no mesmo lugar: a COR da moldura e a FORMA, que é uma
|
|
565
|
+
moldura DUPLA (borda, respiro, anel). O anel transparente de 2px revela o fundo do próprio elemento e é o
|
|
566
|
+
que cria o respiro; sem ele os dois anéis colariam e viraria só uma borda mais grossa — uma diferença de
|
|
567
|
+
espessura que ninguém percebe sem ter o não-marcado ao lado para comparar. A contagem de anéis sobrevive a
|
|
568
|
+
escala de cinza, a daltonismo e a toda paleta do jogo, porque não é uma matiz. */
|
|
569
|
+
.is-changed{border-color:var(--changed)!important;box-shadow:inset 0 0 0 2px transparent,inset 0 0 0 4px var(--changed)}
|
|
570
|
+
/* A marca CEDE ao foco: perder o lugar é pior que perder uma dica. */
|
|
571
|
+
.is-changed:focus-visible,.is-changed:focus{box-shadow:none}
|
|
572
|
+
.ctrl-row kbd{background:var(--ink);color:var(--bg);border-radius:5px;padding:.05em .45em;font-weight:700}
|
|
573
|
+
.ctrl-row.row-off{opacity:.42} /* item desabilitado (ex.: modo de teclado indisponível) = só cinza claro, sem texto extra */
|
|
574
|
+
.ctrl-row .mode-btn[disabled]{cursor:not-allowed;opacity:.7}
|
|
575
|
+
.ctrl-row.ctrl-col{flex-direction:column;align-items:stretch;gap:.4rem}
|
|
576
|
+
.ctrl-row.ctrl-col label{font-weight:700}
|
|
577
|
+
.pad-presets{display:flex;gap:.5rem;flex-wrap:wrap}
|
|
578
|
+
.pad-tag{font-size:.8rem;font-weight:700;padding:.05em .5em;border-radius:999px;background:#20304e;color:#bcd}
|
|
579
|
+
.pad-tag[data-who="crianca"]{background:#2a4a2e;color:#bfe9c2}
|
|
580
|
+
.pad-tag[data-who="adulto"]{background:#2a3a5e;color:#c3d4f0}
|
|
581
|
+
.pad-warn{font-size:.85rem;color:#ffdf9e;background:#3a2e12;border:1px solid #6a5220;border-radius:8px;padding:.45rem .6rem}
|
|
582
|
+
.ctrl-col input[type=range]{width:100%;min-height:var(--tap);accent-color:var(--accent)}
|
|
583
|
+
|
|
584
|
+
/* E13: controles de toque (mobile) — overlay nas bordas inferiores, não cobre o centro */
|
|
585
|
+
.touch{position:absolute;inset:auto 0 0 0;z-index:14;display:flex;justify-content:space-between;align-items:flex-end;gap:8px;padding:6px 8px;pointer-events:none}
|
|
586
|
+
.touch-pad{display:flex;gap:8px;pointer-events:auto}
|
|
587
|
+
.touch-btn{width:56px;height:56px;min-width:var(--tap);min-height:var(--tap);border-radius:12px;border:2px solid rgba(255,255,255,.75);background:rgba(13,17,32,.92);color:#fff;font-size:1.4rem;font-weight:800;line-height:1;display:flex;align-items:center;justify-content:center;touch-action:none;-webkit-user-select:none;user-select:none;cursor:pointer}
|
|
588
|
+
.touch-btn:active{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
589
|
+
.touch-jump{background:rgba(18,74,52,.94)}
|
|
590
|
+
/* Botões de ação em LOSANGO (4 bolhas: 0 baixo, 1 direita, 2 esquerda, 3 cima) + START pílula */
|
|
591
|
+
.touch-actions{align-items:center}
|
|
592
|
+
/* Tamanho FÍSICO (mm), não px: --pad-btn e --pad-diam são calculados no JS a partir de mm reais
|
|
593
|
+
(referência: iPhone 16 ocupando a tela toda). Config em A12e motora. Fallback antes do JS rodar. */
|
|
594
|
+
.pad-diamond{position:relative;width:var(--pad-diam,182px);height:var(--pad-diam,182px);pointer-events:none}
|
|
595
|
+
.pad-b{position:absolute;width:var(--pad-btn,66px);height:var(--pad-btn,66px);border-radius:50%;font-size:calc(var(--pad-btn,66px)*.42);font-weight:800;pointer-events:auto;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center}
|
|
596
|
+
.pad-top{top:0;left:50%;transform:translateX(-50%)}
|
|
597
|
+
.pad-bottom{bottom:0;left:50%;transform:translateX(-50%)}
|
|
598
|
+
.pad-left{left:0;top:50%;transform:translateY(-50%)}
|
|
599
|
+
.pad-right{right:0;top:50%;transform:translateY(-50%)}
|
|
600
|
+
.touch-start{position:absolute;left:50%;bottom:6px;transform:translateX(-50%);min-height:calc(var(--pad-btn,66px)*.7);box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;pointer-events:auto;border-radius:999px;padding:0 22px;font-weight:800;font-size:.82rem;letter-spacing:.08em;background:rgba(13,17,32,.92);color:#fff;border:2px solid rgba(255,255,255,.75);cursor:pointer;z-index:15}
|
|
601
|
+
.touch-start:active{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
602
|
+
/* joystick digital: base (círculo maior) + manopla (círculo menor) */
|
|
603
|
+
/* Direcional (analógico/"alavanca"): base = superfície + deslocamento; manopla = superfície de contato. Ambos em mm (JS). */
|
|
604
|
+
.touch-stick{position:relative;width:var(--stick-base,124px);height:var(--stick-base,124px);border-radius:50%;border:3px solid rgba(255,255,255,.7);background:rgba(13,17,32,.85);touch-action:none;pointer-events:auto;-webkit-user-select:none;user-select:none}
|
|
605
|
+
.touch-knob{position:absolute;left:50%;top:50%;width:var(--stick-knob,58px);height:var(--stick-knob,58px);margin:calc(var(--stick-knob,58px)/-2) 0 0 calc(var(--stick-knob,58px)/-2);border-radius:50%;background:rgba(255,255,255,.88);box-shadow:0 0 0 2px rgba(0,0,0,.45);transition:transform .04s linear;pointer-events:none}
|
|
606
|
+
/* D-pad em cruz (estilo alternativo): 4 braços + miolo; tamanho do braço em mm (JS → --dpad-arm-l/w, --dpad-span) */
|
|
607
|
+
.touch-cross{position:relative;width:var(--dpad-span,120px);height:var(--dpad-span,120px);touch-action:none;pointer-events:auto;-webkit-user-select:none;user-select:none}
|
|
608
|
+
.touch-cross[hidden]{display:none}
|
|
609
|
+
.dpad-arm{position:absolute;display:flex;align-items:center;justify-content:center;background:rgba(13,17,32,.92);border:2px solid rgba(255,255,255,.75);color:rgba(255,255,255,.85);font-size:calc(var(--dpad-arm-w,34px)*.5);line-height:1;pointer-events:none}
|
|
610
|
+
.dpad-arm.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
|
|
611
|
+
.dpad-up,.dpad-down{width:var(--dpad-arm-w,34px);height:var(--dpad-arm-l,42px);left:50%;transform:translateX(-50%)}
|
|
612
|
+
.dpad-left,.dpad-right{height:var(--dpad-arm-w,34px);width:var(--dpad-arm-l,42px);top:50%;transform:translateY(-50%)}
|
|
613
|
+
.dpad-up{top:0;border-radius:8px 8px 0 0;border-bottom:none}
|
|
614
|
+
.dpad-down{bottom:0;border-radius:0 0 8px 8px;border-top:none}
|
|
615
|
+
.dpad-left{left:0;border-radius:8px 0 0 8px;border-right:none}
|
|
616
|
+
.dpad-right{right:0;border-radius:0 8px 8px 0;border-left:none}
|
|
617
|
+
.dpad-center{position:absolute;left:50%;top:50%;width:var(--dpad-arm-w,34px);height:var(--dpad-arm-w,34px);margin:calc(var(--dpad-arm-w,34px)/-2) 0 0 calc(var(--dpad-arm-w,34px)/-2);background:rgba(13,17,32,.92);border:2px solid rgba(255,255,255,.4);pointer-events:none}
|
|
618
|
+
@media (prefers-contrast: more){ .touch-cross .dpad-arm,.dpad-center{background:#000;border-color:#fff} .dpad-arm.on{background:#fff;color:#000} }
|
|
619
|
+
@media (prefers-reduced-motion: reduce){ .touch-knob{transition:none} }
|
|
620
|
+
@media (prefers-contrast: more){ .touch-btn{background:#000;border-color:#fff} .touch-btn:active{background:#fff;color:#000} .touch-stick{background:#000;border-color:#fff} .touch-knob{background:#fff} }
|
|
621
|
+
|
|
622
|
+
@media (max-width:560px){.title{font-size:1.1rem}.hud{gap:1rem}}
|