1. Intención de diseño
Contexto y objetivo del sistema
Intención: NutriTrack es una herramienta profesional para dietistas; el sistema de diseño debe transmitir claridad y confianza, priorizar la lectura rápida de datos clínicos y eliminar toda fricción visual que no aporte información. Cada decisión estética está subordinada a la accesibilidad y la velocidad de carga.
PilarDescripciónRegla clave
Flat 2D Sin sombras, gradientes ni texturas. Elementos planos y limpios. box-shadow: none en componentes core. MUST
Color vibrante Paleta de tokens semánticos. El color comunica estado, no decoración. Usar solo tokens definidos (--primary, --danger…). MUST
Tipografía limpia Inter para lectura; JetBrains Mono para datos y tokens técnicos. No mezclar más de 2 familias tipográficas. MUST
Ritmo de espaciado Escala de 4 px. Espaciado coherente en toda la interfaz. Todos los márgenes/paddings siguen la escala 4/8/12/16/24/32. MUST
2. Tokens de color
Paleta semántica — usar siempre el token, nunca el valor hex directamente
Primary
#F2673C
--primary
Secondary
#8B5CF6
--secondary
Success
#16A34A
--success
Warning
#D97706
--warning
Danger
#DC2626
--danger
Text
#111827
--text
Muted
#6B7280
--muted
Neutral / BG
#F9FAFB
--neutral
Surface
#FFFFFF
--surface

El contraste de --text sobre --surface es 16.1:1 (AAA). El --primary sobre blanco alcanza 3.3:1 — usar solo en elementos gráficos grandes o con borde visible. Para texto sobre fondo blanco usar --text o --muted.

3. Tipografía
Escala 12 / 14 / 16 / 20 / 24 / 32 — Inter + JetBrains Mono
Escala tipográfica
display / h1
32px · 800 · Inter · 1.1
Dashboard Nutricional
h2
24px · 700 · Inter · 1.2
Resumen del Paciente
h3 / section
20px · 700 · Inter · 1.3
Ingesta Calórica Diaria
body-lg
16px · 400 · Inter · 1.5
El paciente ha alcanzado el 87% de su objetivo calórico semanal.
body-md / default
14px · 400 · Inter · 1.6
Última actualización: hoy a las 09:42 · Próxima revisión: 21 jun 2026
label / caption
12px · 600 · JetBrains Mono · 1.4
CALORÍAS · PROTEÍNAS · HIDRATACIÓN
4. Espaciado
Escala base 4 px — todos los valores en múltiplos
Escala de espaciado
--sp-1
4 px · micro · separación interna mínima
--sp-2
8 px · tight · gap entre elementos inline
--sp-3
12 px · snug · padding en botones small
--sp-4
16 px · base · padding estándar de componente
--sp-6
24 px · comfortable · separación entre secciones
--sp-8
32 px · spacious · padding de página / layout
5. Botones
Variantes · tamaños · estados interactivos
Variantes — estado default
Tamaños
Estado disabled
VarianteUso semánticoEstado hoverToken de color
Primary Acción principal de la página (1 por vista) Oscurecer 10% → #D95530 --primary
Secondary Acciones secundarias (nav, filtros, exportar) Oscurecer 10% → #7C3AED --secondary
Ghost Cancelar, cerrar, acciones neutras --neutral bg + --border stroke --border / --text
Danger Eliminar, revocar acceso (siempre con confirmación) Oscurecer 10% → #B91C1C --danger

Regla: el estado focus-visible debe mostrar un anillo de 3 px con el color del token del botón + 2 px de offset. Los botones nunca usan outline:none sin reemplazarlo.

6. Badges de estado
Semáforo visual para el estado del paciente
Variantes de badge
Activo En riesgo Crítico Inactivo
Uso en lista de pacientes
MG
María García López
Plan hipocalórico · Semana 4 de 12
Activo
JR
Jorge Ruiz Navarro
Plan renal · Semana 8 de 24
En riesgo
LP
Lucía Pérez Vidal
Sin plan activo · Alta médica
Inactivo

Los badges comunican estado semántico — no estilo. Nunca usar un badge de color arbitrario fuera de la paleta semántica. El icono (punto) debe incluir un atributo aria-label describiendo el estado cuando no hay texto visible.

7. KPI Cards
Tarjetas de resumen para métricas clínicas
🔥
Calorías
1.847 kcal
▲ 6% vs. ayer
💪
Proteínas
94 g
▼ 3% vs. objetivo
💧
Hidratación
1.9 L
— igual que ayer
📊
IMC
24.3
▲ objetivo alcanzado
ElementoTokenRegla
Borde superior coloreado Color semántico de la métrica 3 px de altura, sin border-radius superior. MUST
Icono contenedor Tint del color semántico (10% opacidad) 32×32 px, border-radius: var(--r-sm). SHOULD
Valor KPI --fs-2xl + fw-800 Siempre --text. Nunca colorear el valor directamente. MUST
Indicador de cambio --success / --danger / --muted Texto de 12 px con símbolo de dirección (▲ ▼ —). MUST
8. Formularios
Búsqueda de paciente · campo de texto · select · estados de error
Búsqueda de paciente
🔍
Busca por nombre completo o número de expediente.

