Finishes the half this card left open last tick. The shared print composable
existed but the 903-line 100-list wall did not use it, so the card deck lived in
TWO places — I wrote both this flight, and they could already drift.
Two duplicates removed:
printCardDeck now delegates to usePosterPrints, sharing THIS wall's
exportState so the HUD keeps rendering one surface. The bundle
still owns what cannot be shared — fetchListRecords knows the
people-groups API, the selector evaluator and the pg_slugs
special case — and hands it over as the `records` provider. The
preview-only "no API configured" hint is preserved, because the
shared action cannot know about it.
openPrintWindow was a local reimplementation of printInPlace.js — same
off-screen iframe, same doc.write, same autoprint script,
differing only in an unused `title` argument. A FOURTH copy of
one mechanism is how a fix to the blank-first-page behaviour
reaches one caller and not the others. Now a one-line adapter.
★ AND check:share-policy CAUGHT A REGRESSION I HAD CAUSED. Adding the
country-posters two-tab MFE last tick gave that bundle a second ShareButton —
the BUG-UPG100-DOUBLE-SHARE state the 100-list already fixed once. Fixed the
same way the 100-list fixed it: the MAP's button is REMOVED and the MFE header
owns sharing. Removed, not flag-gated — a `v-if="false"` button is dead code
that still reads as an affordance to every reader and every counter, which is
exactly why the gate counts tags rather than renders.
Verified by clicking the REAL button in a browser, not by driving the renderer:
116 cards at 2.5in 3.5in with 116 QR codes, and 3.5in 2.5in when the stock
picker is switched to landscape — so records provider, picker, language, shared
composable and print frame are connected end to end. check:mfe-two-tab still
reports exactly one share affordance on the country-posters MFE.