Declaración de accesibilidad, criterio por criterio.
Autoevaluación sobre WCAG 2.2, niveles A y AA, con el método de cada comprobación. Su límite también está declarado, en el propio documento: falta la auditoría externa con lector de pantalla real, y hasta que se haga no afirmamos conformidad en ninguna página de esta web.
Producto: Sistema de Examen Virtual Universidad (plataforma web de exámenes con supervisión) Versión de la norma: WCAG 2.2, niveles A y AA Fecha de evaluación: 2026-07-24 (tercera ronda; segunda 2026-07-19, primera 2026-07-11) Método de evaluación: axe-core 4.12 en navegador real (@axe-core/playwright sobre Chromium) contra 20 escenarios — 11 rutas públicas, la portada en modo oscuro, 6 rutas autenticadas (docente, banco de preguntas, exámenes, acceso del alumno, panel del proctor y administración del tenant), las tres fases del runner del examen (verificación del sistema, vista de preguntas con los cuatro tipos de respuesta, y el diálogo de confirmación de entrega) y la vista de la segunda cámara en el teléfono (/movil/[token], antes y después de activar la cámara) — con las etiquetas wcag2a, wcag2aa, wcag21a, wcag21aa y wcag22aa, y umbral de cero violaciones serious/critical. Se suma a la revisión estática de todo el marcado (src/app/**, src/components/**), el cálculo de ratios de contraste sobre los tokens CSS, los E2E de flujo completo (Playwright/Chromium) y la suite de 900+ tests automatizados.
La medición se hace con prefers-reduced-motion: reduce, porque la web pública anima las entradas con animation-timeline: view() y sin eso axe evalúa el color de un fotograma intermedio en lugar del estado estable que exige el criterio 1.4.3.
Limitación declarada: no se han hecho pruebas con usuarios reales de tecnologías de asistencia. axe automatiza reglas —y por eso encontró lo que la revisión a ojo no veía— pero no sustituye a una persona navegando con NVDA o VoiceOver: se recomienda esa pasada antes de firmar un contrato que la exija. Las reglas automatizadas cubren aproximadamente un tercio de los criterios WCAG; el resto de esta declaración se sostiene en la revisión estática del marcado y en los E2E de flujo completo.
Estado global: Autoevaluación completada — se cumplen todos los criterios AA evaluados, con las salvedades documentadas abajo. La conformidad formal se declara tras una auditoría externa con tecnología de asistencia real, que aún no se ha realizado.
Resumen de conformidad por nivel
| Nivel | Criterios | Cumple | Cumple parcial | No aplica |
|---|---|---|---|---|
| A | 30 | 27 | 1 | 2 |
| AA | 20 | 19 | 1 | 0 |
Nivel A
| Criterio | Estado | Observaciones |
|---|---|---|
| 1.1.1 Contenido no textual | ✅ | Las 2 <img> llevan alt (logo con alt del nombre de la institución); íconos lucide con aria-hidden; botones de solo ícono con aria-label; estados ✓/✗ con alternativa sr-only. |
| 1.2.1 Solo audio / solo vídeo (pregrabado) | ➖ N/A | No hay contenido de audio/vídeo pregrabado. |
| 1.2.2 Subtítulos (pregrabado) | ➖ N/A | Ídem. |
| 1.2.3 Audiodescripción o alternativa | ➖ N/A | Ídem. |
| 1.3.1 Información y relaciones | ✅ | fieldset/legend en opciones de respuesta; label htmlFor en todos los formularios; landmarks header/main; listas reales; headings jerárquicos corregidos. |
| 1.3.2 Secuencia significativa | ✅ | DOM en orden lógico (verificado en runner y paneles). |
| 1.3.3 Características sensoriales | ✅ | Las instrucciones no dependen de forma/posición/color. |
| 1.4.1 Uso del color | ✅ | Tabs, chips, temporizador y severidades tienen indicador no cromático (subrayado, ícono, etiqueta textual). |
| 1.4.2 Control de audio | ➖ N/A | Sin audio automático. |
| 2.1.1 Teclado | ✅ | Todo operable por teclado (controles nativos + Radix); el lockdown no bloquea Tab/flechas. |
| 2.1.2 Sin trampa de teclado | ✅ | Diálogos Radix con foco atrapado intencional y salida por Esc. |
| 2.1.4 Atajos de teclado de un carácter | ✅ | No hay atajos de un carácter. |
| 2.2.1 Tiempo ajustable | ✅ | El límite del examen es esencial (excepción de la norma); además hay acomodaciones por alumno (factor 1.25×/1.5×/2× recalculado en servidor) desde batch5. |
| 2.2.2 Pausar, detener, ocultar | ✅ | El temporizador no parpadea; sin contenido en movimiento automático. |
| 2.3.1 Destellos | ✅ | Nada supera 3 destellos/segundo. |
| 2.4.1 Evitar bloques | ✅ | Skip link "Saltar al contenido principal" en el layout. |
| 2.4.2 Página titulada | ✅ | title.template + metadata por página (incluida la de login). |
| 2.4.3 Orden del foco | ✅ | Gestión de foco al cambiar de pregunta y de fase en el runner. |
| 2.4.4 Propósito del enlace (en contexto) | ✅ | Enlaces con texto descriptivo. |
| 2.5.1 Gestos de puntero | ✅ | Sin gestos multipunto ni basados en trayectoria. |
| 2.5.2 Cancelación del puntero | ✅ | Acciones en click, no en down. |
| 2.5.3 Etiqueta en el nombre | ✅ | Nombres accesibles coinciden con el texto visible. |
| 2.5.4 Activación por movimiento | ✅ | Nada se activa por movimiento del dispositivo. |
| 3.1.1 Idioma de la página | ✅ | lang="es". |
| 3.2.1 Al recibir el foco | ✅ | Sin cambios de contexto al enfocar. |
| 3.2.2 Al introducir datos | ✅ | Sin cambios de contexto al escribir (autoguardado silencioso). |
| 3.2.6 Ayuda consistente | ✅ | Navegación y acciones consistentes entre vistas. |
| 3.3.1 Identificación de errores | ✅ | aria-invalid + aria-describedby + role="alert" en formularios. |
| 3.3.2 Etiquetas o instrucciones | ✅ | Todos los campos con label asociado; las respuestas del examen con aria-labelledby al enunciado. |
| 3.3.7 Entrada redundante | ✅ | No se pide dos veces la misma información. |
Nivel AA
| Criterio | Estado | Observaciones |
|---|---|---|
| 1.2.4 Subtítulos (en vivo) | ➖ N/A | Sin contenido en vivo. |
| 1.2.5 Audiodescripción | ➖ N/A | Ídem. |
| 1.3.4 Orientación | ✅ | Sin bloqueo de orientación de pantalla. |
| 1.3.5 Identificar propósito de entrada | ✅ | autoComplete en login y formularios de alta. |
| 1.4.3 Contraste mínimo | ✅ | Tokens de estado rehechos con pares texto/fondo medidos ≥4.5:1; white-label deriva --primary-foreground por luminancia; muted-foreground oscurecido. Verificado con axe en las 18 rutas auditadas (2026-07-24), que encontró 4 incumplimientos que la revisión estática no podía detectar —el color resuelto con opacidad y herencia no se ve leyendo el marcado— y quedaron corregidos: --medida daba 4,33:1 sobre el papel (ahora 4,94:1); los tokens -vivo, calibrados para superficies oscuras, se usaban como texto sobre papel con 2,0:1 y 2,39:1; un párrafo con opacidad sobre índigo daba 4,46:1; y el índigo pleno como texto sobre tinta, 3,01:1. Los tres últimos se resolvieron con tokens (--medida-texto, --cautela-texto, --indigo-texto) que el CSS resuelve según la superficie. |
| 1.4.4 Redimensionar texto | ✅ | Zoom al 200 % operativo y la heurística anti-DevTools ya no sanciona el zoom (degradada a evidencia; bug A-01 corregido). |
| 1.4.5 Imágenes de texto | ✅ | Sin imágenes de texto. |
| 1.4.10 Reflujo | ✅ | Filas de resultados con flex-wrap; sin scroll horizontal a 320 px. |
| 1.4.11 Contraste no textual | ✅ | Anillo de foco focus-visible con contraste ≥3:1; estados de controles no dependen del color. |
| 1.4.12 Espaciado de texto | ✅ | Sin contenedores de altura fija que recorten al aumentar el espaciado. |
| 1.4.13 Contenido al pasar o enfocar | ✅ | Sin popups personalizados de hover/focus. |
| 2.4.5 Múltiples vías | ✅ | Navegación por secciones y listados; breadcrumbs implícitos en títulos. |
| 2.4.6 Encabezados y etiquetas | ✅ | Encabezados descriptivos por vista. |
| 2.4.7 Foco visible | ✅ | Anillo compartido focus-visible en botones/inputs/tabs/chips. |
| 2.4.11 Foco no oculto (mínimo) | ✅ | El overlay de proctoring es colapsable y no cubre el elemento enfocado en escritorio. |
| 2.5.7 Movimientos de arrastre | ✅ | Sin interacciones de arrastre. |
| 2.5.8 Tamaño del objetivo (mínimo) | ✅ | Objetivos ≥24 px CSS (opciones de respuesta con p-3, muy por encima). |
| 3.1.2 Idioma de las partes | ✅ | Contenido en español uniforme (anglicismos del dominio eliminados). |
| 3.2.3 Navegación consistente | ✅ | Shell de navegación único (DashboardShell). |
| 3.2.4 Identificación consistente | ✅ | Mismos íconos/etiquetas para las mismas acciones. |
| 3.3.3 Sugerencia ante errores | ✅ | Errores con mensaje accionable (no "Error 500" pelado). |
| 3.3.4 Prevención de errores (legal/financiero/datos) | ✅ | La entrega del examen exige confirmación con resumen de sin-responder (Radix AlertDialog con foco atrapado). |
| 3.3.8 Autenticación accesible | ✅ | Login email+contraseña sin rompecabezas cognitivos ni pruebas de memoria. |
| 4.1.3 Mensajes de estado | ✅ | role="alert"/aria-live en errores, avisos de strikes, estado offline, "respondidas X/Y" y panel del proctor. |
Salvedades declaradas (cumplimiento parcial)
- 1.3.1 / tablas de datos (parcial): los listados principales usan listas semánticas; si una vista futura introduce tablas de datos complejas, deberá usar
th scopeantes de declararse. - 2.4.11 Foco no oculto (parcial en pantallas <640 px): el overlay de proctoring puede tapar controles en pantallas muy pequeñas; es colapsable y el examen sigue operable, pero se recomienda rendir en pantalla ≥1024 px (documentado al alumno).
- Alcance de la auditoría automatizada: cubre todas las vistas del producto. El runner del examen entró el 2026-07-24 (verificación del sistema, preguntas y diálogo de entrega) y la segunda cámara en el teléfono (
/movil/[token]) el 2026-07-25, auditada en sus dos estados —antes de activar la cámara y transmitiendo—, ambas con cero violacionesserious/criticala la primera pasada. Ya no queda ninguna pantalla fuera del alcance automatizado.
Funciones de acomodación (más allá de la norma)
- Tiempo extra por alumno (1.25×/1.5×/2×) fijado por el docente por sesión, recalculado en el servidor y auditado (batch5).
- Exención de avisos automáticos por alumno: los eventos de bloqueo (foco/pegar/pestaña) se registran como evidencia sin sanción automática, para tecnologías de asistencia.
- El zoom del navegador nunca genera sanción (la heurística de DevTools es solo evidencia).
- Temporizador con avisos textuales además del color; mensajes de estado anunciados por lector de pantalla.
Esta declaración se basa en la evidencia de audit/05-uxui-a11y.md, audit/ronda2/REPORTE.md y audit/loop/ESTADO.md (tercera ronda). La auditoría automatizada es reproducible: npx playwright test tests/e2e/accesibilidad.spec.ts. Regenerar si cambian el flujo de examen, los tokens de color o el sistema de avisos.
tests/unit/vpat.test.ts vigila que este documento no se desalinee de la cobertura real: si axe empieza a auditar el runner, o deja de hacerlo, el test obliga a corregir la declaración en lugar de dejarla envejecer.