Estado de error
✉️
⚠ Introduce un email válido con dominio completo.
Estado disabled
🔒
Campo de solo lectura. Editar desde el expediente.

Interacción: el estado focus usa border-color: var(--primary). El estado error usa border-color: var(--danger) con mensaje inline. Los labels son siempre visibles (nunca solo placeholder). Todo input debe tener id vinculado con for en el label.

9. Accesibilidad
WCAG 2.2 AA — criterios testables
CriterioRequisitoCómo testar
1.4.3 Contraste texto Mínimo 4.5:1 para texto < 18pt; 3:1 para texto grande axe-core · WebAIM Contrast Checker · --text/#111827 sobre --surface = 16.1:1 ✓
2.1.1 Teclado Todos los botones, inputs y links accesibles con Tab/Enter/Space Navegación completa sin ratón. Verificar orden de Tab lógico.
2.4.7 Focus visible Estado focus siempre visible (anillo 3 px mínimo) Inspeccionar cada componente con Tab; comprobar que el outline es visible sobre cualquier fondo.
3.3.1 Error identificado Los errores de formulario se describen en texto (no solo color) El mensaje de error aparece debajo del campo. aria-describedby vincula input con mensaje.
4.1.2 Nombre/Rol/Valor Todos los controles interactivos tienen nombre accesible Verificar aria-label en iconos solos; labels en todos los inputs.
1.4.11 Contraste no-texto Iconos y bordes de UI: mínimo 3:1 contra fondo --border (#E5E7EB) sobre --surface no supera 3:1 — compensar con texto o icono adicional en campos.
10. Anti-patrones
Lo que explícitamente no se debe hacer
✕ No hacer
Botón con gradiente

Los gradientes violan el principio Flat. Aumentan el peso visual y dificultan el cálculo de contraste.

✓ Correcto

Color plano #F2673C. Sin gradiente, sin sombra. Hover oscurece uniformemente.

✕ No hacer
Texto en gris claro sobre blanco

Contraste insuficiente. El color #cccccc sobre blanco = 1.6:1, muy por debajo del 4.5:1 requerido.

✓ Correcto
Texto en --muted sobre blanco

--muted (#6B7280) sobre blanco = 4.6:1 ✓ Supera el umbral AA.

✕ No hacer
ALERTA AVISO NUEVO

Colores ad-hoc fuera de tokens. Rompen la coherencia y son imposibles de mantener.

✓ Correcto
Alerta En riesgo Activo

Badges con tokens semánticos. Mismo lenguaje visual en toda la app.

✕ No hacer
margin-top: 7px; padding: 13px 19px

Valores de espaciado arbitrarios. Rompen el ritmo de la cuadrícula de 4 px.

✓ Correcto
margin-top: var(--sp-2); padding: var(--sp-3) var(--sp-4)

Tokens de espaciado. Múltiplos de 4 px. Mantenibles y predecibles.

11. Checklist QA
Ejecutar en cada code review antes de merge
  • Sin sombras en componentes core Grep por box-shadow en CSS de componentes. Solo permitido en modales/dropdowns con valor máximo 0 2px 8px rgba(0,0,0,.08).
  • Sin gradientes en fondos interactivos Grep por linear-gradient y radial-gradient. Solo permitido en gráficas de datos.
  • Todos los colores usan tokens CSS No debe haber valores hex directos en estilos de componentes (excepto en la definición de los propios tokens en :root).
  • Contraste AA verificado con axe-core Ejecutar npx axe --dir ./dist. Cero violaciones de contraste en nivel AA.
  • Focus visible en todos los elementos interactivos Navegar con Tab por toda la vista sin ratón. Cada elemento debe mostrar anillo de focus de al menos 3 px.
  • Labels en todos los inputs Comprobar con document.querySelectorAll('input:not([aria-label]):not([id])') — debe devolver lista vacía.
  • Espaciado en múltiplos de 4 px Revisar que todos los padding y margin usan tokens --sp-* o valores de la escala 4/8/12/16/24/32.
  • Tipografía solo Inter / JetBrains Mono Grep por font-family distinto de var(--font) o var(--mono).
  • Botón danger con confirmación Todas las acciones irreversibles (eliminar, revocar) deben tener modal o diálogo de confirmación antes de ejecutar.
  • Estados vacío/carga/error definidos en cada componente No mostrar componentes vacíos sin un estado explícito (skeleton, mensaje, ilustración).

Versión del sistema: 1.0.0 · Generado para NutriTrack SaaS · Revisado con CULTIVA IA Design System Flat Skill (id: 92ae96a9) · WCAG 2.2 AA