# Sistema de diseño

Catálogo de los tokens de la plataforma: qué existe, cuánto vale y cuándo se
usa cada uno.

**Regla única:** en las pantallas no se escriben valores sueltos. Ni un
`padding: 13px`, ni un `#046600`, ni un `border-radius: 10px`. Si necesita una
medida, sale de aquí. Si aquí no está, se añade aquí primero y después se usa.

Los tokens viven en dos sitios complementarios:

- **Marca** (`--marca-*`): los genera el servidor desde `config/branding.php`
  y los imprime en `:root` (ver `docs/BRANDING.md`).
- **Sistema** (`--esp-*`, `--txt-*`, `--radio-*`, …): están en
  `resources/css/tokens.css` y se calculan a partir de los de marca.

---

## 1. Color

### Marca

| Variable                  | FEDEF     | Cuándo                                                |
| ------------------------- | --------- | ----------------------------------------------------- |
| `--marca-primario`        | `#046600` | Acción principal, enlaces, elementos de marca          |
| `--marca-primario-oscuro` | `#023B01` | Fondos profundos, degradados, cabecera de proyección   |
| `--marca-primario-claro`  | `#53AF07` | Realce sobre fondo oscuro, estado activo               |
| `--marca-primario-texto`  | `#FFFFFF` | Texto sobre el primario. **Ya calculado, no lo elija** |
| `--marca-secundario`      | `#C4EC1B` | Segunda voz: subrayados, series de datos, insignias    |
| `--marca-acento`          | `#FFBA00` | Uso escaso: destacar un dato, una insignia             |
| `--marca-primario-rgb`    | `4 102 0` | Para transparencias: `rgb(var(--marca-primario-rgb) / .2)` |

También existen `--marca-secundario-rgb`, `--marca-acento-rgb` y
`--marca-texto-rgb` con el mismo propósito.

### Escalas derivadas

Diez tonos por cada color, del 50 (casi blanco) al 900 (casi negro), con el
color de marca intacto en el 600. Cada tono trae su compañero `…-texto` con el
color legible encima, ya decidido por medición.

```
--marca-primario-50 … --marca-primario-900
--marca-primario-50-texto … --marca-primario-900-texto
--marca-secundario-50 … --marca-secundario-900
--marca-secundario-50-texto … --marca-secundario-900-texto
```

Guía rápida de uso de la escala primaria:

| Tono | Para                                                    |
| ---- | ------------------------------------------------------- |
| 50   | Fondo de fila resaltada, de aviso de marca               |
| 100  | Fondo de insignia, elemento seleccionado                 |
| 200  | Borde de marca                                           |
| 300  | Separador fuerte, cuarta serie de una gráfica            |
| 400  | Tercera serie de una gráfica                             |
| 500  | Segunda serie, hover de superficies claras               |
| 600  | **Botón principal, enlace, icono de marca**              |
| 700  | Ese botón al pasar el puntero                            |
| 800  | Ese botón pulsado                                        |
| 900  | Cabecera de marca, fondo de la proyección                |

### Estados

Cuatro colores, cada uno con cuatro variantes. **Nunca son la única señal**: van
siempre con texto o icono.

| Variable base           | FEDEF     | `-suave` (fondo) | `-borde` | `-fuerte` (texto) |
| ----------------------- | --------- | ---------------- | -------- | ----------------- |
| `--marca-exito`         | `#12803A` | `#E7F2EB`        | `#B3D6C0`| `#117B38`         |
| `--marca-atencion`      | `#FFBA00` | `#FFF8E6`        | `#FFE9AD`| `#8F6800`         |
| `--marca-peligro`       | `#D92D20` | `#FBEAE9`        | `#F3BCB8`| `#C8291D`         |
| `--marca-informacion`   | `#0B6BA8` | `#E7F0F6`        | `#B1D0E3`| `#0B6BA8`         |

Receta de un aviso:

```css
.aviso-peligro {
    background: var(--marca-peligro-suave);
    border: var(--borde-fino) solid var(--marca-peligro-borde);
    border-left: var(--borde-realce) solid var(--marca-peligro);
    color: var(--marca-peligro-fuerte);
    border-radius: var(--radio-md);
    padding: var(--esp-3) var(--esp-4);
}
```

