extraído de bruno-simon.com Ver sitio ↗

Bruno Simon

El portfolio que no se lee: se conduce. Un camión 4x4 sobre un suelo violeta cuadriculado con cruces de neón, un aro de luz que dice por dónde empezar y un rótulo escrito a mano: CLICK TO START.

Fue Site of the Year en Awwwards y sigue siendo el ejemplo canónico de "portfolio como videojuego". La regla de color del mundo es simple: violeta #553DFF para el espacio (neón, árboles, rejilla), ámbar #FFA201 para la vida (farolas, luces del camión). La versión actual renderiza con WebGPU y lo presume con una insignia lima en el HUD. Todo tiene física: chocar es la micro-interacción principal.

dark mode noche arcade física real WebGPU + fallback 3 familias (2 de Google) rótulos a 64px glow, no sombra
Scroll to drive
bruno-simon.com
Captura del portfolio de Bruno Simon: camión bajo una farola ámbar, aro de neón blanco y rótulo CLICK TO START sobre suelo violeta
El aroUn tubo de neón con núcleo blanco caliente #FFFCFF y halo violeta #553DFF marca la zona de inicio. El suelo dentro se ilumina a #6C4EB2.
La farolaEl único calor del mundo: cono ámbar #FFA201 que satura a #FFFF91 en el foco. Violeta para el espacio, ámbar para la vida.
El rótuloCLICK TO START con flecha dibujada a mano, en el mundo, no en un overlay. Las instrucciones son parte del decorado.
01

Color

dark · violeta espacio · ámbar vida
El mundo (muestreado de la captura: render Three.js, no CSS)
#1E0B43
Suelo violeta
el terreno del mundo entero: dominante del frame (23.9%)
blanco encima: 17.7:1 AAA
#553DFF
Violeta neón
el neón del espacio: aro, árboles #5C3CFF, halo de rejilla
3.0:1 sobre suelo: solo display/tubo, nunca texto pequeño
#4129EA
Cruz de rejilla
las marcas × del suelo que se pierden en perspectiva
textura del terreno, no señal de UI
#FFFCFF
Neón blanco
el núcleo del tubo del aro de inicio: blanco caliente con bloom
es luz, no texto: marca zonas de acción
#4118B4
Magenta esquina
el viñeteo de las esquinas del frame: la escena iluminada como recreativa
atmósfera de encuadre, nunca superficie de trabajo
#6D54D3
Violeta árbol
las copas de partículas #5C3CFF y sus luces: la vegetación es neón
3.6:1 sobre suelo: solo texto grande o decorativo
El calor (los focos de vida)
#FFA201
Ámbar farola
el cono de la farola y la atención: el único calor del mundo
sobre suelo: 8.8:1 AAA · suelo encima: 8.8:1 AAA
#FFFF91
Foco
el pico del cono de luz y las luces del camión #FFFB94
sobre suelo: 16.2:1 AAA
La UI (medida en el DOM real)
#FFFFFF
Blanco
todo el texto del sitio; metadata al 80% (rgba(255,255,255,0.8) real)
sobre suelo: 17.7:1 AAA
#FF6A7C
Rosa peligro
"Offline" del HUD (real: rgb(255,106,124)); el aviso largo usa #FF87A2
sobre suelo: 6.4:1 AA · #FF87A2: 8.1:1 AAA
#D5FF95
Lima WebGPU
la insignia del motor en el HUD (real: rgb(213,255,149)): éxito y capacidad
sobre suelo: 15.7:1 AAA
#2A1155
Superficie
paneles sobre el mundo: el suelo iluminado un paso (derivado)
blanco encima: 15.4:1 AAA
El encuadre completo

Nada de esto existe en CSS: el :root del sitio tiene cero variables y el body es transparente porque la escena Three.js pinta el color. Estas paradas están muestreadas píxel a píxel de la captura 1600x900. La trampa del neón: el violeta #553DFF brilla muchísimo pero solo rinde 3:1 sobre el suelo; en el sitio real nunca es texto, es tubo, árbol y rejilla.

02

Typography

3 familias · 2 directas de Google
Aa Gg 44!
Amatic SC + Nunito Amatic SC y Nunito: Google Fonts directas · Original: Pally (Fontshare, HUD) -> HTML: Fredoka (Google substitute)
Amatic SC 700 · rótuloInteract / Unstuck
Nunito 400 · conversaciónPlease drive around to learn more about me.
Nunito 700 · label 13pxMouse Keyboard · Mobile Tablet
Fredoka 500 · HUD (Pally)High · WebGPU · Resets in 04:12
Las tres voces

Amatic SC rotula, Nunito conversa, Pally instrumenta. Los "botones" del mundo (Interact, Unstuck) son rótulos manuscritos de 64px sin caja ni fondo; los mensajes de visitantes van a 50px y los títulos de panel a 40px. Nunito hace todo lo demás a 20px redondos y amables (es el font-size del body entero). La diferencia entre rotular y conversar es la firma tipográfica del sitio.

Sin tracking y sin line-height forzado: todo va con letter-spacing normal (medido) y la métrica nativa de cada familia. La personalidad la ponen los esqueletos.

RolSize realWeightFamiliaUso
letrero64px700Amatic SCInteract / Unstuck
whisper50px700Amatic SCmensajes de visitantes
title40px700Amatic SCpaneles (Devlogs...)
body20px400Nunitoconversación
body sm16px400Nunitonotas al 80%
label13px700Nunitochips del HUD
hud20px500Pallypiezas con voz propia
Amatic SC y Nunito son Google Fonts y se usan directas, sin sustitución (caso poco común en esta galería: dos de las tres fuentes reales del sitio son libres). Original: Pally -> HTML: Fredoka (Google substitute). Pally (Indian Type Foundry, Fontshare) es una geométrica redonda y regordeta con terminales blandos, cargada en Regular/Medium/Bold para el HUD. Se compararon tres candidatas más: Baloo 2 (más pesada de color: a 13px empasta contra el neón), Quicksand (demasiado esbelta: pierde el juguete) y Comfortaa (tan protagonista que compite con Amatic SC). Fredoka gana porque comparte la jovialidad regordeta, cubre 400/500/700 y a tamaños de HUD es casi intercambiable. Regla dura: Amatic SC nunca baja de 40px; a tamaños de párrafo la manuscrita condensada se rompe.
03

Components

letreros, aros y HUD

Botón-letrero (componente firma): los controles del mundo no tienen caja. Amatic SC 700 a 64px, transparente, borde cero y radio cero (todo medido del DOM real). Son letreros pintados que flotan sobre la escena; el hover les da rebote. Si un control vive dentro del mundo, no lleva superficie: las cajas son para paneles que pausan el juego. Unstuck existe porque volcar el camión es parte del juego.

Aro de inicio: la zona de acción no es un botón flotante, es un tubo de neón en el suelo. Núcleo #FFFCFF de 2-3px, halo #553DFF, el interior iluminado a #6C4EB2 y bloom real en la escena. El rótulo de instrucción se dibuja a mano junto al aro, en el mundo, no en un tooltip.

Quality High WebGPU Offline Mouse Keyboard Gamepad

Insignias del HUD (reales): el estado técnico se muestra con orgullo y color caramelo. "High" al 80% de blanco, "WebGPU" en lima #D5FF95 (la insignia del motor es parte de la marca), "Offline" en rosa #FF6A7C. Los chips de input (Mouse Keyboard, Mobile Tablet, gamepad con iconos Xbox reales en el DOM) usan Nunito 700 a 13px; el icono de mando lleva radio 15px medido.

