Tokens
Color, tipografía, radios y sombras. Los valores salen de `tokens/geist.json` y de `theme.css`.
La paleta, los radios y las sombras por defecto de Tailwind están reseteados: bg-blue-50 o shadow-md no compilan. Solo existen los tokens del paquete.
Los valores viven en tokens/geist.json y se compilan a src/styles/colors.css con npm run tokens; un test falla si el CSS quedó desactualizado. Las tablas de esta página se generan de esos mismos archivos.
Fondos: página, superficie y banda
Son tres roles distintos y cada uno tiene su token. Elegir mal se nota sobre todo en oscuro, donde la página es negro puro:
| Token | Rol | Claro | Oscuro |
|---|---|---|---|
bg-background |
La página. body (ya lo pone el paquete) y la raíz del AppShell. |
#ffffff | #000000 |
bg-background-100 |
La superficie: lo que flota sobre la página. Input, Select, Textarea, popup de menú, Popover, Dialog, Sheet, Card, Alert, Toast, barra mobile del shell. | #ffffff | #0a0a0a |
bg-background-200 |
El fondo sutil / banda: Sidebar, thead/tfoot de Table, Card variant="subtle", EmptyState. |
#fafafa | #0a0a0a |
La regla: si el elemento es la página, bg-background; si flota sobre ella, bg-background-100.
Los valores de oscuro son los de vercel.com medidos con getComputedStyle (contact/sales, 2026-09-22): --ds-background-100: hsla(0,0%,4%) = #0a0a0a para las superficies y --ds-background-200: hsla(0,0%,0%) = #000 para la página. background-200 es siempre el tono que no es el de la página: en claro baja a #fafafa, en oscuro no puede bajar de #000 y sube a #0a0a0a. Por eso en oscuro coincide con background-100: Geist tiene dos fondos por tema, no tres.
Color
Diez pasos por familia, de 100 (el más claro en tema claro) a 1000. La convención de Geist: 100–400 son fondos, 500–700 son bordes y elementos, 800–1000 son texto. El contraste de gray-900 sobre cualquier fondo de la misma familia llega a AA.
gray
| Paso | Claro | Oscuro |
|---|---|---|
gray-100 |
#f2f2f2 | #1a1a1a |
gray-200 |
#ebebeb | #1f1f1f |
gray-300 |
#e6e6e6 | #292929 |
gray-400 |
#eaeaea | #2e2e2e |
gray-500 |
#c9c9c9 | #454545 |
gray-600 |
#a8a8a8 | #878787 |
gray-700 |
#8f8f8f | #8f8f8f |
gray-800 |
#7d7d7d | #7d7d7d |
gray-900 |
#4d4d4d | #a0a0a0 |
gray-1000 |
#171717 | #ededed |
gray-alpha
| Paso | Claro | Oscuro |
|---|---|---|
gray-alpha-100 |
#0000000d | #ffffff12 |
gray-alpha-200 |
#00000015 | #ffffff17 |
gray-alpha-300 |
#0000001a | #ffffff21 |
gray-alpha-400 |
#00000014 | #ffffff24 |
gray-alpha-500 |
#00000036 | #ffffff3d |
gray-alpha-600 |
#0000003d | #ffffff82 |
gray-alpha-700 |
#00000070 | #ffffff8a |
gray-alpha-800 |
#00000082 | #ffffff78 |
gray-alpha-900 |
#000000b3 | #ffffff9c |
gray-alpha-1000 |
#000000e8 | #ffffffeb |
blue
| Paso | Claro | Oscuro |
|---|---|---|
blue-100 |
#f0f7ff | #06193a |
blue-200 |
#eaf4ff | #022248 |
blue-300 |
#e0efff | #002f62 |
blue-400 |
#cce7ff | #003771 |
blue-500 |
#97ccff | #004287 |
blue-600 |
#51aeff | #0090ff |
blue-700 |
#0070f7 | #0071f6 |
blue-800 |
#005edc | #005fd8 |
blue-900 |
#0064e2 | #50a8ff |
blue-1000 |
#002453 | #ebf6ff |
red
| Paso | Claro | Oscuro |
|---|---|---|
red-100 |
#ffeef0 | #330a11 |
red-200 |
#ffe9ea | #440d13 |
red-300 |
#ffe4e5 | #5d0e17 |
red-400 |
#ffd8d7 | #6f101b |
red-500 |
#ffb5b6 | #88151f |
red-600 |
#ff6a6e | #f32e40 |
red-700 |
#fc0035 | #f13242 |
red-800 |
#e70022 | #e2162a |
red-900 |
#d60020 | #ff5e63 |
red-1000 |
#46000c | #ffeaed |
amber
| Paso | Claro | Oscuro |
|---|---|---|
amber-100 |
#fff6e1 | #291800 |
amber-200 |
#fff4d4 | #331b00 |
amber-300 |
#fff1c8 | #4f2900 |
amber-400 |
#ffdd84 | #573200 |
amber-500 |
#ffc85e | #6c4100 |
amber-600 |
#ffaa00 | #e99c00 |
amber-700 |
#ffb200 | #ffb200 |
amber-800 |
#ff9900 | #ff9900 |
amber-900 |
#a64f00 | #ff9900 |
amber-1000 |
#541c00 | #fff3d9 |
green
| Paso | Claro | Oscuro |
|---|---|---|
green-100 |
#ecfdec | #00250a |
green-200 |
#e5fce7 | #003110 |
green-300 |
#d3fad1 | #003814 |
green-400 |
#b9f5bc | #004616 |
green-500 |
#82eb8d | #00661d |
green-600 |
#4ce15e | #009431 |
green-700 |
#28a948 | #00ab3e |
green-800 |
#279141 | #009335 |
green-900 |
#107d32 | #00ca52 |
green-1000 |
#00370d | #daffe5 |
teal
| Paso | Claro | Oscuro |
|---|---|---|
teal-100 |
#dffffb | #00211b |
teal-200 |
#ddfef6 | #002922 |
teal-300 |
#ccf9f1 | #003b33 |
teal-400 |
#b1f7ec | #003f35 |
teal-500 |
#52f0db | #005f53 |
teal-600 |
#00e2c4 | #009885 |
teal-700 |
#00a694 | #00a794 |
teal-800 |
#008d7d | #008d7d |
teal-900 |
#007a6e | #00c9b5 |
teal-1000 |
#003d34 | #cefff5 |
purple
| Paso | Claro | Oscuro |
|---|---|---|
purple-100 |
#f9f0ff | #290c33 |
purple-200 |
#f9f1ff | #341142 |
purple-300 |
#f5e8ff | #47185e |
purple-400 |
#f1d9ff | #541a76 |
purple-500 |
#dda9ff | #642290 |
purple-600 |
#c77dff | #9440d5 |
purple-700 |
#9f00f4 | #9440d5 |
purple-800 |
#8400cd | #7d2bba |
purple-900 |
#7c00c9 | #c472fb |
purple-1000 |
#2e004d | #faedff |
pink
| Paso | Claro | Oscuro |
|---|---|---|
pink-100 |
#ffeaf5 | #310d1e |
pink-200 |
#ffeaf2 | #420c25 |
pink-300 |
#ffe0eb | #571032 |
pink-400 |
#ffd5e1 | #5d0c34 |
pink-500 |
#fdb3cc | #76063f |
pink-600 |
#f97ea7 | #b90056 |
pink-700 |
#f22782 | #f12b82 |
pink-800 |
#e4106e | #e6006e |
pink-900 |
#c41562 | #ff518d |
pink-1000 |
#460523 | #ffeaf4 |
brand no está en la tabla porque no tiene valores fijos: se deriva de las tres variables de la app. Ver Theming.
Tipografía
Las utilidades de Geist. cn() las entiende como tamaño de fuente, así que conviven con text-gray-900.
| Utilidad | Tamaño | Interlineado | Peso | Tracking |
|---|---|---|---|---|
text-heading-72 |
72px | 72px | 400 | -4.32px |
text-heading-64 |
64px | 64px | 400 | -3.84px |
text-heading-56 |
56px | 56px | 450 | -3.36px |
text-heading-48 |
48px | 56px | 450 | -2.88px |
text-heading-40 |
40px | 48px | 450 | -2.4px |
text-heading-32 |
32px | 40px | 500 | -1.28px |
text-heading-24 |
24px | 32px | 500 | -0.96px |
text-heading-20 |
20px | 26px | 550 | -0.4px |
text-heading-16 |
16px | 24px | 600 | -0.32px |
text-heading-14 |
14px | 20px | 600 | -0.28px |
text-button-16 |
16px | 20px | 500 | 0 |
text-button-14 |
14px | 20px | 500 | 0 |
text-button-12 |
12px | 16px | 500 | 0 |
text-label-20 |
20px | 32px | 400 | 0 |
text-label-18 |
18px | 20px | 400 | 0 |
text-label-16 |
16px | 20px | 400 | 0 |
text-label-14 |
14px | 20px | 400 | 0 |
text-label-13 |
13px | 16px | 400 | 0 |
text-label-12 |
12px | 16px | 400 | 0 |
text-label-14-mono |
14px | 20px | 400 | 0 |
text-label-13-mono |
13px | 20px | 400 | 0 |
text-label-12-mono |
12px | 16px | 400 | 0 |
text-copy-24 |
24px | 36px | 400 | 0 |
text-copy-20 |
20px | 36px | 400 | 0 |
text-copy-18 |
18px | 28px | 400 | 0 |
text-copy-16 |
16px | 24px | 400 | 0 |
text-copy-14 |
14px | 20px | 400 | 0 |
text-copy-13 |
13px | 18px | 400 | 0 |
text-copy-14-mono |
14px | 20px | 400 | 0 |
text-copy-13-mono |
13px | 18px | 400 | 0 |
Los heading llevan el peso corregido ópticamente, no 600 fijo. Un mismo peso no se ve igual a 14px que a 64px: cuanto más grande el cuerpo, más gruesos se leen los trazos, y 600 a 64px sale plomizo. Los números salen de medir vercel.com (computed style, 2026-09-22); los pasos que no aparecían ahí se interpolan en la misma curva.
No lo pises con font-semibold: para eso está el paso de arriba de la escala. Y necesita Geist como fuente variable (rango 100 900); con una estática los pesos intermedios se redondean y la corrección se pierde.
Cuándo usar cada familia:
| Familia | Para qué |
|---|---|
heading-* |
Títulos. Peso óptico, tracking negativo. |
copy-* |
Párrafos y texto corrido. Interlineado holgado. |
label-* |
Etiquetas, celdas, metadatos. Interlineado ajustado, peso 400. |
button-* |
Texto dentro de controles. Peso 500. |
*-mono |
Código, IDs, importes. Geist Mono. |
Radios
| Utilidad | Valor |
|---|---|
rounded-xs |
4px |
rounded-sm |
6px |
rounded-md |
6px |
rounded-lg |
12px |
rounded-xl |
12px |
rounded-2xl |
16px |
rounded-3xl |
16px |
rounded-4xl |
9999px |
rounded-md (6px) es el radio del sistema: botones, inputs, ítems de menú. rounded-xl (12px) es el de las tarjetas. rounded-full solo en Badge, en avatares y en Button shape="pill".
Sombras
| Utilidad | Dónde |
|---|---|
shadow-tooltip |
Tooltip. |
shadow-menu |
DropdownMenu, Select, Combobox, Popover. |
shadow-modal |
Dialog, AlertDialog, Sheet. |
Las tres terminan en un anillo de 1px que en oscuro reemplaza al borde. No hay sombras decorativas: una sombra en este sistema significa «esto flota», y solo flotan los tres tipos de superficie de arriba.
Foco y movimiento
| Utilidad | Dónde |
|---|---|
focus-visible:focus-ring |
Controles: botones, ítems de menú, tabs, toggles. Anillo de 2px en brand-700 con hueco. |
focus:focus-border |
Campos: Input, Textarea, Select, Combobox. Tiñe el borde y agrega un halo. |
focus:focus-border-error |
Lo mismo, en rojo, cuando el campo tiene aria-invalid. |
transition-control |
150 ms, ease, solo color / fondo / borde / sombra / opacidad. |
animate-skeleton |
El latido del Skeleton. |
Todas las animaciones pasan por motion-reduce, además del reset global del paquete.