### Neutros

| Variable                  | FEDEF     | Cuándo                                              |
| ------------------------- | --------- | --------------------------------------------------- |
| `--marca-fondo`           | `#F3F5EF` | Fondo general de la aplicación                       |
| `--marca-superficie`      | `#FFFFFF` | Tarjetas, tablas, paneles, diálogos                  |
| `--marca-superficie-alt`  | `#F7F9F4` | Filas cebra, encabezado de tabla, zona hundida       |
| `--marca-borde`           | `#DFE4DA` | Separaciones decorativas                             |
| `--marca-borde-fuerte`    | `#7C8B78` | Borde de campo o control (cumple 3 a 1)              |
| `--marca-texto`           | `#0E1A0C` | Texto principal                                      |
| `--marca-texto-tenue`     | `#5C6B59` | Etiquetas, ayudas, metadatos. **No aclararlo más**   |

---

## 2. Espaciado

Retícula de 4 px multiplicada por `--marca-densidad`
(`compacta` 0,85 · `comoda` 1 · `amplia` 1,15).

| Token       | Cómoda | Cuándo                                          |
| ----------- | ------ | ----------------------------------------------- |
| `--esp-1`   | 4 px   | Separar un icono de su texto                     |
| `--esp-2`   | 8 px   | Dentro de un control, entre elementos pegados    |
| `--esp-3`   | 12 px  | Relleno vertical de un campo                     |
| `--esp-4`   | 16 px  | Relleno de tarjeta pequeña, hueco entre campos   |
| `--esp-5`   | 20 px  | Hueco entre grupos de un formulario              |
| `--esp-6`   | 24 px  | Relleno de tarjeta                               |
| `--esp-8`   | 32 px  | Hueco entre bloques                              |
| `--esp-10`  | 40 px  | Relleno de panel                                 |
| `--esp-12`  | 48 px  | Separación entre secciones                       |
| `--esp-16`  | 64 px  | Aire de una sección destacada                    |
| `--esp-20`+ | 80 px+ | Solo en pantallas grandes y páginas de portada   |

`--esp-margen` es el margen lateral de página y crece solo: 16 px en celular,
32 px desde tableta, 48 px desde portátil. Úselo en vez de inventar márgenes.

Existen también `--esp-0`, `--esp-px`, `--esp-7`, `--esp-14`, `--esp-24` y
`--esp-32`.

---

## 3. Tipografía

### Familias

| Token                     | Uso                                     |
| ------------------------- | --------------------------------------- |
| `--marca-fuente-texto`    | Todo el texto corrido                    |
| `--marca-fuente-titulos`  | Títulos y titulares                      |
| `--marca-fuente-mono`     | Códigos de acceso, cifras alineadas      |

En Tailwind: `font-sans`, `font-titulo`, `font-mono`.

### Tamaños

| Token        | Valor      | Cuándo                                                     |
| ------------ | ---------- | ---------------------------------------------------------- |
| `--txt-2xs`  | 11 px      | Etiqueta en mayúsculas, insignia. Nunca un párrafo          |
| `--txt-xs`   | 12 px      | Metadato, pie de tabla                                      |
| `--txt-sm`   | 14 px      | Texto auxiliar, ayuda de campo                              |
| `--txt-base` | 16 px      | **Cuerpo.** Mínimo absoluto para lo que se lee en celular   |
| `--txt-md`   | 17 px      | Cuerpo de lectura larga                                     |
| `--txt-lg`   | 18 px      | Entradilla                                                  |
| `--txt-xl`   | 20 px      | Título de tarjeta                                           |
| `--txt-2xl`  | 24 px      | Título de sección                                           |
| `--txt-3xl`  | 30 px      | Título de página                                            |
| `--txt-4xl`  | 36 px      | Titular                                                     |
| `--txt-5xl`  | 48 px      | Titular grande                                              |
| `--txt-hero` | 32 → 56 px | Titular que se adapta solo, sin media queries               |
| `--txt-cifra`| 36 → 64 px | Cifra grande del panel y del monitor proyectado             |