Whispers

Whispers are messages left by visitors.

- Everyone can see them · - They stay painted on the floor

Your message here

Panel de contenido: cuando algo interrumpe el juego (whispers, menú, leaderboard) sí hay superficie: violeta profundo al 92%, radio 12px, título Amatic 40px, body Nunito 20px, notas a 16px al 80% y un divisor de 1px blanco (el div.line real). El input de whispers escribe en Amatic a 50px y el mensaje queda pintado en el suelo del mundo. El HUD real también avisa en rosa: "Server currently offline. Scores can't be saved." y "Resets in..." para el reinicio de récords.

04

Motion

la física es el contenido

Conducción física

Chasis + 4 ruedas con suspensión, derrape y vuelco. La simulación no usa duraciones: usa masas, fuerzas y amortiguación. La cámara cenital sigue al camión con lag suave (lerp) para que el mundo gire alrededor. Volcar no es un error: es la razón de que exista el botón Unstuck.

cámara: lag con lerp · sin duración: simulación continua

WebGPU con fallback

La versión actual renderiza con WebGPU cuando el navegador puede y cae a WebGL cuando no. El HUD lo presume con la insignia lima y expone el ajuste de calidad (High). El estado técnico es celebración, no letra pequeña.

insignias reales del DOM: "High" · "WebGPU" #D5FF95

Objetos rompibles

Bolos, vallas y letras del suelo tienen cuerpo físico: chocar es la micro-interacción principal. La instrucción real del intro lo dice: "And don't break anything!". Cada adorno del mundo es jugable o no existe.

decorado = objetos con física · el error es divertido

Neón como señal

