# W2-FE-6 — S2b: nutrition board as 14 shell cards (classic stays pixel-identical) + products sold (FE, small BE)

Read _COMMON.md first. Review rows: A #8 #18 #45; D N1 N11 (and the S2a comment in VS/specialties/nutrition.cards.ts). Prototype: SPECIALTIES.nutrition (lines 494-502), nutrition renderers in §5 (~802-895, `nut_*`), screenshot 12_nutrition_unchanged.png and 22_nutrition_dialog_picker.png in /tmp/claude-0/-home-moonui3-public-html/dfed8133-fabe-4b29-871f-5f930c91925d/scratchpad/.

## Goal
Today the shell hosts the whole classic `app-nutrition-consult-board` (features/nutrition/visit/nutrition-consult-board.component.*, 600+774+412 lines) as ONE bare card `nut_board`. Split it so each board section is a catalog card the client can move/hide/resize — while the CLASSIC nutrition screen and the shell default stay visually identical to today (owner: the dietitian's board «ما تتحلّش»).

## Approach (must keep one source of truth)
1. Extract each board section into its own standalone component under features/nutrition/visit/cards/ (some already exist: nv-lifestyle-card, nv-sessions-card, nv-progress-card…). Sections → card ids exactly as the prototype: nut_patient, nut_quest, nut_lifestyle, nut_appts, nut_weights, nut_meas, nut_sessions, nut_plan, nut_notes, nut_meds, nut_labs, nut_packages, nut_photos, nut_progress (conditional). Shared board state (patient, visit, loading, dialogs, actions) goes into ONE injectable store/service provided at the board level (e.g. `NutritionBoardStore`, providedIn component) so the classic board AND the shell cards read the same state. The board's header action bar (rx, lab+rad, plan dialog, print plan, note, next appt, stop) becomes its own bare card `nut_actions` (required, F) in the shell, and stays the board header in classic.
2. The classic board component becomes a thin composition of those section components in its existing 3-column grid (same markup classes/order → identical pixels).
3. In the shell (VS/specialties/nutrition.cards.ts): register the 14 (+ nut_actions) CardDefs (kind spec, spec nutrition, sizes per prototype CATALOG lines 448-461, layer per prototype, permissions as the board uses), the store is provided once per shell for the nutrition type (find where spec cards get an injector — VS/cards/spec-slot-host.component.ts — and provide the store at the shell/tab host level so all nutrition cards share one instance per encounter). New default layout `NUTRITION_DEFAULT_LAYOUT`: keep the two tabs; «الكشف» tab = 3 columns `['minmax(250px,290px)','minmax(0,1fr)','minmax(280px,340px)']` with the prototype's card placement (lines 499-502) so it LOOKS like today's board; «البيانات والقياسات» tab unchanged (nut_measure). Keep hideRail. Bare/compact card chrome so the board still looks like the board (no big shell card heads unless editing — check how dental bare cards do it).
4. Products sold (N11): the packages card shows «المنتجات المباعة» (products sold to this patient: name, qty, date, amount) under packages. Find where the board model gets packages (Nutrition ConsultBoardReader BE) and add `products_sold` there (sales/POS invoice lines for the patient's business partner — reuse existing patient-purchases readers if any, read-only, latest 10). Small BE change in Modules/Nutrition only + test.
5. Unlocking layout saves for nutrition is done by the orchestrator in visit-shell.component.ts (Decision 7) — do NOT edit visit-shell.component.*. Tell the orchestrator in your report when the split is ready for it.

## Screenshot identity (mandatory)
Before changing anything, capture baselines; after, capture again and compare (pixel diff, e.g. pixelmatch from node_modules if present, else ImageMagick `compare -metric AE`). Pages: classic `clinic/encounter/43?classic=1` both tabs, and shell `clinic/encounter/43/shell` both tabs (nutrition patient «ريهام», encounter 43; also 50 = done visit). Tool: Playwright from /home/moonui3/public_html/moon-erp/node_modules/playwright. Auth: mint a Sanctum token `$PHP artisan tinker --execute="echo \App\Models\User::find(2)->createToken('claude-visual-check')->plainTextToken;"`, set localStorage `token` and `lang=ar` on https://moonui3.elbaset.com/app/ then navigate (see /tmp/claude-0/-home-moonui3-public-html/dfed8133-fabe-4b29-871f-5f930c91925d/scratchpad/shot.cjs). The live /app only changes when the orchestrator deploys — for the AFTER shots build a preview with `npx ng build --base-href /app-s2b/ --output-path /tmp/claude-0/-home-moonui3-public-html/dfed8133-fabe-4b29-871f-5f930c91925d/scratchpad/dist-s2b` and copy its `browser/*` into `/home/moonui3/public_html/app-s2b/` (create it; copy `/home/moonui3/public_html/app/assets/config.json` over its assets/config.json and `/home/moonui3/public_html/app/.htaccess` with the `/app/` base replaced by `/app-s2b/`; `chown -R moonui3:moonui3`). Then shoot https://moonui3.elbaset.com/app-s2b/… (the token in localStorage is per origin path-independent, same origin). Note: other agents' uncommitted FE work in the tree is included in that build; that's fine. Delete /home/moonui3/public_html/app-s2b at the end. Revoke your token at the end: `DB::table('personal_access_tokens')->where('name','claude-visual-check')->delete()`. Report the diff numbers; differences must be explained (dynamic dates/times only).

Run ng build at the end. Do not deploy, do not commit.

## Out of scope
visit-shell.component.*, dental files, picker/vitals files (other agents in this wave).