Los campos de formulario **nunca** bajan de `--txt-base` en móvil: por debajo de
16 px, iOS hace zoom al enfocar y descuadra la pantalla.

### Altura de línea, grosor y trazo

| Token             | Valor  | Cuándo                          |
| ----------------- | ------ | ------------------------------- |
| `--alto-ajustado` | 1,1    | Titulares grandes               |
| `--alto-titulo`   | 1,25   | Títulos de sección y tarjeta    |
| `--alto-medio`    | 1,45   | Texto corto, controles          |
| `--alto-texto`    | 1,6    | Párrafos                        |
| `--alto-suelto`   | 1,75   | Listas largas, lectura densa    |

Grosores: `--peso-normal` 400, `--peso-medio` 500, `--peso-semi` 600,
`--peso-fuerte` 700, `--peso-extra` 800.

Trazo: `--trazo-titular` −0,022em (titulares grandes), `--trazo-titulo`
−0,012em, `--trazo-normal` 0, `--trazo-etiqueta` 0,06em (etiquetas en
mayúsculas; sin él, las mayúsculas se apelmazan).

### Anchos de lectura

`--ancho-texto` 68ch · `--ancho-formulario` 26rem · `--ancho-contenido` 75rem ·
`--ancho-ancho` 96rem. Un párrafo que pasa de 68 caracteres por línea se lee
peor, y en la proyección se nota mucho.

### Anchos de pieza

`--ancho-nota` 18rem (globo de ayuda) · `--ancho-columna` 24rem (base cómoda de
una columna antes de que la fila envuelva) · `--ancho-dialogo-sm` 24rem ·
`--ancho-dialogo-md` 32rem · `--ancho-dialogo-lg` 48rem (el tamaño `xl` de
`Modal` usa `--ancho-contenido`). Ninguna de estas medidas se escribe a mano en
un componente: si un diálogo nuevo pide otro tamaño, se añade aquí primero.

---

## 4. Curvatura

Todo sale de `--marca-radio-base` (0,75rem en FEDEF). Una sola perilla cambia el
carácter de la plataforma.

| Token              | FEDEF     | Tailwind            | Cuándo                        |
| ------------------ | --------- | ------------------- | ----------------------------- |
| `--radio-xs`       | 0,25rem   | `rounded-minimo`    | Insignias, casillas           |
| `--radio-sm`       | 0,375rem  | `rounded-chico`     | Campos pequeños, etiquetas    |
| `--radio-md`       | 0,5rem    | `rounded-control`   | Botones y campos              |
| `--radio-lg`       | 0,75rem   | `rounded-tarjeta`   | Tarjetas                      |
| `--radio-xl`       | 1,125rem  | `rounded-panel`     | Paneles y secciones           |
| `--radio-2xl`      | 1,5rem    | `rounded-dialogo`   | Diálogos, hojas móviles       |
| `--radio-completo` | 9999px    | `rounded-pildora`   | Píldoras, avatares            |

Criterio: cuanto mayor la superficie, mayor el radio. Un botón con radio de
tarjeta se ve blando; una tarjeta con radio de botón se ve dura.

Las clases propias de Tailwind (`rounded-lg` y compañía) siguen valiendo lo de
siempre: no se pisaron, para no alterar las pantallas que otro equipo está
corrigiendo.

---

## 5. Elevación

Sombras teñidas con el verde hondo de la marca. La opacidad la multiplica
`--marca-sombra-alfa` (`plana` 0 · `suave` 0,6 · `media` 1 · `marcada` 1,5).

| Token              | Tailwind        | Cuándo                                   |
| ------------------ | --------------- | ---------------------------------------- |
| `--sombra-0`       | `shadow-none`   | Sin elevación                            |
| `--sombra-1`       | `shadow-1`      | Tarjeta en reposo                        |
| `--sombra-2`       | `shadow-2`      | Tarjeta con el puntero encima, botón     |
| `--sombra-3`       | `shadow-3`      | Desplegable, menú, ventana emergente     |
| `--sombra-4`       | `shadow-4`      | Diálogo                                  |
| `--sombra-5`       | `shadow-5`      | Elemento flotante sobre la proyección    |
| `--sombra-interna` | `shadow-interna`| Campo relleno, zona de arrastre          |
| `--sombra-linea`   | `shadow-linea`  | Borde de 1 px que no ocupa maqueta       |

