# Sistema de diseño: Encuestapp

Este documento es la fuente de verdad visual para las interfaces públicas de Encuestapp. La referencia principal es una experiencia de encuesta breve, cálida y editorial: debe sentirse humana, privada y fácil de completar, sin parecer un panel administrativo ni un formulario institucional genérico.

## 1. Contexto técnico detectado

- **Framework:** CodeIgniter 4.7 sobre PHP 8.2 o superior.
- **Renderizado:** vistas PHP del servidor en `app/Views`.
- **Frontend:** HTML, CSS y JavaScript nativos.
- **Estilos:** no hay Tailwind, Sass, CSS Modules ni otro preprocesador instalado.
- **Componentes:** no hay kit de UI, carpeta de primitivas ni sistema de diseño existente.
- **Build:** no hay `package.json`, TypeScript, Vite ni bundler frontend.

Las implementaciones deben respetar este stack. No introducir Tailwind, React, Vue, shadcn/ui, 21st.dev ni dependencias equivalentes sólo para reproducir el diseño. Crear parciales PHP y archivos CSS/JS nativos cuando la reutilización lo justifique. Los estilos de `app/Views/errors` pertenecen al framework y no son tokens del producto.

## 2. Dirección visual

**Atmósfera:** editorial cálida, serena y artesanal; como una hoja de papel de alta calidad sobre un escritorio iluminado. La interfaz debe comunicar cercanía y confianza sin perder precisión.

- **Densidad:** 4/10, aireada pero eficiente.
- **Variación:** 3/10, composición centrada y predecible para reducir carga cognitiva.
- **Movimiento:** 5/10, fluido y discreto; nunca ornamental en exceso.
- **Jerarquía:** una sola tarea por pantalla, una pregunta dominante y navegación inequívoca.
- **Personalidad:** lenguaje humano, formas suaves y una única nota terracota como acento.

La encuesta es el foco. La ambientación nunca debe competir con la pregunta, las opciones o el progreso.

## 3. Tokens de color

Definir estos valores una sola vez como propiedades personalizadas. Los componentes deben consumir los nombres semánticos, no repetir valores hexadecimales.

```css
:root {
  color-scheme: light;

  --color-canvas: #fbf7f0;
  --color-canvas-deep: #f3ece1;
  --color-surface: #ffffff;
  --color-surface-subtle: #fbf8f2;
  --color-ink: #1c1a17;
  --color-ink-hover: #2f2c27;
  --color-text-muted: #7d766a;
  --color-text-soft: #8a8378;
  --color-text-faint: #a39c8f;
  --color-border: #e9e2d5;
  --color-border-strong: #d8cfbe;
  --color-track: #efe8da;
  --color-accent: #c2531d;
  --color-accent-soft: #f4e3d3;
  --color-success: #3f8a4f;
  --color-error: #a83d32;
  --color-focus: #c2531d;

  --color-ambient-peach: #e7b48c;
  --color-ambient-sage: #c9d9c4;
  --color-ambient-sand: #e3cfa4;
}
```

### Reglas de uso

- `--color-ink` lleva títulos, texto primario, botones principales y estados seleccionados.
- `--color-accent` se reserva para progreso, foco, controles elegidos y pequeños indicadores. No usarlo en grandes superficies.
- `--color-success` sólo confirma una operación terminada; `--color-error` sólo comunica errores reales.
- Los tonos ambientales pueden aparecer únicamente en fondos desenfocados de baja opacidad.
- No usar negro puro, blanco como fondo de página, púrpuras neón, degradados saturados ni colores adicionales por sección.
- El contraste mínimo es WCAG AA: 4.5:1 para texto normal y 3:1 para texto grande o límites de controles esenciales.

## 4. Tipografía

- **Display:** `Fraunces`, serif moderna, pesos 500–700. Usarla sólo en preguntas, títulos de confirmación y encabezados editoriales.
- **Interfaz y cuerpo:** `Inter`, `ui-sans-serif`, `system-ui`, sans-serif, pesos 400–700.
- **Cifras y metadatos:** Inter con números tabulares cuando el progreso o las estadísticas cambien.

Importar Fraunces e Inter de forma centralizada. Si las fuentes remotas no están disponibles, la página debe conservar jerarquía y legibilidad con las alternativas declaradas.

```css
:root {
  --font-display: "Fraunces", ui-serif, serif;
  --font-body: "Inter", ui-sans-serif, system-ui, sans-serif;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-body: 1rem;
  --text-question: clamp(1.625rem, 1.45rem + 0.8vw, 1.875rem);
  --text-title: clamp(1.875rem, 1.6rem + 1.2vw, 2.5rem);

  --leading-tight: 1.15;
  --leading-body: 1.6;
}
```

Los párrafos no deben superar 65 caracteres por línea. Evitar mayúsculas salvo en etiquetas breves de progreso o campos; cuando se usen, aplicar tracking entre `0.08em` y `0.14em`.

## 5. Espaciado, forma y elevación

