diff --git a/docs/ADMIN.md b/docs/ADMIN.md
index a20e13a..4d37854 100644
--- a/docs/ADMIN.md
+++ b/docs/ADMIN.md
@@ -197,6 +197,17 @@ src/app/features/admin/categories/
seed), not `AdminCategoriesGateway` - unifying them is Sprint 21 scope
(`docs/SPRINT-PLAN.md`).
+## Sprint 21 - Product Management completion
+
+- **Categories now real**: `AdminProductsLocalGateway` seeds its category dropdown from `AdminCategoriesLocalGateway.loadCategories()` (Sprint 20) instead of raw `BackofficeDataService.loadCategories()` - product `categoryId` now points at real admin-managed categories.
+- **Archive/restore**: `AdminProduct.archived` (soft, distinct from `visible`). List has an "include archived" filter + per-row Archive/Restore action; archived products excluded by default (mirrors categories' `deletedAt`/restore pattern).
+- **Barcode**: added alongside `sku`.
+- **Variants**: lightweight `AdminProductVariant[]` (`name`/`price`/`quantity`), edited as `name|price|quantity` lines (same textarea-parse convention as `specifications`/`attributes`). Not a full options-matrix variant system - scoped to what the model/backend contract actually needs today.
+- **Related products**: `relatedProductIds: string[]`, checkbox picker in the editor sourced from `AdminProductFormComponent`'s `allProducts` input - which is `AdminProductsFacade.products()`, i.e. whatever page is currently loaded in the facade (usually primed by navigating from the list). Not a full catalog search; fine for the current mock-data scale, worth revisiting if `AdminProductsLocalGateway` is ever swapped for a real API with more than a page of products.
+- **Gallery**: `media.gallery` now built via the shared `MediaPickerComponent` (add/remove thumbnails) instead of a raw URL textarea; `media.images`/`media.videos` unchanged (still textarea, out of this ticket's scope).
+- **Preview**: simple read-only line in the editor showing computed discounted price.
+- **Infinite scroll**: `AdminProductsFacade.infiniteScroll` toggle - when on, `loadMore()` appends the next page to `products()` instead of replacing it; pagination UI swaps for a "Load more" button. Off by default (existing paginated behavior unchanged).
+
## Known gaps / backend needs
- **Dashboard metrics endpoint.** Categories/Products counts are computed
diff --git a/docs/BACKEND.md b/docs/BACKEND.md
index 1798caf..25ff982 100644
--- a/docs/BACKEND.md
+++ b/docs/BACKEND.md
@@ -85,9 +85,9 @@ Backend must also support content moderation/validation on publish (disallow dan
## 6. Products
-**Current behavior:** `features/admin/products/` is fully built (list + editor pages) against `AdminProductsLocalGateway` (swappable via an injection token, same pattern as everywhere else) — i.e. it's ready for a real API gateway, but one has never been implemented.
+**Current behavior (Sprint 21):** `features/admin/products/` is fully built (list + editor pages) against `AdminProductsLocalGateway` (swappable via an injection token, same pattern as everywhere else) — i.e. it's ready for a real API gateway, but one has never been implemented. Sprint 21 added `barcode`, `archived` (soft archive/restore), `variants` (`{name, price, quantity}[]`), `relatedProductIds`, and wired the category dropdown to `AdminCategoriesGateway` (see item 5) instead of its own seed.
-**Needed:** product CRUD endpoints matching the existing storefront product contract (`itemID`, `name`, `price`, `currency`, `categoryID`, `visible`, `discount`, `images`, `badges`, `media`, `specificationGroups`, `variantOptions`, `relatedCollections` — see the Product Engagement / Product Experience 2.0 fields folded from prior sprint reports).
+**Needed:** product CRUD endpoints matching the current `AdminProduct` shape (`src/app/features/admin/products/models/admin-product.model.ts`) — `itemID`, `name`, `price`, `currency`, `categoryID`, `visible`, `archived`, `discount`, `images`, `badges`, `media`, `specifications`/`attributes`, `variants`, `relatedProductIds`, plus a bulk endpoint matching `PATCH /items/bulk`-style semantics for `applyBulkVisibility`/`applyBulkDelete`.
**Frontend files:** implement `AdminProductsApiGateway` alongside the existing `AdminProductsLocalGateway` and rebind the injection token — `features/admin/products/pages/*` and the facade do not change.
diff --git a/docs/SPRINT-PLAN.md b/docs/SPRINT-PLAN.md
index 6f05c4d..a58105d 100644
--- a/docs/SPRINT-PLAN.md
+++ b/docs/SPRINT-PLAN.md
@@ -24,12 +24,13 @@ Notify user: **from Sprint 20 (Categories) once product↔category link + admin
- Commit: `feat(admin): complete category management`
- Note: `admin/products`' category dropdown still uses its own `AdminProductsGateway.loadCategories()`, not this new gateway — unification deferred to Sprint 21 (documented in BACKEND.md).
-## Sprint 21 — Product Management completion
-- [ ] Audit gaps vs list: duplicate/archive already exist? verify; add missing (archive state, restore draft, related products, variant editor, price/currency/discount editor, inventory/SKU/barcode fields already present—confirm)
-- [ ] Wire products to real AdminCategoriesGateway (replace ad-hoc category options)
-- [ ] Gallery via MediaPickerComponent, translation editor, preview, infinite-scroll option on list
-- [ ] Update `docs/ADMIN.md`, `docs/BACKEND.md`
+## Sprint 21 — Product Management completion ✅ done
+- [x] Audit + add missing: `archived` (soft, list filter + archive/restore action), `barcode`, `variants` (lightweight name|price|quantity), `relatedProductIds` (checkbox picker)
+- [x] Wired products to real `AdminCategoriesGateway` (`AdminProductsLocalGateway` now seeds from `AdminCategoriesLocalGateway`, replacing its own `BackofficeDataService` category seed)
+- [x] Gallery via `MediaPickerComponent` (add/remove thumbnails); translation editor already existed (Sprint pre-19); preview (computed discounted price); infinite-scroll toggle on list (`facade.loadMore()` appends vs pagination)
+- [x] Updated `docs/ADMIN.md` (new Sprint 21 section), `docs/BACKEND.md` (item 6 rewritten with real field list)
- Commit: `feat(admin): complete product management`
+- Known trade-off: related-products picker sources from whatever page is currently loaded in `AdminProductsFacade.products()`, not a full catalog search — documented in ADMIN.md, fine at current mock scale.
## Sprint 22 — Media System hardening
- [ ] Folder support, tags, search in Media Manager
diff --git a/src/app/features/admin/products/components/admin-product-form.component.html b/src/app/features/admin/products/components/admin-product-form.component.html
index b4798eb..8a107ba 100644
--- a/src/app/features/admin/products/components/admin-product-form.component.html
+++ b/src/app/features/admin/products/components/admin-product-form.component.html
@@ -9,6 +9,9 @@
+
+
+
@@ -17,12 +20,21 @@
+