Las zonas de acción laten con bloom: el aro de inicio es un tubo de luz (núcleo #FFFCFF, halo #553DFF), no un borde CSS. El suelo dentro del aro se ilumina. Lo que importa emite luz; lo que descansa la recibe.

pulso: ~1600ms ease-in-out · glow: bloom del render

Multi-input

Teclado, touch (joystick + botones táctiles reales, js-touch-buttons) y gamepad con iconos Xbox en el DOM. El sitio detecta el esquema de entrada y muestra chips explicativos. El clic inicial del CLICK TO START también desbloquea el audio: motor, colisiones y bocina ligados a la simulación.

chips reales: Mouse Keyboard · Mobile Tablet · icon.is-xbox

Mundo social

Los whispers son mensajes de visitantes pintados en el suelo (Amatic 50px) que se atraviesan conduciendo; el leaderboard cronometra vueltas con reset programado ("Resets in") y avisa en rosa si el servidor está caído. Lo social vive en el mundo, no en un muro de comentarios.

entrada de letreros: rebote ~350ms cubic-bezier(.34,1.56,.64,1)

Accesibilidad: con prefers-reduced-motion, la cámara sigue rígida (sin lag), el neón no late (brillo fijo) y los letreros entran por opacidad. Los paneles de contenido (Three.js, Three.js Journey, Devlogs, Source code, Musics: títulos H2 reales del DOM) ofrecen el portfolio en HTML navegable, con lo que el CV es legible sin conducir.

05

Spacing & shape

un mundo con HUD
El layout es un encuadre, no una página
margen del HUD a los bordes: 40px
el HUD nunca invade el tercio central:
ahí vive el camión y la interfaz
respeta el juego.
Familia de radios
0 · letrero
12px panel
15px chip (real)
100% aro
Escala de espaciado (derivada, base 4)
4px · base
8px
12px
16px
24px
40px · anclaje del HUD
elevación: sin box-shadow (medido: none en todo el DOM)
glow neón: 0 0 8px #FFFCFF, 0 0 24px #553DFF
glow ámbar: 0 0 16px #FFA201

lo que importa emite luz;
lo que descansa la recibe.
06

Principles

guardrails

    Do

  • Violeta para el espacio, ámbar para la vida. El mundo entero es frío #1E0B43/#553DFF; el calor #FFA201 se reserva para faros, farolas y focos de atención.
  • Rotula en Amatic SC 700 y nunca por debajo de 40px: los títulos de este sistema son letreros de mano gigantes.
  • Explica en Nunito 400 a 20px, amable y sin tracking. La diferencia entre rotular y conversar es la firma tipográfica.
  • Haz que la elevación brille: neón blanco con halo violeta para zonas de acción, glow ámbar para lo vivo.
  • Deja los controles del mundo sin caja (letreros transparentes); reserva las superficies para paneles que pausan el juego.
  • Muestra el estado técnico con orgullo y color caramelo: WebGPU en lima #D5FF95, offline en rosa #FF6A7C.
  • Da cuerpo físico a la decoración: si algo está en el mundo, se puede chocar. La interactividad es la ornamentación.

    Don't

  • No uses el violeta neón #553DFF como texto pequeño: rinde 3:1 sobre el suelo; es tubo y rejilla, no tipografía.
  • No pongas Amatic SC en párrafos: por debajo de 40px la manuscrita condensada se rompe.
  • No enfríes el ámbar: las farolas son #FFA201 puro; un amarillo pastel apaga los focos de vida.
  • No uses sombras negras CSS: la profundidad aquí es luz (bloom, halos, conos); una box-shadow gris rompe la noche arcade.
  • No conviertas los letreros en botones con caja: Interact a 64px transparente es la voz del mundo.
  • No añadas tracking ni caps forzadas: todo el sistema va con letter-spacing normal.
  • No pongas verde natural en la vegetación: los árboles de este mundo son violeta #5C3CFF; el color es de neón, no de bosque.
07

Resources

copy & paste
:root {
  --color-primary: #553DFF;        /* violeta neon: espacio, tubo, arboles */
  --color-secondary: #FFA201;      /* ambar: farolas, focos de vida */
  --color-background: #1E0B43;     /* el suelo del mundo (muestreado) */
  --color-background-deep: #1D063B;
  --color-surface: #2A1155;        /* paneles (derivado) */
  --color-neon-core: #FFFCFF;      /* nucleo del tubo de neon */
  --color-grid-cross: #4129EA;     /* las marcas x del suelo */
  --color-tree: #6D54D3;           /* vegetacion neon */
  --color-floor-glow: #6C4EB2;     /* suelo dentro del aro */
  --color-magenta: #4118B4;        /* vinieteo de esquinas */
  --color-lamp-bright: #FFFF91;    /* pico del cono de la farola */
  --color-text-primary: #FFFFFF;
  --color-text-faded: rgba(255, 255, 255, 0.8);
  --color-danger: #FF6A7C;         /* real: "Offline" del HUD */
  --color-danger-soft: #FF87A2;    /* real: aviso de servidor */
  --color-success: #D5FF95;        /* real: insignia WebGPU */
  --color-warning: #FFA201;
  --color-info: #6D54D3;

  --font-display: "Amatic SC", cursive;       /* Google, directa */
  --font-body: "Nunito", sans-serif;          /* Google, directa */
  --font-hud: "Fredoka", "Pally", sans-serif; /* sustituta de Pally */

  --radius-chip: 15px;    /* real: icono de gamepad del HUD */
  --radius-panel: 12px;   /* derivado */
  --radius-letrero: 0;    /* real: los botones del mundo no tienen caja */
  --radius-ring: 100%;

  --shadow-none: none;    /* el DOM real no usa box-shadow */
  --glow-neon: 0 0 8px #FFFCFF, 0 0 24px #553DFF, 0 0 64px rgba(65, 41, 234, 0.5);
  --glow-amber: 0 0 16px #FFA201, 0 0 48px rgba(255, 162, 1, 0.4);

  --space-base: 4px;
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-edge: 40px;

  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-follow: cubic-bezier(0.25, 0.1, 0.25, 1);
  --duration-pop: 350ms;
  --duration-panel: 450ms;
  --duration-pulse: 1600ms;
}
@theme {
  --color-primary: #553DFF;
  --color-secondary: #FFA201;
  --color-background: #1E0B43;
  --color-background-deep: #1D063B;
  --color-surface: #2A1155;
  --color-neon-core: #FFFCFF;
  --color-grid-cross: #4129EA;
  --color-tree: #6D54D3;
  --color-floor-glow: #6C4EB2;
  --color-magenta: #4118B4;
  --color-lamp-bright: #FFFF91;
  --color-text-primary: #FFFFFF;
  --color-danger: #FF6A7C;
  --color-danger-soft: #FF87A2;
  --color-success: #D5FF95;
  --color-warning: #FFA201;
  --color-info: #6D54D3;

  --font-display: "Amatic SC", cursive;
  --font-body: "Nunito", sans-serif;
  --font-hud: "Fredoka", "Pally", sans-serif;

  --radius-chip: 15px;
  --radius-panel: 12px;

  --shadow-glow-neon: 0 0 8px #FFFCFF, 0 0 24px #553DFF, 0 0 64px rgba(65, 41, 234, 0.5);
  --shadow-glow-amber: 0 0 16px #FFA201, 0 0 48px rgba(255, 162, 1, 0.4);

  --spacing-base: 4px;
  --spacing-xs: 8px;
  --spacing-sm: 12px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-edge: 40px;
}
{
  "colors": {
    "primary": "#553DFF",
    "secondary": "#FFA201",
    "background": "#1E0B43",
    "background-deep": "#1D063B",
    "surface": "#2A1155",
    "neon-core": "#FFFCFF",
    "grid-cross": "#4129EA",
    "tree": "#6D54D3",
    "floor-glow": "#6C4EB2",
    "magenta": "#4118B4",
    "lamp-bright": "#FFFF91",
    "truck-light": "#FFFB94",
    "text-primary": "#FFFFFF",
    "text-faded": "rgba(255, 255, 255, 0.8)",
    "danger": "#FF6A7C",
    "danger-soft": "#FF87A2",
    "success": "#D5FF95",
    "warning": "#FFA201",
    "info": "#6D54D3"
  },
  "typography": {
    "display-hand": {
      "fontFamily": "Amatic SC",
      "fontSize": "64px",
      "fontWeight": 700,
      "note": "botones-letrero del mundo: Interact / Unstuck (real)"
    },
    "whisper": {
      "fontFamily": "Amatic SC",
      "fontSize": "50px",
      "fontWeight": 700,
      "note": "mensajes de visitantes (real)"
    },
    "title": {
      "fontFamily": "Amatic SC",
      "fontSize": "40px",
      "fontWeight": 700,
      "note": "titulos de panel (real); minimo absoluto de la familia"
    },
    "body": {
      "fontFamily": "Nunito",
      "fontSize": "20px",
      "fontWeight": 400,
      "note": "el font-size del body entero (real)"
    },
    "body-sm": {
      "fontFamily": "Nunito",
      "fontSize": "16px",
      "fontWeight": 400
    },
    "label": {
      "fontFamily": "Nunito",
      "fontSize": "13px",
      "fontWeight": 700,
      "note": "chips del HUD (real)"
    },
    "hud": {
      "fontFamily": "Pally",
      "substitute": "Fredoka",
      "fontSize": "20px",
      "fontWeight": 500
    }
  },
  "rounded": {
    "chip": "15px",
    "panel": "12px",
    "letrero": "0",
    "ring": "100%"
  },
  "shadow": {
    "none": "none",
    "glow-neon": "0 0 8px #FFFCFF, 0 0 24px #553DFF, 0 0 64px rgba(65, 41, 234, 0.5)",
    "glow-amber": "0 0 16px #FFA201, 0 0 48px rgba(255, 162, 1, 0.4)"
  },
  "spacing": {
    "base": "4px",
    "xs": "8px",
    "sm": "12px",
    "md": "16px",
    "lg": "24px",
    "edge": "40px"
  },
  "motion": {
    "ease-bounce": "cubic-bezier(0.34, 1.56, 0.64, 1)",
    "ease-follow": "cubic-bezier(0.25, 0.1, 0.25, 1)",
    "duration-pop": "350ms",
    "duration-panel": "450ms",
    "duration-pulse": "1600ms",
    "driving": "simulación continua: masas, fuerzas y amortiguación, sin duración"
  }
}
---
version: "1.0"
name: "Bruno Simon"
description: "Sistema visual del portfolio de Bruno Simon: un videojuego conducible hecho en Three.js donde el visitante recorre el CV en un camión 4x4 sobre un suelo violeta profundo (#1E0B43) cuadriculado con cruces neón. La paleta es noche arcade: violeta eléctrico #553DFF para el neón y la vegetación, ámbar #FFA201 para las farolas y las luces del camión, blanco caliente #FFFCFF para los aros de neón, y acentos UI en rosa #FF6A7C (peligro) y lima #D5FF95 (WebGPU/éxito). Tipografía de juguete: Amatic SC condensada a mano para los rótulos gigantes, Nunito redonda para la conversación, y Pally (sustituida por Fredoka) para el HUD. Todo es físico: chocar, derrapar, romper. Dark mode juguetón, neón, con física real."
colors:
  primary: "#553DFF"
  secondary: "#FFA201"
  canvas: "#1E0B43"
  ink: "#FFFFFF"
  neon-core: "#FFFCFF"
  neon-violet: "#5D3CF4"
  grid-cross: "#4129EA"
  tree-highlight: "#6D54D3"
  floor-glow: "#6C4EB2"
  magenta-deep: "#4118B4"
  lamp-bright: "#FFFF91"
  truck-light: "#FFFB94"
  background: "#1E0B43"
  surface: "#2A1155"
  surface-deep: "#1D063B"
  text-primary: "#FFFFFF"
  text-faded: "#FFFFFFCC"
  danger: "#FF6A7C"
  danger-soft: "#FF87A2"
  success: "#D5FF95"
  warning: "#FFA201"
  info: "#6D54D3"
typography:
  display-hand:
    fontFamily: "Amatic SC"
    fontSize: "64px"
    fontWeight: 700
    lineHeight: "normal"
    letterSpacing: "normal"
  whisper:
    fontFamily: "Amatic SC"
    fontSize: "50px"
    fontWeight: 700
    lineHeight: "normal"
    letterSpacing: "normal"
  title:
    fontFamily: "Amatic SC"
    fontSize: "40px"
    fontWeight: 700
    lineHeight: "normal"
    letterSpacing: "normal"
  body:
    fontFamily: "Nunito"
    fontSize: "20px"
    fontWeight: 400
    lineHeight: "normal"
    letterSpacing: "normal"
  body-sm:
    fontFamily: "Nunito"
    fontSize: "16px"
    fontWeight: 400
    lineHeight: "normal"
    letterSpacing: "normal"
  label:
    fontFamily: "Nunito"
    fontSize: "13px"
    fontWeight: 700
    lineHeight: "normal"
    letterSpacing: "normal"
  hud:
    fontFamily: "Pally"
    fontSize: "20px"
    fontWeight: 500
    lineHeight: "normal"
    letterSpacing: "normal"
rounded:
  chip: "15px"
  panel: "12px"
  ring: "100%"
spacing:
  base: "4px"
  xs: "8px"
  sm: "12px"
  md: "16px"
  lg: "24px"
  xl: "40px"
components:
  button-game:
    backgroundColor: "transparent"
    textColor: "{colors.text-primary}"
    typography: "{typography.display-hand}"
    rounded: "0"
    note: "Interact / Unstuck: rotulos Amatic SC 64px sin superficie, como letreros del mundo"
  panel:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.text-primary}"
    typography: "{typography.body}"
    rounded: "{rounded.panel}"
    padding: "24px"
  icon-chip:
    backgroundColor: "{colors.surface-deep}"
    textColor: "{colors.text-primary}"
    typography: "{typography.label}"
    rounded: "{rounded.chip}"
    padding: "8px 12px"
  start-ring:
    borderColor: "{colors.neon-core}"
    rounded: "{rounded.ring}"
    glow: "0 0 24px {colors.neon-violet}, 0 0 64px {colors.grid-cross}"
  whisper-input:
    backgroundColor: "transparent"
    textColor: "{colors.text-primary}"
    typography: "{typography.whisper}"
    placeholder: "Your message here"
