Stability checkpoint — customers split D1 steps 2+3 (MR !116)

Completes the CustomerStateService split started with
ImportExportService. Two more bounded services extracted :

1. CustomerSelectionService (B-7-2c step 2) — batch select + batch
   delete. Owns selectedIds (Set<number>) + selectAll + hasSelection
   + confirmBatchDelete + batchDeleteLoading signals.
   5 methods : toggleSelectAll(pageContent) / toggleSelectOne(id) /
   openBatchDelete / cancelBatchDelete / executeBatchDelete(cb).
   Clear separation from other customer concerns.

2. CustomerCrudService (B-7-2c step 3) — single-customer edit +
   delete + random-create. Owns editingCustomer + editName +
   editEmail + editLoading + editError + deletingCustomer +
   deleteLoading + randomCreate* signals.
   7 methods : openEdit/cancelEdit/saveEdit/openDelete/cancelDelete/
   confirmDelete/addRandomCustomer (each with onAfterChange callback
   for list reload).

Shared httpError() helper hoisted from customers.component.ts to
customers-helpers.ts so the 4 call sites (component + 3 services)
share one implementation.

Counts (cumulative from B-7-2b baseline) :
- customers.component.ts : 838 → 573 LOC (-32 %)
- 3 new services : 187 + 127 + 163 = 477 LOC bounded, each one
  concern, each Injectable{providedIn:'root'} for Angular DI

Template bindings routed through `selection.*` and `crud.*` via
bulk sed — 11 references updated atomically.

Remaining customers complexity : list pagination + sort + search +
apiVersion + summaryMode + detail panel + aggregate. These are more
intertwined (shared customers() signal + load() calls from many
paths) — deferred to future session whether a full
CustomerListStateService gives enough boundary value vs leaving
the component at ~580 LOC.