No mezcle niveles al azar: la elevación es una jerarquía, no un adorno. Si dos
elementos flotan igual, llevan la misma sombra.

### Foco

| Token                 | Valor                          | Cuándo                                     |
| --------------------- | ------------------------------ | ------------------------------------------ |
| `--anillo-foco`       | 3 px del primario al 32 %      | Anillo de foco sobre fondo claro           |
| `--anillo-foco-claro` | 3 px blanco al 55 %            | Anillo de foco sobre fondo oscuro o foto   |
| `--anillo-grosor`     | 3px                            | Grosor del contorno                        |
| `--anillo-separacion` | 2px                            | Separación del contorno al elemento        |

`tokens.css` ya pinta un contorno visible en todo lo enfocable con teclado. Si
un componente dibuja el suyo, que no lo quite: quitar el foco sin sustituirlo
deja la plataforma inutilizable con teclado.

---

## 6. Bordes

`--borde-fino` 1px (separaciones) · `--borde-medio` 1,5px (campos y botones; se
ve más nítido que 1 px sin engordar) · `--borde-grueso` 2px (estado activo o
seleccionado) · `--borde-realce` 3px (barra lateral de aviso, pestaña activa).

---

## 7. Movimiento

Corto y con propósito. Nada por encima de 360 ms: con quince personas mirando la
proyección, una transición lenta parece un cuelgue.

| Token            | Valor  | Cuándo                          |
| ---------------- | ------ | ------------------------------- |
| `--dur-instante` | 80 ms  | Cambio de color al pulsar       |
| `--dur-rapida`   | 140 ms | Puntero encima, foco            |
| `--dur-media`    | 220 ms | Desplegables, pestañas          |
| `--dur-lenta`    | 360 ms | Diálogos, hojas, entradas       |

Ritmos que se repiten. No son transiciones de interfaz sino ciclos, por eso van
aparte; con movimiento reducido se paran igual que todo lo demás.

| Token          | Valor   | Cuándo                                    |
| -------------- | ------- | ----------------------------------------- |
| `--dur-giro`   | 640 ms  | Vuelta del indicador de espera            |
| `--dur-tictac` | 1000 ms | Un segundo real: cuenta regresiva y pulso |
| `--dur-vaiven` | 1400 ms | Ida y vuelta de la barra indeterminada    |

| Curva               | Cuándo                        |
| ------------------- | ----------------------------- |
| `--curva-estandar`  | Uso general                   |
| `--curva-entrada`   | Algo que aparece              |
| `--curva-salida`    | Algo que desaparece           |
| `--curva-suave`     | Movimiento continuo           |

Atajos: `--transicion-color` (color, fondo y borde) y `--transicion-forma`
(transformación y sombra). Anime solo `transform`, `opacity`, `color`,
`background-color`, `border-color` y `box-shadow`; animar `width`, `height`,
`top` o `left` provoca tirones en los celulares de la sala.

`prefers-reduced-motion: reduce` está atendido: quien lo pide en su sistema no
ve animaciones. No hay que hacer nada más en cada componente.

---

## 8. Capas

Rango cerrado. **Nunca escriba un `z-index` a mano.**

| Token             | Valor | Para                                    |
| ----------------- | ----- | --------------------------------------- |
| `--capa-fondo`    | 0     | Imagen o velo de fondo                  |
| `--capa-base`     | 1     | Contenido normal                        |
| `--capa-elevado`  | 10    | Tarjeta levantada, ficha arrastrada     |
| `--capa-pegajoso` | 20    | Encabezado de tabla pegado              |
| `--capa-cabecera` | 30    | Barra superior de la aplicación         |
| `--capa-menu`     | 40    | Desplegables y menús                    |
| `--capa-velo`     | 50    | Velo que atenúa el fondo de un diálogo  |
| `--capa-modal`    | 60    | Diálogo                                 |
| `--capa-aviso`    | 70    | Avisos y mensajes flotantes             |
| `--capa-ayuda`    | 80    | Globos de ayuda                         |
| `--capa-tope`     | 90    | Solo para lo que debe ver todo el mundo |

