extraído de zajno.com ver sitio ↗

zajno®

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.

light mode red 5 variables en el :root 2 tamaños de texto 1 peso caja baja unidad 25px shaders de distorsión
↓ scroll
zajno.com
Captura del hero de Zajno: wordmark zajno gigante en negro sobre gris con el despiece 3D de una cámara debajo
el wordmarkLettering propio a lo ancho del viewport entero (~34vw de letra), negro pleno sobre gris hormigón. El hero no tiene claim: tiene masa.
la placaRender 3D monocromo (el despiece de una cámara en capas) sobre placa blanca #FFFFFF a sangre: sin marco, sin sombra, sin radio.
la operaciónHeader de cinco columnas de texto a 13.33px en caja baja: zajno® / digital studio / work studio contact / twitter instagram / los angeles, ca.
01

Color

light · 5 valores · 1 rojo quirúrgico
tokens reales del :root
#FF3928
rojo zajno · --color-red
un solo trabajo: nombrar proyectos, hover de lo importante, error
sobre gris: 3.0:1 (solo 24px o más) · sobre tinta: 4.9:1 AA
#1A1A1A
tinta · --color-dark
todo el texto, el wordmark y la franja inversa
sobre gris: 14.6:1 AAA · sobre blanco: 17.4:1 AAA
#EBEBEB
gris hormigón
fondo de trabajo de todo el sitio (score 3.0M: la mayor superficie)
tinta encima: 14.6:1 AAA
#FFFFFF
placa blanca
placas de los renders 3D y visores de proyecto (score 2.0M)
un nivel de luminancia sobre el gris: la placa ES el marco
#B2B2B2
muted
metadatos atenuados; solo rinde sobre la franja oscura
1.8:1 sobre gris: nunca texto · 8.2:1 sobre tinta: AAA
rgba(0,0,0,.6)
velo
overlay real de menús y modales, plano y sin blur
superficie de transición, no de texto
el :root completo del sitio real (5 variables)
: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.

la trampa del rojo
acquire
rojo sobre gris: 3.0:1 exacto
el sitio lo usa a 25px (texto grande, AA justo). nunca por debajo de 24px aquí
3.0:1 · el límite exacto de AA para texto grande
acquire
rojo sobre tinta: 4.9:1
el rojo rinde mejor sobre negro: aquí puede bajar a texto normal (AA)
4.9:1 AA texto normal · blanco sobre rojo: 3.6:1 solo grande
02

Typography

1 woff2 · 1 peso · 2 tamaños
zajno grotesk.
archivo 600 Original: grotesca anónima ("s" / sh.woff2) -> HTML: Archivo (Google substitute)
600 · 25px / lh 25px · contenidowe don't do boring websites
600 · 25px / lh 25px · proyectogentlerain.ai
600 · 13.33px / lh 16.67px · navwork   studio   contact   los angeles, ca
700 · lettering · wordmarkzajno®
body · 25px / 600 / lh 1.0 exacta

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.

rolsize realweightlhcaja
wordmark~34vwlettering1.0baja
contenido (h2, h3, p, a, button)25px600 equiv.1.0 (25px)baja
nav / h1-logo / metadatos13.33px600 equiv.1.25 (16.67px)baja
tamaños en todo el DOM: 2 (25 y 13.33)
pesos en la woff2: 1
caja alta encontrada: cero
la fuente llega ofuscada: familia "s", archivo sh.woff2
Original: grotesca propietaria anónima ("s" / sh.woff2, un solo peso) -> HTML: Archivo 600 (Google substitute). La fuente del sitio llega con el nombre ofuscado a propósito; por dibujo (terminaciones horizontales, a de doble piso, contrapunzones compactos, caja baja protagonista) es una neo-grotesca del linaje Helvetica Now Display / Neue Haas Grotesk en corte bold. Se compararon Inter (altura de x mayor, aire de sistema operativo: a 25px/1.0 se ve interfaz, no manifiesto), Roboto (esqueleto geométrico-mecánico) y Work Sans (terminales humanistas que el original no tiene). Archivo 600 gana porque es densa, de aperturas moderadas, muy sólida en caja baja a 25px y aguanta interlínea 1.0 sin que las ascendentes choquen. El original declara peso 400 pero renderiza como semibold: se mapea a 600 y se documenta la diferencia. Mono: no detectada en el sitio.
03

