Add spelling improvements and local Piper TTS
Practice: fire streak badge, first-letter hint on wrong answers, missed-words drill session after practice completes. Test: audio-only mode with listening state before input appears, larger re-read button. Words: definition field (DB migration + admin editor + TTS playback). TTS: replace speechSynthesis with local Piper via /api/tts, WAV cached in data/tts-cache, falls back to browser voice when Piper is not installed. Dockerfile: switched to node:26-slim, installs Piper binary + en_US-lessac-medium voice. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
544469d6c9
commit
6f2281e2a7
8 files changed
+202
-35
No files matched your search
@@ -141,6 +141,34 @@ body {
|
||||
font-size: 2.6rem; font-weight: 800; letter-spacing: 6px; margin: 0.5rem 0;
|
||||
}
|
||||
.countdown { color: var(--muted); }
|
||||
.hint-badge { font-size: 1rem; color: var(--accent-dark); margin: 0.3rem 0 0.5rem; }
|
||||
|
||||
.streak-badge {
|
||||
display: inline-block; margin-left: 0.5rem;
|
||||
background: #fff3cd; color: #7c5200;
|
||||
border-radius: 999px; padding: 0.1rem 0.7rem;
|
||||
font-size: 0.95rem; font-weight: 700;
|
||||
animation: streak-pop 0.3s ease;
|
||||
}
|
||||
@keyframes streak-pop {
|
||||
0% { transform: scale(0.7); opacity: 0; }
|
||||
70% { transform: scale(1.15); }
|
||||
100% { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
|
||||
.test-listening-state {
|
||||
font-size: 1.5rem; font-weight: 700; color: var(--accent);
|
||||
text-align: center; padding: 2rem 0; letter-spacing: 1px;
|
||||
animation: pulse 1s ease-in-out infinite alternate;
|
||||
}
|
||||
@keyframes pulse {
|
||||
from { opacity: 0.6; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
.speak-btn-prominent {
|
||||
font-size: 1.4rem; padding: 0.75rem 2rem; width: 100%; max-width: 340px;
|
||||
display: block; margin: 0 auto 1.25rem;
|
||||
}
|
||||
|
||||
.done-card {
|
||||
background: var(--card); border-radius: var(--radius);
|
||||
@@ -154,6 +182,10 @@ body {
|
||||
font-size: 1.2rem; font-weight: 700; font-family: inherit;
|
||||
background: var(--accent); color: #fff; border: none;
|
||||
border-radius: 12px; padding: 0.7rem 2rem; cursor: pointer; margin-top: 1rem;
|
||||
display: block; width: 100%;
|
||||
}
|
||||
.done-card button.secondary {
|
||||
background: var(--good-bg); color: var(--good); border: 2px solid var(--good);
|
||||
}
|
||||
|
||||
/* ---------- parent dashboard ---------- */
|
||||
|
||||
Reference in new issue
Block a user