Referencia del sistema visual para desarrollo frontend. Fecha: 21 de octubre de 2026.
Formaliza la identidad y los patrones existentes; no introduce un rediseño.
**Cómo consultarlo:** elegir el patrón de pantalla, consultar su documentación especializada y comprobar las APIs y tokens enlazados antes de implementar. **Vigente** identifica una decisión ya establecida; **implementado** describe una capacidad del código; **pendiente** identifica deuda o una decisión todavía no validada. Documentar un hallazgo no lo resuelve.
## 1. Propósito e identidad
Metis Desk organiza la información informática de compañías atendidas por un espacio de soporte: activos, personas, puestos, perfiles, recursos y sus relaciones. Las tareas prioritarias son localizar, consultar, comparar, relacionar y mantener esa información. Las personas de una compañía no equivalen a los usuarios internos de la aplicación.
El carácter visual actual combina superficies claras, tipografía Inter, acciones primarias rojas, navegación global verde oscuro con acento turquesa y componentes Base UI/Vega. Conservar esta identidad; priorizar densidad legible frente a decoración o grandes bloques vacíos.
Principios vigentes, derivados de [AGENTS.md](AGENTS.md) y de los patrones del proyecto:
- **Productividad:** dar prioridad a datos y acciones operativas; presentar ayuda e información secundaria con menor jerarquía.
- **Consistencia:** resolver casos equivalentes con los mismos componentes, conservando restricciones de cada entidad.
- **Jerarquía:** distinguir identidad, datos principales, características técnicas, relaciones, historial y acciones.
- **Accesibilidad:** semántica, teclado, foco y estados comprensibles; verificar las combinaciones visuales efectivas.
- **Capacidad del contenedor:** distribuir según el espacio disponible para la tarea, también con navegaciones y paneles simultáneos.
La precedencia de instrucciones es la de AGENTS: petición actual del usuario, AGENTS más cercano, AGENTS raíz y convenciones aplicables. Dentro del sistema visual:
| Fuente | Responsabilidad |
| --- | --- |
| [AGENTS.md](AGENTS.md) | Restricciones, arquitectura, disciplina, seguridad y validación del trabajo |
| Este DESIGN.md | Mapa de decisiones visuales, componentes, fundamentos y deuda conocida |
| [Listados](docs/patron-de-listados-de-entidades.md) y [diálogos](docs/patron-de-dialogos.md) | Fuentes normativas especializadas; prevalecen sobre un resumen general de este documento en su ámbito |
| [Componentes](docs/componentes-de-interfaz.md), [rutas](docs/rutas-del-cliente.md) y [estructura web](docs/estructura-web-por-entidades-y-operaciones.md) | Contratos de composición, navegación y organización |
| Tokens y componentes implementados | Valores efectivos y APIs reales; su existencia no convierte una desviación en pauta correcta |
| [Auditoría visual](docs/auditoria-ui-ux-visual.md) | Evidencias, escenarios comprobados y limitaciones; no prescribe por sí sola un nuevo diseño |
| [Matriz de skills frontend y UI/UX](docs/skills-frontend-ui-ux.md) | Selección por tarea y criterios complementarios, subordinados a las decisiones específicas de Metis |
Ante una contradicción, comprobar normativa especializada, consumidor y evidencia; identificar qué está obsoleto y corregir documentación dentro del alcance autorizado. No copiar una inconsistencia del código ni presentar una propuesta como implementada. Por ejemplo, el patrón exige altura estable aunque ciertos asistentes todavía no la aplican.
### Responsabilidades de implementación
| Capa | Qué contiene y cómo se consume |
| --- | --- |
| `packages/shadcn-ui` → `@repo/shadcn-ui` | Primitivas vendor, Base UI, estilo `base-vega`. **No modificar su implementación ni configuración**, salvo instrucción explícita del usuario. Consultar su API pública. |
| `packages/rdx-ui` → `@repo/rdx-ui` | Componentes propios genéricos, hooks y catálogo visual. Imports por componente, sin un barrel universal. No conocen DTO, endpoints, consultas ni reglas de negocio de Metis. |
| `modules/*/src/web` | Composición por entidad/operación; datos, permisos, reglas, traducciones y callbacks del dominio consumidor. |
| `apps/web` | Entrada de aplicación, coordinación de navegación y estilos globales. El shell concreto está compuesto actualmente desde `modules/companies`; no se traslada de capa por este documento. |
Preferir `children` y props semánticas explícitas. No construir un componente universal con numerosas combinaciones booleanas ni extraer componentes sin responsabilidad o reutilización real. Mantener APIs accesibles y documentadas. Fuentes de contexto: [configuración de la app](apps/web/components.json), [vendor](packages/shadcn-ui/components.json), [exports propios](packages/rdx-ui/package.json).
## 3. Fundamentos visuales implementados
### Color
El tema se importa desde `@repo/shadcn-ui/globals.css`. Las variables semánticas y sus utilidades Tailwind se definen en [globals.css del vendor](packages/shadcn-ui/src/styles/globals.css); las extensiones propias viven en [global.css de la aplicación](apps/web/src/global.css). Usar `bg-background`, `text-foreground`, `border-border`, etc., en lugar de repetir colores por pantalla. Los siguientes valores son **implementación actual**, no una nueva paleta ni una garantía de contraste:
`--chart-1` a `--chart-5` y `--sidebar-*` están definidos en la misma fuente; no equivalen a estados de negocio. La navegación global utiliza los tokens propios `shell-*`, no los anchos genéricos de sidebar del vendor:
| Token propio, fuente `apps/web/src/global.css` | Valor y función |
| --- | --- |
| `--color-shell-sidebar` | `#0e282c`, fondo de navegación |
| `--color-shell-sidebar-top` / `-bottom` | `#0c252a` / `#102c30`, gradación del fondo |
No existen aquí tokens globales propios `success` o `warning`. Los componentes actuales aportan sus representaciones; no inventar una API de tokens ni extender colores fijos a nuevas pantallas. La semántica de éxito y algunos colores fijos requieren revisión según la auditoría. El modo oscuro tiene tokens, pero no fue validado visualmente en esa auditoría.
### Tipografía y escala
Fuentes locales variables WOFF2, pesos 100–900, `font-display: swap`; [global.css](apps/web/src/global.css) sobrescribe las familias del vendor tanto en `:root` como en `.dark`:
| Utilidad | Familia y uso vigente |
| --- | --- |
| `font-sans` | Inter: interfaz general |
| `font-mono` | Geist Mono: código, identificadores y valores técnicos cuando corresponda |
| `font-serif` | Roboto Serif: contenido editorial puntual, no títulos generales de gestión |
No fijar ejes variables manualmente ni cargar fuentes remotas nuevas. El peso lo controlan las utilidades `font-*`. La escala efectiva combina Tailwind 4, overrides vendor y recetas propias; valores en px equivalentes con raíz de 16 px:
| Papel / fuente | Receta implementada |
| --- | --- |
| Texto general, controles y datos | `text-sm` = 0,875 rem; **`text-base` también se redefine a 0,875 rem** en `@theme` vendor. No asumir que base significa 16 px. |
| Ayudas y metadatos | `text-xs` = 0,75 rem; `FieldHelp` y `DetailField` conservan sus recetas |
| Cabecera de listado / identidad de activo | `text-2xl font-semibold` = 1,5 rem / 600, en `EntityListHeader` y `AssetDetailPage` |
| Título de modal | `text-lg font-bold` = 1,125 rem / 700, en `FormDialog` |
| Grupo de formulario | `text-xs font-semibold uppercase tracking-wide text-muted-foreground`, en `FormSectionTitle`; standalone añade `mb-4`, inline no |
| Encabezados HTML sin receta propia | Vendor h1–h6: 38/30/24/20/16/14 px, pesos 700/700/600/600/600/600; no reemplazan las recetas anteriores |
| Tracking base | `--tracking-normal: -0.02em`, vendor; conservar las variantes implementadas |
El nivel semántico de un encabezado no se elige por su tamaño. Reutilizar las recetas de [EntityListHeader](packages/rdx-ui/src/components/entity-list.tsx), [FormSectionTitle](packages/rdx-ui/src/components/form-section-title.tsx), [DetailField](packages/rdx-ui/src/components/detail-field.tsx) y [FieldHelp](packages/rdx-ui/src/components/field-help.tsx).
### Espacio, forma y elevación
- **Unidad:** `--spacing: 4px` en el tema vendor. En recetas existentes, gap-2/3/4/5/6 son 8/12/16/20/24 px. No convertir esta lista en un conjunto cerrado nuevo: copiar la receta del componente equivalente.
- **Contenido:** `CompanyDetail` usa p-4 y shell:p-6, 16/24 px; `FormDialog`, px-6 y py-5 en cabecera; `FormBody` conserva margen para el anillo de foco. Las separaciones específicas de grupos están en el patrón de diálogos.
- **Controles vendor:** [Button](packages/shadcn-ui/src/components/button.tsx) default h-9 = 36 px, sm 32 px, xs 24 px, lg 40 px; tamaños icon correspondientes. [Input](packages/shadcn-ui/src/components/input.tsx) h-9 = 36 px. No redimensionarlos independientemente por pantalla.
- **Radios vendor:** `--radius: 0.5rem`; sm/md/lg/xl/2xl/3xl/4xl derivan −4/−2/0/+4/+8/+12/+16 px: 4/6/8/12/16/20/24 px con raíz 16. `rounded-full` y los límites de variantes pequeñas conservan su función.
- **Radios propios:** `--radius-shell-control: 8px`, `--radius-shell-popover: 10px`, `--radius-shell: 20px`, `--radius-panel: 12px`; fuente global de la app.
- **Bordes:** usar `border-border`, `border-input` y opacidades de la receta. El diálogo efectivo añade `1px solid color-mix(in oklch, var(--foreground) 1%, var(--border))` en CSS de la app.
- **Sombras:** input/outline consumen `shadow-xs`; claro: `0px 4px 10px -2px hsl(0 0% 0% / 0.05)`, fuente vendor. La escala completa claro/oscuro vive allí. Shell popover: `0 3px 12px rgb(12 40 80 / 8%)`. La última regla global de diálogo aplica `0 24px 60px rgb(12 40 80 / 24%), 0 8px 18px rgb(12 40 80 / 14%), 0 0 0 1px rgb(12 40 80 / 8%)`; sustituye una regla anterior, no representa dos variantes intencionadas.
### Iconos y estados interactivos
Usar el [catálogo semántico propio](packages/rdx-ui/src/lib/icons.ts), basado en Tabler: Activos `BoxIcon`, Recursos `LayersIcon`, Personas `PersonIcon`, Puestos `MonitorIcon`, Perfiles `WorkProfileIcon`. Icono de entidad coherente en navegación, título y alta; título de listado 24 px, icono de Button 16 px por defecto. Decorativos con `aria-hidden`; acciones solo icono con nombre traducido y tooltip.
`apps/web/components.json` declara Tabler; el vendor conserva Lucide en su configuración e iconos internos. No migrar vendor ni importar bibliotecas de iconos directamente desde módulos.
Button ofrece default/outline/secondary/ghost/destructive/link. Conservar sus hover, expanded, disabled y focus-visible; disabled reduce opacidad y bloquea interacción. Input conserva ring de foco y estado inválido. `.app-link` usa primario, subrayado en hover y outline de 2 px con offset de 3 px en foco. Las combinaciones de selección deben comprobarse: V02 está corregido en el inventario claro verificado, con primario, texto secundario y ring contextuales limitados a sus filas. No cambia la paleta global ni añade tokens.
Estos son umbrales existentes, **no mínimos operativos validados para layouts futuros**. V01.1 implementa la composición móvil por debajo de `shell` (768 px): cabecera compacta, franja de compañía/sección y navegación global/contextual mediante un único Sheet modal abierto a la vez. La búsqueda móvil reutiliza la lógica existente y el salto al contenido conserva foco accesible. En los datos sintéticos verificados, `main` comienza en Y=106 px a 320 y 390 px; la ampliación de texto puede aumentar ese alto. V01.2 extiende el Sheet y la franja a los tamaños sin capacidad para columna fija. Véanse [V01.1](docs/navegacion-movil-v01-1.md) y [navegación responsive V01.2](docs/navegacion-responsive-v01-2.md).
La política de V01.2 mide el contenedor del shell y distingue tres presupuestos centralizados: 920 px para raíl de 72, 1160 para raíl y secundaria fija de 240, y 1660 para expansión global de 228 según preferencia. Por debajo de cada capacidad, la presentación correspondiente pasa a Sheet; la secundaria puede ocultarse temporalmente y fijarse de nuevo si cabe. La preferencia `metis-desk:sidebar-collapsed` solo cambia por una acción manual, nunca por resize; no se persiste la ocultación contextual. El raíl tiene etiquetas accesibles, tooltips al foco/hover y expansión temporal con etiquetas.
Cabecera sticky y columna contextual con scroll propio conservan una única zona principal de scroll. El foco de enlaces/activadores que desaparecen se traslada a un equivalente visible; los menús que pasan a fijos liberan modalidad. Se conserva el foco y estado del contenido que permanece montado.
V01.3/V01.4 coordinan el detalle de ambos inventarios con `useContextualDetail` de rdx-ui y un ResizeObserver por caja exterior estable. Cada módulo define su presupuesto; no se utiliza el viewport ni la columna que encoge. Abrir/cerrar detalle no altera el shell. Perder capacidad conserva selección, cierra panel y ofrece reapertura explícita; ganar capacidad conserva el contexto abierto y cerrado permanece cerrado. Recursos conserva selección en URL, cierre compacto y diálogo explícito propios. El breakpoint `inventory` y `useCompactDetail` permanecen como API anterior, sin gobernar estos inventarios; `dashboard` no cambia. El cierre formal se documenta en [V01.4](docs/recursos-responsive-v01-4.md).
Usar [BrowserLink y rutas existentes](docs/rutas-del-cliente.md) para destinos reales; botones para acciones, selección local y modales. Conservar acceso directo, recarga, Atrás/Adelante, clic modificado y sección activa accesible. No inventar rutas de edición o fichas para entidades que no las tienen. Si el esquema narrativo de rutas queda desactualizado, contrastarlo con `workspace/shared/helpers/workspace-routes.ts`; no cambiar el modelo de negocio para adaptar una URL.
## 5. Patrones de listados
Fuente normativa: [patrón de listados](docs/patron-de-listados-de-entidades.md). Receta de partida: `EntityListHeader` + `EntityTable`, con acciones de fila y formularios en componentes independientes.
1. Cabecera: icono, título y subtítulo; alta a la derecha, adaptable al espacio.
2. Banda de búsqueda y filtros propios, con limpieza sin cambiar el ámbito de compañía/perfil.
3. Contador de resultados, Columnas y ordenación.
4. Tabla semántica; valores ausentes «—»; acciones fijadas a la derecha. Acción principal mediante icono, tooltip y nombre; secundarias en menú de tres puntos, sin duplicar la principal.
5. Rango repetido y paginación; filtros/tamaño ajustan página válida. No confundir cero resultados filtrados con falta de registros.
[EntityTable](packages/rdx-ui/src/components/entity-list.tsx) compone bandas, estados, contenido y controles; [useEntityTable](packages/rdx-ui/src/hooks/use-entity-table.ts) gestiona TanStack Table, orden, visibilidad y paginación **locales**. Nombre comienza ascendente salvo criterio explícito; comparación por idioma, sin tildes/mayúsculas y con cifras numéricas. Esto no describe el comportamiento de búsqueda: V07 sigue pendiente.
Columnas de inventario persisten con clave propia en localStorage; otros consumidores deben habilitar una clave explícita. Identificación y acciones no se ocultan. El selector extenso necesita revisión, V08. La búsqueda y ciertos filtros de rutas se conservan según su contrato; la restauración completa de orden/página no está implementada de forma general, V05. Cancelar un modal debe mantener contexto del listado.
Familias por plantilla usan `ScrollableTabsList`; `min-w-0` y scroll horizontal quedan dentro del listado. `onRowClick` solo selecciona desde zonas no interactivas, conservando enlaces, menús y controles internos. No añadir selección múltiple sin operación consumidora.
Para consultas **paginadas en servidor**, seguir [RemoteOptionPicker](packages/rdx-ui/src/components/remote-option-picker.tsx), `RemoteOptionList` y `CursorPagination`: el consumidor aporta página, búsqueda, estado y callbacks. No volver a paginar ni ordenar una página como si fuera el conjunto completo. No imponer paginación remota universal ni virtualización sin medir volumen y coste de los listados actuales.
## 6. Fichas de entidades
Referencia de composición: [AssetDetailPage](modules/assets/src/web/assets/detail/ui/asset-detail-page.tsx) y [WorkstationDetailPage](modules/companies/src/web/workstations/detail/ui/workstation-detail-page.tsx). La identidad incluye nombre, icono y metadatos relevantes; después, datos principales, características técnicas y relaciones. Conservar el ámbito y el retorno al listado.
- Reutilizar `DetailPanel`, `DetailSection`, `DetailField` y `TimeLine` desde rdx-ui cuando su contrato encaje. `DetailField` compone dt/dd; su consumidor mantiene dl y semántica adecuada.
- Información reúne datos y relaciones pertinentes; Historial presenta hechos registrados y sus fechas. No crear una pestaña por cada relación si el patrón existente los reúne en Información; no inventar historial donde no exista.
- Las relaciones con destino existente son navegables; los enlaces y acciones describen su destino real. Los componentes genéricos no resuelven reglas de pertenencia ni consultas.
- Edición explícita; acciones secundarias/destructivas agrupadas y con sus restricciones. Conservar las confirmaciones del dominio.
- El panel lateral es consulta contextual; la ficha completa y el diálogo compacto conservan su función. En el panel de activos, Accordion permite varias secciones abiertas (`multiple` de Base UI).
- No ocultar información o acciones útiles al resumir un grupo vacío. **Pendiente V10:** revisar la acumulación de grupos vacíos, títulos repetidos y explicaciones administrativas antes de decidir qué se pliega inicialmente.
## 7. Formularios, diálogos y asistentes
Fuente normativa: [patrón de diálogos](docs/patron-de-dialogos.md). Cada interacción modal con responsabilidad propia vive en su fichero; el padre aporta apertura, datos y callbacks. Reutilizar `FormDialog`, `FormBody`, `FormActions`, `FormStepActions`, `FormLabel`, `FormSection`, `FormSectionTitle`, `FieldHelp`, `FormHelp` y selectores existentes antes de crear estructuras equivalentes.
| Capacidad implementada | Uso y adopción pendiente |
| --- | --- |
| FormDialog small/medium/large | Desde sm: máximos 36 rem/48 rem; large 90vw con máximo 1200 px. Margen y altura máxima respecto a ventana. Consultar su [implementación](packages/rdx-ui/src/components/form-dialog.tsx). |
| `layout="stable"` | Para contenido variable, pasos, filtros y selecciones: altura `calc(100dvh - 2rem)`; desde sm, `min(85dvh,900px)`. Puestos/perfiles lo utilizan; activos/recursos lo adoptan en el sprint 1, con Anterior deshabilitado en el primer paso para estabilizar también el pie móvil (V03 verificado). |
| `layout="picker"` | Selector de altura estable; búsqueda inicial en input `data-quick-search`; tabla `layout="fill"`, selección primera y compacta, confirmación/cancelación de borrador. |
| `layout="content"` | Diálogos breves de contenido estable; es el default técnico, no la elección normativa para asistentes variables. |
| FormBody | Scroll interno, `min-h-0`, margen de foco; `contentLayout="fill"` distribuye alto restante y permite que EmptyState crezca por toda la cadena flex. |
| FormHelp | Hermano de FormBody antes de acciones, junto al pie; scroll propio y límite actual del 40 %. Su densidad en ventana corta requiere diseño adicional, V04. ContextHelp dentro del cuerpo no garantiza ese anclaje. |
| FormProgress | Paso actual, completados y anuncio con foco; falta ajustar etiquetas estrechas, V04. No simular navegación clicable si los pasos no la ofrecen. |
Etiquetas con `htmlFor`, obligatoriedad según contrato y un único indicador de `FormLabel`; campos optativos sin sufijo. Títulos de grupo uniformes; título y contador en fila usan `layout="inline"` e `items-center`. Secciones adaptadas a su contenedor; detalles de columnas, reordenación accesible y numeración pertenecen al patrón especializado.
Una fuente de verdad por campo; React Hook Form y schemas Zod según patrones existentes. Errores junto al campo o como error global según su origen, con asociación accesible para mensajes propios; no cerrar ni limpiar antes de confirmar guardado. La ayuda no rellena campos automáticamente; propuestas de nombre o selecciones únicas solo donde el contrato específico ya lo establece.
Conservar cabecera y acciones visibles, scroll del cuerpo y valores al retroceder. Guardar al final del asistente; impedir envíos duplicados. Cancelar/Escape/cierre descartan el borrador según la operación y restituyen foco al disparador; **V06** se corrigió en el inventario mediante finalFocus de Base UI: disparador capturado en la apertura y destino alternativo local cuando no está disponible. No añadir manualmente primitivas de modalidad que Base UI ya resuelve.
En diálogos anidados, mantener borrador padre y foco de retorno; cancelar selección no modifica el padre. Un alta rápida guardada puede persistir aunque después se cancele el formulario principal: respetar su contrato, no tratarla como una selección provisional. No añadir niveles de anidación sin revisar los consumidores existentes.
## 8. Estados y comunicación
| Situación | Convención vigente / limitación conocida |
| --- | --- |
| Carga inicial | Mensaje de estado sin fingir vacío; reservar estructura cuando la integración lo permita. Activos aún desmonta controles, V12. |
| Actualización en segundo plano | TanStack Query gestiona estado remoto; conservar datos y controles disponibles. No duplicar la caché en estado local. |
| Sin registros / sin resultados | Distinguir primer registro de filtros sin coincidencias. Mantener CTA de alta o limpieza cuando proceda; EmptyState para incorporación de elementos en pasos. |
| Éxito | Confirmar solo tras respuesta satisfactoria. No equiparar color primario con éxito: FormFeedback mantiene una inconsistencia señalada en la auditoría, sin estado de éxito visual validado. |
| Error | Mensaje recuperable, contexto del campo/formulario/consulta y reintento pertinente; sin SQL, stacks ni secretos. |
| Advertencia / información | Usar componentes y textos existentes adecuados a la finalidad; explicación secundaria con ayuda contextual. No inventar un token global a partir de una apariencia aislada. |
| Selección | Estado visual y semántico además de color; en pickers distinguir borrador/confirmación. Revisar pareja de colores, V02. |
| Acción deshabilitada | `disabled` o contrato accesible de la primitiva, estado visible y restricciones conservadas; no ofrecer acciones que la operación no permite. |
| Valor ausente | En toda celda de listado/sublistado/PickerList, exclusivamente «—»; conservar 0 y false con su representación correcta. |
| Estado de negocio | Texto real como Inactivo o Sin puesto activo no equivale automáticamente a ausencia. «Sin asignar» puede ser placeholder de un selector; en una celda que solo carece de sede corresponde «—». V11 requiere revisar renderizadores. |
Textos de interfaz es/en mediante i18n; código e identificadores en inglés, documentación en castellano. Etiquetas breves para columnas/acciones, explicación en ayuda contextual. V09 se corrigió separando profiles.reviewLabel (Revisión/Review) de los motivos completos conservados en las celdas. No deducir permisos ni estado de una entidad solo por color.
Aplicar las obligaciones de AGENTS y de los patrones; comprobar comportamiento en navegador, además de JSX:
- Elementos semánticos, jerarquía de encabezados, nombres accesibles y asociación etiqueta/control. Iconos decorativos ocultos al lector; acciones de icono identificables.
- Teclado sin operaciones exclusivas de ratón/arrastre, orden DOM coherente, Tab/Shift+Tab, Enter/Espacio y Escape según la primitiva. No bloquear controles internos de filas.
- Foco visible sin recortes; inicial pertinente, contenido inválido accesible y retorno al origen al cerrar. PickerList busca por defecto. Verificar cada consumidor, no presumir cobertura general por usar Dialog.
- Validación HTML nativa conserva su semántica; su ausencia de `aria-invalid` no prueba un defecto. Para errores propios, asociar mensajes y estado al control, abrir grupos inválidos y diferenciar error global.
- Medir colores computados de texto/fondo efectivo y estados. Referencia [WCAG 2.2, 1.4.3](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html): 4,5:1 texto normal, 3:1 texto grande según su definición. V02: el enlace sobre selección pasó de ≈2,68:1 a ≈7,81:1 en el sprint 1; normal ≈4,65:1 y hover sin selección ≈12,86:1, con foco visible comprobado. Blanco sobre el botón primario medido ≈4,65:1; no extender el fallo a todos sus usos.
- Comprobar zoom 200/400 %, acceso a contenido/acciones, contraste de estados y respeto a movimiento reducido; conservar las variantes `motion-reduce` existentes. Estas comprobaciones, lector de pantalla y modo oscuro no se validaron completamente en la auditoría.
No declarar cumplimiento WCAG global a partir de tokens, snapshots, capturas o una muestra de contraste.
## 10. Responsive y densidad operativa
Vigente: distribución por contenedor para grupos de formulario, orden DOM conservado, acciones accesibles, nombres que puedan partirse y tabla desplazable dentro de su área. Los umbrales concretos de componentes como `TemplateMetadataSection` están en el patrón de diálogos; no son breakpoints globales nuevos.
- Escritorio amplio: mostrar datos comparables y paneles cuando quepan; evitar márgenes ornamentales y tarjetas sin función.
- Portátil/tablet: aplicar la política del shell V01.2 y después la capacidad real del inventario de activos según V01.3. No deducir el modo contextual del viewport; recursos aplica el presupuesto propio de V01.4.
- Móvil: contenido y acciones alcanzables sin desbordamiento global horizontal; la tabla puede tener scroll propio. V01.1 mantiene compañía y sección en una franja sticky, y sus destinos en Sheet; la navegación de portátil/tablet sigue V01.2 y el detalle de activos sigue V01.3.
- Ventanas bajas: altura dinámica, cuerpo desplazable y pie visible; no reducir campos para hacerlos caber. El presupuesto de ayuda y la versión compacta de progreso siguen pendientes, V04.
- Formularios y tablas extensas: usar grupos/pestañas/componentes existentes; truncar solo con acceso al valor completo cuando sea necesario. La búsqueda del selector de columnas, V08, y el resumen de ficha, V10, requieren implementación o diseño adicional.
Ninguna propuesta de nuevo ancho, breakpoint, colapso inicial o token se considera decisión vigente por aparecer en la auditoría.
## 11. Verificación, calidad y deuda trazada
Procedimiento: [Playwright MCP](docs/playwright-mcp.md), [preparador sintético autenticado](scripts/visual-audit.py) y [auditoría visual](docs/auditoria-ui-ux-visual.md).
1. Identificar consumidores equivalentes, patrón, cambio esperado y datos necesarios. Consultar las skills instaladas pertinentes: frontend-design, shadcn, vercel-composition-patterns y vercel-react-best-practices; sus recomendaciones no autorizan modificar vendor ni regenerar el proyecto.
2. Reutilizar sesión/entorno sintético activo; si se prepara uno, seguir el procedimiento aislado y retirarlo al terminar. No usar bases reales, fixtures destructivas o guardar formularios sin autorización correspondiente.
3. Para cambios visuales relevantes, comparar antes/después en navegador cuando sea viable. Revisar carga/error/vacío, contenido largo, teclado, foco y contraste, con resoluciones representativas de la matriz: 1920×1080, 1440×900, 1366×768, 1024×768, 768×1024, 390×844 y 320×640; priorizar problemas y evitar capturas redundantes.
4. Esperar carga y transiciones antes de medir. Abrir los PNG: captura, snapshot, geometría y prueba funcional son evidencias distintas. Las capturas en `.artifacts/playwright/`, excluidas de Git, **no son evidencia portable por sí solas**: acompañar el informe con escenarios, medidas y un mecanismo explícito de entrega de imágenes sin secretos.
5. Ejecutar pruebas de comportamiento y comprobaciones apropiadas al alcance según AGENTS; cambios transversales de código requieren typecheck, lint, test, check y build. Para documentación, enlaces, tokens y diff bastan; informar lo ejecutado y lo pendiente, sin afirmar validaciones no realizadas.
V02, V03, V06 y V09 están **resueltos en los escenarios verificados del sprint 1**; los otros ocho hallazgos siguen pendientes. Las mediciones originales y el seguimiento posterior se conservan en la auditoría:
| V01 | Resuelto en los escenarios verificados de V01.1–V01.4: navegación y ambos inventarios por capacidad | 28 métodos visuales y once resoluciones; presupuestos/contratos documentados en [V01.4](docs/recursos-responsive-v01-4.md). Fallos globales previos identificados |
| V10 | Jerarquía de ficha | Diseñar resumen de vacíos y grupos sin ocultar relaciones/acciones; validar fixture poblada |
| V11 | Renderizadores y semántica de ausencia | Aplicar pauta de «—» distinguiendo estado de negocio |
| V12 | Carga inicial de implementación | Reservar estructura y mensajes precisos; probar recuperación y actualización |
La auditoría usó una compañía y un portátil. Faltan relaciones pobladas, fichas de otras entidades, todos los pasos de puesto/perfil, guardados positivos, rendimiento con volumen y comprobación de accesibilidad ampliada. Los riesgos detectados solo por código conservan esa categoría; no implican fallo visual demostrado.
## 12. Gobernanza y mantenimiento
- Antes de añadir componente, buscar equivalentes en rdx-ui y módulos. Extraer por responsabilidad/repetición real y documentar consumidores, props, accesibilidad y estados en [componentes de interfaz](docs/componentes-de-interfaz.md). Fuente: disciplina y frontend de AGENTS.
- Modificar un patrón en su documento especializado, revisar consumidores equivalentes y actualizar este mapa si cambia una decisión transversal. Documentar una excepción con motivo, alcance y verificación; no convertir una desviación accidental en variante.
- Añadir tokens solo ante una necesidad real no cubierta: nombre semántico, fuente, usos, pares/estados y contraste verificado. Las extensiones propias se implementan fuera de vendor. Esta v1 no crea tokens propuestos ni una escala paralela.
- Mantener APIs coherentes y revisar consumidores al cambiarlas; no introducir compatibilidad hipotética, flags universales o duplicación de estado remoto. Fuente: contratos de AGENTS y composición de componentes.
- Incorporar hallazgos con su estado, reproducción y evidencia. Marcar resuelto únicamente después de implementar y verificar; actualizar auditoría/trazabilidad sin borrar las limitaciones históricas.
Fuentes de esta versión: normas y código enlazados, las cuatro skills indicadas y la auditoría del 21 de octubre de 2026. Se volvieron a inspeccionar sus capturas conservadas de Activos en escritorio y Nuevo puesto a 320 px como referencia documental. No se inició otra aplicación ni se repitieron las pruebas de navegación para redactar esta v1.