Usar una escala base de 4 px:

```css
:root {
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-14: 3.5rem;

  --radius-control: 1rem;
  --radius-card: 1.75rem;
  --radius-pill: 999px;

  --shadow-card: 0 30px 60px -25px rgb(28 26 23 / 0.35);
  --shadow-selected: 0 6px 18px -8px rgb(194 83 29 / 0.45);
  --shadow-action: 0 10px 20px -8px rgb(28 26 23 / 0.5);
}
```

- El radio de 28 px pertenece al contenedor principal; las opciones usan 16 px y las acciones primarias forma de píldora.
- Las sombras deben estar teñidas con el color tinta y tener bordes difusos. No usar glows.
- La elevación sólo separa la encuesta del ambiente. Dentro de la tarjeta, preferir bordes, fondos sutiles y espacio.
- El borde estándar es de 1 px; opciones seleccionables usan 2 px para que el estado sea visible.

## 6. Composición y layout

- El flujo principal ocupa al menos `100dvh`, centrado en ambos ejes cuando el contenido cabe y alineado arriba cuando crece.
- Contenedor de encuesta: ancho máximo de `36rem` (576 px), ancho fluido y margen horizontal mínimo de 16 px.
- Espaciado exterior: entre 56 y 80 px verticales según viewport.
- Padding interior: 28 px en móvil y 40 px desde 640 px.
- Altura mínima del área de pregunta: 420 px en escritorio; en móvil debe crecer naturalmente, nunca recortar contenido.
- La cabecera de progreso, el panel y la navegación forman regiones separadas dentro de una sola tarjeta.
- Las opciones se muestran en una columna en móvil y dos columnas desde 640 px cuando sus textos permanecen legibles.
- Nunca provocar scroll horizontal. No fijar alturas en controles con contenido variable.
- Los elementos ambientales son decorativos, quedan detrás del contenido y llevan `aria-hidden="true"`.

El fondo combina un degradado radial muy tenue, tres manchas desenfocadas y una retícula al 4% de opacidad. Debe existir una versión simplificada sin filtros para dispositivos de bajo rendimiento y para `prefers-reduced-motion`.

## 7. Componentes y estados

### Indicador de tiempo

Píldora oscura, centrada sobre la tarjeta, texto de 11–12 px en mayúsculas y un pequeño punto melocotón. Debe indicar una expectativa real, por ejemplo: “Encuesta de 2 minutos”.

### Progreso

Mostrar “Paso N de M” y porcentaje. La barra tiene 6 px de alto, pista cálida y relleno terracota. Actualizar `aria-valuenow`, `aria-valuemin`, `aria-valuemax` y un nombre accesible al cambiar de paso.

### Opciones de selección única

- Toda la tarjeta es un `label` asociado a un `input[type="radio"]` real.
- No ocultar el input con `display: none`; usar una técnica visualmente oculta que conserve foco y semántica.
- Reposo: superficie blanca y borde cálido.
- Hover: elevación máxima de 2 px y borde más firme.
- Seleccionado: borde terracota, fondo terracota suave y sombra seleccionada.
- Foco visible: anillo de 3 px con separación de 2 px.
- Cada opción tiene un título corto y una explicación útil; no repetir información.

### Escala de valoración

Cinco botones reales con `aria-pressed`. Los pictogramas emocionales son una ayuda secundaria y deben acompañarse de una etiqueta textual accesible (“1, Muy mala” a “5, Excelente”). El estado activo invierte tinta y papel y se eleva 3 px. No depender sólo del color o del emoji.

### Chips multiselección

Botones de al menos 44 px de alto con `aria-pressed`. Reposo con borde; activo con fondo tinta y texto papel. Los emojis temáticos son opcionales y decorativos (`aria-hidden="true"`), nunca sustituyen el texto.

### Campo de comentario

Etiqueta siempre visible arriba, indicador “opcional” discreto y textarea de altura flexible. El foco usa tinta o terracota; el error aparece debajo con texto concreto. No usar la etiqueta como placeholder.

### Navegación

- Acción primaria a la derecha: “Continuar” y, en el último paso editable, “Enviar encuesta”.
- Acción secundaria “Atrás” a la izquierda; puede ocultarse visualmente en el primer paso sin alterar bruscamente el layout.
- Botones deshabilitados deben conservar contraste suficiente y exponer `disabled` de forma nativa.
- Durante el envío, bloquear dobles clics y cambiar el contenido por “Enviando…”, manteniendo el ancho del botón.

### Confirmación

Icono de check verde dibujado, título Fraunces, mensaje breve y un resumen opcional. No mostrar datos sensibles ni afirmar que la respuesta llegó si el servidor todavía no la confirmó.

## 8. Estados de producto obligatorios