Components

texto, placas y un rojo
fila de proyecto (componente firma · pasa el cursor)
01 acquire product hunt x 1 · awwwards x 2 · css x 4 marketplace
02 evergreen awwwards x 1 · cssda x 4 · dribbble select x 1 biotech
03 8finance awwwards x 1 · cssda x 4 crypto
04 gentlerain.ai awwwards x 2 · cssda x 3 · fwa x 1 educational

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.

navegación (13.33px · cinco columnas de texto)

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.

placa de media (blanco sobre gris, sin marco)
render 3d monocromo a sangre

La placa blanca sobre el gris #EBEBEB ES el marco: un nivel de luminancia de diferencia, sin borde dibujado, sin sombra, sin radio.

cta (el único button del DOM real no tiene caja)

"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).

franja inversa · #1A1A1A

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.

© zajno digital studiotwitterinstagramdribbblelos angeles, ca

La franja inversa es el único cambio de superficie: sin bordes ni divisores, el negro ES el divisor.

04

Spacing & shape

todo múltiplo de 25
escala de espaciado (medida del layout; el :root no la declara)
5px
10px
25px · LA unidad: cuerpo = interlínea = margen = gap
50px
100px
200px · respiros entre bloques
header: 5 columnas de texto a intervalos regulares
contenido: 2 columnas asimétricas o ancho completo
margen exterior: 25px · gap: 25px
el wordmark y las placas van a sangre
familia de radios (completa)
0 · todo recto
100% · círculos (22 nodos)
elevación
sombras css en 4000 nodos: cero
elevación: placa blanca sobre gris (1 nivel)
overlay: rgba(0,0,0,.6) plano, sin blur

la única curva de la marca es el punto
sobre la j del wordmark: un círculo perfecto.
05

Principles

guardrails

    do

  • Reserva el rojo #FF3928 para nombrar lo importante: proyectos, hovers de CTA, errores. Un solo trabajo, siempre el mismo.
  • Usa dos tamaños y solo dos: 25px/1.0 para el contenido, 13.33px para la operación.
  • Mantén la interlínea 1.0 a 25px y protege la legibilidad con párrafos cortos, no con aire.
  • Escribe en caja baja, incluidos títulos y navegación.
  • Cuadra todo a múltiplos de 25px: la unidad compartida hace que el brutalismo se vea intencional.
  • Deja las imágenes como placas blancas a sangre sobre el gris, sin marco ni sombra ni radio.
  • Confía el drama al motion: color en 250ms --o3, transform en 600ms --o6, reveals largos con --io6.
  • Cuando necesites oscuro, invierte a #1A1A1A completo: el rojo contrasta mejor ahí (4.9:1).

    don't

  • 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.
  • No introduzcas un segundo acento ni semánticos verdes o azules: aquí son ruido.
  • No abras la interlínea del cuerpo a 1.4-1.5: el bloque compacto de 25/25 es la voz de la marca.
  • No mezcles pesos: la woff2 original trae uno y el sistema entero vive en él.
  • No pongas sombras, radios intermedios ni bordes decorativos. Placa sobre gris, y ya.
  • No uses #B2B2B2 como texto sobre el gris (1.8:1): solo sobre la franja negra.
  • No conviertas los premios en badges con pills: "awwwards x 2" es texto corrido a 25px, como todo.
  • No imites el wordmark con un bold cualquiera: es lettering; si no puedes dibujarlo, úsalo como imagen.
06

Motion & interaction

las curvas viven en el :root

easings tokenizados

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.

--o3: cubic-bezier(.215,.61,.355,1)
--o6: cubic-bezier(.19,1,.22,1)
--io6: cubic-bezier(.16,1,.3,1)

distorsión líquida scroll-linked

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.

intensidad = f(velocidad de scroll)
asentamiento: inercia con lerp

hover con visor

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.

color: 250ms var(--o3) (la receta dominante)
visor: persigue al cursor con lerp

entradas easeOutExpo

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.

transform: 600ms var(--o6) · fade: 1800ms var(--io6)
scroll: virtual, documento de 100vh

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.

07

Resources

copy & paste
: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.