Hardcoded EXPECTED_CHARS (15k) caused progress to stall at ~20-25% for short statements. Now expected size is derived from input text length. Also emit an explicit 85% event when the LLM stream finishes, and throttle SSE events to 300ms to reduce browser overhead.