1 · Los seis principios
Todo lo demás en esta guía es consecuencia de estos seis. Si algo no está documentado, resuélvelo con ellos.
1 · El fondo manda el color
El verde solo existe sobre oscuro. El navy solo sobre claro. Es la regla que más se rompe y la que más delata un diseño que no es nuestro.
2 · Bordes de medio píxel
.5px solid, nunca 1px. Un borde grueso separa una interfaz cara de una barata.
3 · Todo lo que se toca, responde
Un botón que no se mueve al pasarle el cursor se siente muerto.
4 · Movimiento lento y suave
Un solo easing, y las cosas suben 2 o 3 píxeles, no 10. Si la animación se nota, está mal calibrada.
5 · Jerarquía con color
Un texto secundario es #5b6478, no negro al 50%. La opacidad se adivina en pantalla y desaparece impresa.
6 · Nada se inventa
Si no hay dato, va un guion largo —. Un cero fingiendo ser dato es peor que un hueco honesto.
2 · Logo
Dos versiones oficiales en SVG (383×68). Usar siempre estas, en toda página, diseño e imagen.
| Versión | URL | Cuándo |
|---|---|---|
| AZUL | …/69cde95ac859395cde4752e3.svg | Fondos claros y blancos |
| BLANCO | …/69cde95a69eb1fa3e7917e1d.svg | Fondos oscuros y navy |
- Tamaños: nav 180px · sidebar de app alto 32px · footer 140px · OG alto ~48px
- Siempre enlaza a
https://superleads.mx(o al inicio si es app interna) - El logo va solo: sin caja blanca detrás ni contenedor decorativo. Si el fondo es oscuro, usa la versión blanca — no metas el azul en un recuadro
- Ícono de "acceder":
…/68bdf4dd6d0aaa7737d9cfdd.png - La versión texto y el PNG viejo ya no se usan en diseños nuevos
3 · Color
Tres primarios resuelven el 80% de cualquier pantalla. Los secundarios sostienen y matizan; los de estado están reservados y nunca se reciclan.
Colores primarios
Colores secundarios
Neutros y texto
Textos sobre fondo oscuro
#ffffff — Texto principal
#7a9fd4 — Subtítulos y descripciones
#4a6aaa — Labels, notas, contadores
#3a5a9a — Texto de apoyo, el más tenue permitido
Colores de estado
Reservados. Nunca decorativos ni como "serie 4" de una gráfica. Siempre acompañados de texto o ícono — el color solo nunca comunica.
Tokens — copia esto al inicio de tu CSS
:root{
/* — Primarios — */
--green:#56EF9F; --navy:#002582; --navy-deep:#001240;
/* — Secundarios — */
--green-d:#2BC878; --navy-mid:#001a5e;
--blue:#0039C8; --blue-mid:#2A89FB;
--blue-soft:#F4F7FF; --blue-softer:#EEF2FF;
/* — Neutros — */
--ink:#1a1a1a; --border:#e0e8f8;
--muted:#5b6478; --dim:#98a1b0;
/* — Estado — */
--ok:#0ca30c; --warn:#eb6834;
--bad:#d03b3b; --destructive:#d92d43;
/* — Gráficas (paleta validada, separada de la marca) — */
--chart-1:#2a78d6; --chart-2:#eb6834; --chart-3:#1baf7a;
/* — Movimiento — */
--ease:cubic-bezier(.16,1,.3,1);
/* — Sombras — */
--shadow-sm:0 1px 2px rgba(0,37,130,.04);
--shadow-card:0 10px 32px rgba(0,37,130,.08);
--shadow-btn:0 10px 28px rgba(0,37,130,.22);
--shadow-cta:0 10px 28px rgba(86,239,159,.28);
--shadow-pill:0 10px 32px rgba(0,37,130,.08);
}Reglas de uso — las que no se negocian
| Regla | Por qué |
|---|---|
| Verde SOLO sobre navy/oscuro. Nunca sobre blanco. | Sobre blanco no alcanza contraste y se ve barato. Sobre claro, usa navy o blue. |
| Navy para texto y botones sobre fondos claros. | Es la voz de la marca en documentos y formularios. |
| Blue para links, bordes activos y eyebrows claros. | Es el "verde del contexto claro". |
| Los colores de estado no se reciclan. | Si el rojo también es decorativo, el rojo de alerta deja de alarmar. |
Las gráficas usan --chart-*, no la marca. | La paleta de marca no pasa pruebas de daltonismo en marcas pequeñas. |
| Texto siempre en tinta, nunca del color de su serie. | Un valor pintado del color de su barra se vuelve ilegible. |
4 · Tipografía
Familia única: Plus Jakarta Sans. No hay segunda fuente.
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,600;0,700;0,800;1,700;1,800&display=swap" rel="stylesheet">
Hero H1 con énfasis
46–50px · 800 · -1.8px · 1.07
Título de página
32–36px · 800 · -0.8px · 1.12
Título de tarjeta
16–22px · 800 · -0.3px · 1.2
Subtítulo de sección — la línea que explica de qué va lo que sigue, en tono tranquilo.
14–15px · 400 · 1.7
Texto body. El cuerpo de todo lo que se lee de corrido, con interlineado generoso para que el ojo no se pierda entre renglones largos.
13–15px · 400–500 · 1.78
10–11px · 700 · 1.3px · mayúsculas
$4,260,000.00
Stat · 26–32px · 800 · -1px · tabular-nums
Reglas
- Énfasis en H1:
<em>italic — verde sobre oscuro, azul sobre claro - Números en columna o que cambian en vivo:
font-variant-numeric: tabular-nums. Sin esto los dígitos bailan al actualizarse - Nunca centres párrafos de más de dos líneas. Títulos sí, texto corrido no
- Ancho de lectura: 65–75 caracteres (
max-width: 46remen documentos)
5 · Espaciado y radios
Escala de múltiplos de 4, sin excepción: 4 · 8 · 12 · 16 · 20 · 24 · 32 · 40 · 56 · 72
8px
controles
12px
tarjetas
16–24px
contenedores
pill
badges
| Contexto | Desktop | Mobile |
|---|---|---|
| Hero / Footer / CTA block | 72px 56px | 28px 18px |
| Sección estándar | 72px 56px | 28px 18px |
| Tarjeta | 20–24px | 16px |
| Panel interno | 16–20px | 14px |
6 · Sombras y bordes
Grandes, suaves y teñidas de navy — nunca negras ni duras. Una sombra negra sobre nuestro azul se ve sucia.
Al ras · solo borde
Apoyado · tarjeta en reposo
Levantado · hover, panel
Encima · modal, píldora
/* Nivel 0 — al ras */ border:.5px solid var(--border); /* Nivel 1 — apoyado */ box-shadow:0 1px 2px rgba(0,37,130,.04); /* Nivel 2 — levantado */ box-shadow:0 10px 32px rgba(0,37,130,.08); /* Nivel 3 — encima de todo */ box-shadow:0 8px 40px rgba(0,0,0,.12); /* Intención — CTA verde en hover */ box-shadow:0 10px 28px rgba(86,239,159,.28); /* Intención — navy en hover */ box-shadow:0 10px 28px rgba(0,37,130,.22);
Bordes
- Estructurales: siempre
.5px solid. En Tailwind:border-[0.5px] - Sobre claro:
#e0e8f8· Sobre oscuro:rgba(255,255,255,.07), hoverrgba(86,239,159,.25) - Punteado solo para zonas de "agregar" y estados vacíos
7 · Movimiento — el sentir del clic
Esta sección separa una interfaz que se siente cara de una que se siente lenta. Todo se mide desde que el dedo toca.
La única curva
--ease:cubic-bezier(.16,1,.3,1);
Sale rápido y frena suave. Todo usa esta curva. Si algo usa linear o ease-in-out, está fuera del sistema.
Los tiempos
| Interacción | Duración | Qué se mueve |
|---|---|---|
| Presionado (active) | 0ms — inmediato | Baja a scale(.98) o pierde su lift. Debe ser instantáneo: es el acuse de recibo del clic. |
| Hover de botón | 200ms | translateY(-2px) + sombra de intención |
| Hover de tarjeta | 300ms | translateY(-3px) + sombra nivel 2 |
| Cambio de color | 200ms | color, background, border-color |
| Panel / acordeón | 300ms | opacity + translateY(6px→0) |
| Modal / overlay | 250ms | opacity + scale(.95→1) |
| Fondo decorativo | 90–130s | Deriva imperceptible (§16) |
La regla de los 400 ms
Lo que tarda una acción define cómo se comunica:
| Tarda | Qué mostrar |
|---|---|
< 100ms | Nada. Solo el estado active del botón. |
100–400ms | Nada más que el active. Un spinner que parpadea molesta más que ayuda. |
400ms – 2s | Spinner dentro del botón + botón deshabilitado. El texto no cambia. |
2s – 10s | Spinner + texto que cambia ("Guardando…", "Analizando…"). |
> 10s | Pantalla de proceso con etapas que avanzan. El usuario tiene que ver que algo pasa, no un spinner eterno. |
Retrasos de guardado (debounce)
| Acción | Espera | Por qué |
|---|---|---|
| Autoguardado de formulario | 2500ms | Suficiente para no guardar en cada tecla, corto para no perder trabajo. |
| Autoguardado de nota | 1200ms | El texto libre se escribe en ráfagas más cortas. |
| Búsqueda mientras se escribe | 300ms | Debajo se siente nervioso; arriba, lento. |
| Al salir de la pantalla | 0ms | Todo debounce pendiente debe dispararse. Nunca se pierde lo tecleado. |
Todo botón que dispara algo debe, en este orden: 1) hundirse al instante · 2) deshabilitarse mientras trabaja · 3) decir cómo terminó (Guardado 14:32 o el mensaje real del error). Nunca "algo salió mal" — siempre qué salió mal y qué hacer.
8 · Botones
Pásales el cursor: todos son los reales del sistema.
Primario — verde (CTA principal)
El de la acción más importante de la pantalla. Solo uno por vista.
.btn-primary{
display:inline-flex;align-items:center;justify-content:center;gap:8px;
background:var(--green);color:var(--navy);
padding:14px 26px;border-radius:8px;border:none;
font-family:inherit;font-size:14px;font-weight:700;cursor:pointer;
transition:transform .2s var(--ease),box-shadow .2s var(--ease),background-color .2s;
}
.btn-primary:hover{transform:translateY(-2px);box-shadow:var(--shadow-cta)}
.btn-primary:active{transform:translateY(0);box-shadow:none}
.btn-primary:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}
.btn-primary:focus-visible{outline:2px solid var(--blue);outline-offset:2px}Secundario — navy
La acción importante pero no principal, sobre fondo claro.
.btn-navy{
background:var(--navy);color:#fff;
padding:12px 22px;border-radius:8px;border:none;
font-size:13px;font-weight:700;cursor:pointer;
transition:transform .2s var(--ease),box-shadow .2s var(--ease),background-color .2s;
}
.btn-navy:hover{background:var(--navy-mid);transform:translateY(-2px);box-shadow:var(--shadow-btn)}
.btn-navy:active{transform:translateY(0);box-shadow:none}Terciario, fantasma y destructivo
/* Terciario — acciones de apoyo en fila */ .btn-outline{background:#fff;color:var(--navy);border:.5px solid var(--border); padding:10px 18px;border-radius:8px;font-size:13px;font-weight:700} .btn-outline:hover{background:var(--navy);color:#fff;border-color:var(--navy)} /* Fantasma — navegación, cancelar */ .btn-ghost{background:transparent;color:var(--muted);padding:10px 18px;font-size:13px;font-weight:600} .btn-ghost:hover{background:rgba(0,37,130,.05);color:var(--navy)} /* Destructivo — discreto hasta que se necesita */ .btn-danger{background:transparent;color:var(--muted);padding:8px;border-radius:8px} .btn-danger:hover{background:#fef2f2;color:var(--destructive)}
Tamaños e íconos
| Tamaño | Padding | Fuente | Cuándo |
|---|---|---|---|
| Grande | 16px 30px | 15px | Hero, CTA de cierre |
| Normal | 14px 26px | 14px | Acción principal |
| Compacto | 10px 18px | 13px | Barras de acciones |
| Mini | 6px 14px | 12px | Dentro de tarjetas, nav |
| Ícono | 36px cuadrado | — | Solo ícono, title obligatorio |
- Íconos de
14–16px,stroke-width:2,fill:none - Color: navy sobre verde · blanco sobre navy · hereda en outline y ghost
gap:8pxrespecto al texto. Ícono a la izquierda, salvo flechas de avance
El botón no cambia de tamaño al entrar en carga (reserva el ancho). Un botón que se encoge y crece es el detalle que arruina una interfaz por lo demás correcta.
9 · Formularios
Achica la ventana y mira la rejilla: se compacta sola de dos columnas a una, sin media queries.
La rejilla que se compacta sola
.form-grid{
display:grid;
grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
gap:20px;
}
/* Campo que necesita todo el ancho */
.form-grid .full{grid-column:1/-1}auto-fit + minmax es la clave: si caben dos columnas de 280px las pone, si no colapsa a una. Nunca uses repeat(2, 1fr) fijo — se desborda en móvil. Para grupos de tres: minmax(200px, 1fr).
Formulario vivo
Como aparece en el panel y en la hoja del cliente.
Se muestra junto al colegio durante la llamada.
Solo alumnos pagando colegiatura hoy — sin lista de espera.
Liga o celular — el botón verde abre la conversación al instante.
Correo inválido.
El botón nunca desaparece: se apaga y ocupa el mismo espacio.
Marca todas: lo normal es más de una.
Anatomía de un campo
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:13px;font-weight:500;color:var(--navy)}
.field input,.field textarea,.field select{
width:100%;padding:10px 14px;
border:.5px solid var(--border);border-radius:8px;background:#fff;
font-family:inherit;font-size:14px;color:var(--ink);
transition:border-color .2s,box-shadow .2s;
}
.field input::placeholder{color:var(--dim)}
.field input:hover{border-color:#c9d6f0}
.field input:focus{
outline:none;border-color:var(--blue);
box-shadow:0 0 0 3px rgba(0,57,200,.10);
}
.hint{font-size:11px;line-height:1.45;color:var(--muted)}
.err-msg{font-size:12px;font-weight:500;color:var(--destructive)}
.field input[aria-invalid="true"]{border-color:var(--destructive)}
/* Número protagonista */
.field input.grande{height:56px;font-size:24px;font-weight:600;
color:var(--navy);font-variant-numeric:tabular-nums}El hint es obligatorio en cualquier campo donde quepa duda de qué contar o en qué unidad. Resuelve la pregunta antes de que se haga: qué incluir, qué no, o a qué cálculo alimenta el dato.
La regla de los tres estados
Un Sí/No con "No" preseleccionado hace que el campo se vea contestado sin que nadie lo haya contestado — y contamina los datos.
Clic sobre la opción ya activa la des-selecciona. Y en el código: if (valor != null), nunca if (valor) — porque 0 es una respuesta.
| Valor | Significa | Se ve |
|---|---|---|
null | Sin preguntar | Ningún chip activo |
0 / no | Respondió que no | Chip "No" activo |
1 / sí | Respondió que sí | Chip "Sí" activo |
Validación y autoguardado
- Valida al salir del campo (
blur), no en cada tecla — marcar en rojo un correo a medio teclear es hostil - Solo lo verdaderamente obligatorio bloquea. Un campo que frena el avance rompe la conversación en una sesión en vivo
- Si el envío falla, lleva al usuario al error. Un botón que no hace nada porque hay un error en otra pantalla es un botón roto
- Se guarda solo, y se dice: debounce 2.5s, flush al salir, indicador
Guardando… → Guardado 14:32 - El botón de avanzar se llama "Guardar y Continuar", no "Continuar" — nombra lo que hace y da tranquilidad
12 · Tarjetas
Pásales el cursor: suben 3px con sombra teñida de navy.
Sobre fondo claro
Blanco, borde .5px, radio 12px, sombra nivel 1.
Misma altura
Todas las tarjetas de una rejilla miden igual.
Sobre fondo oscuro
Fondo blanco al 4%, borde blanco al 7%. Hover: borde verde al 25%.
.card{
background:#fff;border:.5px solid var(--border);border-radius:12px;
padding:20px;box-shadow:var(--shadow-sm);
transition:transform .3s var(--ease),box-shadow .3s,border-color .3s;
}
.card:hover{transform:translateY(-3px);box-shadow:var(--shadow-card);
border-color:rgba(0,57,200,.25)}
/* Sobre oscuro */
.card-dark{background:rgba(255,255,255,.04);border:.5px solid rgba(255,255,255,.07)}
.card-dark:hover{border-color:rgba(86,239,159,.25)}
/* Rejilla uniforme */
.cards{display:grid;gap:24px;grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}Todas las tarjetas con la misma altura y el mismo ancho (height:100% en el hijo). Una tarjeta "destacada" del doble de ancho deja huecos con casi cualquier número de elementos — la simetría gana.
13 · Eyebrows, badges y stats
Eyebrow
.eyebrow{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.eyebrow::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--blue)}
.eyebrow span{font-size:11px;font-weight:700;text-transform:uppercase;
letter-spacing:1.3px;color:var(--blue)}
/* Sobre oscuro */
.eyebrow-dark::before{background:var(--green)}
.eyebrow-dark span{color:var(--green)}Badges y pills
Stats
El stat héroe (la cifra que sostiene la conversación) va solo, sobre navy-deep, a 48–60px, con su contexto humano debajo en una fila de stats chicos. Una cifra grande sin contexto es un número; con contexto es un argumento.
14 · Grids y layout
| Uso | Columnas |
|---|---|
| Hero | 1fr 1fr |
| Tarjetas de features | repeat(auto-fill, minmax(280px, 1fr)) |
| Stats bar | repeat(auto-fit, minmax(160px, 1fr)) |
| Formulario | repeat(auto-fit, minmax(280px, 1fr)) |
| CTA block | 1fr auto |
| Contenido + widget | 1fr 1fr |
| Panel de app | sidebar 288px + 1fr |
Anchos máximos: app 1400px · página de contenido 1100px · documento de lectura 46rem.
Usa auto-fit/auto-fill con minmax antes que media queries. El layout que se acomoda solo no se rompe en el tamaño que no probaste.
15 · Visualización de datos
La paleta de marca NO se usa en gráficas: el verde y el navy no pasan las pruebas de contraste ni de daltonismo en marcas pequeñas.
Comparación — barras a la misma escala
Composición — apilada al 100% con separación de 2px
Reglas
- Un solo tono claro→oscuro para magnitudes. Dos tonos + gris para polaridad. Nunca arcoíris
- El color sigue a la entidad, no a su posición: si un filtro cambia el número de series, las que quedan no cambian de color
- Texto en tinta, nunca del color de la serie. La marca de color va al lado
- Leyenda siempre con 2+ series, y etiqueta directa en las importantes
- Marcas finas: líneas 2px, puntos ≥8px, separación de 2px entre segmentos apilados
- Contraste en marcas oscuras: sobre relleno oscuro el texto va blanco, sin excepción
- Nunca dos ejes Y. Dos magnitudes distintas → dos gráficas
- Sin dato, no hay gráfica. No dibujes un cero: oculta el panel
Números en la interfaz
- Moneda con dos decimales y símbolo (
$134,000.00), porcentajes con 1–2 decimales - Sin dato:
—(guion largo), nunca0,N/Ani vacío - Fechas en
America/Mexico_City, formato medium (14 ago 2026)
16 · Fondos y elementos decorativos
Círculos difusos muy tenues, muy grandes, siempre detrás. Y una deriva tan lenta que a simple vista está quieta.
.fondo{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.globo-1{position:absolute;top:-30%;right:-15%;width:520px;height:520px;
border-radius:50%;background:rgba(42,137,251,.05);filter:blur(100px)}
.globo-2{position:absolute;bottom:-30%;left:-10%;width:480px;height:480px;
border-radius:50%;background:rgba(86,239,159,.05);filter:blur(110px)}
/* Deriva — el fondo respira sin que nadie lo note */
@keyframes deriva{
0%,100%{transform:translate3d(0,0,0) scale(1)}
50% {transform:translate3d(-48px,36px,0) scale(1.08)}
}
.globo-1{animation:deriva 90s ease-in-out infinite}
.globo-2{animation:deriva 130s ease-in-out infinite reverse}
/* Círculo de acento en secciones oscuras */
section::before{content:"";position:absolute;right:-100px;top:-100px;
width:480px;height:480px;border-radius:50%;
background:rgba(86,239,159,.03);pointer-events:none}Separador de barra de stats (sobre oscuro): rejilla con gap:1px y fondo #0a3070 — el de la cabecera de esta página.
17 · Estados de la interfaz
Toda pantalla que carga datos necesita cuatro diseños, no uno.
Vacío
Aún no hay diagnósticos. Inicia una sesión para descubrir oportunidades.
Cargando
Consultando el censo del INEGI…
Arriba de 10s: etapas que avanzan.
Error
No se pudo guardar: verifica que la migración 0010 esté aplicada.
El mensaje real, junto a la acción que falló. Nunca destruye lo escrito.
Éxito
Discreto: Guardado 14:32 en tinta.
Toast solo para acciones grandes · 3s · abajo al centro.
18 · Modos especiales
Modo presentación
- Oculta la navegación y deja solo el contenido, para compartir pantalla
- El botón que lo activa debe ser visible desde cualquier pantalla: si se puede encender en un lado y no apagar en otro, es una trampa
- El estado persiste y se restaura antes del primer pintado, para que no haya parpadeo
Modo privado (métricas ocultas)
Conversión
6.16%
Ocupación
70.00%
filter: blur(7px); user-select: none;— no se lee ni se copia- Los nombres se ven, las cifras no. Un ojo al lado revela u oculta
- Arranca oculto por defecto: es más seguro descubrir a propósito que tapar a las prisas
19 · Impresión y PDF
@media print{
*{print-color-adjust:exact;-webkit-print-color-adjust:exact}
@page{size:letter;margin:16mm}
html,body{background:#fff !important}
.no-print,nav,.sidebar,.topbar,button{display:none !important}
/* Las tarjetas se aplanan: en papel solo gastan tinta */
.card{border:0 !important;box-shadow:none !important;
background:transparent !important;padding:0 !important}
body{font-size:11pt;line-height:1.5}
h1,h2,h3{break-after:avoid}
figure,.par-dato{break-inside:avoid}
/* Las secciones SÍ pueden partirse: evitarlo deja huecos al pie */
}- Jerarquía por color, nunca por opacidad: la mayoría de las impresoras no resuelven un azul al 30%
- El documento se ve igual en pantalla que en papel — así nadie imprime sorpresas
20 · Accesibilidad
- Contraste mínimo: 4.5:1 en texto normal, 3:1 en texto grande y marcas de gráfica
- Foco siempre visible:
outline: 2px solid var(--blue); outline-offset: 2px. Nuncaoutline:nonesin reemplazo — dale Tab a los botones de arriba - Área táctil mínima 44×44px. Un botón de 32px necesita padding invisible alrededor
- Nada depende solo del color: los estados llevan ícono o texto además del color
- Todo ícono solo lleva
titleyaria-label - Controles ocultos por hover deben verse en táctil (
opacity-100en móvil, hover solo desdemd:). Un botón invisible que sí recibe toques es un accidente esperando
21 · Checklist antes de entregar
Márcalo. Si algo queda sin palomear, no está listo.
Marca
Estructura
Interacción
Contenido
Cierre
22 · Anti-patrones
Lo que delata un diseño fuera del sistema. Si tu pantalla tiene algo de la columna izquierda, corrígelo.
| ❌ No | ✅ Sí |
|---|---|
Verde #56EF9F sobre blanco | Navy o blue sobre claro; verde solo sobre oscuro |
border: 1px solid #ddd | border: .5px solid var(--border) |
Sombras negras rgba(0,0,0,.2) | Sombras teñidas de navy |
opacity: .5 para jerarquía de texto | El color --muted o --dim |
transition: all .3s ease | Propiedades nombradas + var(--ease) |
| Hover que mueve 8px | translateY(-2px) botón · -3px tarjeta |
repeat(2, 1fr) fijo en formularios | repeat(auto-fit, minmax(280px, 1fr)) |
Un <select> con 4 opciones | Chips, todas visibles |
| Toggle con "No" preseleccionado | Tres estados, nada activo al inicio |
| "Ocurrió un error, intenta de nuevo" | El mensaje real y qué hacer |
Mostrar 0 cuando no hay dato | — |
| Botón que se encoge al cargar | Ancho reservado, spinner adentro |
| Tarjeta destacada del doble de ancho | Cuadrícula uniforme |
| Colores de marca en gráficas | Paleta --chart-* validada |
| Un spinner eterno sin explicación | Etapas que avanzan arriba de 10s |
| Acción principal al fondo del menú | Acción principal arriba |
Resuélvelo con los seis principios — y luego agrégalo a esta guía.