Closing the invoice dialog left the guest stranded: the hold blocks the
room until it expires, and the public booking read-back has no bolt11, so
there was no way back to the invoice — they had to wait out the hold to try
the room again.
Persist each hold's invoice on the device when it is created
(usePendingBooking, localStorage keyed by room, one per room, pruned on
expiry). On the room page, if a live hold exists for it (verified via the
public booking endpoint), show a 'Resume payment' banner that reopens the
invoice from the saved bolt11 and resumes the settlement poll. The saved
entry is cleared when the booking confirms, the hold lapses, or it expires.
Works without an account — the store is the browser's, not the server's.
Verified headlessly against a real hold: the banner shows for a live hold
and resumes to the invoice (QR + amount); an expired hold shows nothing and
is pruned. vue-tsc build passes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>