---

# DESIGN.md - Bruno Simon

> Sistema de diseño extraído de `https://bruno-simon.com` (home, julio 2026) siguiendo el skill `url-inspiration-styleguide`.
> Colores, familias, tamaños y radios medidos sobre el sitio en vivo con Puppeteer: `@font-face` reales, estilos computados del HUD DOM y muestreo de píxeles de la captura 1600x900 (la escena es un render Three.js; el suelo, el neón y las luces no existen en CSS, así que se muestrean de la captura). Lo que el sitio no expone (escalas, estados con superficie) va marcado como *(derivado para completar el sistema)*.

---

## 1. Tema Visual y Atmósfera

El portfolio de Bruno Simon no se lee: **se conduce**. Al entrar hay un camión 4x4 aparcado bajo una farola, un aro de neón blanco que dice por dónde empezar y un rótulo escrito a mano: *CLICK TO START*. A partir de ahí, el visitante recorre el CV con las flechas del teclado (o un gamepad, o los pulgares en el móvil), derrapando entre secciones, atropellando bolos y dejando mensajes pintados en el suelo. Fue Site of the Year en Awwwards en su primera versión y sigue siendo el ejemplo canónico de "portfolio como videojuego"; la versión actual renderiza con WebGPU cuando el navegador puede (con toggle de calidad `High` visible en el HUD) y cae a WebGL cuando no.

El mundo es **noche arcade**. El suelo es un violeta profundo `#1E0B43` que se oscurece a `#1D063B` en los bordes del frame, cuadriculado con líneas y cruces de neón azul-violeta `#4129EA` que se pierden en perspectiva isométrica. La vegetación no es verde: los árboles son nubes de partículas violeta `#5C3CFF` con luces `#6D54D3`, como cerezos radiactivos. Las esquinas del frame viran a un magenta profundo `#4118B4`: la escena entera está iluminada como un local de recreativas.

Contra ese frío violeta, el sistema enciende **calor puntual**: la farola derrama un cono ámbar `#FFA201` que satura a `#FFFF91` en el foco; el camión lleva una barra LED naranja incandescente y luces de techo `#FFFB94`. La regla de color del mundo es exactamente esa: **violeta para el espacio, ámbar para la vida**. Y flotando entre ambos, el blanco caliente `#FFFCFF` del aro de neón, que no es un borde CSS sino un tubo de luz con bloom real.

La tipografía es de juguete y son tres voces medidas en el DOM: **Amatic SC** (la condensada manuscrita de Google) en 700 para todos los rótulos del mundo, gigante (40px los títulos de panel, 50px los mensajes de visitantes, 64px los botones `Interact` y `Unstuck`, que no tienen fondo ni borde: son letreros, no botones). **Nunito** en 400 para la conversación ("My name is Bruno Simon... Please drive around... And don't break anything!") a 20px redondos y amables. Y **Pally** (Fontshare, peso 500) para piezas del HUD. Los acentos de interfaz son caramelo: rosa `#FF6A7C` para los avisos ("Server currently offline"), lima `#D5FF95` para la insignia WebGPU.

**Palabras clave de personalidad**: juguetón, arcade, neón, físico, conducible, nocturno, manuscrito, cálido en los focos

**Densidad del layout**: el HUD es mínimo (contador, mapa, sonido, calidad); el mundo es denso en objetos con física

**Modo preferido**: oscuro violeta (la escena es de noche; no existe modo claro)

**Nivel de ornamentación**: alto y funcional: cada adorno (bolos, farolas, vallas) es un objeto con física que se puede chocar

**Audiencia visual objetivo**: developers creativos y clientes que quieren ver hasta dónde llega Three.js; visitantes que se quedan a jugar

---

## 2. Paleta de Colores y Roles Semánticos

Una noche violeta con dos temperaturas: neón frío para el espacio (violetas, magentas, azul eléctrico) y focos cálidos para la vida (ámbar, amarillo). Los acentos de UI son pastel caramelo (rosa, lima) medidos directamente del DOM.

### Colores de marca

| Nombre | Variable CSS | Hex | Rol | Texto sobre él |
|--------|-------------|-----|-----|----------------|
| Violeta neón | `--color-primary` | `#553DFF` | El neón del mundo: aro (saturación medida `#5D3CF4`-`#553DFF`), árboles `#5C3CFF`, cruces del suelo | `#FFFFFF` |
| Ámbar farola | `--color-secondary` | `#FFA201` | El calor: farolas, luces del camión, foco de atención | `#1E0B43` |
| Violeta suelo | `--color-canvas` | `#1E0B43` | El terreno del mundo entero (medido en captura) | `#FFFFFF` |
| Neón blanco | `--color-neon-core` | `#FFFCFF` | El núcleo del tubo de neón del aro de inicio | no lleva texto |

### Colores de escena (muestreados de la captura 1600x900)

La escena es un render Three.js: estos valores están muestreados píxel a píxel, no declarados en CSS.

| Nombre | Hex | Dónde se midió |
|--------|-----|----------------|
| Suelo | `#1E0B43` | Terreno medio (cuantizado dominante `#200040`, 23.9% del frame) |
| Suelo profundo | `#1D063B` | Bordes inferiores del frame |
| Cruz de rejilla | `#4129EA` | Las marcas `x` del suelo (pico de saturación `#422ADF`) |
| Aro de neón | `#553DFF` a `#FFFCFF` | Tubo: violeta en el halo, blanco caliente en el núcleo |
| Árbol violeta | `#5C3CFF` / `#6D54D3` | Copas de partículas y sus luces |
| Halo del suelo | `#6C4EB2` | El interior iluminado del aro de inicio |
| Magenta esquina | `#4118B4` | Viñeteo magenta de las esquinas superiores |
| Farola | `#FFA201` a `#FFFF91` | Cono de luz y foco |
| Luces del camión | `#FFFB94` | Barra LED y techo |

### Colores de superficie

| Nombre | Variable CSS | Hex | Rol |
|--------|-------------|-----|-----|
| Canvas | `--color-background` | `#1E0B43` | El suelo del mundo; el fondo de cualquier UI |
| Superficie | `--color-surface` | `#2A1155` | Paneles sobre el mundo *(derivado: el suelo iluminado un paso)* |
| Superficie honda | `--color-surface-deep` | `#1D063B` | Zonas de reposo, footers *(medido en bordes)* |

### Colores de texto

