From 34d18c4152d016b1e1bc5fd02252fb5d537b89fe Mon Sep 17 00:00:00 2001 From: Noah Date: Sat, 9 May 2026 00:56:11 -0700 Subject: [PATCH 1/4] feat(phase-3b T6): voice-note card + single-instance VoiceNotePlayer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the `` placeholder with the full spec surface from `docs/specs/2026-04-19-ui-design/files-inline.md` §Voice note: - Card on `--bg-2` with `--line` border, radius 10 px, 10/12 padding, max-width 420 px (100% on mobile). - 32×32 play / pause IconBtn (`--moss-2` border, switches between `icon_play` / `icon_pause` glyphs added in this commit). - Waveform strip — fixed 24 px tall SVG with 64 bars, `--moss-1` for unplayed and `--moss-2` for played. Peaks come from `AudioContext.decodeAudioData` over the fetched blob; on decode failure (codec unsupported, AudioContext unavailable) the strip stays at the flat 0.05 baseline so the chrome reads as "loading" rather than "broken". - mm:ss / mm:ss timer in the spec mono font / 11 px / `--ink-3`, with `--:--` for the duration until `loadedmetadata` fires. Single-instance playback (`VoiceNotePlayer` in `crates/web/src/voice_note_player.rs`): each card claims the player slot on play and watches the shared signal so a competing claim pauses our `