En Tailwind: `z-cabecera`, `z-modal`, `z-aviso`, etc.

---

## 9. Superposiciones

| Token               | Cuándo                                                     |
| ------------------- | ---------------------------------------------------------- |
| `--velo-claro`      | Atenuar contenido sobre fondo claro                        |
| `--velo-suave`      | Velo ligero sobre fotografía                               |
| `--velo-fuerte`     | Velo de un diálogo                                         |
| `--velo-marca`      | Degradado verde que garantiza el texto blanco sobre la foto del ingreso |
| `--degradado-marca` | Superficie de marca (cabecera de proyección, panel lateral) |
| `--vidrio`          | Valor para `backdrop-filter` en barras translúcidas        |
| `--desenfoque-suave` | `backdrop-filter` del velo de un diálogo: el fondo se reconoce pero no compite |

El tramo del `--velo-marca` que va del 0 % al 45 % (donde vive el texto del
panel de ingreso) está medido: por debajo de 0,88 de opacidad, el punto más
claro de la fotografía deja el texto pequeño por debajo de 4,5 a 1. Quien
cambie ese valor tiene que volver a medirlo, porque la fotografía la reemplaza
cada cliente y no puede ser ella la que decida la legibilidad.

---

## 10. Tacto y tamaños mínimos

| Token               | Valor | Cuándo                                            |
| ------------------- | ----- | ------------------------------------------------- |
| `--toque-min`       | 44px  | Mínimo absoluto de cualquier cosa que se toque    |
| `--control-alto-sm` | 36px  | Control secundario **solo en escritorio**         |
| `--control-alto`    | 44px  | Botón y campo estándar                            |
| `--control-alto-lg` | 52px  | Acción principal en móvil, botón de la proyección |
| `--icono-sm`        | 16px  | Icono dentro de texto pequeño                     |
| `--icono`           | 20px  | Icono de botón                                    |
| `--icono-lg`        | 24px  | Icono de cabecera                                 |

Los quince directivos participan desde su celular: un control por debajo de
44 px se falla al tocarlo. En Tailwind: `min-h-toque`, `min-w-toque`, `h-control`.

---

## 11. Puntos de corte

CSS no admite variables dentro de `@media`, así que en las consultas se escribe
el literal. Estas son las anchuras que **sí** se prueban:

| Ancho   | Qué es                          | Variable de referencia |
| ------- | ------------------------------- | ---------------------- |
| 360 px  | Celular pequeño                 | `--bp-movil`           |
| 390 px  | Celular normal                  | `--bp-movil-grande`    |
| 768 px  | Tableta                         | `--bp-tableta`         |
| 1024 px | Escritorio pequeño              | `--bp-escritorio`      |
| 1280 px | Portátil del facilitador        | `--bp-portatil`        |
| 1920 px | Proyección de la sala           | `--bp-proyeccion`      |
| 2560 px | Pantalla ancha                  | `--bp-panoramico`      |

En Tailwind se añadieron `xs` (360px), `proyeccion` (1920px) y `panoramico`
(2560px) a los puntos de corte normales.

Se diseña primero para 360 px y se va ampliando. Ninguna pantalla puede
desbordar a lo ancho en ninguna de esas anchuras.

---

## 12. Modo oscuro e impresión

- **Oscuro:** existe pero no se fuerza. Se activa con `data-tema="oscuro"` en el
  elemento raíz, o `data-tema="auto"` para seguir al sistema operativo. Solo
  cambian los neutros; la marca se mantiene.
- **Contraste alto:** con `prefers-contrast: more`, los bordes se refuerzan y el
  texto tenue pasa a texto principal. Automático.
