Aprendizaje de idiomas gamificado que se viste de blanco y verde: tipografía rounded bold con peso 700 dominante, botones 3D con sombra inferior sólida, y un sistema de colores con nombres de animales que es parte del lenguaje interno de la marca.
Duolingo is the world's most popular way to learn a language. It's 100% free, fun and science-based. Practice online on duolingo.com or on the apps!
| Role | Size | Weight | LH |
|---|---|---|---|
| pageTitle | 40px | 700 | 44px |
| heading-lg | 28px | 700 | 32px |
| heading-sm | 20px | 700 | 24px |
| body | 20px | 500 | 28px |
| caption | 16px | 500 | 24px |
| label | 16px | 700 | 16px |
Keep practicing every day to maintain your streak. You earned 50 XP today. ¡Buen trabajo!
:root {
/* Color — blanco + verde macaw + azul whale + sistema de animales */
--color-canvas: #FFFFFF; /* --color-snow */
--color-surface: #F0F0F0;
--color-surface-elevated: #FFFFFF;
--color-surface-blue: #DDF4FF;
--color-ink: #4B4B4B; /* --color-eel */
--color-ink-soft: #777777; /* --color-wolf */
--color-muted: #AFAFAF; /* --color-hare */
--color-text-dark: #15171A;
--color-primary: #58CC02; /* --color-macaw, verde signature */
--color-primary-hover: #58B810;
--color-primary-active: #3C9E00;
--color-secondary: #1CB0F6; /* --color-whale */
--color-secondary-hover: #009BE4;
--color-accent: #00CD9C; /* --color-peacock */
--color-accent-soft: #DDF4FF;
--color-warning: #FFC800; /* --color-owl/bee */
--color-error: #EA2B2B; /* --color-cardinal */
--color-border: #E5E5E5; /* --color-swan */
--color-border-emphasized: #CECECE;
--color-on-primary: #FFFFFF;
/* Typography */
--font-display: 'Nunito', system-ui, sans-serif;
--font-body: 'Nunito', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
/* Scale — peso 700 dominante (firma de marca) */
--f-pageTitle: 700 40px/44px var(--font-display);
--f-heading-lg: 700 28px/32px var(--font-display);
--f-heading-sm: 700 20px/24px var(--font-display);
--f-body: 500 20px/28px var(--font-body);
--f-caption: 500 16px/24px var(--font-body);
--f-label: 700 16px/16px var(--font-display); /* uppercase, 0.04em */
/* Radius + shadow 3D */
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px; /* --web-ui_card-border-radius, cards */
--radius-xl: 16px; /* --web-ui_button-border-radius, botones */
--shadow-3d-green: 0 4px 0 #3C9E00; /* sombra sólida del botón verde */
--shadow-3d-blue: 0 4px 0 #009BE4; /* sombra sólida del botón azul */
--shadow-card: 0 2px 0 #E5E5E5; /* sombra sutil de card */
/* Spacing — base 4px */
--space-4: 4px; --space-8: 8px; --space-12: 12px;
--space-16: 16px; --space-24: 24px; --space-32: 32px;
--space-40: 40px; --space-60: 60px;
/* Motion */
--ease: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 100ms; /* pressed 3D */
--duration-base: 150ms; /* hover */
}@theme {
/* Color */
--color-canvas: #FFFFFF;
--color-surface: #F0F0F0;
--color-surface-elevated: #FFFFFF;
--color-surface-blue: #DDF4FF;
--color-ink: #4B4B4B;
--color-ink-soft: #777777;
--color-muted: #AFAFAF;
--color-text-dark: #15171A;
--color-primary: #58CC02;
--color-primary-hover: #58B810;
--color-primary-active: #3C9E00;
--color-secondary: #1CB0F6;
--color-secondary-hover: #009BE4;
--color-accent: #00CD9C;
--color-accent-soft: #DDF4FF;
--color-warning: #FFC800;
--color-error: #EA2B2B;
--color-border: #E5E5E5;
--color-on-primary: #FFFFFF;
/* Font families */
--font-display: 'Nunito', system-ui, sans-serif;
--font-body: 'Nunito', system-ui, sans-serif;
/* Font sizes (px) */
--text-pageTitle: 40px;
--text-heading-lg: 28px;
--text-heading-sm: 20px;
--text-body: 20px;
--text-caption: 16px;
--text-label: 16px;
/* Font weights — 700 dominante */
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-bold: 700;
--font-weight-extrabold: 800;
/* Radius */
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
/* Shadow 3D */
--shadow-3d-green: 0 4px 0 #3C9E00;
--shadow-3d-blue: 0 4px 0 #009BE4;
/* Spacing */
--spacing-4: 4px; --spacing-8: 8px; --spacing-12: 12px;
--spacing-16: 16px; --spacing-24: 24px; --spacing-60: 60px;
/* Easing */
--ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
}{
"color": {
"canvas": "#FFFFFF",
"surface": "#F0F0F0",
"surfaceBlue": "#DDF4FF",
"ink": "#4B4B4B",
"inkSoft": "#777777",
"muted": "#AFAFAF",
"textDark": "#15171A",
"primary": "#58CC02",
"primaryHover": "#58B810",
"primaryActive": "#3C9E00",
"secondary": "#1CB0F6",
"secondaryHover": "#009BE4",
"accent": "#00CD9C",
"accentSoft": "#DDF4FF",
"warning": "#FFC800",
"error": "#EA2B2B",
"border": "#E5E5E5",
"onPrimary": "#FFFFFF"
},
"font": {
"display": { "family": "Nunito", "substituteOf": "Feather (custom, self-hosted)" },
"body": { "family": "Nunito", "substituteOf": "DIN Next Rounded (commercial)" }
},
"fontSize": {
"pageTitle": { "px": 40, "weight": 700, "lineHeight": "44px" },
"headingLg": { "px": 28, "weight": 700, "lineHeight": "32px" },
"headingSm": { "px": 20, "weight": 700, "lineHeight": "24px" },
"body": { "px": 20, "weight": 500, "lineHeight": "28px" },
"caption": { "px": 16, "weight": 500, "lineHeight": "24px" },
"label": { "px": 16, "weight": 700, "lineHeight": "16px", "tracking": "0.04em", "transform": "uppercase" }
},
"radius": { "sm": "6px", "md": "8px", "lg": "12px", "xl": "16px", "full": "50%" },
"spacing": { "base": "4px", "sm": "8px", "md": "12px", "lg": "16px", "xl": "24px", "2xl": "32px", "3xl": "40px", "section": "60px" },
"shadow": {
"3dGreen": "0 4px 0 #3C9E00",
"3dBlue": "0 4px 0 #009BE4",
"card": "0 2px 0 #E5E5E5"
},
"motion": {
"ease": "cubic-bezier(0.16, 1, 0.3, 1)",
"durationFast": "100ms",
"durationBase": "150ms"
}
}---
version: "1.0"
name: "Duolingo"
description: "Sistema visual de aprendizaje de idiomas: canvas blanco puro, verde signature #58CC02 (macaw) como acento de marca, tipografía rounded bold (Feather custom + DIN Next Rounded) con peso 700 dominante, botones 3D con sombra inferior solida, y un sistema de colores con nombres de animales. Juguetón, redondeado, educativo y vibrante."
colors:
primary: "#58CC02"
primary-hover: "#58B810"
primary-active: "#3C9E00"
secondary: "#1CB0F6"
accent: "#00CD9C"
accent-soft: "#DDF4FF"
neutral: "#777777"
background: "#FFFFFF"
surface: "#F0F0F0"
surface-elevated: "#FFFFFF"
surface-blue: "#DDF4FF"
text-primary: "#4B4B4B"
text-secondary: "#777777"
text-muted: "#AFAFAF"
text-on-primary: "#FFFFFF"
text-dark: "#15171A"
border: "#E5E5E5"
border-subtle: "#F0F0F0"
border-emphasized: "#CECECE"
success: "#58CC02"
success-bg: "#DDF4FF"
warning: "#FFC800"
warning-bg: "#FFF8DD"
error: "#EA2B2B"
error-bg: "#FFE5E5"
info: "#1CB0F6"
info-bg: "#DDF4FF"
typography:
display-xl:
fontFamily: "Feather"
fontSize: "40px"
fontWeight: 700
lineHeight: "110%"
letterSpacing: "0em"
display-lg:
fontFamily: "Feather"
fontSize: "28px"
fontWeight: 700
lineHeight: "115%"
display-md:
fontFamily: "Feather"
fontSize: "24px"
fontWeight: 700
lineHeight: "120%"
heading:
fontFamily: "Feather"
fontSize: "20px"
fontWeight: 700
lineHeight: "130%"
body-lg:
fontFamily: "DIN Next Rounded"
fontSize: "20px"
fontWeight: 500
lineHeight: "175%"
body-md:
fontFamily: "DIN Next Rounded"
fontSize: "19px"
fontWeight: 400
lineHeight: "160%"
body-sm:
fontFamily: "DIN Next Rounded"
fontSize: "15px"
fontWeight: 400
lineHeight: "150%"
label:
fontFamily: "Feather"
fontSize: "16px"
fontWeight: 700
lineHeight: "150%"
letterSpacing: "0.04em"
caption:
fontFamily: "DIN Next Rounded"
fontSize: "16px"
fontWeight: 500
lineHeight: "150%"
rounded:
sm: "6px"
md: "8px"
lg: "12px"
xl: "16px"
full: "50%"
spacing:
base: "4px"
sm: "8px"
md: "12px"
lg: "16px"
xl: "24px"
2xl: "30px"
3xl: "40px"
gap: "16px"
section-padding: "60px"
card-padding: "24px"
button-padding: "16px"
components:
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.text-on-primary}"
typography: "{typography.label}"
rounded: "{rounded.xl}"
padding: "16px"
shadow: "0 4px 0 #3C9E00"
button-secondary:
backgroundColor: "{colors.secondary}"
textColor: "{colors.text-on-primary}"
rounded: "{rounded.xl}"
padding: "16px"
shadow: "0 4px 0 #009BE4"
card:
backgroundColor: "{colors.surface-elevated}"
borderColor: "{colors.border}"
rounded: "{rounded.lg}"
padding: "24px"
---
# DESIGN.md - Duolingo
> Sistema de diseño extraído de `https://duolingo.com` + `https://blog.duolingo.com` (sitio app + blog, junio 2026) siguiendo el skill `url-inspiration-styleguide`.
> Valores observados del CSS de la app (style1.css + style2.css descomprimidos del CDN Cloudfront) + CSS del blog (screen.css) + HTML del blog (server-rendered con colores hex reales). El sitio principal es una SPA React sin server-render, por lo que los colores hex se extrajeron del blog y del CSS. Estados derivados marcados con `(derivado para completar el sistema)`.
---
## 1. Tema Visual y Atmósfera
Duolingo se siente como un juego que se viste de educación. El canvas es blanco puro `#FFFFFF` (snow en el sistema de animales), sin crema ni tibio: es un blanco limpio de producto educativo que deja que los colores vibrantes hagan el trabajo. Sobre ese blanco cae un verde signature `#58CC02` (macaw, el color más reconocible de la marca) que organiza toda la interacción: CTA, botones primary, progress bars, success states. Es un verde brillante y optimista, no un verde corporativo ni un verde banking.
La personalidad aparece en la tipografía rounded bold. Duolingo usa dos fuentes rounded: **Feather** (custom, self-hosted, usada en la app para todo lo display y labels) y **DIN Next Rounded** (commercial, usada en el blog para body). Ambas son rounded sans-serif con peso 700 dominante (59 ocurrencias vs 14 de 400), lo que le da al sistema una voz gruesa, amigable y segura, como una maestra de primaria que sabe lo que dice. Los botones tienen un efecto 3D signature: sombra inferior sólida `0 4px 0` que crea un borde inferior oscuro, como si el botón tuviera profundidad física.
La traducción digital debe conservar esa mezcla de juego y educación: canvas blanco, verde signature como acento de marca, tipografía rounded bold, botones 3D con sombra inferior sólida, esquinas redondeadas generosas (16px para botones, 12px para cards), y un sistema de colores con nombres de animales que es parte del lenguaje interno de la marca. Cuando el sistema se ve bien, parece el cruce entre un juego móvil, un libro de texto amigable y un producto educativo que se atreve a ser colorido.
**Palabras clave de personalidad**: juguetón, redondeado, educativo, vibrante, grueso, optimista, gamificado
**Densidad del layout**: cómoda (aire generoso, cards con padding 24px)
**Modo preferido**: claro (blanco puro)
**Nivel de ornamentación**: medio (tipografía rounded bold, colores vibrantes, botones 3D, sin decoración superficial)
**Audiencia visual objetivo**: personas de todas las edades que quieren aprender idiomas de forma divertida y gamificada, no académica ni intimidante
---
## 2. Paleta de Colores y Roles Semánticos
La paleta real del sitio se organiza con un sistema de nombres de animales: cada color tiene un animal (macaw=verde, snow=blanco, whale=azul, cardinal=rojo, eel=oscuro, owl=amarillo, etc.). Los valores hex se extrajeron del blog server-rendered y del CSS del blog (screen.css con 154KB).
### Colores de marca
| Nombre | Variable CSS | Hex | Rol | Texto sobre el |
|--------|-------------|-----|-----|----------------|
| Verde macaw | `--color-primary` | `#58CC02` | CTA primary, success, progress, marca (`--color-macaw` real, 8 ocurrencias en blog + 7 en CSS) | `#FFFFFF` |
| Verde hover | `--color-primary-hover` | `#58B810` | Hover del verde (derivado, `#58B810` real del blog HTML) | `#FFFFFF` |
| Verde active | `--color-primary-active` | `#3C9E00` | Pressed state, sombra 3D del botón verde (derivado) | `#FFFFFF` |
| Azul whale | `--color-secondary` | `#1CB0F6` | CTA secondary, info, links (`--color-whale` real, 32 ocurrencias en blog CSS) | `#FFFFFF` |
| Azul hover | `--color-secondary-hover` | `#009BE4` | Hover del azul (`#009BE4` real del blog CSS, 3 ocurrencias) | `#FFFFFF` |
| Teal peacock | `--color-accent` | `#00CD9C` | Acento, success alternativo (`#00CD9C` real del blog HTML) | `#FFFFFF` |
| Azul claro | `--color-accent-soft` | `#DDF4FF` | Fondos de énfasis suaves (`#DDF4FF` real del blog CSS, 5 ocurrencias) | `#1CB0F6` |
### Colores de superficie
| Nombre | Variable CSS | Hex | Rol |
|--------|-------------|-----|-----|
| Fondo blanco | `--color-bg` | `#FFFFFF` | Fondo general, `--color-snow` real del CSS app |
| Superficie gris | `--color-surface` | `#F0F0F0` | Secciones alternas, `#F0F0F0` real del blog CSS (7 ocurrencias) |
| Superficie elevada | `--color-surface-elevated` | `#FFFFFF` | Cards, modales |
| Superficie azul | `--color-surface-blue` | `#DDF4FF` | Fondos de énfasis azul, `#DDF4FF` real |
| Borde claro | `--color-border` | `#E5E5E5` | Bordes sutiles, `#E5E5E5` real del blog CSS (20 ocurrencias) |
| Borde sutil | `--color-border-subtle` | `#E6E6E6` | Hairlines, `#E6E6E6` real (11 ocurrencias) |
| Borde énfasis | `--color-border-emphasized` | `#CECECE` | Bordes fuertes, `#CECECE` real (17 ocurrencias) |
### Colores de texto
| Nombre | Variable CSS | Hex | Uso |
|--------|-------------|-----|-----|
| Texto oscuro | `--color-text` | `#4B4B4B` | Headings, body, `--color-eel` real (22 ocurrencias en blog CSS) |
| Texto muted | `--color-text-muted` | `#777777` | Metadata, captions, `--color-wolf` real (7 ocurrencias) |
| Texto gris claro | `--color-text-light` | `#AFAFAF` | Placeholders, `--color-hare` real (25 ocurrencias) |
| Texto gris medio | `--color-text-gray` | `#5A5A5A` | Texto secundario, `#5A5A5A` real (7 ocurrencias) |
| Texto on-primary | `--color-text-on-primary` | `#FFFFFF` | Texto sobre verde/azul CTA, `--color-snow` |
| Texto dark | `--color-text-dark` | `#15171A` | Ghost accent, near-black, `#15171A` real del blog CSS variable |
### Colores de estado
| Estado | Variable CSS | Hex | Texto |
|--------|-------------|-----|-------|
| Éxito | `--color-success` | `#58CC02` | `#FFFFFF` |
| Éxito (bg) | `--color-success-bg` | `#DDF4FF` | `#58CC02` |
| Advertencia | `--color-warning` | `#FFC800` | `#15171A` |
| Advertencia (bg) | `--color-warning-bg` | `#FFF8DD` | `#15171A` |
| Error | `--color-error` | `#EA2B2B` | `#FFFFFF` |
| Error (bg) | `--color-error-bg` | `#FFE5E5` | `#EA2B2B` |
| Info | `--color-info` | `#1CB0F6` | `#FFFFFF` |
| Info (bg) | `--color-info-bg` | `#DDF4FF` | `#1CB0F6` |
> `#EA2B2B` (cardinal) es real del blog HTML (5 ocurrencias). `#FFC800` (bee/owl) es el amarillo known de Duolingo para warning/streaks. `#58CC02` (macaw) se usa para success porque es el verde de marca.
### Sistema de nombres de animales (design system interno)
> Duolingo nombra sus colores con animales. Esta es la tabla de traducción observada en el CSS:
| Animal | Color | Hex | Uso |
|--------|-------|-----|-----|
| macaw | Verde | `#58CC02` | Primary, success, marca |
| snow | Blanco | `#FFFFFF` | Fondo, texto sobre color |
| whale | Azul | `#1CB0F6` | Secondary, info, links |
| cardinal | Rojo | `#EA2B2B` | Error, danger |
| eel | Oscuro | `#4B4B4B` | Texto principal |
| wolf | Gris | `#777777` | Texto muted |
| hare | Gris claro | `#AFAFAF` | Texto ligero, placeholders |
| swan | Gris muy claro | `#E5E5E5` | Bordes, divisores |
| owl | Amarillo | `#FFC800` | Warning, streaks, oro |
| bee | Amarillo | `#FFC800` | Variante de owl |
| peacock | Teal | `#00CD9C` | Acento, success alternativo |
| blue-jay | Azul claro | `#1FC2FF` | Variante de whale |
| polar | Blanco | `#FFFFFF` | Variante de snow |
| fire-ant | Rojo oscuro | (no detectado) | Error dark |
| turtle | Verde oscuro | (no detectado) | Variante de macaw |
---
## 3. Reglas de Tipografía
```css
/* Display + Headings + Labels: Feather (custom, self-hosted, usada en la app
como `feather, sans-serif`) -> sustituto Google: Nunito (rounded sans-serif
con peso 700 y masa similar, familia humanista redondeada) */
--font-display: 'Nunito', 'Feather', system-ui, sans-serif;
/* Body: DIN Next Rounded (commercial, usada en el blog como `din-next-rounded`)
-> sustituto Google: Nunito (mismo sustituto, cubre el rango rounded) */
--font-body: 'Nunito', 'DIN Next Rounded', system-ui, sans-serif;
/* Mono: no detectado en el sitio de marketing (la app usa system monospace) */
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
```
**Google Fonts (sustitutos):**
```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=Nunito:wght@400;500;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
```
**Nota sobre sustitución**: el sitio usa dos fuentes rounded:
- **Feather** (custom, self-hosted, `feather, sans-serif` en CSS de la app): la voz principal de la marca, usada para todo lo display, headings y labels. Es una rounded sans-serif bold, custom para Duolingo. No está en Google Fonts.
- **DIN Next Rounded** (commercial, `din-next-rounded` en CSS del blog, 31 ocurrencias): usada para body en el blog. Es una rounded sans-serif de Dalton Stergiou. No está en Google Fonts.
`Nunito` sustituye a ambas: es una rounded sans-serif con pesos 200-1000, masa similar, y un humanismo redondeado que encaja con el tono juguetón-educativo de Duolingo. No está en la lista AI-slop y su carácter redondeado es cercano a Feather y DIN Next Rounded.
### Escala tipográfica
> Token · px · line-height · peso · uso. Valores reales del CSS de la app (`--text-pageTitle-*`, `--text-heading-*`, `--text-body-*`, `--text-caption-*`, `--text-label-*`).
| Token | px equiv. | Line height | Weight | Uso |
|-------|-----------|-------------|--------|-----|
| `--text-pageTitle-large` | 40px (2.5rem) | 44px (2.75rem) | 700 | Hero headline (Feather) |
| `--text-pageTitle-small` | 32px (2rem) | 36px (2.25rem) | 700 | Display secundario |
| `--text-heading-large` | 28px (1.75rem) | 32px (2rem) | 700 | Titular de sección |
| `--text-heading-medium` | 24px (1.5rem) | 32px (2rem) | 700 | Subtítulo de bloque |
| `--text-heading-small` | 20px (1.25rem) | 24px (1.5rem) | 700 | Título de card |
| `--text-heading-xsmall` | 16px (1rem) | 20px (1.25rem) | 700 | Título pequeño |
| `--text-body` | 20px (1.25rem) | 28px (1.75rem) | 500 | Body general (DIN Next Rounded) |
| `--text-body-bold` | 20px (1.25rem) | 28px (1.75rem) | 700 | Body bold |
| `--text-caption` | 16px (1rem) | 24px (1.5rem) | 500 | Caption, descripciones |
| `--text-label-large` | 24px (1.5rem) | 24px (1.5rem) | 700 | Label grande (uppercase, 0.04em) |
| `--text-label-medium` | 16px (1rem) | 16px (1rem) | 700 | Label, CTA (uppercase, 0.04em) |
### Pesos tipográficos
```css
--font-regular: 400; /* Body del blog, descripciones (14 ocurrencias) */
--font-medium: 500; /* Body de la app, captions (6 ocurrencias) */
--font-bold: 700; /* DOMINANTE: headings, labels, CTAs (59 ocurrencias) */
```
> El peso 700 es el dominante absoluto (59 ocurrencias vs 14 de 400 y 6 de 500). Esta es la firma tipográfica de Duolingo: texto grueso y seguro en todas partes. Los headings siempre van en 700, los labels siempre en 700, y el body de la app va en 500 (medio) mientras que el blog usa 400. El bold es la voz de un producto educativo que quiere sentirse accesible pero firme.
### Letter spacing
```css
--tracking-normal: 0em; /* Body, headings */
--tracking-label: 0.04em; /* Labels (uppercase con tracking amplio) */
```
**Regla clave**: los labels siempre van en uppercase con `letter-spacing: 0.04em` y peso 700. Es la firma de los botones y CTAs: texto grueso, en mayúsculas, con tracking amplio, en una rounded sans-serif. Esta combinación le da al sistema ese tono de "producto educativo gamificado" que es inconfundiblemente Duolingo.
---
## 4. Estilos de Componentes
### Botones
**Primario (verde macaw con sombra 3D)**
```
Background: var(--color-primary) -> #58CC02
Color de texto: var(--color-text-on-primary) -> #FFFFFF
Padding: 16px (--web-ui_button-padding real)
Border-radius: var(--web-ui_button-border-radius) -> 16px
Font-family: var(--font-display) -> Feather
Font-weight: 700
Font-size: 14px (--web-ui_button-font-size real)
Text-transform: uppercase
Letter-spacing: 0.04em
Box-shadow: 0 4px 0 #3C9E00 (sombra inferior sólida 3D, real del CSS)
Transicion: background-color 150ms ease, transform 100ms ease
Hover:
Background: var(--color-primary-hover) -> #58B810
Active/Pressed:
Background: var(--color-primary-active) -> #3C9E00
Transform: translateY(4px)
Box-shadow: 0 0 0 #3C9E00 (la sombra desaparece al presionar)
Disabled:
Opacity: 0.4
Cursor: not-allowed
Focus:
Outline: 2px solid var(--color-secondary) -> #1CB0F6
Outline-offset: 3px
```
> La sombra `0 4px 0` (real del CSS, observada en `box-shadow: 0 4px 0 rgb(...)`) es la firma de los botones Duolingo: crea un efecto 3D donde el botón parece tener profundidad física, como un botón de juguete. Al presionar (`active`), el botón se mueve 4px hacia abajo y la sombra desaparece, simulando que se hunde. Es el gesto más distintivo del sistema.
**Secundario (azul whale con sombra 3D)**
```
Background: var(--color-secondary) -> #1CB0F6
Color de texto: #FFFFFF
Padding: 16px
Border-radius: 16px
Box-shadow: 0 4px 0 #009BE4 (sombra azul oscura)
Hover:
Background: #009BE4
Active:
Transform: translateY(4px)
Box-shadow: 0 0 0 #009BE4
```
**Outline (blanco con borde)**
```
Background: transparent
Color de texto: var(--color-text) -> #4B4B4B
Border: 2px solid var(--color-border-emphasized) -> #CECECE
Border-radius: 16px
Padding: 16px
Hover:
Border-color: var(--color-text) -> #4B4B4B
```
**Ghost / Texto**
```
Background: transparent
Color: var(--color-secondary) -> #1CB0F6
Border: none
Padding: 8px 16px
Font-weight: 700
Hover:
Color: #009BE4
```
### Inputs de texto
```
Background: var(--color-surface-elevated) -> #FFFFFF
Border: 2px solid var(--color-border) -> #E5E5E5
Border-radius: var(--rounding-lg) -> 12px
Padding: 12px 16px
Font-family: var(--font-body) -> DIN Next Rounded
Font-size: 15px
Font-weight: 400
Color: var(--color-text) -> #4B4B4B
Placeholder: var(--color-text-light) -> #AFAFAF
Focus:
Border-color: var(--color-secondary) -> #1CB0F6
Box-shadow: 0 0 0 3px rgba(28, 176, 246, 0.18)
Outline: none
Error:
Border-color: var(--color-error) -> #EA2B2B
```
### Cards
```
Background: var(--color-surface-elevated) -> #FFFFFF
Border: 1px solid var(--color-border) -> #E5E5E5
Border-radius: var(--web-ui_card-border-radius) -> 12px
Padding: 24px
Hover (si es clickeable):
Border-color: var(--color-border-emphasized) -> #CECECE
Box-shadow: 0 2px 0 var(--color-border) (sombra 3D sutil)
```
> El radio de cards es `12px` (`--web-ui_card-border-radius` real del CSS, 13 ocurrencias), generoso y redondeado, en línea con el tono juguetón. El radio de botones es `16px` (`--web-ui_button-border-radius`, 11 ocurrencias), aún más redondeado.
### Badges / Chips
```
Padding: 4px 12px
Border-radius: var(--rounding-md) -> 8px
Font-family: var(--font-display) -> Feather
Font-size: 12px
Font-weight: 700
Text-transform: uppercase
Letter-spacing: 0.04em
Success:
Background: var(--color-success-bg) -> #DDF4FF
Color: var(--color-success) -> #58CC02
Error:
Background: var(--color-error-bg) -> #FFE5E5
Color: var(--color-error) -> #EA2B2B
Info:
Background: var(--color-info-bg) -> #DDF4FF
Color: var(--color-info) -> #1CB0F6
```
### Alertas / Toasts (derivados para completar el sistema)
```
Padding: 16px 20px
Border-radius: 12px
Font-family: var(--font-body) -> DIN Next Rounded
Font-size: 15px
Font-weight: 500
Success: background #DDF4FF, color #58CC02, border-left 4px solid #58CC02
Warning: background #FFF8DD, color #FFC800, border-left 4px solid #FFC800
Error: background #FFE5E5, color #EA2B2B, border-left 4px solid #EA2B2B
Info: background #DDF4FF, color #1CB0F6, border-left 4px solid #1CB0F6
```
### Navegación / Header
```
Background: var(--color-bg) -> #FFFFFF
Height: 64px aprox
Padding horizontal: 24px
Border-bottom: 1px solid var(--color-border) -> #E5E5E5
Logo:
Verde #58CC02 o texto oscuro #4B4B4B, peso 700, Feather
Links de nav:
Color: var(--color-text-muted) -> #777777
Font-family: var(--font-body) -> DIN Next Rounded
Font-size: 15px
Font-weight: 700
Hover: Color var(--color-text) -> #4B4B4B
CTA del nav:
Rectángulo verde #58CC02, texto blanco uppercase, 16px padding, radius 16px
Box-shadow: 0 4px 0 #3C9E00 (efecto 3D)
```
---
## 5. Principios de Layout
### Escala de espaciado
```css
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-15: 60px;
--space-20: 80px;
```
> El CSS de la app usa `--web-ui_button-padding: 16px` y `--card-padding: 24px` como valores base. El padding de sección es 60px, más compacto que otros sitios premium.
### Contenedores
```css
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1080px;
--container-xl: 1280px;
```
### Grid
```
Sistema: 12 columnas (estándar)
Gutter: 16px
Margin lateral: 24px en desktop, 16px en tablet, 12px en mobile
Patrones base: hero a una columna con titular pageTitle y CTA verde, grid de
2-3 columnas para cards de características, franjas de color azul (#DDF4FF)
para destacar secciones, y ilustraciones de Duo (búho mascota) como
elemento visual recurrente.
```
### Filosofía de espaciado
Duolingo tiene un espaciado cómodo pero no excesivo. El padding de card es 24px (generoso para contenido), el padding de botón es 16px (uniforme en todos los botones), y el padding de sección es 60px (más compacto que los 80px de sitios editoriales). La densidad refleja el producto: una app educativa que muestra mucho contenido de aprendizaje en poco espacio, organizada con claridad y sin overwhelmar al usuario.
---
## 6. Profundidad y Elevación
La marca es **flat con sombras 3D sólidas**. Su sensación de profundidad no viene de sombras material con blur, sino de sombras inferiores sólidas `0 4px 0` que crean un efecto 3D físico, como botones de juguete. Es la firma de elevación de Duolingo: profundidad por bordes inferiores, no por blur.
### Sistema de sombras
```css
--shadow-none: none;
--shadow-button: 0 4px 0 var(--color-primary-active);
--shadow-button-blue: 0 4px 0 #009BE4;
--shadow-card: 0 2px 0 var(--color-border);
--shadow-popover: 0 4px 0 var(--color-border-emphasized);
```
> Las sombras son sólidas (sin blur, sin alpha), un efecto 3D donde el elemento parece tener un borde inferior del mismo color pero más oscuro. Es un gesto de juguete físico, no de material design.
### Niveles de elevación
| Nivel | Token de sombra | Uso |
|-------|----------------|-----|
| 0 - Base | `--shadow-none` | Secciones, fondos |
| 1 - Button 3D | `--shadow-button` | Botones primary (verde) |
| 2 - Button 3D blue | `--shadow-button-blue` | Botones secondary (azul) |
| 3 - Card | `--shadow-card` | Cards con sombra inferior sutil |
| 4 - Popover | `--shadow-popover` | Popovers, dropdowns |
### Radios de borde
```css
--radius-sm: 6px;
--radius-md: 8px; /* badges, chips */
--radius-lg: 12px; /* cards (--web-ui_card-border-radius, predominante) */
--radius-xl: 16px; /* botones (--web-ui_button-border-radius) */
--radius-full: 50%; /* avatares, iconos circulares */
```
> Los radios son generosos y redondeados, en línea con el tono juguetón-educativo. El radio de botones (16px) es más redondeado que el de cards (12px), creando una jerarquía donde los elementos interactivos son más amigables. No hay radios de 0px ni esquinas afiladas en el sistema.
---
## 7. Lo que Sí y lo que No
### Sí hacer
1. **Usa el verde `#58CC02` (macaw) como acento de marca principal** - CTA, success, progress, marca; es el color más reconocible de Duolingo.
2. **Mantén la tipografía rounded bold (peso 700 dominante)** - la voz gruesa y redondeada es la firma; nunca uses serif ni sans-serif afilada.
3. **Usa sombras 3D sólidas `0 4px 0` en botones** - el efecto 3D físico es el gesto más distintivo; sin blur, sin alpha, solo un borde inferior oscuro.
4. **Usa radios generosos (16px botones, 12px cards)** - las esquinas redondeadas son parte del tono juguetón; nunca uses esquinas afiladas.
5. **Mantén los labels en uppercase con tracking 0.04em y peso 700** - la combinación es la firma de CTAs y botones.
6. **Usa el azul `#1CB0F6` (whale) como secondary** - info, links, CTA alternativo; el azul complementa al verde sin competir.
### No hacer
1. **No uses serif ni tipografía afilada** - la marca es rounded sans-serif; una serif borra la personalidad juguetón-educativa.
2. **No uses peso 400 como voz por defecto para headings** - el peso 700 es la firma; 400 se siente demasiado ligero para el tono gamificado.
3. **No uses sombras con blur ni glassmorphism** - la profundidad va por sombras sólidas 3D, no por blur material.
4. **No uses esquinas afiladas ni radios pequeños** - el sistema es redondeado (12px mínimo para cards); las esquinas afiladas rompen el tono.
5. **No introduzcas colores fuera de la paleta de animales** - macaw, whale, cardinal, owl, eel; cualquier otro color fragmenta el sistema.
6. **No uses el verde `#58CC02` como fondo de todo el sitio** - es un acento; bañar todo el sitio lo vuelve agresivo y pierde impacto.
---
## 8. Comportamiento Responsive
### Breakpoints
```css
/* Mobile first — CSS de la app y blog */
/* sm: */ @media (max-width: 480px) { }
/* md: */ @media (max-width: 767px) { }
/* lg: */ @media (max-width: 991px) { }
```
### Cambios por breakpoint
**Mobile (< 480px)**
- Navegación: logo + menú compacto, CTA verde compacto
- Grid: 1 columna
- PageTitle: 32px (small), no 40px
- Padding de contenedor: 16px
- Cards: apiladas, una por fila
- Botones: ancho completo (full-width)
**Tablet (480px - 767px)**
- Navegación: logo + links + CTA
- Grid: 2 columnas para cards
- PageTitle: 40px
- Padding de contenedor: 20px
**Desktop (> 767px)**
- Navegación: full nav visible
- Grid: 3 columnas en cards, hero a una columna
- PageTitle: 40px (large)
- Padding de contenedor: 24px
- Sección padding: 60px vertical
### Touch targets (mobile)
- Botones mínimo: 44x44px (el botón con 16px padding + 14px font cumple)
- Links de navegación: altura mínima 44px
- Inputs: altura mínima 44px
### Filosofía responsive
Mobile-first con ambición de juego. En pequeño formato la marca debe seguir sintiéndose como una app educativa gamificada, no como un sitio recortado. Prioriza un titular grueso contundente, un CTA verde 3D claro, y cards redondeadas en grid compacto. Los botones se vuelven full-width en mobile para facilitar el tap.
---
## 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 Duolingo.
PALETA: Canvas blanco puro #FFFFFF. Verde signature #58CC02 (macaw) como primary.
Azul #1CB0F6 (whale) como secondary. Rojo #EA2B2B (cardinal) para error.
Texto oscuro #4B4B4B (eel). Gris #777777 (wolf) para muted.
TIPOGRAFÍA: Display + headings + labels en Nunito (sustituto de Feather) peso 700
DOMINANTE. Body en Nunito (sustituto de DIN Next Rounded) peso 500. Labels en
uppercase con tracking 0.04em.
ESTILO: Juguetón, redondeado, educativo, vibrante. Botones 3D con sombra inferior
sólida 0 4px 0 (sin blur). Radios generosos (16px botones, 12px cards).
TOKENS: Usa siempre variables CSS; no hardcodees colores fuera del sistema.
MODO: Claro (blanco puro).
```
### Prompt: Crear nueva pantalla
```text
Crea una pantalla de [FUNCIONALIDAD] para Duolingo.
Requisitos:
- Debe sentirse como un juego educativo, no como un SaaS ni un curso académico
- Usa fondo blanco puro #FFFFFF y verde #58CC02 como acento primary
- Titulares en Nunito peso 700, redondeados y gruesos
- Botones con sombra 3D sólida 0 4px 0 (sin blur), radius 16px
- Labels en uppercase con tracking 0.04em y peso 700
- Radios generosos: 16px botones, 12px cards
- Responsive, con CTA principal verde 3D
```
### Prompt: Añadir componente al UI kit
```text
Añade un componente de [TIPO] al sistema de Duolingo.
Debe:
- Usar solo tokens del DESIGN.md de Duolingo
- Mantener radios de 16px para botones, 12px para cards, 8px para badges
- Tener versión default, hover, active (con translateY 4px), focus y disabled
- Sentirse juguetón y educativo, no corporativo ni serio
- Sombras 3D sólidas (0 4px 0) en botones, no sombras material con blur
- Tipografía: Nunito 700 para headings/labels, 500 para body
```
### Prompt: Revisión de consistencia
```text
Revisa esta interfaz y detecta qué no sigue el sistema de Duolingo.
Verifica:
1. Si la tipografía es rounded bold (peso 700 dominante, no serif ni afilada)
2. Si los botones tienen sombra 3D sólida 0 4px 0 (no sombras con blur)
3. Si los radios son generosos (16px botones, 12px cards, no esquinas afiladas)
4. Si el verde #58CC02 es el acento primary (no otros verdes ni azules como primary)
5. Si los labels están en uppercase con tracking 0.04em
6. Si hay elementos serios, corporativos o no-juguetones (no deben estar)
```
### Prompt: Variante de campaña
```text
Genera una variante [curso / idioma / evento] para Duolingo manteniendo el sistema base.
Conserva:
- Verde #58CC02 como primary
- Blanco #FFFFFF como canvas
- Nunito peso 700 para display
- Botones 3D con sombra sólida
- Radios generosos
Puedes variar:
- El acento secundario entre azul #1CB0F6, teal #00CD9C o amarillo #FFC800
- Las ilustraciones de Duo (búho mascota)
- El balance entre gamificación y contenido educativo
```
---
## 10. Movimiento (Motion)
Duolingo usa motion juguetón y físico, consistente con el tono de juego educativo. Los botones tienen un efecto 3D al presionar (translateY 4px + sombra que desaparece), las animaciones de success/error son celebratorias (confeti, saltos), y las transiciones son rápidas y energéticas.
**Nivel de motion**: juguetón-físico
**Duraciones**: 100ms (pressed, rápido para efecto físico), 150ms (hover, transiciones de color), 200ms (transiciones medias), 800ms (scroll reveal), 900ms (entrada orquestada del hero), 26s (ken-burns del hero)
**Easings**: `ease` (transiciones generales), `ease-out` (transiciones de salida), `cubic-bezier(0.16, 1, 0.3, 1)` (para reveals escalonados)
**Propiedades animadas**: transform (translateY para efecto 3D de botones), background-color, color, box-shadow, opacity
**Patrones de motion**:
- Entrada escalonada del hero con `animation-delay`
- Scroll reveal por sección (fade-up 26px, 800ms)
- Ken-burns lento en la captura del hero (26s, alternate, scale 1 -> 1.07)
- Efecto 3D al presionar botones: `transform: translateY(4px)` + `box-shadow: 0 0 0` (la sombra desaparece)
- Transiciones de 150ms en hover de botones (cambio de color)
- Animaciones de celebración (confeti, saltos de Duo) en success states
```css
--ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
--ease-out: ease-out;
--duration-fast: 100ms; /* pressed 3D effect */
--duration-base: 150ms; /* hover */
--duration-slow: 200ms;
--duration-reveal: 800ms;
--duration-kenburns: 26s;
```
> **Accesibilidad**: respeta `@media (prefers-reduced-motion: reduce)` y reduce todos los gestos a cambios de color sin desplazamiento. El ken-burns del hero y los reveals escalonados se desactivan; el contenido aparece estático. El efecto 3D de botones se puede conservar (es un cambio de box-shadow, no de posición).
---
## Anexo: Stack técnico detectado
- **Plataforma / builder**: React SPA (Single Page Application, sin server-render en la página principal), blog en Ghost (`blog.duolingo.com` con `ghost-accent-color` variable)
- **Framework CSS**: CSS custom con variables en `:root` (no Tailwind), sistema de design tokens completo con nombres de animales (`--color-macaw`, `--color-snow`, etc.), servido desde Cloudfront CDN (`d35aaqx5ub95lt.cloudfront.net`)
- **Sistema de colores**: nombres de animales (macaw=verde, snow=blanco, whale=azul, cardinal=rojo, eel=oscuro, owl=amarillo, wolf=gris, hare=gris claro, swan=gris muy claro, peacock=teal, etc.), referenciados como `rgb(var(--color-*))` con tripletas RGB
- **Tipografía**: dos fuentes rounded:
- **Feather** (custom, self-hosted, `feather, sans-serif`): voz principal de la app. No en Google Fonts.
- **DIN Next Rounded** (commercial, `din-next-rounded`, 31 ocurrencias en blog CSS): body del blog. No en Google Fonts.
- **GenSenRounded** (2 ocurrencias): probablemente para CJK languages.
- **KaTeX** fonts (math rendering): KaTeX_Main, KaTeX_Fraktur, etc.
- **Animación**: CSS-first con transitions y `@keyframes`. No se detectaron librerías de motion pesadas.
- **3D / WebGL**: no detectado.
- **CDN / assets**: `d35aaqx5ub95lt.cloudfront.net` para CSS/JS/images de la app, `blog.duolingo.com/assets/` para CSS del blog
- **Comportamiento**: app de aprendizaje de idiomas (SPA React) + blog (Ghost) con research reports, dear duolingo column, y shop. El sistema de diseño usa un lenguaje de animales para colores que es parte de la cultura interna de Duolingo.
- **Mascota**: Duo el búho, presente en ilustraciones y animaciones como elemento de marca recurrente