- **Carga inicial:** esqueleto con las dimensiones del progreso, pregunta y opciones; no spinner aislado.
- **Envío:** botón ocupado, controles bloqueados y anuncio mediante una región `aria-live="polite"`.
- **Éxito:** reemplazar el formulario sólo después de una respuesta exitosa del servidor.
- **Error de validación:** conservar respuestas, llevar el foco al primer campo inválido y explicar cómo corregirlo.
- **Error de red/servidor:** mensaje dentro de la tarjeta, opción clara para reintentar y respuestas locales intactas.
- **Encuesta vacía o no disponible:** explicar que no hay preguntas disponibles y ofrecer una salida segura; no renderizar una tarjeta en blanco.
- **Sesión expirada o encuesta cerrada:** mensaje específico, sin reutilizar un 404 genérico.

## 9. Movimiento e interacción

```css
:root {
  --duration-fast: 150ms;
  --duration-normal: 180ms;
  --duration-panel: 450ms;
  --ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-progress: cubic-bezier(0.65, 0, 0.35, 1);
}
```

- Entrada de panel: opacidad de 0 a 1 y traslación vertical de 10 px a 0 durante 450 ms.
- Opciones: transiciones de 150–180 ms para `transform`, color, borde y sombra.
- Fondo: flotación lenta de 14 s, con variaciones de fase; nunca debe mover contenido.
- Check de éxito: dibujar trazo sólo una vez después de confirmar el envío.
- Animar preferentemente `transform` y `opacity`. La barra de progreso puede animar su escala horizontal desde el origen izquierdo en lugar del ancho.
- Respetar `prefers-reduced-motion: reduce`: detener blobs, eliminar desplazamientos y mostrar inmediatamente paneles y check.

## 10. Contenido y tono

- Español claro, cercano y neutral; frases breves y acciones concretas.
- Una pregunta por paso. Explicar por qué se solicita un dato sólo cuando aporte confianza.
- Usar contenido real del producto; nunca lorem ipsum.
- Evitar clichés como “eleva tu experiencia”, “sin límites”, “revolucionario” o “la próxima generación”.
- No prometer privacidad absoluta sin respaldo. Preferir: “Usaremos tus respuestas únicamente para mejorar este servicio”.
- No usar nombres ficticios genéricos ni métricas inventadas.

## 11. Accesibilidad y comportamiento

- HTML semántico: `main`, `form`, `fieldset`, `legend`, botones e inputs nativos.
- Cada control interactivo debe tener un objetivo mínimo de 44 × 44 px.
- El teclado debe completar todo el flujo; Enter no debe enviar antes del último paso.
- Al avanzar, mover el foco al título de la nueva pregunta mediante `tabindex="-1"`, sin desplazar de forma agresiva.
- Anunciar cambios de paso y errores con regiones vivas mesuradas.
- Persistir el estado al navegar hacia atrás. No perder respuestas después de un error de envío.
- Incluir protección CSRF de CodeIgniter en el formulario y validar nuevamente en el servidor.
- No almacenar respuestas sensibles en `localStorage` sin una decisión explícita de producto.

## 12. Responsive

- **Menos de 640 px:** una columna, padding de 28 px o menos, botones de valoración distribuidos sin reducir objetivos táctiles.
- **Desde 640 px:** opciones breves pueden formar dos columnas y el padding sube a 40 px.
- **Alturas reducidas:** alinear el contenido al inicio y permitir scroll vertical natural.
- **Texto:** títulos fluidos con `clamp()`; cuerpo nunca menor de 14 px y preferentemente 16 px para contenido continuo.
- **Área segura:** contemplar `env(safe-area-inset-*)` cuando la encuesta se presente como experiencia de pantalla completa.

## 13. Patrones prohibidos

- No pegar el boceto Tailwind ni cargar Tailwind por CDN.
- No agregar un framework frontend o kit de componentes para esta pantalla.
- No dispersar colores, radios y sombras como valores mágicos.
- No usar negro puro, neón, glows, glassmorphism excesivo ni degradados de texto.
- No convertir cada región en una tarjeta independiente.
- No usar spinners genéricos, alerts del navegador ni errores que borren el formulario.
- No ocultar inputs de forma que pierdan foco o accesibilidad.
- No depender únicamente de color, movimiento o emojis para comunicar estado.
- No animar sin alternativa para movimiento reducido.
- No usar `100vh`; usar `100dvh` con fallback razonable.
- No presentar datos de demostración como respuestas reales.

## 14. Criterio de terminado

Una pantalla se considera alineada con este sistema cuando:

1. Utiliza vistas PHP, CSS y JavaScript nativos compatibles con CodeIgniter.
2. Consume los tokens semánticos de este documento y no introduce una segunda paleta.
3. Conserva la jerarquía: contexto breve, progreso, una pregunta, respuesta y navegación.
4. Implementa teclado, foco visible, lectores de pantalla y movimiento reducido.
5. Cubre carga, vacío, validación, envío, error y éxito sin perder respuestas.
6. Funciona sin scroll horizontal desde 320 px y mantiene objetivos táctiles de 44 px.
7. No añade dependencias ni configuración global sin justificar primero la carencia.