| Nombre | Variable CSS | Hex | Uso |
|--------|-------------|-----|-----|
| Blanco | `--color-text-primary` | `#FFFFFF` | Todo el texto del sitio (real: títulos, body, botones) |
| Blanco desvanecido | `--color-text-faded` | `rgba(255,255,255,0.8)` | Metadata del HUD (real: labels de calidad) |
| Rosa peligro | `--color-danger` | `#FF6A7C` | Estado offline del HUD (real: `rgb(255,106,124)`) |
| Rosa aviso | `--color-danger-soft` | `#FF87A2` | Mensajes de error largos (real: `rgb(255,135,162)`) |
| Lima | `--color-success` | `#D5FF95` | Insignia WebGPU del HUD (real: `rgb(213,255,149)`) |

### Contraste verificado (sobre `#1E0B43`)

| Combinación | Ratio | Nivel |
|-------------|-------|-------|
| `#FFFFFF` sobre `#1E0B43` | 17.7:1 | AAA |
| `#D5FF95` sobre `#1E0B43` | 15.7:1 | AAA |
| `#FFFF91` sobre `#1E0B43` | 16.2:1 | AAA |
| `#FFA201` sobre `#1E0B43` | 8.8:1 | AAA |
| `#FF6A7C` sobre `#1E0B43` | 6.4:1 | AA (AAA en texto grande) |
| `#FF87A2` sobre `#1E0B43` | 8.1:1 | AAA |
| `#6D54D3` sobre `#1E0B43` | 3.6:1 | solo texto grande o decorativo |
| `#553DFF` sobre `#1E0B43` | 3.0:1 | solo display/neón, nunca texto pequeño |
| `#1E0B43` sobre `#FFA201` | 8.8:1 | AAA |

> **La trampa del neón**: el violeta `#553DFF` brilla muchísimo en pantalla pero solo rinde 3:1 sobre el suelo. En el sitio real nunca es texto: es tubo, árbol y rejilla. Si lo necesitas como texto, súbelo a `#6D54D3`+tamaño grande o pásalo a blanco con glow violeta.

### Colores de estado

Los tres primeros son reales (medidos en el DOM del HUD); el resto *(derivado para completar el sistema)*.

| Estado | Variable CSS | Hex | Origen |
|--------|-------------|-----|--------|
| Peligro | `--color-danger` | `#FF6A7C` | Real: "Offline" del HUD |
| Peligro suave | `--color-danger-soft` | `#FF87A2` | Real: "Server currently offline. Scores can't be saved." |
| Éxito / capacidad | `--color-success` | `#D5FF95` | Real: insignia "WebGPU" |
| Aviso | `--color-warning` | `#FFA201` | El ámbar de las farolas *(rol derivado)* |
| Info | `--color-info` | `#6D54D3` | El violeta claro de los árboles *(rol derivado)* |

---

## 3. Reglas de Tipografía

```css
/* Tres familias reales medidas en el DOM:
   1. Amatic SC 700 (Google Fonts, directa): rótulos del mundo
   2. Nunito 400/700/900 (Google Fonts, directa): conversación y HUD
   3. Pally 400/500/700 (Fontshare, self-hosted) -> sustituto Google: Fredoka */
--font-display: 'Amatic SC', cursive;
--font-body:    'Nunito', sans-serif;
--font-hud:     'Fredoka', 'Pally', sans-serif;
--font-mono:    ui-monospace, SFMono-Regular, Menlo, monospace; /* no detectada en el sitio (derivada para código) */
```

**Google Fonts:**
```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=Amatic+SC:wght@700&family=Nunito:wght@400;700;900&family=Fredoka:wght@400;500;700&display=swap" rel="stylesheet">
```

### Nota sobre sustitución tipográfica

**Amatic SC y Nunito son Google Fonts y se usan directas, sin sustitución** (caso poco común en esta galería: dos de las tres fuentes reales del sitio son libres).

**Original: Pally -> HTML: Fredoka (Google substitute).** Pally (Indian Type Foundry, distribución Fontshare) es una geométrica redonda y regordeta con terminales blandos y personalidad de juguete, cargada por el sitio en Regular/Medium/Bold para piezas del HUD. Fontshare no es Google Fonts y su licencia ITF no permite redistribución casual.

Candidatas comparadas antes de decidir:

| Candidata | Por qué encaja | Por qué se descarta |
|---|---|---|
| **Fredoka** | Geométrica redonda con la misma jovialidad regordeta, terminales blandos y contadores generosos; pesos 300-700 con los tres que Pally aporta (400/500/700). A tamaños de HUD (13-20px) es casi intercambiable. | **Elegida.** |
| Baloo 2 | Muy cercana en espíritu rechoncho. | Más pesada de color tipográfico en 400: a 13px del HUD empasta contra el neón. |
| Quicksand | Geométrica redonda ligera. | Demasiado esbelta y elegante: pierde el "juguete" que comparten Pally y el mundo del sitio. |
| Comfortaa | Redondez máxima. | Su geometría es tan protagonista que compite con Amatic SC; el HUD debe ser neutro-amable. |

### Escala tipográfica

> Tamaños reales medidos: **64px** (botones Interact/Unstuck, Amatic 700), **50px** (whispers, Amatic 700), **40px** (títulos de panel, Amatic 700), **20px** (body Nunito 400, el `font-size` del body entero), **16px** (notas `text-small`), **13px** (labels 700 del HUD).

| Token | px real | Weight | Familia | Uso |
|-------|---------|--------|---------|-----|
| `--f-display-hand` | 64px | 700 | Amatic SC | Botones-letrero del mundo (`Interact`, `Unstuck`) |
| `--f-whisper` | 50px | 700 | Amatic SC | Mensajes de visitantes ("Your message here") |
| `--f-title` | 40px | 700 | Amatic SC | Títulos de panel (`Three.js`, `Devlogs`, `Musics`) |
| `--f-body` | 20px | 400 | Nunito | Conversación y párrafos (el default del body) |
| `--f-body-sm` | 16px | 400 | Nunito | Notas y aclaraciones (`text-small text-faded`) |
| `--f-label` | 13px | 700 | Nunito | Labels de iconos del HUD ("Mouse Keyboard", "Mobile Tablet") |
| `--f-hud` | 20px | 500 | Pally/Fredoka | Piezas de HUD con voz propia |

### Pesos tipográficos

```css
/* Amatic SC: solo 700. A 40-64px el trazo manuscrito necesita el bold. */
--font-hand: 700;
/* Nunito: 400 el body, 700 los labels, 900 cargada para énfasis puntual. */
--font-regular: 400;
--font-bold:    700;
--font-black:   900;
/* Pally: 500 (Medium) como peso de trabajo del HUD. */
--font-hud-weight: 500;
```

### Reglas de composición

- **Amatic SC nunca baja de 40px.** Es una condensada manuscrita: a tamaños de párrafo se vuelve ilegible. En el sitio real su mínimo medido es 40px.
- **Nunito nunca hace de display.** A 20px/400 es la voz que explica; los titulares son siempre de Amatic.
- **Sin tracking en ninguna de las tres.** Todo va con `letter-spacing: normal` (medido). La personalidad ya la ponen los esqueletos.
- **line-height normal.** El sitio no fuerza interlíneas: los rótulos manuscritos respiran con su métrica nativa.

---

## 4. Estilos de Componentes

### Botón-letrero (componente firma)

Los "botones" del mundo (`Interact`, `Unstuck`) no tienen caja: son rótulos manuscritos gigantes, como letreros pintados que flotan sobre la escena.

