fix: mobile menu overlay, speech bubble timing, TTS static file fallback

- Mobile nav menu now overlays content (absolute positioning) instead of
  pushing it down
- Speech bubbles stay visible for minimum 400ms even when TTS resolves
  instantly or fails
- kokoroPlayCached checks audio cache and loads static files even when
  Kokoro worker hasn't loaded — fixes TTS not playing on production
- CORS_ORIGIN env now supports comma-separated origins
- Rename "VIDEO REPLAY" to play icon + "REPLAY"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 11:59:18 +00:00
co-authored by Claude Opus 4.6
parent 1a7ad74859
commit e6b5aa4b9b
5 changed files with 47 additions and 16 deletions
+8 -2
View File
@@ -34,8 +34,14 @@ app.onError((err, c) => {
app.use('*', logger())
// CORS: lock down in production, allow all in dev
const allowedOrigin = process.env.CORS_ORIGIN || '*'
app.use('/api/*', cors({ origin: allowedOrigin }))
// Supports comma-separated origins: CORS_ORIGIN=https://a.com,https://b.com
const corsEnv = process.env.CORS_ORIGIN || '*'
const allowedOrigins = corsEnv === '*' ? '*' : corsEnv.split(',').map(s => s.trim())
app.use('/api/*', cors({
origin: Array.isArray(allowedOrigins)
? (origin) => allowedOrigins.includes(origin) ? origin : allowedOrigins[0]
: allowedOrigins,
}))
// COOP/COEP headers: required for SharedArrayBuffer (Kokoro TTS WASM threading)
app.use('*', async (c, next) => {