--- convoy: scanner-desktop-layout brief_number: 3 depends_on: [] recommended_model: composer-2.5-fast model_tier: fast files: - components/scanner/ScannerResultPanel.js - test/components/ScannerResultPanel.test.js cross_brief_commitments: - brief: 6 description: | Brief 6 passes `focusedCard`, `queue`, `isIdentifying`, handlers (`onAddToOwned`, `onAddToList`, `onRescan`), and `commitError`. On successful add, Brief 6 advances `focusedCardId` to the next unprocessed entry and fires `ScannerToast` — this component calls `onAddToOwned` only. --- # Brief 3: Live match inspector rail ## Goal (1 sentence) Build the right-rail `ScannerResultPanel` that inspects the focused cart entry and commits one card via `VOCAB.ADD_TO_MY_COLLECTION`. ## Files in scope (do not edit anything else) - `components/scanner/ScannerResultPanel.js` - `test/components/ScannerResultPanel.test.js` ## Conventions to follow - Import `VOCAB` from `lib/collection-vocabulary.js` — never ship forbidden strings (`forbidden-stale-strings` CI). - Primitives: `GlassSurface`, `Button` from `components/ui`. - Duplicate minimally from `ReviewCardItem.js`: `CONDITION_OPTIONS`, `confidencePercent`, `confidenceRingColor` (do not edit `ReviewCardItem` in this brief). - Confidence captions (Design direction): ≥90% *Excellent match.* · ≥70% *Good match.* · <70% *Low confidence — verify before adding.* - Inspector thumbnail + tiles: solid `--bg-secondary` — **no `backdrop-filter`** on per-card elements. - Empty state: centered muted scan/camera SVG illustration + single line: *Point your camera at a card or upload an image to see a match.* — **no** Upload/Batch CTAs in rail. - Populated: thumbnail, name (`text-lg font-semibold`), set · rarity · collector #, condition `