```
Background: transparent        (real)
Border: none                    (real)
Border-radius: 0                (real)
Font: Amatic SC 700, 64px       (real)
Color: #FFFFFF                  (real)
Sombra de texto: 0 0 12px rgba(85,61,255,0.6)  (derivado: glow neón para despegarlo del suelo)

Hover (derivado del comportamiento del mundo):
  Transform: scale(1.06) con rebote
  El glow sube de radio

Regla: si un control vive DENTRO del mundo, no lleva superficie.
Las cajas son para paneles que interrumpen el juego.
```

### Rótulo manuscrito de instrucción

```
"CLICK TO START" con flecha dibujada a mano apuntando al aro
Font: Amatic SC 700, blanco #FFFFFF
Acompañado de icono de sonido dibujado con el mismo trazo
Regla: las instrucciones son parte del decorado, no tooltips
```

### Aro de inicio (neón)

```
Forma: elipse en perspectiva sobre el suelo
Tubo: núcleo #FFFCFF de 2-3px + halo #553DFF
Glow: bloom real en la escena; en CSS plano (derivado):
  box-shadow: 0 0 8px #FFFCFF, 0 0 24px #553DFF, 0 0 64px #4129EA
Interior: el suelo se ilumina a #6C4EB2
Rol: zona de acción. El neón marca "aquí pasa algo".
```

### Panel de contenido

Los paneles (whispers, menú, leaderboard) interrumpen el juego con una capa.

```
Background: rgba(30,11,67,0.92)   (derivado del suelo #1E0B43)
Border-radius: 12px                (derivado; el DOM real usa overlay a sangre)
Padding: 24px
Título: Amatic SC 700, 40px, #FFFFFF   (real)
Body: Nunito 400, 20px, #FFFFFF        (real)
Nota: Nunito 400, 16px, rgba(255,255,255,0.8)  (real: text-small text-faded)
Línea divisoria: 1px #FFFFFF (real: div.line con background blanco)
```

### Chip de icono del HUD

```
Contenido: icono + label ("Mouse Keyboard", "Mobile Tablet", mando Xbox)
Label: Nunito 700, 13px, #FFFFFF   (real)
Icono de gamepad: radio 15px (real: span.icon.is-xbox)
Background: transparente sobre el mundo; superficie #1D063B si necesita asiento (derivado)
```

### Insignias de estado del HUD (reales)

```
Calidad:  "High" - Nunito 400, 20px, rgba(255,255,255,0.8), line-height 58px
Motor:    "WebGPU" - Nunito 400, 20px, #D5FF95 (lima)
Servidor: "Offline" - Nunito 400, 20px, #FF6A7C (rosa)
Regla: el estado técnico se muestra con orgullo en el HUD, con color
de caramelo: la insignia WebGPU en lima es parte de la marca.
```

### Whisper (mensaje de visitante)

```
Input y render: Amatic SC 700, 50px, #FFFFFF   (real)
Placeholder: "Your message here"
Reglas mostradas al usuario (reales): "Everyone can see them" + notas en 16px faded
En el mundo: el mensaje queda pintado en el suelo con el mismo trazo
```

### Contador / cronómetro

```
Uso: vueltas cronometradas y récords ("Resets in...")
Font: Nunito 400, 20px (real); cifras grandes en Amatic 700 (derivado)
Aviso de servidor: #FF87A2 (real)
```

### Triggers del HUD (menú y mapa)

```
Botones reales: js-menu-trigger y js-map-trigger (Nunito 400, 20px)
Sin caja: iconos dibujados sobre el mundo, anclados a las esquinas
Hover: scale con rebote (derivado de la voz del mundo)
```

### Navegación de paneles

```
Botones reales del DOM: previous / next / open / close
Font heredada: Amatic SC 700, 64px (misma voz que los letreros)
Las flechas de navegación son rótulos, no iconos de sistema
Cierre: botón js-close con label de teclado ("A" para gamepad)
```

---

## 5. Principios de Layout

### El layout es un mundo con HUD

No hay grid de página: hay una escena isométrica-cenital y capas de HUD ancladas a los bordes. La cámara sigue al camión; el "layout" es la composición del encuadre.

```
+--------------------------------------------------+
| [sonido] [calidad High/WebGPU]        [mapa]     |
|                                                    |
|            (mundo: camión, farola,                 |
|             aro de neón, árboles)                  |
|                                                    |
|      CLICK TO START ~~~>  (rótulo en escena)       |
|                                                    |
| [chips de input: teclado/touch/gamepad]  [menú]   |
+--------------------------------------------------+
```

### Escala de espaciado

*(derivada: el DOM real ancla por absolutos; base 4px coherente con los paddings observados)*

```css
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 40px;   /* margen del HUD a los bordes */
```

### Reglas

1. **El centro es del juego.** El HUD nunca invade el tercio central del frame, donde vive el camión.
2. **Las instrucciones se rotulan en el mundo** (CLICK TO START junto al aro), no en overlays.
3. **Cada objeto es interactivo o no existe.** Bolos, vallas y letras del suelo tienen cuerpo físico: el decorado es jugable.
4. **Los paneles pausan.** Cuando un panel de contenido abre, el mundo queda detrás desenfocado/oscurecido y el input pasa al panel.

---

## 6. Profundidad y Elevación

La profundidad se hace con **luz de neón y bloom**, no con sombras CSS (medido: `box-shadow: none` en todo el DOM).

### Sistema de elevación

| Nivel | Técnica | Uso |
|-------|---------|-----|
| 0 - Suelo | `#1E0B43` con viñeteo a `#1D063B` y magenta `#4118B4` en esquinas | El mundo |
| 1 - Rejilla | Cruces `#4129EA` con leve emisión | La textura del suelo |
| 2 - Objeto | Iluminación de escena + sombras proyectadas del render | Camión, árboles, farola |
| 3 - Neón | Tubo `#FFFCFF` + halo `#553DFF` + suelo iluminado `#6C4EB2` | Zonas de acción |
| 4 - Foco | Conos ámbar `#FFA201` -> `#FFFF91` | Los puntos de vida |
| 5 - HUD/Panel | Blanco sobre overlay oscuro, sin sombra | La interfaz |

```css
/* Glow de neón para CSS plano (derivado de los valores medidos) */
--glow-neon:  0 0 8px #FFFCFF, 0 0 24px #553DFF, 0 0 64px rgba(65, 41, 234, 0.5);
--glow-amber: 0 0 16px #FFA201, 0 0 48px rgba(255, 162, 1, 0.4);
--shadow-none: none;   /* el DOM real no usa box-shadow */
```

> **Regla**: lo que importa emite luz; lo que descansa la recibe. Un elemento "elevado" en este sistema no flota con sombra: **brilla**. El violeta ilumina espacio, el ámbar ilumina vida.

### Radios de borde

```css
--radius-chip: 15px;    /* real: el icono de gamepad del HUD */
--radius-panel: 12px;   /* derivado para paneles */
--radius-ring: 100%;    /* el aro de neón */
--radius-letrero: 0;    /* real: los botones-letrero no tienen caja */
```

---

## 7. Lo que Sí y lo que No

### Sí hacer

