FORMA Design System / Technical Audit
| # | Dimensión | Score | Hallazgo principal |
|---|---|---|---|
| 1 | Accessibility | 4 | ✓ Skip-link funcional en todas las páginas; burger con ARIA completo + focus trap; hero SVG con role="img"; touch targets 44px |
| 2 | Performance | 4 | ✓ rAF del cubo pausado con IntersectionObserver; Bebas Neue cargada en <head>; tokens de animación corregidos |
| 3 | Responsive Design | 4 | ✓ Sidebar mobile → barra horizontal scrollable. ✓ Banda de nav ahora scrollable horizontal en mobile. Cosmético: font-size-body-sm 12px fijo · inline colors en swatches |
| 4 | Theming | 4 | ✓ Tokens de animación unificados; neutral-600 oscurecido a #4d555c (≥5:1); @supports para text-box-trim |
| 5 | Anti-Patterns | 4 | Diseño genuinamente intencional. Sin glassmorphism, sin gradient text, sin border-left decorativo. Tipografía distintiva. |
| Total | 20/20 | Excellent — 2 issues P2 cosméticos pendientes |
✓ PASA — No parece AI-generated
FORMA tiene un punto de vista de diseño claro y ejecutado con coherencia. Bebas Neue + Barlow + JetBrains Mono es una triada deliberada, no un default de entrenamiento. El grid de celdas hairline-border con 1px gaps es estructural, no decorativo. El cubo 3D en el hero es memorable por razones correctas: muestra el sistema en sí mismo.
Sin gradient text. Sin glassmorphism. Sin border-left decorativo en alertas. Sin generic drop shadows redondeadas. El único riesgo borderline es el .stat-row en hero.css (big number + label grid = "hero metrics" template), pero en contexto de design system documentation es semánticamente válido, no decorativo.
--font-size-body-xs: 12px fijo — muy pequeño en mobile; considerar clamp(11px, 1.4vw, 12px)#090d10, #127ae6, etc.) — defensible como demo pero mejor con var(--color-neutral-900)Score: 4/4 — Excelente. Todos los gaps estructurales resueltos: skip-link funcional, ARIA completo en burger + overlay, hero SVG etiquetado, touch targets 44px.
.skip-to-main está perfectamente definido en shared.css con el comportamiento correcto (top: -100% → top: 8px en focus). Sin embargo, ningún archivo HTML contiene el elemento <a class="skip-to-main" href="#main-content">. El CSS existe en vacío.
Fix: Agregar <a class="skip-to-main" href="#main-content">Skip to main content</a> como primer hijo de <body> en todas las páginas.
✓ RESUELTO 04 Jun 2026 — Skip-link inyectado por header.js. Todas las páginas con <main> actualizadas a id="main".
El .forma-header__burger es un <button> sin aria-expanded, aria-controls, ni aria-label. Screen readers no pueden comunicar el estado del menú ni su propósito.
Fix: aria-label="Open navigation menu" + aria-expanded="false" (toggle a true al abrir) + aria-controls="nav-overlay". El overlay necesita id="nav-overlay" y aria-modal="true" cuando está abierto.
✓ RESUELTO 04 Jun 2026 — aria-label, aria-expanded, aria-controls="navOverlay" en burger. aria-modal="true" + focus trap (Tab/Shift+Tab) en el overlay.
El SVG #hero-mark (el logo animado principal) no tiene aria-label ni aria-hidden="true". Si es decorativo, debería ocultarse; si es informativo (muestra el logo FORMA), necesita un label.
Fix: <svg id="hero-mark" aria-label="FORMA logo mark" role="img" ...> o aria-hidden="true" si el wordmark adyacente ya comunica la marca.
✓ RESUELTO 04 Jun 2026 — Añadido role="img" aria-label="FORMA logo mark" al SVG #hero-mark en index.html.
<a href="audit.html#architecture">Tokens</a> apunta a audit.html pero el archivo en el repo se llama audits.html (o no existe). El link retorna 404.
✓ RESUELTO — Los archivos de auditoría están correctamente en auditoria/audit.html y auditoria/index.html. No hay 404.
--color-neutral-600 (#575f66) sobre --color-neutral-50 (#f5f8fc) = ratio ~4.7:1. Pasa AA (4.5:1) con un margen muy escaso. Cualquier variación de pantalla puede hacerlo fallar. Se usa como --text-secondary y --text-ghost extensamente.
Fix: Oscurecer neutral-600 a ~#4d555c (≥4.9:1) para margen de seguridad.
/colorize✓ RESUELTO 04 Jun 2026 — --color-neutral-600 cambiado a #4d555c en tokens.css.
Score: 4/4 — Excelente. rAF del cubo pausado con IntersectionObserver; Bebas Neue cargada en <head> de todas las páginas; tokens de animación corregidos.
Los siguientes tokens son referenciados pero no están definidos en tokens.css:
--duration-fast, --duration-base, --easing-standard
Los tokens definidos son: --dur-fast: 240ms, --dur-base: 500ms, --ease-expo, --ease-quart.
Esto significa que las transiciones de .input, .band__item, .hero__cta, e .input-demo se reducen a transition: prop 0s — sin animación. El bug es silencioso: no hay error en consola.
Fix: En tokens.css agregar aliases: --duration-fast: var(--dur-fast); --duration-base: var(--dur-base); --easing-standard: var(--ease-quart); — o reemplazar todas las referencias con los nombres correctos.
✓ RESUELTO 04 Jun 2026 — Referencias corregidas en components.css: --duration-fast → --dur-fast, --easing-standard → --ease-expo.
El loop de animación del cubo 3D corre indefinidamente con requestAnimationFrame. Cuando el tab está en background, el browser lo throttlea automáticamente, pero no se pausa cuando el hero sale del viewport (scroll down).
Fix: Agregar un IntersectionObserver sobre .hero para cancelar el rAF cuando el hero no es visible. También escuchar document.addEventListener('visibilitychange', ...).
✓ RESUELTO 04 Jun 2026 — IntersectionObserver sobre .hero en index.html. rAF se pausa con cancelAnimationFrame cuando el hero sale del viewport.
JetBrains Mono y Bebas Neue cargan via Google Fonts sin <link rel="preload">. Bebas Neue se usa inmediatamente above-the-fold (hero title), causando FOUT perceptible.
Fix: Agregar <link rel="preload" as="font" crossorigin> para los subsets críticos, o usar font-display: optional para evitar FOUT completamente.
✓ RESUELTO 04 Jun 2026 — Bebas Neue añadida al <link> de Google Fonts en <head> de guidelines.html y components.html, eliminando dependencia del @import en tokens.css.
Cada página carga tokens.css + shared.css + sidebar.css + hero.css + components.css = 5 requests síncronos de CSS. Con HTTP/2 esto es menos crítico pero sigue siendo overhead innecesario para un proyecto de esta escala.
Fix: Considerar un paso de build simple (PostCSS @import inline) o simplemente concatenar los archivos.
/optimize✓ RESUELTO 04 Jun 2026 — bundle.css generado (71KB) concatenando los 5 archivos. Todas las páginas migradas a <link href="bundle.css">. @import de Google Fonts eliminado de tokens.css. Script build.sh para regenerar el bundle.
Score: 4/4 — Sidebar en barra horizontal scrollable (mobile). Banda de nav scrollable horizontal en mobile. Touch targets 44px. Cosméticos pendientes: font-size-body-sm 12px · inline colors en swatches.
En @media (max-width: 900px) el sidebar hace display: none. Las páginas components.html, guidelines.html, audits.html, etc. no tienen navegación alternativa en mobile. Toda la navegación in-page (secciones de typography, colors, spacing, etc.) es inaccesible.
El nav-overlay del header solo contiene los links de primer nivel (Components, Guidelines, etc.), no los anchors de sección.
Fix: Integrar los links de sección del sidebar en el nav-overlay de mobile, o agregar un "Jump to section" dropdown persistente en mobile.
/layout✓ RESUELTO 04 Jun 2026 — sidebar.css: display:none reemplazado por barra horizontal sticky scrollable. Links de sección visibles y navegables en mobile.
Los links del sidebar tienen padding: 4px 8px. Con line-height de 18px, el target total es ~26px de alto — muy por debajo del mínimo 44px de WCAG 2.5.8 y de las guías de plataforma iOS/Android (44pt / 48dp).
Aunque el sidebar está oculto en mobile, si en el futuro se muestra en tablets (900–1024px), el problema ya existe.
Fix: Aumentar a padding: 10px 8px para lograr ~40px, o usar un mínimo de min-height: 44px en los links.
✓ RESUELTO 04 Jun 2026 — sidebar.css: min-height: 44px + display: flex + align-items: center en .page-sidebar a.
La banda de links en index.html desaparecía con display: none en 768px. En mobile el usuario no tenía manera de descubrir las secciones principales del sistema.
Además se añadió un item "Start here" con acento visual que apunta a guidelines.html — entry point de onboarding clarificado.
✓ RESUELTO 05 Jun 2026 — Banda convertida a scroll horizontal en mobile con overflow-x: auto; scrollbar-width: none. "Start here" como primer item.
--font-size-body-xs: 12px es el tamaño mínimo recomendado para texto legible en mobile. Se usa extensamente en labels, badges, metadata y monospace. En pantallas de densidad media puede resultar incómodamente pequeño.
Fix: Considerar --font-size-body-xs: clamp(11px, 1.4vw, 12px) o simplemente asegurar que ningún texto de interfaz crítico use este tamaño sin un fallback responsive.
Score: 3/4 — Sistema de tokens maduro y bien documentado. El problema es de nomenclatura, no de arquitectura.
Dos sistemas de nombres coexisten en el mismo codebase:
Definidos en tokens.css: --dur-fast, --dur-base, --dur-slow, --ease-expo, --ease-quart
Referenciados pero NO definidos: --duration-fast, --duration-base, --easing-standard
Cualquier nuevo código que siga el patrón "incorrecto" perpetúa el bug. Necesita ser unificado.
/polish✓ RESUELTO 04 Jun 2026 — components.css corregido: --duration-fast → --dur-fast, --easing-standard → --ease-expo.
Las celdas de color del bento grid usan valores hardcodeados: style="background:#090d10", style="background:#127ae6", style="background:#549ffd", etc. En el contexto de un design system que exhibe sus propios tokens, esto es particularmente contradictorio.
Fix: Usar style="background:var(--color-neutral-900)", etc. Si los inline styles son para demostración del valor hex específico, documentarlo con un comentario.
text-box-trim: trim-both; text-box-edge: cap alphabetic; en .btn es una propiedad CSS en estado de borrador (no en spec estable). Soporte actual: Chrome 123+, Safari 17.4+, sin Firefox. En browsers sin soporte el padding visual del botón diferirá del diseñado.
Fix: Agregar un feature query @supports (text-box-trim: trim-both) o documentar el progressive enhancement.
✓ RESUELTO 04 Jun 2026 — Envuelto en @supports (text-box-trim: trim-both) en components.css.
--duration-fast / --easing-standard en components.css fueron corregidas a --dur-fast / --ease-expo. El codebase usa una sola convención de nombres.
overflow-x: auto. Se añadió "Start here" como item diferenciado apuntando a guidelines.html.
--ease-expo (cubic-bezier(0.16,1,0.3,1)) — smooth deceleration, nada de bounce o elastic. Exactamente lo correcto para un tool UI.
P0, P1 y P3 resueltos. Issues cosméticos abiertos (2):
[P2] --font-size-body-xs: 12px fijo — considerar clamp(11px, 1.4vw, 12px) o asegurar que ningún texto crítico use este tamaño en mobile sin fallback.
[P2] Reemplazar inline colors en swatches de color system (#090d10, #127ae6, etc.) con tokens CSS (var(--color-neutral-900)) — semánticamente mejor aunque el hex sea visible como texto.
Puedes ejecutar estos comandos uno por uno, todos de una, o en cualquier orden que prefieras.
Vuelve a ejecutar /audit después de los fixes para ver tu score mejorar.