El mockup muestra que una fila es etiqueta + uno o varios controles en la
misma línea (Cliente = input + "...", Canal / Zona = dos mitades, Serie +
Número = 72 px + resto, select + número + botón) y que la cabecera tiene a
lo sumo 2 columnas. Los campos de un solo control no lo permitían.
- Controles sin etiqueta combinables dentro de sbo-field: sbo-input,
sbo-textarea, sbo-number, sbo-date, sbo-select y el botón .sbo-btn;
ocupan el espacio sobrante o un width fijo.
- El primer control de la fila toma el id de la etiqueta (claimId); los
demás se nombran con ariaLabel. El error de la fila marca todos sus
controles (aria-invalid / aria-describedby).
- Los campos con etiqueta (sbo-text-field, sbo-number-field, ...,
sbo-lookup-field) pasan a ser atajos de un solo control con la misma API.
- CSS global: .sbo-group y .sbo-btn reemplazan a .sbo-pick/.sbo-pair.
- CLAUDE.md apunta al mockup renombrado (tools/oferta_venta.html).
- Verificado en Chrome contra SAP real, con una cabecera que reproduce las
filas compuestas del mockup.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- apps/web: Angular 22 standalone, zoneless, OnPush, vitest; proxy /api
hacia el backend; presupuesto de bundle (aviso 260 kB, error 400 kB).
- libs/sap-types: tipos de auth/permisos/Service Layer y el evaluador de
patrones de menú, compartidos por api y web (se compila en postinstall).
El backend deja de tener su propia copia del evaluador.
- Temas por variables CSS: claro por defecto con la paleta del mockup de
Oferta de ventas, oscuro incluido; ThemeService + selector, con el tema
guardado aplicado antes del primer pintado. Agregar un tema = 1 css +
1 import + 1 entrada.
- Criterios de interfaz ligera en CLAUDE.md y README.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Raíz con workspaces apps/* y libs/*, reglas del proyecto base y flujo
por branch de cliente en CLAUDE.md, y el mockup de Oferta de ventas.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>