1. **Violeta para el espacio, ámbar para la vida.** El mundo entero es frío `#1E0B43`/`#553DFF`; el calor `#FFA201` se reserva para faros, farolas y focos de atención.
2. **Rotula en Amatic SC 700 y nunca por debajo de 40px.** Los títulos de este sistema son letreros de mano gigantes.
3. **Explica en Nunito 400 a 20px.** Amable, redonda, sin tracking. La diferencia entre rotular y conversar es la firma tipográfica.
4. **Haz que la elevación brille**: neón blanco con halo violeta para zonas de acción, glow ámbar para lo vivo. Nada de sombras negras.
5. **Deja los controles del mundo sin caja** (letreros transparentes); reserva las superficies para paneles que pausan el juego.
6. **Muestra el estado técnico con orgullo y color caramelo**: WebGPU en lima `#D5FF95`, offline en rosa `#FF6A7C`.
7. **Da cuerpo físico a la decoración.** Si algo está en el mundo, se puede chocar. La interactividad es la ornamentación.
8. **Marca las zonas de acción con un aro de neón en el suelo**, no con un botón flotante.

### No hacer

1. **No uses el violeta neón `#553DFF` como texto pequeño.** Rinde 3:1 sobre el suelo: es tubo y rejilla, no tipografía.
2. **No pongas Amatic SC en párrafos.** Por debajo de 40px la manuscrita condensada se rompe.
3. **No enfríes el ámbar.** Las farolas son `#FFA201` puro; un amarillo pastel apaga los focos de vida del mundo.
4. **No uses sombras negras CSS.** La profundidad aquí es luz (bloom, halos, conos); una `box-shadow` gris rompe la noche arcade.
5. **No conviertas los letreros en botones con caja.** `Interact` a 64px transparente es la voz del mundo; una píldora con fondo lo convierte en un formulario.
6. **No añadas tracking ni caps forzadas.** Todo el sistema va con `letter-spacing: normal` y la caja que trae cada familia.
7. **No pongas verde natural en la vegetación.** Los árboles de este mundo son violeta `#5C3CFF`: el color es de neón, no de bosque.
8. **No tapes el tercio central del frame con HUD.** Ahí vive el camión; la interfaz respeta el juego.

---

## 8. Comportamiento Responsive

### Breakpoints

El sitio no reordena columnas: **cambia el esquema de control y el encuadre**.

```css
/* (derivado del comportamiento observable y de los chips de input reales) */
/* sm: */ @media (min-width: 640px)  { }
/* md: */ @media (min-width: 768px)  { }
/* lg: */ @media (min-width: 1024px) { }
```

### Cambios por breakpoint

**Mobile (< 640px)**
- Input: joystick táctil + botones `Interact`/`Unstuck` en pantalla (reales: `js-touch-buttons`)
- La cámara encuadra más cerca del camión
- Los paneles de contenido pasan a sangre completa
- El HUD reduce a sonido + mapa; las insignias de calidad se ocultan

**Tablet (640px a 1024px)**
- Controles táctiles con chips de icono visibles ("Mobile Tablet", real)
- Calidad de render ajustada (menos partículas de vegetación)

**Desktop (> 1024px)**
- Teclado (WASD/flechas) y gamepad (chips con iconos Xbox reales en el DOM)
- Encuadre amplio con el viñeteo magenta completo
- Insignias High/WebGPU visibles

### Touch y accesibilidad de juego

- Botones táctiles de gran superficie (los letreros de 64px son el target)
- `Unstuck` siempre visible: la mecánica de rescate es parte de la UI (si el camión vuelca, un botón lo endereza)
- El sitio detecta el esquema de entrada y muestra chips explicativos con icono + label de 13px/700

---

## 9. Guía de Prompts para Agentes

### Prompt de inicialización de sesión

```text
Estás trabajando con el sistema de diseño del portfolio de Bruno Simon
(videojuego conducible en Three.js).

PALETA: suelo violeta profundo #1E0B43 (bordes #1D063B, esquinas magenta
#4118B4). Neón violeta #553DFF para espacio: aro de inicio (núcleo blanco
caliente #FFFCFF), árboles #5C3CFF/#6D54D3, cruces de rejilla #4129EA.
Calor SOLO en focos de vida: ámbar #FFA201 (farolas, luces del camión,
picos #FFFF91). UI caramelo: peligro rosa #FF6A7C/#FF87A2, éxito lima
#D5FF95. Texto siempre blanco #FFFFFF (faded: 80%).

TIPOGRAFÍA: Amatic SC 700 para rótulos (40px mínimo, 50-64px normal),
Nunito 400 para conversación (20px) y 700 para labels (13px), Fredoka
(sustituta de Pally) para HUD. Sin tracking, line-height normal.

ESTILO: los controles del mundo son letreros transparentes sin caja;
las superficies son para paneles que pausan. Elevación = luz (glow neón
violeta, glow ámbar), nunca box-shadow negra. Radios: 15px chips, 12px
paneles, 0 letreros. MODO: noche arcade, sin modo claro.
```

### Prompt: Crear nueva pantalla

```text
Crea una pantalla de [FUNCIONALIDAD] para el mundo de Bruno Simon.

Requisitos:
- Fondo violeta #1E0B43 con viñeteo #1D063B y esquinas magenta
- Titular en Amatic SC 700 a 40px o más, blanco
- Body en Nunito 400 a 20px, blanco; notas a 16px al 80%
- La acción principal marcada con neón: aro/subrayado #FFFCFF + halo #553DFF
- Un solo foco ámbar #FFA201 por vista (la vida de la escena)
- Controles del mundo sin caja (letrero transparente + glow); paneles
  con superficie rgba(30,11,67,0.92) y radio 12px
- Estados con color caramelo: rosa #FF6A7C peligro, lima #D5FF95 éxito
- Nada de sombras negras: la profundidad es luz
```

### Prompt: Añadir componente al UI kit

```text
Añade un componente de [TIPO] al sistema de Bruno Simon.

Debe:
- Usar solo tokens del DESIGN.md de Bruno Simon
- Elegir voz: letrero del mundo (Amatic 700 >= 40px, transparente, glow)
  o panel (superficie violeta, radio 12px, Nunito)
- Estados: hover con scale(1.06) y rebote; focus con aro de neón
  (outline #FFFCFF + halo violeta); disabled al 40%
- Peligro en rosa #FF6A7C, éxito en lima #D5FF95, foco de atención
  en ámbar #FFA201
- Sin box-shadow negra; el glow es la elevación
```

### Prompt: Revisión de consistencia

```text
Revisa esta interfaz y detecta qué no sigue el sistema de Bruno Simon.

Verifica:
1. Si Amatic SC aparece por debajo de 40px (no debe)
2. Si el violeta neón #553DFF se usa como texto pequeño (no debe: 3:1)
3. Si hay box-shadow negra donde debería haber glow
4. Si el ámbar #FFA201 se reparte en vez de concentrarse en focos de vida
5. Si los controles del mundo llevan caja/fondo (deben ser letreros)
6. Si hay tracking o caps forzadas (todo va normal)
7. Si la vegetación u objetos del mundo usan colores naturales (aquí son neón)
8. Si el HUD invade el tercio central del frame
9. Si los estados usan rojo/verde de sistema en vez del caramelo rosa/lima
```

### Prompt: Variante de campaña

```text
Genera una variante [sección del mundo / minijuego / evento] para
Bruno Simon manteniendo el sistema base.

Conserva:
- El suelo violeta #1E0B43 con rejilla de cruces #4129EA
- Amatic SC 700 gigante para rótulos y Nunito 400 para conversación
- La regla de temperatura: violeta = espacio, ámbar = vida
- El neón blanco/violeta como marcador de zonas de acción

Puedes variar:
- Los objetos físicos de la zona (bolos, rampas, dianas)
- El color del neón de zona (lima #D5FF95 para retos, rosa #FF6A7C
  para peligro), manteniendo el núcleo blanco del tubo
- La densidad de vegetación violeta
```