- **Impresión:** el fondo pasa a blanco y las sombras desaparecen, para que las
  actas y los tableros salgan limpios en papel y en PDF.

---

## 13. Lista de comprobación antes de dar por buena una pantalla

1. ¿Algún valor escrito a mano que debería ser un token?
2. ¿Se ve completa a 360 px sin desborde horizontal?
3. ¿Todo lo tocable mide 44 × 44 px o más?
4. ¿Se recorre entera con el tabulador y se ve dónde está el foco?
5. ¿Algún estado se explica solo con color?
6. ¿El texto pequeño llega a 4,5 a 1 de contraste?
7. ¿Las animaciones desaparecen con `prefers-reduced-motion`?
8. ¿Se lee bien proyectada a 1920 px desde el fondo de la sala?

---

## 14. Kit de componentes (`resources/js/Components/UI/`)

La caja de herramientas con la que se arman las pantallas. Cada componente
lleva arriba un comentario con su propósito, sus props y un ejemplo de uso.
El catálogo vivo, con todas las variantes y estados, está en `/kit` (solo en
entorno local; ver `routes/kit.php` y `resources/js/Pages/Kit.vue`).

### Qué hay

| Componente | Para qué |
| --- | --- |
| `Boton` | Acción. Variantes primario, secundario, discreto y peligro; tamaños sm, md y lg; estado ocupado; icono; ancho completo. |
| `CampoTexto` `CampoArea` `CampoSelect` `CampoNumero` | Campos de formulario, con etiqueta, ayuda, error, requerido, deshabilitado y prefijo o sufijo. |
| `CampoBase` | Armazón de los cuatro anteriores. Solo se usa suelto para envolver un control a medida. |
| `Casilla` `Opcion` | Casilla de verificación y opción única, con área táctil de fila completa y variante de tarjeta. |
| `Tarjeta` | Unidad de contenido con cabecera, cuerpo y pie. Variantes plana y elevada. |
| `Panel` | Sección de pantalla con título, descripción y acciones. |
| `Etiqueta` | Distintivo de estado. Siempre con texto. |
| `Tabla` | Datos tabulares. Cabecera fija, filas alternas, cifras a la derecha y conversión a tarjetas apiladas por debajo de 768 px. |
| `Modal` | Diálogo con foco atrapado, cierre con Escape y hoja inferior en celular. |
| `Aviso` | Mensaje de estado dentro de la página. |
| `BarraProgreso` `Cargando` `EstadoVacio` | Avance, espera y ausencia de datos. |
| `Separador` `Migas` `Pestanas` `Tooltip` | Estructura y navegación. |
| `CuentaRegresiva` | Reloj de cuenta atrás para las dinámicas cronometradas del retiro. |
| `Icono` | Catálogo cerrado de pictogramas de trazo. |

### Cómo se traen

```js
import { Boton, CampoTexto, Tarjeta } from '@/Components/UI';
// o, para uno solo:
import Boton from '@/Components/UI/Boton.vue';
```

### Reglas del kit

1. **Ni un valor suelto.** Todos los componentes se dibujan con las variables
   de este documento. Si a un componente le falta una medida, se añade primero
   a `tokens.css`.
2. **Nada de marca escrita a mano.** Ni rutas de logo, ni nombre de cliente, ni
   colores: salen de `usePage().props.marca` y de las variables `--marca-*`.
3. **Los atributos no declarados se propagan.** Lo que se le pase de más a un
   componente aterriza donde tiene que aterrizar: en los campos, `class` y
   `style` se quedan en el contenedor y el resto va al control real.
4. **El color nunca informa solo.** Etiqueta, Aviso, CuentaRegresiva y los
   errores de campo llevan siempre icono o palabra además del color.
5. **44 × 44 px como mínimo tocable.** El tamaño `sm` de `Boton` mide 36 px en
   escritorio y sube a 44 px en pantalla táctil.
6. **`base.css`** (en la misma carpeta) guarda lo poco que varios componentes
   comparten: `.ui-solo-lectores`, la familia `.ui-campo*` y la familia
   `.ui-eleccion*`. La importa cada componente que la necesita.
