* fix(web-shell): prevent queued-prompt loss from drain race
The auto-drain effect popped a queued prompt, called setQueuedPrompts,
then submitted via setTimeout(0). Because the daemon flips streamingState
asynchronously, the setState re-render could re-run the effect and pop a
second prompt before the first registered as streaming — both submitted
back-to-back and the first was lost.
Arm an "awaiting turn start" gate synchronously at pop so the re-run is
blocked until streamingState goes non-idle, released by a dedicated
effect with a safety-net timer for a prompt that never streams (e.g. a
queued slash command). Cleanup no longer cancels/re-queues the pending
submit while the gate is armed.
* feat(web-shell): friendlier Esc interruption + queued-prompt UX
* refactor(web-shell): tidy Esc/queue code per review
Behavior-preserving cleanups addressing review feedback on the Esc-interruption
and queued-prompt changes:
- Remove the now-dead queue.footer i18n key (EN + ZH) and the unreferenced
.queuedHint CSS, orphaned when the Esc-clears-queue behavior was dropped.
- Co-locate the queued-prompt styles in QueuedPromptDisplay.module.css instead
of reaching into the parent App.module.css.
- Make the Esc confirm-window constants the single source of truth: export them
from escapeIntent.ts and drive the countdown-ring duration from one of them
via a CSS custom property.
- Nudge the queue-drain safety net with a dedicated tick counter instead of
cloning queuedPrompts, so it no longer re-renders the composer for a no-op.
- Drop a redundant !compact guard in StatusBar left over from flattening a
ternary.
- Document the pop/gate-arm ordering invariant in the drain effect.