---

## 10. Movimiento (Motion) e Interacción JS

El motion de este sitio no es animación de interfaz: **es un motor de físicas al servicio del humor**. El portfolio fue Site of the Year en Awwwards precisamente por esto: la interacción ES el contenido. Es el motivo por el que está en esta galería.

**Nivel de motion**: total. Todo lo que se ve tiene simulación: el camión tiene suspensión, los bolos caen, las letras del suelo salen despedidas.

**Arquitectura observada**:
- Canvas Three.js a viewport completo (`js-canvas experience`, 1600x900 a dpr 1)
- **Renderer WebGPU con fallback**: el HUD real muestra las insignias `High` y `WebGPU` (lima `#D5FF95`); la calidad es configurable
- Física de vehículo: chasis + 4 ruedas con suspensión, derrape y vuelco (de ahí el botón real `Unstuck`)
- Multi-input real: teclado, touch (joystick + botones `js-touch-buttons`) y gamepad (chips con iconos Xbox en el DOM)
- Sistema social ("whispers"): mensajes de visitantes escritos en Amatic 50px que quedan en el mundo; leaderboard con servidor (el HUD real avisa "Server currently offline. Scores can't be saved." en rosa y "Resets in..." para el reinicio de récords)

**Patrones de motion observados**:
- **Conducción física**: aceleración, frenada, derrape con inercia; la cámara cenital sigue al camión con lag suave (lerp) para que el mundo "gire" alrededor
- **Loader jugable**: la pantalla de carga termina en un rótulo manuscrito CLICK TO START con flecha dibujada; el clic inicial también desbloquea el audio
- **Objetos rompibles**: bolos, vallas y letras con cuerpo físico; chocar es la micro-interacción principal ("And don't break anything!" es la instrucción real del intro)
- **Neón como señal**: las zonas de acción laten con bloom; el aro de inicio es un tubo de luz, no un borde
- **Botón-letrero con rebote**: `Interact`/`Unstuck` aparecen contextualos, con entrada elástica *(comportamiento derivado de la voz del mundo)*
- **Sonido físico**: motor, colisiones y bocina ligados a la simulación; toggle de sonido en el HUD desde el primer frame

**Duraciones y easings** *(la simulación no usa duraciones: usa masas, fuerzas y amortiguación; estos valores son la traducción derivada a CSS)*:

```css
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);  /* entradas de letreros: rebote */
--ease-follow: cubic-bezier(0.25, 0.1, 0.25, 1);    /* cámara: lag suave */
--duration-pop:    350ms;   /* aparición de letreros y chips */
--duration-panel:  450ms;   /* apertura de paneles de contenido */
--duration-pulse:  1600ms;  /* latido del neón de zonas de acción */
/* la conducción y las colisiones no tienen duración: son simulación continua */
```

**Inventario de interacciones observadas**:

| Interacción | Disparador | Respuesta | Capa |
|-------------|-----------|-----------|------|
| Conducción | teclado / touch / gamepad | física de vehículo con suspensión | render |
| Colisión | contacto con objetos | los objetos salen despedidos + sonido | render |
| Vuelco | física | botón Unstuck aparece (64px Amatic) | render+DOM |
| Zona de acción | entrar en el aro de neón | el contenido se activa / panel abre | render+DOM |
| Whisper | escribir en el input (50px) | mensaje pintado en el suelo del mundo | DOM→render |
| Leaderboard | cruzar meta cronometrada | tiempo enviado al servidor ("Resets in") | DOM+red |
| Cambio de calidad | toggle High del HUD | densidad de render ajustada | DOM→render |
| Sonido | CLICK TO START inicial | audio desbloqueado; motor y bocina | DOM→audio |
| Mapa / menú | js-map-trigger / js-menu-trigger | overlay sobre el juego | DOM |

**Reglas de interacción**:
1. **El input es siempre físico**: no hay "click en card", hay conducir hasta la zona y entrar en el aro de neón.
2. **El error es divertido**: volcar el camión no es un fallo, es la razón de que exista el botón `Unstuck` (a 64px manuscritas).
3. **Lo social vive en el mundo**: los whispers no son un muro de comentarios, son pintadas en el suelo que el visitante atraviesa conduciendo.
4. **El estado técnico es celebración**: la insignia WebGPU en lima presume del motor; la calidad es un ajuste visible, no un menú oculto.

> **Accesibilidad**: respeta `@media (prefers-reduced-motion: reduce)`: cámara sin lag (seguimiento rígido), neón sin latido (brillo fijo), letreros sin rebote (aparición por opacidad). Los paneles de contenido (Three.js Journey, Devlogs, Source code, Musics: títulos H2 reales del DOM) ofrecen el contenido del portfolio en HTML navegable, con lo que el CV es legible sin conducir.

---

## Anexo: Stack técnico detectado

- **Plataforma**: escena Three.js a canvas completo (`js-canvas experience`) con **renderer WebGPU** y fallback (insignias reales `High` / `WebGPU` en el HUD); física de vehículo con suspensión y vuelco (botón `Unstuck` real).
- **Título real del documento**: "Bruno's".
- **Sistema de tokens**: cero variables CSS en el `:root`. El body declara `font-size: 20px` con `Nunito, sans-serif`; el fondo es transparente (la escena pinta el color).
- **Tipografía**: tres familias reales cargadas: **Amatic SC 700** (Google, `document.fonts`), **Nunito 400/700/900** (Google) y **Pally Regular/Medium/Bold** (`@font-face` self-hosted de Fontshare; Medium cargado en uso). Cargador de fuentes propio (`js-fonts-loader` con un div de prueba por familia).
- **Colores DOM reales**: texto `#FFFFFF` y `rgba(255,255,255,0.8)`; peligro `rgb(255,106,124)` y `rgb(255,135,162)`; lima WebGPU `rgb(213,255,149)`; divisor `div.line` blanco; icono gamepad con radio 15px.
- **Colores de escena muestreados** (captura 1600x900, cuantización 16): suelo dominante `#200040`-cluster (23.9% del frame), medido fino `#1E0B43`/`#1D063B`; neón `#553DFF`/`#5D3CF4` con núcleo `#FFFCFF`; cruces `#4129EA`; árboles `#5C3CFF`/`#6D54D3`; halo de suelo `#6C4EB2`; esquinas `#4118B4`; farola `#FFA201`->`#FFFF91`; luces del camión `#FFFB94`.
- **Input**: teclado, touch (`js-touch-buttons` con joystick) y gamepad (iconos Xbox reales: `span.icon.is-xbox`); chips explicativos "Mouse Keyboard" / "Mobile Tablet" a 13px/700.
- **Social/backend**: whispers (mensajes de visitantes, input Amatic 50px "Your message here", reglas visibles), leaderboard con reset programado ("Resets in") y aviso de estado del servidor en rosa.
- **Paneles de contenido**: títulos H2 reales `Three.js`, `Three.js Journey`, `Devlogs`, `Source code`, `Musics`, `Some more links` (Amatic 40px).
- **Reconocimiento**: Awwwards Site of the Year (primera versión, 2019); el portfolio conducible es referencia canónica de Three.js y del propio curso Three.js Journey de Bruno Simon.
- **(no detectado)**: framework de UI (DOM artesanal), librería de física expuesta (Cannon.js en v1 según el propio autor; la actual no la declara en el DOM), variables CSS de color, box-shadows (ninguna), modo claro, tipografía mono.