Este documento define la identidad visual del Design System Stack-and-Flow. Está inspirado en el estilo de la landing de Agent Teams — una interfaz oscura de alta precisión que combina minimalismo técnico con energía de herramienta profesional. Sirve como referencia de diseño para tokens, componentes y decisiones visuales.
Stack-and-Flow se siente como el interior de un instrumento de precisión. El fondo no es simplemente oscuro — es un negro azulado profundo (#060C13) que actúa como void con tinte frío perceptible, sobre el que todo el contenido emerge con claridad y temperatura visual coherente.
La firma visual es la combinación de superficies opacas y transparencias con blur — algunos cards son sólidos y elevados, otros son semitransparentes con backdrop-filter: blur(), creando capas de profundidad sin recurrir a sombras dramáticas. El acento rojo carmesí (#db143c en light, #ff0036 en dark) no domina — puntúa. Aparece en gradientes de botón, glows sutiles y estados activos.
El elemento diferenciador es el grid de fondo sutil — líneas translúcidas de 40×40px que dan al canvas una textura de hoja técnica sin interferir con el contenido. Combinado con el backdrop-filter de la navbar, crea la ilusión de estar trabajando dentro de una herramienta nativa, no de navegar una web de marketing.
Características clave:
- Negro azulado profundo (
#060C13) como fondo base — Paleta A, H215 S50, tinte frío perceptible sin romper oscuridad - Grid de fondo sutil (líneas
rgbaa baja opacidad) sobre el canvas principal - Navbar flotante con
backdrop-filter: blur(16px)ybackground: rgba(6,12,19,0.75)— efecto cristal con tinte frío - Rojo carmesí como acento de punctuación, nunca como relleno general
- Botones primarios con glow neon multi-capa — gradiente rojo + halo exterior
- Botones secundarios con borde semitransparente y glow contenido
- Cards opacas vs. cards semitransparentes — coexisten en el mismo sistema
- Space Grotesk Variable en todos los contextos — peso 500 como base, 700 en headings
El color de marca. Dos valores según el modo:
| Contexto | Token | Valor |
|---|---|---|
| Light mode | --color-brand-primary |
#db143c |
| Dark mode | --color-brand-primary |
#ff0036 |
Escala completa (light):
| Token | Valor | Uso |
|---|---|---|
primary |
#db143c |
Brand, buttons, active states |
primary-dark |
#c41136 |
Hover pressed |
primary-darker |
#b60f32 |
Active/pressed |
primary-darkest |
#8c0b26 |
Extra énfasis, accents |
primary-light |
#e63358 |
Hover lifted |
primary-lighter |
#ea4566 |
Hover elevated |
primary-lightest |
#f07a92 |
Tints, highlighted text |
Escala completa (dark — más vibrante):
| Token | Valor | Uso |
|---|---|---|
primary |
#ff0036 |
Brand, buttons, active states |
primary-dark |
#e60030 |
Hover pressed |
primary-darker |
#cc002b |
Active/pressed |
primary-darkest |
#990020 |
Extra énfasis, accents |
primary-light |
#ff335e |
Hover lifted |
primary-lighter |
#ff4d72 |
Hover elevated |
primary-lightest |
#ff809b |
Tints, highlighted text |
Por qué dos valores: en dark mode el rojo necesita mayor vibración para mantener contraste y "salir" sobre el fondo azul-slate.
#ff0036tiene más presencia que#db143cy mantiene ratio AA (4.96:1) sobre el canvas#060C13.
Paleta A — Azul-slate: H215 S50, tinte frío perceptible. Verificado accesible con
#FF0036en canvas (4.96:1) y surface (4.71:1).
| Token | Dark | Light | Uso |
|---|---|---|---|
background |
#060C13 |
Docusaurus default (white) | Canvas principal |
background-surface |
#0B131E |
— | Cards sólidas, code blocks |
background-surface-raised |
#0F1824 |
— | Headers de tabla, énfasis sutil |
navbar-bg |
rgba(6,12,19,0.75) |
rgba(255,255,255,0.7) |
Navbar con backdrop-blur |
card-backdrop-bg |
rgba(6,12,19,0.38) |
rgba(255,255,255,0.32) |
CardContainer flotante con backdropBlur |
sidebar-mobile-bg |
rgba(6,12,19,1.0) |
#ffffff |
Sidebar mobile |
dropdown-bg |
#0B131E |
#ffffff |
Menus desplegables |
| Token | Dark | Uso |
|---|---|---|
surface-raised |
#0F1824 |
Headers de tabla, fondos sutiles |
border |
#172230 |
Bordes estándar, separadores |
border-strong |
#202C3C |
Bordes de componentes interactivos |
| Rol | Dark | Light | Contraste aprox. |
|---|---|---|---|
| Primario (headings) | #ffffff |
#000000 |
21:1 ✅ |
| Secundario (body) | #cccccc |
sistema | ~7:1 sobre #060C13 ✅ |
| Terciario (labels, nav) | #888888 |
sistema | ~5:1 sobre #060C13 ✅ |
| Sidebar activo | #adadad |
— | ~6:1 sobre #060C13 ✅ |
| Disabled / muted | #6a6b6c |
— | ~4.5:1 — disabled, WCAG exime ✅ |
| Rol | Token | Dark | Light |
|---|---|---|---|
| Error / Danger | --color-error |
#ff0036 |
#db143c |
| Success | --color-success |
#22c55e |
#16a34a |
| Warning | --color-warning |
#fbbf24 |
#d97706 |
| Info | --color-info |
#3b82f6 |
#1d4ed8 |
Usadas en overlays, glows y estados interactivos.
Usa los tints semánticos transparentes para énfasis inline, feedback de hover/active/focus y tracks de progress/slider.
Usa los tokens de superficie semántica opaca (*-surface-light / *-surface-dark) para contenedores de estado o superficies flotantes/elevadas donde el contenido de abajo no debe transparentarse.
| Rol | Valor |
|---|---|
| Red glow base | rgba(255, 0, 54, 0.15) |
| Red glow active | rgba(255, 0, 54, 0.30) |
| Red menu active bg | rgba(255, 0, 54, 0.10) |
| Red menu hover bg | rgba(255, 255, 255, 0.05) |
| Red tinted surface | rgba(255, 0, 54, 0.06) |
| Warm amber glow | rgba(255, 185, 0, 0.12) |
| White overlay subtle | rgba(255, 255, 255, 0.05) |
| White overlay medium | rgba(255, 255, 255, 0.07) |
| White border faint | rgba(255, 255, 255, 0.06) |
| Black overlay heavy | rgba(0, 0, 0, 0.60) |
Space Grotesk Variable — humanista geométrica, todos los pesos en un único archivo de fuente variable. Reduce CLS (Cumulative Layout Shift) al eliminar el font swap.
@import '@fontsource-variable/space-grotesk';
font-family: 'Space Grotesk Variable', 'Space Grotesk', system-ui, -apple-system, sans-serif;Space Grotesk reemplaza a Inter en todos los contextos. Se usa para headings, body, botones, captions, código de UI y navegación.
Monospace: fuente del sistema (ui-monospace, SFMono-Regular, Menlo) para code blocks técnicos.
| Peso | Uso |
|---|---|
400 |
Texto secundario, captions ligeras, fine print |
500 |
Baseline de body — el peso de trabajo del sistema |
600 |
Botones, badges, labels con énfasis, bold captions |
700 |
Headings — todos los h1–h6 |
Principio: el peso 500 como baseline (no 400) da un heft extra que mejora la legibilidad sobre fondos oscuros. El peso 400 se reserva para contextos donde se necesita contraste de jerarquía visual.
| Rol | Tamaño | Peso | Line Height | Letter Spacing | Notas |
|---|---|---|---|---|---|
| Display Hero | 56–64px | 700 | 1.10 | 0px | Headings de landing |
| Section Heading | 36–48px | 700 | 1.15 | 0px | Secciones principales |
| Card Heading | 22–24px | 700 | 1.20 | 0px | Títulos de card |
| Sub-heading | 18–20px | 600 | 1.40 | 0.1px | Subtítulos, features |
| Body Large | 18px | 500 | 1.60 | 0.2px | Párrafos prominentes |
| Body | 16px | 500 | 1.60 | 0.2px | Texto principal |
| Body Small | 14px | 500 | 1.50 | 0.1px | UI labels, nav links sidebar |
| Button | 16px | 600 | 1.15 | 0.01em | letter-spacing: 0.01em |
| Nav Link | 16px | 600 | 1.40 | 0.01em | Links de navbar principal |
| Caption | 14px | 500 | 1.40 | 0.2px | Metadata, labels |
| Badge / Tag | 10–12px | 600–700 | 1.40 | 0.02em | Micro-labels, "New" badges |
| Code (UI) | 93% | 500 | 1.60 | 0.3px | Inline code, snippets |
| Announcement | 13–14px | 500 | — | 0.01em | Banners de anuncio |
- Tracking positivo en dark: +0.01em–+0.2px en body text compensa la irradiación del blanco sobre negro
- 700 solo en headings: los headings usan bold (700) de forma consistente — nunca en body
- Sin
font-style: italicpara énfasis — usar peso o color en su lugar - Space Grotesk everywhere: no mezclar con otras familias salvo monospace del sistema para code
A diferencia de un sistema de elevación con sombras, Stack-and-Flow usa un sistema de opacidad y blur que distingue las capas por su nivel de transparencia.
| Nivel | Tipo | Tratamiento | Uso |
|---|---|---|---|
| Base | Opaco | background: #060C13 + grid sutil |
Canvas de página |
| Raised | Opaco | background: #0B131E + border: 1px solid #172230 |
Cards sólidas, code blocks, dropdowns |
| Frosted | Semitransparente | background: rgba(6,12,19,0.38) + border: rgba(255,0,54,0.5) + backdrop-filter: blur(20px) |
CardContainer backdropBlur="md" cuando flota sobre contenido |
| Frosted Light | Semitransparente | background: rgba(255,255,255,0.32) + border: rgba(255,0,54,0.5) + backdrop-filter: blur(20px) |
CardContainer backdropBlur="md" en light mode cuando flota sobre contenido |
| Tinted | Semitransparente colored | background: rgba(255,0,54,0.06–0.15) |
Botones secondary, hover states, menús activos |
| Overlay | Semitransparente oscuro | background: rgba(0,0,0,0.6) + backdrop-filter: blur(4px) |
Fondos de modal, sidebar backdrop |
Card opaca — usa para contenido estructural, tablas, code snippets:
background: #0B131E;
border: 1px solid #172230;
border-radius: 8px;Card frosted — usá solo cuando el CardContainer flota sobre contenido (backdropBlur="sm|md|lg"):
background: rgba(6, 12, 19, 0.38);
backdrop-filter: blur(20px); /* md; sm=10px, lg=36px */
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 0, 54, 0.5);
border-radius: 8px;Card tinted — usa para estados activos o elementos con énfasis de acento:
background: rgba(255, 0, 54, 0.08);
border: 1px solid rgba(255, 0, 54, 0.2);
border-radius: 8px;Solo los elementos que literalmente flotan sobre otros (navbar, mobile sidebar, modals, tooltips o un CardContainer usado como superficie flotante) usan backdrop-filter. Los cards de contenido no lo usan — son opacos. Esta distinción es intencional: el blur implica "estoy flotando", el opaco implica "soy contenido". En CardContainer, mantené backdropBlur="none" para cards en flujo normal y usá sm, md o lg solo para superficies glass/floating.
Primary — Neon Gradient:
background: linear-gradient(135deg, #ff1a4b 0%, #cc0030 100%);
border: none;
border-radius: 9999px; /* pill */
color: #ffffff;
font-weight: 500;
letter-spacing: 0.01em;
box-shadow:
0 0 0 1.5px rgba(255, 60, 90, 0.5),
0 0 16px 4px rgba(255, 0, 54, 0.45),
0 0 40px 6px rgba(255, 0, 54, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.15);Hover: gradiente más intenso + glow exterior ampliado.
Secondary — Ghost con glow contenido:
background: rgba(255, 0, 54, 0.06);
border: 1.5px solid rgba(255, 0, 54, 0.5);
border-radius: 9999px;
color: #ffffff;
box-shadow:
0 0 8px 2px rgba(255, 0, 54, 0.15),
0 0 24px 4px rgba(255, 0, 54, 0.07),
inset 0 0 10px rgba(255, 0, 54, 0.04);Light mode: color: #cc0030, borde opaco.
Transición: box-shadow 0.25s ease, background 0.25s ease — nunca cambio de color instantáneo.
Forma: todos los botones son pill (border-radius: 9999px) — sin botones rectangulares en la UI principal.
background: rgba(6, 12, 19, 0.75);
backdrop-filter: blur(16px);
border-bottom: 1px solid #172230;- Links:
color: #9c9c9d→#ffffffen hover,text-decoration: underlineopcional - CTA button al final: botón primary pill
- Sticky en top, transición suave al hacer scroll
- Mobile: hamburger → sidebar con fade + slide (
translateX(-16px)→0)
Tres variantes que coexisten:
- Opaco (
#0B131E+ borde#172230) — contenido, docs, features - Frosted (rgba + blur) — elementos flotantes
- Tinted red (
rgba(255,0,54,0.06–0.10)+ borde red semitransparente) — estados activos, highlights de acento
Border-radius estándar: 8px. Cards grandes: 12px.
background: rgba(22, 163, 74, 1); /* success */
/* o */
background: rgba(255, 0, 54, 1); /* brand */
color: #ffffff; /* dark: color: #000 para green */
border-radius: 3px;
padding: 1px 6px;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.02em;"New" badge: verde (#16a34a light, #22c55e dark con color: #000).
background: #0B131E;
border: 1px solid #202C3C;
border-radius: 8px;
color: #f9f9f9;Focus: el borde se aclara + outline compartido focus-ring (2px solid var(--color-primary), offset 2px).
Placeholder: #6a6b6c.
background: #0B131E;
border: 1px solid #172230;
border-radius: 8px;
font-size: 93%; /* --ifm-code-font-size */Highlighted line: rgba(219,20,60,0.10) (light) / rgba(255,0,54,0.15) (dark).
Drawer es una superficie flotante tipo dialog para tareas suplementarias, navegación, formularios y contenido largo. Usa el mismo overlay que Modal (opacity, blur o transparent) y un panel opaco surface con borde, sombra de modal y movimiento por opacity + transform solamente.
startyendson placements lógicos: enmd+respetan LTR/RTL; en mobile se adaptan a bottom sheet.top,bottomy el bottom sheet mobile usan utilidadesmax-h-drawer-*basadas en--size-drawer-block-viewport.- Los footers de bottom/mobile drawers usan safe area para no colisionar con home indicators.
- Header y footer permanecen visibles;
Drawer.Bodyes la región con scroll interno. prefers-reduced-motionelimina las transiciones de entrada/salida sin cambiar semántica ni foco.
Patrón reutilizable para cualquier badge con métrica numérica:
- Sección izquierda:
rgba(255,255,255,0.05)+ icono - Divider:
1px solid #262626 - Sección derecha:
rgba(255,185,0,0.07)+ número en#fbbf24 - Hover: borde dorado
rgba(255,185,0,0.55)+box-shadow: 0 0 0 3px rgba(255,185,0,0.12)
border-bottom: 1px solid rgba(255, 0, 54, 0.35);
font-size: 0.85rem;
font-weight: 500;
letter-spacing: 0.01em;Links: #ff4d6d → #ff8099 hover, con border-bottom: 1px solid rgba para subrayado sutil.
Algunos componentes usan bordes con intensidad variable — no un borde plano sino un gradient border con destello. El efecto simula iluminación direccional sobre el borde del componente.
Técnica (pseudo-elemento):
/* El elemento necesita position: relative, background sólido y border: 1px solid transparent */
.gradient-border {
position: relative;
border: 1.5px solid transparent;
background-clip: padding-box;
}
.gradient-border::before {
content: '';
position: absolute;
inset: -1.5px;
border-radius: inherit;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.18) 0%,
rgba(255, 0, 54, 0.55) 40%,
rgba(255, 0, 54, 0.15) 100%
);
z-index: -1;
}Variante secundaria (botón ghost con destello):
.gradient-border::before {
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.12) 0%,
rgba(255, 0, 54, 0.45) 45%,
rgba(255, 0, 54, 0.08) 100%
);
}Regla de uso: solo en elementos interactivos que necesiten énfasis visual de borde — botones secondary, inputs en focus, cards activas. Nunca en bordes estructurales (separadores, tablas).
Tres columnas de links sobre fondo base (#060C13). Sin cards, sin bordes — el contenido flota directo sobre el canvas.
footer {
background: #060C13;
border-top: 1px solid #172230;
padding: 48px 0 24px;
}Estructura:
- Columnas: Documentation / Community / More (o las que el producto defina)
- Títulos de columna: 14px Space Grotesk 600,
#ffffff - Links: 14px Space Grotesk 500,
#888888→#cccccchover - Copyright: 12px Space Grotesk 400,
#6a6b6c, centrado - Gap entre columnas:
32px–48px - Sin
backdrop-filter, sin cards, sin sombras — opaco y limpio
El canvas principal usa un grid de doble línea como textura técnica:
Dark:
background:
linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px) 0 0 / 40px 40px,
linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px) 0 0 / 40px 40px,
#060C13;Light:
background:
linear-gradient(rgba(0, 0, 0, 0.035) 1px, transparent 1px) 0 0 / 40px 40px,
linear-gradient(90deg, rgba(0, 0, 0, 0.035) 1px, transparent 1px) 0 0 / 40px 40px,
var(--background);Regla: el grid aparece en el canvas de docs y landing. No en modals, dropdowns, ni cards.
| Nombre | Valor | Uso |
|---|---|---|
| Base glow | 0 4px 20px rgba(219,20,60,0.15) |
Light: hover de elementos de marca |
| Active glow | 0 8px 30px rgba(219,20,60,0.30) |
Light: estados activos |
| Base glow dark | 0 4px 20px rgba(255,0,54,0.15) |
Dark: hover de elementos de marca |
| Active glow dark | 0 8px 30px rgba(255,0,54,0.30) |
Dark: estados activos |
| Amber stars glow | 0 0 0 3px rgba(255,185,0,0.12) |
GitHub stars badge hover |
.fade-in-section {
opacity: 0;
transform: translateY(12px);
transition:
opacity 560ms cubic-bezier(.2,.8,.2,1),
transform 560ms cubic-bezier(.2,.8,.2,1);
will-change: opacity, transform;
}
/* Al entrar en viewport: */
.fade-in-visible {
opacity: 1;
transform: translateY(0);
}Curva cubic-bezier(.2,.8,.2,1) — ease-out suave con ligero overshoot inicial.
Stack-and-Flow provee dos primitivos de fondo animado como componentes independientes. No son un solo componente con prop theme — son motores distintos con responsabilidades distintas.
Motor de partículas físicas 2D. Gestiona posición, velocidad, aceleración y pulso de partículas via requestAnimationFrame.
Lo que varía por tema (configuración declarativa):
type CanvasTheme = {
orbs: {
count: { mobile: number; desktop: number }
color: string // e.g. '255, 0, 54'
minRadius: number
maxRadius: number
}
sparks: {
count: { mobile: number; desktop: number }
color: string
}
foci: Array<{
baseX: number // posición relativa 0–1
baseY: number
color: string
speed: number
range: number
}>
ambient: {
color: string
opacity: number
}
fps: { mobile: number; desktop: number }
}Lo que NO varía (lógica interna del motor): física de partículas, wrap horizontal, resize handler, frame throttling.
Temas incluidos:
bokeh— orbs rojos difusos + sparks con halo, foci dinámicos. Inspirado en bokeh de lente fotográfica.
Uso:
<CanvasEngine theme="bokeh" className="absolute inset-0" aria-hidden />Escalabilidad: un tema nuevo = un archivo themes/aurora.ts con la configuración. Si el nuevo efecto necesita física diferente (e.g. partículas que siguen el cursor), es un motor nuevo — no una prop adicional.
Componente para SVGs animados con interpolación declarativa (opacity, transform, path morph). Motor completamente distinto a CanvasEngine — no comparten código.
<SvgAnimation src={LogoSvg} animation="fade-pulse" />Animations disponibles:
fade-pulse— opacity cíclica suave (0.4 → 1.0 → 0.4)float— translateY suave (-6px → 0 → -6px)spin-slow— rotación completa en 8s
Wrapper de layout que posiciona cualquier primitivo de fondo. Los productos lo usan como contenedor — el DS no dicta qué va dentro.
// Solo canvas
<BackgroundSlot>
<CanvasEngine theme="bokeh" />
</BackgroundSlot>
// Solo SVG
<BackgroundSlot>
<SvgAnimation src={LogoSvg} animation="fade-pulse" />
</BackgroundSlot>
// Composición libre
<BackgroundSlot>
<CanvasEngine theme="bokeh" />
<SvgAnimation src={LogoSvg} animation="fade-pulse" />
</BackgroundSlot>CSS:
.background-slot {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
z-index: 0;
}El Hero NO es un componente del DS — cada producto define su propia narrativa visual. El DS provee los primitivos para construirlo.
Patrón recomendado:
<section className="relative overflow-hidden">
{/* Capa 0 — fondo animado */}
<BackgroundSlot>
<CanvasEngine theme="bokeh" />
</BackgroundSlot>
{/* Capa 1 — contenido */}
<div className="relative z-10 max-w-[1200px] mx-auto px-6 md:px-10 lg:px-16 py-20 md:py-32">
<h1>…</h1>
<p>…</p>
<div className="flex gap-4">
<Button variant="primary" rounded>Get Started</Button>
<Button variant="secondary" rounded>View on GitHub</Button>
</div>
</div>
</section>Regla: el grid de fondo (section 6) y CanvasEngine coexisten — el grid es CSS, el canvas es encima con mix-blend-mode: screen opcional para que los glows interactúen con el grid.
8px — todas las medidas son múltiplos de 8 o 4.
1 · 2 · 3 · 4 · 8 · 10 · 12 · 16 · 20 · 24 · 32 · 40 · 48 · 64 · 80 · 96 · 120
- Max-width:
1200px, centrado conmargin: 0 auto - Padding horizontal:
24px(mobile) →40px(tablet) →64px(desktop)
- Padding vertical entre secciones:
80px–120px - Padding interno de cards:
16px–32px - Gap entre elementos relacionados:
8px–16px
- Hero: una columna centrada
- Features: 2–3 columnas en desktop, 1 columna en mobile
- Docs: sidebar fija + contenido + TOC opcional
| Valor | Uso |
|---|---|
3px |
Badges micro, "New" labels |
6px |
Dropdown items, menú links |
8px |
Input fields, cards estándar, botones secundarios, code blocks |
9999px |
Botones pill (CTA, nav CTA) — forma circular máxima |
12px |
Cards grandes, pagination nav links |
Todos los valores de texto sobre sus respectivos fondos cumplen WCAG AA (4.5:1) como mínimo. Los textos primarios cumplen AAA (7:1+).
| Combinación | Contraste | Nivel |
|---|---|---|
#ffffff sobre #060C13 |
~21:1 | AAA ✅ |
#cccccc sobre #060C13 |
~7.5:1 | AAA ✅ |
#888888 sobre #060C13 |
~5.1:1 | AA ✅ |
#adadad sobre #060C13 |
~6.1:1 | AA ✅ |
#ff0036 sobre #060C13 |
~4.96:1 | AA ✅ |
#ff0036 sobre #0B131E |
~4.71:1 | AA ✅ |
#ff0036 sobre #0F1824 |
~4.51:1 | AA ✅ |
#ff335e sobre #0F1824 |
~5.00:1 | AA ✅ (usar para links/iconos sobre raised) |
#db143c sobre #ffffff |
~4.7:1 | AA ✅ |
#cc0030 sobre #ffffff |
~5.4:1 | AA ✅ |
#22c55e sobre #060C13 |
~6.8:1 | AA ✅ |
#000000 sobre #22c55e |
~6.8:1 | AA ✅ (badge dark) |
⚠️ Nunca usar#ff0036como color de texto sobre#ffffffen light mode — contraste insuficiente. Siempre usar#cc0030o más oscuro en light.⚠️ #6a6b6c(disabled/muted) no cumple AA sobre los fondos dark — es correcto: WCAG exime explícitamente los estadosdisableddel requisito de contraste.
- La altura visual de los controles compartidos se define con la escala
control:xs = 24px,sm = 32px,md = 40px,lg = 48px. - Tokens Tailwind v4:
--spacing-control-xs|sm|md|lggeneran utilidadesh-control-*yw-control-*;--spacing-form-field-sm|md|lggeneranh-form-field-*;--spacing-touch-target-mingeneramin-h-touch-target-min,min-w-touch-target-minysize-touch-target-min. Button,IconButtonyLinkCTA (button/outlined) usan esa escala visual compartida.Linkregularsigue siendo tipográfico e inline.InputySelectusan la escala semánticaform-field:sm = 48px,md = 56px,lg = 64px, porque su altura contempla label, floating label, adornments y alineación entre campos.--spacing-touch-target-min(44px) es una guía de target táctil, no una altura visual universal. Úsalo para superficies touch-first o para ampliar el hit area de controles compactos comoCheckboxySwitchsin agrandar su forma visible.- Otras excepciones documentadas:
TextAreasigue siendo multiline/content-driven;Chipconserva una escala compacta de tag/token;Badgesigue siendo informativo, no un control interactivo general. - Nav links y elementos de menú deben seguir ofreciendo un área cómoda en contextos touch-first, aunque su altura visual no use necesariamente la escala
control.
- Todos los elementos interactivos consumen la utilidad compartida
focus-ringenfocus-visible. - Contrato:
outline-style: solid,outline-color: var(--color-primary),outline-width: 2px,outline-offset: 2px. - Nunca
outline: nonesin reponerfocus-visible:focus-ringo una variante equivalente para wrappers, peers, groups o:has(:focus-visible).
- Transiciones: máximo
560ms. Respetarprefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
.fade-in-section {
transition: none;
opacity: 1;
transform: none;
}
}- Usar
#060C13como fondo dark base — azul-slate profundo con tinte frío H215 S50 - Aplicar el grid de fondo (opacidad 0.025–0.035) en el canvas principal con
#060C13como color base - Diferenciar
backdrop-filter: blur(elementos flotantes) debackground: #0B131E(contenido) - Usar el rojo más vibrante en dark (
#ff0036) y el más sobrio en light (#db143c) - Para links/iconos sobre
surface-raised(#0F1824) usar#ff335e— mantiene 5:1 exacto - Construir botones primarios con gradiente + glow multi-capa — el neon es signature
- Mantener texto secundario en
#cccccc(dark) para ~7.5:1 de contraste - Usar
border-radius: 9999pxexclusivamente en botones CTA principales - Aplicar
transition: box-shadow 0.25s ease, background 0.25s easeen todos los elementos interactivos - Usar
font-weight: 700solo en headings (h1–h6), nunca en body - Añadir
will-change: opacity, transforma animaciones de entrada para evitar jank
- No usar negro puro
#000000como fondo dark — la paleta aprobada es azul-slate#060C13 - No aplicar
backdrop-filter: blura cards de contenido — solo a elementos flotantes - No usar weights menores a 500 para body text en dark mode — el 400 se percibe demasiado fino
- No crear sombras decorativas sin propósito — la profundidad viene del contraste de superficie, no de box-shadows
- No mezclar pill buttons con botones rectangulares en la misma sección
- No omitir el
border: 1px soliden cards dark — sin borde, las cards se funden con el fondo - No usar el grid de fondo dentro de cards, modals o dropdowns — solo en el canvas raíz
- No aplicar colores arbitrarios fuera de la paleta definida — cada nuevo color necesita justificación de contraste
- No animar propiedades que fuercen layout (
width,height,top,left) — soloopacity,transform,box-shadow
Dark background: #060C13
Dark surface: #0B131E
Dark surface-raised: #0F1824
Dark border: #172230
Dark border-strong: #202C3C
Brand red (dark): #ff0036
Brand red-light (dark): #ff335e ← usar sobre surface-raised
Brand red (light): #db143c
Primary text (dark): #ffffff
Secondary text (dark): #cccccc
Tertiary text (dark): #888888
Success (dark): #22c55e
Warning (dark): #fbbf24
Navbar bg (dark): rgba(6, 12, 19, 0.75) + blur(16px)
Hero section:
"Crea una hero section con fondo
#060C13, grid de líneasrgba(255,255,255,0.025)cada 40px, heading 64px Space Grotesk 700 en#ffffff, descripción 18px peso 500 en#cccccc, y dos botones pill: primary con gradiente#ff1a4b → #cc0030y glow neon multi-capa, secondary con bordergba(255,0,54,0.5)y fondorgba(255,0,54,0.06)"
Feature card:
"Diseña un feature card con fondo
#0B131E, borde1px solid #172230,border-radius: 8px, heading 22px Space Grotesk 700, body text 16px peso 500 en#cccccc, y un icono en#ff0036en la esquina superior izquierda"
Navbar:
"Construye una navbar sticky con
background: rgba(6,12,19,0.75),backdrop-filter: blur(16px),border-bottom: 1px solid #172230, links en#888888→#ffffffon hover, y un botón CTA pill con gradiente rojo a la derecha"
Estado activo en sidebar:
"Aplica estado activo con
background: rgba(255,0,54,0.10),color: #ff0036,font-weight: 500,border-radius: 8px— sin borde adicional"
Badge "New":
"Badge con
background: #22c55e(dark) /#16a34a(light),color: #000(dark) /#fff(light),border-radius: 3px,padding: 1px 6px, 10px Space Grotesk 700,letter-spacing: 0.02em"
- ¿El fondo es
#060C13(azul-slate) — no negro puro#000000, no gris oscuro? - ¿Las cards tienen borde
1px solid #172230— sin borde se funden con el fondo? - ¿El
backdrop-filter: blursolo está en elementos flotantes (navbar, modals)? - ¿El texto secundario es
#cccccc— no#999999ni menor contraste? - ¿Los botones primarios tienen gradiente + glow, no color flat?
- ¿Los botones son pill (
border-radius: 9999px) — no rectangulares? - ¿El rojo en light mode es
#db143co más oscuro — nunca#ff0036? - ¿Space Grotesk Variable está cargado como variable font — no como múltiples pesos estáticos?
- ¿Las animaciones de entrada usan
cubic-bezier(.2,.8,.2,1)conwill-change? - ¿Hay
prefers-reduced-motionpara las animaciones de scroll?