un estudio de los ángeles que tokeniza sus curvas de animación antes que su escala de grises: el :root real declara cinco variables, dos de color y tres de easing.
Gris hormigón #EBEBEB, tinta #1A1A1A (--color-dark) y un solo saturado, el rojo #FF3928 (--color-red), reservado a los nombres de proyecto. Una única grotesca bold servida como un woff2 anónimo, usada a exactamente dos tamaños: 25px con interlínea 1.0 y 13.33px. Todo en caja baja, todo múltiplo de 25, y un lienzo WebGL de scroll virtual donde los shaders doblan las imágenes al hacer scroll.
:root {
--color-dark: #1a1a1a;
--color-red: #ff3928;
--o3: cubic-bezier(.215, .61, .355, 1); /* easeOutCubic */
--o6: cubic-bezier(.19, 1, .22, 1); /* easeOutExpo */
--io6: cubic-bezier(.16, 1, .3, 1); /* reveals largos */
}
Esto es todo lo que Zajno tokeniza: dos colores y tres curvas de animación. Ni espaciado, ni tipografía, ni sombras. Un estudio que versiona sus easings como otros versionan su paleta está diciendo dónde cree que vive su marca: en el movimiento. El resto de valores (gris, blanco, muted) se miden del censo de área del DOM.
los párrafos de zajno son bloques compactos donde cada línea toca a la siguiente. la interlínea 1.0 a 25px es la voz del sistema.
La legibilidad se protege con párrafos cortos (3 a 5 líneas), no con aire entre líneas. Abrir la interlínea a 1.5 convierte esto en cualquier otro sitio. No hay escala tipográfica: hay dos alturas y una rejilla, y la jerarquía extra la dan el wordmark, la posición y el rojo.
| rol | size real | weight | lh | caja |
|---|---|---|---|---|
| wordmark | ~34vw | lettering | 1.0 | baja |
| contenido (h2, h3, p, a, button) | 25px | 600 equiv. | 1.0 (25px) | baja |
| nav / h1-logo / metadatos | 13.33px | 600 equiv. | 1.25 (16.67px) | baja |
Estructura real (a.ho-wr-bo-a): número + servicio + premios como texto corrido + nombre + categoría. En hover, el nombre vira a rojo en 250ms con --o3 y, en el sitio real, la imagen del proyecto emerge en el canvas WebGL siguiendo al cursor con lag elástico (aquí, una placa que persigue al puntero con lerp). Los premios son contenido, no badges: nada de pills ni iconos.
El header flota sobre el gris sin fondo propio. Hover: color hacia el rojo en 250ms cubic-bezier(.215,.61,.355,1), la transición más repetida del sitio.
La placa blanca sobre el gris #EBEBEB ES el marco: un nivel de luminancia de diferencia, sin borde dibujado, sin sombra, sin radio.
"Send Request" es texto de 25px en tinta, sin fondo, sin borde, sin radio, padding 0. El énfasis lo dan la posición (final de página, rodeado de gris) y el hover rojo. Focus: outline 2px rojo (derivado). Disabled: opacidad .4 (derivado).
Sobre la franja negra el rojo rinde su mejor contraste (4.9:1, AA texto normal): los enlaces calientes del footer pueden ir en rojo a cualquiera de los dos tamaños. El muted #B2B2B2 también vive aquí (8.2:1), nunca sobre el gris.
La franja inversa es el único cambio de superficie: sin bordes ni divisores, el negro ES el divisor.
El :root real declara tres curvas con nombre: --o3 (easeOutCubic) para micro-interacciones, --o6 (easeOutExpo) para transforms de entrada y --io6 para los reveals largos. Zajno versiona sus curvas como otros versionan colores.
Las imágenes de proyecto viven dentro de un canvas WebGL a viewport completo. Al hacer scroll, el shader las dobla proporcionalmente a la velocidad y las asienta con inercia al frenar: la intensidad es función de la velocidad, no del tiempo. La firma de Zajno.
Sobre una fila de proyecto, el nombre vira a rojo en 250ms --o3 y la imagen emerge en el canvas siguiendo al cursor con lag elástico. El color avisa, el shader seduce: dos capas de la misma interacción.
Los bloques entran con transform de 600ms sobre --o6: arrancan rapidísimo y frenan larguísimo. El fade de carga inicial usa el keyframe real "fade" con 1800ms sobre --io6. Y el scroll es virtual: el documento mide un viewport y la rueda alimenta un progreso perseguido.
Las tres curvas reales del :root, lado a lado: --o3 resuelve rápido (micro), --o6 pega el golpe y frena (entradas), --io6 se desliza hasta el final (reveals). Con prefers-reduced-motion los shaders se congelan, el scroll virtual cede a scroll nativo y solo quedan los cambios de color de 250ms; el patrón hover-visor necesita equivalente por foco de teclado: nombre en rojo + imagen estática.
:root {
/* reales del sitio */
--color-dark: #1A1A1A;
--color-red: #FF3928;
--o3: cubic-bezier(0.215, 0.61, 0.355, 1);
--o6: cubic-bezier(0.19, 1, 0.22, 1);
--io6: cubic-bezier(0.16, 1, 0.3, 1);
/* medidos del censo del DOM */
--color-background: #EBEBEB;
--color-surface-media: #FFFFFF;
--color-surface-inverse: #1A1A1A;
--color-text-primary: #1A1A1A;
--color-text-accent: #FF3928;
--color-text-muted: #B2B2B2; /* solo sobre oscuro */
--color-text-on-dark: #EBEBEB;
--color-overlay: rgba(0, 0, 0, 0.6);
--color-border: rgba(26, 26, 26, 0.16);
--font-display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-body: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-weight: 600; /* el único peso */
--text-body: 25px; /* line-height: 25px (1.0 exacta) */
--text-nav: 13.33px; /* line-height: 16.67px */
--text-transform: lowercase; /* todo el sistema va en caja baja */
--radius-none: 0;
--radius-full: 100%;
--shadow-none: none;
--space-unit: 25px; /* cuerpo = interlínea = margen = gap */
--space-1: 5px;
--space-2: 10px;
--space-3: 25px;
--space-4: 50px;
--space-5: 100px;
--space-6: 200px;
--duration-micro: 250ms; /* con --o3 */
--duration-enter: 600ms; /* con --o6 */
--duration-reveal: 1800ms; /* con --io6, keyframe "fade" */
}@theme {
--color-dark: #1A1A1A;
--color-red: #FF3928;
--color-background: #EBEBEB;
--color-surface-media: #FFFFFF;
--color-surface-inverse: #1A1A1A;
--color-text-primary: #1A1A1A;
--color-text-accent: #FF3928;
--color-text-muted: #B2B2B2;
--color-text-on-dark: #EBEBEB;
--font-display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-body: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
--text-body: 25px;
--text-body--line-height: 1;
--text-nav: 13.33px;
--text-nav--line-height: 1.25;
--radius-none: 0;
--spacing-1: 5px;
--spacing-2: 10px;
--spacing-3: 25px;
--spacing-4: 50px;
--spacing-5: 100px;
--spacing-6: 200px;
--ease-o3: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-o6: cubic-bezier(0.19, 1, 0.22, 1);
--ease-io6: cubic-bezier(0.16, 1, 0.3, 1);
}{
"colors": {
"dark": "#1A1A1A",
"red": "#FF3928",
"background": "#EBEBEB",
"surface-media": "#FFFFFF",
"surface-inverse": "#1A1A1A",
"text-primary": "#1A1A1A",
"text-accent": "#FF3928",
"text-muted": "#B2B2B2",
"text-on-dark": "#EBEBEB",
"overlay": "rgba(0, 0, 0, 0.6)",
"border": "rgba(26, 26, 26, 0.16)"
},
"typography": {
"body": {
"fontFamily": "grotesca anónima (s / sh.woff2)",
"substitute": "Archivo 600",
"fontSize": "25px",
"fontWeight": 600,
"lineHeight": "1.0",
"letterSpacing": "normal",
"textTransform": "lowercase"
},
"nav": {
"fontFamily": "grotesca anónima (s / sh.woff2)",
"substitute": "Archivo 600",
"fontSize": "13.33px",
"fontWeight": 600,
"lineHeight": "1.25",
"letterSpacing": "normal",
"textTransform": "lowercase"
},
"wordmark": {
"fontFamily": "lettering propio",
"fontSize": "~34vw",
"lineHeight": "1.0",
"letterSpacing": "-0.02em",
"note": "es un dibujo, no una fuente: usar como imagen"
}
},
"rounded": {
"none": "0px",
"full": "100%"
},
"shadow": {
"none": "none"
},
"spacing": {
"unit": "25px",
"scale": ["5px", "10px", "25px", "50px", "100px", "200px"],
"rule": "cuerpo = interlinea = margen = gap = 25px"
},
"motion": {
"o3": { "curve": "cubic-bezier(0.215, 0.61, 0.355, 1)", "duration": "250ms", "use": "color y micro-interacciones" },
"o6": { "curve": "cubic-bezier(0.19, 1, 0.22, 1)", "duration": "600ms", "use": "transforms de entrada" },
"io6": { "curve": "cubic-bezier(0.16, 1, 0.3, 1)", "duration": "1800ms", "use": "reveal de carga (keyframe fade)" },
"scroll": "virtual: documento de 100vh, canvas WebGL con distorsion liquida ligada a la velocidad"
}
}---
version: "1.0"
name: "Zajno"
description: "Sistema visual de Zajno: estudio digital de Los Ángeles (web, branding, 3D, animación) construido sobre un gris hormigón #EBEBEB, una tinta #1A1A1A declarada como --color-dark y un solo saturado, el rojo #FF3928 declarado como --color-red, reservado a los nombres de proyecto. Una única grotesca bold servida como un solo woff2 anónimo (sh.woff2) usada a exactamente dos tamaños: 25px con interlínea 1.0 y 13.33px para la navegación, todo en caja baja. El wordmark gigante ocupa medio viewport y los renders 3D monocromos hacen de imagen. Sin sombras, sin radios salvo el círculo, y un sistema de motion tokenizado en el :root con tres curvas easeOut (--o3, --o6, --io6) sobre un lienzo WebGL de scroll virtual famoso por sus shaders de distorsión líquida."
colors:
primary: "#FF3928"
red: "#FF3928"
ink: "#1A1A1A"
dark: "#1A1A1A"
background: "#EBEBEB"
surface: "#EBEBEB"
surface-media: "#FFFFFF"
surface-inverse: "#1A1A1A"
text-primary: "#1A1A1A"
text-secondary: "#1A1A1A"
text-muted: "#B2B2B2"
text-accent: "#FF3928"
text-on-dark: "#EBEBEB"
text-on-red: "#FFFFFF"
border: "#1A1A1A26"
border-on-dark: "#EBEBEB26"
overlay: "#00000099"
black: "#000000"
success: "#1A1A1A"
info: "#1A1A1A"
error: "#FF3928"
warning: "#FF3928"
typography:
body:
fontFamily: "Zajno Grotesk (sh.woff2)"
fontSize: "25px"
fontWeight: 400
lineHeight: "1.0"
letterSpacing: "normal"
heading:
fontFamily: "Zajno Grotesk (sh.woff2)"
fontSize: "25px"
fontWeight: 400
lineHeight: "1.0"
letterSpacing: "normal"
nav:
fontFamily: "Zajno Grotesk (sh.woff2)"
fontSize: "13.33px"
fontWeight: 400
lineHeight: "1.25"
letterSpacing: "normal"
wordmark:
fontFamily: "lettering propio (SVG/canvas)"
fontSize: "~34vw"
fontWeight: 900
lineHeight: "1.0"
letterSpacing: "-0.02em"
rounded:
none: "0px"
full: "100%"
spacing:
base: "5px"
xs: "10px"
sm: "15px"
md: "25px"
lg: "50px"
xl: "100px"
edge: "25px"
components:
project-link:
textColor: "{colors.ink}"
accentColor: "{colors.red}"
typography: "{typography.body}"
rounded: "{rounded.none}"
hover: "el nombre pasa a rojo #FF3928 y el visor WebGL distorsiona la imagen"
nav-link:
textColor: "{colors.ink}"
typography: "{typography.nav}"
hover: "color 0.25s cubic-bezier(.215,.61,.355,1)"
button-text:
backgroundColor: "transparent"
textColor: "{colors.ink}"
typography: "{typography.body}"
rounded: "{rounded.none}"
media-plate:
backgroundColor: "{colors.surface-media}"
render: "render 3D monocromo (despieces de producto) a sangre completa"
---
# DESIGN.md - Zajno
> Sistema de diseño extraído de `https://zajno.com` (home, julio 2026) siguiendo el skill `url-inspiration-styleguide`.
> Colores y easings leídos de las variables reales del `:root` (`--color-dark: #1a1a1a`, `--color-red: #ff3928`, `--o3`, `--o6`, `--io6`), tamaños y familias medidos de los estilos computados de 4000 nodos, censo de área de color sobre el DOM vivo. La fuente llega como un único `@font-face` con nombre ofuscado (`s`, archivo `sh.woff2`): la identificación es visual y va documentada como sustitución. Lo que el sitio no expone va marcado como *(derivado para completar el sistema)*.
---
## 1. Tema Visual y Atmósfera
Zajno es un estudio de Los Ángeles que colecciona Awwwards y FWA haciendo webs con shaders, y su home es una declaración de método: **tipografía enorme, gris hormigón y un rojo que solo aparece cuando algo importa**. El primer viewport es el wordmark `zajno®` dibujado a lo ancho de la pantalla entera, un lettering propio de trazos gruesos y curvas geométricas, negro sobre gris `#EBEBEB`. Debajo, un render 3D monocromo: el despiece de una cámara flotando en capas, blanco sobre blanco. No hay foto de equipo, no hay gradiente, no hay decoración. Hay masa tipográfica y objetos.
La paleta está tokenizada en el `:root` real del sitio, y son dos variables: `--color-dark: #1a1a1a` y `--color-red: #ff3928`. Todo lo demás es el gris `#EBEBEB` del fondo (3.0M de score de área en el censo), el blanco `#FFFFFF` de las placas de media (2.0M) y un velo `rgba(0,0,0,.6)` para overlays. El rojo `#FF3928` tiene un solo trabajo: **nombrar proyectos**. Acquire, Evergreen, 8Finance, Gentlerain.ai, Brightmark aparecen en rojo a 25px; el resto del texto, en tinta. En un sistema donde nada tiene color, el rojo es un índice.
La tipografía es un acto de reducción extrema: **un solo archivo woff2** (`sh.woff2`, familia declarada como `s`, un solo peso) usado a **exactamente dos tamaños**: 25px con `line-height: 25px` (interlínea 1.0 exacta) para todo el contenido (h2, h3, párrafos, botones) y 13.33px para la navegación y metadatos. Todo en caja baja, incluido el nombre del estudio. No hay escala tipográfica: hay dos alturas y una rejilla. El "display" del sitio no es una fuente más grande, es el wordmark como objeto gráfico.
Y luego está el motion, que es la reputación de Zajno: la página tiene scroll virtual (el documento mide un viewport; la rueda alimenta un canvas WebGL a pantalla completa), y las imágenes de proyecto viven dentro de ese canvas, donde los shaders las doblan: distorsión líquida al hacer scroll, desplazamiento RGB en las transiciones, olas al hover. Los easings están tokenizados en el `:root` como `--o3`, `--o6` y `--io6`, tres curvas easeOut de manual.
**Palabras clave de personalidad**: brutalista amable, monocromo, tipográfico, rojo quirúrgico, caja baja, shader-driven
**Densidad del layout**: masiva en el hero (el wordmark llena la pantalla), aireada en el contenido (bloques de 25px con mucho gris alrededor)
**Modo preferido**: claro (gris hormigón `#EBEBEB`; el negro `#1A1A1A` entra como franja inversa y como masa tipográfica)
**Nivel de ornamentación**: nulo en el DOM; los shaders del canvas son la única ornamentación y solo durante el movimiento
**Audiencia visual objetivo**: startups y marcas de producto que quieren un sitio que se sienta hecho a mano por gente que gana premios haciéndolos
---
## 2. Paleta de Colores y Roles Semánticos
El `:root` real declara dos colores. El censo de área añade el gris de fondo, el blanco de las placas y un gris muted. Cinco valores gobiernan todo el sitio.
### Colores de marca
| Nombre | Variable CSS | Hex | Rol | Texto sobre él |
|--------|-------------|-----|-----|----------------|
| Rojo Zajno | `--color-red` (real) | `#FF3928` | Nombres de proyecto, hover de lo importante, el único saturado | `#FFFFFF` solo a 24px o más |
| Tinta | `--color-dark` (real) | `#1A1A1A` | Todo el texto, el wordmark, la franja inversa | `#EBEBEB` |
| Gris hormigón | `--color-background` | `#EBEBEB` | Fondo del sitio (score 3.0M, la mayor superficie) | `#1A1A1A` |
### Colores de superficie
| Nombre | Variable CSS | Hex | Rol |
|--------|-------------|-----|-----|
| Gris hormigón | `--color-background` | `#EBEBEB` | Fondo de trabajo de todo el sitio |
| Blanco placa | `--color-surface-media` | `#FFFFFF` | Placas de los renders 3D y visores de proyecto (score 2.0M) |
| Negro tinta | `--color-surface-inverse` | `#1A1A1A` | Franja de contacto/footer y bloques inversos |
| Velo | `--color-overlay` | `rgba(0,0,0,0.6)` | Overlay real de menús y modales |
| Negro puro | `--color-black` | `#000000` | Máscaras del canvas, nunca superficie de texto |
### Colores de texto
| Nombre | Variable CSS | Hex | Uso |
|--------|-------------|-----|-----|
| Tinta | `--color-text-primary` | `#1A1A1A` | Párrafos, h2/h3, navegación, botones |
| Rojo | `--color-text-accent` | `#FF3928` | Nombres de proyecto (h2 reales medidos en rojo) y hovers de énfasis |
| Muted | `--color-text-muted` | `#B2B2B2` | Metadatos atenuados (real: `rgb(178,178,178)` en el censo) |
| Sobre oscuro | `--color-text-on-dark` | `#EBEBEB` | Texto sobre la franja negra |
| Sobre rojo | `--color-text-on-red` | `#FFFFFF` | Solo display grande sobre rojo |
### Contraste verificado
| Combinación | Ratio | Nivel |
|-------------|-------|-------|
| `#1A1A1A` sobre `#EBEBEB` | 14.6:1 | AAA |
| `#1A1A1A` sobre `#FFFFFF` | 17.4:1 | AAA |
| `#EBEBEB` sobre `#1A1A1A` | 14.6:1 | AAA |
| `#FF3928` sobre `#EBEBEB` | 3.0:1 | Solo texto grande (24px o más); los h2 de 25px pasan justo |
| `#FF3928` sobre `#FFFFFF` | 3.6:1 | AA solo texto grande |
| `#FF3928` sobre `#1A1A1A` | 4.9:1 | AA texto normal: el rojo rinde mejor sobre negro |
| `#FFFFFF` sobre `#FF3928` | 3.6:1 | AA solo texto grande |
| `#B2B2B2` sobre `#EBEBEB` | 1.8:1 | Nunca texto: solo señales decorativas |
| `#B2B2B2` sobre `#1A1A1A` | 8.2:1 | AAA: el muted funciona sobre oscuro |
> **La trampa del rojo**: `#FF3928` sobre el gris `#EBEBEB` da exactamente 3.0:1. El sitio real lo usa a 25px (texto grande, pasa AA por 0.0 de margen). Nunca lo bajes de 24px sobre gris; si necesitas rojo pequeño, ponlo sobre la franja negra (4.9:1, AA texto normal).
### Colores de estado
El sitio no tiene estados semánticos: el formulario de contacto resuelve el error en rojo de marca. *(Derivados para completar el sistema)*: éxito e info en tinta, error y aviso en el rojo `#FF3928`, sin fondos tintados, que no existen en este sistema.
| Estado | Variable CSS | Hex | Nota |
|--------|-------------|-----|------|
| Éxito | `--color-success` | `#1A1A1A` | *(derivado)* mensaje en tinta, la calma es el default |
| Info | `--color-info` | `#1A1A1A` | *(derivado)* |
| Error | `--color-error` | `#FF3928` | coherente: el rojo ya significa "mira aquí" |
| Aviso | `--color-warning` | `#FF3928` | *(derivado)* |
---
## 3. Reglas de Tipografía
```css
/* Familia real: un solo @font-face con nombre ofuscado
font-family: "s"; src: url("/static/font/sh.woff2");
Un archivo, un peso. Grotesca bold de corte Helvetica Now/Neue Haas.
-> sustituto Google: Archivo 600 */
--font-display: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--font-body: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
/* Mono: no detectada en el sitio. Solo para bloques de código en
documentación. (derivado para completar el sistema) */
--font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
```
**Google Fonts (sustituto):**
```html
<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=Archivo:wght@500;600;700&display=swap" rel="stylesheet">
```
### Nota sobre sustitución tipográfica
**Original: grotesca propietaria anónima (`s` / sh.woff2) -> HTML: Archivo 600 (Google substitute).**
La fuente del sitio llega con el nombre ofuscado a propósito (familia `s`, archivo `sh.woff2`, un solo peso declarado como 400 que renderiza como un semibold). Por dibujo (terminaciones horizontales, `a` de doble piso, contrapunzones compactos, `t` de asta recta, caja baja protagonista) es una neo-grotesca del linaje Helvetica Now Display / Neue Haas Grotesk en corte bold.
Candidatas comparadas antes de decidir:
| Candidata | Por qué encaja | Por qué se descarta |
|---|---|---|
| **Archivo** | Grotesca de raíz americana con los rasgos exactos del original a peso 600: densa, de aperturas moderadas, muy sólida en caja baja a 25px, y aguanta bloques con interlínea 1.0 sin que las ascendentes choquen. Familia variable con el rango 500-700 que este sistema necesita. | **Elegida.** |
| Inter | Neo-grotesca de referencia en UI. | Altura de x mayor y aire más "sistema operativo"; a 25px/1.0 se ve interfaz, no manifiesto. |
| Roboto | Disponible en todos los pesos. | Esqueleto geométrico-mecánico; pierde el sabor Helvetica del original. |
| Work Sans | Buen color tipográfico en bold. | Detalles humanistas (terminales inclinados) que el original no tiene. |
> El peso: el original declara 400 pero pinta como 600. En el HTML se usa **Archivo 600** como equivalente visual y se documenta aquí la diferencia. El interletrado queda en `normal`, como el original.
### Escala tipográfica
> Tamaños reales medidos: **25px con line-height 25px** (h2, h3, párrafos, enlaces de proyecto, botones: todo el contenido) y **13.3328px con line-height 16.6672px** (h1-logo, navegación, metadatos). Dos tamaños en todo el sitio. El wordmark del hero es lettering gráfico, no un tamaño de fuente.
| Token | px real | Line height | Weight | Uso |
|-------|---------|-------------|--------|-----|
| `--f-wordmark` | ~34vw | 1.0 | lettering | `zajno®` como objeto del hero, negro pleno |
| `--f-body` | 25px | 1.0 (25px) | 600 (equiv.) | TODO el contenido: h2, h3, p, enlaces, botones |
| `--f-nav` | 13.33px | 1.25 (16.67px) | 600 (equiv.) | Navegación, h1-logo, metadatos, créditos |
### Pesos tipográficos
```css
--font-semibold: 600; /* el único peso del sistema (la woff2 solo trae uno) */
```
> **Un archivo, un peso, dos tamaños.** La jerarquía se construye con color (rojo = proyecto), con posición y con el canvas. Si necesitas más jerarquía, no engordes: sube al wordmark o baja a 13.33px.
### Letter spacing
```css
--tracking-text: normal; /* 25px y 13.33px van sin tracking */
--tracking-wordmark: -0.02em; /* solo el lettering del hero aprieta (derivado del dibujo) */
```
**Regla clave**: la interlínea 1.0 exacta a 25px es la voz del sistema. Los párrafos de Zajno son bloques compactos donde cada línea toca a la siguiente; abrir la interlínea a 1.5 lo convierte en cualquier otro sitio. La legibilidad se protege con párrafos cortos (3 a 5 líneas), no con aire entre líneas.
---
## 4. Estilos de Componentes
El DOM tiene pocos componentes y ninguno lleva fondo, borde, radio ni sombra: el sistema señala con color y responde con el canvas.
### Fila de proyecto (componente firma)
```
Estructura real (a.ho-wr-bo-a): número de orden ("01") + servicio
("Full-cycle product development") + premios ("Awwwards x 2, CSSDA x 4,
FWA x 1") + NOMBRE en rojo ("Acquire") + categoría ("Marketplace")
Font: 25px / line-height 25px / un peso
Color base: #1A1A1A; el nombre del proyecto: #FF3928
Sin subrayado, sin flecha, sin caja
Hover:
color 0.25s cubic-bezier(.215,.61,.355,1) (real: la transición
más repetida del sitio)
y la imagen del proyecto entra en el canvas WebGL con distorsión
líquida siguiendo al cursor
```
### Navegación
```
Header en tres columnas de texto: logo "zajno®" (h1 real de 13.33px),
"digital studio", bloque work/studio/contact, redes, "los angeles, ca"
Font: 13.33px / line-height 16.67px / caja baja
Color: #1A1A1A
Sin fondo: el header flota sobre el gris
Hover:
color 0.25s cubic-bezier(.215,.61,.355,1) hacia el rojo #FF3928
(derivado: el patrón del sitio es señalar con rojo lo activo)
```
### Botón (no hay botones con caja)
```
El único button real del DOM: "Send Request", texto de 25px en tinta,
sin fondo, sin borde, sin radio, padding 0.
El énfasis del CTA se consigue con posición (final de página, rodeado
de gris) y con el hover rojo + distorsión del canvas.
Focus: outline 2px solid #FF3928, offset 3px (derivado)
Disabled: opacity 0.4 (derivado)
```
### Placa de media
```
Background: #FFFFFF
Contenido: render 3D monocromo (despieces de producto, cámaras,
objetos flotando en capas) a sangre, sin marco ni sombra
Radio: 0
La placa blanca sobre el gris #EBEBEB ES el marco: 1 nivel de
luminancia de diferencia, sin borde dibujado
```
### Contador de premios
```
Texto plano dentro de la fila de proyecto: "Awwwards x 2", "CSSDA x 4",
"FWA x 1", "Product Hunt x 1"
Font: 25px, mismo cuerpo que todo
Color: #1A1A1A (o #B2B2B2 atenuado sobre la franja oscura)
Los premios son contenido, no badges: nada de pills ni iconos
```
### Franja inversa / footer
```
Background: #1A1A1A
Texto: #EBEBEB a 25px/1.0; metadatos a 13.33px
El rojo #FF3928 rinde aquí su mejor contraste (4.9:1): los enlaces
calientes del footer pueden ir en rojo a cualquier tamaño de los dos
```
### Overlay
```
Background: rgba(0,0,0,0.6) (real)
Sin blur: el velo es plano, el contenido de detrás se adivina
Cierre con la misma curva --o6 del sistema
```
### Formulario de contacto (derivado del CTA real)
```
El sitio expone el disparador "Send Request" (texto de 25px). Para
los campos del formulario (derivado para completar el sistema):
Input:
Background: transparent
Border: none; border-bottom: 1px solid rgba(26,26,26,0.16)
Font: 25px / line-height 25px / caja baja
Color: #1A1A1A · Placeholder: #B2B2B2 solo si el campo vive
sobre la franja oscura; sobre gris, placeholder en tinta al 40%
Focus: border-bottom-color #FF3928 (el rojo señala el campo vivo)
Error:
Mensaje en #FF3928 a 25px (nunca más pequeño sobre gris)
El campo mantiene la línea base roja
Regla: una línea base, no una caja. Un input con borde completo
y radio no existe en este sistema.
```
### Indicador de página / progreso
```
Puntos circulares (los 22 nodos con border-radius 100% del censo):
discos de 8px en tinta, el activo en rojo #FF3928.
Sin números, sin barras: el círculo es la única forma curva permitida.
Transición del activo: color 250ms var(--o3).
```
---
## 5. Principios de Layout
### Escala de espaciado
Sin tokens de espaciado en el `:root` (solo hay color y easings). La rejilla implícita se mide del layout: múltiplos de 25px, el mismo valor que el cuerpo/interlínea. El espaciado y la tipografía comparten unidad.
```css
--space-1: 5px;
--space-2: 10px;
--space-3: 25px; /* LA unidad: igual al cuerpo y a la interlínea */
--space-4: 50px;
--space-5: 100px;
--space-6: 200px; /* respiros entre bloques de contenido */
```
### Rejilla
```
Header real: columnas de texto repartidas a intervalos regulares sobre
el ancho completo (logo / claim / nav / redes / ciudad), un patrón de
5 columnas con margen exterior de ~25px.
El contenido usa 2 columnas asimétricas (texto | placa de media) o
ancho completo (wordmark, filas de proyecto).
--grid-margin: 25px (medido)
--grid-gap: 25px (medido, la misma unidad)
```
### Contenedores
```css
--container: 100vw; /* el wordmark y las placas van a sangre */
--container-text: 38ch; /* los párrafos de 25px se cortan estrechos (derivado) */
```
### Filosofía de espaciado
Todo es múltiplo de 25. El cuerpo mide 25, la interlínea mide 25, el margen mide 25, el gap mide 25: **la página entera late en la misma unidad**, y por eso puede permitirse interlínea 1.0 sin verse rota. La regla práctica: cuando dudes de un espacio, usa 25px o un múltiplo; cuando dudes de un tamaño de texto, no inventes uno.
---
## 6. Profundidad y Elevación
### Sistema de sombras
```css
/* Cero sombras CSS en 4000 nodos medidos. */
--shadow-none: none;
```
> La única "profundidad" del sitio son los renders (los despieces 3D llevan luz y oclusión propias, dentro de la imagen) y el velo `rgba(0,0,0,.6)` de los overlays. El DOM es plano: una placa blanca sobre gris es toda la elevación que existe.
### Niveles de elevación
| Nivel | Superficie | Sombra | Uso |
|-------|-----------|--------|-----|
| 0 - Canvas | `#EBEBEB` | ninguna | Fondo de trabajo |
| 1 - Placa | `#FFFFFF` | ninguna | Renders y visores de proyecto |
| 2 - Inversa | `#1A1A1A` | ninguna | Franja de contacto/footer |
| 3 - Velo | `rgba(0,0,0,.6)` | ninguna | Overlays y menús |
### Radios de borde
```css
--radius-none: 0; /* todo recto */
--radius-full: 100%; /* 22 ocurrencias: puntos e indicadores circulares */
```
> Igual que la tipografía: o recto o círculo. El punto sobre la `j` del wordmark es un círculo perfecto y esa es toda la curva que la marca necesita.
---
## 7. Lo que Sí y lo que No
### Sí hacer
1. **Reserva el rojo `#FF3928` para nombrar lo importante** (proyectos, hovers de CTA, errores). Un solo trabajo, siempre el mismo: así se mantiene quirúrgico.
2. **Usa dos tamaños y solo dos**: 25px/1.0 para el contenido, 13.33px para la operación. La jerarquía extra la dan el wordmark y el color.
3. **Mantén la interlínea 1.0 a 25px** y protege la legibilidad con párrafos cortos, no con aire.
4. **Escribe en caja baja**, incluidos títulos y navegación. La caja alta no existe en este sistema.
5. **Cuadra todo a múltiplos de 25px**: margen, gap, respiros. La unidad compartida es lo que hace que el brutalismo se vea intencional.
6. **Deja las imágenes como placas blancas a sangre sobre el gris**, sin marco, sin sombra, sin radio.
7. **Confía el drama al motion**: distorsión en el canvas, curvas easeOut largas (`--o6`), color en 0.25s. El DOM quieto, el shader vivo.
8. **Cuando necesites oscuro, invierte a `#1A1A1A` completo** y aprovecha que el rojo contrasta mejor ahí (4.9:1).
### No hacer
1. **No uses el rojo a menos de 24px sobre el gris**: 3.0:1 es el límite exacto. Rojo pequeño solo sobre negro.
2. **No introduzcas un segundo acento** ni estados semánticos de colores nuevos: verde o azul aquí son ruido.
3. **No abras la interlínea del cuerpo a 1.4-1.5.** El bloque compacto de 25/25 es la voz de la marca.
4. **No mezcles pesos.** La woff2 original trae uno; el sistema entero vive en un solo peso (Archivo 600 como sustituto).
5. **No pongas sombras, radios intermedios ni bordes decorativos.** Placa sobre gris, y ya.
6. **No uses `#B2B2B2` como texto sobre el gris** (1.8:1): solo sobre la franja negra o como señal decorativa.
7. **No conviertas los premios en badges con pills.** "Awwwards x 2" es texto corrido a 25px, como todo.
8. **No hagas el wordmark con una fuente.** Es lettering: si no puedes dibujarlo, usa el logo como imagen, no lo imites con un bold cualquiera.
---
## 8. Comportamiento Responsive
### Breakpoints
El sitio es un lienzo WebGL con capas HTML; los cambios de layout se resuelven por viewport:
```css
/* sm: */ @media (min-width: 640px) { }
/* md: */ @media (min-width: 768px) { }
/* lg: */ @media (min-width: 1024px) { }
```
### Cambios por breakpoint
**Mobile (< 768px)**
- El wordmark sigue a sangre pero pasa a ~50vw de alto de letra: sigue siendo el hero
- El cuerpo baja de 25px a ~18-20px manteniendo interlínea 1.0
- Las filas de proyecto se apilan: número, servicio, premios, nombre en rojo, categoría, en vertical
- El canvas reduce o elimina los shaders (rendimiento y touch)
**Tablet (768px a 1024px)**
- Dos columnas donde el desktop usa cinco en el header
- Placas de media a ancho completo
**Desktop (> 1024px)**
- Sistema completo: scroll virtual, shaders de distorsión, hover rojo con visor
- Header de cinco columnas de texto, wordmark a ~34vw
### Touch targets (mobile)
- Filas de proyecto: los 25px con interlínea 1.0 dan cajas justas; en móvil el área de tap debe crecer a 44px con padding *(derivado)*
- Navegación de 13.33px: padding vertical mínimo de 12px para llegar a 44px
### Filosofía responsive
El desktop es el hábitat (los shaders siguen al cursor, que en touch no existe). En móvil, Zajno conserva **la composición tipográfica** (wordmark gigante, bloques compactos, rojo quirúrgico) y sacrifica el motion antes que el layout. La marca sobrevive sin shaders; no sobrevive sin su tipografía a interlínea 1.0.
---
## 9. Guía de Prompts para Agentes
### Prompt de inicialización de sesión
```text
Estás trabajando con el sistema de diseño de Zajno (estudio digital).
PALETA: gris hormigón #EBEBEB de fondo, tinta #1A1A1A (--color-dark),
UN solo saturado: rojo #FF3928 (--color-red), reservado a nombres de
proyecto, hovers importantes y errores. Placas de media en #FFFFFF.
Franja inversa #1A1A1A con texto #EBEBEB. Overlay rgba(0,0,0,.6).
Muted #B2B2B2 SOLO sobre oscuro.
TIPOGRAFÍA: una grotesca bold (Archivo 600, sustituta de la woff2
propietaria anónima del sitio), un solo peso, DOS tamaños: 25px con
line-height 25px (todo el contenido) y 13.33px (navegación y metadatos).
Todo en caja baja. Sin tracking.
ESTILO: cero sombras, cero radios salvo círculos, cero cajas con borde.
Unidad universal de 25px para espaciados. El drama va en el motion:
color 0.25s cubic-bezier(.215,.61,.355,1), transform 0.6s
cubic-bezier(.19,1,.22,1), reveals largos con cubic-bezier(.16,1,.3,1).
MODO: claro.
```
### Prompt: Crear nueva pantalla
```text
Crea una pantalla de [FUNCIONALIDAD] para Zajno.
Requisitos:
- Fondo #EBEBEB, tinta #1A1A1A, rojo #FF3928 solo en lo que importa
- Texto de contenido a 25px con line-height 25px, caja baja, un peso
- Navegación y metadatos a 13.33px
- Espaciados en múltiplos de 25px
- Media como placas blancas a sangre, sin marco ni sombra ni radio
- Máximo una franja inversa #1A1A1A por vista
- El rojo nunca a menos de 24px sobre el gris
- CTAs como texto (sin caja); el énfasis lo dan posición y hover rojo
```
### Prompt: Añadir componente al UI kit
```text
Añade un componente de [TIPO] al sistema de Zajno.
Debe:
- Usar solo tokens del DESIGN.md de Zajno
- Vivir en los dos tamaños del sistema (25px/1.0 o 13.33px)
- Señalar interacción con color (tinta -> rojo, 0.25s
cubic-bezier(.215,.61,.355,1)), nunca con sombra ni con caja
- Tener default, hover, focus (outline 2px rojo) y disabled (opacidad .4)
- Cuadrar todos sus espaciados a múltiplos de 25px
```
### Prompt: Revisión de consistencia
```text
Revisa esta interfaz y detecta qué no sigue el sistema de Zajno.
Verifica:
1. Si hay más de dos tamaños de texto (25 y 13.33 son los únicos)
2. Si la interlínea del cuerpo es 1.0 exacta
3. Si aparece caja alta donde debería haber caja baja
4. Si el rojo #FF3928 aparece a menos de 24px sobre el gris
5. Si hay algún color fuera de #EBEBEB/#FFFFFF/#1A1A1A/#FF3928/#B2B2B2
6. Si hay sombras, radios intermedios o bordes decorativos
7. Si los espaciados cuadran a múltiplos de 25px
8. Si hay más de un peso tipográfico
```
### Prompt: Variante de campaña
```text
Genera una variante [proyecto / servicio / campaña] para Zajno
manteniendo el sistema base.
Conserva:
- El monocromo gris/tinta con el rojo quirúrgico
- Los dos tamaños (25/13.33), el peso único y la caja baja
- La unidad de 25px y las placas blancas a sangre
Puedes variar:
- El objeto del render 3D (despiece, producto, abstracción)
- La proporción del wordmark en el hero (34vw a 50vw)
- La cantidad de filas de proyecto (3 a 8)
```
---
## 10. Movimiento (Motion)
El motion de Zajno está tokenizado en el `:root` real, cosa rarísima y reveladora: el estudio versiona sus curvas como otros versionan sus colores. Y el escenario es un canvas WebGL de scroll virtual (el documento mide un viewport exacto) donde las imágenes viven dentro de shaders.
**Nivel de motion**: alto y de firma; los shaders de distorsión son el motivo por el que Zajno está en esta galería
**Tokens de easing reales del `:root`:**
```css
--o3: cubic-bezier(0.215, 0.61, 0.355, 1); /* easeOutCubic: micro-interacciones */
--o6: cubic-bezier(0.19, 1, 0.22, 1); /* easeOutExpo: transforms de entrada */
--io6: cubic-bezier(0.16, 1, 0.3, 1); /* easeOutQuint suave: reveals largos */
```
**Duraciones** (medidas de los estilos computados):
- 250ms con `--o3`: color y opacity+transform de enlaces y navegación (la receta dominante: 23 nodos)
- 300ms `ease`: fundidos simples
- 600ms con `--o6`: transform de entrada de bloques (el "golpe suave" easeOutExpo)
- 1000ms `ease`: transforms largos de layout
- 1800ms con `--io6`: el gran reveal de opacidad al cargar (keyframe real: `fade`)
- scroll-linked: la distorsión del canvas no tiene duración, sigue a la velocidad del scroll
**Propiedades animadas en el DOM**: `color`, `opacity`, `transform`. Lo demás (olas, líquido, desplazamiento RGB) ocurre en el shader.
**Patrones de motion**:
- **Distorsión líquida scroll-linked**: las imágenes dentro del canvas se doblan proporcionalmente a la velocidad del scroll y se asientan con inercia al frenar; la intensidad del shader es función de la velocidad, no del tiempo
- **Hover con visor**: al pasar por una fila de proyecto, el nombre vira a rojo en 250ms `--o3` y la imagen del proyecto emerge en el canvas siguiendo al cursor con lag elástico
- **Entrada easeOutExpo**: los bloques entran con `transform` 600ms `--o6`: rápido al arrancar, frenada larguísima
- **Fade de carga**: keyframe `fade` con 1800ms `--io6` para el primer render de la página
- **Scroll virtual con inercia**: la rueda alimenta un progreso perseguido con lerp; el documento jamás se desplaza
> **Accesibilidad**: con `prefers-reduced-motion: reduce`, los shaders se congelan (imagen plana), el scroll virtual cede a scroll nativo, y quedan solo los cambios de color de 250ms. El patrón hover-visor debe tener equivalente por foco de teclado: nombre en rojo + imagen estática visible.
### Recetas de motion listas para copiar
**Los tokens (cópialos tal cual: son los reales del sitio):**
```css
:root {
--o3: cubic-bezier(0.215, 0.61, 0.355, 1); /* micro · 250ms */
--o6: cubic-bezier(0.19, 1, 0.22, 1); /* entradas · 600ms */
--io6: cubic-bezier(0.16, 1, 0.3, 1); /* reveals · 1800ms */
}
```
**El hover de proyecto (color en --o3):**
```css
.project-name {
color: #1A1A1A;
transition: color 250ms var(--o3);
}
.project-row:hover .project-name,
.project-row:focus-within .project-name { color: #FF3928; }
```
**La entrada easeOutExpo (el golpe suave):**
```css
.block-enter {
transform: translateY(40px);
opacity: 0;
transition: transform 600ms var(--o6), opacity 600ms var(--o6);
}
.block-enter.in { transform: none; opacity: 1; }
```
**El fade de carga (keyframe real del sitio):**
```css
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.page-load { animation: fade 1800ms var(--io6) both; }
```
**El visor que persigue al cursor (esqueleto del patrón WebGL):**
```js
// en el sitio real la imagen vive en el shader; el patrón es el mismo
let tx = 0, ty = 0, vx = 0, vy = 0;
list.addEventListener('pointermove', (e) => { tx = e.clientX; ty = e.clientY; });
(function tick() {
vx += (tx - vx) * 0.14; // lag elástico: el lerp es el easing
vy += (ty - vy) * 0.14;
viewer.style.transform = `translate(${vx}px, ${vy}px)`;
requestAnimationFrame(tick);
})();
// la distorsión: uniform u_strength = f(velocidad de scroll),
// decae con inercia al frenar
```
---
## Anexo: Stack técnico detectado
- **Plataforma**: lienzo WebGL a viewport completo (canvas único de 1600x900 en la medición) con capas HTML encima; scroll virtual (`scrollHeight` del documento = altura del viewport). Los visores de proyecto y las distorsiones viven en el shader, no en el DOM.
- **Sistema de tokens**: el `:root` real declara exactamente **5 variables: 2 de color y 3 de easing** (`--color-dark`, `--color-red`, `--o3`, `--o6`, `--io6`). Ni espaciado ni tipografía tokenizados. Un estudio que tokeniza sus curvas de animación antes que su escala de grises dice mucho de sus prioridades.
- **Tipografía**: un solo `@font-face`: familia `s`, archivo `/static/font/sh.woff2`, peso declarado 400 (render visual semibold). Nombre ofuscado deliberadamente. Dos tamaños computados en todo el DOM: 25px/25px y 13.3328px/16.6672px.
- **Colores computados** (censo de 4000 nodos): `rgb(235,235,235)` fondo (3.0M), `rgb(255,255,255)` placas (2.0M), `rgb(0,0,0)` y `rgba(0,0,0,.6)` overlays, `rgb(26,26,26)` texto, `rgb(255,57,40)` acento (2.1K: quirúrgico), `rgb(178,178,178)` muted residual.
- **Radios**: una sola entrada: `100%` (22 nodos). **Sombras**: ninguna.
- **Animación CSS**: keyframe real `fade`; transiciones dominantes `0.25s cubic-bezier(.215,.61,.355,1)` (color, opacity+transform), `0.6s cubic-bezier(.19,1,.22,1)` (transform), `1.8s cubic-bezier(.16,1,.3,1)` (opacity).
- **Proyectos del índice real**: Acquire (Marketplace), Evergreen (Biotech), 8Finance (Crypto), Gentlerain.ai (Educational), Brightmark, con contadores de premios como contenido: Awwwards, CSSDA, FWA, Product Hunt, Dribbble Select.
- **SEO del title real**: "Zajno Digital Studio | Web Design, Branding, 3D, Animation & Webflow Development Services".
- **(no detectado)**: librería de motion pública (GSAP/three.js/curtains.js quedan como hipótesis del bundle), variables de espaciado, media queries de sistema, modo oscuro, tipografía mono.