Two things the operator hit straight away.
1. Creating a quote parked her on the quote detail page.
She is working through notes one after another, so that pulled her
out of the list for a document she had just reviewed in the modal.
`afterCreate` now defaults to "list": the modal closes, the toast
confirms, and she is back where she was with the row's first slot
now showing the quote number.
2. "Couldn't load this quote's PDF" — blaming a supplier.
The message was right about the failure and wrong about the cause.
The readiness rule existed in TWO places: `quotes-service.ts` for
the send path, `quote-pdf-service.ts` for the PDF route. When the
supplier requirement was dropped I changed one of them and left the
other enforcing it. So a counter note whose lines never had a
supplier could be quoted and sent but never rendered.
Both copies now call one function, `quoteItemReadinessGaps`, so a
third copy cannot appear. Verified in the browser: Q202609631 now
fails with "Every item still needs: cost price, not processed,
selling price" — no supplier — and that quote's line genuinely has
cost 0, selling 0 and is_processed false, so refusing it is correct.
The phantom requirement is gone; the real blockers are named.
`is_processed` is deliberately KEPT. It is the flag that says a
person reviewed the line, and nothing else can set it on a
delivery-note quote — the quote_items update whitelists exclude it.
Dropping it would let a quote go out with lines nobody looked at.
The quotes-service test mock now spreads the real module, so these
tests run against the real rule rather than a stub that could agree
with the implementation while production disagreed.
Full suite 3676 passing, tsc clean, no new lint errors.