The deploy gate (all 16 suites back to back) had the timed-run check read 23
where the suite demanded >= 25: under the fake clock the suite's own waits
advance the app's interval, so a loaded machine can tick a few extra seconds
between the card switch and the read. The assertion keeps its meaning - a
fresh budget, not the exhausted card's leftover (~0) - with a looser low end
and a comment explaining why. No app behaviour changed.
The phone (touch) chat chrome carried a 55% flat white veil while every other
Aero surface uses the thin 32% Ask-pill tint, so the header, welcome card and
composer read as plain white on a bright sky. They now use the same flat glass
as the cards, the answer/user bubbles keep 42% for long reading, and the
composer's field is a lighter 42% tile. The shared Aero wash block moved above
the touch media query so its background-image can no longer resurrect the bake
on phones.
The timed run worked but was invisible: the only cue was a small chip among the
streak/XP counters. The chrome pill now draws the countdown along its lower
edge, the chip is bordered (a control, not a stat), turns rose with the bar in
the last ten seconds, and fires one soft haptic tick at ten seconds.
Contrast scan clean on the phone chat in all three themes; activities suite
pins the countdown bar (25 checks). Version 0.6.2, SW v84.
From your notes: the generator now stores a verbatim source quote with every
activity (schema + prompt + a server-side clamp so a chatty model cannot drop a
card), and the feedback panel shows the sentence that carries it with the quote
highlighted green. Decks made before the change, and quotes the model trimmed,
fall back to a local IDF-weighted match over the saved notes text
(lib/notes-source.ts): nothing is shown unless at least two distinct terms
land. The passage hides in exam mode with the other reveals.
Read aloud: a Web Speech API speaker control on the text a learner reads
(flashcard faces, questions, statements, sentences, instructions) via
lib/speech.ts and components/SpeakButton.tsx — one utterance app-wide, a voice
matched to the deck's language, and no button at all where the browser has no
speech synthesis. It used to sit inside the flashcard's flip button (nested
buttons, tapping it flipped the card); it now lives next to the hint row.
Timed runs: the feed chrome carries a timer chip (off by default) that gives
each card 30 seconds; a card that runs out is recorded as a miss through the
same path as a wrong answer (history + SRS agree), shows a toast, and the feed
moves straight on with a fresh budget. handleAnswered ignores a second result
per card, so a timeout plus a manual answer cannot record twice.
The generator's type spec now names what each type suits (language decks lean
on flashcards/matching/fill blank, ordering needs a real sequence, short answer
reasoning), so the deck-aware guidance covers all seven types.
New activities-test suite (24 checks: quote path, local path, the green mark,
the speech stub, the timed run on Playwright's fake clock), registered in
run-all; phase2 pins that the notes passage stays hidden in exam mode; en+cs
keys for every new string; no new dependencies. Version 0.6.1, SW v83.