Opt-in din builder (checkbox music, default off). Orchestrator-only: parintele
detine AudioContext (reutilizeaza beep._ctx); camerele nu stiu de muzica.
- arpegiu pentatonica minora (oscilatoare sine scurte), tempo ~1.8x pe ultimul
minut (legat de _deadline-ul Timer Calm); fara timer -> loop calm fara accelerare
- buton 🎵/🔇 in bara chrome (#btn-music)
- duck pe voce: voiceSay onstart/onend regleaza gain (vocea are prioritate)
- fallback fara AudioContext -> no-op, buton ascuns (zero penalizare)
- porneste la start + resume; stop la showFinale + toggle
- hook test window.__music; exemplu-campanie.html regenerat (ramane opt-in off)
Smoke 30/30 (test nou "muzica ambient": opt-in, start, tempo sub 1 min, duck, toggle).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ceas M:SS in bara chrome a campaniei. Opt-in din builder (camp "Timp limita
(minute)", default 0 = fara; cleanState coerce 0..120).
- porneste exact la "Incepe aventura" (intro necronometrat)
- deadline ABSOLUT in sessionStorage -> resume nu reseteaza ceasul
- sub 1 min -> auriu (.low); expirare -> ingheata 0:00 + marcaj discret
(.expired), jocul curge nestingherit (zero penalizare, stelele raman)
- fara rosu pulsant (public copii) -> reduced-motion safe by default
- exemplu-campanie.html regenerat (ramane fara timer - opt-in, ca vocea)
Fundatie pentru muzica T10 (accelerare sub 1 min) + footer diploma.
Test nou (smoke 29/29): format M:SS, prag auriu, freeze la expirare,
jocul continua dupa expirare, resume pastreaza ceasul.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pasa de igiena (T8/T5/D8). Majoritatea erau deja livrate (persist guard D12,
esc/letter D13, validare 0 puzzle). Reale ramase:
- updateHud arcade/point NU erau identice (arcade: vieti/dusmani/bombe/raza;
point: obiecte). Partea duplicata reala (scor + bara litere castigate) extrasa
in SNIP.hudJs -> hudLetters(isSolved); isSolved(j) difera per motor
(doorsSolved vs solvedFlags). Injectat in ambele; demo-uri regenerate.
- Stil top-level invalid la import: TOP_STYLES guard -> fallback classic + alert;
idem la load din storage corupt. Test nou (smoke 28/28).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Feedback user: nu se aud sunete, raza prea mare, lipsesc powerup-urile.
- sfx(type) WebAudio local in arcade: bomb/explosion/enemy/powerup/death;
beep(ok) din libJS ramane pentru raspuns corect/gresit.
- raza fixa EXPLOSION_RANGE=3 -> bombRange variabil de la BASE_RANGE=1
(Bomberman clasic); maxBombs de la BASE_BOMBS=1.
- powerup-uri: la spargerea cutiei, sansa 0.32 sa cada flacara (raza+1)
sau bomba (bombe+1); ridicate mergand pe ele; HUD arata bombe/raza.
- fix: powerup-ul cadea pe celula cutiei si checkExplosionHits il stergea
instant -> colectez brokenBoxes, drop dupa checkExplosionHits.
Hooks __game: powerups/bombRange/maxBombs/dropPowerupAt. Smoke 27/27.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audit faptic (masurat) pe 5 motoare + campanie. Deja OK din restyle S3:
tap targets (arcade 56x52, classic 44/48, chat 44), contrast (terminal .dim
9.4:1, classic hint 6:1), focus/keyboard (butoane reale, navigare cu sageti).
Reparat:
- reduced-motion (lacune): .confetti display:none in classic + SNIP.baseCss +
campanie; flipin final in SNIP.finalCss (#fOverlay .fword span) + campanie
(#fin-word span); dt-blink in campanie. (pop/flip/shake/bin/tile-pop/tp/
door-glow/crt-flicker erau deja acoperite.) flipin/pop au 'backwards' fill ->
animation:none le revine la starea vizibila, nu raman ascunse.
- tap: overworld dpad 42x42 -> 44x44 (singura tinta sub prag).
- aria: #dots role=group+label; fiecare dot role=img cu aria-label ce reflecta
starea (neinceputa/in curs/rezolvata) via setDot; dpad arcade+overworld cu
aria-label (Sus/Jos/Stanga/Dreapta/Pune bomba); spacere .sp aria-hidden.
Test nou smoke #9c (emulateMedia reducedMotion -> confetti display:none;
tap>=44px pe dpad; aria dinamic pe dots). 26/26. Demo-uri regenerate (terminal
neatins - nu foloseste SNIP base/final).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Feature nou (vocea nu exista deloc). Opt-in via checkbox 'voice' in builder
(off implicit), buton toggle in bara chrome a campaniei (parintele detine).
Voicing orchestrator-only, uniform pe toate 5 motoarele (fara dublu-citit):
povestea la 'Incepe aventura', intrebarea camerei la roomReady, mesajul final.
Edge cases (toate tratate):
- getVoices() gol sincron -> re-citire la onvoiceschanged.
- fara voce ro-* -> vocea default a sistemului (doar u.lang='ro-RO').
- speechSynthesis.cancel() in hideAll() -> fara replici fantoma la schimbarea scenei.
- fara 'speechSynthesis' in window -> buton ascuns, totul no-op.
- window.voiceSay expus pe parinte pt. viitor (replici motoare cu guard typeof).
Bug prins de test: #btn-voice{display:inline-flex} batea UA [hidden] ->
adaugat #btn-voice[hidden]{display:none}.
Test nou smoke #9b (voce opt-in: buton, citeste poveste/intrebare, cancel,
toggle) + asertare buton-ascuns cand voice=false. Suita 25/25. Demo regenerat.
AGENTS.md/TODOS actualizate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Secțiunea ▶ BOARD ACTIV (S1-S4) sus, convenție [ ]→[~]→[x]→[!] citită la
start de sesiune. AGENTS.md root indexează TODOS.md ca board durabil (harness
task list se resetează, ăsta nu). Notat: ipoteza S1 din HANDOFF (beep nedefinit)
pare greșită — beep e definit la escape-builder.html:1725.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>